From 477b98d43d369d2e0f2c2a6f793a12fbc3ebab4a Mon Sep 17 00:00:00 2001 From: terrafrost Date: Wed, 6 Jul 2022 20:38:10 -0500 Subject: [PATCH] SSH2 / SFTP: unify logging and add a new mode - LOG_SIMPLE_REALTIME --- phpseclib/Net/SFTP.php | 94 ++++++++++++++++++++++++++---------------- phpseclib/Net/SSH2.php | 81 +++++++++++++++++++++++++----------- 2 files changed, 116 insertions(+), 59 deletions(-) diff --git a/phpseclib/Net/SFTP.php b/phpseclib/Net/SFTP.php index ec84cba3..d1c930b9 100644 --- a/phpseclib/Net/SFTP.php +++ b/phpseclib/Net/SFTP.php @@ -203,6 +203,39 @@ class SFTP extends SSH2 */ private $packet_log = []; + /** + * Real-time log file pointer + * + * @see self::_append_log() + * @var resource|closed-resource + */ + private $realtime_log_file; + + /** + * Real-time log file size + * + * @see self::_append_log() + * @var int + */ + private $realtime_log_size; + + /** + * Real-time log file wrap boolean + * + * @see self::_append_log() + * @var bool + */ + private $realtime_log_wrap; + + /** + * Current log size + * + * Should never exceed self::LOG_MAX_SIZE + * + * @var int + */ + private $log_size; + /** * Error information * @@ -3222,24 +3255,7 @@ class SFTP extends SSH2 if (defined('NET_SFTP_LOGGING')) { $packet_type = '-> ' . $this->packet_types[$type] . ' (' . round($stop - $start, 4) . 's)'; - if (NET_SFTP_LOGGING == self::LOG_REALTIME) { - switch (PHP_SAPI) { - case 'cli': - $start = $stop = "\r\n"; - break; - default: - $start = '
';
-                        $stop = '
'; - } - echo $start . $this->format_log([$data], [$packet_type]) . $stop; - @flush(); - @ob_flush(); - } else { - $this->packet_type_log[] = $packet_type; - if (NET_SFTP_LOGGING == self::LOG_COMPLEX) { - $this->packet_log[] = $data; - } - } + $this->append_log($packet_type, $data); } } @@ -3340,24 +3356,7 @@ class SFTP extends SSH2 if (defined('NET_SFTP_LOGGING')) { $packet_type = '<- ' . $this->packet_types[$this->packet_type] . ' (' . round($stop - $start, 4) . 's)'; - if (NET_SFTP_LOGGING == self::LOG_REALTIME) { - switch (PHP_SAPI) { - case 'cli': - $start = $stop = "\r\n"; - break; - default: - $start = '
';
-                        $stop = '
'; - } - echo $start . $this->format_log([$packet], [$packet_type]) . $stop; - @flush(); - @ob_flush(); - } else { - $this->packet_type_log[] = $packet_type; - if (NET_SFTP_LOGGING == self::LOG_COMPLEX) { - $this->packet_log[] = $packet; - } - } + $this->append_log($packet_type, $packet); } if (isset($request_id) && $this->use_request_id && $packet_id != $request_id) { @@ -3371,6 +3370,29 @@ class SFTP extends SSH2 return $packet; } + /** + * Logs data packets + * + * Makes sure that only the last 1MB worth of packets will be logged + * + * @param string $message_number + * @param string $message + */ + private function append_log($message_number, $message) + { + $this->append_log_helper( + NET_SFTP_LOGGING, + $message_number, + $message, + $this->packet_type_log, + $this->packet_log, + $this->log_size, + $this->realtime_log_file, + $this->realtime_log_wrap, + $this->realtime_log_size + ); + } + /** * Returns a log of the packets that have been sent and received. * diff --git a/phpseclib/Net/SSH2.php b/phpseclib/Net/SSH2.php index 04bcb12e..d21c883c 100644 --- a/phpseclib/Net/SSH2.php +++ b/phpseclib/Net/SSH2.php @@ -139,16 +139,16 @@ class SSH2 const LOG_COMPLEX = 2; /** * Outputs the content real-time - * - * @see \phpseclib3\Net\SSH2::getLog() */ const LOG_REALTIME = 3; /** * Dumps the content real-time to a file - * - * @see \phpseclib3\Net\SSH2::getLog() */ const LOG_REALTIME_FILE = 4; + /** + * Outputs the message numbers real-time + */ + const LOG_SIMPLE_REALTIME = 5; /** * Make sure that the log never gets larger than this * @@ -792,6 +792,7 @@ class SSH2 * Real-time log file wrap boolean * * @see self::_append_log() + * @var bool */ private $realtime_log_wrap; @@ -4150,25 +4151,59 @@ class SSH2 * @param string $message */ private function append_log($message_number, $message) + { + $this->append_log_helper( + NET_SSH2_LOGGING, + $message_number, + $message, + $this->message_number_log, + $this->message_log, + $this->log_size, + $this->realtime_log_file, + $this->realtime_log_wrap, + $this->realtime_log_size + ); + } + + /** + * Logs data packet helper + * + * @param int $constant + * @param string $message_number + * @param string $message + * @param array &$message_number_log + * @param array &$message_log + * @param int &$log_size + * @param resource &$realtime_log_file + * @param bool &$realtime_log_wrap + * @param int &$realtime_log_size + */ + protected function append_log_helper($constant, $message_number, $message, array &$message_number_log, array &$message_log, &$log_size, &$realtime_log_file, &$realtime_log_wrap, &$realtime_log_size) { // remove the byte identifying the message type from all but the first two messages (ie. the identification strings) if (strlen($message_number) > 2) { Strings::shift($message); } - switch (NET_SSH2_LOGGING) { + switch ($constant) { // useful for benchmarks case self::LOG_SIMPLE: - $this->message_number_log[] = $message_number; + $message_number_log[] = $message_number; + break; + case self::LOG_SIMPLE_REALTIME: + echo $message_number; + echo PHP_SAPI == 'cli' ? "\r\n" : '
'; + @flush(); + @ob_flush(); break; // the most useful log for SSH2 case self::LOG_COMPLEX: - $this->message_number_log[] = $message_number; - $this->log_size += strlen($message); - $this->message_log[] = $message; - while ($this->log_size > self::LOG_MAX_SIZE) { - $this->log_size -= strlen(array_shift($this->message_log)); - array_shift($this->message_number_log); + $message_number_log[] = $message_number; + $log_size += strlen($message); + $message_log[] = $message; + while ($log_size > self::LOG_MAX_SIZE) { + $log_size -= strlen(array_shift($message_log)); + array_shift($message_number_log); } break; // dump the output out realtime; packets may be interspersed with non packets, @@ -4192,28 +4227,28 @@ class SSH2 // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily // at the beginning of the file case self::LOG_REALTIME_FILE: - if (!isset($this->realtime_log_file)) { + if (!isset($realtime_log_file)) { // PHP doesn't seem to like using constants in fopen() $filename = NET_SSH2_LOG_REALTIME_FILENAME; $fp = fopen($filename, 'w'); - $this->realtime_log_file = $fp; + $realtime_log_file = $fp; } - if (!is_resource($this->realtime_log_file)) { + if (!is_resource($realtime_log_file)) { break; } $entry = $this->format_log([$message], [$message_number]); - if ($this->realtime_log_wrap) { + if ($realtime_log_wrap) { $temp = "<<< START >>>\r\n"; $entry .= $temp; - fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp)); + fseek($realtime_log_file, ftell($realtime_log_file) - strlen($temp)); } - $this->realtime_log_size += strlen($entry); - if ($this->realtime_log_size > self::LOG_MAX_SIZE) { - fseek($this->realtime_log_file, 0); - $this->realtime_log_size = strlen($entry); - $this->realtime_log_wrap = true; + $realtime_log_size += strlen($entry); + if ($realtime_log_size > self::LOG_MAX_SIZE) { + fseek($realtime_log_file, 0); + $realtime_log_size = strlen($entry); + $realtime_log_wrap = true; } - fputs($this->realtime_log_file, $entry); + fputs($realtime_log_file, $entry); } }