| @@ -23,8 +23,12 @@ | ||
| 23 | 23 | $response = ['status' => 'error']; |
| 24 | 24 | |
| 25 | 25 | $cp_options = get_option('code-profiler'); |
| 26 | 26 | |
| 27 | + code_profiler_log_debug( | |
| 28 | + esc_html__('Entering AJAX endpoint (profiler initialization)', 'code-profiler') | |
| 29 | + ); | |
| 30 | + | |
| 27 | 31 | // If this is an AJAX call, make sure it comes from an admin/superadmin. |
| 28 | 32 | if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'codeprofiler_start_profiler') { |
| 29 | 33 | // Admin/Superadmin only |
| 30 | 34 | if (! is_super_admin() ) { |
| @@ -34,8 +38,12 @@ | ||
| 34 | 38 | code_profiler_wp_send_json( $response ); |
| 35 | 39 | } |
| 36 | 40 | } |
| 37 | 41 | |
| 42 | + code_profiler_log_debug( | |
| 43 | + esc_html__('Verifying security nonce', 'code-profiler') | |
| 44 | + ); | |
| 45 | + | |
| 38 | 46 | // Verify the security nonce |
| 39 | 47 | if ( empty( $_POST['cp_nonce'] ) || ! wp_verify_nonce( $_POST['cp_nonce'], 'start_profiler_nonce') ) { |
| 40 | 48 | $msg = esc_html__('Missing or wrong security nonce. Reload the page and try again', 'code-profiler'); |
| 41 | 49 | $response['message'] = $msg; |
| @@ -42,8 +50,12 @@ | ||
| 42 | 50 | code_profiler_log_error( $msg ); |
| 43 | 51 | code_profiler_wp_send_json( $response ); |
| 44 | 52 | } |
| 45 | 53 | |
| 54 | + code_profiler_log_debug( | |
| 55 | + esc_html__('Checking MU plugin availability', 'code-profiler') | |
| 56 | + ); | |
| 57 | + | |
| 46 | 58 | // Verify the MU plugin is loaded |
| 47 | 59 | if (! defined('CODE_PROFILER_MU_ON') ) { |
| 48 | 60 | $msg = esc_html__('The MU plugin is not loaded, please check the log', 'code-profiler'); |
| 49 | 61 | $response['message'] = $msg; |
| @@ -50,11 +62,19 @@ | ||
| 50 | 62 | code_profiler_log_error( $msg ); |
| 51 | 63 | code_profiler_wp_send_json( $response ); |
| 52 | 64 | } |
| 53 | 65 | |
| 66 | + code_profiler_log_debug( | |
| 67 | + esc_html__('Cleaning up the temporary folder', 'code-profiler') | |
| 68 | + ); | |
| 69 | + | |
| 54 | 70 | // Clean-up temp files left in the profiles folder |
| 55 | 71 | code_profiler_cleantmpfiles(); |
| 56 | 72 | |
| 73 | + code_profiler_log_debug( | |
| 74 | + esc_html__('Retrieving parameters #1', 'code-profiler') | |
| 75 | + ); | |
| 76 | + | |
| 57 | 77 | // Frontend or backend |
| 58 | 78 | if ( empty( $_POST['where'] ) || ! in_array( $_POST['where'], ['frontend', 'backend', 'custom'] ) ) { |
| 59 | 79 | $msg = sprintf( esc_html__('Missing or incorrect parameter (%s)', 'code-profiler'), 'where'); |
| 60 | 80 | $response['message'] = $msg; |
| @@ -62,8 +82,12 @@ | ||
| 62 | 82 | code_profiler_wp_send_json( $response ); |
| 63 | 83 | } |
| 64 | 84 | $cp_options['mem_where'] = $_POST['where']; |
| 65 | 85 | |
| 86 | + code_profiler_log_debug( | |
| 87 | + esc_html__('Retrieving parameters #2', 'code-profiler') | |
| 88 | + ); | |
| 89 | + | |
| 66 | 90 | if ( empty( $_POST['post'] ) ) { |
| 67 | 91 | $msg = sprintf( esc_html__('Missing or incorrect parameter (%s)', 'code-profiler'), 'post'); |
| 68 | 92 | $response['message'] = $msg; |
| 69 | 93 | code_profiler_log_error( $msg ); |
| @@ -74,8 +98,12 @@ | ||
| 74 | 98 | // Make sure we have no more that 4 decimals, because when returning |
| 75 | 99 | // it via AJAX, it will display more decimals than that |
| 76 | 100 | $microtime = number_format( microtime( true ), 4, '.', ''); |
| 77 | 101 | |
| 102 | + code_profiler_log_debug( | |
| 103 | + esc_html__('Retrieving parameters #3', 'code-profiler') | |
| 104 | + ); | |
| 105 | + | |
| 78 | 106 | // Authentication |
| 79 | 107 | if ( empty( $_POST['user'] ) || ! in_array( $_POST['user'], ['authenticated', 'unauthenticated'] ) ) { |
| 80 | 108 | $msg = sprintf( esc_html__('Missing or incorrect parameter (%s)', 'code-profiler'), 'user'); |
| 81 | 109 | $response['message'] = $msg; |
| @@ -83,8 +111,12 @@ | ||
| 83 | 111 | code_profiler_wp_send_json( $response ); |
| 84 | 112 | } |
| 85 | 113 | $cp_options['mem_user'] = $_POST['user']; |
| 86 | 114 | |
| 115 | + code_profiler_log_debug( | |
| 116 | + esc_html__('Retrieving parameters #4', 'code-profiler') | |
| 117 | + ); | |
| 118 | + | |
| 87 | 119 | if ( empty( $_POST['profile'] ) || strlen( $_POST['profile'] ) > 100 ) { |
| 88 | 120 | $profile = code_profiler_profile_name(); |
| 89 | 121 | } else { |
| 90 | 122 | $profile = sanitize_file_name( $_POST['profile'] ); |
| @@ -92,14 +124,18 @@ | ||
| 92 | 124 | |
| 93 | 125 | // URI to profile |
| 94 | 126 | $url = esc_url_raw( $_POST['post'] ); |
| 95 | 127 | code_profiler_log_info( sprintf( |
| 96 | - esc_html__('Starting Code Profiler v%s for %s (profile: %s)', 'code-profiler'), | |
| 128 | + esc_html__('Initializing Code Profiler v%s for %s (profile: %s)', 'code-profiler'), | |
| 97 | 129 | CODE_PROFILER_VERSION, |
| 98 | 130 | $url, |
| 99 | 131 | $profile |
| 100 | 132 | ) ); |
| 101 | 133 | |
| 134 | + code_profiler_log_debug( | |
| 135 | + esc_html__('Retrieving parameters #5', 'code-profiler') | |
| 136 | + ); | |
| 137 | + | |
| 102 | 138 | // User-agent |
| 103 | 139 | if ( empty( $_POST['ua'] ) ) { |
| 104 | 140 | $ua = 'Firefox'; |
| 105 | 141 | } else { |
| @@ -117,12 +153,20 @@ | ||
| 117 | 153 | $ua_signature = CODE_PROFILER_UA['Desktop']['Firefox']; |
| 118 | 154 | } |
| 119 | 155 | $cp_options['ua'] = $ua; |
| 120 | 156 | |
| 157 | + code_profiler_log_debug( | |
| 158 | + esc_html__('Creating security key', 'code-profiler') | |
| 159 | + ); | |
| 160 | + | |
| 121 | 161 | // Create security key |
| 122 | 162 | $profiler_key = bin2hex( random_bytes( 16 ) ); |
| 123 | 163 | $cp_options['hash'] = sha1( $profiler_key ); |
| 124 | 164 | |
| 165 | + code_profiler_log_debug( | |
| 166 | + esc_html__('Building HTTP query', 'code-profiler') | |
| 167 | + ); | |
| 168 | + | |
| 125 | 169 | // Build query |
| 126 | 170 | $url = add_query_arg( [ |
| 127 | 171 | 'CODE_PROFILER_ON' => $microtime, |
| 128 | 172 | 'profiler_key' => $profiler_key |
| @@ -135,9 +179,9 @@ | ||
| 135 | 179 | 'Expires' => '0', |
| 136 | 180 | 'httpversion' => '1.1', |
| 137 | 181 | // Devs must be allowed to use it on localhost over TLS too |
| 138 | 182 | 'sslverify' => apply_filters('https_local_ssl_verify', false ), |
| 139 | - 'timeout' => 180, // 180-second timeout instead of the default 5s | |
| 183 | + 'timeout' => 300, // 300-second timeout instead of the default 5s | |
| 140 | 184 | 'redirection' => 0, // We don't want to be redirected |
| 141 | 185 | 'headers' => [ |
| 142 | 186 | 'code-profiler-key' => $profiler_key, |
| 143 | 187 | 'Accept-Language' => 'en-US,en;q=0.5', |
| @@ -144,8 +188,12 @@ | ||
| 144 | 188 | 'User-Agent' => $ua_signature |
| 145 | 189 | ] |
| 146 | 190 | ]; |
| 147 | 191 | |
| 192 | + code_profiler_log_debug( | |
| 193 | + esc_html__('Checking HTTP options', 'code-profiler') | |
| 194 | + ); | |
| 195 | + | |
| 148 | 196 | // Forward basic authentication if any (not available from WP CLI) |
| 149 | 197 | if ( function_exists('apache_request_headers') ) { |
| 150 | 198 | $apache_headers = apache_request_headers(); |
| 151 | 199 | if ( isset( $apache_headers['Authorization'] ) ) { |
| @@ -150,14 +198,19 @@ | ||
| 150 | 198 | $apache_headers = apache_request_headers(); |
| 151 | 199 | if ( isset( $apache_headers['Authorization'] ) ) { |
| 152 | 200 | $headers['headers']['Authorization'] = $apache_headers['Authorization']; |
| 153 | 201 | } |
| 154 | - // WP-CLI (wp code-profiler run --u=FOO --p=BAR) | |
| 202 | + // WP-CLI ($ wp code-profiler run --u=FOO --p=BAR) | |
| 155 | 203 | } elseif ( defined('WP_CLI') && ! empty( $_POST['Authorization'] ) ) { |
| 156 | 204 | $headers['headers']['Authorization'] = $_POST['Authorization']; |
| 157 | 205 | } |
| 158 | 206 | |
| 159 | 207 | if ( $_POST['user'] == 'authenticated') { |
| 208 | + | |
| 209 | + code_profiler_log_debug( | |
| 210 | + esc_html__('Creating authentication cookies', 'code-profiler') | |
| 211 | + ); | |
| 212 | + | |
| 160 | 213 | // Used for authentication |
| 161 | 214 | if ( is_ssl() ) { |
| 162 | 215 | $cookie_auth = SECURE_AUTH_COOKIE; |
| 163 | 216 | $scheme = 'secure_auth'; |
| @@ -181,25 +234,52 @@ | ||
| 181 | 234 | $response['message'] = $msg; |
| 182 | 235 | code_profiler_log_error( $msg ); |
| 183 | 236 | code_profiler_wp_send_json( $response ); |
| 184 | 237 | } |
| 185 | - $cp_options['mem_username'] = strtolower( $username ); | |
| 238 | + $cp_options['mem_username'] = strtolower( $username ); | |
| 186 | 239 | $headers['cookies'][ $cookie_auth ] = wp_generate_auth_cookie( $user_object->ID, time() + 180, $scheme ); |
| 240 | + if ( empty( $headers['cookies'][ $cookie_auth ] ) ) { | |
| 241 | + $msg = esc_html__('Unable to create the authentication cookie', 'code-profiler'); | |
| 242 | + code_profiler_log_error( $msg ); | |
| 243 | + $response['message'] = $msg; | |
| 244 | + code_profiler_wp_send_json( $response ); | |
| 245 | + } | |
| 187 | 246 | $headers['cookies'][ LOGGED_IN_COOKIE ] = wp_generate_auth_cookie( $user_object->ID, time() + 180, 'logged_in'); |
| 247 | + if ( empty( $headers['cookies'][ LOGGED_IN_COOKIE ] ) ) { | |
| 248 | + $msg = esc_html__('Unable to create the "logged_in" cookie', 'code-profiler'); | |
| 249 | + code_profiler_log_error( $msg ); | |
| 250 | + $response['message'] = $msg; | |
| 251 | + code_profiler_wp_send_json( $response ); | |
| 252 | + } | |
| 188 | 253 | // WP CLI |
| 189 | 254 | } else { |
| 190 | 255 | $id = get_current_user_id(); |
| 191 | 256 | $headers['cookies'][ $cookie_auth ] = wp_generate_auth_cookie( $id, time() + 180, $scheme ); |
| 257 | + if ( empty( $headers['cookies'][ $cookie_auth ] ) ) { | |
| 258 | + $msg = esc_html__('Unable to create the authentication cookie', 'code-profiler'); | |
| 259 | + code_profiler_log_error( $msg ); | |
| 260 | + $response['message'] = $msg; | |
| 261 | + code_profiler_wp_send_json( $response ); | |
| 262 | + } | |
| 192 | 263 | $headers['cookies'][ LOGGED_IN_COOKIE ] = wp_generate_auth_cookie( $id, time() + 180, 'logged_in'); |
| 264 | + if ( empty( $headers['cookies'][ LOGGED_IN_COOKIE ] ) ) { | |
| 265 | + $msg = esc_html__('Unable to create the "logged_in" cookie', 'code-profiler'); | |
| 266 | + code_profiler_log_error( $msg ); | |
| 267 | + $response['message'] = $msg; | |
| 268 | + code_profiler_wp_send_json( $response ); | |
| 269 | + } | |
| 193 | 270 | } |
| 194 | - $session_id = session_id(); | |
| 271 | + $session_id = session_id(); | |
| 195 | 272 | if ( $session_id !== false ) { |
| 196 | - $session_name = session_name(); | |
| 197 | - $headers['cookies'][ $session_name ] = $session_id; | |
| 273 | + $session_name = session_name(); | |
| 274 | + $headers['cookies'][ $session_name ] = $session_id; | |
| 198 | 275 | } |
| 199 | 276 | } |
| 200 | 277 | |
| 201 | 278 | if ( function_exists('opcache_reset') ) { |
| 279 | + code_profiler_log_debug( | |
| 280 | + esc_html__('Clearing opcode cache', 'code-profiler') | |
| 281 | + ); | |
| 202 | 282 | opcache_reset(); |
| 203 | 283 | } |
| 204 | 284 | |
| 205 | 285 | // GET or POST method |
| @@ -208,8 +288,13 @@ | ||
| 208 | 288 | $cp_options['mem_method'] = 'post'; |
| 209 | 289 | |
| 210 | 290 | // Optional POST payload |
| 211 | 291 | if (! empty( $_POST['payload'] ) ) { |
| 292 | + | |
| 293 | + code_profiler_log_debug( | |
| 294 | + esc_html__('Building POST payload', 'code-profiler') | |
| 295 | + ); | |
| 296 | + | |
| 212 | 297 | $payload_array = explode( PHP_EOL, trim( $_POST['payload'] ) ); |
| 213 | 298 | foreach( $payload_array as $item ) { |
| 214 | 299 | $payload = explode('=', trim( $item ), 2 ); |
| 215 | 300 | if ( isset( $payload[1] ) ) { |
| @@ -231,8 +316,13 @@ | ||
| 231 | 316 | } |
| 232 | 317 | |
| 233 | 318 | // Optional user-defined cookies |
| 234 | 319 | if (! empty( $_POST['cookies'] ) ) { |
| 320 | + | |
| 321 | + code_profiler_log_debug( | |
| 322 | + esc_html__('Building HTTP Cookies', 'code-profiler') | |
| 323 | + ); | |
| 324 | + | |
| 235 | 325 | $cookies_array = explode( PHP_EOL, trim( $_POST['cookies'] ) ); |
| 236 | 326 | foreach( $cookies_array as $item ) { |
| 237 | 327 | $cookie = explode('=', trim( $item ), 2 ); |
| 238 | 328 | if ( isset( $cookie[1] ) ) { |
| @@ -247,8 +337,12 @@ | ||
| 247 | 337 | } |
| 248 | 338 | |
| 249 | 339 | update_option('code-profiler', $cp_options ); |
| 250 | 340 | |
| 341 | + code_profiler_log_debug( | |
| 342 | + esc_html__('Sending HTTP request', 'code-profiler') | |
| 343 | + ); | |
| 344 | + | |
| 251 | 345 | // We must allow developers to run the profiler |
| 252 | 346 | // on a local IP (e.g, http://127.0.0.1/) |
| 253 | 347 | add_filter('http_request_host_is_external', '__return_true'); |
| 254 | 348 | $res = $safe_method( $url, $headers ); |
| @@ -263,8 +357,12 @@ | ||
| 263 | 357 | code_profiler_log_error( sprintf( $msg, $res->get_error_message() ) ); |
| 264 | 358 | code_profiler_wp_send_json( $response ); |
| 265 | 359 | } |
| 266 | 360 | |
| 361 | + code_profiler_log_debug( | |
| 362 | + esc_html__('Fetching HTTP response', 'code-profiler') | |
| 363 | + ); | |
| 364 | + | |
| 267 | 365 | // HTTP status code |
| 268 | 366 | if (! empty( $cp_options['http_response'] ) ) { |
| 269 | 367 | if ( preg_match( "/{$cp_options['http_response']}/", $res['response']['code'] ) ) { |
| 270 | 368 | $msg = esc_html__('The website returned the following HTTP status code: %s %s.', 'code-profiler'). |
| @@ -278,8 +376,13 @@ | ||
| 278 | 376 | code_profiler_log_error( sprintf( $msg, $res['response']['code'], $res['response']['message'] ) ); |
| 279 | 377 | code_profiler_wp_send_json( $response ); |
| 280 | 378 | } |
| 281 | 379 | } |
| 380 | + | |
| 381 | + code_profiler_log_debug( | |
| 382 | + esc_html__('Decoding body', 'code-profiler') | |
| 383 | + ); | |
| 384 | + | |
| 282 | 385 | // Check response |
| 283 | 386 | $message = json_decode( $res['body'], true ); |
| 284 | 387 | if ( isset( $message['status'] ) && isset( $message['message'] ) ) { |
| 285 | 388 | $response['status'] = $message['status']; |
| @@ -285,21 +388,27 @@ | ||
| 285 | 388 | $response['status'] = $message['status']; |
| 286 | 389 | $response['message'] = $message['message']; |
| 287 | 390 | code_profiler_wp_send_json( $response ); |
| 288 | 391 | } |
| 289 | - code_profiler_log_info( esc_html__('Collecting data to analyze', 'code-profiler') ); | |
| 392 | + code_profiler_log_info( | |
| 393 | + esc_html__('Collecting data to analyze', 'code-profiler') | |
| 394 | + ); | |
| 290 | 395 | // Return success |
| 291 | 396 | $response = ['status' => 'success']; |
| 292 | 397 | $response['message'] = 'success'; |
| 293 | 398 | $response['microtime'] = $microtime; |
| 294 | 399 | |
| 400 | + code_profiler_log_debug( | |
| 401 | + esc_html__('Leaving AJAX endpoint', 'code-profiler') | |
| 402 | + ); | |
| 403 | + | |
| 295 | 404 | // AJAX action? |
| 296 | 405 | if ( defined('DOING_AJAX') && DOING_AJAX ) { |
| 297 | 406 | code_profiler_wp_send_json( $response ); |
| 298 | - } else { | |
| 299 | - return json_encode( $response ); | |
| 300 | 407 | } |
| 301 | 408 | |
| 409 | + return json_encode( $response ); | |
| 410 | + | |
| 302 | 411 | } |
| 303 | 412 | |
| 304 | 413 | // ===================================================================== |
| 305 | 414 | |
| @@ -308,8 +417,12 @@ | ||
| 308 | 417 | function codeprofiler_prepare_report() { |
| 309 | 418 | |
| 310 | 419 | $response = ['status' => 'error']; |
| 311 | 420 | |
| 421 | + code_profiler_log_debug( | |
| 422 | + esc_html__('Entering AJAX endpoint (report preparation)', 'code-profiler') | |
| 423 | + ); | |
| 424 | + | |
| 312 | 425 | // If this is an AJAX call, make sure it comes from an admin/superadmin. |
| 313 | 426 | if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'codeprofiler_prepare_report') { |
| 314 | 427 | // Admin/Superadmin only |
| 315 | 428 | if (! is_super_admin() ) { |
| @@ -319,8 +432,12 @@ | ||
| 319 | 432 | code_profiler_wp_send_json( $response ); |
| 320 | 433 | } |
| 321 | 434 | } |
| 322 | 435 | |
| 436 | + code_profiler_log_debug( | |
| 437 | + esc_html__('Verifying security nonce', 'code-profiler') | |
| 438 | + ); | |
| 439 | + | |
| 323 | 440 | // Verify the security nonce |
| 324 | 441 | if ( empty( $_POST['cp_nonce'] ) || ! wp_verify_nonce( $_POST['cp_nonce'], 'start_profiler_nonce') ) { |
| 325 | 442 | $msg = esc_html__('Missing or wrong security nonce. Reload the page and try again', 'code-profiler'); |
| 326 | 443 | $response['message'] = $msg; |
| @@ -327,8 +444,12 @@ | ||
| 327 | 444 | code_profiler_log_error( $msg ); |
| 328 | 445 | code_profiler_wp_send_json( $response ); |
| 329 | 446 | } |
| 330 | 447 | |
| 448 | + code_profiler_log_debug( | |
| 449 | + esc_html__('Retrieving profile ID', 'code-profiler') | |
| 450 | + ); | |
| 451 | + | |
| 331 | 452 | if ( empty( $_POST['microtime'] ) || ! preg_match('/^\d{10}\.\d+$/', $_POST['microtime'] ) ) { |
| 332 | 453 | $msg = esc_html__('Missing parameter (microtime).', 'code-profiler'); |
| 333 | 454 | $response['message'] = $msg; |
| 334 | 455 | code_profiler_log_error( $msg ); |
| @@ -335,8 +456,12 @@ | ||
| 335 | 456 | code_profiler_wp_send_json( $response ); |
| 336 | 457 | } |
| 337 | 458 | $microtime = sanitize_text_field( $_POST['microtime'] ); |
| 338 | 459 | |
| 460 | + code_profiler_log_debug( | |
| 461 | + esc_html__('Retrieving profile name', 'code-profiler') | |
| 462 | + ); | |
| 463 | + | |
| 339 | 464 | $profile = sanitize_file_name( $_POST['profile'] ); |
| 340 | 465 | if ( empty( $profile ) ) { |
| 341 | 466 | $msg = esc_html__('Missing profile name.', 'code-profiler'); |
| 342 | 467 | $response['message'] = $msg; |
| @@ -343,9 +468,11 @@ | ||
| 343 | 468 | code_profiler_log_error( $msg ); |
| 344 | 469 | code_profiler_wp_send_json( $response ); |
| 345 | 470 | } |
| 346 | 471 | |
| 347 | - code_profiler_log_info( esc_html__('Preparing report', 'code-profiler') ); | |
| 472 | + code_profiler_log_info( | |
| 473 | + esc_html__('Preparing the report', 'code-profiler') | |
| 474 | + ); | |
| 348 | 475 | require 'class-report.php'; |
| 349 | 476 | $report = new CodeProfiler_Report( $profile, $microtime ); |
| 350 | 477 | $report->prepare_report(); |
| 351 | 478 | |
| @@ -357,19 +484,81 @@ | ||
| 357 | 484 | $cp_options = get_option('code-profiler'); |
| 358 | 485 | unset( $cp_options['hash'] ); |
| 359 | 486 | update_option('code-profiler', $cp_options ); |
| 360 | 487 | |
| 361 | - code_profiler_log_info( esc_html__('All done, exiting profiler', 'code-profiler') ); | |
| 488 | + code_profiler_log_info( | |
| 489 | + esc_html__('All done, exiting profiler', 'code-profiler') | |
| 490 | + ); | |
| 362 | 491 | $response['cp_profile'] = $microtime; |
| 363 | 492 | $response['status'] = 'success'; |
| 364 | 493 | $response['message'] = 'success'; |
| 365 | 494 | |
| 495 | + code_profiler_log_debug( | |
| 496 | + esc_html__('Leaving AJAX endpoint', 'code-profiler') | |
| 497 | + ); | |
| 498 | + | |
| 366 | 499 | // AJAX action? |
| 367 | 500 | if ( defined('DOING_AJAX') && DOING_AJAX ) { |
| 368 | 501 | code_profiler_wp_send_json( $response ); |
| 369 | - } else { | |
| 370 | - return json_encode( $response ); | |
| 371 | 502 | } |
| 503 | + | |
| 504 | + return json_encode( $response ); | |
| 505 | + | |
| 506 | +} | |
| 507 | + | |
| 508 | +// ===================================================================== | |
| 509 | +// Rename a profile. | |
| 510 | + | |
| 511 | +add_action('wp_ajax_codeprofiler_rename', 'codeprofiler_rename'); | |
| 512 | + | |
| 513 | +function codeprofiler_rename() { | |
| 514 | + | |
| 515 | + $response = ['status' => 'error']; | |
| 516 | + | |
| 517 | + // Admin/Superadmin only | |
| 518 | + if (! is_super_admin() ) { | |
| 519 | + $response['message'] = esc_html__('You are not allowed to performed this action', 'code-profiler'); | |
| 520 | + wp_send_json( $response ); | |
| 521 | + } | |
| 522 | + | |
| 523 | + // Verify the security nonce | |
| 524 | + if ( empty( $_POST['cp_nonce'] ) || ! wp_verify_nonce( $_POST['cp_nonce'], 'rename-profile') ) { | |
| 525 | + $response['message'] = esc_html__('Missing or wrong security nonce. Reload the page and try again', 'code-profiler'); | |
| 526 | + wp_send_json( $response ); | |
| 527 | + } | |
| 528 | + | |
| 529 | + if ( empty( $_POST['new_name'] ) ) { | |
| 530 | + $response['message'] = esc_html__('Please enter a name for this profile.', 'code-profiler'); | |
| 531 | + wp_send_json( $response ); | |
| 532 | + } | |
| 533 | + $new_name = sanitize_file_name( $_POST['new_name'] ); | |
| 534 | + if ( strlen( $new_name ) > 100 ) { | |
| 535 | + $new_name = substr( $new_name, 0, 100 ); | |
| 536 | + } | |
| 537 | + if ( empty( $new_name ) ) { | |
| 538 | + $response['message'] = esc_html__('Please enter a name for this profile.', 'code-profiler'); | |
| 539 | + wp_send_json( $response ); | |
| 540 | + } | |
| 541 | + | |
| 542 | + if ( empty( $_POST['profile'] ) || ! preg_match('/^\d{10}\.\d{4}$/', $_POST['profile'] ) ) { | |
| 543 | + $response['message'] = esc_html__('Missing profile identifier.', 'code-profiler'); | |
| 544 | + wp_send_json( $response ); | |
| 545 | + } | |
| 546 | + $profile = $_POST['profile']; | |
| 547 | + | |
| 548 | + $glob = glob( CODE_PROFILER_UPLOAD_DIR ."/$profile*" ); | |
| 549 | + if ( is_array( $glob ) ) { | |
| 550 | + foreach( $glob as $path ) { | |
| 551 | + // preg_quote is needed for Windows servers because ABSPATH will contain backslashes | |
| 552 | + if ( preg_match('`^'. preg_quote( CODE_PROFILER_UPLOAD_DIR ) .'/(\d{10}\.\d{4})\..+?\.([a-z]+?\.profile)$`', $path, $match ) ) { | |
| 553 | + rename( $path, CODE_PROFILER_UPLOAD_DIR . "/{$match[1]}.$new_name.{$match[2]}" ); | |
| 554 | + } | |
| 555 | + } | |
| 556 | + } | |
| 557 | + | |
| 558 | + $response['status'] = 'success'; | |
| 559 | + $response['newname'] = $new_name; | |
| 560 | + wp_send_json( $response ); | |
| 372 | 561 | |
| 373 | 562 | } |
| 374 | 563 | |
| 375 | 564 | // ===================================================================== |