# code-profiler/1.4/lib/ajax.php

Code Profiler – WordPress Performance Profiling and Debugging Made Easy, version 1.4. 301 lines.

- Page: https://pluginprobe.com/plugins/code-profiler/1.4/code/lib/ajax.php
- Raw: https://pluginprobe.com/plugins/code-profiler/1.4/raw/lib/ajax.php
- Modified: 2022-03-30T03:29:58+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/code-profiler/1.4/code/lib/ajax.php#L10-L20`.

```php
<?php
/*
 +=====================================================================+
 |    ____          _        ____             __ _ _                   |
 |   / ___|___   __| | ___  |  _ \ _ __ ___  / _(_) | ___ _ __         |
 |  | |   / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__|        |
 |  | |__| (_) | (_| |  __/ |  __/| | | (_) |  _| | |  __/ |           |
 |   \____\___/ \__,_|\___| |_|   |_|  \___/|_| |_|_|\___|_|           |
 |                                                                     |
 |  (c) Jerome Bruandet ~ https://code-profiler.com/                   |
 +=====================================================================+
*/

if (! defined( 'ABSPATH' ) ) { die( 'Forbidden' ); }

// =====================================================================
// Start the profiler.

add_action( 'wp_ajax_codeprofiler_start_profiler', 'codeprofiler_start_profiler' );

function codeprofiler_start_profiler() {

	$response = ['status' => 'error'];

	$cp_options = get_option( 'code-profiler' );

	// If this is an AJAX call, make sure it comes from an admin/superadmin.
	if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'codeprofiler_start_profiler' ) {
		// Admin/Superadmin only
		if (! is_super_admin() ) {
			$msg = esc_html__('You are not allowed to performed this action', 'code-profiler');
			$response['message'] = $msg;
			code_profiler_log_error( $msg );
			code_profiler_wp_send_json( $response );
		}
	}

	// Verify the security nonce
	if ( empty( $_POST['cp_nonce'] ) || ! wp_verify_nonce( $_POST['cp_nonce'], 'start_profiler_nonce' ) ) {
		$msg = esc_html__('Missing or wrong security nonce. Reload the page and try again', 'code-profiler');
		$response['message'] = $msg;
		code_profiler_log_error( $msg );
		code_profiler_wp_send_json( $response );
	}

	// Verify the MU plugin is loaded
	if (! defined('CODE_PROFILER_MU_ON') ) {
		$msg = esc_html__('The MU plugin is not loaded, please check the log', 'code-profiler');
		$response['message'] = $msg;
		code_profiler_log_error( $msg );
		code_profiler_wp_send_json( $response );
	}

	// Frontend or backend
	if ( empty( $_POST['where'] ) || ! in_array( $_POST['where'], [ 'frontend', 'backend', 'custom' ] ) ) {
		$msg = sprintf( esc_html__('Missing or incorrect parameter (%s)', 'code-profiler'), 'where' );
		$response['message'] = $msg;
		code_profiler_log_error( $msg );
		code_profiler_wp_send_json( $response );
	}
	if ( empty( $_POST['post'] ) ) {
		$msg = sprintf( esc_html__('Missing or incorrect parameter (%s)', 'code-profiler'), 'post' );
		$response['message'] = $msg;
		code_profiler_log_error( $msg );
		code_profiler_wp_send_json( $response );
	}

	// Make sure we have no more that 4 decimals, because when returning
	// it via AJAX, it will display more decimals than that
	$microtime = number_format( microtime( true ), 4, '.', '' );

	// Authentication
	if ( empty( $_POST['user'] ) || ! in_array( $_POST['user'], [ 'authenticated', 'unauthenticated' ] ) ) {
		$msg = sprintf( esc_html__('Missing or incorrect parameter (%s)', 'code-profiler'), 'user' );
		$response['message'] = $msg;
		code_profiler_log_error( $msg );
		code_profiler_wp_send_json( $response );
	}

	if ( empty( $_POST['profile'] ) || strlen( $_POST['profile'] ) > 100 ) {
		$profile = code_profiler_profile_name();
	} else {
		$profile = sanitize_file_name( $_POST['profile'] );
	}

	// URI to profile
	$url = esc_url_raw( $_POST['post'] );
	code_profiler_log_info( sprintf(
		esc_html__('Starting Code Profiler v%s for %s (profile: %s)', 'code-profiler' ),
		CODE_PROFILER_VERSION,
		$url,
		$profile
	) );

	// User-agent
	if ( empty( $_POST['ua'] ) ) {
		$ua = 'FireFox';
	} else {
		$ua = sanitize_text_field( $_POST['ua'] );
	}
	foreach( CODE_PROFILER_UA as $types => $types_array ) {
		foreach( $types_array as $name => $value ) {
			if ( $ua == $name ) {
				$ua_signature = $value;
				break;
			}
		}
	}
	if ( empty( $ua_signature ) ) {
		$ua_signature = CODE_PROFILER_UA['Desktop']['FireFox'];
	}

	// Create security key
	$profiler_key			= bin2hex( random_bytes( 16 ) );
	$cp_options['hash']	= sha1( $profiler_key );
	update_option( 'code-profiler', $cp_options );

	// Build query
	$url = add_query_arg( [
		'CODE_PROFILER_ON'	=> $microtime,
		'profiler_key'			=> $profiler_key,
	], $url );

	global $wp_version;
	$headers = [
		'Cache-Control' 	=> 'no-cache, no-store, must-revalidate',
		'Pragma' 			=> 'no-cache',
		'Expires' 			=> '0',
		'httpversion'   	=> '1.1',
		// Devs must be allowed to use it on localhost over TLS too
		'sslverify'     	=> apply_filters( 'https_local_ssl_verify', false ),
		'timeout'       	=> 180,	// 180-second timeout instead of the default 5s
		'redirection'		=> 0,		// We don't want to be redirected
		'headers'       	=> [
			'code-profiler-key' => $profiler_key,
			'Accept-Language'   => 'en-US,en;q=0.5',
			'User-Agent'    	  => $ua_signature
		 ]
	];

	// Forward basic authentication if any (not available from WP CLI)
	if ( function_exists('apache_request_headers') ) {
		$apache_headers = apache_request_headers();
		if ( isset( $apache_headers['Authorization'] ) ) {
			$headers['headers']['Authorization'] = $apache_headers['Authorization'];
		}
	// WP-CLI (wp code-profiler run --u=FOO --p=BAR)
	} elseif ( defined('WP_CLI') && ! empty( $_POST['Authorization'] ) ) {
		$headers['headers']['Authorization'] = $_POST['Authorization'];
	}

	if ( $_POST['user'] == 'authenticated' ) {
		// Used for authentication
		if ( is_ssl() ) {
			$cookie_auth = SECURE_AUTH_COOKIE;
			$scheme      = 'secure_auth';
		} else {
			$cookie_auth = AUTH_COOKIE;
			$scheme      = 'auth';
		}
		$id 													= get_current_user_id();
		$headers['cookies'][ $cookie_auth ]			= wp_generate_auth_cookie( $id, time() + 180, $scheme );
		$headers['cookies'][ LOGGED_IN_COOKIE ]	= wp_generate_auth_cookie( $id, time() + 180, 'logged_in' );
		$session_id 										= session_id();
		if ( $session_id !== false ) {
			$session_name 									= session_name();
			$headers['cookies'][ $session_name ]	= $session_id;
		}
	}

	if ( function_exists( 'opcache_reset' )  ) {
		opcache_reset();
	}

	// We must allow developers to run the profiler
	// on a local IP (e.g, http://127.0.0.1/)
	add_filter( 'http_request_host_is_external', '__return_true' );
	$res = wp_safe_remote_get( $url, $headers );

	// Connection error
	if ( is_wp_error( $res ) ) {
		$msg = esc_html__('Cannot connect to the requested page: %s', 'code-profiler');
		$response['message'] = sprintf(
			$msg,
			esc_html( $res->get_error_message() )
		);
		code_profiler_log_error( sprintf( $msg, $res->get_error_message() ) );
		code_profiler_wp_send_json( $response );
	}

	// HTTP status code
	if (! empty( $cp_options['http_response'] ) ) {
		if ( preg_match( "/{$cp_options['http_response']}/", $res['response']['code'] ) ) {
			$msg = esc_html__('The website returned the following HTTP status code: %s %s.', 'code-profiler').
					' '.
					esc_html__('By default, the profiler will always abort and throw an error if the server did not return a 200 HTTP status code. You can change that behaviour in the Settings section if the page you are profiling needs to return a different code (3xx, 4xx or 5xx).', 'code-profiler');
			$response['message'] = sprintf(
				$msg,
				(int) $res['response']['code'],
				esc_html( $res['response']['message'] )
			);
			code_profiler_log_error( sprintf( $msg, $res['response']['code'], $res['response']['message'] ) );
			code_profiler_wp_send_json( $response );
		}
	}
	// Check response
	$message = json_decode( $res['body'], true );
	if ( isset( $message['status'] ) && isset( $message['message'] ) ) {
		$response['status']	= $message['status'];
		$response['message']	= $message['message'];
		code_profiler_wp_send_json( $response );
	}
	code_profiler_log_info( esc_html__('Collecting data to analyze', 'code-profiler' ) );
	// Return success
	$response					= ['status' => 'success'];
	$response['message']		= 'success';
	$response['microtime']	= $microtime;

	// AJAX action?
	if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
		code_profiler_wp_send_json( $response );
	} else {
		return json_encode( $response );
	}

}

// =====================================================================

add_action( 'wp_ajax_codeprofiler_prepare_report', 'codeprofiler_prepare_report' );

function codeprofiler_prepare_report() {

	$response = ['status' => 'error'];

	// If this is an AJAX call, make sure it comes from an admin/superadmin.
	if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'codeprofiler_prepare_report' ) {
		// Admin/Superadmin only
		if (! is_super_admin() ) {
			$msg = esc_html__('You are not allowed to performed this action', 'code-profiler');
			$response['message'] = $msg;
			code_profiler_log_error( $msg );
			code_profiler_wp_send_json( $response );
		}
	}

	// Verify the security nonce
	if ( empty( $_POST['cp_nonce'] ) || ! wp_verify_nonce( $_POST['cp_nonce'], 'start_profiler_nonce' ) ) {
		$msg = esc_html__('Missing or wrong security nonce. Reload the page and try again', 'code-profiler');
		$response['message'] = $msg;
		code_profiler_log_error( $msg );
		code_profiler_wp_send_json( $response );
	}

	if ( empty( $_POST['microtime'] ) || ! preg_match( '/^\d{10}\.\d+$/', $_POST['microtime'] ) ) {
		$msg = esc_html__('Missing parameter (microtime).', 'code-profiler');
		$response['message'] = $msg;
		code_profiler_log_error( $msg );
		code_profiler_wp_send_json( $response );
	}
	$microtime = sanitize_text_field( $_POST['microtime'] );

	$profile = sanitize_file_name( $_POST['profile'] );
	if ( empty( $profile ) ) {
		$msg = esc_html__('Missing profile name.', 'code-profiler');
		$response['message'] = $msg;
		code_profiler_log_error( $msg );
		code_profiler_wp_send_json( $response );
	}

	code_profiler_log_info( esc_html__('Preparing report', 'code-profiler') );
	require 'class-report.php';
	$report = new CodeProfiler_Report( $profile, $microtime );
	$report->prepare_report();

	// Take a 1s break so that we can spot any potential error
	// in the backend before AJAX refresh the page
	usleep(1000000);

	// Clear hash
	$cp_options = get_option( 'code-profiler' );
	unset( $cp_options['hash']	);
	update_option( 'code-profiler', $cp_options );

	code_profiler_log_info( esc_html__('All done, exiting profiler', 'code-profiler') );
	$response['cp_profile']  = $microtime;
	$response['status']  = 'success';
	$response['message'] = 'success';

	// AJAX action?
	if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
		code_profiler_wp_send_json( $response );
	} else {
		return json_encode( $response );
	}

}

// =====================================================================
// EOF

```
