Compare commits

...

59 Commits

Author SHA1 Message Date
Ilia Ross
f6b62525f8 Add ability to track session state using session database (solution two) 2025-07-02 15:27:54 +03:00
Ilia Ross
57138d505b Add ability to track session state in a separate file (solution one) 2025-07-02 14:45:41 +03:00
Ilia Ross
58580b7f4b Fix to enable log rotation for Webmin logs 2025-07-01 15:10:49 +03:00
Ilia Ross
d9a120c760 Fix to remove non-breakable spaces that don't belong in values within parentheses 2025-07-01 14:33:27 +03:00
Ilia Ross
fb832eff82 Fix to always enable HSTS 2025-06-30 14:08:54 +03:00
Ilia Ross
75b0a6f7bb Fix sending HSTS over plain HTTP does nothing
* Note: per the spec (RFC 6797), HSTS only takes effect when delivered on an HTTPS response

https://datatracker.ietf.org/doc/html/rfc6797#section-7.2
2025-06-30 13:43:46 +03:00
Ilia Ross
40707d8602 Update changelog 2025-06-29 23:04:51 +03:00
Ilia Ross
ac45266ee4 Add missing referenced variable 2025-06-29 22:28:42 +03:00
Ilia Ross
522aeb5264 Fix to consider ancient systems 2025-06-29 22:28:30 +03:00
Ilia Ross
1d24db1686 Add a warning to the login pages if the connection is not secure 2025-06-29 13:42:02 +03:00
Jamie Cameron
527043b54d Merge pull request #2506 from webmin/dev/fix-support-for-ssleay-1.93+
Fix latest SSLeay support for redirects to SSL work
2025-06-28 18:20:24 -07:00
Ilia Ross
56b62346b4 Fix not to use SSL unless clients wants it explicitly 2025-06-29 01:04:30 +03:00
Ilia Ross
ee39f99d23 Fix not to print unnecessary horizontal line
* Note: we're already inside the container
2025-06-28 15:02:23 +03:00
Ilia Ross
a223243db4 Fix comment for clarity 2025-06-27 04:01:15 +03:00
Ilia Ross
b59bdc4f1a Fix latest SSLeay support for redirects to SSL work 2025-06-27 03:57:06 +03:00
Ilia Ross
d087f9f024 Fix to correctly concatenate if string is empty 2025-06-24 13:33:26 +03:00
Jamie Cameron
1607a59239 Handle case where mime_header_checks is not set
https://forum.virtualmin.com/t/double-header-checks/133851/8
2025-06-23 16:52:26 -07:00
Jamie Cameron
70589cf88a Fix regexp to match actual output
https://github.com/webmin/webmin/issues/2501
2025-06-22 15:58:07 -07:00
Jamie Cameron
c429fbb202 Merge branch 'master' of github.com:webmin/webmin 2025-06-22 14:11:53 -07:00
Jamie Cameron
f24375e13a Deal with DNF5 format
https://github.com/webmin/webmin/issues/2501
2025-06-22 14:11:43 -07:00
Ilia Ross
d428f4d4c1 Fix comment
49ceeebbf8 (commitcomment-160355697)
2025-06-22 01:02:51 +03:00
Ilia Ross
f0e07518c9 Fix setting innodb_file_per_table option as it's always enabled by default 2025-06-21 22:45:17 +03:00
Ilia Ross
29709c3c51 Update changelog for another minor release 2025-06-21 21:05:07 +03:00
Ilia Ross
fb71fbd5ae Fix to show output properly without redirecting prematurely 2025-06-21 20:49:55 +03:00
Ilia Ross
a1f06c5548 Fix text consistency 2025-06-21 20:49:33 +03:00
Jamie Cameron
10e8a420c0 Filter out instances of the same version 2025-06-21 10:39:35 -07:00
Jamie Cameron
8149eef10a Add status monitor for PHP FPM
https://github.com/webmin/webmin/issues/2499
2025-06-20 21:53:14 -07:00
Jamie Cameron
c4b98ef376 Nut UPS is no longer supported 2025-06-19 21:31:41 -07:00
Jamie Cameron
621d5c22bc CFengine is no longer supported 2025-06-19 21:30:34 -07:00
Jamie Cameron
98000bb007 BIND 4 is no longer supported 2025-06-19 21:29:46 -07:00
Jamie Cameron
d90a33bb0c Jabber is no longer supported by Webmin 2025-06-19 21:27:45 -07:00
Jamie Cameron
d795fc7d60 Merge branch 'master' of github.com:webmin/webmin 2025-06-19 21:23:30 -07:00
Jamie Cameron
b397ece0ab Most options have moved away from set-variable
https://github.com/webmin/webmin/issues/2497
2025-06-19 21:21:47 -07:00
Jamie Cameron
0a11f182b0 Merge pull request #2498 from webmin/dev/musthost-redirect
Add ability to redirect to enforced host
2025-06-18 12:32:05 -07:00
Ilia Ross
7c05368e8f Add UI API to mask sensitive text unless specifically hovered 2025-06-18 16:53:55 +03:00
Ilia Ross
49ceeebbf8 Add ability to redirect to enforced host 2025-06-17 20:28:49 +03:00
Jamie Cameron
01867c86e0 new version bump 2025-06-16 21:09:27 -07:00
Ilia Ross
008890dfa1 Update changelog 2025-06-16 20:52:29 +03:00
Ilia Ross
5d846e80b2 Fix to use new API to properly resolve default value
55d03d426a (commitcomment-159889070)
2025-06-15 23:54:37 +03:00
Jamie Cameron
ce6bbe44ff Factor out code to create the site file, and add a function to force a re-gen 2025-06-15 08:24:17 -07:00
Ilia Ross
3bc15788af Fix warnings 2025-06-15 14:52:29 +03:00
Jamie Cameron
faa5dddb0a Merge branch 'master' of github.com:webmin/webmin 2025-06-12 09:57:24 -07:00
Jamie Cameron
55d03d426a Add option for SMTPUTF8 2025-06-12 09:57:16 -07:00
Ilia Ross
da9aa22fa7 Fix not to rely on which, or the scriptlets will fail on EL 10 systems 2025-06-12 19:17:50 +03:00
Ilia Ross
06ce137903 Fix to consider path separator as config init may never be run 2025-06-12 01:57:35 +03:00
Ilia Ross
5462c3bbf8 Fix to use API to check for command 2025-06-12 01:52:48 +03:00
Ilia Ross
bae4af7490 Fix not to depend on the path 2025-06-11 23:53:32 +03:00
Ilia Ross
bfd2bfbc11 Update changelog for 2.402 2025-06-09 00:46:51 +03:00
Ilia Ross
8de7fde8bb Fix license 2025-06-08 21:03:36 +03:00
Ilia Ross
e5e8cde28e Fix support for old RPM module name prefixes 2025-06-08 18:02:12 +03:00
Ilia Ross
09d0b26aea Add module list flag support when building modules 2025-06-06 22:41:05 +03:00
Ilia Ross
87ba4dd181 Add minimal list of modules in a separate file 2025-06-05 23:47:48 +03:00
Ilia Ross
282b28da5e Fix to use new file names for modes 2025-06-05 23:38:46 +03:00
Ilia Ross
d519c4099f Add missing "webmincron" module to the core 2025-06-05 03:23:48 +03:00
Ilia Ross
0be73ac433 Add missing "servers" module to the core 2025-06-05 03:07:17 +03:00
Ilia Ross
b0c029887f Add missing modules for core 2025-06-05 03:02:37 +03:00
Ilia Ross
ce16f80848 Add support for building on given list of modules 2025-06-05 02:56:18 +03:00
Ilia Ross
cc407bc1c3 Fix to sort alphabetically default modules list 2025-06-05 00:28:05 +03:00
Ilia Ross
8e5633d9af Fix provides 2025-06-04 23:01:08 +03:00
41 changed files with 483 additions and 359 deletions

View File

