AlkantarClanX12

Your IP : 216.73.217.24


Current Path : /www/capitalgmcbuickregina_830/public/wp-content/plugins/wp-cerber/admin/
Upload File :
Current File : /www/capitalgmcbuickregina_830/public/wp-content/plugins/wp-cerber/admin/cerber-admin.php

<?php
/*
	Copyright (C) 2015-26 CERBER TECH INC., https://wpcerber.com

    Licensed under the GNU GPL.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/

/*

*========================================================================*
|                                                                        |
|	       ATTENTION!  Do not change or edit this file!                  |
|                                                                        |
*========================================================================*

*/

const UIS_LOADER_HTML = '<div class="uis_loader_wrapper"><div class="uis_page_loader"></div></div>';

add_action( 'admin_init', function () {

	CRB_Globals::admin_init();

	if ( cerber_is_wp_ajax() ) {
		return;
	}

	crb_show_phpinfo();
	crb_settings_processor();
	crb_do_export_settings();
	crb_do_import();
	crb_delete_alert();
	crb_admin_headers();

	// @since 8.8.2.3 Workaround: if scheduled (cron) tasks are not executed on the website
	$last = get_site_transient( 'cerber_daily_1' );
	if ( ! $last
	     || ! is_array( $last )
	     || $last[0] < ( time() - DAY_IN_SECONDS ) ) {
        CRB_Deferred_Tasks::add( 'cerber_do_hourly_2' );
        CRB_Deferred_Tasks::add( 'cerber_daily_run' );
	}

} );

function cerber_assets_dir() {
	return cerber_plugin_dir() . '/assets';
}

// Scan dashboard ===========================================================

function cerber_scanner_show_dashboard( $msg = '', $status = 0 ) {

	$loader = ( $status ) ? UIS_LOADER_HTML : '';
	$stats = cerber_get_stats_html();
	$stats = array_shift( $stats );
	$note = ( $status ) ? '' : __( 'It seems this website has never been scanned. To start scanning click the button below.', 'wp-cerber' );

	?>
    <div id="crb-scan-display">
        <div id="crb-scan-tiles">
            <div class="crb-scan-info scan-tile">
                <table>
                    <tr>
                        <td><?php _e( 'Started', 'wp-cerber' ); ?></td>
                        <td id="crb-started" data-init="-">-</td>
                    </tr>
                    <tr>
                        <td><?php _e( 'Finished', 'wp-cerber' ); ?></td>
                        <td id="crb-finished" data-init="-">-</td>
                    </tr>
                    <tr>
                        <td><?php _e( 'Duration', 'wp-cerber' ); ?></td>
                        <td id="crb-duration" data-init="-">-</td>
                    </tr>
                    <tr>
                        <td><?php _e( 'Performance', 'wp-cerber' ); ?></td>
                        <td id="crb-performance" data-init="-">-</td>
                    </tr>
                    <tr>
                        <td>Mode</td>
                        <td id="crb-smode" data-init="-">-</td>
                    </tr>
                </table>
            </div>
            <div id="crb-scan-filter" class="crb-scan-info scan-tile">
                <?php echo $stats; ?>
            </div>
            <div class="scan-tile">
                <div><p><span id="crb-scanned-files" data-init="0">0</span> / <span id="crb-total-files"
                                                                                    data-init="0">0</span>
                    </p>
                    <p><?php echo __( 'Scanned / Files to scan', 'wp-cerber' ); ?></p>
                </div>
            </div>

            <div class="scan-tile">
                <div><p><span id="crb-critical" data-init="0">0</span> / <span id="crb-warning" data-init="0">0</span>
                    </p>
                    <p><?php _e( 'Critical issues', 'wp-cerber' ); ?> / <?php _e( 'Issues total', 'wp-cerber' ); ?></p>
                </div>
            </div>

        </div>

        <div id="crb-scan-progress">
            <div>
                <div id="the-scan-bar"></div>
            </div>
        </div>

        <div id="crb-scan-message"><?php echo $msg; ?></div>

    </div>
    <div id="crb-scan-details">

        <?php

        if ( $note ) {
	        echo '<div id="crb-scan-note">' . $note . '</div>';
        }

        ?>

        <table class="crb-table" id="crb-browse-files">
			<?php
			$rows = array();
			$rows[] = '<tr class="crb-scan-container" id="crb-wordpress" style=""><td colspan="6">WordPress</td></tr>';
			$rows[] = '<tr class="crb-scan-container" id="crb-muplugins" style=""><td colspan="6">Must use plugins</td></tr>';
			$rows[] = '<tr class="crb-scan-container" id="crb-dropins" style=""><td colspan="6">Drop-ins</td></tr>';
			$rows[] = '<tr class="crb-scan-container" id="crb-plugins" style=""><td colspan="6">Plugins</td></tr>';
			$rows[] = '<tr class="crb-scan-container" id="crb-themes" style=""><td colspan="6">Themes</td></tr>';
			$rows[] = '<tr class="crb-scan-container" id="crb-uploads" style=""><td colspan="6">Uploads folder</td></tr>';
			$rows[] = '<tr class="crb-scan-container" id="crb-unattended" style=""><td colspan="6">Unattended files</td></tr>';
			echo implode( "\n", $rows );
			?>
        </table>
        <?php echo $loader; ?>
    </div>

	<?php

	cerber_ref_upload_form();
}

function cerber_show_scanner() {
	// https://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html

	$msg = '';
	$status = 0;

	if ( $scan = cerber_get_scan() ) {
		if ( ! $scan['finished'] ) {
			if ( $scan['cloud']
			     && cerber_is_cloud_enabled()
			     && $scan['started'] > ( time() - 900 )
			) {
				$msg = __( 'Currently a scheduled scan in progress. Please wait until it is finished.', 'wp-cerber' );
				$status = 1;
			}
			else {
				/* translators: %s is the date and time when the previous scan started. */
				$msg = sprintf( __( 'Previous scan started %s has not been completed. Continue scanning?', 'wp-cerber' ), cerber_date( $scan['started'], false ) );
				$status = 2;
			}
		}
		else {
			$status = 3;
		}
	}

	$start_quick = '<input data-control="start_scan" data-mode="quick" type="button" value="' . __( 'Start Quick Scan', 'wp-cerber' ) . '" class="button button-primary">';
	$start_full = '<input data-control="start_scan" data-mode="full" type="button" value="' . __( 'Start Full Scan', 'wp-cerber' ) . '" class="button button-primary">';
	$stop = '<input id="crb-stop-scan" style="display: none;" data-control="stop_scan" type="button" value="' . __( 'Stop Scanning', 'wp-cerber' ) . '" class="button button-primary">';
	$continue = '<input id="crb-continue-scan" data-control="continue_scan" type="button" value="' . __( 'Continue Scanning', 'wp-cerber' ) . '" class="button button-primary">';
	$controls = '';

	switch ( $status ) {
		case 0:
		case 3:
			$controls = $start_quick . $start_full;
			break;
		case 1:
			$controls = '';
			break;
		case 2:
			$controls = $start_quick . $start_full . $continue;
			break;
	}

	$controls .= $stop;

	echo '<div id="crb-scanner">';

	cerber_scanner_show_dashboard( $msg, $status );

	$d = '';
	if ( nexus_is_valid_request() && ! nexus_is_granted( 'submit' ) ) {
		$d = 'disabled="disabled"';
	}

	?>
    <div id="crb-scan-area">
        <form>
            <table id="crb-scan-controls">
                <tr>
                    <td id="crb-file-controls">
                        <input data-control="delete_file" type="button"
                               class="button button-secondary"
							<?php echo $d; ?>
                               value="<?php _e( 'Delete', 'wp-cerber' ); ?>"/>
                        <input data-control="ignore_add_file" type="button" class="button button-secondary"
							<?php echo $d; ?>
                               value="<?php _e( 'Ignore', 'wp-cerber' ); ?>"/>
                    </td>
                    <td>
						<?php echo $controls; ?>
                    </td>
                    <!-- <td><a href="#" data-control="full-paths">Show full paths</a></td> -->
                    <td><a href="#" class="dashicons dashicons-list-view" data-control="full-paths"
                           title="Toggle full/relative paths"></a></td>
                </tr>
            </table>
        </form>
    </div>

	<?php

	echo '</div>';
}

