mirror of
https://github.com/webmin/webmin.git
synced 2026-02-03 06:03:28 +00:00
274 lines
7.3 KiB
Perl
Executable File
274 lines
7.3 KiB
Perl
Executable File
#!/usr/local/bin/perl
|
|
# upload.cgi
|
|
# Upload multiple files
|
|
|
|
require './updown-lib.pl';
|
|
&error_setup($text{'upload_err'});
|
|
&ReadParse(\%getin, "GET");
|
|
$upid = $getin{'id'};
|
|
|
|
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,
|
|
$direct_dir);
|
|
foreach my $k (keys %in) {
|
|
$in{$k} = $in{$k}->[0] if ($k !~ /^upload\d+/);
|
|
}
|
|
$can_upload || &error($text{'upload_ecannot'});
|
|
|
|
# Validate inputs
|
|
$in{'dir'} || &error($text{'upload_edir'});
|
|
if (defined($in{'email_def'}) && !$in{'email_def'}) {
|
|
$in{'email'} =~ /\S/ || &error($text{'upload_eemail'});
|
|
$email = $in{'email'};
|
|
}
|
|
if ($can_mode != 3) {
|
|
# User can be entered
|
|
scalar(@uinfo = getpwnam($in{'user'})) ||
|
|
&error($text{'upload_euser'});
|
|
&can_as_user($in{'user'}) ||
|
|
&error(&text('upload_eucannot', $in{'user'}));
|
|
$in{'group_def'} || scalar(@ginfo = getgrnam($in{'group'})) ||
|
|
&error($text{'upload_egroup'});
|
|
$can_mode == 0 || $in{'group_def'} || &in_group(\@uinfo, \@ginfo) ||
|
|
&error($text{'upload_egcannot'});
|
|
}
|
|
elsif (&supports_users()) {
|
|
# User to upload as is set in the ACL
|
|
@uinfo = getpwnam($remote_user);
|
|
}
|
|
for($i=0; defined($in{"upload$i"}); $i++) {
|
|
for(my $j=0; $j<@{$in{"upload$i"}}; $j++) {
|
|
$d = $in{"upload${i}"}->[$j];
|
|
$f = $in{"upload${i}_filename"}->[$j];
|
|
$found++ if ($d && $f);
|
|
}
|
|
}
|
|
$found || &error($text{'upload_enone'});
|
|
&can_write_file($in{'dir'}) ||
|
|
&error(&text('upload_eaccess', "<tt>$in{'dir'}</tt>", $!));
|
|
|
|
# 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]);
|
|
|
|
# Create the directory if needed
|
|
if (!-d $in{'dir'} && $in{'mkdir'}) {
|
|
mkdir($in{'dir'}, 0755) || &error(&text('upload_emkdir', $!));
|
|
}
|
|
|
|
&ui_print_header(undef, $text{'upload_title'}, "");
|
|
|
|
# Move or save the actual files, showing progress
|
|
$msg = undef;
|
|
for($i=0; defined($in{"upload$i"}); $i++) {
|
|
for(my $j=0; $j<@{$in{"upload$i"}}; $j++) {
|
|
$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'}) {
|
|
$path = "$in{'dir'}/$1";
|
|
}
|
|
else {
|
|
$path = $in{'dir'};
|
|
}
|
|
print &text('upload_saving',
|
|
"<tt>".&html_escape($path)."</tt>"),"<br>\n";
|
|
|
|
if ($mpath) {
|
|
# Move file as we already have it in disk
|
|
rename($mpath, $path) ||
|
|
&move_source_dest($mpath, $path) ||
|
|
&error(&text('upload_emove',
|
|
"<tt>".&html_escape($mpath)."</tt>",
|
|
"<tt>".&html_escape($path)."</tt>", $!));
|
|
}
|
|
else {
|
|
# Write uploaded data to the destination file
|
|
if (!&open_tempfile(FILE, ">$path", 1)) {
|
|
&error(&text('upload_eopen', "<tt>$path</tt>",
|
|
$!));
|
|
}
|
|
&print_tempfile(FILE, $d);
|
|
&close_tempfile(FILE);
|
|
push(@uploads, $path);
|
|
}
|
|
@st = stat($path);
|
|
print &text('upload_saved', &nice_size($st[7])),"<p>\n";
|
|
|
|
$estatus = undef;
|
|
if ($in{'zip'}) {
|
|
print &text('upload_unzipping',
|
|
"<tt>$path</tt>"),"<br>\n";
|
|
local ($err, $out);
|
|
$path =~ /^(\S*\/)/;
|
|
local $dir = $1;
|
|
local $qdir = quotemeta($dir);
|
|
local $qpath = quotemeta($path);
|
|
local @files;
|
|
if ($path =~ /\.zip$/i) {
|
|
# ZIP file
|
|
if (!&has_command("unzip")) {
|
|
$err = &text('upload_ecmd', "unzip");
|
|
}
|
|
else {
|
|
open(OUT, &webmin_command_as_user($uinfo[0], 0, "(cd $qdir && unzip -o $qpath)")." 2>&1 </dev/null |");
|
|
while(<OUT>) {
|
|
$out .= $_;
|
|
if (/^\s*[a-z]+:\s+(.*)/) {
|
|
push(@files, $1);
|
|
}
|
|
}
|
|
close(OUT);
|
|
$err = $out if ($?);
|
|
}
|
|
$fmt = "zip";
|
|
}
|
|
elsif ($path =~ /\.tar$/i) {
|
|
# Un-compressed tar file
|
|
if (!&has_command("tar")) {
|
|
$err = &text('upload_ecmd', "tar");
|
|
}
|
|
else {
|
|
open(OUT, &webmin_command_as_user($uinfo[0], 0, "(cd $qdir && tar xvf $qpath)")." 2>&1 </dev/null |");
|
|
while(<OUT>) {
|
|
$out .= $_;
|
|
if (/^(.*)/) {
|
|
push(@files, $1);
|
|
}
|
|
}
|
|
close(OUT);
|
|
$err = $out if ($?);
|
|
}
|
|
$fmt = "tar";
|
|
}
|
|
elsif ($path =~ /\.(lha|lhz)$/i) {
|
|
# LHAarc file
|
|
if (!&has_command("lha")) {
|
|
$err = &text('upload_ecmd', "lha");
|
|
}
|
|
else {
|
|
open(OUT, &webmin_command_as_user($uinfo[0], 0, "(cd $qdir && lha xf $qpath)")." 2>&1 </dev/null |");
|
|
while(<OUT>) {
|
|
$out .= $_;
|
|
if (/(\S[^\t]*\S)\s+\-\s+/) {
|
|
push(@files, "/".$1);
|
|
}
|
|
}
|
|
close(OUT);
|
|
$err = $out if ($?);
|
|
}
|
|
$fmt = "lha";
|
|
}
|
|
elsif ($path =~ /\.(tar\.gz|tgz|tar\.bz|tbz|tar\.bz2|tbz2)$/i) {
|
|
# Compressed tar file
|
|
local $zipper = $path =~ /bz(2?)$/i ? "bunzip2"
|
|
: "gunzip";
|
|
if (!&has_command("tar")) {
|
|
$err = &text('upload_ecmd', "tar");
|
|
}
|
|
elsif (!&has_command($zipper)) {
|
|
$err = &text('upload_ecmd', $zipper);
|
|
}
|
|
else {
|
|
open(OUT, &webmin_command_as_user($uinfo[0], 0, "(cd $qdir && $zipper -c $qpath | tar xvf -)")." 2>&1 </dev/null |");
|
|
while(<OUT>) {
|
|
$out .= $_;
|
|
if (/^(.*)/) {
|
|
push(@files, $1);
|
|
}
|
|
}
|
|
close(OUT);
|
|
$err = $out if ($?);
|
|
}
|
|
$fmt = $zipper eq "gunzip" ? "tgz" : "tbz2";
|
|
}
|
|
else {
|
|
# Doesn't look possible
|
|
$err = $text{'upload_notcomp'};
|
|
}
|
|
if (!$err) {
|
|
my $jn = join("<br>",
|
|
map { " <tt>$_</tt>" }
|
|
@files);
|
|
if ($in{'zip'} == 2) {
|
|
unlink($path);
|
|
$ext{$path} = $text{'upload_deleted'}.
|
|
"<br>".$jn;
|
|
}
|
|
else {
|
|
$ext{$path} = $text{'upload_extracted'}.
|
|
"<br>".$jn;
|
|
}
|
|
}
|
|
else {
|
|
$ext{$path} = &text('email_eextract', $err);
|
|
}
|
|
$estatus = $err ? &text('email_extfailed', $err)
|
|
: &text('email_extdone_'.$fmt);
|
|
print &text('upload_unzipdone', $estatus),"<p>\n";
|
|
}
|
|
|
|
# Add to email message
|
|
$msg .= &text('email_upfile', $f)."\n";
|
|
$msg .= &text('email_uppath', $path)."\n";
|
|
$msg .= &text('email_upsize', &nice_size($st[7]))."\n";
|
|
if ($estatus) {
|
|
$msg .= &text('email_upextract', $estatus)."\n";
|
|
}
|
|
$msg .= "\n";
|
|
}
|
|
}
|
|
|
|
# Switch back to root
|
|
&switch_uid_back();
|
|
|
|
# Save the settings
|
|
if ($module_info{'usermin'}) {
|
|
&lock_file("$user_module_config_directory/config");
|
|
$userconfig{'dir'} = $in{'dir'};
|
|
&write_file("$user_module_config_directory/config", \%userconfig);
|
|
&unlock_file("$user_module_config_directory/config");
|
|
}
|
|
else {
|
|
&lock_file("$module_config_directory/config");
|
|
$config{'dir_'.$remote_user} = $in{'dir'};
|
|
$config{'user_'.$remote_user} = $in{'user'};
|
|
$config{'group_'.$remote_user} = $in{'group_def'} ? undef
|
|
: $in{'group'};
|
|
&write_file("$module_config_directory/config", \%config);
|
|
&unlock_file("$module_config_directory/config");
|
|
}
|
|
|
|
# Send email
|
|
if ($email && $msg) {
|
|
$msg = $text{'email_upmsg'}."\n\n".$msg;
|
|
&send_email_notification($email, $text{'email_subjectu'}, $msg);
|
|
}
|
|
|
|
&webmin_log("upload", undef, undef, { 'uploads' => \@uploads });
|
|
|
|
&ui_print_footer("index.cgi?mode=upload", $text{'index_return'});
|
|
|