mirror of
https://github.com/webmin/webmin.git
synced 2026-02-05 23:22:15 +00:00
Compare commits
37 Commits
dev/embed-
...
dev/fix-la
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a75781d61a | ||
|
|
45348f5b02 | ||
|
|
548c078813 | ||
|
|
76ccb2b7ed | ||
|
|
61d2081371 | ||
|
|
458916b4d8 | ||
|
|
37451ad905 | ||
|
|
9eec58a1f1 | ||
|
|
178f527afa | ||
|
|
cd1555b3e1 | ||
|
|
2d7cfca67f | ||
|
|
e92a35b3ed | ||
|
|
e35efd0f00 | ||
|
|
a12f385a5b | ||
|
|
5dc7cfafd7 | ||
|
|
35aee74311 | ||
|
|
d04dfdf157 | ||
|
|
41f1adf0df | ||
|
|
1ae01bed8d | ||
|
|
4a6f5d9a6a | ||
|
|
bb3a4bc1e8 | ||
|
|
084c117547 | ||
|
|
20d481e96b | ||
|
|
6af5ed6e2f | ||
|
|
3fa687e716 | ||
|
|
d21188c2ad | ||
|
|
ba3be31335 | ||
|
|
adb3d0bb67 | ||
|
|
cd9bc8b7c4 | ||
|
|
cce8911f0f | ||
|
|
cde548ada3 | ||
|
|
00d0a89630 | ||
|
|
9c971202b3 | ||
|
|
2aa3bce4da | ||
|
|
4103177d1e | ||
|
|
31b6cdc82b | ||
|
|
fd8c634277 |
@@ -30,7 +30,7 @@ push(@EXPORT, qw(&unique));
|
||||
push(@EXPORT, qw($config_directory $var_directory $remote_error_handler %month_to_number_map %number_to_month_map $webmin_feedback_address $default_lang $default_charset $module_index_name $module_index_link %in $in @in $progress_callback_prefix $progress_callback_url $wait_for_debug $wait_for_input @matches $theme_no_table $webmin_logfile $pragma_no_cache));
|
||||
|
||||
# Functions defined in themes
|
||||
push(@EXPORT, qw(&theme_post_save_domain &theme_post_save_domains &theme_post_save_server &theme_select_server &theme_select_domain &theme_post_save_folder &theme_post_change_modules &theme_address_button &theme_virtualmin_ui_rating_selector &theme_virtualmin_ui_show_cron_time &theme_virtualmin_ui_parse_cron_time &theme_virtualmin_ui_html_editor_bodytags &theme_virtualmin_ui_show_html_editor &theme_post_change_theme &theme_pre_change_theme));
|
||||
push(@EXPORT, qw(&theme_post_save_domain &theme_post_save_domains &theme_post_save_server &theme_select_server &theme_select_domain &theme_post_save_folder &theme_post_change_modules &theme_address_button &theme_virtualmin_ui_rating_selector &theme_virtualmin_ui_show_cron_time &theme_virtualmin_ui_parse_cron_time &theme_virtualmin_ui_html_editor_bodytags &theme_virtualmin_ui_show_html_editor &theme_post_change_theme &theme_pre_change_theme &theme_fonts &theme_css_inline));
|
||||
|
||||
$called_from_webmin_core = 1;
|
||||
do "web-lib.pl";
|
||||
|
||||
@@ -1988,6 +1988,8 @@ if (@transfer) {
|
||||
}
|
||||
}
|
||||
if (@notify) {
|
||||
my %done;
|
||||
@notify = grep { !$done{$_->{'name'}}++ } @notify;
|
||||
my $also = { 'name' => 'also-notify',
|
||||
'type' => 1,
|
||||
'members' => \@notify};
|
||||
@@ -1996,6 +1998,8 @@ if (@notify) {
|
||||
'values' => [ 'yes' ] });
|
||||
}
|
||||
if (@transfer) {
|
||||
my %done;
|
||||
@transfer = grep { !$done{$_->{'name'}}++ } @transfer;
|
||||
my $allow = { 'name' => 'allow-transfer',
|
||||
'type' => 1,
|
||||
'members' => \@transfer };
|
||||
|
||||
@@ -40,6 +40,7 @@ if (@keyrecs) {
|
||||
my $kt = $key->{'ksk'} ? 'ksk' : 'zone';
|
||||
my ($keyrec) = grep { $_->{'values'}->[0] ==
|
||||
($key->{'ksk'} ? 257 : 256) } @keyrecs;
|
||||
next if (!$keyrec);
|
||||
my $keyline = format_dnssec_public_key(
|
||||
join(" ", $keyrec->{'name'}, $keyrec->{'class'},
|
||||
$keyrec->{'type'}, @{$keyrec->{'values'}}));
|
||||
|
||||
@@ -350,7 +350,7 @@ if ($fh6) {
|
||||
while(1) {
|
||||
$$port++;
|
||||
if ($$port < 0 || $$port > 65535) {
|
||||
return "Failed to allocate a free port number: $port";
|
||||
return "Failed to allocate a free port number: $$port";
|
||||
}
|
||||
$pack = pack_sockaddr_in($$port, INADDR_ANY);
|
||||
next if (!bind($fh, $pack));
|
||||
|
||||
@@ -29,9 +29,6 @@ table.ui_table thead td {
|
||||
table.sortable tbody td {
|
||||
padding: 2px;
|
||||
}
|
||||
table.ui_table td * {
|
||||
line-height:1.5em;
|
||||
}
|
||||
table.ui_table td textarea {line-height:normal; font-family:monospace;}
|
||||
table.ui_table td div.barchart * {
|
||||
margin: 0;
|
||||
@@ -55,9 +52,16 @@ div.ui_form_end_buttons {
|
||||
padding: 6px 3px;
|
||||
}
|
||||
.ui_form_end_buttons input {
|
||||
padding: 2px;
|
||||
padding: 1px;
|
||||
}
|
||||
table.ui_grid_table td { padding: 2px 4px; }
|
||||
.ui_form_value td > b > input+label+tt,
|
||||
.ui_form_value td > b > input+label {
|
||||
font-weight: normal !important;
|
||||
}
|
||||
table.ui_grid_table td {
|
||||
padding: 2px 4px;
|
||||
}
|
||||
select,
|
||||
input {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
@@ -2371,6 +2371,8 @@ if (ref($opts)) {
|
||||
&print_tempfile(CFILE, "ExecReload=$kill -HUP \$MAINPID\n") if ($opts->{'reload'} eq '0');
|
||||
&print_tempfile(CFILE, "ExecStop=$opts->{'stop'}\n") if ($opts->{'stop'});
|
||||
&print_tempfile(CFILE, "ExecReload=$opts->{'reload'}\n") if ($opts->{'reload'});
|
||||
&print_tempfile(CFILE, "ExecStartPre=$opts->{'startpre'}\n") if ($opts->{'startpre'});
|
||||
&print_tempfile(CFILE, "ExecStartPost=$opts->{'startpost'}\n") if ($opts->{'startpost'});
|
||||
&print_tempfile(CFILE, "Type=$opts->{'type'}\n") if ($opts->{'type'});
|
||||
&print_tempfile(CFILE, "Environment=\"$opts->{'env'}\"\n") if ($opts->{'env'});
|
||||
&print_tempfile(CFILE, "User=$opts->{'user'}\n") if ($opts->{'user'});
|
||||
@@ -2381,8 +2383,8 @@ if (ref($opts)) {
|
||||
&print_tempfile(CFILE, "RestartSec=$opts->{'restartsec'}\n") if ($opts->{'restartsec'});
|
||||
&print_tempfile(CFILE, "TimeoutSec=$opts->{'timeout'}\n") if ($opts->{'timeout'});
|
||||
&print_tempfile(CFILE, "TimeoutStopSec=$opts->{'timeoutstopsec'}\n") if ($opts->{'timeoutstopsec'});
|
||||
&print_tempfile(CFILE, "StandardOutput=file:$opts->{'logstd'}\n") if ($opts->{'logstd'});
|
||||
&print_tempfile(CFILE, "StandardError=file:$opts->{'logerr'}\n") if ($opts->{'logerr'});
|
||||
&print_tempfile(CFILE, "StandardOutput=".($opts->{'logstd'} =~ /^\// ? 'file:' : '')."$opts->{'logstd'}\n") if ($opts->{'logstd'});
|
||||
&print_tempfile(CFILE, "StandardError=".($opts->{'logerr'} =~ /^\// ? 'file:' : '')."$opts->{'logerr'}\n") if ($opts->{'logerr'});
|
||||
}
|
||||
|
||||
&print_tempfile(CFILE, "\n");
|
||||
|
||||
@@ -16,7 +16,7 @@ fwd_mode=0
|
||||
delete_warn=y
|
||||
top_buttons=2
|
||||
view_html=2
|
||||
view_images=3
|
||||
view_images=1
|
||||
mail_usermin=mail
|
||||
sync_create=0
|
||||
sync_modify=1
|
||||
|
||||
@@ -2947,7 +2947,8 @@ my $iframe_body = <<EOF;
|
||||
theme_mail_iframe_onload(iframe);
|
||||
return;
|
||||
}
|
||||
const iframe_spinner = document.querySelector('#mail-iframe-spinner'),
|
||||
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document,
|
||||
iframe_spinner = document.querySelector('#mail-iframe-spinner'),
|
||||
iframe_resize = function() {
|
||||
const iframeobj = document.querySelector('#mail-iframe'),
|
||||
iframe_height_bound = iframeobj.contentWindow.document.body.getBoundingClientRect().bottom,
|
||||
@@ -2955,8 +2956,11 @@ my $iframe_body = <<EOF;
|
||||
iframe_height =
|
||||
iframe_height_bound > iframe_scroll_height ?
|
||||
iframe_height_bound : iframe_scroll_height;
|
||||
iframeobj.style.height = Math.ceil(iframe_height) + "px";
|
||||
iframeobj.style.height = Math.ceil(iframe_height - 1) + "px";
|
||||
};
|
||||
iframeDoc.body.style.removeProperty('width');
|
||||
iframeDoc.body.style.margin = '4px';
|
||||
iframeDoc.body.style.padding = '0';
|
||||
iframe_spinner && iframe_spinner.remove();
|
||||
iframe.classList.add("loaded");
|
||||
setTimeout(iframe_resize);
|
||||
@@ -2980,6 +2984,15 @@ my $iframe_body = <<EOF;
|
||||
})();
|
||||
});
|
||||
}, 99);
|
||||
iframeDoc.addEventListener('click', function(event) {
|
||||
if (event.target.tagName.toLowerCase() === 'summary' &&
|
||||
event.target.dataset.resize === 'iframe') {
|
||||
setTimeout(iframe_resize);
|
||||
}
|
||||
});
|
||||
iframe.contentWindow.addEventListener('resize', function() {
|
||||
setTimeout(iframe_resize);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<iframe
|
||||
@@ -4399,10 +4412,10 @@ elsif ($line =~ /^END:VEVENT/) {
|
||||
# Try to add local 'when (period)'
|
||||
my $dtstart_local_obj =
|
||||
$event{'_obj_dtstart_local_time'} =
|
||||
make_date($event{'dtstart_local_timestamp'}, { _ });
|
||||
make_date($event{'dtstart_local_timestamp'}, { });
|
||||
my $dtend_local_obj =
|
||||
$event{'_obj_dtend_local_time'} =
|
||||
make_date($event{'dtend_local_timestamp'}, { _ });
|
||||
make_date($event{'dtend_local_timestamp'}, { });
|
||||
# Build when local, e.g.:
|
||||
# Tue Jun 04, 2024 04:30 PM – 05:15
|
||||
# PM (Asia/Nicosia +0300)
|
||||
@@ -4579,6 +4592,12 @@ my ($calendars) = @_;
|
||||
my @calendars = @{$calendars};
|
||||
$calendars = { };
|
||||
if (@calendars) {
|
||||
# Fonts for our HTML
|
||||
$calendars->{'html'} .= &theme_fonts()
|
||||
if (defined(&theme_fonts));
|
||||
my $theme_css_inline;
|
||||
$theme_css_inline = &theme_css_inline('calendar')
|
||||
if (defined(&theme_css_inline));
|
||||
# CSS for HTML version
|
||||
$calendars->{'html'} .= <<STYLE;
|
||||
<style>
|
||||
@@ -4588,6 +4607,7 @@ if (@calendars) {
|
||||
border-collapse: collapse;
|
||||
border: 1px solid #99999933;
|
||||
margin-bottom: 4px;
|
||||
font-family: 'RobotoLocal',arial,helvetica,clean,sans-serif !important;
|
||||
}
|
||||
.calendar-table-inner {
|
||||
table-layout: fixed;
|
||||
@@ -4610,44 +4630,50 @@ if (@calendars) {
|
||||
font-weight: bold;
|
||||
}
|
||||
.calendar-month {
|
||||
font-size: 21px;
|
||||
font-size: 19px;
|
||||
color: #1d72ff;
|
||||
text-align: center;
|
||||
padding: 2px 8px;
|
||||
}
|
||||
.calendar-day {
|
||||
font-size: 24px;
|
||||
font-size: 19px;
|
||||
text-align: center;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
.calendar-week {
|
||||
font-size: 16px;
|
||||
font-size: 13px;
|
||||
border-top: 1px dotted #999999aa;
|
||||
padding: 6px;
|
||||
display: inline-block;
|
||||
}
|
||||
.calendar-details h2 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
font-size: 15px;
|
||||
}
|
||||
.calendar-details p {
|
||||
margin: 4px 0;
|
||||
}
|
||||
.calendar-details .title {
|
||||
font-size: 20px;
|
||||
font-size: 16px;
|
||||
}
|
||||
.calendar-details .detail strong {
|
||||
opacity: 0.66;
|
||||
opacity: 0.83;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.calendar-details .detail + .desc p:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
details.calendar-details {
|
||||
font-size: 90%;
|
||||
font-size: 87%;
|
||||
display: inline-block;
|
||||
margin-left: 9px;
|
||||
}
|
||||
.calendar-details > .calendar-table-inner .detail:has(strong),
|
||||
.calendar-details > .calendar-table-inner .detail strong,
|
||||
.calendar-details > .calendar-table-inner .detail + td {
|
||||
font-size: 13px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
details.calendar-details summary {
|
||||
cursor: help;
|
||||
}
|
||||
@@ -4655,6 +4681,7 @@ if (@calendars) {
|
||||
.calendar-details tr:has(>.detail+td:empty) {
|
||||
display: none;
|
||||
}
|
||||
$theme_css_inline
|
||||
</style>
|
||||
STYLE
|
||||
foreach my $calendar (@calendars) {
|
||||
|
||||
@@ -107,7 +107,7 @@ if ($product eq "webmin") {
|
||||
$size = int(`du -sk $tmp_dir`);
|
||||
@deps = ( "perl", "libnet-ssleay-perl", "openssl", "libauthen-pam-perl", "libpam-runtime", "libio-pty-perl", "unzip", "shared-mime-info", "tar", "libdigest-sha-perl", "libdigest-md5-perl", "gzip" );
|
||||
$deps = join(", ", @deps);
|
||||
@recommends = ( "libdatetime-perl", "libdatetime-timezone-perl", "libdatetime-locale-perl", "libtime-piece-perl", "libencode-detect-perl", "libtime-hires-perl", "libsocket6-perl", "lynx", "qrencode" );
|
||||
@recommends = ( "libdatetime-perl", "libdatetime-timezone-perl", "libdatetime-locale-perl", "libtime-piece-perl", "libencode-detect-perl", "libtime-hires-perl", "libsocket6-perl", "libthreads-perl", "libthreads-shared-perl", "lynx", "qrencode" );
|
||||
$recommends = join(", ", @recommends);
|
||||
open(CONTROL, ">$control_file");
|
||||
print CONTROL <<EOF;
|
||||
|
||||
@@ -87,7 +87,7 @@ Release: $rel
|
||||
Provides: %{name}-%{version} perl(WebminCore)
|
||||
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) lynx shared-mime-info perl-File-Basename perl-File-Path qrencode
|
||||
Recommends: perl(DateTime) perl(DateTime::TimeZone) perl(DateTime::Locale) perl(Time::Piece) perl(Encode::Detect) perl(Time::HiRes) perl(Socket6) perl(threads) perl(threads::shared) lynx shared-mime-info perl-File-Basename perl-File-Path qrencode
|
||||
AutoReq: 0
|
||||
License: BSD-3-clause
|
||||
Group: System/Tools
|
||||
|
||||
@@ -330,7 +330,7 @@ Corvus Latinux 8.0 redhat-linux 7.1 `cat /etc/latinux-release 2>/dev/null` =~
|
||||
Immunix Linux $1 redhat-linux $1 $etc_issue =~ /Immunix.*\s([0-9\.]+)/i || `cat /etc/immunix-release 2>/dev/null` =~ /([0-9\.]+)/
|
||||
|
||||
# All versions of Gentoo (which don't appear to have version numbers)
|
||||
Gentoo Linux Any version gentoo-linux * -d "/usr/portage"
|
||||
Gentoo Linux Any version gentoo-linux * -d "/usr/portage" || `cat /etc/os-release 2>/dev/null` =~ /gentoo/
|
||||
|
||||
# Secure Linux (now called Trustix?)
|
||||
Secure Linux 1.0 redhat-linux 7.2 `cat /etc/securelinux-release 2>/dev/null` =~ /SecureLinux.*1\.0/i
|
||||
|
||||
@@ -56,7 +56,7 @@ if ($in{'action'} eq $text{'action_sync'}) {
|
||||
if (defined($in{'sync_service_name'}) &&
|
||||
defined($in{'sync_service_status'})) {
|
||||
my $service_name = $in{'sync_service_name'};
|
||||
if ($service_name !~ /^(chronyd|systemd-timesyncd)$/) {
|
||||
if ($service_name !~ /^(chronyd|chrony|systemd-timesyncd)$/) {
|
||||
&error(&text('error_serviceunknown', &html_escape($service_name)));
|
||||
}
|
||||
my $service_status = int($in{'sync_service_status'});
|
||||
|
||||
@@ -5,7 +5,8 @@ use warnings;
|
||||
no warnings 'redefine';
|
||||
no warnings 'uninitialized';
|
||||
require './time-lib.pl';
|
||||
our (%in, %text, %config, %access, $base_remote_user, $get_hardware_time_error);
|
||||
our (%in, %text, %config, %access, $base_remote_user,
|
||||
$get_hardware_time_error, $cronyd_name);
|
||||
|
||||
my ($rawdate, $rawhwdate, %system_date, $rawtime, %hw_date, $txt);
|
||||
$txt = "";
|
||||
@@ -174,13 +175,14 @@ if ( ( !$access{ 'sysdate' } && &has_command( "date" ) || !$access{ 'hwdate' } &
|
||||
$config{'timeserver_hardware'}));
|
||||
}
|
||||
}
|
||||
if (&foreign_require('init') && &init::action_status('chronyd') > 0 && &has_command("chronyc")) {
|
||||
my $chronyd_running = &init::status_action('chronyd');
|
||||
my $chronyd_run_atboot = &init::action_status('chronyd');
|
||||
my $ui_hiddens = &ui_hidden("sync_service_name", "chronyd");
|
||||
if (&foreign_require('init') &&
|
||||
&init::action_status($cronyd_name) > 0 && &has_command("chronyc")) {
|
||||
my $chronyd_running = &init::status_action($cronyd_name);
|
||||
my $chronyd_run_atboot = &init::action_status($cronyd_name);
|
||||
my $ui_hiddens = &ui_hidden("sync_service_name", $cronyd_name);
|
||||
$ui_hiddens .= &ui_hidden("timeserver", $config{'timeserver'})
|
||||
if (!$ntp_support);
|
||||
print &ui_table_row(&text('index_tabsync2', 'chronyd'),
|
||||
print &ui_table_row(&text('index_tabsync2', $cronyd_name),
|
||||
$ui_hiddens.
|
||||
&ui_radio("sync_service_status",
|
||||
(($chronyd_run_atboot == 2 && $chronyd_running) ? 2 :
|
||||
|
||||
@@ -13,6 +13,7 @@ our ($timezones_file, $currentzone_link, $currentzone_file, $timezones_dir,
|
||||
$sysclock_file);
|
||||
our ($get_hardware_time_error);
|
||||
our $cron_cmd = "$module_config_directory/sync.pl";
|
||||
our $cronyd_name = $gconfig{'os_type'} eq 'debian-linux' ? 'chrony' : 'chronyd';
|
||||
our $rawtime;
|
||||
if ($config{'zone_style'}) {
|
||||
do "$config{'zone_style'}-lib.pl";
|
||||
@@ -49,13 +50,13 @@ if (&has_command("ntpdate")) {
|
||||
elsif (&has_command("sntp")) {
|
||||
$out = &backquote_logged("sntp -s $servs 2>&1");
|
||||
}
|
||||
elsif (&foreign_require('init') && &init::action_status('chronyd') > 0 && &has_command("chronyc")) {
|
||||
my $chronyd_running = &init::status_action('chronyd');
|
||||
$out = &backquote_logged("systemctl restart chronyd 2>&1");
|
||||
elsif (&foreign_require('init') && &init::action_status($cronyd_name) > 0 && &has_command("chronyc")) {
|
||||
my $chronyd_running = &init::status_action($cronyd_name);
|
||||
$out = &backquote_logged("systemctl restart $cronyd_name 2>&1");
|
||||
$out .= &backquote_logged("chronyc makestep 2>&1");
|
||||
sleep ($chronyd_running ? 5 : 15);
|
||||
if (!$chronyd_running) {
|
||||
&backquote_logged("systemctl stop chronyd 2>&1");
|
||||
&backquote_logged("systemctl stop $cronyd_name 2>&1");
|
||||
}
|
||||
}
|
||||
elsif (&foreign_require('init') && &init::action_status('systemd-timesyncd') > 0) {
|
||||
|
||||
@@ -22,7 +22,7 @@ sub open_last_command
|
||||
{
|
||||
local ($fh, $user) = @_;
|
||||
local $quser = quotemeta($user);
|
||||
open($fh, "(last -F $quser || last $quser) |");
|
||||
open($fh, "(last -F -w $quser || last -w $quser) |");
|
||||
}
|
||||
|
||||
# read_last_line(handle)
|
||||
@@ -39,12 +39,15 @@ while(1) {
|
||||
# jcameron pts/0 fudu Thu Feb 22 09:47 - 10:15
|
||||
return ($1, $2, $3, $4, $5 eq "down" ? "Shutdown" : $5, $6);
|
||||
}
|
||||
elsif ($line =~ /^(\S+)\s+(\S+)\s+(\S+)?\s+(\S+\s+\S+\s+\d+\s+\d+:\d+:\d+\s+\d+)\s+\-\s+(\S+\s+\S+\s+\d+\s+\d+:\d+:\d+\s+\d+)\s+\((\d+:\d+)\)/) {
|
||||
elsif ($line =~ /^(\S+)\s+(\S+)\s+(\S+)?\s+(\S+\s+\S+\s+\d+\s+\d+:\d+:\d+\s+\d+)\s+\-\s+(\S+\s+\S+\s+\d+\s+\d+:\d+:\d+\s+\d+)\s+\((.*?\d+:\d+)\)/) {
|
||||
# jcameron pts/0 fudu Thu Feb 22 09:47 - 10:15
|
||||
# jcameron pts/0 fudu Sun Feb 4 02:26:28 2024 - Wed Feb 7 18:25:09 2024 (3+15:58)
|
||||
return ($1, $2, $3, $4, $5 eq "down" ? "Shutdown" : $5, $6);
|
||||
}
|
||||
elsif ($line =~ /^(\S+)\s+(\S+)\s+(\S+)?\s+(\S+\s+\S+\s+\d+\s+\d+:\d+)\s+still/) {
|
||||
# root pts/0 fudu Fri Feb 23 18:46 still logged in
|
||||
elsif ($line =~ /^(\S+)\s+(\S+)\s+(\S+)?\s+(\S+\s+\S+\s+\d+\s+\d+:\d+)\s+still/ ||
|
||||
$line =~ /^(\S+)\s+(\S+)\s+(\S+)?\s+(\S+\s+\S+\s+\d+\s+\d+:\d+:\d+\s+\d+)\s+still/) {
|
||||
# root pts/0 fudu Fri Feb 23 18:46 still logged in
|
||||
# root pts/0 fudu Tue Jun 18 23:10:30 2024 still logged in
|
||||
return ($1, $2, $3, $4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2176,7 +2176,7 @@ if (!$@ && $] > 5.011) {
|
||||
}
|
||||
|
||||
# Return fully detailed object
|
||||
if (%{$opts}) {
|
||||
if (ref($only)) {
|
||||
# Can we get ago time
|
||||
my $ago;
|
||||
my $ago_secs = time() - $secs;
|
||||
@@ -2228,6 +2228,10 @@ if (!$@ && $] > 5.011) {
|
||||
}
|
||||
};
|
||||
$data->{'year'} = DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%Y");
|
||||
$data->{'day'} = DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%d");
|
||||
$data->{'week'} = DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%a");
|
||||
$data->{'weekfull'} = DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%A");
|
||||
$data->{'month'} = DateTime->from_epoch(locale => $locale_name_loaded, epoch => $secs, time_zone => $tz)->strftime("%b");
|
||||
$data->{'complete'} =~ s/(\d+):(\d+):(\d+)(.*?)/$1:$2$4/;
|
||||
($data->{'complete_short'} = $data->{'complete'}) =~ s/(.*?)([\s\,]*\Q$data->{'year'}\E.*)/$1/;
|
||||
|
||||
@@ -13569,12 +13573,22 @@ my $ws_proto = lc($ENV{'HTTPS'}) eq 'on' ? 'wss' : 'ws';
|
||||
my %miniserv;
|
||||
&get_miniserv_config(\%miniserv);
|
||||
my $http_host_conf = &trim($miniserv{'websocket_host'} || $host);
|
||||
# Pass as defined
|
||||
if ($http_host_conf) {
|
||||
if ($http_host_conf !~ /^wss?:\/\//) {
|
||||
$http_host_conf = "$ws_proto://$http_host_conf";
|
||||
}
|
||||
$http_host_conf =~ s/[\/]+$//g;
|
||||
}
|
||||
# Try to rely on the proxy
|
||||
if (!defined($http_host_conf)) {
|
||||
my $forwarded_host = $ENV{'HTTP_X_FORWARDED_HOST'};
|
||||
if ($forwarded_host) {
|
||||
$http_host_conf = "$ws_proto://$forwarded_host".
|
||||
&get_webprefix();
|
||||
$http_host_conf =~ s/\/$//;
|
||||
}
|
||||
}
|
||||
my $http_host = $http_host_conf || "$ws_proto://$ENV{'HTTP_HOST'}";
|
||||
return "$http_host/$module/ws-$port";
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ if (!$eol_data->{'_eol_timestamp'}) {
|
||||
&error_stderr("The provided data is not a valid EOL data hash reference");
|
||||
return undef;
|
||||
}
|
||||
my $eol_date = &make_date($eol_data->{'_eol_timestamp'}, { '_' => 1 });
|
||||
my $eol_date = &make_date($eol_data->{'_eol_timestamp'}, { });
|
||||
if (ref($eol_date)) {
|
||||
my $eol_in = sub {
|
||||
my $eol_date = shift;
|
||||
|
||||
@@ -10,6 +10,10 @@ my ($o) = @_;
|
||||
print &ui_table_row($text{'acl_user'},
|
||||
&ui_opt_textbox("user", $o->{'user'} eq '*' ? undef : $o->{'user'},
|
||||
20, $text{'acl_sameuser'}));
|
||||
|
||||
print &ui_table_row($text{'acl_sudoenforce'},
|
||||
&ui_yesno_radio("sudoenforce",
|
||||
$o->{'sudoenforce'} == 1 ? 1 : 0));
|
||||
}
|
||||
|
||||
sub acl_security_save
|
||||
@@ -17,4 +21,5 @@ sub acl_security_save
|
||||
my ($o) = @_;
|
||||
|
||||
$o->{'user'} = $in{'user_def'} ? '*' : $in{'user'};
|
||||
$o->{'sudoenforce'} = $in{'sudoenforce'} ? 1 : 0;
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
user=root
|
||||
sudoenforce=1
|
||||
|
||||
@@ -168,13 +168,21 @@ EOF
|
||||
print "<div data-label=\"$text{'index_connecting'}\" id=\"terminal\"></div>\n";
|
||||
|
||||
# Get a free port that can be used for the socket
|
||||
my $port = &allocate_miniserv_websocket();
|
||||
my $port = &allocate_miniserv_websocket($module_name);
|
||||
|
||||
# Check permissions for user to run as
|
||||
my $user = $access{'user'};
|
||||
if ($user eq "*") {
|
||||
$user = $remote_user;
|
||||
}
|
||||
elsif ($user eq "root" && $remote_user ne $user && !$in{'user'} &&
|
||||
$access{'sudoenforce'} ne '0') {
|
||||
# If possible, start with a sudo-capable user
|
||||
my @uinfo = getpwnam($remote_user);
|
||||
if (@uinfo && $uinfo[7]) {
|
||||
$user = $remote_user;
|
||||
}
|
||||
}
|
||||
$user = $config{'user'} if ($user eq 'root' && $config{'user'});
|
||||
|
||||
# Switch to given user
|
||||
@@ -200,7 +208,7 @@ $ENV{'SESSION_ID'} = $main::session_id;
|
||||
" >$module_var_directory/websocket-connection-$port.out 2>&1 </dev/null");
|
||||
|
||||
# Open the terminal
|
||||
my $url = &get_miniserv_websocket_url($port, $config{'host'});
|
||||
my $url = &get_miniserv_websocket_url($port, $config{'host'}, $module_name);
|
||||
my $canvasAddon = $termlinks->{'js'}[3];
|
||||
my $webGLAddon = $termlinks->{'js'}[4];
|
||||
my $term_script = <<EOF;
|
||||
|
||||
@@ -9,3 +9,4 @@ index_eproxy=The Terminal module cannot be used when accessing Webmin via anothe
|
||||
|
||||
acl_user=Run shell as Unix user
|
||||
acl_sameuser=Same as Webmin login
|
||||
acl_sudoenforce=Enforce <em>sudo</em>-only privileges
|
||||
|
||||
@@ -14,7 +14,7 @@ my @uinfo = getpwnam($user);
|
||||
my ($uid, $gid);
|
||||
if ($user ne "root" && !$<) {
|
||||
if (!@uinfo) {
|
||||
&remove_miniserv_websocket($port);
|
||||
&remove_miniserv_websocket($port, $module_name);
|
||||
die "User $user does not exist!";
|
||||
}
|
||||
$uid = $uinfo[2];
|
||||
@@ -83,7 +83,7 @@ my ($shellfh, $pid) = &proc::pty_process_exec($shellexec, $uid, $gid, $shelllogi
|
||||
&reset_environment();
|
||||
my $shcmd = "'$shellexec".($shelllogin ? " $shelllogin" : "")."'";
|
||||
if (!$pid) {
|
||||
&remove_miniserv_websocket($port);
|
||||
&remove_miniserv_websocket($port, $module_name);
|
||||
die "Failed to run shell with $shcmd\n";
|
||||
}
|
||||
else {
|
||||
@@ -99,7 +99,7 @@ close(STDIN);
|
||||
|
||||
# Clean up when socket is terminated
|
||||
$SIG{'ALRM'} = sub {
|
||||
&remove_miniserv_websocket($port);
|
||||
&remove_miniserv_websocket($port, $module_name);
|
||||
die "timeout waiting for connection";
|
||||
};
|
||||
alarm(60);
|
||||
@@ -154,13 +154,13 @@ Net::WebSocket::Server->new(
|
||||
}
|
||||
if (!syswrite($shellfh, $msg, length($msg))) {
|
||||
&error_stderr("Write to shell failed : $!");
|
||||
&remove_miniserv_websocket($port);
|
||||
&remove_miniserv_websocket($port, $module_name);
|
||||
exit(1);
|
||||
}
|
||||
},
|
||||
disconnect => sub {
|
||||
&error_stderr("WebSocket connection closed");
|
||||
&remove_miniserv_websocket($port);
|
||||
&remove_miniserv_websocket($port, $module_name);
|
||||
kill('KILL', $pid) if ($pid);
|
||||
exit(0);
|
||||
}
|
||||
@@ -173,7 +173,7 @@ Net::WebSocket::Server->new(
|
||||
my $ok = sysread($shellfh, $buf, 1024);
|
||||
if ($ok <= 0) {
|
||||
&error_stderr("End of output from shell");
|
||||
&remove_miniserv_websocket($port);
|
||||
&remove_miniserv_websocket($port, $module_name);
|
||||
exit(0);
|
||||
}
|
||||
if ($wsconn) {
|
||||
@@ -186,5 +186,5 @@ Net::WebSocket::Server->new(
|
||||
],
|
||||
)->start;
|
||||
&error_stderr("Exited WebSocket server");
|
||||
&remove_miniserv_websocket($port);
|
||||
&cleanup_miniserv_websockets([$port]);
|
||||
&remove_miniserv_websocket($port, $module_name);
|
||||
&cleanup_miniserv_websockets([$port], $module_name);
|
||||
Reference in New Issue
Block a user