function cerber_ref_upload_form() {
	?>

    <div id="crb-ref-upload-dialog" style="display: none;">
        <div class="crb-popup-inner">
        <p><?php _e( 'We have not found any integrity data to verify', 'wp-cerber' ); ?> <span
                    id="ref-section-name"></span>.</p>
        <p><?php _e( "You have to upload a ZIP archive from which you've installed it. This enables the security scanner to verify the integrity of the code and detect malware.", 'wp-cerber' ); ?></p>
        <?php /* translators: %s is the maximum file size allowed for upload. */ ?>
        <p><?php echo sprintf( __( 'Maximum upload file size: %s.' ), esc_html( size_format( wp_max_upload_size() ) ) ); ?></p>
        <form enctype="multipart/form-data">
            <input type="file" name="refile" id="refile" required="required" accept=".zip">
            <input type="submit" name="submit" value="<?php _e( 'Upload file', 'wp-cerber' ); ?>"
                   class="button button-primary">
            <ul style="list-style: none;">
                <li style="display:none;" class="crb-status-msg"><?php _e( 'The file is being uploaded, please wait', 'wp-cerber' ); ?>&#8230;</li>
                <li style="display:none;" class="crb-status-msg"><?php _e( 'Processing the file, please wait', 'wp-cerber' ); ?>&#8230;</li>
            </ul>
        </form>
        </div>
    </div>

	<?php
}

add_action( 'wp_ajax_cerber_scan_control', 'cerber_manual_scan' );
function cerber_manual_scan() {

	cerber_check_ajax_permissions();

	ob_start(); // Collecting possible junk warnings and notices cause we need clean JSON to be sent

	$scanner = array();
	$console_log = array();
	$scan_do = '';

	if ( cerber_is_http_post() && $scan_do = crb_get_post_fields( 'cerber_scan_do' ) ) {
		$scan_do = preg_replace( '/[^a-z_\-\d]/i', '', $scan_do );
		$mode = ( $mode = crb_get_post_fields( 'cerber_scan_mode' ) ) ? preg_replace( '/[^a-z_\-\d]/i', '', $mode ) : 'quick';

		$scanner = crb_scan_run_scanner( $scan_do, $mode );

	}
	else {
		$console_log[] = 'Unknown HTTP request';
	}

	$next_do = ( ! empty( $scanner['cerber_scan_do'] ) ) ? $scanner['cerber_scan_do'] : 'stop';

	$console_log = array_merge( $console_log, cerber_db_get_errors() );

	$console_log[] = 'PHP MEMORY ' . @ini_get( 'memory_limit' );

	$ret = array(
		'console_log'    => $console_log,
		'cerber_scan_do' => $next_do,
		'cerber_scanner' => $scanner,
		//'scan'           => cerber_get_scan(), // debug only
	);

	ob_end_clean();

	echo json_encode( $ret );

	crb_admin_stop_ajax();
}

/**
 * File viewer, server side AJAX
 *
 */
add_action( 'wp_ajax_cerber_view_file', function () {

	cerber_check_ajax_permissions();

	$get = crb_get_query_params();

	if ( ! $file_name = $get['file'] ) {
		crb_admin_stop_ajax( 'Error: Filename not specified. Please run a new malware scan.' );
	}

	if ( ! @file_exists( $file_name ) ) {
		crb_admin_stop_ajax( 'Error: The requested file doesn\'t exist or has been deleted: ' . crb_escape_html( $file_name ) . '. Please run a new malware scan.' );

		return;
	}

	if ( ! @is_file( $file_name ) ) {
		crb_admin_stop_ajax( 'Error: The requested file is not an ordinary file: ' . crb_escape_html( $file_name ) );

		return;
	}

	$file_size = filesize( $file_name );

	if ( $file_size > 8000000 ) {
		crb_admin_stop_ajax( 'Error: The requested is too large to display: ' . crb_size_format( $file_size ) );

		return;
	}

	if ( $file_size <= 0 ) {
		crb_admin_stop_ajax( 'The requested file is empty.' );

		return;
	}

	if ( ! $source = file_get_contents( $file_name ) ) {
		crb_admin_stop_ajax( 'Error: Unable to load file.' );

		return;
	}

	$source = crb_escape_html( $source );

	if ( ! $source ) {
		$source = 'Unable to display the contents of the file. This file contains non-printable characters.';
	}

	if ( cerber_detect_exec_extension( $file_name )
	     || cerber_check_extension( $file_name, array( 'js', 'css', 'inc' ) )
	     || cerber_is_htaccess( $file_name )
	) {
		$paint = true;
	}
	else {
		$paint = false;
	}

	$overlay = '';
	if ( $paint ) {
		$overlay = '<div id="crb-overlay">Loading, please wait...</div>';
	}

	$sh_url = CRB_Globals::assets_url( 'sh/' );
	$sheight = absint( $get['sheight'] ) - 100; // highlighter is un-responsible, so we need tell him the real height

	?>
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script src="<?php echo $sh_url ?>scripts/shCore.js"></script>
        <script src="<?php echo $sh_url; ?>scripts/shBrushPhp.js"></script>
        <link href="<?php echo $sh_url; ?>styles/shCore.css" rel="stylesheet" type="text/css"/>
        <link href="<?php echo $sh_url; ?>styles/shThemeDefault.css" rel="stylesheet" type="text/css"/>
        <style>
            body {
                overflow: hidden;
                font-family: 'Roboto', sans-serif;
                font-size: 14px;
            }

            #crb-overlay {
                display: flex;
                justify-content: center;
                align-items: center;
                text-align: center;
                background-color: #fff;
                position: fixed;
                width: 100%;
                height: 100%
                z-index: 2;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
            }

            #crb-issue {
                border-left: 3px solid crimson;
                background-color: #eee;
                padding: 1em;
                overflow: auto;
            }

            #crb-file-content {
            <?php
            if (!$paint) {
                echo '
                max-height: '.$sheight .'px;
                overflow: auto;
                padding: 15px;
                ';
            }
            else {
                echo 'overflow: hidden;';
            }
            ?>
            }

            .syntaxhighlighter {
                max-height: <?php echo $sheight; ?>px;
            }

            .syntaxhighlighter code {
                font-family: Menlo, Consolas, Monaco, monospace !important;
                font-size: 13px !important;
            }

            .syntaxhighlighter .gutter .line {
                border-right: 3px solid #c7c7c7 !important;
            }

        </style>
    </head>

    <body>

	<?php

	echo $overlay;

	echo '<pre id="crb-file-content" class="brush: php; toolbar: false;">' . $source . '</pre>';

	$scan_id = absint( $get['scan_id'] );

	$the_file = cerber_db_get_row( 'SELECT * FROM ' . cerber_get_db_prefix() . CRB_SCANFILES_TABLE . ' WHERE scan_id = ' . $scan_id . ' AND file_name = "' . $file_name . '"' );

	if ( $the_file ) {
		echo '<div id="crb-issue">Issue: ' . cerber_get_issue_title( $the_file['scan_status'] ) . '</div>';
	}

	if ( $paint ) :
		?>

        <script id="wp-cerber-js-<?php echo crb_sanitize_id( __FUNCTION__ . '_' . __LINE__ ); ?>">

            SyntaxHighlighter.defaults["highlight"];
            SyntaxHighlighter.all();

            function crb_waitUntilRender() {
                let overlay = document.getElementById("crb-overlay").style.visibility = "hidden";
            }

            let intervalID = setInterval(crb_waitUntilRender, 200);

        </script>

	<?php

	endif;

	?>

    </body>
    </html>

	<?php

	crb_admin_stop_ajax();

} );

/**
 * Upload a reference ZIP archive for a theme or a plugin
 *
 */
