3 # Upgrade webmin if possible
5 require './webmin-lib.pl';
6 &foreign_require("proc", "proc-lib.pl");
7 &foreign_require("acl", "acl-lib.pl");
12 &ui_print_header(undef, $text{'upgrade_title'}, "");
14 # Save this CGI from being killed by the upgrade
15 $SIG{'TERM'} = 'IGNORE';
17 if ($in{'source'} == 0) {
19 &error_setup(&text('upgrade_err1', $in{'file'}));
21 if (!-r $file) { &inst_error($text{'upgrade_efile'}); }
22 if ($file =~ /webmin-(\d+\.\d+)/) {
26 if ($version == &get_webmin_version()) {
27 &inst_error(&text('upgrade_elatest', $version));
29 elsif ($version <= &get_webmin_version()) {
30 &inst_error(&text('upgrade_eversion', $version));
34 elsif ($in{'source'} == 1) {
36 &error_setup($text{'upgrade_err2'});
40 &inst_error($text{'upgrade_ebrowser'});
43 print MOD $in{'upload'};
45 if ($in{'upload_filename'} =~ /webmin-(\d+\.\d+)/) {
49 elsif ($in{'source'} == 2) {
50 # find latest version at www.webmin.com by looking at index page
51 &error_setup($text{'upgrade_err3'});
52 ($ok, $version) = &get_latest_webmin_version();
53 $ok || &inst_error($version);
55 if ($version == &get_webmin_version()) {
56 &inst_error(&text('upgrade_elatest', $version));
58 elsif ($version <= &get_webmin_version()) {
59 &inst_error(&text('upgrade_eversion', $version));
62 if ($in{'mode'} eq 'rpm') {
64 $progress_callback_url = &convert_osdn_url(
65 "http://$osdn_host/webadmin/webmin-$version-1.noarch.rpm");
67 elsif ($in{'mode'} eq 'deb') {
68 # Downloading Debian package
69 $progress_callback_url = &convert_osdn_url(
70 "http://$osdn_host/webadmin/webmin_${version}_all.deb");
72 elsif ($in{'mode'} eq 'solaris-pkg') {
73 # Downloading my Solaris package
74 $progress_callback_url = &convert_osdn_url(
75 "http://$osdn_host/webadmin/webmin-$version.pkg.gz");
78 # Downloading tar.gz file
79 $progress_callback_url = &convert_osdn_url(
80 "http://$osdn_host/webadmin/webmin-$version.tar.gz");
82 ($host, $port, $page, $ssl) = &parse_http_url($progress_callback_url);
84 &http_download($host, $port, $page, $file, \$error,
85 \&progress_callback, $ssl);
86 $error && &inst_error($error);
89 elsif ($in{'source'} == 5) {
90 # Download from some URL
91 &error_setup(&text('upgrade_err5', $in{'url'}));
93 $in{'url'} = &convert_osdn_url($in{'url'});
94 $progress_callback_url = $in{'url'};
95 if ($in{'url'} =~ /^(http|https):\/\/([^\/]+)(\/.*)$/) {
97 $host = $2; $page = $3; $port = $ssl ? 443 : 80;
98 if ($host =~ /^(.*):(\d+)$/) { $host = $1; $port = $2; }
99 &http_download($host, $port, $page, $file, \$error,
100 \&progress_callback, $ssl);
102 elsif ($in{'url'} =~ /^ftp:\/\/([^\/]+)(:21)?\/(.*)$/) {
103 $host = $1; $ffile = $3;
104 &ftp_download($host, $ffile, $file,
105 \$error, \&progress_callback);
107 else { &inst_error($text{'upgrade_eurl'}); }
109 $error && &inst_error($error);
110 if ($in{'url'} =~ /webmin-(\d+\.\d+)/) {
114 elsif ($in{'source'} == 3) {
115 # Get the latest version from Caldera with cupdate
116 &redirect("/cupdate/");
118 elsif ($in{'source'} == 4) {
119 # Just run the command emerge webmin
120 &error_setup(&text('upgrade_err4'));
124 $qfile = quotemeta($file);
126 # Import the signature for RPM
127 if ($in{'mode'} eq 'rpm') {
128 system("rpm --import $module_root_directory/jcameron-key.asc >/dev/null 2>&1");
131 # Check the signature if possible
133 # Check the package signature
134 ($ec, $emsg) = &gnupg_setup();
136 if ($in{'mode'} eq 'rpm') {
137 # Use rpm's gpg signature verification
138 my $out = `rpm --checksig $qfile 2>&1`;
141 $emsg = &text('upgrade_echecksig',
146 # Do a manual signature check
147 if ($in{'source'} == 2) {
148 # Download the key for this tar.gz
149 my ($sigtemp, $sigerror);
150 &http_download($update_host, $update_port, "/download/sigs/webmin-$version.tar.gz-sig.asc", \$sigtemp, \$sigerror);
153 $emsg = &text('upgrade_edownsig',
157 my $data =&read_file_contents($file);
159 &verify_data($data, $sigtemp);
163 "upgrade_everify$vc",
164 &html_escape($vmsg));
169 $emsg = $text{'upgrade_nosig'};
174 # Tell the user about any GnuPG error
182 print "$text{'upgrade_sigok'}<p>\n";
186 print "$text{'upgrade_nocheck'}<p>\n";
189 if ($in{'mode'} ne 'gentoo') {
190 # gunzip the file if needed
194 if ($two eq "\037\213") {
195 if (!&has_command("gunzip")) {
196 &inst_error($text{'upgrade_egunzip'});
198 $newfile = &transname();
199 $out = `gunzip -c $qfile 2>&1 >$newfile`;
202 &inst_error(&text('upgrade_egzip', "<tt>$out</tt>"));
204 unlink($file) if ($need_unlink);
209 $qfile = quotemeta($file);
211 if ($in{'mode'} eq 'rpm') {
212 # Check if it is an RPM package
214 if (open(RPM, "$root_directory/rpm-name")) {
215 chop($rpmname = <RPM>);
218 $out = `rpm -qp $qfile`;
219 $out =~ /(^|\n)\Q$rpmname\E-(\d+\.\d+)/ ||
220 &inst_error($text{'upgrade_erpm'});
223 if ($version == &get_webmin_version()) {
224 &inst_error(&text('upgrade_elatest', $version));
226 elsif ($version <= &get_webmin_version()) {
227 &inst_error(&text('upgrade_eversion', $version));
232 $ENV{'tempdir'} = $gconfig{'tempdir'};
233 print "<p>",$text{'upgrade_setuprpm'},"<p>\n";
236 &proc::safe_process_exec(
237 "rpm -U --force $qfile", 0, 0,
238 STDOUT, undef, 1, 1);
241 &proc::safe_process_exec(
242 "rpm -U --ignoreos --ignorearch $qfile", 0, 0,
243 STDOUT, undef, 1, 1);
245 unlink($file) if ($need_unlink);
248 elsif ($in{'mode'} eq 'deb') {
249 # Check if it is a Debian package
251 if (open(RPM, "$root_directory/deb-name")) {
252 chop($debname = <RPM>);
255 $out = `dpkg --info $qfile`;
256 $out =~ /Package:\s+(\S+)/ && $1 eq $debname ||
257 &inst_error($text{'upgrade_edeb'});
258 $out =~ /Version:\s+(\S+)/ ||
259 &inst_error($text{'upgrade_edeb'});
262 if ($version == &get_webmin_version()) {
263 &inst_error(&text('upgrade_elatest', $version));
265 elsif ($version <= &get_webmin_version()) {
266 &inst_error(&text('upgrade_eversion', $version));
270 # Install the package
271 $ENV{'tempdir'} = $gconfig{'tempdir'};
272 print "<p>",$text{'upgrade_setupdeb'},"<p>\n";
274 &proc::safe_process_exec("dpkg --install $qfile", 0, 0,
275 STDOUT, undef, 1, 1);
276 unlink($file) if ($need_unlink);
279 elsif ($in{'mode'} eq 'solaris-pkg' || $in{'mode'} eq 'sun-pkg') {
280 # Check if it is a solaris package
281 &foreign_require("software", "software-lib.pl");
282 &foreign_call("software", "is_package", $file) ||
283 &inst_error($text{'upgrade_epackage'});
284 my @p = &foreign_call("software", "file_packages", $file);
286 # The package name will always include "webmin" in lower case,
287 # but may be preceeded by the source package source ("WS" for the
288 # Webmin.com package, "SUNW" for the Sun distributed package).
289 # and it could have trailing characters to define a set of items
290 # that are installed separately ("r" for the Sun "root" package,
291 # "u" for the Sun "usr" package.
293 # So the problem is how to match the requested package to the
294 # currently installed package.
298 # Hardcode till I can get a better thought for doing this
299 # via a config (or other) file..
300 ($pkg, $description) = split(/ /, $p);
301 if ($pkg =~ /^(SUNWwebminu|WSwebmin)$/) {
311 &inst_error($text{'upgrade_ewpackage'});
314 # Install the package
315 print "<p>",$text{'upgrade_setuppackage'},"<p>\n";
316 print "PKG: $pkg<br>";
317 $ENV{'KEEP_ETC_WEBMIN'} = 1;
319 # Need to do this inline, otherwise the child process won't install the
320 # package. It would be interesting, however, if this were embedded in
321 # a remote script that could be nohup'd and it would restart the server.
323 &proc::safe_process_exec_logged(
324 "$config_directory/stop", 0, 0, STDOUT, undef, 1,1);
327 $in{'adminfile'} = '$module_root_directory/adminupgrade';
328 $rv = &software::install_package($file, $pkg);
329 &error($rv) if ($rv);
330 unlink($file) if ($need_unlink);
331 $ENV{'config_dir'} = $config_directory;
332 $ENV{'webmin_upgrade'} = 1;
333 $ENV{'autothird'} = 1;
334 $ENV{'tempdir'} = $gconfig{'tempdir'};
335 print "<p>",$text{'upgrade_setup'},"<p>\n";
338 # We now need to figure out the installed directory for
339 # this package. The best way is to find the basename
340 # for the miniserv.pl file associated with this package
341 # or, in grep context:
342 # grep "miniserv.pl.*$pkg"
343 # and the first element includes the pathname.
345 $targ = `grep "miniserv.pl.*$pkg" /var/sadm/install/contents`;
346 if ($targ =~ /^(.*)\/miniserv.pl.*$/) {
350 $setup = $in{'dir'} ? "./setup.sh '$in{'dir'}'" : "./setup.sh";
351 print "Package Directory: $dir<br>";
352 print "cd $dir && ./setup.sh<br>";
353 &proc::safe_process_exec(
354 "cd $dir && ./setup.sh", 0, 0, STDOUT, undef, 1, 1);
355 &proc::safe_process_exec_logged(
356 "$config_directory/start", 0, 0, STDOUT, undef, 1,1);
359 elsif ($in{'mode'} eq 'caldera') {
360 # Check if it is a Caldera RPM of Webmin
361 $out = `rpm -qp $file`;
362 $out =~ /^webmin-(\d+\.\d+)/ ||
363 &inst_error($text{'upgrade_erpm'});
364 if ($1 <= &get_webmin_version() && !$in{'force'}) {
365 &inst_error(&text('upgrade_eversion', "$1"));
368 open(OUT, "rpm -qpl $file |");
370 $wfound++ if (/^\/etc\/webmin/);
373 $wfound || &inst_error($text{'upgrade_ecaldera'});
376 print "<p>",$text{'upgrade_setuprpm'},"<p>\n";
378 &proc::safe_process_exec("rpm -U --ignoreos --ignorearch '$file'", 0, 0,
379 STDOUT, undef, 1, 1);
380 unlink($file) if ($need_unlink);
383 elsif ($in{'mode'} eq 'gentoo') {
384 # Check if it is a gentoo .tar.gz or .ebuild file of webmin
385 open(EMERGE, "emerge --pretend '$file' 2>/dev/null |");
389 if (/\s+[NRU]\s+\]\s+([^\/]+)\/webmin\-(\d\S+)/) {
394 $version || &inst_error($text{'upgrade_egentoo'});
396 if ($version == &get_webmin_version()) {
397 &inst_error(&text('upgrade_elatest', $version));
399 elsif ($version <= &get_webmin_version()) {
400 &inst_error(&text('upgrade_eversion', $version));
404 # Install the Gentoo package
405 print "<p>",$text{'upgrade_setupgentoo'},"<p>\n";
407 &proc::safe_process_exec("emerge '$file'", 0, 0, STDOUT, undef, 1, 1);
408 unlink($file) if ($need_unlink);
412 # Check if it is a webmin tarfile
413 open(TAR, "tar tf $file 2>&1 |");
416 if (/^webmin-([0-9\.]+)\//) {
419 if (/^usermin-([0-9\.]+)\//) {
420 $usermin_version = $1;
422 if (/^[^\/]+\/(\S+)$/) {
425 if (/^(webmin-([0-9\.]+)\/([^\/]+))$/ && $3 ne ".") {
426 # Found a top-level file, or *possibly* a directory
427 # under some versions of tar. Keep it so we know which
431 elsif (/^(webmin-[0-9\.]+\/([^\/]+))\// && $2 ne ".") {
432 # Found a sub-directory, like webmin-1.xx/foo/
433 # Keep this, so that we know which modules to extract.
434 # Also keep the full directory like webmin-1.xx/foo
435 # to avoid treating it as a file.
441 if ($usermin_version) {
442 &inst_error(&text('upgrade_eusermin', $usermin_version));
445 if ($hasfile{'module.info'}) {
446 &inst_error(&text('upgrade_emod', 'edit_mods.cgi'));
449 &inst_error($text{'upgrade_etar'});
453 if ($version == &get_webmin_version()) {
454 &inst_error(&text('upgrade_elatest', $version));
456 elsif ($version <= &get_webmin_version()) {
457 &inst_error(&text('upgrade_eversion', $version));
461 # Work out where to extract
463 # Since we are currently installed in a fixed directory,
464 # just extract to a temporary location
465 $extract = &transname();
466 mkdir($extract, 0755);
469 # Next to the current directory
473 # Do the extraction of the tar file, and run setup.sh
476 # Extact top-level files like setup.sh and os_list.txt
477 $topfiles = join(" ", map { quotemeta($_) }
478 grep { !$tardir{$_} } @topfiles);
479 $out = `cd $extract ; tar xf $file $topfiles 2>&1 >/dev/null`;
481 &inst_error(&text('upgrade_euntar', "<tt>$out</tt>"));
484 # Add current modules and current non-module directories
485 # (like themes and lang and images)
486 @mods = grep { $intar{$_} } map { $_->{'dir'} }
487 &get_all_module_infos(1);
488 opendir(DIR, $root_directory);
489 foreach $d (readdir(DIR)) {
490 next if ($d =~ /^\./);
491 my $p = "$root_directory/$d";
492 if (-d $p && !-r "$p/module.info" && $intar{$d}) {
498 # Extract current modules and other directories
499 $mods = join(" ", map { quotemeta("webmin-$version/$_") }
501 $out = `cd $extract ; tar xf $file $mods 2>&1 >/dev/null`;
503 &inst_error(&text('upgrade_euntar', "<tt>$out</tt>"));
507 # Extract the whole file
508 $out = `cd $extract ; tar xf $file 2>&1 >/dev/null`;
510 &inst_error(&text('upgrade_euntar', "<tt>$out</tt>"));
513 unlink($file) if ($need_unlink);
514 $ENV{'config_dir'} = $config_directory;
515 $ENV{'webmin_upgrade'} = 1;
516 $ENV{'autothird'} = 1;
517 $ENV{'tempdir'} = $gconfig{'tempdir'};
518 $ENV{'deletedold'} = 1 if ($in{'delete'});
519 print "<p>",$text{'upgrade_setup'},"<p>\n";
521 $setup = $in{'dir'} ? "./setup.sh '$in{'dir'}'" : "./setup.sh";
522 &proc::safe_process_exec(
523 "cd $extract/webmin-$version && $setup", 0, 0,
524 STDOUT, undef, 1, 1);
528 # Can delete the old root directory
529 system("rm -rf \"$root_directory\"");
532 # Can delete the temporary source directory
533 system("rm -rf \"$extract\"");
537 &webmin_log("upgrade", undef, undef, { 'version' => $version,
538 'mode' => $in{'mode'} });
541 # Forcibly disconnect all other login sessions
542 &foreign_require("acl", "acl-lib.pl");
543 &get_miniserv_config(\%miniserv);
544 &acl::open_session_db(\%miniserv);
545 foreach $s (keys %acl::sessiondb) {
546 if ($s ne $main::session_id) {
547 delete($acl::sessiondb{$s});
550 dbmclose(%acl::sessiondb);
551 &restart_miniserv(1);
554 # Find out about any updates for this new version.
555 ($updates) = &fetch_updates($update_url);
556 $updates = &filter_updates($updates, $version);
557 if (scalar(@$updates)) {
558 print "<br>",&text('upgrade_updates', scalar(@$updates),
559 "update.cgi?source=0&show=0&missing=0"),"<p>\n";
562 &ui_print_footer("", $text{'index_return'});
566 unlink($file) if ($need_unlink);
567 unlink($updatestemp);
568 print "<b>$main::whatfailed : $_[0]</b> <p>\n";
569 &ui_print_footer("", $text{'index_return'});