Move un-used modules to special category, show link to refresh
authorJamie Cameron <jcameron@webmin.com>
Tue, 4 Mar 2008 00:56:51 +0000 (00:56 +0000)
committerJamie Cameron <jcameron@webmin.com>
Tue, 4 Mar 2008 00:56:51 +0000 (00:56 +0000)
20 files changed:
CHANGELOG
README
blue-theme/images/refresh-small.gif [new file with mode: 0644]
blue-theme/left.cgi
blue-theme/theme.pl
config_save.cgi
fsdump/ftp.pl
fsdump/lang/en
fsdump/linux-lib.pl
lang/en
makedebian.pl
makedist.pl
software/install_pack.cgi
software/software-lib.pl
ui-lib.pl
version
web-lib-funcs.pl
webmin/lang/en
webmin/postinstall.pl [new file with mode: 0644]
webmin/webmin-lib.pl

index c3c9b5c..3683109 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -88,3 +88,6 @@ Changed the error message that appears when Webmin detects a link from another w
 Links from unknown referers are now blocked by default, to prevent XSS attacks. This may break browsers that don't supply a Referer: HTTP header.
 ---- Changes since 1.400 ----
 Big Czech translation updates, thanks to Petr Vanek and the Czech translation team.
+All popups in Webmin are now XSS-safe, and thus do not need protection from unknown referers which prevented them from working in some browsers.
+All Webmin session IDs are now stored MD5 hashed, to prevent sessions from being captured if the sessiondb DBM is somehow read by an attacker.
+Many Dutch updates, thanks to Gandyman.
diff --git a/README b/README
index 67c5bd6..3f9a02b 100644 (file)
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-Webmin Version 1.400
+Webmin Version 1.403
 --------------------
 Webmin is a web-based interface for system administration for Unix. 
 Using any browser that supports tables and forms, you can setup user
diff --git a/blue-theme/images/refresh-small.gif b/blue-theme/images/refresh-small.gif
new file mode 100644 (file)
index 0000000..65a2a0e
Binary files /dev/null and b/blue-theme/images/refresh-small.gif differ
index 2d6f9ab..97ee763 100755 (executable)
@@ -7,8 +7,12 @@ do './ui-lib.pl';
 &ReadParse();
 %text = &load_language($current_theme);
 
-# Work out what categories we have
+# Work out what modules and categories we have
 @modules = &get_visible_module_infos();
+if (&get_product_name() eq 'webmin') {
+       @unmodules = grep { $_->{'installed'} eq '0' } @modules;
+       @modules = grep { $_->{'installed'} ne '0' } @modules;
+       }
 %cats = &list_categories(\@modules);
 if (defined($cats{''})) {
        $cats{'others'} = $cats{''};
@@ -94,6 +98,23 @@ else {
                        }
                print "</div>\n";
                }
+
+       # Show un-installed modules
+       if (@unmodules) {
+               &print_category_opener('_unused', $in{'_unused'} ? 1 : 0,
+                      "<font color=#888888>$text{'main_unused'}</font>");
+               $cls = $in{'_unused'} ? "itemshown" : "itemhidden";
+               print "<div class='$cls' id='_unused'>";
+               foreach $minfo (@unmodules) {
+                       &print_category_link("$minfo->{'dir'}/",
+                                            $minfo->{'desc'},
+                                            undef,
+                                            undef,
+                                            $minfo->{'noframe'} ? "_top" : "",
+                                       );
+                       }
+               print "</div>\n";
+               }
        }
 
 # Show module/help search form
@@ -130,6 +151,12 @@ if (&get_product_name() eq 'webmin' &&             # For Webmin
        print "<div class='aftericon'><a target=right href='feedback_form.cgi'>$text{'left_feedback'}</a></div></div>\n";
        }
 
+# Show refesh modules link, for master admin
+if (&foreign_available("webmin")) {
+       print "<div class='linkwithicon'><img src=images/refresh-small.gif>\n";
+       print "<div class='aftericon'><a target=right href='webmin/refresh_modules.cgi'>$text{'main_refreshmods'}</a></div></div>\n";
+       }
+
 # Show logout link
 &get_miniserv_config(\%miniserv);
 if ($miniserv{'logout'} && !$ENV{'SSL_USER'} && !$ENV{'LOCAL_USER'} &&
index da4b605..5415b3f 100755 (executable)
@@ -282,3 +282,12 @@ $theme_ui_columns_count++;
 return $rv;
 }
 