add_action( 'wp_ajax_cerber_ref_upload', function () {

	cerber_check_ajax_permissions();

	//ob_start(); // Collecting possible junk warnings and notices cause we need clean JSON to be sent

	$error = '';

	$folder = cerber_get_tmp_file_folder();
	if ( crb_is_wp_error( $folder ) ) {
		cerber_end_ajax( array( 'error' => $folder->get_error_message() ) );
	}

	if ( isset( $_FILES['refile'] ) ) {

		// Step 1, saving file

        if ( ! is_uploaded_file( $_FILES['refile']['tmp_name'] ) ) {
			$error = 'Unable to read uploaded file';
		}

		if ( ! cerber_check_extension( $_FILES['refile']['name'], array( 'zip' ) ) ) {
			$error = __( 'This type of file is not supported. Please upload a ZIP archive.', 'wp-cerber' );
		}

		if ( cerber_detect_exec_extension( $_FILES['refile']['name'] ) ) {
			$error = __( 'Executable files are not supported. Please upload a ZIP archive.', 'wp-cerber' );
		}

		if ( false !== strpos( $_FILES['refile']['name'], '/' ) ) {
			$error = 'Incorrect filename';
		}

		if ( $error ) {
			cerber_end_ajax( array( 'error' => $error ) );
		}

		if ( false === @move_uploaded_file( $_FILES['refile']['tmp_name'], $folder . $_FILES['refile']['name'] ) ) {
			cerber_end_ajax( array( 'error' => 'Unable to copy file to ' . $folder ) );
		}

	}
	else {

		// Step 2, creating hash

		$result = cerber_need_for_hash();
		if ( crb_is_wp_error( $result ) ) {
			cerber_end_ajax( array( 'error' => $result->get_error_message() ) );
		}
	}

	cerber_end_ajax();

} );

/**
 * Deleting files, server side AJAX
 *
 */
add_action( 'wp_ajax_cerber_scan_bulk_files', function () {

	cerber_check_ajax_permissions();

	$post = crb_get_post_fields();

	if ( empty( $post['files'] ) || empty( $post['scan_id'] ) ) {
		crb_admin_stop_ajax( 'Error!' );

		return;
	}

	$scan_id = absint( $post['scan_id'] );

	if ( ! cerber_get_scan( $scan_id ) ) {
		crb_admin_stop_ajax( 'Error!' );

		return;
	}

	$operation = $post['scan_file_operation'];

	if ( ( ! $ignore = cerber_get_set( 'ignore-list' ) ) || ! is_array( $ignore ) ) {
		$ignore = array();
	}

	global $crb_list;
	$crb_list = array();
	$i = 0;
	$errors = array();
	$time = time();
	$user_id = get_current_user_id();

	foreach ( $post['files'] as $file_name ) {

		if ( ! is_file( $file_name ) ) {
			continue;
		}

		$the_file = cerber_db_get_row( 'SELECT * FROM ' . cerber_get_db_prefix() . CRB_SCANFILES_TABLE . ' WHERE scan_id = ' . $scan_id . ' AND file_name = "' . $file_name . '"', MYSQL_FETCH_OBJECT );
		if ( ! $the_file || ! is_file( $the_file->file_name ) ) {
			$errors[] = 'Unknown file: ' . $file_name;
			continue;
		}

		switch ( $operation ) {
			case 'delete_file':
				$result = cerber_quarantine_file( $file_name, $scan_id );
				break;
			case 'ignore_add_file':
				$ignore[ $the_file->file_name_hash ] = array(
					$the_file->file_name,
					@hash_file( 'sha256', $the_file->file_name ),
					$user_id,
					$time,
				);
				$result = true;
				break;
		}

		if ( crb_is_wp_error( $result ) ) {
			$errors[] = $result->get_error_message();
		}
        elseif ( ! $result ) {
			$errors[] = 'Unknown error 55';
		}
		else {
			$i ++;
			$crb_list[] = $file_name;
		}

	}

	if ( $operation == 'ignore_add_file' ) {
		// Update the last scan results to keep it up to date and avoid user confusing
		if ( $scan = cerber_get_scan() ) {

		    crb_file_filter( $scan['issues'], function ( $file_name ) {
				global $crb_list;
				if ( in_array( $file_name, $crb_list ) ) {
					return false;
				}

				return true;
			} );

			cerber_update_scan( $scan );
		}
		if ( ! cerber_update_set( 'ignore-list', $ignore ) ) {
			$errors [] = 'Unable to update the ignore list';
		}
	}

	crb_scan_diagnostic_log( $errors );

	cerber_end_ajax( array( 'errors' => $errors, 'number' => $i, 'processed' => $crb_list ) );

} );

/**
 * Finalizes current AJAX request and sends data to the client
 *
 * @param $data array
 */
function cerber_end_ajax( $data = array() ) {

	if ( ! $data ) {
		$data = array();
	}

	$data['cerber_db_errors'] = cerber_db_get_errors();

	if ( ! $data['cerber_db_errors'] ) {
		$data['OK'] = 'OK!';
	}

	echo json_encode( $data );

	if ( ! nexus_is_valid_request() ) {
		wp_die();
	}
}

function crb_admin_stop_ajax( $msg = '' ) {
	if ( $msg ) {
		echo $msg;
	}
	if ( ! nexus_is_valid_request() ) {
		exit;
	}
}

function cerber_show_quarantine() {

	$folder = cerber_get_the_folder( true );
	if ( crb_is_wp_error( $folder ) ) {
		echo '<p>ERROR: ' . $folder->get_error_message() . '</p>';

		return;
	}

	$per_page = crb_admin_get_per_page();
	$first = ( crb_get_page_num() - 1 ) * $per_page;
	$last = $first + $per_page;

	$filter_scan = crb_get_query_params( 'scan', '\d+' );

	list ( $list, $count, $scan_list ) = cerber_quarantine_get_files( $first, $last, $filter_scan );

	_crb_qr_total_sync( $count );

	if ( ! $list ) {
		if ( ! $filter_scan ) {
			echo crb_ui_renderer()->render_element( crb_ui_message_box( array( __( 'There are no files in the quarantine at the moment.', 'wp-cerber' ) ) ) );
		}
		else {
			echo __( 'No files match the specified filter.', 'wp-cerber' ) . ' <a href="' . crb_admin_link_for_html( 'scan_quarantine' ) . '">' . __( 'Click here to see the full list of files', 'wp-cerber' ) . '</a>.';
		}

		return;
	}

	$rows = array();
	$ofs = get_option( 'gmt_offset' ) * 3600;

	foreach ( $list as $file ) {
		$p = array(
			'cerber_admin_do' => 'scan_tegrity',
			'crb_scan_id'     => $file['scan_id'],
			'crb_file_id'     => $file['qfile']
		);

		$p['crb_scan_adm'] = 'delete';
		$delete = '<a class="crb-confirm-action" href="' . cerber_admin_link_add( $p ) . '">' . __( 'Delete', 'wp-cerber' ) . '</a>';

		$p['crb_scan_adm'] = 'restore';
		$restore = ( ! $file['can'] ) ? '' : ' | <a class="crb-confirm-action" href="' . cerber_admin_link_add( $p ) . '">' . __( 'Restore', 'wp-cerber' ) . '</a>';

		$moved = strtotime( $file['date'] ) - $ofs;
		$will = cerber_auto_date( $file['scan_id'] + DAY_IN_SECONDS * crb_get_settings( 'scan_qcleanup' ) );

		$file_name = str_replace( DIRECTORY_SEPARATOR, '<wbr>' . DIRECTORY_SEPARATOR, $file['source'] );

		$rows[] = array(
			'<span title="' . cerber_date( $file['scan_id'] ) . '">' . cerber_auto_date( $file['scan_id'] ) . '</span>',
			'<span title="' . cerber_date( $moved ) . '">' . cerber_auto_date( $moved ) . '</span>',
			$will,
			$file['size'],
			$file_name,
			'<span style="white-space: pre;">' . $delete . $restore . '</span>'
		);
	}

	$heading = array(
		__( 'Scanned', 'wp-cerber' ),
		__( 'Quarantined', 'wp-cerber' ),
		__( 'Automatic deletion', 'wp-cerber' ),
		__( 'Size', 'wp-cerber' ),
		__( 'File', 'wp-cerber' ),
		__( 'Action', 'wp-cerber' ),
	);

	$table = cerber_make_table( $rows, $heading, 'crb-quarantine' );

	$table .= cerber_page_navi( $count, $per_page );

	$filter = '';
	if ( count( $scan_list ) > 1 ) {
		krsort( $scan_list );
		$list = array( 0 => __( 'All scans', 'wp-cerber' ) );
		foreach ( $scan_list as $s ) {
			$list[ $s ] = cerber_date( $s, false );
		}
		$filter = '<div style="text-align: right; margin-bottom: 1em;"><form style="width: auto;" action="">' . cerber_select( 'scan', $list, $filter_scan ) . ' <input value="Filter" class="button" type="submit"><input name="page" value="cerber-integrity" type="hidden"><input name="tab" value="scan_quarantine" type="hidden"></form></div>';
	}

	echo $filter . $table;
}

