Handle hostnames with upper-case letters
[webmin.git] / updown / download.cgi
1 #!/usr/local/bin/perl
2 # download.cgi
3 # Save a download or start it right now
4
5 require './updown-lib.pl';
6 require 'timelocal.pl';
7 &ReadParse();
8 &error_setup($text{'download_err'});
9
10 # Validate and store inputs
11 $i = 0;
12 @urls = split(/[\r\n]+/, $in{'urls'});
13 @urls || &error($text{'download_enone'});
14 foreach $u (@urls) {
15         local ($proto, $host, $port, $page, $ssl);
16         if ($u =~ /^http/) {
17                 ($host, $port, $page, $ssl, $user, $pass) = &parse_http_url($u);
18                 $proto = $ssl ? "https" : "http";
19                 }
20         elsif ($u =~ /^ftp:\/\/([^\/]+)(:21)?(\/.*)$/) {
21                 $proto = "ftp";
22                 $host = $1; $page = $3;
23                 }
24         else {
25                 &error(&text('download_eurl', $u));
26                 }
27         if ($host =~ /^([^:\@]+):([^:\@]+)\@(\S+)/) {
28                 $user = $1;
29                 $pass = $2;
30                 $host = $3;
31                 }
32         $download{"url_$i"} = $u;
33         $download{"proto_$i"} = $proto;
34         $download{"host_$i"} = $host;
35         $download{"user_$i"} = $user;
36         $download{"pass_$i"} = $pass;
37         $download{"port_$i"} = $port;
38         $download{"page_$i"} = $page;
39         $download{"ssl_$i"} = $ssl;
40         $i++;
41         }
42 $in{'dir'} || &error($text{'upload_edir'});
43 &can_write_file($in{'dir'}) ||
44         &error(&text('download_eaccess', "<tt>$in{'dir'}</tt>", $!));
45 $download{'dir'} = $in{'dir'};
46 if ($can_mode != 3) {
47         # User can be entered
48         scalar(@uinfo = getpwnam($in{'user'})) || &error($text{'upload_euser'});
49         &can_as_user($in{'user'}) ||
50                 &error(&text('download_eucannot', $in{'user'}));
51         $download{'uid'} = $uinfo[2];
52         $in{'group_def'} || scalar(@ginfo = getgrnam($in{'group'})) ||
53                 &error($text{'upload_egroup'});
54         $can_mode == 0 || $in{'group_def'} || &in_group(\@uinfo, \@ginfo) ||
55                 &error($text{'download_egcannot'});
56         $download{'gid'} = scalar(@ginfo) ? $ginfo[2] : $uinfo[3];
57         }
58 else {
59         # User is fixed
60         if (&supports_users()) {
61                 @uinfo = getpwnam($remote_user);
62                 $download{'uid'} = $uinfo[2];
63                 $download{'gid'} = $uinfo[3];
64                 }
65         }
66 if ($in{'bg'} && $can_schedule) {
67         # Validate time
68         $in{'hour'} =~ /^\d+$/ && $in{'min'} =~ /^\d+$/ &&
69                 $in{'day'} =~ /^\d+$/ && $in{'year'} =~ /^\d+$/ ||
70                         &error($text{'download_edate'});
71         eval { $download{'time'} = timelocal(0, $in{'min'}, $in{'hour'},
72                          $in{'day'}, $in{'month'}, $in{'year'}-1900) };
73         $@ && &error($text{'download_edate2'});
74         }
75 if (defined($in{'email_def'}) && !$in{'email_def'}) {
76         # Validate email
77         $in{'email'} =~ /\S/ || &error($text{'upload_eemail'});
78         $download{'email'} = $in{'email'};
79         }
80
81 # Create the directory if needed
82 if (!-d $download{'dir'} && $in{'mkdir'}) {
83         &switch_uid_to($download{'uid'}, $download{'gid'});
84         mkdir($download{'dir'}, 0755) || &error(&text('upload_emkdir', $!));
85         &switch_uid_back();
86         }
87
88 # Save the settings
89 if ($module_info{'usermin'}) {
90         &lock_file("$user_module_config_directory/config");
91         $userconfig{'ddir'} = $in{'dir'};
92         &write_file("$user_module_config_directory/config", \%userconfig);
93         &unlock_file("$user_module_config_directory/config");
94         }
95 else {
96         &lock_file("$module_config_directory/config");
97         $config{'ddir_'.$remote_user} = $in{'dir'};
98         $config{'duser_'.$remote_user} = $in{'user'};
99         $config{'dgroup_'.$remote_user} = $in{'group_def'} ? undef
100                                                            : $in{'group'};
101         &write_file("$module_config_directory/config", \%config);
102         &unlock_file("$module_config_directory/config");
103         }
104
105 if ($in{'bg'} && $can_background) {
106         # Create a script to be called by At
107         &foreign_require("cron", "cron-lib.pl");
108         &lock_file($atjob_cmd);
109         &cron::create_wrapper($atjob_cmd, $module_name, "download.pl");
110         &unlock_file($atjob_cmd);
111         &save_download(\%download);
112
113         if (!$can_schedule) {
114                 # Just run this script right now
115                 &execute_command("$atjob_cmd $download{'id'} &");
116                 }
117         else {
118                 # Create an At job to do the download
119                 &foreign_require("at", "at-lib.pl");
120                         {
121                         local %ENV;
122                         delete($ENV{'FOREIGN_MODULE_NAME'});
123                         delete($ENV{'FOREIGN_ROOT_DIRECTORY'});
124                         &clean_environment();
125                         $ENV{'REMOTE_USER'} = $remote_user;     # For usermin
126                         $ENV{'BASE_REMOTE_USER'} = $base_remote_user;
127                         &at::create_atjob(
128                                 $module_info{'usermin'} ? $remote_user : "root",
129                                 $download{'time'},
130                                 "$atjob_cmd $download{'id'}",
131                                 "/");
132                         &reset_environment();
133                         }
134                 }
135
136         &redirect("index.cgi?mode=download");
137         }
138 else {
139         # Download it now, and show the results
140         &ui_print_unbuffered_header(undef, $text{'download_title'}, "");
141
142         $error = &do_download(\%download, \&progress_callback, \@paths);
143         @paths = grep { $_ } @paths;
144         if (@paths) {
145                 print "<p>$text{'download_done'}<p>\n";
146                 foreach $p (@paths) {
147                         @st = stat($p);
148                         print "<tt>$p</tt> ($st[7] bytes)<br>\n";
149                         }
150                 }
151         if ($error) {
152                 print "<p><b>",&text('download_failed', $error),"</b><p>\n";
153                 }
154
155         &ui_print_footer("index.cgi?mode=download", $text{'index_return'});
156         }
157 &webmin_log("download", undef, undef, { 'urls' => \@urls,
158                                         'time' => $download{'time'} });
159