mirror of
https://github.com/webmin/webmin.git
synced 2026-03-15 06:42:44 +00:00
Compare commits
22 Commits
2.620
...
534c529705
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
534c529705 | ||
|
|
2d0063129c | ||
|
|
ad37eabdfe | ||
|
|
6d3da61b95 | ||
|
|
4d05e8a2d0 | ||
|
|
e8e804ddca | ||
|
|
202a1b0b78 | ||
|
|
3c1c327530 | ||
|
|
2d7900d550 | ||
|
|
e9586fb2d8 | ||
|
|
9d95b5c977 | ||
|
|
d9c651d06d | ||
|
|
c70bae48aa | ||
|
|
83abdc8858 | ||
|
|
2833450b48 | ||
|
|
a0c023637f | ||
|
|
6721e13a6b | ||
|
|
2b2814fdf4 | ||
|
|
4dacdc31f6 | ||
|
|
2627ba289e | ||
|
|
b4a67a0d90 | ||
|
|
63af275296 |
44
CHANGELOG.md
44
CHANGELOG.md
@@ -1,5 +1,35 @@
|
||||
## Changelog
|
||||
|
||||
#### 2.621 (January 25, 2026)
|
||||
* Fix to prevent NAT from dropping idle RPC sessions during long transfers
|
||||
* Fix to improve the message when socket authentication is used in the MySQL/MariaDB module
|
||||
* Fix to make upload tracking work correctly in all situations and on all systems
|
||||
* Fix to correctly display the PHP version in the PHP Configuration module when managing packages
|
||||
* Update Xterm.js to the latest version with lots of improvements and fixes
|
||||
* Update Authentic theme to the latest version with various improvements and fixes:
|
||||
* Fix the support for the cloned Terminal module
|
||||
* Fix error handling for file uploads when the user is out of quota or the system is out of disk space in the File Manager module
|
||||
* Fix to stop loading full file into memory for upload check to prevent memory leak on large uploads in the File Manager module
|
||||
* Fix to permanently save the state of the navigation menu and right-side slider when toggled
|
||||
|
||||
|
||||
#### 2.620 (January 9, 2026)
|
||||
* Add ability to use correct driver depending on the database in MySQL/MariaDB module
|
||||
* Add improvements to BIND DNS module for better key management
|
||||
* Add support for Ubuntu 26.04 development preview
|
||||
* Add a config option to increase the RPC timeout
|
||||
* Add support for EC SSL certificate and key in the ProFTPd module
|
||||
* Add support for using `gpart` in FreeBSD disk management module
|
||||
* Add support for Ed25519 public key in User and Groups module
|
||||
* Fix RPC session timeout during large file transfers
|
||||
* Fix selection and configuration of TLS certificate and key in the ProFTPd module
|
||||
* Update Authentic theme to the latest version with various improvements and fixes:
|
||||
* Add support for multiple scrollable tabs in the File Manager
|
||||
* Fix displaying of the right-side toolbar in File Manager when using Safari
|
||||
* Fix to print menu separator when no virtual servers are added yet in Virtualmin
|
||||
* Fix bugs in white palette
|
||||
* Fix exported file name in data tables
|
||||
|
||||
#### 2.610 (November 23, 2025)
|
||||
* Fix to drop dependency on `IO::Pty` Perl module
|
||||
* Fix `virtual-server` module server-side search to work correctly
|
||||
@@ -270,7 +300,7 @@
|
||||
* Fix to using the `qrencode` command to generate QR codes locally instead of the remote Google Chart API
|
||||
* Fix a number of various other issues
|
||||
|
||||
#### 2.105 (November 09, 2023)
|
||||
#### 2.105 (November 9, 2023)
|
||||
* Fix param to read only headers [sourceforge.net/usermin-bugs#501](https://sourceforge.net/p/webadmin/usermin-bugs/501/)
|
||||
* Fix not to set `reuse` flag on initial Let's Encrypt request
|
||||
* Fix to correctly escape mail file names upon deletion
|
||||
@@ -285,7 +315,7 @@
|
||||
* Fix the absent init script for legacy systems after the initial installation
|
||||
* Update the Authentic theme to the latest version with various fixes and improvements
|
||||
|
||||
#### 2.103 (October 08, 2023)
|
||||
#### 2.103 (October 8, 2023)
|
||||
* Add support for hostname detection using `hostnamectl` command
|
||||
* Add support for other ACME services
|
||||
* Add ability to hide dotfiles in File Manager [#1578](https://github.com/webmin/authentic-theme/issues/1578)
|
||||
@@ -334,7 +364,7 @@
|
||||
* Fix clearing packages caches before checking for updates in status collection #1863
|
||||
* Update the Authentic theme to the latest version
|
||||
|
||||
#### 2.020 (March 08, 2023)
|
||||
#### 2.020 (March 8, 2023)
|
||||
* Add full locale support
|
||||
* Add slave zone file format option in BIND DNS module
|
||||
* Add support for editing ACLs in File Manager
|
||||
@@ -504,10 +534,10 @@ This release updates the built-in Let's Encrypt client, adds support for creatin
|
||||
#### Version 1.930 (August 18, 2019)
|
||||
These updates fix a [security vulnerability](http://webmin.com/security.html) and should be installed IMMEDIATELY by all users. Although it is not exploitable in a Webmin install with the default configuration, upgrading is strongly recommended.
|
||||
|
||||
#### Version 1.920 (July 04, 2019)
|
||||
#### Version 1.920 (July 4, 2019)
|
||||
This update includes the latest theme version, translation updates, the ability to disable hosts file entries, easier monitoring of bootup actions, and a bunch of bugfixes.
|
||||
|
||||
#### Version 1.910 (May 09, 2019)
|
||||
#### Version 1.910 (May 9, 2019)
|
||||
This release includes theme and translation updates, a page for editing package repositories, cron and status module improvements, and a bunch of other bugfixes and small improvements.
|
||||
|
||||
#### Version 1.900 (November 19, 2018)
|
||||
@@ -519,7 +549,7 @@ This version includes Ubuntu 18 network config support, translation updates, mul
|
||||
#### Version 1.880 (March 16, 2018)
|
||||
This version includes German, Catalan and Bulgarian translation updates, a new version of the Authentic theme, support for directly editing the MySQL and PostgreSQL config files, Let's Encrypt bugfixes, more control over system status email notifications, and more.
|
||||
|
||||
#### Version 1.870 (December 08, 2018)
|
||||
#### Version 1.870 (December 8, 2018)
|
||||
This release includes many translation updates, fixes for Let's Encrypt support, UI cleanups, and most importantly a new major version of the Authentic theme.
|
||||
|
||||
#### Version 1.860 (October 10, 2017)
|
||||
@@ -528,7 +558,7 @@ This release includes Let's Encrypt DNS fixes, Majordomo module improvements, XS
|
||||
#### Version 1.850 (June 28, 2017)
|
||||
This release includes Let's Encrypt fixes, Majordomo module improvements, FirewallD forwarding support, translation updates, an update to the Authentic theme, and a bunch of other bugfixes.
|
||||
|
||||
#### Version 1.840 (May 08, 2017)
|
||||
#### Version 1.840 (May 8, 2017)
|
||||
This major release includes a large theme update, XSS security fixes, per-domain SSL cert support, thin-provisioned LVM support, Let's Encrypt improvements, translation updates, and the usual gang of bugfixes. Also available is Usermin 1.710, which contains many of the same updates.
|
||||
|
||||
#### Version 1.830 (December 29, 2016)
|
||||
|
||||
File diff suppressed because one or more lines are too long
63
fastrpc.cgi
63
fastrpc.cgi
@@ -78,7 +78,7 @@ if ($use_ipv6) {
|
||||
}
|
||||
$sel = select($rmask, undef, undef, $config_rpc_timeout);
|
||||
if ($sel <= 0) {
|
||||
print STDERR "fastrpc: accept timed out\n"
|
||||
print STDERR "fastrpc[$$]: accept timed out\n"
|
||||
if ($gconfig{'rpcdebug'});
|
||||
exit;
|
||||
}
|
||||
@@ -115,8 +115,15 @@ while(1) {
|
||||
if ($sel <= 0) {
|
||||
# Don't kill the control session while a tcpwrite/tcpread is
|
||||
# running
|
||||
next if (keys %xfer_kids);
|
||||
print STDERR "fastrpc: session timed out\n"
|
||||
my $nk = scalar(keys %xfer_kids);
|
||||
if ($nk) {
|
||||
print STDERR "fastrpc[$$]: idle timeout, but $nk ".
|
||||
"transfer(s) active: ".
|
||||
join(",", sort keys %xfer_kids)."\n"
|
||||
if ($gconfig{'rpcdebug'});
|
||||
next;
|
||||
}
|
||||
print STDERR "fastrpc[$$]: session timed out\n"
|
||||
if ($gconfig{'rpcdebug'});
|
||||
last;
|
||||
}
|
||||
@@ -132,7 +139,7 @@ while(1) {
|
||||
exit if ($rv <= 0);
|
||||
$rawarg .= $got;
|
||||
}
|
||||
print STDERR "fastrpc: raw $rawarg\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: raw $rawarg\n" if ($gconfig{'rpcdebug'});
|
||||
my $dumper = substr($rawarg, 0, 5) eq '$VAR1' ? 1 : 0;
|
||||
my $arg = &unserialise_variable($rawarg);
|
||||
|
||||
@@ -140,19 +147,19 @@ while(1) {
|
||||
my $rv;
|
||||
if ($arg->{'action'} eq 'ping') {
|
||||
# Just respond with an OK
|
||||
print STDERR "fastrpc: ping\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: ping\n" if ($gconfig{'rpcdebug'});
|
||||
$rv = { 'status' => 1 };
|
||||
}
|
||||
elsif ($arg->{'action'} eq 'check') {
|
||||
# Check if some module is supported
|
||||
print STDERR "fastrpc: check $arg->{'module'}\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: check $arg->{'module'}\n" if ($gconfig{'rpcdebug'});
|
||||
$rv = { 'status' => 1,
|
||||
'rv' => &foreign_check($arg->{'module'}, undef, undef,
|
||||
$arg->{'api'}) };
|
||||
}
|
||||
elsif ($arg->{'action'} eq 'config') {
|
||||
# Get the config for some module
|
||||
print STDERR "fastrpc: config $arg->{'module'}\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: config $arg->{'module'}\n" if ($gconfig{'rpcdebug'});
|
||||
my %config = &foreign_config($arg->{'module'});
|
||||
$rv = { 'status' => 1, 'rv' => \%config };
|
||||
}
|
||||
@@ -161,7 +168,7 @@ while(1) {
|
||||
my $file = $arg->{'file'} ? $arg->{'file'} :
|
||||
$arg->{'name'} ? &tempname($arg->{'name'}) :
|
||||
&tempname();
|
||||
print STDERR "fastrpc: write $file\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: write $file\n" if ($gconfig{'rpcdebug'});
|
||||
open(FILE, ">$file");
|
||||
binmode(FILE);
|
||||
print FILE $arg->{'data'};
|
||||
@@ -173,7 +180,7 @@ while(1) {
|
||||
my $file = $arg->{'file'} ? $arg->{'file'} :
|
||||
$arg->{'name'} ? &tempname($arg->{'name'}) :
|
||||
&tempname();
|
||||
print STDERR "fastrpc: tcpwrite $file\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: tcpwrite $file\n" if ($gconfig{'rpcdebug'});
|
||||
my $tsock = time().$$;
|
||||
my $tsock6 = $use_ipv6 ? time().$$."v6" : undef;
|
||||
my $tport = $port + 1;
|
||||
@@ -187,7 +194,7 @@ while(1) {
|
||||
close(MAIN);
|
||||
close(MAIN6) if ($use_ipv6);
|
||||
# Accept connection in separate process
|
||||
print STDERR "fastrpc: tcpwrite $file port $tport\n"
|
||||
print STDERR "fastrpc[$$]: tcpwrite $file port $tport\n"
|
||||
if ($gconfig{'rpcdebug'});
|
||||
my $rmask;
|
||||
vec($rmask, fileno($tsock), 1) = 1;
|
||||
@@ -202,12 +209,12 @@ while(1) {
|
||||
elsif ($use_ipv6 && vec($rmask, fileno($tsock6), 1)) {
|
||||
accept(TRANS, $tsock6) || exit;
|
||||
}
|
||||
print STDERR "fastrpc: tcpwrite $file accepted\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: tcpwrite $file accepted\n" if ($gconfig{'rpcdebug'});
|
||||
my $buf;
|
||||
my $err;
|
||||
if (open(FILE, ">$file")) {
|
||||
binmode(FILE);
|
||||
print STDERR "fastrpc: tcpwrite $file writing\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: tcpwrite $file writing\n" if ($gconfig{'rpcdebug'});
|
||||
my $bs = &get_buffer_size();
|
||||
while(read(TRANS, $buf, $bs) > 0) {
|
||||
my $ok = (print FILE $buf);
|
||||
@@ -217,10 +224,10 @@ while(1) {
|
||||
}
|
||||
}
|
||||
close(FILE);
|
||||
print STDERR "fastrpc: tcpwrite $file written\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: tcpwrite $file written\n" if ($gconfig{'rpcdebug'});
|
||||
}
|
||||
else {
|
||||
print STDERR "fastrpc: tcpwrite $file open failed $!\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: tcpwrite $file open failed $!\n" if ($gconfig{'rpcdebug'});
|
||||
$err = "Failed to open $file : $!";
|
||||
}
|
||||
print TRANS $err ? "$err\n" : "OK\n";
|
||||
@@ -229,7 +236,7 @@ while(1) {
|
||||
}
|
||||
else {
|
||||
$xfer_kids{$cpid} = 1;
|
||||
print STDERR "fastrpc: tcpwrite $file started\n"
|
||||
print STDERR "fastrpc[$$]: tcpwrite $file started\n"
|
||||
if ($gconfig{'rpcdebug'});
|
||||
$rv = { 'status' => 1, 'rv' => [ $file, $tport ] };
|
||||
}
|
||||
@@ -238,7 +245,7 @@ while(1) {
|
||||
}
|
||||
elsif ($arg->{'action'} eq 'read') {
|
||||
# Transfer data from a file
|
||||
print STDERR "fastrpc: read $arg->{'file'}\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: read $arg->{'file'}\n" if ($gconfig{'rpcdebug'});
|
||||
my ($data, $got);
|
||||
open(FILE, "<$arg->{'file'}");
|
||||
binmode(FILE);
|
||||
@@ -251,7 +258,7 @@ while(1) {
|
||||
}
|
||||
elsif ($arg->{'action'} eq 'tcpread') {
|
||||
# Transfer data from a file over TCP connection
|
||||
print STDERR "fastrpc: tcpread $arg->{'file'}\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: tcpread $arg->{'file'}\n" if ($gconfig{'rpcdebug'});
|
||||
if (-d $arg->{'file'}) {
|
||||
$rv = { 'status' => 1, 'rv' => [ undef, "$arg->{'file'} is a directory" ] };
|
||||
}
|
||||
@@ -296,7 +303,7 @@ while(1) {
|
||||
}
|
||||
else {
|
||||
$xfer_kids{$cpid} = 1;
|
||||
print STDERR "fastrpc: tcpread $arg->{'file'} ".
|
||||
print STDERR "fastrpc[$$]: tcpread $arg->{'file'} ".
|
||||
"started\n"
|
||||
if ($gconfig{'rpcdebug'});
|
||||
$rv = { 'status' => 1,
|
||||
@@ -309,23 +316,23 @@ while(1) {
|
||||
}
|
||||
elsif ($arg->{'action'} eq 'require') {
|
||||
# require a library
|
||||
print STDERR "fastrpc: require $arg->{'module'}/$arg->{'file'}\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: require $arg->{'module'}/$arg->{'file'}\n" if ($gconfig{'rpcdebug'});
|
||||
eval {
|
||||
&foreign_require($arg->{'module'},
|
||||
$arg->{'file'});
|
||||
};
|
||||
if ($@) {
|
||||
print STDERR "fastrpc: require error $@\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: require error $@\n" if ($gconfig{'rpcdebug'});
|
||||
$rv = { 'status' => 0, 'rv' => $@ };
|
||||
}
|
||||
else {
|
||||
print STDERR "fastrpc: require done\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: require done\n" if ($gconfig{'rpcdebug'});
|
||||
$rv = { 'status' => 1 };
|
||||
}
|
||||
}
|
||||
elsif ($arg->{'action'} eq 'call') {
|
||||
# execute a function
|
||||
print STDERR "fastrpc: call $arg->{'module'}::$arg->{'func'}(",join(",", @{$arg->{'args'}}),")\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: call $arg->{'module'}::$arg->{'func'}(",join(",", @{$arg->{'args'}}),")\n" if ($gconfig{'rpcdebug'});
|
||||
my @rv;
|
||||
eval {
|
||||
local $main::error_must_die = 1;
|
||||
@@ -334,7 +341,7 @@ while(1) {
|
||||
@{$arg->{'args'}});
|
||||
};
|
||||
if ($@) {
|
||||
print STDERR "fastrpc: call error $@\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: call error $@\n" if ($gconfig{'rpcdebug'});
|
||||
$rv = { 'status' => 0, 'rv' => $@ };
|
||||
}
|
||||
elsif (@rv == 1) {
|
||||
@@ -343,11 +350,11 @@ while(1) {
|
||||
else {
|
||||
$rv = { 'status' => 1, 'arv' => \@rv };
|
||||
}
|
||||
print STDERR "fastrpc: call $arg->{'module'}::$arg->{'func'} done = ",join(",", @rv),"\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: call $arg->{'module'}::$arg->{'func'} done = ",join(",", @rv),"\n" if ($gconfig{'rpcdebug'});
|
||||
}
|
||||
elsif ($arg->{'action'} eq 'eval') {
|
||||
# eval some perl code
|
||||
print STDERR "fastrpc: eval $arg->{'module'} $arg->{'code'}\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: eval $arg->{'module'} $arg->{'code'}\n" if ($gconfig{'rpcdebug'});
|
||||
my $erv;
|
||||
if ($arg->{'module'}) {
|
||||
my $pkg = $arg->{'module'};
|
||||
@@ -358,7 +365,7 @@ while(1) {
|
||||
else {
|
||||
$erv = eval $arg->{'code'};
|
||||
}
|
||||
print STDERR "fastrpc: eval $arg->{'module'} $arg->{'code'} done = $rv error = $@\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: eval $arg->{'module'} $arg->{'code'} done = $rv error = $@\n" if ($gconfig{'rpcdebug'});
|
||||
if ($@) {
|
||||
$rv = { 'status' => 0, 'rv' => $@ };
|
||||
}
|
||||
@@ -367,11 +374,11 @@ while(1) {
|
||||
}
|
||||
}
|
||||
elsif ($arg->{'action'} eq 'quit') {
|
||||
print STDERR "fastrpc: quit\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: quit\n" if ($gconfig{'rpcdebug'});
|
||||
$rv = { 'status' => 1 };
|
||||
}
|
||||
else {
|
||||
print STDERR "fastrpc: unknown $arg->{'action'}\n" if ($gconfig{'rpcdebug'});
|
||||
print STDERR "fastrpc[$$]: unknown $arg->{'action'}\n" if ($gconfig{'rpcdebug'});
|
||||
$rv = { 'status' => 0 };
|
||||
}
|
||||
$rawrv = &serialise_variable($rv, $dumper);
|
||||
|
||||
@@ -344,7 +344,7 @@ foreach $c (@$conf) {
|
||||
}
|
||||
print TEMP map { "$_\n" } &directive_lines($_[0]);
|
||||
close(TEMP);
|
||||
&set_ownership_permissions(undef, undef, 0700, $temp);
|
||||
&set_ownership_permissions(undef, undef, 0644, $temp);
|
||||
local $out = &backquote_logged("$config{'logrotate'} -f $temp 2>&1");
|
||||
return ($?, $out);
|
||||
}
|
||||
|
||||
@@ -885,7 +885,7 @@ root_epass1=No new password entered
|
||||
root_epass2=Passwords do not match
|
||||
root_none=No password!
|
||||
root_auto=Automatic (typically <tt>root</tt>)
|
||||
root_socket=The MySQL <tt>$1</tt> user is using Unix socket authentication, so no password is needed and the password cannot be changed.
|
||||
root_socket=The MySQL <tt>$1</tt> user uses Unix socket authentication, so no password is needed. However, you can switch to password authentication on the <a href='list_users.cgi'>User Permissions</a> page.
|
||||
|
||||
mysqlpass_err=MySQL safe mode
|
||||
mysqlpass_esafecmd=The command $1 needed to start MySQL with authentication disabled was not found
|
||||
|
||||
@@ -2248,7 +2248,7 @@ return $rv->{'data'}->[0]->[0] =~ /unix_socket/i ? 'socket' : 'password';
|
||||
sub list_authentication_plugins
|
||||
{
|
||||
my ($ver, $variant) = &get_remote_mysql_variant();
|
||||
if ($variant eq "mariadb" && &compare_version_numbers($ver, "10.4") >= 0 ||
|
||||
if ($variant eq "mariadb" && &compare_version_numbers($ver, "10.3") >= 0 ||
|
||||
$variant eq "mysql" && &compare_version_numbers($ver, "5.7.6") >= 0) {
|
||||
my $rv = &execute_sql($master_db, "show plugins");
|
||||
my @plugins = map { $_->[0] } grep { $_->[1] eq 'ACTIVE' &&
|
||||
|
||||
@@ -61,8 +61,7 @@ if (&foreign_installed("package-updates")) {
|
||||
my @allpkgs = &extend_installable_php_packages(\@newpkgs);
|
||||
@allpkgs = sort { $b->{'ver'} cmp $a->{'ver'} } @allpkgs;
|
||||
print &ui_select("u", undef,
|
||||
[ map { [ $_->{'name'},
|
||||
"PHP $_->{'ver'}" ] } @allpkgs ]);
|
||||
[ map { [ $_->{'name'}, "PHP $_->{'ver'}" ] } @allpkgs ]);
|
||||
print &ui_hidden(
|
||||
"redir", &get_webprefix()."/$module_name/list_pkgs.cgi");
|
||||
print &ui_hidden("redirdesc", $text{'pkgs_title'});
|
||||
|
||||
@@ -1047,7 +1047,8 @@ my @pkgs;
|
||||
my @extra = ('cli', 'fpm');
|
||||
foreach my $pkg (@{$pkgs}) {
|
||||
my $p = { 'name' => $pkg->{'name'},
|
||||
'ver' => $pkg->{'shortver'} };
|
||||
'shortver' => $pkg->{'shortver'},
|
||||
'ver' => $pkg->{'ver'} };
|
||||
$p->{'name'} .= ' '.join(' ', map { "$1-$_" } @extra)
|
||||
if ($p->{'name'} =~ /^(.*)-common$/);
|
||||
push(@pkgs, $p);
|
||||
|
||||
@@ -388,6 +388,58 @@ $str =~ s/["'<>&\\]/sprintf('\x%02x', ord $&)/ge;
|
||||
return $str;
|
||||
}
|
||||
|
||||
=head2 tempname_dir_sys()
|
||||
|
||||
Returns a shared base directory for system-wide temporary files. This directory
|
||||
does not depend on the current user. The directory is chosen once per process
|
||||
and verified by creating a temporary probe file.
|
||||
|
||||
The result is cached for the lifetime of the current Perl process.
|
||||
|
||||
=cut
|
||||
sub tempname_dir_sys
|
||||
{
|
||||
# Cache per module
|
||||
state %base;
|
||||
my @can_dirs;
|
||||
|
||||
# Return cached value if already determined
|
||||
my $mod = &get_module_name() || '';
|
||||
return $base{$mod} if (defined $base{$mod});
|
||||
|
||||
# Check configured system temp dirs (module override first)
|
||||
my $modk = $mod ? "tempdir_sys_$mod" : undef;
|
||||
push(@can_dirs, $gconfig{$modk}) if ($modk && $gconfig{$modk});
|
||||
push(@can_dirs, $gconfig{'tempdir_sys'}) if ($gconfig{'tempdir_sys'});
|
||||
|
||||
# Common fallbacks
|
||||
push(@can_dirs, "/dev/shm", "/tmp", "/var/tmp", "/usr/tmp");
|
||||
|
||||
# Remove empty and duplicate entries, which can happen when both configured
|
||||
# dirs are set to the same path, or when a configured path matches one of
|
||||
# the built-in defaults
|
||||
@can_dirs = &unique(grep { $_ } @can_dirs);
|
||||
|
||||
# Test each candidate in turn
|
||||
for my $dir (@can_dirs) {
|
||||
next if (!-d $dir);
|
||||
next if (!-w $dir);
|
||||
|
||||
# Confirm we can actually create a file
|
||||
my $tmp = "$dir/.webmin_${$}_".int(rand(1e16));
|
||||
if (open(my $fh, ">", $tmp)) {
|
||||
close($fh);
|
||||
unlink($tmp);
|
||||
$base{$mod} = $dir; # Success, cache and return
|
||||
return $base{$mod};
|
||||
}
|
||||
}
|
||||
|
||||
my $keys = ($modk && $gconfig{$modk}) ? "$modk or tempdir_sys" : "tempdir_sys";
|
||||
&error("No usable system temp directory found. Set $keys to a writable ".
|
||||
"directory in $config_directory/config and try again.");
|
||||
}
|
||||
|
||||
=head2 tempname_dir()
|
||||
|
||||
Returns the base directory under which temp files can be created.
|
||||
@@ -8542,8 +8594,19 @@ else {
|
||||
open(FILE, "<".$localfile) ||
|
||||
return &$main::remote_error_handler("Failed to open $localfile : $!");
|
||||
my $bs = &get_buffer_size();
|
||||
my $last_ping = time();
|
||||
my $ping_every = int(($gconfig{'rpc_timeout'} || 60) / 2);
|
||||
$ping_every = 30 if ($ping_every < 30);
|
||||
while(read(FILE, $got, $bs) > 0) {
|
||||
print TWRITE $got;
|
||||
if (time() - $last_ping >= $ping_every) {
|
||||
eval {
|
||||
local $main::remote_error_handler =
|
||||
sub { return undef; };
|
||||
&remote_rpc_call($host, { 'action' => 'ping' });
|
||||
};
|
||||
$last_ping = time();
|
||||
}
|
||||
}
|
||||
close(FILE);
|
||||
shutdown(TWRITE, 1);
|
||||
@@ -8587,8 +8650,19 @@ else {
|
||||
open(FILE, ">$localfile") ||
|
||||
return &$main::remote_error_handler("Failed to open $localfile : $!");
|
||||
my $bs = &get_buffer_size();
|
||||
my $last_ping = time();
|
||||
my $ping_every = int(($gconfig{'rpc_timeout'} || 60) / 2);
|
||||
$ping_every = 30 if ($ping_every < 30);
|
||||
while(read(TREAD, $got, $bs) > 0) {
|
||||
print FILE $got;
|
||||
if (time() - $last_ping >= $ping_every) {
|
||||
eval {
|
||||
local $main::remote_error_handler =
|
||||
sub { return undef; };
|
||||
&remote_rpc_call($host, { 'action' => 'ping' });
|
||||
};
|
||||
$last_ping = time();
|
||||
}
|
||||
}
|
||||
close(FILE);
|
||||
close(TREAD);
|
||||
@@ -10847,7 +10921,7 @@ else {
|
||||
&webmin_debug_log($1 eq ">" ? "WRITE" :
|
||||
$1 eq ">>" ? "APPEND" : "READ", "nul") if ($db);
|
||||
}
|
||||
elsif ($file =~ /^(>|>>)(\/dev\/.*)/ || lc($file) eq "nul") {
|
||||
elsif ($file =~ /^(>|>>)(\/dev\/(?!shm\/).*)/ || lc($file) eq "nul") {
|
||||
# Writes to /dev/null or TTYs don't need to be handled
|
||||
&webmin_debug_log($1 eq ">" ? "WRITE" : "APPEND", $2) if ($db);
|
||||
return open($fh, "<".$file);
|
||||
@@ -13997,8 +14071,7 @@ return $dir;
|
||||
}
|
||||
|
||||
# allocate_miniserv_websocket([module], [base-remote-user])
|
||||
# Allocate a new websocket and
|
||||
# stores it miniserv.conf file
|
||||
# Allocate a new websocket and stores it miniserv.conf file
|
||||
sub allocate_miniserv_websocket
|
||||
{
|
||||
my ($module, $buser) = @_;
|
||||
|
||||
@@ -46,7 +46,6 @@ my $termlinks =
|
||||
'js' => ["xterm.js?$wver",
|
||||
"xterm-addon-attach.js?$wver",
|
||||
"xterm-addon-fit.js?$wver",
|
||||
"xterm-addon-canvas.js?$wver",
|
||||
"xterm-addon-webgl.js?$wver"] };
|
||||
|
||||
# Pre-process options
|
||||
@@ -77,6 +76,7 @@ if ($conf_cols_n && $conf_rows_n && !$xmlhr) {
|
||||
my $conf_screen_reader = $config{'screen_reader'} eq 'true' ? 'true' : 'false';
|
||||
$termjs_opts{'Options'} = "{ cols: $env_cols, rows: $env_rows, ".
|
||||
"screenReaderMode: $conf_screen_reader, ".
|
||||
"overviewRuler: { width: 9 }, ".
|
||||
"fontSize: $font_size }";
|
||||
|
||||
my $term_size = "
|
||||
@@ -212,8 +212,7 @@ $ENV{'SESSION_ID'} = $main::session_id;
|
||||
|
||||
# Open the terminal
|
||||
my $url = &get_miniserv_websocket_url($port, $config{'host'}, $module_name);
|
||||
my $canvasAddon = $termlinks->{'js'}[3];
|
||||
my $webGLAddon = $termlinks->{'js'}[4];
|
||||
my $webGLAddon = $termlinks->{'js'}[3];
|
||||
my $term_script = <<EOF;
|
||||
|
||||
(function() {
|
||||
@@ -222,11 +221,10 @@ my $term_script = <<EOF;
|
||||
err_conn_cannot = 'Cannot connect to the socket $url',
|
||||
err_conn_lost = 'Connection to the socket $url lost',
|
||||
webGLAddonLink = '$webGLAddon',
|
||||
canvasAddonLink = '$canvasAddon',
|
||||
detectWebGLContext = (function() {
|
||||
const canvas = document.createElement("canvas"),
|
||||
gl = canvas.getContext("webgl") ||
|
||||
canvas.getContext("experimental-webgl");
|
||||
gl = canvas.getContext("webgl") ||
|
||||
canvas.getContext("experimental-webgl");
|
||||
return gl instanceof WebGLRenderingContext ? true : false;
|
||||
})();
|
||||
socket.onopen = function() {
|
||||
@@ -234,27 +232,31 @@ my $term_script = <<EOF;
|
||||
attachAddon = new AttachAddon.AttachAddon(this),
|
||||
fitAddon = new FitAddon.FitAddon(),
|
||||
renderScript = document.createElement('script');
|
||||
renderScript.src = detectWebGLContext ? webGLAddonLink : canvasAddonLink;
|
||||
|
||||
renderScript.src = webGLAddonLink;
|
||||
renderScript.async = false;
|
||||
document.body.appendChild(renderScript);
|
||||
|
||||
// Wait to load requested render addon
|
||||
renderScript.addEventListener('load', function() {
|
||||
const rendererAddon = detectWebGLContext ?
|
||||
new WebglAddon.WebglAddon() :
|
||||
new CanvasAddon.CanvasAddon();
|
||||
let rendererAddon;
|
||||
|
||||
if (detectWebGLContext && typeof WebglAddon === 'object') {
|
||||
rendererAddon = new WebglAddon.WebglAddon();
|
||||
term.loadAddon(rendererAddon);
|
||||
|
||||
// Handle case of dropping WebGL context
|
||||
if (rendererAddon.onContextLoss) {
|
||||
rendererAddon.onContextLoss(function() {
|
||||
rendererAddon.dispose();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
term.loadAddon(attachAddon);
|
||||
term.loadAddon(fitAddon);
|
||||
term.loadAddon(rendererAddon);
|
||||
term.open(termcont);
|
||||
setTimeout(function() {term.focus()}, 6e2);
|
||||
|
||||
// Handle case of dropping WebGL context
|
||||
if (typeof WebglAddon === 'object') {
|
||||
rendererAddon.onContextLoss(function() {
|
||||
rendererAddon.dispose();
|
||||
});
|
||||
}
|
||||
setTimeout(function() { term.focus() }, 6e2);
|
||||
|
||||
// On resize event triggered by fit()
|
||||
term.onResize(function(e) {
|
||||
|
||||
@@ -114,6 +114,7 @@ my $server_socket = IO::Socket::INET->new(
|
||||
ReuseAddr => 1,
|
||||
);
|
||||
$server_socket || die "failed to listen on port $port";
|
||||
our $connected = 0;
|
||||
Net::WebSocket::Server->new(
|
||||
listen => $server_socket,
|
||||
on_connect => sub {
|
||||
@@ -129,6 +130,7 @@ Net::WebSocket::Server->new(
|
||||
$conn->on(
|
||||
handshake => sub {
|
||||
# Is the key valid for this Webmin session?
|
||||
&error_stderr("WebSocket handshake received");
|
||||
my ($conn, $handshake) = @_;
|
||||
my $key = $handshake->req->fields->{'sec-websocket-key'};
|
||||
my $dsess = &encode_base64($main::session_id);
|
||||
@@ -138,13 +140,18 @@ Net::WebSocket::Server->new(
|
||||
&error_stderr("Key $key does not match session ID $dsess");
|
||||
$conn->disconnect();
|
||||
}
|
||||
else {
|
||||
$connected = 1;
|
||||
}
|
||||
},
|
||||
ready => sub {
|
||||
my ($conn) = @_;
|
||||
$connected || die "Not connected yet in ready";
|
||||
$conn->send_binary($shellbuf) if ($shellbuf);
|
||||
},
|
||||
utf8 => sub {
|
||||
my ($conn, $msg) = @_;
|
||||
$connected || die "Not connected yet in utf8";
|
||||
utf8::encode($msg) if (utf8::is_utf8($msg));
|
||||
# Check for resize escape sequence explicitly
|
||||
if ($msg =~ /^\\033\[8;\((\d+)\);\((\d+)\)t$/) {
|
||||
@@ -168,6 +175,7 @@ Net::WebSocket::Server->new(
|
||||
}
|
||||
},
|
||||
disconnect => sub {
|
||||
$connected = 0;
|
||||
&error_stderr("WebSocket connection closed");
|
||||
&remove_miniserv_websocket($port, $module_name);
|
||||
kill('KILL', $pid) if ($pid);
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
// 0.11.0
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.AttachAddon=t():e.AttachAddon=t()}(self,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;function s(e,t,s){return e.addEventListener(t,s),{dispose:()=>{s&&e.removeEventListener(t,s)}}}Object.defineProperty(t,"__esModule",{value:!0}),t.AttachAddon=void 0,t.AttachAddon=class{constructor(e,t){this._disposables=[],this._socket=e,this._socket.binaryType="arraybuffer",this._bidirectional=!(t&&!1===t.bidirectional)}activate(e){this._disposables.push(s(this._socket,"message",(t=>{const s=t.data;e.write("string"==typeof s?s:new Uint8Array(s))}))),this._bidirectional&&(this._disposables.push(e.onData((e=>this._sendData(e)))),this._disposables.push(e.onBinary((e=>this._sendBinary(e))))),this._disposables.push(s(this._socket,"close",(()=>this.dispose()))),this._disposables.push(s(this._socket,"error",(()=>this.dispose())))}dispose(){for(const e of this._disposables)e.dispose()}_sendData(e){this._checkOpenSocket()&&this._socket.send(e)}_sendBinary(e){if(!this._checkOpenSocket())return;const t=new Uint8Array(e.length);for(let s=0;s<e.length;++s)t[s]=255&e.charCodeAt(s);this._socket.send(t)}_checkOpenSocket(){switch(this._socket.readyState){case WebSocket.OPEN:return!0;case WebSocket.CONNECTING:throw new Error("Attach addon was loaded before socket was open");case WebSocket.CLOSING:return console.warn("Attach addon socket is closing"),!1;case WebSocket.CLOSED:throw new Error("Attach addon socket is closed");default:throw new Error("Unexpected socket state")}}}})(),e})()));
|
||||
// 0.12.0
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.AttachAddon=t():e.AttachAddon=t()}(globalThis,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;function s(e,t,s){return e.addEventListener(t,s),{dispose:()=>{s&&e.removeEventListener(t,s)}}}Object.defineProperty(t,"__esModule",{value:!0}),t.AttachAddon=void 0,t.AttachAddon=class{constructor(e,t){this._disposables=[],this._socket=e,this._socket.binaryType="arraybuffer",this._bidirectional=!(t&&!1===t.bidirectional)}activate(e){this._disposables.push(s(this._socket,"message",(t=>{const s=t.data;e.write("string"==typeof s?s:new Uint8Array(s))}))),this._bidirectional&&(this._disposables.push(e.onData((e=>this._sendData(e)))),this._disposables.push(e.onBinary((e=>this._sendBinary(e))))),this._disposables.push(s(this._socket,"close",(()=>this.dispose()))),this._disposables.push(s(this._socket,"error",(()=>this.dispose())))}dispose(){for(const e of this._disposables)e.dispose()}_sendData(e){this._checkOpenSocket()&&this._socket.send(e)}_sendBinary(e){if(!this._checkOpenSocket())return;const t=new Uint8Array(e.length);for(let s=0;s<e.length;++s)t[s]=255&e.charCodeAt(s);this._socket.send(t)}_checkOpenSocket(){switch(this._socket.readyState){case WebSocket.OPEN:return!0;case WebSocket.CONNECTING:throw new Error("Attach addon was loaded before socket was open");case WebSocket.CLOSING:return console.warn("Attach addon socket is closing"),!1;case WebSocket.CLOSED:throw new Error("Attach addon socket is closed");default:throw new Error("Unexpected socket state")}}}})(),e})()));
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,2 +1,2 @@
|
||||
// 0.10.0
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(self,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0,t.FitAddon=class{activate(e){this._terminal=e}dispose(){}fit(){const e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;const t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal)return;if(!this._terminal.element||!this._terminal.element.parentElement)return;const e=this._terminal._core,t=e._renderService.dimensions;if(0===t.css.cell.width||0===t.css.cell.height)return;const r=0===this._terminal.options.scrollback?0:e.viewport.scrollBarWidth,i=window.getComputedStyle(this._terminal.element.parentElement),o=parseInt(i.getPropertyValue("height")),s=Math.max(0,parseInt(i.getPropertyValue("width"))),n=window.getComputedStyle(this._terminal.element),l=o-(parseInt(n.getPropertyValue("padding-top"))+parseInt(n.getPropertyValue("padding-bottom"))),a=s-(parseInt(n.getPropertyValue("padding-right"))+parseInt(n.getPropertyValue("padding-left")))-r;return{cols:Math.max(2,Math.floor(a/t.css.cell.width)),rows:Math.max(1,Math.floor(l/t.css.cell.height))}}}})(),e})()));
|
||||
// 0.11.0
|
||||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FitAddon=t():e.FitAddon=t()}(globalThis,(()=>(()=>{"use strict";var e={};return(()=>{var t=e;Object.defineProperty(t,"__esModule",{value:!0}),t.FitAddon=void 0,t.FitAddon=class{activate(e){this._terminal=e}dispose(){}fit(){const e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;const t=this._terminal._core;this._terminal.rows===e.rows&&this._terminal.cols===e.cols||(t._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal)return;if(!this._terminal.element||!this._terminal.element.parentElement)return;const e=this._terminal._core._renderService.dimensions;if(0===e.css.cell.width||0===e.css.cell.height)return;const t=0===this._terminal.options.scrollback?0:this._terminal.options.overviewRuler?.width||14,r=window.getComputedStyle(this._terminal.element.parentElement),i=parseInt(r.getPropertyValue("height")),o=Math.max(0,parseInt(r.getPropertyValue("width"))),s=window.getComputedStyle(this._terminal.element),n=i-(parseInt(s.getPropertyValue("padding-top"))+parseInt(s.getPropertyValue("padding-bottom"))),l=o-(parseInt(s.getPropertyValue("padding-right"))+parseInt(s.getPropertyValue("padding-left")))-t;return{cols:Math.max(2,Math.floor(l/e.css.cell.width)),rows:Math.max(1,Math.floor(n/e.css.cell.height))}}}})(),e})()));
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,8 +1,10 @@
|
||||
/*!
|
||||
* Xterm.js v5.5.0 (https://github.com/xtermjs/xterm.js)
|
||||
* Copyright (c) 2017-2023, The xterm.js authors (https://github.com/xtermjs/xterm.js)
|
||||
* Xterm.js v6.0.0 (https://github.com/xtermjs/xterm.js)
|
||||
* Copyright (c) 2017-2026, The xterm.js authors (https://github.com/xtermjs/xterm.js)
|
||||
* Copyright (c) 2014-2016, SourceLair Private Company (https://www.sourcelair.com)
|
||||
* Copyright (c) 2012-2013, Christopher Jeffrey (https://github.com/chjj/)
|
||||
* Licensed under MIT (https://github.com/xtermjs/xterm.js/blob/master/LICENSE)
|
||||
*/
|
||||
.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#FFF;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}
|
||||
.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none;}.xterm.focus,.xterm:focus{outline:none;}.xterm .xterm-helpers{position:absolute;top:0;z-index:5;}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none;}.xterm .composition-view{background:#000;color:#FFF;display:none;position:absolute;white-space:nowrap;z-index:1;}.xterm .composition-view.active{display:block;}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0;}.xterm .xterm-screen{position:relative;}.xterm .xterm-screen canvas{position:absolute;left:0;top:0;}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal;}.xterm.enable-mouse-events{cursor:default;}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer;}.xterm.column-select.focus{cursor:crosshair;}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none;}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent;}.xterm .xterm-accessibility-tree{font-family:monospace;user-select:text;white-space:pre;}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content;}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;}.xterm-dim{opacity:1!important;}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline;}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through;}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute;}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7;}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none;}.xterm-decoration-top{z-index:2;position:relative;}.xterm .xterm-scrollable-element>.scrollbar{cursor:default;}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important;}.xterm .xterm-scrollable-element>.visible{opacity:1;background:rgba(0,0,0,0);transition:opacity 100ms linear;z-index:11;}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none;}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity 800ms linear;}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none;}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px;}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;}
|
||||
/* custom */
|
||||
.xterm .xterm-decoration-overview-ruler { display: none; }
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user