function cerber_quarantine_do( $what, $scan_id, $qfile ) {
	$scan_id = absint( $scan_id );
	if ( ! $scan_id ) {
		cerber_admin_notice( 'Error: Wrong scan parameters.' );

		return;
	}

	$dir = cerber_get_the_folder( true );
	if ( crb_is_wp_error( $dir ) ) {
		crb_admin_error_notice( $dir );

		return;
	}

	$dir .= 'quarantine' . DIRECTORY_SEPARATOR . $scan_id;

	$file = $dir . DIRECTORY_SEPARATOR . $qfile;
	if ( ! @is_file( $file ) || is_link( $file ) ) {
		cerber_admin_notice( 'Error: No file to process' );

		return;
	}

	$rst = $dir . '/.restore';
	if ( ! file_exists( $rst ) || ! $handle = @fopen( $rst, 'r' ) ) {
		cerber_admin_notice( 'Error: A restore registry file is corrupt or missing.' );

		return;
	}

	$data = null;
	while ( ( $line = fgets( $handle ) ) !== false ) {
		if ( $p = crb_parse_qline( $dir, $line ) ) {
			if ( $p['qfile'] == $qfile ) {
				$data = $p;
				break;
			}
		}
	}

	if ( ! $data ) {
		cerber_admin_notice( 'Error: No information about this file. Unable to proceed.' );

		return;
	}

	$err = null;
	$msg = null;
	switch ( $what ) {
		case 'delete':
			if ( unlink( $file ) ) {
				$msg = __( 'The file has been deleted from the quarantine.', 'wp-cerber' );
				crb_qr_total_update( -1 );
			}
			else {
				$err = 'Unable to delete the file: ' . $file;
			}
			break;
		case 'restore':
			if ( $data['can'] ) {
				$target_dir = dirname( $data['source'] );
				if ( ! file_exists( $target_dir ) && ! mkdir( $target_dir, 0755, true ) ) {
					$err = 'Unable to create directory: <b>' . $target_dir . '</b>. Check permissions of parent directories.';
				}
				if ( ! $err ) {
					if ( @rename( $file, $data['source'] ) ) {
						$msg = __( 'The file has been restored to its original location.', 'wp-cerber' );
						crb_qr_total_update( -1 );
					}
					else {
						$err = 'A file error occurred while restoring the file. Check permissions of directories.';
					}
				}
			}
			else {
				$err = 'This file cannot be restored and needs to be manually copied. <p>See instructions in this file: ' . $rst . '</p>';
			}
			break;
	}
	if ( $err ) {
        crb_add_admin_error( $err );
	}
	if ( $msg ) {
		cerber_admin_message( $msg );
	}
}

function cerber_show_ignore() {

	$per_page = crb_admin_get_per_page();
	$first = ( crb_get_page_num() - 1 ) * $per_page;

	if ( ! $list = cerber_get_set( 'ignore-list' ) ) {
		echo crb_ui_renderer()->render_element( crb_ui_message_box( array( __( 'The list is empty.', 'wp-cerber' ) ) ) );

		return;
	}

	$count = count( $list );
	$list = array_slice( $list, $first, $per_page );

	$rows = array();

	foreach ( $list as $key => $file ) {

		$delete = '<a class="crb-confirm-action" href="' . cerber_admin_link_add( array(
				'cerber_admin_do' => 'scan_tegrity',
				'crb_scan_adm'    => 'remove_ignore',
				'crb_file_id'     => $key
			) ) . '">' . __( 'Remove from the list', 'wp-cerber' ) . '</a>';

		$rows[] = array(
			cerber_date( $file[3] ),
			cerber_date( cerber_get_date( $file[0] ) ),
			crb_size_format( cerber_get_size( $file[0] ) ),
			$file[0],
			'<span style="white-space: pre;">' . $delete . '</span>'
		);
	}

	$heading = array(
		__( 'Added', 'wp-cerber' ),
		__( 'Modified', 'wp-cerber' ),
		__( 'Size', 'wp-cerber' ),
		__( 'File', 'wp-cerber' ),
		__( 'Action', 'wp-cerber' ),
	);

	$table = cerber_make_table( $rows, $heading );

	$table .= cerber_page_navi( $count, $per_page );

	echo $table;
}

function crb_remove_ignore( $id ) {
	if ( ! $list = cerber_get_set( 'ignore-list' ) ) {
		return false;
	}
	if ( ! isset( $list[ $id ] ) ) {
		return false;
	}

	unset( $list[ $id ] );

	return cerber_update_set( 'ignore-list', $list );

}

// Scan analytics ===========================================================

/**
 * Renders the message box shown when no scan data is available for analytics reports.
 *
 * @return string The rendered message box HTML.
 */
function crb_scan_no_message() {
	return crb_ui_renderer()->render_element( crb_ui_message_box( array(
		crb_ui_element( 'p', array(), crb_ui_element( 'b', array(), __( 'No data for generating reports', 'wp-cerber' ) ) ),
		__( 'Please run the Full Scan. After the scan is completed, analytics reports will be generated.', 'wp-cerber' ),
	) ) );
}

function cerber_scan_insights() {

	if ( ! $scan_id = crb_scan_last_full() ) {
		echo crb_scan_no_message();

		return;
	}

	if ( $ext = crb_get_query_params( 'fext' ) ) {
		cerber_show_files( $ext, $scan_id );

		return;
	}

	?>

    <div id="crb_scan_insights">
        <div class="crb_async_content" data-ajax_route="scanner_analytics" data-scan_id="<?php echo $scan_id; ?>" data-itype="1">
        </div>
        <div class="crb_async_content" data-ajax_route="scanner_analytics" data-scan_id="<?php echo $scan_id; ?>" data-itype="2">
        </div>
        <div id="crb_ins_ext_list" class="crb_async_content" data-ajax_route="scanner_analytics" data-scan_id="<?php echo $scan_id; ?>" data-itype="3">
        </div>
    </div>

	<?php

}

/**
 * @param string $ext
 * @param int $scan_id
 */
function cerber_show_files( $ext, $scan_id ) {

	$ext = cerber_db_real_escape( $ext );
	$scan_id = absint( $scan_id );
	$per_page = 25;
	$limit = crb_build_sql_limit( $per_page );
	$files = cerber_db_get_results( 'SELECT SQL_CALC_FOUND_ROWS file_name, file_mtime, file_size FROM ' . cerber_get_db_prefix() . CRB_SCANFILES_TABLE . ' WHERE scan_id = ' . $scan_id . ' AND file_ext = "' . $ext . '" ' . $limit );
	$total = cerber_db_get_var( 'SELECT FOUND_ROWS()' );

	if ( ! $files ) {
		echo '<p>No files found. Please run the Full Scan.</p>';

		return;
	}

	$title = ( $ext == '.' ) ? __( 'Files without extension', 'wp-cerber' ) : 'Files with the "' . $ext . '" extension';
	echo '<div style="display: table-cell"><h3>' . $title . '</h3></div><div style="display: table-cell; vertical-align: middle;">  &nbsp; <a href="' . crb_admin_link_for_html( 'scan_insights' ) . '#crb_ins_ext_list" class="page-title-action">' . __( 'Back to list', 'wp-cerber' ) . '</a></div>';

	echo crb_make_file_table( $files ) . cerber_page_navi( $total, $per_page );
}

/**
 * @param string $type
 *
 * @return string|WP_Error
 *
 * @since 8.6.4
 */
function cerber_generate_insights( $type ) {

	if ( ! $scan_id = crb_scan_last_full() ) {
		return crb_scan_no_message();
	}

	$key = 'scan_insights_' . $type;

	// Cache
	if ( $report = cerber_get_set( $key, $scan_id, false ) ) {
		return $report;
	}

	switch ( $type ) {
		case 1:
			$report = crb_scan_insights_brief( $scan_id );
			break;
		case 2:
			$report = crb_scan_insights_lrgst( $scan_id );
			break;
		case 3:
			$report = crb_scan_insights_exts( $scan_id );
			break;
	}

	// Cache
	if ( $report ) {
		cerber_update_set( $key, $report, $scan_id, false, time() + 24 * 3600 );
	}
	else {
		$report = 'ERROR: Unknown report';
	}

	return $report;
}

