#!/usr/local/bin/perl # Show a terminal that is connected to a Websockets server via Webmin proxying # XXX don't grant to new users # XXX Virtualmin integration? require './xterm-lib.pl'; &ReadParse(); # Get Webmin current version for links serial my $wver = &get_webmin_version(); $wver =~ s/\.//; # Build Xterm dependency links my $termlinks = { 'css' => ['xterm.css?$wver'], 'js' => ['xterm.js?$wver', 'xterm-addon-attach.js?$wver'] }; # Pre-process options my ($conf_size_str, $def_cols_n, $def_rows_n, $rcvd_cnt_w, $rcvd_cnt_h, $rcvd_or_def_col_w, $rcvd_or_def_row_h, $rcvd_or_def_col_o, $rcvd_or_def_row_o, $resize_call, $xmlhr, %termjs_opts ) = ($config{'size'}, 80, 24, int($ENV{'HTTP_X_AGENT_WIDTH'}) || int($in{'w'}), int($ENV{'HTTP_X_AGENT_HEIGHT'}) || int($in{'h'}), int($in{'f'}) || 9, int($in{'l'}) || 18, int($in{'g'}) || 1, int($in{'o'}) || 0, int($in{'r'}), $ENV{'HTTP_X_REQUESTED_WITH'} eq "XMLHttpRequest"); # Parse module config my ($conf_cols_n, $conf_rows_n) = ($conf_size_str =~ /([\d]+)X([\d]+)/i); $conf_cols_n = int($conf_cols_n); $conf_rows_n = int($conf_rows_n); if ($conf_cols_n && $conf_rows_n) { $termjs_opts{'ContainerStyle'} = "style='width: fit-content; margin: 0 auto;'"; } else { $termjs_opts{'ContainerStyle'} = "style='height: 97%;'"; } # Set default container size in fixel depending on the mode my $calc_cols_abs = ($rcvd_cnt_w || int($conf_cols_n * $rcvd_or_def_col_w) || 720) . "px"; my $calc_rows_abs = ($rcvd_cnt_h || int($conf_rows_n * $rcvd_or_def_row_h) || 432) . "px"; $calc_cols_abs = "auto" if (!$conf_cols_n); $calc_rows_abs = "88vh" if (!$conf_rows_n); # Set pixel to columns conversion my $cols_num_user = int($rcvd_cnt_w / $rcvd_or_def_col_w); # Set pixel to rows (lines) conversion my $rows_num_user = int($rcvd_cnt_h / $rcvd_or_def_row_h); # Set columns and rows environment vars my $env_cols = $ENV{'COLUMNS'} = $conf_cols_n || $cols_num_user || $def_cols_n; my $env_rows = $ENV{'LINES'} = $conf_rows_n || $rows_num_user || $def_rows_n; # Define columns and rows $termjs_opts{'Options'} = "{ cols: $env_cols, rows: $env_rows }"; # Adjust columns and rows offset for env vars, which # should be always a tiny bit smaller than Xterm.js $ENV{'COLUMNS'} -= $rcvd_or_def_col_o; $ENV{'LINES'} -= $rcvd_or_def_row_o; # Tweak old themes inline my $styles_inline = <{'css'}[0]\">\n". "\n". "\n". "\n" ); # Print main container print "
\n"; # Set column size depending on the browser window # size unless defined in config (non-auto mode) if (!$conf_cols_n && !$conf_rows_n) { if ((!$rcvd_cnt_w || !$rcvd_cnt_h) || $resize_call) { print ""; return; } } # Clear URL to make sure resized and # reloaded page will work properly print ""; # Check for needed modules my $modname = "Net::WebSocket::Server"; eval "use ${modname};"; if ($@) { print &text('index_cpan', "$modname", "../cpan/download.cgi?source=3&cpan=$modname&mode=2&return=/$module_name/&returndesc=".&urlize($module_info{'desc'})),"

\n"; &ui_print_footer("/", $text{'index'}); return; } # Pick a port and configure Webmin to proxy it my $port = $config{'base_port'} || 555; while(1) { &open_socket("127.0.0.1", $port, my $fh, \$err); last if ($err); close($fh); $port++; } my %miniserv; &get_miniserv_config(\%miniserv); my $wspath = "/$module_name/ws-".$port; $miniserv{'websockets_'.$wspath} = "host=127.0.0.1 port=$port wspath=/ user=$remote_user"; &put_miniserv_config(\%miniserv); &reload_miniserv(); # Launch the shell server on that port &foreign_require("cron"); my $shellserver_cmd = "$module_config_directory/shellserver.pl"; if (!-r $shellserver_cmd) { &cron::create_wrapper($shellserver_cmd, $module_name, "shellserver.pl"); } my $user = $access{'user'}; if ($user eq "*") { $user = $remote_user; } defined(getpwnam($user)) || &error(&text('index_euser', $user)); my $tmpdir = &tempname_dir(); $ENV{'SESSION_ID'} = $main::session_id; &system_logged("$shellserver_cmd $port $user >$tmpdir/ws-$port.out 2>&1 \n"; if ($xmlhr) { print "var xterm_argv = ". &convert_to_json( { 'files' => $termlinks, 'cols' => $env_cols, 'rows' => $env_rows, 'socket_url' => $url }); } else { print $term_script; } print "\n"; &ui_print_footer();