@@ -1,5 +1,17 @@
## Changelog
#### 2.403 (June 30, 2025)
* Add support for the Webmin webserver to work in both HTTP and HTTPS modes at the same time
* Add status monitor for PHP FPM #2499
* Add support for redirecting to the enforced domain when the `musthost_redirect` directive is set
* Add a UI API to mask sensitive text—like displayed passwords, unless hovered over container
* Fix MySQL/MariaDB to remove obsolete `set-variable` options that break modern config files #2497
#### 2.402 (June 16, 2025)
* Update the Authentic theme to the latest version with various fixes and improvements
* Fix support for EL10-based systems
#### 2.401 (June 2, 2025)
* Add forgotten password recovery support for Virtualmin mailbox users
* Add forgotten password recovery support in Usermin

File diff suppressed because one or more lines are too long

View File

@@ -26,82 +26,94 @@ $last_restart_time_flag = $module_var_directory."/restart-flag";
# if the Apache binary changes, when Webmin is upgraded, or once every five
# minutes if automatic rebuilding is enabled.
if ($module_name ne 'htaccess') {
local %oldsite;
local $httpd = &find_httpd();
local @st = stat($httpd);
&read_file($site_file, \%oldsite);
local @sst = stat($site_file);
if ($oldsite{'path'} ne $httpd ||
$oldsite{'size'} != $st[7] ||
$oldsite{'webmin'} != &get_webmin_version() ||
$config{'auto_mods'} && $sst[9] < time()-5*60) {
# Need to build list of supported modules
local ($ver, $mods, $fullver) = &httpd_info($httpd);
if ($ver) {
my @allmods = &available_modules();
local @mods = map { "$_/$ver" }
&configurable_modules(\@allmods);
foreach my $m (@mods) {
if ($m =~ /(\S+)\/(\S+)/) {
$httpd_modules{$1} = $2;
}
}
# Call again now that known modules have been set, as
# sometimes there are dependencies due to LoadModule
# statements in an IfModule block
undef(@get_config_cache);
@allmods = &available_modules();
@mods = map { "$_/$ver" }
&configurable_modules(\@allmods);
local %site = ( 'size' => $st[7],
'path' => $httpd,
'modules' => join(' ', @mods),
'allmodules' => join(' ', @allmods),
'version' => $ver,
'fullversion' => $fullver,
'webmin' => &get_webmin_version() );
&lock_file($site_file);
&write_file($site_file, \%site);
chmod(0644, $site_file);
&unlock_file($site_file);
}
}
}
# Read the site-specific setup file, then require in all the module-specific
# .pl files
if (&read_file($site_file, \%site)) {
local($m, $f, $d);
$httpd_size = $site{'size'};
foreach $m (split(/\s+/, $site{'modules'})) {
if ($m =~ /(\S+)\/(\S+)/) {
$httpd_modules{$1} = $2;
}
}
foreach $m (split(/\s+/, $site{'allmodules'})) {
$all_httpd_modules{$m} = $site{'version'};
}
foreach $m (keys %httpd_modules) {
if (!-r "$module_root_directory/$m.pl") {
delete($httpd_modules{$m});
}
}
foreach $f (split(/\s+/, $site{'htaccess'})) {
if (-r $f) { push(@htaccess_files, $f); }
}
foreach $m (keys %httpd_modules) {
do "$m.pl";
}
foreach $d (split(/\s+/, $site{'defines'})) {
$httpd_defines{$d}++;
}
&create_site_file();
}
&read_site_file();
$apache_docbase = $config{'apache_docbase'} ? $config{'apache_docbase'} :
$httpd_modules{'core'} >= 2.0 ?
"http://httpd.apache.org/docs-2.0/mod/" :
"http://httpd.apache.org/docs/mod/";
# create_site_file()
# If the Apache binary or Webmin version has changed, create the site
# file containing all known Apache modules
sub create_site_file
{
my %oldsite;
my $httpd = &find_httpd();
my @st = stat($httpd);
&read_file($site_file, \%oldsite);
my @sst = stat($site_file);
if ($oldsite{'path'} ne $httpd ||
$oldsite{'size'} != $st[7] ||
$oldsite{'webmin'} != &get_webmin_version() ||
$config{'auto_mods'} && $sst[9] < time()-5*60) {
# Need to build list of supported modules
my ($ver, $mods, $fullver) = &httpd_info($httpd);
if ($ver) {
my @allmods = &available_modules();
my @mods = map { "$_/$ver" }
&configurable_modules(\@allmods);
foreach my $m (@mods) {
if ($m =~ /(\S+)\/(\S+)/) {
$httpd_modules{$1} = $2;
}
}
# Call again now that known modules have been set, as
# sometimes there are dependencies due to LoadModule
# statements in an IfModule block
undef(@get_config_cache);
@allmods = &available_modules();
@mods = map { "$_/$ver" }
&configurable_modules(\@allmods);
my %site = ( 'size' => $st[7],
'path' => $httpd,
'modules' => join(' ', @mods),
'allmodules' => join(' ', @allmods),
'version' => $ver,
'fullversion' => $fullver,
'webmin' => &get_webmin_version() );
&lock_file($site_file);
&write_file($site_file, \%site);
chmod(0644, $site_file);
&unlock_file($site_file);
}
}
}
# read_site_file()
# Read the site-specific setup file, then require in all the module-specific
# .pl files
sub read_site_file
{
if (&read_file($site_file, \%site)) {
foreach my $m (split(/\s+/, $site{'modules'})) {
if ($m =~ /(\S+)\/(\S+)/) {
$httpd_modules{$1} = $2;
}
}
foreach my $m (split(/\s+/, $site{'allmodules'})) {
$all_httpd_modules{$m} = $site{'version'};
}
foreach my $m (keys %httpd_modules) {
if (!-r "$module_root_directory/$m.pl") {
delete($httpd_modules{$m});
}
}
foreach my $f (split(/\s+/, $site{'htaccess'})) {
if (-r $f) { push(@htaccess_files, $f); }
}
foreach my $m (keys %httpd_modules) {
do "$m.pl";
}
foreach my $d (split(/\s+/, $site{'defines'})) {
$httpd_defines{$d}++;
}
}
}
# parse_config_file(handle, lines, file, [recursive])
# Parses lines of text from some config file into a data structure. The
# return value is an array of references, one for each directive in the file.
@@ -2274,5 +2286,15 @@ sub format_config_allowed
return $config{'format_config'};
}
# clear_apache_modules_cache()
# If new Apache modules were enabled, force re-gen of the site file
# that contains the modules cache
sub clear_apache_modules_cache
{
&unlink_file($site_file);
&create_site_file();
&read_site_file();
}
1;

View File