function crb_scan_insights_brief( $scan_id ) {

	$scan_id = absint( $scan_id );

	$table = cerber_get_db_prefix() . CRB_SCANFILES_TABLE;

	$result = '<h3>' . __( 'Brief summary', 'wp-cerber' ) . '</h3>';

	$list = array(
		array( 'WordPress root directory (ABSPATH) ', ABSPATH ),
		array( 'WordPress uploads directory', cerber_get_upload_dir() ),
		array( 'WordPress content directory', dirname( cerber_get_plugins_dir() ) ),
		array( 'WordPress plugins directory', cerber_get_plugins_dir() ),
		array( 'WordPress themes directory', cerber_get_themes_dir() ),
		array( 'WordPress must-use plugin directory (WPMU_PLUGIN_DIR) ', WPMU_PLUGIN_DIR ),
		array( 'PHP directory for uploading files', ini_get( 'upload_tmp_dir' ) ),
		array( 'Server directory for temporary files', sys_get_temp_dir() ),
		array( 'Server directory for users\' session data', session_save_path() ),
	);

	$folders = array();

	foreach ( $list as $item ) {
		if ( ! $item[1] || ! @file_exists( $item[1] ) ) {
			continue;
		}
		$item[2] = 0;
		$item[3] = 0;
		$item[1] = rtrim( $item[1], DIRECTORY_SEPARATOR ) . DIRECTORY_SEPARATOR;
		if ( $files = cerber_db_get_col( 'SELECT file_size FROM ' . $table . ' WHERE scan_id = ' . $scan_id . ' AND file_name LIKE "' . $item[1] . '%"' ) ) {
			$item[2] = count( $files );
			if ( $sum = array_sum( $files ) ) {
				$item[3] = crb_size_format( $sum );
			}
		}
		$folders[] = $item;
	}

	$sql = 'SELECT file_size FROM ' . $table . ' WHERE scan_id = ' . $scan_id . ' AND file_name NOT LIKE "' . ABSPATH . '%"';
	$files = cerber_db_get_col( $sql );
	if ( $files ) {
		if ( $sum = array_sum( $files ) ) {
			$sum = crb_size_format( $sum );
		}
		$folders[] = array( 'Above the WordPress installation directory', '', count( $files ), $sum );
	}

	$column = array_column( $folders, 2 );
	array_multisort( $column, SORT_DESC, $folders );

	return $result . cerber_make_table( $folders, array(
			__( 'Directory', 'wp-cerber' ),
			__( 'Path', 'wp-cerber' ),
			__( 'Files', 'wp-cerber' ),
			__( 'Space Occupied', 'wp-cerber' )
		), '', 'crb-table-align-right-3', 'crb-monospace' );

}

function crb_scan_insights_exts( $scan_id ) {

	$scan_id = absint( $scan_id );

	$table = cerber_get_db_prefix() . CRB_SCANFILES_TABLE;
	$list = array();

	$offset = 0;
	$total = 0;
	$done = false;
	//cerber_exec_timer( 15 );

	while ( true ) {

		if ( ! $files = cerber_db_get_results( 'SELECT file_name, file_name_hash, file_mtime, file_size, file_ext FROM ' . $table . ' WHERE scan_id = ' . $scan_id . ' LIMIT ' . CRB_SQL_CHUNK . ' OFFSET ' . $offset ) ) {
			$done = true;
			break;
		}

		$offset += CRB_SQL_CHUNK;

		foreach ( $files as $file ) {
			if ( ! $ext = crb_get_extension( $file['file_name'] ) ) {
				$ext = '.';
			}


			if ( empty( $file['file_ext'] ) ) {
				cerber_db_query( 'UPDATE ' . $table . ' SET file_ext = "' . $ext . '" WHERE scan_id = ' . $scan_id . ' AND file_name_hash = "' . $file['file_name_hash'] . '"' );
			}

			if ( ! isset( $list[ $ext ] ) ) {
				$list[ $ext ] = array( 0, 0, array(), array() );
			}

			$list[ $ext ][0] ++;
			$list[ $ext ][1] += $file['file_size'];

			$list[ $ext ][2][] = $file['file_size'];
			$list[ $ext ][3][] = $file['file_mtime'];

			$total ++;
		}

	}

	if ( ! $done && ( count( $files ) < CRB_SQL_CHUNK ) ) {
		$done = true;
	}

	if ( ! $done ) {
		return array( 'continue' => 1 );
	}

	if ( ! $list ) {
		return crb_scan_no_message();
	}

	$base = crb_admin_link_for_html( 'scan_insights' );
	$none = __( 'No extension', 'wp-cerber' );
	$result = array();

	foreach ( $list as $ext => $data ) {
		$text = ( $ext == '.' ) ? $none : $ext;
		$result[] = array(
			'<a href="' . $base . '&amp;fext=' . esc_attr( $ext ) . '">' . $text . '</a>',
			$data[0],
			crb_size_format( $data[1] ),
			crb_size_format( min( $data[2] ) ),
			crb_size_format( max( $data[2] ) ),
			crb_size_format( round( $data[1] / $data[0], 0 ) ),
			cerber_date( min( $data[3] ) ),
			cerber_date( max( $data[3] ) ),
		);
	}

	// Sorting by a column in a multidimensional array

	$column = array_column( $result, 1 );
	array_multisort( $column, SORT_DESC, $result );

	// Create table

	//$report = '<h3>The file system report is based on the last full scan.</h3>';
	$report = '<h3>' . __( 'File extensions statistics', 'wp-cerber' ) . '</h3>';

	$report .= cerber_make_table( $result, array(
		__( 'Extension', 'wp-cerber' ),
		__( 'Files', 'wp-cerber' ),
		__( 'Space Occupied', 'wp-cerber' ),
		__( 'Smallest', 'wp-cerber' ),
		__( 'Largest', 'wp-cerber' ),
		__( 'Average Size', 'wp-cerber' ),
		__( 'Oldest', 'wp-cerber' ),
		__( 'Newest', 'wp-cerber' ),
	), 'crb-ext-statistics', 'crb_align_right', 'crb-monospace crb-anchor-decorated' );

	return $report;
}

function crb_scan_insights_lrgst( $scan_id ) {

	$scan_id = absint( $scan_id );

	$files_revalt = warp_run_db( static function ( CRB_Database $db ) use ( $scan_id ): Revalt {
		return $db->table( cerber_get_db_prefix() . CRB_SCANFILES_TABLE )
		          ->select( 'file_name', 'file_mtime', 'file_size' )
		          ->where( 'scan_id', '=', $scan_id )
		          ->order_by( 'file_size', 'DESC' )
		          ->limit( 10 )
		          ->get_query_results();
	} );

	if ( $files_revalt->has_errors() ) {
		return crb_scan_no_message();
	}

	$files = $files_revalt->get_results( array() );

	if ( empty( $files ) ) {
		return crb_scan_no_message();
	}

	$title = '<h3>' . __( 'Top 10 largest files', 'wp-cerber' ) . '</h3>';

	return $title . crb_make_file_table( $files );
}

function crb_scan_insights_duplicates( $scan_id ) {

	$scan_id = absint( $scan_id );

	// SQL Doesn't work
	/* ( ! $files = cerber_db_get_results( 'SELECT file_name, file_mtime, file_size, file_hash FROM ' . cerber_get_db_prefix() . CRB_SCANFILES_TABLE . ' WHERE scan_id = ' . $scan_id . ' GROUP BY file_hash HAVING COUNT(*) > 1 LIMIT 100' ) ) {
		return '';
	}*/

	if ( ! $files = cerber_db_get_col( 'SELECT file_hash FROM ' . cerber_get_db_prefix() . CRB_SCANFILES_TABLE . ' WHERE scan_id = ' . $scan_id . ' AND file_size !=0 AND file_hash !="" ' ) ) {
		return crb_scan_no_message();
	}

	$dup = array_unique( array_diff_assoc( $files, array_unique( $files ) ) );

	rsort( $dup );

	$list = array();
	foreach ( $dup as $hash ) {
		if ( $fl = cerber_db_get_results( 'SELECT file_name, file_mtime, file_size FROM ' . cerber_get_db_prefix() . CRB_SCANFILES_TABLE . ' WHERE scan_id = ' . $scan_id . ' AND file_hash = "' . $hash . '"' ) ) {
			$list = array_merge( $list, $fl );
		}
	}

	$result = '<h3>Duplicate files</h3>';

	return $result . crb_make_file_table( $list );

}