+sub theme_post_change_modules
+{
+print "<script>\n";
+print "top.left.location = top.left.location;\n";
+print "</script>\n";
+}
+
+1;
+
index 32cfa2f..88a4ccf 100755 (executable)
@@ -43,6 +43,12 @@ if (defined(&$pfn)) {
        &foreign_call($m, "config_post_save", \%config, \%oldconfig);
        }
 
+# Refresh installed modules
+if (&foreign_check("webmin")) {
+       &foreign_require("webmin", "webmin-lib.pl");
+       &webmin::build_installed_modules(0, $m);
+       }
+
 &webmin_log("_config_", undef, undef, \%in, $m);
 &redirect("/$m/");
 
index 8bbfb3e..fb1f9d6 100755 (executable)
@@ -65,44 +65,14 @@ while(1) {
                else {
                        &error_exit("Unknown permissions $perms");
                        }
-
-               # Open passive port
-               $pasv = &ftp_command("PASV", 2, \$err);
-               $pasv || &error_exit("FTP port failed : $err");
-               $pasv =~ /\(([0-9,]+)\)/;
-               @n = split(/,/ , $1);
-               &open_socket("$n[0].$n[1].$n[2].$n[3]", $n[4]*256 + $n[5],
-                            "CON", \$err) ||
-                       &error_exit("FTP port failed : $err");
-
-               if ($mode == 0) {
-                       # Read from file
-                       &ftp_command("RETR $file", 1, \$err) ||
-                               &error_exit("FTP read failed : $err");
-                       $opened = 1;
-                       }
-               elsif ($mode == 1) {
-                       # Create new file if requested by the client, or if
-                       # the touch command was specified by the caller
-                       &ftp_command("STOR $file", 1, \$err) ||
-                               &error_exit("FTP write failed : $err");
-                       $touched = 0;
-                       $opened = 1;
-                       }
-               elsif ($mode == 2) {
-                       # Otherwise append to the file
-                       &ftp_command("APPE $file", 1, \$err) ||
-                               &error_exit("FTP write failed : $err");
-                       $opened = 1;
-                       }
-               else {
-                       $opened = 0;
-                       }
                print "A0\n";
                }
        elsif ($line =~ /^W(\d+)/) {
                # Write to FTP server
-               $opened || &error_exit("FTP connection not opened yet");
+               if ($opened != 1) {
+                       &open_ftp_file($mode);
+                       }
+               #$opened || &error_exit("FTP connection not opened yet");
                $len = $1;
                read(STDIN, $buf, $len);
                $wrote = (print CON $buf);
@@ -110,8 +80,9 @@ while(1) {
                }
        elsif ($line =~ /^R(\d+)/) {
                # Read from to FTP server
-               # XXX doesn't work yet?
-               $opened || &error_exit("FTP connection not opened yet");
+               if ($opened != 2) {
+                       &open_ftp_file(0);
+                       }
                $len = $1;
                $read = read(CON, $buf, $len);
                if ($read >= 0) {
@@ -167,4 +138,41 @@ $rv =~ s/<p>/\n\n/g;
 return $rv;
 }
 
+sub open_ftp_file
+{
+local ($mode) = @_;
+
+# Open passive port
+local $pasv = &ftp_command("PASV", 2, \$err);
+$pasv || &error_exit("FTP port failed : $err");
+$pasv =~ /\(([0-9,]+)\)/;
+local @n = split(/,/ , $1);
+&open_socket("$n[0].$n[1].$n[2].$n[3]", $n[4]*256 + $n[5],
+            "CON", \$err) ||
+       &error_exit("FTP port failed : $err");
+
+if ($mode == 0) {
+       # Read from file
+       &ftp_command("RETR $file", 1, \$err) ||
+               &error_exit("FTP read failed : $err");
+       $opened = 2;
+       }
+elsif ($mode == 1) {
+       # Create new file if requested by the client, or if
+       # the touch command was specified by the caller
+       &ftp_command("STOR $file", 1, \$err) ||
+               &error_exit("FTP write failed : $err");
+       $touched = 0;
+       $opened = 1;
+       }
+elsif ($mode == 2) {
+       # Otherwise append to the file
+       &ftp_command("APPE $file", 1, \$err) ||
+               &error_exit("FTP write failed : $err");
+       $opened = 1;
+       }
+else {
+       $opened = 0;
+       }
+}
 
index 6137baa..0ee2122 100644 (file)
@@ -100,6 +100,7 @@ dump_emulti2=Multi-file backups cannot be done to a remote server
 dump_ermt=Missing or invalid path to <tt>rmt</tt> program
 dump_reverify=Attempt test restore after backup to verify?
 dump_remount=Remount with <tt>noatime</tt> option during backup?
+dump_eftpupdate=Adding files to an existing archive is not possible when using FTP.
 
 edit_err=Failed to create backup
 edit_edir=Missing backup directory
index 2778e04..b140e53 100644 (file)
@@ -234,6 +234,10 @@ if ($_[0]->{'fs'} eq 'tar') {
        $_[0]->{'multi'} = $in{'multi'};
        $_[0]->{'links'} = $in{'links'};
        $_[0]->{'xdev'} = $in{'xdev'};
+       if ($in{'update'} && $in{'rsh_def'} == 3) {
+               # Cannot append via FTP
+               &error($text{'dump_eftpupdate'});
+               }
        $_[0]->{'update'} = $in{'update'};
        if ($in{'gzip'} && $in{'update'}) {
                &error($text{'dump_egzip3'});
diff --git a/lang/en b/lang/en
index 7bd93ba..1d199bb 100644 (file)
--- a/lang/en
+++ b/lang/en
@@ -9,6 +9,8 @@ main_none=You do not have access to any Webmin modules.
 main_skill=Skill level
 main_readonly=(Read-only mode)
 main_return=Return to $1
+main_unused=Un-used Modules
+main_refreshmods=Refesh Modules
 
 link_essl=The Net::SSLeay Perl module needed to make HTTPS connections is not installed on your system.
 
index 251a508..2c9cae7 100755 (executable)
@@ -411,6 +411,7 @@ print "Wrote source deb/${product}_$ver.dsc\n";
 if (!$webmail) {
        # Add to our repository
        chdir("/usr/local/webadmin/deb/repository");
+       system("reprepro -Vb . remove sarge $product");
        system("reprepro -Vb . includedeb sarge ../${product}_${ver}_all.deb");
        }
 
index 9a6992e..8003fb5 100755 (executable)
@@ -37,7 +37,8 @@ $zipdir = "zips";
          "config-lib.pl", "entities_map.txt", "ui-lib.pl",
          "password_form.cgi", "password_change.cgi", "pam_login.cgi",
          "module_chooser.cgi", "config-windows", "xmlrpc.cgi",
-         "uptracker.cgi", "create-module.pl", "webmin_search.cgi" );
+         "uptracker.cgi", "create-module.pl", "webmin_search.cgi",
+        );
 if ($min) {
        # Only those required by others
        @mlist = ("cron", "init", "inittab", "proc", "webmin", "acl", "servers",
@@ -151,7 +152,7 @@ if (!$min && -d $zipdir) {
        system("rm -rf $zipdir/webmin");
        system("mkdir $zipdir/webmin");
        system("cp -rp $tardir/$dir/* $zipdir/webmin");
-       system("rm -rf $zipdir/webmin/{fdisk,exports,bsdexports,hpuxexports,sgiexports,zones,rbac}");
+       system("rm -rf $zipdir/webmin/{fdisk,exports,bsdexports,hpuxexports,sgiexports,zones,rbac,Webmin}");
        system("rm -rf $zipdir/webmin/acl/Authen-SolarisRBAC-0.1/*");
        system("rm -f $zipdir/webmin/software/msi-lib.pl");
        system("echo zip >$zipdir/webmin/install-type");
index 6cd367d..f4f51ba 100755 (executable)
@@ -83,6 +83,16 @@ elsif ($in{'source'} == 3) {
        &webmin_log($config{'update_system'}, "install", undef,
                    { 'packages' => \@packs } ) if (@packs);
 
+       if ($in{'caller'} && &foreign_check("webmin")) {
+               # Software installed - refresh installed flag cache
+               &foreign_require("webmin", "webmin-lib.pl");
+               ($inst, $changed) =
+                       &webmin::build_installed_modules(0, $in{'caller'});
+               if (@$changed && defined(&theme_post_change_modules)) {
+                       &theme_post_change_modules();
+                       }
+               }
+
        if ($in{'return'}) {
                &ui_print_footer($in{'return'}, $in{'returndesc'});
                }
index 5790446..7ee2aca 100644 (file)
@@ -177,7 +177,9 @@ return undef if (!defined(&update_system_resolve));
 return undef if (!&foreign_check($module_name));
 local $pkg = &update_system_resolve($name);
 return undef if (!$pkg);
-return &text('missing_link', $desc, "../$module_name/install_pack.cgi?source=3&update=".&urlize($pkg)."&return=".&urlize($return)."&returndesc=".&urlize($returndesc), $text{$update_system."_name"});
+local ($cpkg) = caller();
+local $caller = eval '$'.$cpkg.'::module_name';
+return &text('missing_link', $desc, "../$module_name/install_pack.cgi?source=3&update=".&urlize($pkg)."&return=".&urlize($return)."&returndesc=".&urlize($returndesc)."&caller=".&urlize($caller), $text{$update_system."_name"});
 }
 
 # update_system_button(field-name, label)
index 8e44f15..065ba2b 100644 (file)
--- a/ui-lib.pl
+++ b/ui-lib.pl
@@ -181,7 +181,7 @@ sub ui_form_start
 return &theme_ui_form_start(@_) if (defined(&theme_ui_form_start));
 local ($script, $method, $target, $tags) = @_;
 local $rv;
-$rv .= "<form class='ui_form' action='$script' ".
+$rv .= "<form class='ui_form' action='".&html_escape($script)."' ".
        ($method eq "post" ? "method=post" :
         $method eq "form-data" ?
                "method=post enctype=multipart/form-data" :
@@ -1128,10 +1128,10 @@ if ($i%$cols) {
        $rv .= "</tr>\n";
        }
 $rv .= "</table>\n";
-if ($title) {
+if (defined($title)) {
        $rv = "<table class=ui_table border ".
              ($width ? " width=$width%" : "").">\n".
-             "<tr $tb> <td><b>$title</b></td> </tr>\n".
+             ($title ? "<tr $tb> <td><b>$title</b></td> </tr>\n" : "").
               "<tr $cb> <td>$rv</td> </tr>\n".
              "</table>";
        }
diff --git a/version b/version
index 0f1a1dd..324ed20 100644 (file)
--- a/version
+++ b/version
@@ -1 +1 @@
-1.400
+1.403
index d2043d6..a4b0518 100755 (executable)
@@ -3037,6 +3037,14 @@ foreach $m (@rv) {
                $m->{'desc'} = $gaccess{"desc_".$m->{'dir'}};
                }
        }
+
+# Apply installed flags
+local %installed;
+&read_file_cached("$config_directory/installed.cache", \%installed);
+foreach $m (@rv) {
+       $m->{'installed'} = $installed{$m->{'dir'}};
+       }
+
 return @rv;
 }
 
index 339866e..16d0bd6 100644 (file)
@@ -802,4 +802,7 @@ blocked_clear=Clear All Blocks
 blocked_cleardesc=Click this button to clear all current host and user blocks, by restarting the Webmin server process.
 blocked_restarting=The Webmin server process is now restarting to clear blocked hosts and users - please wait for a few seconds before continuing.
 
+refreshmods_title=Refresh Modules
+refreshmods_installed=Checking for usable Webmin modules ..
+refeshmods_counts=.. found $2 with installed applications, $1 not installed.
 
diff --git a/webmin/postinstall.pl b/webmin/postinstall.pl
new file mode 100644 (file)
index 0000000..20c9f02
--- /dev/null
@@ -0,0 +1,9 @@
+
+require 'webmin-lib.pl';
+
+# Update cache of which module's underlying servers are installed 
+sub module_install
+{
+&build_installed_modules();
+}
+
index 6a9e11d..e4ab949 100644 (file)
@@ -1351,4 +1351,35 @@ else {
 return undef;
 }
 
+# build_installed_modules(force-all, force-mod)
+# Calls each module's install_check function, and updates the cache of
+# modules whose underlying servers are installed.
+sub build_installed_modules
+{
+local ($force, $mod) = @_;
+local %installed;
+local $changed;
+&read_file_cached("$config_directory/installed.cache", \%installed);
+local @changed;
+foreach my $minfo (&get_all_module_infos()) {
+       next if ($mod && $minfo->{'dir'} ne $mod);
+       next if (defined($installed{$minfo->{'dir'}}) && !$force && !$mod);
+       next if (!&check_os_support($minfo));
+       $@ = undef;
+       local $o = $installed{$minfo->{'dir'}};
+       eval {
+               local $main::error_must_die = 1;
+               $installed{$minfo->{'dir'}} =
+                       &foreign_installed($minfo->{'dir'}, 0) ? 1 : 0;
+               };
+       if ($@) {
+               # Couldn't check .. assume no
+               $installed{$minfo->{'dir'}} = 0;
+               }
+       push(@changed, $minfo->{'dir'}) if ($installed{$minfo->{'dir'}} ne $o);
+       }
+&write_file("$config_directory/installed.cache", \%installed);
+return wantarray ? (\%installed, \@changed) : \%installed;
+}
+
 1;