get_log_status(); $specific = $this->get_log_specific(); $enabled = apply_filters( 'mainwp_log_status', $enabled ); $specific = apply_filters( 'mainwp_log_specific', $specific ); $this->set_log_priority( $enabled, $specific ); $this->autoEnableLoggingActions = array( static::CONNECT_LOG_PRIORITY, ); } /** * Method init. */ public function init() { $enabled = get_option( 'mainwp_actionlogs' ); if ( false === $enabled && ! get_transient( 'mainwp_transient_action_logs' ) ) { $sites_count = MainWP_DB::instance()->get_websites_count(); if ( empty( $sites_count ) ) { set_transient( 'mainwp_transient_action_logs', true, 2 * WEEK_IN_SECONDS ); } } } /** * Method set_log_priority() * * Sets the log priority. * * @param mixed $logPriority Log priority value. * @param mixed $spec_log Specific log. */ public function set_log_priority( $logPriority, $spec_log = 0 ) { $this->logPriority = (int) $logPriority; $this->logSpecific = (int) $spec_log; // 1 - specific log, 0 - not specific log. } /** * Method enable_log_priority() * * Sets the log priority. * * @param mixed $logPriority Log priority value. * @param mixed $spec_log Specific log. */ public function enable_log_priority( $logPriority, $spec_log = 1 ) { $spec_log = $spec_log ? 1 : 0; $logPriority = intval( $logPriority ); MainWP_Utility::update_option( 'mainwp_specific_logs', $spec_log ); MainWP_Utility::update_option( 'mainwp_actionlogs', $logPriority ); MainWP_Utility::update_option( 'mainwp_actionlogs_enabled_timestamp', time() ); $this->log_action( 'Action logs set to: ' . $this->get_log_text( $logPriority ), ( $spec_log ? $logPriority : static::LOG ), 2, true ); $this->set_log_priority( $logPriority, $spec_log ); } /** * Method get_log_status() * * Get log status. * * @return mixed $enabled log status. */ public function get_log_status() { $enabled = get_option( 'mainwp_actionlogs' ); if ( false === $enabled ) { if ( get_transient( 'mainwp_transient_action_logs' ) ) { $enabled = self::DEBUG; } else { $enabled = static::DISABLED; } } return $enabled; } /** * Method get_log_specific() * * Get log specific status. * * @return mixed $enabled log status. */ public function get_log_specific() { return get_option( 'mainwp_specific_logs', 0 ); } /** * Method get_log_type_info() * * Get log type info. * * @param int $type Log type value. * @param int $logcolor Log color value. * * @return int $currentColor log color code. */ public function get_log_type_info( $type, $logcolor ) { $currentColor = ''; $prefix = ''; if ( static::DEBUG === $type || static::DEBUG === $logcolor ) { $currentColor = static::DEBUG_COLOR; $prefix = '[DEBUG]'; } elseif ( static::INFO === $type || static::INFO === $logcolor ) { $currentColor = static::INFO_COLOR; $prefix = '[INFO]'; } elseif ( static::WARNING === $type || static::WARNING === $logcolor ) { $currentColor = static::WARNING_COLOR; $prefix = '[WARNING]'; } elseif ( static::LOG === $type || static::LOG === $logcolor ) { $currentColor = static::LOG_COLOR; $prefix = '[LOG]'; } return array( 'log_color' => $currentColor, 'log_prefix' => $prefix, ); } /** * Method debug() * * Grab debug. * * @param string $text Debug message text. * * @return string Log debug message. */ public function debug( $text ) { return $this->log( $text, static::DEBUG ); } /** * Method info() * * Grab info. * * @param string $text Info message text. * * @return string Log info message. */ public function info( $text ) { return $this->log( $text, static::INFO ); } /** * Method warning() * * Grab warning information. * * @param string $text Warning message text. * * @return string Log warning message. */ public function warning( $text ) { return $this->log( $text, static::WARNING ); } /** * Method actions() * * Grab actions information. * * @param string $text Warning message text. * @param int $priority priority message. * @param int $log_color Set color: 0 - LOG, 1 - WARNING, 2 - INFO, 3- DEBUG. * @param bool $forced forced logging. * * @return string Log warning message. */ public function log_action( $text, $priority, $log_color = 0, $forced = false ) { return $this->log( $text, $priority, $log_color, $forced ); } /** * Method log_events(). * * @param string $event_name Event name. * @param string $text Log update check. */ public function log_events( $event_name, $text = '' ) { switch ( $event_name ) { case 'update-check': $this->log_action( '[Update Checks] :: ' . $text, static::UPDATE_CHECK_LOG_PRIORITY ); break; case 'regular-schedule': $this->log_action( '[Regular Schedule] :: ' . $text, static::LOGS_REGULAR_SCHEDULE ); break; case 'debug-updates-crons': $this->log_action( '[Debug updates crons] :: ' . $text, static::DEBUG_UPDATES_SCHEDULE ); break; default: break; } } /** * Method log_update_check(). * * @param string $text Log update check. */ public function log_update_check( $text = '' ) { $this->log_action( $text, static::UPDATE_CHECK_LOG_PRIORITY ); } /** * Method log_update_check(). * * @param string $text Log update check. */ public function log_uptime_check( $text = '' ) { $this->log_action( $text, static::UPTIME_CHECK_LOG_PRIORITY ); } /** * Method log_uptime_notice(). * * @param string $text Log update check. */ public function log_uptime_notice( $text = '' ) { $this->log_action( $text, static::UPTIME_NOTICE_LOG_PRIORITY ); } /** * Method debug_for_website() * * Grab website debug and info. * * @param object $website Child site object. * @param string $action Performed action. * @param string $message Debug message. * * @return mixed Website debug info. * * @uses \MainWP\Dashboard\MainWP_Utility::get_nice_url() */ public function debug_for_website( $website, $action, $message ) { if ( empty( $website ) ) { return $this->log( '[-] [-] ::' . $action . ':: ' . $message, static::DEBUG ); } return $this->log( '[' . $website->name . '] [' . MainWP_Utility::get_nice_url( $website->url ) . '] ::' . $action . ':: ' . $message, static::DEBUG, 0, false, $website ); } /** * Method info_for_website() * * Grab Website Info. * * @param object $website Child site object. * @param string $action Performed action. * @param string $message Info message. * * @return mixed Website Info. * * @uses \MainWP\Dashboard\MainWP_Utility::get_nice_url() */ public function info_for_website( $website, $action, $message ) { if ( empty( $website ) ) { return $this->log( '[-] [-] ::' . $action . ':: ' . $message, static::INFO ); } return $this->log( '[' . $website->name . '] [' . MainWP_Utility::get_nice_url( $website->url ) . '] ::' . $action . ':: ' . $message, static::INFO ); } /** * Method warning_for_website() * * Grab Website Warnings. * * @param object $website Child site object. * @param string $action Performed action. * @param string $message Warning message. * @param bool $addStackTrace Add or Don't add stack trace. * * @return string Website warnings. */ public function warning_for_website( $website, $action, $message, $addStackTrace = true ) { $stackTrace = ''; if ( $addStackTrace ) { ob_start(); // phpcs:ignore -- for debugging. debug_print_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); $stackTrace = "\n" . ob_get_clean(); } if ( empty( $website ) ) { return $this->log( '[-] [-] :: ' . $action . ' :: ' . $message . $stackTrace, static::WARNING ); } return $this->log( '[' . $website->name . '] [' . MainWP_Utility::get_nice_url( $website->url ) . '] ::' . $action . ':: ' . $message . $stackTrace, static::WARNING ); } /** * Method log_to_db() * * Log to database. * * @param string $text Log record text. * @param int $priority Set priority. * @param int $log_color Set color. * @param bool $forced forced logging. * @param mixed $website website object. * * @return bool true|false Default is False. */ private function log_to_db( $text, $priority, $log_color = 0, $forced = false, $website = false ) { if ( static::DISABLED === $this->logPriority ) { return false; } $priority = (int) apply_filters( 'mainwp_log_to_db_priority', $priority, $website ); $do_log = false; if ( 1 === $this->logSpecific ) { // 1 - specific log, 0 - not specific log. if ( $this->logPriority === $priority ) { // specific priority number saved setting. $do_log = true; } } elseif ( $this->logPriority >= $priority ) { $do_log = true; } $do_log = apply_filters( 'mainwp_log_do_to_db', $do_log, $website ); if ( ! $forced && ! $do_log ) { return false; } $text = $this->prepare_log_info( $text ); do_action( 'mainwp_before_log_data', $text, $priority, $log_color ); if ( defined( 'DOING_CRON' ) && DOING_CRON && 'CRON' !== strtoupper( substr( $text, 0, 4 ) ) ) { $text = 'CRON :: ' . $text; } /** * Current user global. * * @global string */ global $current_user; $user = ''; if ( ! empty( $current_user ) && ! empty( $current_user->user_login ) ) { $user = $current_user->user_login; } elseif ( defined( 'WP_CLI' ) ) { $user = 'WP_CLI'; } elseif ( defined( 'DOING_CRON' ) ) { $user = 'DOING_CRON'; } $data = array(); $data['log_content'] = $text; $data['log_user'] = $user; $data['log_type'] = $priority; $data['log_color'] = intval( $log_color ); $data['log_timestamp'] = time(); $data = apply_filters( 'mainwp_log_to_db_data', $data ); MainWP_DB_Common::instance()->insert_action_log( $data ); return true; } /** * Method log() * * Create Log File. * * @param string $text Log record text. * @param int $priority Set priority. * @param int $log_color Set color. * @param bool $forced forced logging. * @param mixed $website Site object. * * @return bool true|false Default is False. */ private function log( $text, $priority, $log_color = 0, $forced = false, $website = false ) { // phpcs:ignore -- NOSONAR - complex function. if ( in_array( $priority, $this->autoEnableLoggingActions ) && (int) $this->logPriority !== (int) $priority ) { $this->enable_log_priority( $priority, 1 ); } if ( static::DISABLED === $this->logPriority ) { return false; } $log_to_db = apply_filters( 'mainwp_logger_to_db', true, $website ); if ( $log_to_db ) { return $this->log_to_db( $text, $priority, $log_color, $forced, $website ); } $text = $this->prepare_log_info( $text ); $do_log = false; if ( 1 === $this->logSpecific ) { // 1 - specific log, 0 - not specific log. if ( $this->logPriority === $priority ) { // specific priority number saved setting. $do_log = true; } } elseif ( $this->logPriority >= $priority ) { $do_log = true; } if ( $do_log ) { $this->logCurrentFile = $this->get_log_file(); $logCurrentHandle = fopen( $this->logCurrentFile, 'a+' ); if ( $logCurrentHandle ) { $time = gmdate( $this->logDateFormat ); $prefix = '[' . $this->get_log_text( $priority ) . ']'; /** * Current user global. * * @global string */ global $current_user; if ( ! empty( $current_user ) && ! empty( $current_user->user_login ) ) { $prefix .= ' [administrator]'; } fwrite( $logCurrentHandle, $time . ' ' . $prefix . ' ' . $text . "\n" ); fclose( $logCurrentHandle ); } if ( filesize( $this->logCurrentFile ) > ( $this->logMaxMB * 1048576 ) ) { $logCurrentHandle = fopen( $this->logCurrentFile, 'a+' ); if ( $logCurrentHandle ) { fseek( $logCurrentHandle, 0 ); $newLogFile = $this->logCurrentFile . '.tmp'; $newLogHandle = false; $chunkSize = filesize( $this->logCurrentFile ) - ( $this->logMaxMB * 1048576 ); while ( is_resource( $logCurrentHandle ) && ! feof( $logCurrentHandle ) && ( $chunkSize > 0 ) ) { $content = fread( $logCurrentHandle, $chunkSize ); if ( false === $content ) { break; } $pos = strrpos( $content, "\n" ); if ( $newLogHandle ) { fwrite( $newLogHandle, $content ); } elseif ( $pos ) { if ( ! $newLogHandle ) { $newLogHandle = fopen( $newLogFile, 'w+' ); } fwrite( $newLogHandle, substr( $content, $pos + 1 ) ); } } if ( is_resource( $logCurrentHandle ) ) { fclose( $logCurrentHandle ); } if ( $newLogHandle ) { fclose( $newLogHandle ); wp_delete_file( $this->logCurrentFile ); if ( file_exists( $newLogFile ) ) { rename( $newLogFile, $this->logCurrentFile ); } } } } return true; } return false; } /** * Method prepare_log_info() * * Prepare log data. * * @param mixed $data Log data. * * @return mixed $data filtered data. */ public function prepare_log_info( $data ) { $patterns[0] = '/user=([^\&]+)\&/'; $replacement[0] = 'user=xxxxxx&'; $patterns[1] = '/alt_user=([^\&]+)\&/'; $replacement[1] = 'alt_user=xxxxxx&'; $patterns[2] = '/\&server=([^\&]+)\&/'; $replacement[2] = '&server=xxxxxx&'; $data = preg_replace( $patterns, $replacement, $data ); return $data; } /** * Method prepend() * * Prepend content to log file. * * @param mixed $str Custom string. * @param mixed $filename Filename. */ public function prepend( $str, $filename ) { $context = stream_context_create(); $fp = fopen( $filename, 'r', 1, $context ); $tmpname = md5( $str ); // NOSONAR - safe for salt file name. file_put_contents( $tmpname, $str ); file_put_contents( $tmpname, $fp, FILE_APPEND ); fclose( $fp ); wp_delete_file( $filename ); rename( $tmpname, $filename ); } /** * Method init_execution_time(). * * @param string $time_index index for timer. * * Init execution time start value. */ public function init_execution_time( $time_index = '' ) { if ( null === static::$time_start || ! is_array( static::$time_start ) ) { static::$time_start = array( 'start' => microtime( true ) ); $this->log_action( 'execution time :: init :: [start]', static::EXECUTION_TIME_LOG_PRIORITY ); } if ( ! empty( $time_index ) && is_string( $time_index ) && 'start' !== $time_index ) { static::$time_start[ $time_index ] = microtime( true ); $this->log_action( 'execution time :: init :: [' . $time_index . ']', static::EXECUTION_TIME_LOG_PRIORITY ); } } /** * Method log_execution_time(). * * @param string $text Log record text. * * Log the execution time value. */ public function log_execution_time( $text = '' ) { $exec_time = $this->get_execution_time(); $this->log_action( 'execution time :: ' . ( ! empty( $text ) ? (string) $text : '' ) . ' :: [time=' . round( $exec_time, 4 ) . '](seconds)', static::EXECUTION_TIME_LOG_PRIORITY ); } /** * Method get_execution_time(). * * Get the execution time value. * * @param string $time_index Index for timer. * * @return int execution time. */ private function get_execution_time( $time_index = '' ) { if ( empty( static::$time_start ) ) { return 0; } $start = 0; if ( ! empty( $time_index ) ) { $start = is_array( static::$time_start ) && isset( static::$time_start[ $time_index ] ) ? static::$time_start[ $time_index ] : 0; } if ( empty( $start ) ) { $start = is_array( static::$time_start ) && isset( static::$time_start['start'] ) ? static::$time_start['start'] : 0; } if ( empty( $start ) ) { return 0; } return microtime( true ) - $start; // seconds. } /** * Method get_log_file() * * Grab Log File. * * @return mixed Log File. */ public function get_log_file() { if ( empty( $this->logDirectory ) ) { $this->logDirectory = MainWP_System_Utility::get_mainwp_dir(); $this->logDirectory = $this->logDirectory[0]; } return $this->logDirectory . $this->logFileNamePrefix . $this->logFileNameSuffix; } /** * Method get_log_text() * * Grab what type of log entry. * * @param mixed $priority Set priority. * * @return string LOG -OR- DISABLED|DEBUG|INFO|WARNING|INFO UPDATE */ public function get_log_text( $priority ) { switch ( $priority ) { case static::DISABLED: return 'DISABLED'; case static::DEBUG: return 'DEBUG'; case static::INFO: return 'INFO'; case static::WARNING: return 'WARNING'; default: return 'SPEC LOG'; } } /** * Method check_log_daily() * * Daily checks to clear the log file. */ public function check_log_daily() { $status = (int) $this->get_log_status(); if ( 0 >= $status ) { return; } $today_m_y = date_i18n( 'd/m/Y' ); //phpcs:ignore -- local time. // one time per day. if ( get_option( 'mainwp_logger_check_daily' ) !== $today_m_y ) { $num_days = apply_filters( 'mainwp_logger_keep_days', 7 ); MainWP_DB_Common::instance()->delete_action_log( $num_days ); MainWP_Utility::update_option( 'mainwp_logger_check_daily', $today_m_y ); $enabled_time = get_option( 'mainwp_actionlogs_enabled_timestamp', false ); if ( false === $enabled_time ) { MainWP_Utility::update_option( 'mainwp_actionlogs_enabled_timestamp', time() ); } elseif ( $enabled_time + $num_days * DAY_IN_SECONDS < time() ) { MainWP_Utility::update_option( 'mainwp_actionlogs', static::DISABLED ); } } } /** * Method clear_log_db() * * Clear the log file. */ public function clear_log_db() { MainWP_DB_Common::instance()->delete_action_log(); } /** * Method clear_log() * * Clear the log file. */ public function clear_log() { $logFile = $this->get_log_file(); wp_delete_file( $logFile ); $fh = fopen( $logFile, 'w' ); if ( false === $fh ) { return; } fclose( $fh ); } /** * Method show_log_db() * * Grab log file and build output to screen. */ public function show_log_db() { //phpcs:ignore -- NOSONAR - complexity. echo ''; echo '
'; // phpcs:ignore -- local time. $limit = 500; //phpcs:disable WordPress.Security.NonceVerification $paged = isset( $_GET['paged'] ) ? intval( $_GET['paged'] ) : 0; //phpcs:ignore -- NOSONAR -ok. if ( $paged <= 0 ) { $paged = 0; } else { --$paged; } $params = array(); if ( isset( $_GET['hour'] ) && ! empty( $_GET['hour'] ) ) { // phpcs:ignore -- local time. $params['hour'] = intval( $_GET['hour'] ); // phpcs:ignore -- local time. } else { $params['hour'] = $limit; } $order = isset( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : ''; //phpcs:ignore -- NOSONAR -ok. $total = MainWP_DB::instance()->get_var_field( MainWP_DB_Common::instance()->get_sql_log( $paged, $order, array( 'count' => true ) ) ); $rows = MainWP_DB::instance()->query( MainWP_DB_Common::instance()->get_sql_log( $paged, $order, $params ) ); $count = $rows ? MainWP_DB::num_rows( $rows ) : 0; $show_info = ''; if ( isset( $_GET['hour'] ) ) { $show_info = $count . ' latest items from a total of ' . $total; } elseif ( isset( $_GET['paged'] ) ) { //phpcs:ignore -- NOSONAR -ok. $from = $limit * $paged; $show_info = $count . ' items, from ' . $from . ' - ' . ( $from + $limit ) . ' of ' . $total . ' total.'; } if ( ! empty( $show_info ) ) { echo '

' . esc_html__( 'Showing ', 'mainwp' ) . ': ' . $show_info; //phpcs:ignore -- NOSONAR ok. } //phpcs:enable WordPress.Security.NonceVerification $start_wrapper = 'Click to See Response

'; while ( $rows && ( $row = MainWP_DB::fetch_object( $rows ) ) ) { $line = $row->log_content; if ( 120 * 1024 < strlen( $line ) ) { $line = '[Data row too long]'; } $time = gmdate( $this->logDateFormat, MainWP_Utility::get_timestamp( $row->log_timestamp ) ); $showInfo = $this->get_log_type_info( $row->log_type, $row->log_color ); $currentColor = $showInfo['log_color']; $prefix = $time . ' ' . $showInfo['log_prefix']; $line = htmlentities( $line ); if ( false !== strpos( $line, '[data-start]' ) ) { $line = str_replace( '[data-start]', $start_wrapper, $line ); $line = str_replace( '[data-end]', $end_wrapper, $line ); } echo '
'; echo $prefix . ' ' . $line; // phpcs:ignore WordPress.Security.EscapeOutput echo '
'; } echo '
'; echo ''; ?> get_log_file(); if ( ! file_exists( $logFile ) ) { return; } $fh = fopen( $logFile, 'r' ); if ( false === $fh ) { return; } $previousColor = ''; $fontOpen = false; $firstLinePassedProcessed = false; echo ''; echo '
'; while ( false !== ( $line = fgets( $fh ) ) ) { $currentColor = $previousColor; if ( stristr( $line, '[DEBUG]' ) ) { $currentColor = static::DEBUG_COLOR; $firstLinePassed = true; } elseif ( stristr( $line, '[INFO]' ) ) { $currentColor = static::INFO_COLOR; $firstLinePassed = true; } elseif ( stristr( $line, '[WARNING]' ) ) { $currentColor = static::WARNING_COLOR; $firstLinePassed = true; } elseif ( stristr( $line, '[LOG]' ) ) { $currentColor = static::LOG_COLOR; $firstLinePassed = true; } else { $firstLinePassed = false; } if ( $firstLinePassedProcessed && ! $firstLinePassed ) { echo ' Click to See Response
'; } echo '
'; $fontOpen = true; } echo esc_html( htmlentities( $line ) ); } if ( $fontOpen ) { echo '
'; } echo ''; ?>