function crb_scan_last_full() {

	$scans = cerber_db_get_col( 'SELECT DISTINCT scan_id FROM ' . cerber_get_db_prefix() . CRB_SCANFILES_TABLE . ' WHERE scan_mode = 1 ORDER BY scan_id DESC LIMIT 1' );

	if ( $scans ) {
		$scan_id = $scans[0];
		$scan = cerber_get_scan( $scan_id );
		if ( $scan['finished']
		     || ( $scan['aborted'] && $scan['next_step'] > 5 ) ) { // Step 5 is enough for analysis
			return $scan_id;
		}
	}

	return false;
}

/**
 * @param int $user_id
 * @param string $tab
 * @param bool $cache_only
 *
 * @return string
 */
function crb_generate_user_insights( $user_id, $tab, $cache_only = false ) {

	if ( $tab != 'activity' ) {
		$tab = 'traffic';
	}

	$result = '';
	$links = array();

	if ( $user = crb_get_userdata( $user_id ) ) {
		$labels = cerber_get_labels();
		$list = array();

		if ( $data = crb_q_cache_get( 'SELECT COUNT(activity) as cnt, activity FROM ' . CERBER_LOG_TABLE . ' WHERE user_id = ' . $user_id . ' GROUP BY activity', CERBER_LOG_TABLE, $cache_only ) ) {
			foreach ( $data as $item ) {
				$list[ $item[1] ] = 1;
				$links[] = array( array( 'filter_activity' => $item[1], 'filter_user' => $user_id ), crb_array_get( $labels, $item[1], 'Unknown' ) . ' - ' . $item[0] );
			}
		}

		if ( $tab == 'activity' ) {
			if ( $data = crb_q_cache_get( 'SELECT COUNT(activity) as cnt, activity FROM ' . CERBER_LOG_TABLE . ' WHERE user_login = "' . $user->user_login . '" OR user_login = "' . $user->user_email . '" GROUP BY activity', CERBER_LOG_TABLE, $cache_only ) ) {
				foreach ( $data as $item ) {
					if ( isset( $list[ $item[1] ] ) ) {
						continue;
					}
					$links[] = array( array( 'filter_activity' => $item[1], 'filter_login' => $user->user_login . '|' . $user->user_email ), crb_array_get( $labels, $item[1], 'Unknown' ) . ' - ' . $item[0] );
				}
			}
		}

		if ( $links ) {
			array_unshift( $links, array( array( 'filter_user' => $user_id ), __( 'All' ) ) );
			$result = '<div id="crb-quick-insights">' . crb_build_quick_nav_block( $links, $tab ) . '</div>';
		}

	}

	if ( ! $result ) {
		if ( $cache_only ) {
			return '';
		}

		$result = __( 'No activity has been logged yet.', 'wp-cerber' );
	}

	return $result;
}

// Miscellaneous admin routines ===========================================================

/**
 * Detects file extension
 *
 * @param string $file_name
 *
 * @return string
 */
function crb_get_extension( $file_name ) {

	$name = basename( $file_name );

	if ( $name == '.htaccess' ) {
		return '';
	}

	if ( false === ( $last_dot = strrpos( $name, '.' ) ) ) {
		return '';
	}

	/*$first_dot = strpos( $name, '.' );

	if ( $last_dot !== $first_dot
	     && cerber_detect_exec_extension( $name ) ) {
		$ext = substr( $name, $first_dot + 1 );
	}
	else {
		$ext = substr( $name, $last_dot + 1 );
	}*/

	$ext = substr( $name, $last_dot + 1 );

	if ( ! $ext ) {
		$ext = '';
	}

	return $ext;
}

function crb_make_file_table( $files ) {

	$result = array();
	foreach ( $files as $file ) {
		$result[] = array(
			$file['file_name'],
			crb_size_format( $file['file_size'] ),
			cerber_date( $file['file_mtime'] ),
		);
	}

	return cerber_make_table( $result, array(
		__( 'File Name', 'wp-cerber' ),
		__( 'Size', 'wp-cerber' ),
		__( 'Modified', 'wp-cerber' ),
	), '', 'crb_align_right', 'crb-monospace crb-anchor-decorated' );

}

/**
 * Generates an HTML table
 *
 * @param array $rows Rows of the table. Each row is an array, and each cell can be a string or array ['class' => '', 'cell' => ''].
 * @param array $heading Optional array of column headings.
 * @param string $id Optional ID for the table.
 * @param string $class Optional class for the table.
 * @param string $body_class Optional class for the table body.
 * @param string $head_class Optional class for the table header.
 * @param bool $show_footer Whether to show a footer with the same content as the header.
 *
 * @return string HTML code of the table
 *
 * @since 8.6.4
 */
function cerber_make_table( array $rows, array $heading = array(), string $id = '', string $class = '', string $body_class = '', string $head_class = '', $show_footer = true ) {

	$tr = array();

	foreach ( $rows as $row ) {

        $tr_cells = array();

		foreach ( $row as $cell ) {

			if ( is_array( $cell ) ) {
				$cell_class = crb_escape_html( $cell['class'] ?? '' );
				$val        = $cell['cell'] ?? 'none';
			}
            else {
				$cell_class = '';
				$val        = $cell;
			}

			$tr_cells [] = '<td class="' . $cell_class . '">' . $val . '</td>';
		}

		$tr[] = implode( '', $tr_cells );
	}

	$tfoot = '';
	$thead = '';

	if ( $heading ) {

		$head_class = crb_escape_html( $head_class );

		$titles = '<tr><th>' . implode( '</th><th>', $heading ) . '</th></tr>';
		$thead = '<thead class="' . $head_class . '">' . $titles . '</thead>';

		if ( $show_footer ) {
			$tfoot = '<tfoot class="' . $head_class . '">' . $titles . '</tfoot>';
		}
	}

	$id = ( $id ) ? 'id="' . crb_escape_html( $id ) . '"' : '';

	return '<table ' . $id . ' class="widefat crb-table cerber-margin ' . crb_escape_html( $class ) . '">' . $thead . $tfoot . '<tbody class="' . crb_escape_html( $body_class ) . '"><tr>' . implode( '</tr><tr>', $tr ) . '</tr></tbody></table>';

}

function cerber_get_chmod( $file ) {
	return substr( sprintf( '%o', @fileperms( $file ) ), - 4 );
}

function cerber_get_size( $file ) {
	$size = @filesize( $file );

	return ( is_numeric( $size ) ) ? $size : 0;
}

function cerber_get_date( $file ) {
	$mtime = @filemtime( $file );

	return ( is_numeric( $mtime ) ) ? $mtime : 0;
}

function crb_show_admin_announcement( $text = '', $big = true ) {
	$class = ( $big ) ? 'crb-cerber-logo-big' : 'crb-cerber-logo-small';

    echo '<div class="cerber-msg crb-announcement crb-dismiss-scope' . ' ' . $class . '"><table><tr><td id="crb-ann-logo"></td>' .
	     '<td id="crb-ann-text"><div>' . $text . '</div></td></tr></table></div>';
}

/**
 * Retrieves query parameters from the URL of the currently displayed page or AJAX referrer.
 *
 * Supports both standard requests and AJAX requests. For AJAX requests, query parameters
 * are extracted from the "referrer_page_url" request field. If the query parameters do not
 * contain specific keys from the $list, those keys are added with empty string values.
 *
 * @param array $list An optional list of specific query parameters to retrieve.
 *                    Missing query parameters will be included in the result with empty string values.
 *
 * @return array An associative array of query parameters with basic sanitization applied.
 *
 */
function crb_get_referrer_params( array $list = array() ): array {

	$query_params = array();

	if ( cerber_is_wp_ajax() ) {
		if ( $ref_url = crb_get_request_field( 'referrer_page_url' ) ) {
			if ( $temp = parse_url( $ref_url, PHP_URL_QUERY ) ) {
				parse_str( $temp, $query_params );
			}
		}
	}
	else {
		$query_params = crb_get_query_params();
	}

	if ( ! is_array( $query_params ) ) {
		$query_params = array();
	}

	if ( ! empty( $list ) ) {
		$default_values = array_fill_keys( $list, '' );
		$query_params = array_merge( $default_values, array_intersect_key( $query_params, $default_values ) );
	}

	array_walk_recursive( $query_params, function ( &$item ) {
		$item = preg_replace( '/[^\w\-.:*|@]/i', '', $item ); // Some basic sanitization
	} );

	return $query_params;
}