@@ -23,7 +23,7 @@ foreach $m (@mods) {
}
# Force re-detection of modules
unlink($site_file);
&clear_apache_modules_cache();
# Force restart Apache
if ($changed && &is_apache_running()) {

View File

@@ -64,7 +64,7 @@ sub run
};
root($o->{'config'}, \&$conf_check);
my $service = ($o->{'config'} =~ /usermin/ ? 'usermin' : 'webmin');
my $systemctlcmd = `which systemctl`;
my $systemctlcmd = &has_command('systemctl');
$systemctlcmd =~ s/\s+$//;
if ($o->{'cmd'} =~ /^(start|stop|restart|reload)$/) {
my $rs = system("$o->{'config'}/$o->{'cmd'} $service");

View File

@@ -95,8 +95,10 @@ sub main {
undef, 1, undef, undef, 5);
if ($latest_known_versions_remote &&
!$latest_known_versions_remote_error) {
%versions_remote = map{split /=/, $_}
(split(/\n/, $latest_known_versions_remote));
%versions_remote = map {
my ($k, $v) = split(/=/, $_, 2);
defined($v) ? ($k => $v) : ();
} split(/\n/, $latest_known_versions_remote);
} elsif ($latest_known_versions_remote_error) {
say BRIGHT_YELLOW, "Warning: ", RESET, "Cannot fetch remote packages versions list - $latest_known_versions_remote_error";
}

View File

@@ -818,3 +818,8 @@ body > .mode > b[data-mode="server-manager"] > a > .ff-cloudmin {
[data-pro-disabled$="-elem"] a:hover {
filter: grayscale(1) contrast(1);
}
.not-secure {
color: #f00a38;
float: right;
cursor: help;
}

View File

@@ -189,6 +189,9 @@ pam_mesg2=You must respond to the question below to login.
pam_login=Continue
pam_restart=Restart
login_notsecure=Not Secure
login_notsecure_desc=This connection is not secure and could let a man-in-the-middle attack intercept your password or session cookie. Use HTTPS unless you are on a trusted local network or behind a secure reverse proxy.
acl_root=Root directory for file chooser
acl_otherdirs=Other visible directories in file chooser
acl_nodot=Hide dot files in file chooser?

View File

@@ -1,34 +1,28 @@
#!/usr/local/bin/perl
# Builds a tar.gz package of a specified Webmin version
if ($0 =~ /^(.*)\//) {
chdir($1);
}
@ARGV == 1 || @ARGV == 2 || @ARGV == 3 || usage();
if ($ARGV[0] eq "-minimal" || $ARGV[0] eq "--minimal") {
$min++;
shift(@ARGV);
}
if ($ARGV[0] =~ /^--exclude-modules/) {
$exclude_modules = $ARGV[0];
shift(@ARGV);
}
if ($ARGV[0] =~ /^--product-type/) {
$product_type = $ARGV[0];
$product_type =~ s/--product-type=//;
if ($product_type =~ /^(minimal|essential)$/) {
$product_suff = "-$product_type";
$product_pref = "$product_type-";
# Parse command line options
$mod_list = 'full';
@ARGV = map { /^--\S+\s+/ ? split(/\s+/, $_) : $_ } @ARGV;
while (@ARGV && $ARGV[0] =~ /^--?/) {
my $opt = shift(@ARGV);
if ($opt eq '--minimal' || $opt eq '-minimal') {
$min = 1;
next;
}
shift(@ARGV);
if ($opt eq '--mod-list') {
$mod_list = shift(@ARGV) // usage();
next;
}
usage();
}
@ARGV == 1 || usage();
$fullvers = $ARGV[0];
$fullvers =~ /^([0-9\.]+)(\-(\d+))?$/ || usage();
$vers = $1;
$release = $3;
$tardir = $min ? "minimal" : "tarballs";
$vfile = $product_pref ? "$product_pref$fullvers" : $min ? "$fullvers-minimal" : $fullvers;
$zipdir = "zips";
$fullvers =~ /^([0-9\.]+)(?:-(\d+))?$/ || usage();
($vers, $release) = ($1, $2);
$tardir = $min ? 'minimal' : 'tarballs';
$vfile = $min ? "$fullvers-minimal" : $fullvers;
$zipdir = 'zips';
$vers || usage();
@files = ("config.cgi", "config-*-linux",
@@ -70,20 +64,15 @@ if ($min) {
}
else {
# All the modules
my $mod_def_list;
my $mods_list;
my $curr_dir = $0;
($curr_dir) = $curr_dir =~ /^(.+)\/[^\/]+$/;
$curr_dir = "." if ($curr_dir !~ /^\//);
open(my $fh, '<', "$curr_dir/mod_def_list.txt") || die "Error opening \"mod_def_list.txt\" : $!\n";
$mod_def_list = do { local $/; <$fh> };
open(my $fh, '<', "$curr_dir/mod_${mod_list}_list.txt") ||
die "Error opening \"mod_${mod_list}_list.txt\" : $!\n";
$mods_list = do { local $/; <$fh> };
close($fh);
@mlist = split(/\s+/, $mod_def_list);
if ($exclude_modules) {
$exclude_modules =~ s/--exclude-modules=//;
my @mlist_excluded =
grep { my $f = $_; ! grep $_ eq $f, split(',', $exclude_modules) } @mlist;
@mlist = @mlist_excluded;
}
@mlist = split(/\s+/, $mods_list);
}
# Build EOL data
@@ -296,6 +285,6 @@ close(ARFILE);
sub usage
{
die "usage: makedist.pl [-minimal] [--exclude-modules] <version>";
die "Usage: $0 [--minimal] [--mod-list type] <version>\n";
}

View File

@@ -29,6 +29,8 @@ my ($force_theme, $url, $upstream, $debdepends, $debrecommends,
$no_prefix, $force_usermin, $release, $allow_overwrite, $final_mod,
$dsc_file, $dir, $ver, @exclude);
my $mod_list = 'full';
while(@ARGV) {
my $a = shift(@ARGV);
if ($a eq "--deb-depends") {
@@ -79,6 +81,9 @@ while(@ARGV) {
elsif ($a eq "--exclude") {
push(@exclude, shift(@ARGV));
}
elsif ($a eq "--mod-list") {
$mod_list = shift(@ARGV);
}
elsif ($a =~ /^\-\-/) {
print STDERR "Unknown option $a\n";
exit(1);
@@ -113,6 +118,7 @@ if (!$dir) {
print " [--dsc-file file.dsc]\n";
print " [--force-theme]\n";
print " [--exclude file-or-dir]\n";
print " [--mod-list full|core|minimal]\n";
print RESET, "\n";
exit(1);
}
@@ -246,7 +252,7 @@ if ($debdepends && exists($minfo{'depends'})) {
my $curr_dir = $0;
($curr_dir) = $curr_dir =~ /^(.+)\/[^\/]+$/;
$curr_dir = "." if ($curr_dir !~ /^\//);
my $mod_def_file = "$curr_dir/mod_def_list.txt";
my $mod_def_file = "$curr_dir/mod_${mod_list}_list.txt";
next if (! -r $mod_def_file);
open(my $fh, '<', $mod_def_file) ||
die "Error opening \"$mod_def_file\" : $!\n";
@@ -279,7 +285,7 @@ if (exists($minfo{'deb_requires'})) {
foreach my $debrequire (split(/\s+/, $minfo{'deb_requires'})) {
push(@rrequires, $debrequire);
}
$rdeps .= ", " . join(", ", @rrequires) if (@rrequires);
$rdeps .= ($rdeps ? ', ' : '') . join(", ", @rrequires) if (@rrequires);
}
# Build (append) list of recommended packages (not Webmin modules)
@@ -288,7 +294,8 @@ if (exists($minfo{'deb_recommends'})) {
foreach my $debrecommend (split(/\s+/, $minfo{'deb_recommends'})) {
push(@rrecommends, $debrecommend);
}
$rrecom .= ", " . join(", ", @rrecommends) if (@rrecommends);
$rrecom .= ($rrecom ? ', ' : '') . join(", ", @rrecommends)
if (@rrecommends);
}
# Build (standalone) list of suggested packages (not Webmin modules)

View File

@@ -32,10 +32,12 @@ my $release = 1;
$ENV{'PATH'} = "/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin";
my $allow_overwrite = 0;
my ($force_theme, $rpmdepends, $rpmrecommends, $no_prefix, $set_prefix, $vendor,
$url, $force_usermin, $final_mod, $sign, $keyname,
my ($force_theme, $rpmdepends, $rpmrecommends, $no_prefix, $set_prefix,
$obsolete_wbm, $vendor, $url, $force_usermin, $final_mod, $sign, $keyname,
$epoch, $dir, $ver, @exclude);
my $mod_list = 'full';
# Parse command-line args
while(@ARGV) {
# XXX Untainting isn't needed when running as non-root?
@@ -52,6 +54,12 @@ while(@ARGV) {
elsif ($a eq "--no-prefix") {
$no_prefix = 1;
}
elsif ($a eq "--prefix") {
$set_prefix = &untaint(shift(@ARGV));
}
elsif ($a eq "--obsolete-wbm") {
$obsolete_wbm = 1;
}
elsif ($a eq "--licence" || $a eq "--license") {
$licence = &untaint(shift(@ARGV));
}
@@ -79,9 +87,6 @@ while(@ARGV) {
elsif ($a eq "--rpm-dir") {
$basedir = &untaint(shift(@ARGV));
}
elsif ($a eq "--prefix") {
$set_prefix = &untaint(shift(@ARGV));
}
elsif ($a eq "--vendor") {
$vendor = &untaint(shift(@ARGV));
}
@@ -97,6 +102,9 @@ while(@ARGV) {
elsif ($a eq "--exclude") {
push(@exclude, shift(@ARGV));
}
elsif ($a eq "--mod-list") {
$mod_list = shift(@ARGV);
}
elsif ($a =~ /^\-\-/) {
print STDERR "Unknown option $a\n";
exit(1);
@@ -121,6 +129,7 @@ if (!$dir) {
print " [--rpm-dir directory]\n";
print " [--no-prefix]\n";
print " [--prefix prefix]\n";
print " [--no-wbm-prefix]\n";
print " [--vendor name]\n";
print " [--licence name]\n";
print " [--url url]\n";
@@ -134,6 +143,7 @@ if (!$dir) {
print " [--sign]\n";
print " [--key keyname]\n";
print " [--exclude file]\n";
print " [--mod-list full|core|minimal]\n";
print RESET, "\n";
exit(1);
}
@@ -164,7 +174,8 @@ if (!-d $spec_dir || !-d $rpm_source_dir || !-d $rpm_dir) {
# Is this actually a module or theme directory?
-d $source_dir || die "$dir is not a directory";
my ($depends, $prefix, $desc, $prog, $iver, $istheme, $post_config);
my ($depends, $prefix, $prefix_auto, $desc, $prog, $iver,
$istheme, $post_config);
if ($minfo{'desc'}) {
$depends = join(" ", map { s/\/[0-9\.]+//; $_ }
grep { !/^[0-9\.]+$/ }
@@ -200,6 +211,7 @@ elsif ($tinfo{'desc'}) {
else {
die "$source_dir does not appear to be a webmin module or theme";
}
$prefix_auto = $prefix;
$prefix = "" if ($no_prefix);
$prefix = $set_prefix if ($set_prefix);
my $ucprog = ucfirst($prog);
@@ -267,7 +279,7 @@ if ($rpmdepends && defined($minfo{'depends'})) {
my $curr_dir = $0;
($curr_dir) = $curr_dir =~ /^(.+)\/[^\/]+$/;
$curr_dir = "." if ($curr_dir !~ /^\//);
my $mod_def_file = "$curr_dir/mod_def_list.txt";
my $mod_def_file = "$curr_dir/mod_${mod_list}_list.txt";
next if (! -r $mod_def_file);
open(my $fh, '<', $mod_def_file) ||
die "Error opening \"$mod_def_file\" : $!\n";
@@ -300,7 +312,7 @@ if (exists($minfo{'rpm_requires'})) {
foreach my $rpmrequire (split(/\s+/, $minfo{'rpm_requires'})) {
push(@rrequires, $rpmrequire);
}
$rdeps .= " " . join(" ", @rrequires) if (@rrequires);
$rdeps .= ($rdeps ? ' ' : '') . join(" ", @rrequires) if (@rrequires);
}
# Build (append) list of recommended packages (not Webmin modules)
@@ -309,7 +321,8 @@ if (exists($minfo{'rpm_recommends'})) {
foreach my $rpmrecommend (split(/\s+/, $minfo{'rpm_recommends'})) {
push(@rrecommends, $rpmrecommend);
}
$rrecom .= " " . join(" ", @rrecommends) if (@rrecommends);
$rrecom .= ($rrecom ? ' ' : '') . join(" ", @rrecommends)
if (@rrecommends);
}
# Build (standalone) list of suggested packages (not Webmin modules)
@@ -344,6 +357,12 @@ if (exists($minfo{'rpm_obsoletes'})) {
}
}
# Fix support for old module name prefixes
if ($obsolete_wbm) {
push(@rprovides, "$prefix_auto$mod");
push(@robsoletes, "$prefix_auto$mod");
}
# Create the SPEC file
my $vendorheader = $vendor ? "Vendor: $vendor" : "";
my $urlheader = $url ? "URL: $url" : "";
@@ -360,7 +379,7 @@ Summary: $desc
Name: $prefix$mod
Version: $ver
Release: $release
Requires: /bin/sh /usr/bin/perl /usr/libexec/$prog $rdeps
Requires: /bin/sh /usr/bin/perl $prog $rdeps
EOF
print $SPEC "Recommends: $rrecom\n" if ($rrecom);
print $SPEC "Suggests: " . join(" ", @rsuggests) . "\n" if (@rsuggests);

View File

@@ -90,7 +90,7 @@ Requires(pre): /usr/bin/perl
Requires: /bin/sh /usr/bin/perl perl(lib) perl(open) perl(Net::SSLeay) perl(Time::Local) perl(Data::Dumper) perl(File::Path) perl(File::Basename) perl(Digest::SHA) perl(Digest::MD5) openssl unzip tar gzip
Recommends: perl(DateTime) perl(DateTime::TimeZone) perl(DateTime::Locale) perl(Time::Piece) perl(Encode::Detect) perl(Time::HiRes) perl(Socket6) html2text shared-mime-info perl-File-Basename perl-File-Path perl-JSON-XS qrencode perl(DBI) perl(DBD::mysql)
AutoReq: 0
License: BSD-3-clause
License: BSD-3-Clause
Group: System/Tools
Source: http://www.webmin.com/download/$tarfile
Vendor: $rpm_maintainer

View File

@@ -610,6 +610,53 @@ if ($config{'logclear'}) {
push(@childpids, $logclearer);
}
# session_state(session-id, set-state)
# Sets or gets the active state of the client, which is used to determine
# whether the client is away or not. This is used to allow for the session to
# expire after a period of inactivity in case a client has opened connections or
# makes HTTP requests in the background. Returns 1 if the client is currently
# not away (ie. active), or 0 if it is away.
sub session_state
{
my ($sid, $set) = @_;
return 1 if (!$sid);
# Check session database
my %sessiondb;
dbmopen(%sessiondb, $config{'sessiondb'}, 0700);
if ($@) {
dbmclose(%sessiondb);
eval "use NDBM_File";
dbmopen(%sessiondb, $config{'sessiondb'}, 0700);
}
# Get current record
my $skey = &hash_session_id($sid);
my ($user, $ltime, $ip, $lifetime, $active);
if (exists($sessiondb{$skey})) {
($user, $ltime, $ip, $lifetime, $active) =
split(/\s+/, $sessiondb{$skey});
$lifetime //= 0; # preserve or default to 0
$active //= 1; # default to 'alive'
}
# Update flag if caller supplied a value
if ($user && $ltime && $ip && defined($set)) {
$active = $set ? 1 : 0;
$sessiondb{$skey} = join(' ', $user, $ltime, $ip, $lifetime, $active);
print DEBUG "websocket updated status for $sid to $active\n";
}
else {
print DEBUG "websocket current status for $sid is $active\n";
}
# Save the record back to the database
dbmclose(%sessiondb);
# Return the active state
return $active;
}
# Setup the logout time dbm if needed
if ($config{'session'}) {
eval "use SDBM_File";
@@ -918,11 +965,27 @@ while(1) {
# Initialize SSL for this connection
if ($use_ssl) {
($ssl_con, $ssl_certfile,
$ssl_keyfile) = &ssl_connection_for_ip(
SOCK, $ipv6fhs{$s});
print DEBUG "ssl_con returned $ssl_con\n";
$ssl_con || exit;
my $byte = '';
# Look at the first byte of the socket
# buffer but don't consume it
recv(SOCK, $byte, 1, MSG_PEEK);
if (length($byte) &&
# Check if the first byte is a TLS
(ord($byte) == 0x16 ||
# Check if the first byte is SSL
(ord($byte) & 0x80))) {
($ssl_con,
$ssl_certfile,
$ssl_keyfile) =
&ssl_connection_for_ip(
SOCK, $ipv6fhs{$s});
print DEBUG "ssl_con returned ".
"$ssl_con\n";
$ssl_con || exit;
}
else {
$use_ssl = 0;
}
}
print DEBUG
@@ -1101,8 +1164,10 @@ while(1) {
print $outfd "0 0\n";
}
else {
local ($user, $ltime, $ip, $lifetime) =
local ($user, $ltime, $ip, $lifetime, $state) =
split(/\s+/, $sessiondb{$skey});
$lifetime //= 0;
$state //= 1;
local $lot = &get_logout_time($user, $session_id);
if ($lot &&
$time_now - $ltime > $lot*60 &&
@@ -1131,7 +1196,7 @@ while(1) {
# Session is OK, update last time
# and remote IP
print $outfd "2 $user\n";
$sessiondb{$skey} = "$user $time_now $vip";
$sessiondb{$skey} = "$user $time_now $vip $lifetime $state";
}
}
}
@@ -1520,7 +1585,8 @@ if (defined($header{'host'})) {
else {
$host = $header{'host'};
}
if ($config{'musthost'} && $host ne $config{'musthost'}) {
if ($config{'musthost'} && $host ne $config{'musthost'} &&
!$config{'musthost_redirect'}) {
# Disallowed hostname used
&http_error(400, "Invalid HTTP hostname");
}
@@ -1543,6 +1609,22 @@ if ($config{'redirect_prefix'}) {
}
$prot = $ssl ? "https" : "http";
# Redirect to the configured "musthost", if "musthost_redirect" is set, rather
# than showing an error
if ($config{'musthost'} && $host ne $config{'musthost'} &&
$config{'musthost_redirect'}) {
&write_data("HTTP/1.0 302 Moved Temporarily\r\n");
&write_data("Date: $datestr\r\n");
&write_data("Server: @{[&server_info()]}\r\n");
&write_data("Location: $prot://$config{'musthost'}:$redirport\r\n");
&write_keep_alive(0);
&write_data("\r\n");
&log_request($loghost, $authuser, $reqline, 302, 0) if $reqline;
shutdown(SOCK, 1);
close(SOCK);
return;
}
undef(%in);
if ($page =~ /^([^\?]+)\?(.*)$/) {
# There is some query string information
@@ -5899,7 +5981,8 @@ while(1) {
syswrite($fh, $buf, length($buf)) || last;
}
my $now = time();
if ($now - $last_session_check_time > 10) {
if ($now - $last_session_check_time > 10 &&
&session_state($session_id) == 1) {
# Re-validate the browser session every 10 seconds
print DEBUG "verifying websockets session $session_id\n";
print $PASSINw "verify $session_id 0 $acptip\n";

1
mod_core_list.txt Normal file
View File

@@ -0,0 +1 @@
acl apache authentic-theme backup-config bind8 change-user cron dovecot fail2ban fdisk filemin firewalld fsdump gray-theme htaccess-htpasswd init logrotate logviewer lvm mailboxes mailcap mount mysql net package-updates passwd phpini postfix proc procmail proftpd quota servers software spam sshd status system-status time updown useradmin usermin webmin webmincron webminlog xterm

View File

@@ -1 +0,0 @@
cron dfsadmin exports inetd init mount samba useradmin fdisk format proc webmin quota software pap acl apache lpadmin bind8 sendmail squid bsdexports hpuxexports net dhcpd custom servers time syslog mysql man inittab raid postfix webminlog postgresql xinetd status cpan pam nis shell fetchmail passwd at proftpd sshd heartbeat cluster-software cluster-useradmin qmailadmin stunnel usermin fsdump lvm procmail cluster-webmin firewall sgiexports openslp webalizer shorewall adsl-client updown ppp-client pptp-server pptp-client ipsec ldap-useradmin change-user cluster-shell cluster-cron spam htaccess-htpasswd logrotate cluster-passwd mailboxes ipfw sarg bandwidth cluster-copy backup-config smart-status idmapd krb5 smf ipfilter rbac tunnel zones cluster-usermin dovecot syslog-ng mailcap ldap-client phpini filter bacula-backup ldap-server exim tcpwrappers package-updates system-status webmincron shorewall6 iscsi-server iscsi-client gray-theme iscsi-target iscsi-tgtd bsdfdisk fail2ban authentic-theme firewalld filemin firewall6 logviewer xterm

1
mod_full_list.txt Normal file
View File

@@ -0,0 +1 @@
acl adsl-client apache at authentic-theme backup-config bacula-backup bandwidth bind8 bsdexports bsdfdisk change-user cluster-copy cluster-cron cluster-passwd cluster-shell cluster-software cluster-useradmin cluster-usermin cluster-webmin cpan cron custom dfsadmin dhcpd dovecot exim exports fail2ban fdisk fetchmail filemin filter firewall firewall6 firewalld format fsdump gray-theme heartbeat hpuxexports htaccess-htpasswd idmapd inetd init inittab ipfilter ipfw ipsec iscsi-client iscsi-server iscsi-target iscsi-tgtd krb5 ldap-client ldap-server ldap-useradmin logrotate logviewer lpadmin lvm mailboxes mailcap man mount mysql net nis openslp package-updates pam pap passwd phpini postfix postgresql ppp-client pptp-client pptp-server proc procmail proftpd qmailadmin quota raid rbac samba sarg sendmail servers sgiexports shell shorewall shorewall6 smart-status smf software spam squid sshd status stunnel syslog syslog-ng system-status tcpwrappers time tunnel updown useradmin usermin webalizer webmin webmincron webminlog xinetd xterm zones

1
mod_minimal_list.txt Normal file
View File

@@ -0,0 +1 @@
acl cron init inittab man proc servers system-status webmin webmincron webminlog

View File

@@ -50,9 +50,10 @@ print &ui_table_row($text{'cnf_stor'},
'NDB', 'ARCHIVE', 'CSV',
'BLACKHOLE' ], 1, 0, 1));
my $ifpt_def_off = &get_innodb_file_per_table_default() ? 0 : 1;
$fpt = &find_value("innodb_file_per_table", $mems);
print &ui_table_row($text{'cnf_fpt'},
&ui_yesno_radio("fpt", $fpt));
&ui_yesno_radio("fpt", $fpt // $ifpt_def_off));
$ilt = &find_value("innodb_lock_wait_timeout", $mems);
print &ui_table_row($text{'cnf_ilt'},

View File

@@ -88,20 +88,13 @@ if ($mysql_version =~ /mariadb/i) {
}
&fix_mysql_text(\%text);
if (&compare_version_numbers($mysql_version, "5.5") >= 0) {
@mysql_set_variables = ( "key_buffer_size", "sort_buffer_size",
"net_buffer_length" );
}
else {
@mysql_set_variables = ( "key_buffer", "sort_buffer",
"net_buffer_length" );
}
if (&compare_version_numbers($mysql_version, "5.6") >= 0) {
@mysql_number_variables = ( "table_open_cache", "max_connections" );
}
else {
@mysql_number_variables = ( "table_cache", "max_connections" );
}
@mysql_byte_variables = ( "max_allowed_packet" );
my $mysql8_optout = &compare_version_numbers($mysql_version, "8.0") >= 0 && $mysql_version !~ /maria/i;
if (!$mysql8_optout) {
@@ -115,6 +108,15 @@ else {
push(@mysql_set_variables, "myisam_sort_buffer_size");
}
if (&compare_version_numbers($mysql_version, "5.5") >= 0) {
push(@mysql_byte_variables, "key_buffer_size", "sort_buffer_size",
"net_buffer_length");
}
else {
@mysql_set_variables = ( "key_buffer", "sort_buffer",
"net_buffer_length" );
}
# make_authstr([login], [pass], [host], [port], [sock], [unix-user], [ssl])
# Returns a string to pass to MySQL commands to login to the database
sub make_authstr
@@ -1766,6 +1768,18 @@ return
$variant eq "mysql" && &compare_version_numbers($ver, "8.0") >= 0;
}
# get_innodb_file_per_table_default()
# Returns 1 if the InnoDB file-per-table option is disabled by default
sub get_innodb_file_per_table_default
{
my ($ver, $variant) = &get_remote_mysql_variant();
return
($variant eq 'mariadb' && &compare_version_numbers($ver, '10.1.0') < 0) ||
($variant eq 'mysql' && &compare_version_numbers($ver, '5.6.6') < 0)
? 1
: 0;
}
# get_plugin_sql(version, variant, plainpass, plugin)
# Get the right query for setting user password with plugin
sub get_plugin_sql

View File

@@ -18,7 +18,7 @@ else {
$mysql_login ? "<tt>$mysql_login</tt>"
: "<label>$text{'root_auto'}</label>");
print &ui_table_row($text{'root_pass'},
$mysql_pass ? "<tt>$mysql_pass</tt>"
$mysql_pass ? "<tt>".&ui_text_mask($mysql_pass)."</tt>"
: &ui_text_color($text{'root_none'}, 'danger'));
print &ui_table_row($text{'root_newpass1'},
&ui_password("newpass1", undef, 20));

View File

@@ -13,6 +13,7 @@ foreach my $l (&get_all_mysqld_files()) {
$conf = &get_mysql_config();
($mysqld) = grep { $_->{'name'} eq 'mysqld' } @$conf;
$mysqld || &error($text{'cnf_emysqld'});
$mems = $mysqld->{'members'};
# Parse mysql server inputs
if ($in{'port_def'}) {
@@ -53,11 +54,9 @@ else {
&save_directive($conf, $mysqld, "default-storage-engine",
$in{'stor'} ? [ $in{'stor'} ] : [ ]);
$fpt = &find_value("innodb_file_per_table", $mems);
if ($fpt || $in{'fpt'}) {
&save_directive($conf, $mysqld, "innodb_file_per_table",
[ $in{'fpt'} ]);
}
my $ifpt_def_off = &get_innodb_file_per_table_default();
&save_directive($conf, $mysqld, "innodb_file_per_table",
[ $in{'fpt'} ? ($ifpt_def_off ? 1 : undef) : 0 ]);
if ($in{'ilt_def'}) {
&save_directive($conf, $mysqld, "innodb_lock_wait_timeout", [ ]);

View File

@@ -72,7 +72,13 @@ print "$text{'pam_prefix'}\n";
print &ui_form_start("@{[&get_webprefix()]}/pam_login.cgi", "post");
print &ui_hidden("cid", $in{'cid'});
print &ui_table_start($text{'pam_header'},
my $not_secure;
if ($ENV{'HTTPS'} ne 'ON') {
$not_secure = ui_tag('span', "&#9888; $text{'login_notsecure'}",
{ class => 'not-secure', title => $text{'login_notsecure_desc'} });
}
print &ui_table_start($text{'pam_header'} . $not_secure,
"width=40% class='loginform'", 2);
if ($gconfig{'realname'}) {

View File

@@ -27,7 +27,8 @@ print &ui_form_end([ [ undef, $text{'opts_save'} ] ]);
# Header map contents
print &ui_hr();
if (&get_real_value("header_checks") eq "") {
my $hc = &get_real_value("mime_header_checks");
if ($hc eq "") {
print $text{'opts_header_checks_no_map'},"<p>\n";
} else {
&generate_map_edit("header_checks", $text{'map_click'}." ".
@@ -37,8 +38,11 @@ if (&get_real_value("header_checks") eq "") {
# MIME header map contents
print &ui_hr();
if (&get_real_value("mime_header_checks") eq "") {
my $mhc = &get_real_value("mime_header_checks");
if ($mhc eq "") {
print $text{'opts_mime_header_checks_no_map'},"<p>\n";
} elsif ($mhc eq $hc) {
print $text{'opts_mime_header_checks_same_map'},"<p>\n";
} else {
&generate_map_edit("mime_header_checks", $text{'map_click'}." ".
&hlink($text{'help_map_format'}, "header"), 1,

View File

@@ -654,6 +654,7 @@ opts_header_checks=Header checking tables
opts_mime_header_checks=MIME header checking tables
opts_header_checks_no_map=(No header checking map is currently defined. Define a map first, then you can edit it)
opts_mime_header_checks_no_map=(No MIME header checking map is currently defined. Define a map first, then you can edit it)
opts_mime_header_checks_same_map=(MIME header checks are the same as regular header checks. Define a different map first, then you can edit it)
header_name=Regular expression
header_value=Action for matches
header_discard=Discard (with log message..)
@@ -868,6 +869,7 @@ opts_smtpd_tls_key_file=TLS private key file
opts_smtpd_tls_CAfile=TLS certificate authority file
opts_smtpd_use_tls=Enable TLS encryption?
opts_smtp_enforce_tls=Require TLS encryption?
opts_smtputf8_enable=Enable SMTPUTF8 support?
sasl_err=Failed to save SMTP authentication and encryption
sasl_ecert=Missing or invalid TLS certificate file
sasl_ekey=Missing or invalid TLS key file

View File

@@ -436,7 +436,7 @@ sub option_freefield
sub option_yesno
{
my $name = $_[0];
my $v = &get_current_value($name);
my $v = &resolve_current_value($name);
my $key = 'opts_'.$name;
print &ui_table_row(defined($_[1]) ? &hlink($text{$key}, "opt_".$name)

View File

@@ -100,6 +100,11 @@ if (&compare_version_numbers($postfix_version, 3.3) >= 0) {
&option_yesno("smtp_balance_inet_protocols");
}
# SMTPUTF8 support
if (&compare_version_numbers($postfix_version, 3.0) >= 0) {
&option_yesno("smtputf8_enable");
}
print &ui_table_end();
print &ui_form_end([ [ undef, $text{'opts_save'} ] ]);

View File

@@ -91,7 +91,14 @@ print "$text{'session_prefix'}\n";
print &ui_form_start("@{[&get_webprefix()]}/session_login.cgi", "post");
print &ui_hidden("page", $in{'page'});
print &ui_table_start($text{'session_header'},
my $not_secure;
if ($ENV{'HTTPS'} ne 'ON') {
$not_secure = ui_tag('span', "&#9888; $text{'login_notsecure'}",
{ class => 'not-secure', title => $text{'login_notsecure_desc'} });
}
print &ui_table_start($text{'session_header'} . $not_secure,
"width=40% class='loginform'", 2);
# Login message

View File

@@ -662,7 +662,7 @@ if [ ! -f "$config_dir/.pre-install" ]; then
fi
# Test if we have systemd system
systemctlcmd=$(which systemctl 2>/dev/null)
systemctlcmd=$(command -v systemctl 2>/dev/null || :)
if [ -x "$systemctlcmd" ]; then
initsys=$(cat /proc/1/comm 2>/dev/null)
if [ "$initsys" != "systemd" ]; then
@@ -819,15 +819,27 @@ if [ "$upgrading" != 1 ]; then
echo licence_module=$licence_module >>$config_dir/config
fi
# Enable log rotation by default
echo "logclear=1" >> $config_dir/miniserv.conf
echo "logclear=1" >> $config_dir/config
# Enable HSTS by default
echo "ssl_hsts=1" >> $config_dir/miniserv.conf
# Disallow unknown referers by default
echo "referers_none=1" >>$config_dir/config
else
# one-off hack to set log variable in config from miniserv.conf
grep log= $config_dir/config >/dev/null
if [ "$?" = "1" ]; then
grep log= $config_dir/miniserv.conf >> $config_dir/config
grep logtime= $config_dir/miniserv.conf >> $config_dir/config
grep logclear= $config_dir/miniserv.conf >> $config_dir/config
# Enable log rotation if not set
grep logclear= $config_dir/miniserv.conf >/dev/null
if [ "$?" != "0" ]; then
echo "logclear=1" >> $config_dir/miniserv.conf
echo "logclear=1" >> $config_dir/config
fi
# Enable HSTS by default if not set
grep ssl_hsts= $config_dir/miniserv.conf >/dev/null
if [ "$?" != "0" ]; then
echo "ssl_hsts=1" >> $config_dir/miniserv.conf
fi
# Disallow unknown referers if not set

View File

@@ -97,7 +97,6 @@ if ($in{'need_unlink'}) {
"delete_file.cgi?file=".
&urlize($in{'file'})),"<p>\n";
}
print &ui_hr();
&ui_print_footer("", $text{'index_return'});
exit;
}

View File

@@ -119,6 +119,13 @@ while(<CMD>) {
$pkg =~ s/\-\d.*$//; # Strip version number from end
push(@rv, $pkg);
}
elsif (/\]\s+(Upgrading|Installing)\s+(\S+)/) {
# Line like :
# [3/8] Upgrading libcurl-0:8.11.1-5.fc42 100% ...
local $pkg = $2;
$pkg =~ s/:\d.*$//; # Strip version number from end
push(@rv, $pkg);
}
if (!/ETA/ && !/\%\s+done\s+\d+\/\d+\s*$/) {
print &html_escape($_."\n");
}

View File

@@ -1,24 +0,0 @@
# cfengine-monitor.pl
# Monitor the cfengine daemon on this host
# Check the PID file to see if cfd is running
sub get_cfengine_status
{
local %cconfig = &foreign_config($_[1]);
&has_command($cconfig{'cfd'}) || return { 'up' => -1 };
local @pids = &find_byname("cfd");
if (@pids) {
return { 'up' => 1 };
}
else {
return { 'up' => 0 };
}
}
sub parse_cfengine_dialog
{
&depends_check($_[0], "cfengine");
}
1;

View File

@@ -33,7 +33,5 @@ else {
&reset_environment();
&webmin_log("refresh");
print $text{'refresh_done'},"<p>\n";
print &js_redirect("index.cgi");
&ui_print_footer("", $text{'index_return'});
}

View File

@@ -1,28 +0,0 @@
# dnsadmin-monitor.pl
# Monitor the BIND 4 DNS server on this host
# Check the PID file to see if BIND is running
sub get_dnsadmin_status
{
return { 'up' => -1 } if (!&foreign_check($_[1]));
&foreign_require($_[1], "dns-lib.pl");
local %dconfig = &foreign_config($_[1]);
return { 'up' => -1 } if (!-r $dconfig{'named_boot_file'});
if (open(PID, "<".$dconfig{'named_pid_file'}) && <PID> =~ /(\d+)/ && kill(0, $1)) {
close(PID);
local @st = stat($dconfig{'named_pid_file'});
return { 'up' => 1,
'desc' => &text('up_since', scalar(localtime($st[9]))) };
}
else {
return { 'up' => 0 };
}
}
sub parse_dnsadmin_dialog
{
&depends_check($_[0], "dnsadmin");
}
1;

View File

@@ -1,28 +0,0 @@
# jabber-monitor.pl
# Monitor the jabber server on this host
# Check the PID file to see if mon is running
sub get_jabber_status
{
return { 'up' => -1 } if (!&foreign_check($_[1]));
local %jconfig = &foreign_config($_[1]);
-r $jconfig{'jabber_config'} || return { 'up' => -1 };
&foreign_require($_[1], "jabber-lib.pl");
local $pidfile = &foreign_call($_[1], "jabber_pid_file");
if (open(PID, "<".$pidfile) && ($pid = int(<PID>)) && kill(0, $pid)) {
return { 'up' => 1 };
}
else {
return { 'up' => 0 };
}
}
sub parse_jabber_dialog
{
&depends_check($_[0], "jabber");
eval "use XML::Parser";
&error(&text('jabber_eparser', "<tt>XML::Parser</tt>")) if ($@);
}
1;

View File

@@ -25,7 +25,6 @@ type_inetd=Internet and RPC Server
type_xinetd=Extended Internet Server
type_squid=Squid Proxy Server
type_bind8=BIND DNS Server
type_dnsadmin=BIND 4 DNS Server
type_dhcpd=DHCP Server
type_tcp=TCP Connection
type_http=HTTP Request
@@ -51,12 +50,10 @@ type_change=File or Directory Change
type_oldfile=File Not Changed
type_qmailadmin=QMail Server
type_mon=MON Service Monitor
type_jabber=Jabber IM Server
type_usermin=Usermin Webserver
type_portsentry=Portsentry Daemon
type_hostsentry=Hostsentry Daemon
type_webmin=Webmin Webserver
type_cfengine=Configuration Engine Daemon
type_memory=Free Memory
type_proftpd=ProFTPD Server
type_dovecot=Dovecot IMAP/POP3 Server
@@ -66,7 +63,6 @@ type_raid=RAID Device Status
type_iface=Network Interface Status
type_init=Bootup Action
type_sensors=LM Sensor Status
type_nut=NUT UPS Value
type_mailq=Mail Queue Size
type_dns=DNS Lookup
type_query=SQL Query
@@ -78,6 +74,7 @@ type_smtp=SMTP Connection
type_imap=IMAP Connection
type_firewalld=FirewallD Server
type_reboot=Reboot Required
type_phpini=PHP-FPM Server
mon_create=Create Monitor
mon_edit=Edit Monitor
@@ -333,8 +330,6 @@ acl_sched=Can change scheduled monitoring?
change_file=File or directory to monitor (fail if changed)
jabber_eparser=The Perl module $1 is not installed on your system.
memory_min2=Minimum free real memory
memory_emin=Missing or invalid amount of free real memory
memory_eproc=Webmin does not know how to check free memory on your operating system
@@ -374,7 +369,7 @@ init_eaction=No action selected
refresh_title=Refresh Status
refresh_doing=Refreshing the status of all monitors ..
refresh_doing2=Refreshing the status of $1 selected monitors ..
refresh_done=.. done.
refresh_done=.. done
sensors_name=Sensor to check
sensors_value=Failed when
@@ -387,17 +382,6 @@ sensors_cur=$1 (currently $2 $3)
sensors_emin=Missing or invalid minimum value
sensors_emax=Missing or invalid maximum value
nut_ups=NUT UPS to check
nut_name=Attribute to check
nut_value=Failed when
nut_value1=Value is below $1
nut_value2=Value is above $1
nut_cmd=The command <tt>upsc</tt> is not installed on your system. This monitor requires the NUT package be installed and configured to operate.
nut_eups=No USP to check entered
nut_cur=$1 (currently $2)
nut_emin=Missing or invalid minimum value
nut_emax=Missing or invalid maximum value
mailq_system=Mail server
mailq_qmailadmin=Qmail
mailq_postfix=Postfix
@@ -622,4 +606,11 @@ imap_euser=Missing IMAP login
reboot_pkgs=Package updates require a reboot
phpini_file=PHP-FPM version
phpini_nofile=PHP-FPM configuration file not found!
phpini_efile=No PHP-FPM version selected!
phpini_noinit=No bootup action found for PHP-FPM version
phpini_noinit2=Bootup action $1 does not exist!
phpini_downinit=Bootup action $1 is down
__norefs=1

View File

@@ -1,89 +0,0 @@
# Check if some NUT value is too low or high
sub get_nut_status
{
return { 'up' => -1 } if (!&has_command("upsc"));
local @sens = &get_ups_values($_[0]->{'ups'});
local ($sens) = grep { $_->{'name'} eq $_[0]->{'name'} } @sens;
return { 'up' => 1 } if (!$sens);
if ($_[0]->{'mode'} == 1) {
return $sens->{'value'} < $_[0]->{'min'} ? { 'up' => 0 }
: { 'up' => 1 };
}
elsif ($_[0]->{'mode'} == 2) {
return $sens->{'value'} > $_[0]->{'max'} ? { 'up' => 0 }
: { 'up' => 1 };
}
}
sub show_nut_dialog
{
if (!&has_command("upsc")) {
print &ui_table_row(undef, $text{'nut_cmd'}, 4);
}
else {
# UPS name
print &ui_table_row($text{'nut_ups'},
&ui_textbox("ups", $_[0]->{'ups'}, 20));
# Value to check
local @sens = &get_ups_values();
if (@sens) {
print &ui_table_row($text{'nut_name'},
&ui_select("name", $_[0]->{'name'},
[ map { [ $_->{'name'},
&text('nut_cur', $_->{'name'}, $_->{'value'}) ] }
@sens ]));
}
else {
print &ui_table_row($text{'nut_name'},
&ui_textbox("name", $_[0]->{'name'}, 20));
}
# Expected value
print &ui_table_row($text{'nut_value'},
&ui_radio("mode", $_[0]->{'mode'} || 1,
[ [ 1, &text('sensors_value1',
&ui_textbox("min", $_[0]->{'min'}, 8)) ],
[ 2, &text('sensors_value2',
&ui_textbox("max", $_[0]->{'max'}, 8)) ] ]),
3);
}
}
sub parse_nut_dialog
{
&has_command("upsc") || &error($text{'nut_cmd'});
$in{'ups'} =~ /^\S+$/ || &error($text{'nut_eups'});
$_[0]->{'ups'} = $in{'ups'};
$_[0]->{'name'} = $in{'name'};
$_[0]->{'mode'} = $in{'mode'};
$_[0]->{'max'} = $in{'max'};
$_[0]->{'min'} = $in{'min'};
if ($in{'mode'} == 1) {
$in{'min'} =~ /^[0-9\.\+\-]+$/ || &error($text{'nut_emin'});
}
elsif ($in{'mode'} == 2) {
$in{'max'} =~ /^[0-9\.\+\-]+$/ || &error($text{'nut_emax'});
}
}
# get_ups_values(ups)
# Returns a list of NUT attribute names and values for some UPS
sub get_ups_values
{
if (!scalar(@get_ups_cache)) {
local @rv;
open(SENS, "upsc ".quotemeta($_[0])." 2>/dev/null |");
while(<SENS>) {
if (/^(\S+):\s+(.*)/) {
push(@rv, { 'name' => $1,
'value' => $2 });
}
}
close(SENS);
@get_ups_cache = @rv;
}
return @get_ups_cache;
}

51
status/phpini-monitor.pl Normal file
View File

@@ -0,0 +1,51 @@
# phpini-monitor.pl
# Monitor a FPM-FPM server
sub get_phpini_status
{
my ($serv, $mod) = @_;
return { 'up' => -1 } if (!&foreign_check("phpini"));
return { 'up' => -1 } if (!&foreign_check("init"));
&foreign_require("phpini");
my @files = &phpini::list_php_configs();
my ($file) = grep { $_->[0] eq $serv->{'inifile'} } @files;
return { 'up' => -1,
'desc' => $text{'phpini_nofile'} } if (!$file);
my $init = &phpini::get_php_ini_bootup($serv->{'inifile'});
return { 'up' => -1,
'desc' => $text{'phpini_noinit'} } if (!$init);
&foreign_require("init");
my $st = &init::status_action($init);
if ($st < 0) {
return { 'up' => -1,
'desc' => &text('phpini_noinit2', $init) };
}
elsif ($st > 0) {
return { 'up' => 1 };
}
else {
return { 'up' => 0,
'desc' => &text('phpini_downinit', $init) };
}
}
sub show_phpini_dialog
{
my ($serv) = @_;
&foreign_require("phpini");
my @files = grep { $_->[1] }
map { [ $_->[0], &phpini::get_php_ini_version($_->[0]) ] }
&phpini::list_php_configs();
my %donever;
@files = grep { !$donever{$_->[1]}++ } @files;
print &ui_table_row($text{'phpini_file'},
&ui_select("inifile", $serv->{'inifile'}, \@files));
}
sub parse_phpini_dialog
{
my ($serv) = @_;
$in{'inifile'} || &error($text{'phpini_efile'});
$serv->{'inifile'} = $in{'inifile'};
}

View File

@@ -3760,5 +3760,56 @@ my ($content, $attrs) = @_;
return ui_tag('p', $content, $attrs);
}
=head2 ui_text_mask(text, [tag], [extra_class])
Returns an HTML string with the given text hidden inside a tag that only shows
on hover. If a second parameter is given, it is used as the outer tag that
triggers the hover (default is "td"). If a third parameter is provided,
it is added as an extra class to both the tag and its style.
=cut
sub ui_text_mask
{
return &theme_ui_text_mask(@_) if (defined(&theme_ui_text_mask));
my ($text, $tag, $extra_class) = @_;
my $class = 'hover-mask';
my $classcss = ".$class";
if ($extra_class) {
$class .= " $extra_class";
$classcss .= ".$extra_class";
}
$tag ||= 'td';
my $style_content = <<"CSS";
x-ui-text-mask${classcss} {
position: relative;
display: inline-block;
color: transparent;
transition:color .25s ease;
}
x-ui-text-mask${classcss}::after{
content: attr(data-mask);
position: absolute;
inset: 0;
color: var(--ui-password-mask-color, #000);
pointer-events: none;
transition: opacity .25s ease;
}
$tag:has(>*>x-ui-text-mask${classcss}):hover x-ui-text-mask${classcss},
$tag:has(>x-ui-text-mask${classcss}):hover x-ui-text-mask${classcss}{
color: inherit;
}
$tag:has(>*>x-ui-text-mask${classcss}):hover x-ui-text-mask${classcss}::after,
$tag:has(>x-ui-text-mask${classcss}):hover x-ui-text-mask${classcss}::after{
opacity: 0;
}
CSS
my $rv = '';
$rv .= &ui_tag('style', $style_content, { type => 'text/css' })
if (!$main::ui_text_mask_donecss->{"$tag$class"}++);
$rv .= &ui_tag('x-ui-text-mask', $text,
{ 'class' => $class, 'data-mask' => '••••••••' });
return $rv;
}
1;

View File

@@ -1 +1 @@
2.401
2.402

View File

@@ -1077,11 +1077,13 @@ sub PrintHeader
{
my ($cs, $mt, $headers) = @_;
$mt ||= "text/html";
if ($ENV{'SSL_HSTS'} == 1 && uc($ENV{'HTTPS'}) eq "ON") {
print "Strict-Transport-Security: max-age=31536000;\n";
}
elsif (uc($ENV{'HTTPS'}) ne "ON") {
print "Strict-Transport-Security: max-age=0;\n";
if (uc($ENV{'HTTPS'}) eq "ON") {
if ($ENV{'SSL_HSTS'}) {
print "Strict-Transport-Security: max-age=31536000;\n";
}
else {
print "Strict-Transport-Security: max-age=0;\n";
}
}
if ($pragma_no_cache || $gconfig{'pragma_no_cache'}) {
print "pragma: no-cache\n";
@@ -2126,7 +2128,7 @@ if ($_[0] =~ /^\// || $_[0] =~ /^[a-z]:[\\\/]/i) {
else {
# Check each directory in the path
my %donedir;
foreach my $d (split($path_separator, $ENV{'PATH'})) {
foreach my $d (split($path_separator || ":", $ENV{'PATH'})) {
next if ($donedir{$d}++);
$d =~ s/$slash$// if ($d ne $slash);
my $t = &translate_filename("$d/$_[0]");

View File

@@ -28,7 +28,7 @@ print &ui_table_row($text{'debug_file'},
print &ui_table_row($text{'debug_size'},
&ui_radio("debug_size_def", $gconfig{'debug_size'} ? 0 : 1,
[ [ 1, $text{'default'}.
" (".&nice_size($main::default_debug_log_size).")" ],
" (".&html_strip(&nice_size($main::default_debug_log_size)).")" ],
[ 0, &ui_bytesbox("debug_size", $gconfig{'debug_size'}) ] ]
), undef, [ "valign=middle","valign=middle" ]);