Handle hostnames with upper-case letters
[webmin.git] / usermin / upgrade.cgi
1 #!/usr/local/bin/perl
2 # upgrade.cgi
3 # Upgrade usermin if possible
4
5 require './usermin-lib.pl';
6 $access{'upgrade'} || &error($text{'acl_ecannot'});
7 &foreign_require("proc", "proc-lib.pl");
8 &ReadParseMime();
9 &get_usermin_miniserv_config(\%miniserv);
10
11 &ui_print_unbuffered_header(undef, $in{'install'} ? $text{'upgrade_title2'} : $text{'upgrade_title'}, "");
12
13 if ($in{'source'} == 0) {
14         # from local file
15         &error_setup(&text('upgrade_err1', $in{'file'}));
16         $file = $in{'file'};
17         if (!(-r $file)) { &inst_error($text{'upgrade_efile'}); }
18         }
19 elsif ($in{'source'} == 1) {
20         # from uploaded file
21         &error_setup($text{'upgrade_err2'});
22         $file = &transname();
23         $need_unlink = 1;
24         if ($no_upload) {
25                 &inst_error($text{'upgrade_ebrowser'});
26                 }
27         &open_tempfile(MOD, ">$file", 0, 1);
28         &print_tempfile(MOD, $in{'upload'});
29         &close_tempfile(MOD);
30         }
31 elsif ($in{'source'} == 2) {
32         # find latest version at www.webmin.com by looking at index page
33         &error_setup($text{'upgrade_err3'});
34         $file = &transname();
35         &http_download('www.webmin.com', 80, '/index6.html', $file, \$error);
36         $error && &inst_error($error);
37         open(FILE, $file);
38         while(<FILE>) {
39                 if (/usermin-([0-9\.]+)\.tar\.gz/) {
40                         $version = $1;
41                         last;
42                         }
43                 }
44         close(FILE);
45         unlink($file);
46         if (!$in{'force'}) {
47                 if ($version == &get_usermin_version()) {
48                         &inst_error(&text('upgrade_elatest', $version));
49                         }
50                 elsif ($version <= &get_usermin_version()) {
51                         &inst_error(&text('upgrade_eversion', $version));
52                         }
53                 }
54
55         # Work out the current Usermin type (webmail or regular)
56         $product = "usermin";
57         if (&has_command("rpm") && $in{'mode'} eq 'rpm' &&
58             &execute_command("rpm -q usermin-webmail") == 0) {
59                 $product = "usermin-webmail";
60                 }
61         elsif (&has_command("dpkg") && $in{'mode'} eq 'deb' &&
62                &execute_command("dpkg --list usermin-webmail") == 0) {
63                 $product = "usermin-webmail";
64                 }
65
66         if ($in{'mode'} eq 'rpm') {
67                 $progress_callback_url = &convert_osdn_url(
68                     "http://$webmin::osdn_host/webadmin/${product}-${version}-1.noarch.rpm");
69                 }
70         elsif ($in{'mode'} eq 'deb') {
71                 $progress_callback_url = &convert_osdn_url(
72                     "http://$webmin::osdn_host/webadmin/${product}_${version}_all.deb");
73                 }
74         else {
75                 $progress_callback_url = &convert_osdn_url(
76                     "http://$webmin::osdn_host/webadmin/${product}-${version}.tar.gz");
77                 }
78         ($host, $port, $page, $ssl) = &parse_http_url($progress_callback_url);
79         &http_download($host, $port, $page, $file, \$error,
80                        \&progress_callback, $ssl);
81         $error && &inst_error($error);
82         $need_unlink = 1;
83         }
84 elsif ($in{'source'} == 5) {
85         # Download from some URL
86         &error_setup(&text('upgrade_err5', $in{'url'}));
87         $file = &transname();
88         $progress_callback_url = $in{'url'};
89         if ($in{'url'} =~ /^(http|https):\/\/([^\/]+)(\/.*)$/) {
90                 $ssl = $1 eq 'https';
91                 $host = $2; $page = $3; $port = $ssl ? 443 : 80;
92                 if ($host =~ /^(.*):(\d+)$/) { $host = $1; $port = $2; }
93                 &http_download($host, $port, $page, $file, \$error,
94                                \&progress_callback, $ssl);
95                 }
96         elsif ($in{'url'} =~ /^ftp:\/\/([^\/]+)(:21)?\/(.*)$/) {
97                 $host = $1; $ffile = $3;
98                 &ftp_download($host, $ffile, $file,
99                               \$error, \&progress_callback);
100                 }
101         else { &inst_error($text{'upgrade_eurl'}); }
102         $need_unlink = 1;
103         $error && &inst_error($error);
104         }
105 $qfile = quotemeta($file);
106
107 # gunzip the file if needed
108 open(FILE, $file);
109 read(FILE, $two, 2);
110 close(FILE);
111 if ($two eq "\037\213") {
112         if (!&has_command("gunzip")) {
113                 &inst_error($text{'upgrade_egunzip'});
114                 }
115         $newfile = &transname();
116         $out = `gunzip -c $file 2>&1 >$newfile`;
117         if ($?) {
118                 unlink($newfile);
119                 &inst_error(&text('upgrade_egzip', "<tt>$out</tt>"));
120                 }
121         unlink($file) if ($need_unlink);
122         $need_unlink = 1;
123         $file = $newfile;
124         }
125 $qfile = quotemeta($file);
126
127 # Get list of updates
128 $updatestemp = &transname();
129 &http_download($update_host, $update_port, $update_page, $updatestemp,
130                \$updates_error);
131
132 if ($in{'mode'} eq 'rpm') {
133         # Check if it is an RPM package
134         $out = `rpm -qp $qfile`;
135         $out =~ /^usermin-(\d+\.\d+)/ ||
136             $out =~ /^usermin-webmail-(\d+\.\d+)/ ||
137                 &inst_error($text{'upgrade_erpm'});
138         $version = $1;
139         if ($version <= &get_usermin_version() && !$in{'force'}) {
140                 &inst_error(&text('upgrade_eversion', $version));
141                 }
142
143         # Install the RPM
144         if ($in{'force'}) {
145                 $cmd = "rpm -U --force $qfile";
146                 }
147         else {
148                 $cmd = "rpm -U --ignoreos --ignorearch --nodeps $qfile";
149                 }
150         print "<p>",&text($in{'install'} ? 'upgrade_setup2' : 'upgrade_setup',
151                           "<tt>$cmd</tt>"),"<br>\n";
152         print "<pre>";
153         &proc::safe_process_exec($cmd, 0, 0, STDOUT, undef, 1);
154         print "</pre>";
155         unlink($file) if ($need_unlink);
156         }
157 elsif ($in{'mode'} eq 'deb') {
158         # Check if it is a Debian package
159         $out = `dpkg --info $qfile`;
160         $out =~ /Package:\s+(\S+)/ &&
161             ($1 eq "usermin" || $1 eq "usermin-webmail") ||
162                 &inst_error($text{'upgrade_edeb'});
163         $out =~ /Version:\s+(\S+)/ ||
164                 &inst_error($text{'upgrade_edeb'});
165         $version = $1;
166         if ($version <= &get_usermin_version() && !$in{'force'}) {
167                 &inst_error(&text('upgrade_eversion', $version));
168                 }
169
170         # Install the package
171         $cmd = "dpkg --install $qfile";
172         print "<p>",&text($in{'install'} ? 'upgrade_setup2' : 'upgrade_setup',
173                           "<tt>$cmd</tt>"),"<br>\n";
174         print "<pre>";
175         &proc::safe_process_exec($cmd, 0, 0, STDOUT, undef, 1);
176         print "</pre>";
177         unlink($file) if ($need_unlink);
178         }
179 else {
180         # Check if it is a usermin tarfile
181         open(TAR, "tar tf $file 2>&1 |");
182         while(<TAR>) {
183                 if (/^usermin-([0-9\.]+)\//) {
184                         $version = $1;
185                         }
186                 if (/^webmin-([0-9\.]+)\//) {
187                         $webmin_version = $1;
188                         }
189                 if (/^[^\/]+\/(\S+)$/) {
190                         $hasfile{$1}++;
191                         }
192                 }
193         close(TAR);
194         if ($webmin_version) {
195                 &inst_error(&text('upgrade_ewebmin', $webmin_version));
196                 }
197         if (!$version) {
198                 if ($hasfile{'module.info'}) {
199                         &inst_error(&text('upgrade_emod', 'edit_mods.cgi'));
200                         }
201                 else {
202                         &inst_error($text{'upgrade_etar'});
203                         }
204                 }
205         if (!$in{'force'}) {
206                 if ($version <= &get_usermin_version()) {
207                         &inst_error(&text('upgrade_eversion', $version));
208                         }
209                 }
210
211         $| = 1;
212         local $cmd;
213         if ($in{'install'}) {
214                 # Installing .. extract it in /usr/local and run setup.sh
215                 local $root = "/usr/local";
216                 mkdir($root, 0755);
217                 $out = `cd $root ; tar xf $file 2>&1 >/dev/null`;
218                 if ($?) {
219                         &inst_error(&text('upgrade_euntar', "<tt>$out</tt>"));
220                         }
221                 unlink($file) if ($need_unlink);
222                 $ENV{'config_dir'} = $standard_usermin_dir;
223                 $ENV{'var_dir'} = "/var/usermin";
224                 $perl = &get_perl_path();
225                 $ENV{'perl'} = $perl;
226                 $ENV{'autoos'} = 3;
227                 $ENV{'port'} = 20000;
228                 $ENV{'ssl'} = 1;
229                 $ENV{'os_type'} = $gconfig{'os_type'};
230                 $ENV{'os_version'} = $gconfig{'os_version'};
231                 $ENV{'real_os_type'} = $gconfig{'real_os_type'};
232                 $ENV{'real_os_version'} = $gconfig{'real_os_version'};
233                 $cmd = "(cd $root/usermin-$version && ./setup.sh)";
234                 print "<p>",&text('upgrade_setup2', "<tt>setup.sh</tt>"),"<br>\n";
235                 }
236         else {
237                 # Upgrading .. work out where to extract
238                 if ($in{'dir'}) {
239                         # Since we are currently installed in a fixed directory,
240                         # just extract to a temporary location
241                         $extract = &transname();
242                         mkdir($extract, 0755);
243                         }
244                 else {
245                         # Next to the current directory
246                         $extract = "$miniserv{'root'}/..";
247                         }
248
249                 # Extract it next to the current directory and run setup.sh
250                 $out = `cd $extract ; tar xf $file 2>&1 >/dev/null`;
251                 if ($?) {
252                         &inst_error(&text('upgrade_euntar', "<tt>$out</tt>"));
253                         }
254                 unlink($file) if ($need_unlink);
255                 $ENV{'config_dir'} = $config{'usermin_dir'};
256                 $ENV{'webmin_upgrade'} = 1;
257                 $ENV{'autothird'} = 1;
258                 $setup = $in{'dir'} ? "./setup.sh '$in{'dir'}'" : "./setup.sh";
259                 if ($in{'delete'}) {
260                         $ENV{'deletedold'} = 1;
261                         $cmd = "(cd $extract/usermin-$version && $setup && rm -rf \"$miniserv{'root'}\")";
262                         }
263                 else {
264                         $cmd = "(cd $extract/usermin-$version && $setup)";
265                         }
266                 print "<p>",&text('upgrade_setup', "<tt>setup.sh</tt>"),"<br>\n";
267                 }
268         print "<pre>";
269         &proc::safe_process_exec($cmd, 0, 0, STDOUT, undef, 1);
270         print "</pre>";
271         if ($in{'dir'}) {
272                 # Can delete the temporary source directory
273                 system("rm -rf \"$extract\"");
274                 }
275         }
276
277 # Notify Webmin that this module might now be usable
278 &foreign_require("webmin", "webmin-lib.pl");
279 ($inst, $changed) = &webmin::build_installed_modules(0, 'usermin');
280 if (@$changed && defined(&theme_post_change_modules)) {
281         &theme_post_change_modules();
282         }
283
284 &webmin_log($in{'install'} ? "uinstall" : "upgrade", undef, undef,
285             { 'version' => $version, 'mode' => $in{'mode'} });
286
287 # Find out about any updates for this new version.
288 if ($updates_error) {
289         print "<br>",&text('upgrade_eupdates', $updates_error),"<p>\n";
290         }
291 else {
292         open(UPDATES, $updatestemp);
293         while(<UPDATES>) {
294                 if (/^([^\t]+)\t+([^\t]+)\t+([^\t]+)\t+([^\t]+)\t+(.*)/) {
295                         push(@updates, [ $1, $2, $3, $4, $5 ]);
296                         }
297                 }
298         close(UPDATES);
299         unlink($updatestemp);
300         $bversion = &base_version($version);
301         foreach $u (@updates) {
302                 next if ($u->[1] >= $bversion + .01 || $u->[1] <= $bversion ||
303                          $u->[1] <= $version);
304                 local $osinfo = { 'os_support' => $u->[3] };
305                 next if (!&check_usermin_os_support($osinfo));
306                 $ucount++;
307                 }
308         if ($ucount) {
309                 print "<br>",&text('upgrade_updates', $ucount,
310                         "update.cgi?source=0&show=0&missing=0"),"<p>\n";
311                 }
312         }
313
314 &ui_print_footer("", $text{'index_return'});
315
316 sub inst_error
317 {
318 unlink($file) if ($need_unlink);
319 print "<br><b>$whatfailed : $_[0]</b> <p>\n";
320 &ui_print_footer("", $text{'index_return'});
321 exit;
322 }
323