/**
 * Returns info about the theme/plugin a given file belongs to
 *
 * @param string $file
 *
 * @return string
 *
 * @since 9.5.5.8
 */
function crb_get_file_owner( $file ): string {

	$ret = '';
	$file_type = crb_detect_file_type( $file );

	switch ( $file_type ) {
		case CERBER_FT_WP:
			$ret = 'WordPress';
			break;

		case CERBER_FT_PLUGIN:

			$parts = explode( DIRECTORY_SEPARATOR, ltrim( mb_substr( $file, strlen( cerber_get_plugins_dir() ) ), DIRECTORY_SEPARATOR ), 2 );

			$plugin_folder = $parts[0] . DIRECTORY_SEPARATOR;
			$result = false;

			foreach ( get_plugins() as $id => $item ) {
				if ( 0 === strpos( $id, $plugin_folder ) ) {
					$result = $item;
					break;
				}
			}

			if ( $result ) {
				$ret = 'Plugin: ' . $result['Name'] . ' by ' . $result['Author'] . ( $result['AuthorURI'] ? ' (' . $result['AuthorURI'] . ')' : '' );
			}

			break;

		case CERBER_FT_THEME:

			$parts = explode( DIRECTORY_SEPARATOR, ltrim( mb_substr( $file, strlen( cerber_get_themes_dir() ) ), DIRECTORY_SEPARATOR ), 2 );
			$theme_folder = $parts[0];
			$wp_themes = wp_get_themes();

			if ( $theme = $wp_themes[ $theme_folder ] ?? false ) {
				$ret = 'Theme: ' . $theme->get( 'Name' ) . ' ' . $theme->get( 'Version' ) . ' by ' . $theme->get( 'Author' );
			}

			break;
	}

	return $ret;
}

add_filter( 'manage_application-passwords-user_columns', function ( $columns ) {
	end( $columns );
	$key = key( $columns );
	$last = array_pop( $columns );

	return array_merge( $columns,
		array(
			'app_cerber_log_ok'   => __( 'Authorized', 'wp-cerber' ),
			'app_cerber_log_fail' => __( 'Authorization Failed', 'wp-cerber' ),
			$key                  => $last
		) );
} );

add_action( 'manage_application-passwords-user_custom_column', function ( $column_name, $item ) {
	global $user_id;
	if ( $column_name == 'app_cerber_log_ok' && ! empty( $item['last_ip'] ) ) {
		$link = cerber_activity_link( array( 4 ) ) . '&amp;filter_user=' . $user_id;
		echo '<a href="' . $link . '">View Log</a>';
	}
	if ( $column_name == 'app_cerber_log_fail' ) {
		$user = get_user_by( 'ID', $user_id );
		$link = cerber_activity_link( array( 8 ) ) . '&amp;filter_login=' . $user->user_email . '|' . $user->user_login;
		echo '<a href="' . $link . '">View Log</a>';
	}

}, 10, 2 );

/**
 * Streams the HTTP request traffic log as a CSV download and terminates the current request.
 *
 * Builds an unbounded traffic export from the supplied admin filter arguments and writes the CSV
 * response headers, metadata, column headings, and every matching row to the output stream. The
 * accepted filters are the traffic log query arguments listed in CRB_Traffic_Log::QUERY_PARAMS,
 * the same filters used by the traffic admin screen; any filter absent from $params falls back to the
 * current request's query parameters.
 *
 * @param array<string,mixed> $params Optional traffic log filter arguments; supplied values take
 *                                    precedence over the current request's query parameters.
 *
 * @return void This function does not return to the caller.
 */
function cerber_export_traffic( $params = array() ) {

	crb_try_raise_php_limits( '512M' );

	// Keep the stream projection aligned with the CSV mapping below.
	$args = is_array( $params ) ? $params : array();
	$args['columns'] = array( 'ip', 'stamp', 'uri', 'session_id', 'user_id', 'processing', 'request_method', 'http_code', 'wp_type', 'blog_id' );

	if ( crb_get_settings( 'plain_date' ) ) {
		function _crb_csv_date( $timestamp ) {
			static $gmt_offset;
			if ( $gmt_offset === null ) {
				$gmt_offset = get_option( 'gmt_offset' ) * 3600;
			}

			return date( 'Y-m-d H:i:s', $timestamp + $gmt_offset );
		}
	}
	else {
		function _crb_csv_date( $timestamp ) {
			return cerber_date( $timestamp, false );
		}
	}

	// Delay header output until export setup is known to be valid.

	$send_header = static function ( int $total, array $range ) {

		$info = array();

		if ( $range ) {
			$info[] = array( 'Newest record:', _crb_csv_date( $range['newest'] ) );
			$info[] = array( 'Oldest record:', _crb_csv_date( $range['oldest'] ) );
		}

		$heading = array(
			__( 'IP address', 'wp-cerber' ),
			__( 'Date', 'wp-cerber' ),
			'Method',
			'URI',
			'HTTP Code',
			'Request ID',
			__( 'User ID', 'wp-cerber' ),
			__( 'Page generation time', 'wp-cerber' ),
			'Blog ID',
			'Type',
			'Unix Timestamp',
		);

		cerber_send_csv_header( 'wp-cerber-http-requests', $total, $heading, $info );
	};

	// Resolve query metadata before output so setup errors can still use wp_die().

	$export = CRB_Traffic_Log::stream_log( $args );

	if ( $export->has_errors() ) {

		$error_message = __( 'WP Cerber: unable to export the traffic log.', 'wp-cerber' );

		// Show internal diagnostics only to administrators.

		if ( current_user_can( 'manage_options' ) ) {
			$root_cause = $export->get_root_cause();

			if ( $root_cause ) {
				$error_message .= $root_cause['message'] . ' [ERROR CODE: ' . $root_cause['code'] . ']';
			}
		}

		wp_die( crb_escape_html( $error_message ) );
	}

	$total  = (int) $export->get_element( 'total', 0 );
	$range  = $export->get_element( 'range', array() );
	$stream = $export->get_element( 'stream', array() );

	// Make the stream handle the only remaining owner of the unbuffered result.
	$export = null;

	$first = true;

	// Always release the unbuffered result, including future early exits.
	try {
		foreach ( $stream as $row ) {

			if ( $first ) {
				$send_header( $total, $range );
				$first = false;
			}

			$values = array();

			$values[] = $row->ip;
			$values[] = _crb_csv_date( $row->stamp );
			$values[] = $row->request_method;
			$values[] = $row->uri;
			$values[] = $row->http_code;
			$values[] = $row->session_id;
			$values[] = $row->user_id;
			$values[] = $row->processing;
			$values[] = $row->blog_id;
			$values[] = $row->wp_type;
			$values[] = $row->stamp;

			cerber_send_csv_line( $values );
		}
	}
	finally {
		// Trigger generator cleanup before sending the final response terminator.
		$stream = null;
	}

	if ( $first ) {
		$send_header( $total, $range );
	}

	exit;
}
/**
 * Streams the activity log as a CSV download and terminates the current request.
 *
 * Builds an unbounded activity export from the supplied admin filter arguments, writes the CSV
 * response headers, metadata, column headings, and every matching row to the output stream. The
 * accepted filters are the same activity log query arguments handled by CRB_Activity::stream_log();
 * non-array input is ignored and treated as an empty filter set. Dates honor the plain_date setting.
 *
 * On export setup failure no CSV bytes are sent; the request is terminated with wp_die() and an
 * escaped diagnostic message. On success the function always emits a CSV file, including a
 * header-only file when no rows match, releases the unbuffered database stream, and exits.
 *
 * @param array<string,mixed> $params Optional activity log filter arguments.
 *
 * @return void This function does not return to the caller.
 */
