Handle hostnames with upper-case letters
[webmin.git] / updown / upload.cgi
1 #!/usr/local/bin/perl
2 # upload.cgi
3 # Upload multiple files
4
5 require './updown-lib.pl';
6 &error_setup($text{'upload_err'});
7 &ReadParse(\%getin, "GET");
8 $upid = $getin{'id'};
9 &ReadParseMime($upload_max, \&read_parse_mime_callback, [ $upid ]);
10 $can_upload || &error($text{'upload_ecannot'});
11
12 # Validate inputs
13 $in{'dir'} || &error($text{'upload_edir'});
14 if (defined($in{'email_def'}) && !$in{'email_def'}) {
15         $in{'email'} =~ /\S/ || &error($text{'upload_eemail'});
16         $email = $in{'email'};
17         }
18 if ($can_mode != 3) {
19         # User can be entered
20         scalar(@uinfo = getpwnam($in{'user'})) ||
21                 &error($text{'upload_euser'});
22         &can_as_user($in{'user'}) ||
23                 &error(&text('upload_eucannot', $in{'user'}));
24         $in{'group_def'} || scalar(@ginfo = getgrnam($in{'group'})) ||
25                 &error($text{'upload_egroup'});
26         $can_mode == 0 || $in{'group_def'} || &in_group(\@uinfo, \@ginfo) ||
27                 &error($text{'upload_egcannot'});
28         }
29 else {
30         # User is fixed
31         if (&supports_users()) {
32                 @uinfo = getpwnam($remote_user);
33                 }
34         }
35 for($i=0; defined($d = $in{"upload$i"}); $i++) {
36         $f = $in{"upload${i}_filename"};
37         $found++ if ($d && $f);
38         }
39 $found || &error($text{'upload_enone'});
40 &can_write_file($in{'dir'}) ||
41         &error(&text('upload_eaccess', "<tt>$in{'dir'}</tt>", $!));
42
43 # Switch to the upload user
44 &switch_uid_to($uinfo[2], scalar(@ginfo) ? $ginfo[2] : $uinfo[3]);
45
46 # Create the directory if needed
47 if (!-d $in{'dir'} && $in{'mkdir'}) {
48         mkdir($in{'dir'}, 0755) || &error(&text('upload_emkdir', $!));
49         }
50
51 &ui_print_header(undef, $text{'upload_title'}, "");
52
53 # Save the actual files, showing progress
54 $msg = undef;
55 for($i=0; defined($d = $in{"upload$i"}); $i++) {
56         $f = $in{"upload${i}_filename"};
57         next if (!$f);
58         if (-d $in{'dir'}) {
59                 $f =~ /([^\\\/]+)$/;
60                 $path = "$in{'dir'}/$1";
61                 }
62         else {
63                 $path = $in{'dir'};
64                 }
65         print &text('upload_saving', "<tt>$path</tt>"),"<br>\n";
66         if (!&open_tempfile(FILE, ">$path", 1)) {
67                 &error(&text('upload_eopen', "<tt>$path</tt>", $!));
68                 }
69         &print_tempfile(FILE, $d);
70         &close_tempfile(FILE);
71         push(@uploads, $path);
72         @st = stat($path);
73         print &text('upload_saved', &nice_size($st[7])),"<p>\n";
74
75         $estatus = undef;
76         if ($in{'zip'}) {
77                 print &text('upload_unzipping', "<tt>$path</tt>"),"<br>\n";
78                 local ($err, $out);
79                 $path =~ /^(\S*\/)/;
80                 local $dir = $1;
81                 local $qdir = quotemeta($dir);
82                 local $qpath = quotemeta($path);
83                 local @files;
84                 &switch_uid_back();
85                 if ($path =~ /\.zip$/i) {
86                         # ZIP file
87                         if (!&has_command("unzip")) {
88                                 $err = &text('upload_ecmd', "unzip");
89                                 }
90                         else {
91                                 open(OUT, &webmin_command_as_user($uinfo[0], 0, "(cd $qdir && unzip -o $qpath)")." 2>&1 </dev/null |");
92                                 while(<OUT>) {
93                                         $out .= $_;
94                                         if (/^\s*[a-z]+:\s+(.*)/) {
95                                                 push(@files, $1);
96                                                 }
97                                         }
98                                 close(OUT);
99                                 $err = $out if ($?);
100                                 }
101                         $fmt = "zip";
102                         }
103                 elsif ($path =~ /\.tar$/i) {
104                         # Un-compressed tar file
105                         if (!&has_command("tar")) {
106                                 $err = &text('upload_ecmd', "tar");
107                                 }
108                         else {
109                                 open(OUT, &webmin_command_as_user($uinfo[0], 0, "(cd $qdir && tar xvf $qpath)")." 2>&1 </dev/null |");
110                                 while(<OUT>) {
111                                         $out .= $_;
112                                         if (/^(.*)/) {
113                                                 push(@files, $1);
114                                                 }
115                                         }
116                                 close(OUT);
117                                 $err = $out if ($?);
118                                 }
119                         $fmt = "tar";
120                         }
121                 elsif ($path =~ /\.(lha|lhz)$/i) {
122                         # LHAarc file
123                         if (!&has_command("lha")) {
124                                 $err = &text('upload_ecmd', "lha");
125                                 }
126                         else {
127                                 open(OUT, &webmin_command_as_user($uinfo[0], 0, "(cd $qdir && lha xf $qpath)")." 2>&1 </dev/null |");
128                                 while(<OUT>) {
129                                         $out .= $_;
130                                         if (/(\S[^\t]*\S)\s+\-\s+/) {
131                                                 push(@files, "/".$1);
132                                                 }
133                                         }
134                                 close(OUT);
135                                 $err = $out if ($?);
136                                 }
137                         $fmt = "lha";
138                         }
139                 elsif ($path =~ /\.(tar\.gz|tgz|tar\.bz|tbz|tar\.bz2|tbz2)$/i) {
140                         # Compressed tar file
141                         local $zipper = $path =~ /bz(2?)$/i ? "bunzip2"
142                                                             : "gunzip";
143                         if (!&has_command("tar")) {
144                                 $err = &text('upload_ecmd', "tar");
145                                 }
146                         elsif (!&has_command($zipper)) {
147                                 $err = &text('upload_ecmd', $zipper);
148                                 }
149                         else {
150                                 open(OUT, &webmin_command_as_user($uinfo[0], 0, "(cd $qdir && $zipper -c $qpath | tar xvf -)")." 2>&1 </dev/null |");
151                                 while(<OUT>) {
152                                         $out .= $_;
153                                         if (/^(.*)/) {
154                                                 push(@files, $1);
155                                                 }
156                                         }
157                                 close(OUT);
158                                 $err = $out if ($?);
159                                 }
160                         $fmt = $zipper eq "gunzip" ? "tgz" : "tbz2";
161                         }
162                 else {
163                         # Doesn't look possible
164                         $err = $text{'upload_notcomp'};
165                         }
166                 &switch_uid_to($uinfo[2], scalar(@ginfo) ? $ginfo[2] : $uinfo[3]);
167                 if (!$err) {
168                         local $j = join("<br>",
169                                 map { "&nbsp;&nbsp;<tt>$_</tt>" } @files);
170                         if ($in{'zip'} == 2) {
171                                 unlink($path);
172                                 $ext{$path} = $text{'upload_deleted'}."<br>".$j;
173                                 }
174                         else {
175                                 $ext{$path} = $text{'upload_extracted'}."<br>".$j;
176                                 }
177                         }
178                 else {
179                         $ext{$path} = &text('email_eextract', $err);
180                         }
181                 $estatus = $err ? &text('email_extfailed', $err)
182                                 : &text('email_extdone_'.$fmt);
183                 print &text('upload_unzipdone', $estatus),"<p>\n";
184                 }
185
186         # Add to email message
187         $msg .= &text('email_upfile', $f)."\n";
188         $msg .= &text('email_uppath', $path)."\n";
189         $msg .= &text('email_upsize', &nice_size($st[7]))."\n";
190         if ($estatus) {
191                 $msg .= &text('email_upextract', $estatus)."\n";
192                 }
193         $msg .= "\n";
194         }
195
196 # Switch back to root
197 &switch_uid_back();
198
199 # Save the settings
200 if ($module_info{'usermin'}) {
201         &lock_file("$user_module_config_directory/config");
202         $userconfig{'dir'} = $in{'dir'};
203         &write_file("$user_module_config_directory/config", \%userconfig);
204         &unlock_file("$user_module_config_directory/config");
205         }
206 else {
207         &lock_file("$module_config_directory/config");
208         $config{'dir_'.$remote_user} = $in{'dir'};
209         $config{'user_'.$remote_user} = $in{'user'};
210         $config{'group_'.$remote_user} = $in{'group_def'} ? undef
211                                                            : $in{'group'};
212         &write_file("$module_config_directory/config", \%config);
213         &unlock_file("$module_config_directory/config");
214         }
215
216 # Send email
217 if ($email && $msg) {
218         $msg = $text{'email_upmsg'}."\n\n".$msg;
219         &send_email_notification($email, $text{'email_subjectu'}, $msg);
220         }
221
222 &webmin_log("upload", undef, undef, { 'uploads' => \@uploads });
223
224 &ui_print_footer("index.cgi?mode=upload", $text{'index_return'});
225