function cerber_export_activity( $params = array() ) {

	crb_try_raise_php_limits( '512M' );

	// Preserve the validated admin filters for the export stream.
	$args = is_array( $params ) ? $params : array();

	$labels        = cerber_get_labels( 'activity' );
	$status_labels = cerber_get_labels( 'status' ) + crb_get_lockout_reason();

	$placeholder = array( 0, '', '', '', '' );

	if ( crb_get_settings( 'plain_date' ) ) {
		function _crb_csv_date( $timestamp ) {
			static $gmt_offset;
			if ( $gmt_offset === null ) {
				$gmt_offset = get_option( 'gmt_offset' ) * 3600;
			}

			return date( 'Y-m-d H:i:s', $timestamp + $gmt_offset );
		}
	}
	else {
		function _crb_csv_date( $timestamp ) {
			return cerber_date( $timestamp, false );
		}
	}

	// Delay header output until export setup is known to be valid.

	$send_header = static function ( int $total, array $filters, array $range ) {

		$info = array();

		if ( $filters['ip'] ) {
			$info[] = array( 'Filter by IP:', $filters['ip'] );
		}

		if ( $filters['user_id'] ) {
			$user      = crb_get_userdata( $filters['user_id'] );
			$user_name = $user ? $user->display_name : '';
			$info[]    = array( 'Filter by user:', $user_name );
		}

		if ( $filters['search'] ) {
			$info[] = array( 'Search results for:', $filters['search'] );
		}

		if ( $range ) {
			$info[] = array( 'Newest record:', _crb_csv_date( $range['newest'] ) );
			$info[] = array( 'Oldest record:', _crb_csv_date( $range['oldest'] ) );
		}

		$heading = array(
			__( 'IP Address', 'wp-cerber' ),
			__( 'Date', 'wp-cerber' ),
			__( 'Event', 'wp-cerber' ),
			__( 'Status', 'wp-cerber' ),
			__( 'Local User', 'wp-cerber' ),
			__( 'User login', 'wp-cerber' ),
			__( 'User ID', 'wp-cerber' ),
			__( 'Username', 'wp-cerber' ),
			__( 'By user', 'wp-cerber' ),
			'Unix Timestamp',
			'Request ID',
			'URL',
		);

		cerber_send_csv_header( 'wp-cerber-activity', $total, $heading, $info );
	};

	// Resolve query metadata before output so setup errors can still use wp_die().

	$export = CRB_Activity::stream_log( $args );

	if ( $export->has_errors() ) {

		$export_message = __( 'WP Cerber: unable to export the activity log.', 'wp-cerber' );

		// Show internal diagnostics only to administrators.

		if ( current_user_can( 'manage_options' ) ) {
			$root_cause = $export->get_root_cause();

			if ( $root_cause ) {
				$export_message .= ' [' . $root_cause['code'] . '] ' . $root_cause['message'];
			}
		}

		wp_die( crb_escape_html( $export_message ) );
	}

	$total   = (int) $export->get_element( 'total', 0 );
	$filters = $export->get_element( 'filters', array() );
	$range   = $export->get_element( 'range', array() );
	$stream  = $export->get_element( 'stream', array() );

	// Make the stream handle the only remaining owner of the unbuffered result.
	$export = null;

	$first = true;

	// Always release the unbuffered result, including future early exits.
	try {
		foreach ( $stream as $row ) {

			if ( $first ) {
				$send_header( $total, $filters, $range );
				$first = false;
			}

			$values = array();

			if ( ! empty( $row->details ) ) {
				$details = explode( '|', $row->details );
			}
			else {
				$details = $placeholder;
			}

			$values[] = $row->ip;
			$values[] = _crb_csv_date( $row->stamp );
			$values[] = $labels[ $row->activity ];

			$values[] = $status_labels[ $row->ac_status ] ?? '';

			$values[] = $row->display_name;
			$values[] = $row->ulogin;
			$values[] = $row->user_id;
			$values[] = $row->user_login;

			$values[] = $row->ac_by_user;

			$values[] = $row->stamp;
			$values[] = $row->session_id;
			$values[] = $details[4];

			cerber_send_csv_line( $values );
		}
	}
	finally {
		// Trigger generator cleanup before sending the final response terminator.
		$stream = null;
	}

	if ( $first ) {
		$send_header( $total, $filters, $range );
	}

	exit;

}

/**
 * Sends HTTP headers and outputs the initial metadata and column headings for a CSV export.
 *
 * Generated metadata, additional info rows, and headings are all escaped by
 * cerber_send_csv_line(). The output uses CRLF line endings to preserve the
 * historical CSV export format.
 *
 * @param string $file_name_prefix Prefix for the downloaded file.
 * @param int $total Total number of rows expected.
 * @param array<int, string> $heading Optional list of column headings.
 * @param array<int, array<int, string>> $additional_info Optional list of metadata rows, each row being a list of cell values.
 *
 * @return void
 */
function cerber_send_csv_header( string $file_name_prefix, int $total, array $heading = array(), array $additional_info = array() ) {
	$file_name = $file_name_prefix . '-' . crb_site_label() . '.csv';

	crb_send_file_headers( $file_name, 'text/csv', true );

    // Common header info

	cerber_send_csv_line( array( 'Generated by:', 'WP Cerber Security ' . CERBER_VER ) );
	cerber_send_csv_line( array( 'Website:', crb_get_blogname_decoded() ) );
	cerber_send_csv_line( array( 'Date:', cerber_date( time(), false ) ) );
	cerber_send_csv_line( array( 'Rows in this file:', (string) $total ) );

	// Additional header info

	foreach ( $additional_info as $info_row ) {
		cerber_send_csv_line( $info_row );
	}

	echo "\r\n";

	if ( empty( $heading ) ) {
		return;
	}

	cerber_send_csv_line( $heading );
}

/**
 * Formats and outputs a CSV line
 *
 * @param string[] $row_values
 *
 * @return void
 */
function cerber_send_csv_line( array $row_values ) {

	foreach ( $row_values as &$value ) {
		$value = '"' . str_replace( '"', '""', trim( (string) $value ) ) . '"';
	}

	echo implode( ',', $row_values ) . "\r\n";
}

/**
 * Sends HTTP headers for a database export download (tables or settings).
 * Optionally disables output buffering to allow direct streaming for massive tables.
 *
 * @param string $file_name The name of the file to be downloaded.
 * @param string $ct Content-Type header value.
 * @param bool $disable_buffering Set to true ONLY for streaming large datasets via Generator.
 */
function crb_send_file_headers( string $file_name, string $ct = 'text/csv', bool $disable_buffering = false ): void {
	$file_name = rawurlencode( $file_name );

	if ( $disable_buffering ) {
		// Aggressively destroy all buffer layers
		while ( ob_get_level() > 0 ) {
			ob_end_clean();
		}
		// Bypass Nginx FastCGI buffering
		header( 'X-Accel-Buffering: no' );
	}
	else {
		// Safely clear only the topmost buffer to remove any garbage (e.g., BOM)
		if ( ob_get_level() > 0 ) {
			ob_clean();
		}
	}

	header( "Content-Type: {$ct}" );
	header( "Content-Disposition: attachment; filename*=UTF-8''{$file_name}" );

	// Prevent caching of sensitive DB dumps
	header( 'Cache-Control: no-store' );
}

function crb_admin_download_file( $t, $query = array() ) {
	switch ( $t ) {
		case 'activity':
			cerber_export_activity( $query );
			break;
		case 'traffic':
			cerber_export_traffic( $query );
			break;
		case 'get_diag_log':
			cerber_manage_diag_log( 'download' );
			break;
	}
}

/**
 * Disable Jetpack's Asset CDN on the WP Cerber admin pages
 *
 * @since 9.5.1
 */
add_filter(
	'jetpack_force_disable_site_accelerator',
	function () {
		if ( cerber_is_admin_page() ) {
			return true;
		}

		return false;
	}
);

Home - Capital GMC Buick Regina

No data

Welcome to Capital GMC BUICK – REGINA

Thank you for choosing Capital GMC Buick | Regina, your premier certified Buick and GMC dealership proudly serving drivers in Regina and the surrounding communities. Whether you’re searching for a brand-new Buick or GMC vehicle or a meticulously inspected pre-owned model, we have a diverse selection to match your needs and lifestyle.

Beyond our impressive inventory, we offer a seamless and stress-free financing experience through our well-connected finance centre, where our team of experts is dedicated to securing the best loan or lease options for you, quickly, transparently, and hassle-free.

But our commitment to you doesn’t stop at the sale. Our state-of-the-art service centre is staffed with skilled Buick and GMC technicians who use the latest equipment and genuine OEM parts to keep your vehicle running at its best. From routine maintenance to complex repairs, we’ve got you covered.

Experience top-tier customer service, quality vehicles, and expert care, all in one place. Visit Capital GMC Buick | Regina today or call us at 306-205-8072 with any questions. We’re here to help!

Ask a Question