PluginProbe
Code Profiler – WordPress Performance Profiling and Debugging Made Easy / 1.6.8
Code Profiler – WordPress Performance Profiling and Debugging Made Easy v1.6.8
1.9.5 1.9.4 1.9.3 trunk 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.6 1.6.1 1.6.10 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 All 40 releases
code-profiler / lib / ajax.php

ajax.php in Code Profiler – WordPress Performance Profiling and Debugging Made Easy 1.6.8, at lib/ajax.php

691 lines 20.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /*
3 +=====================================================================+
4 | ____ _ ____ __ _ _ |
5 | / ___|___ __| | ___ | _ \ _ __ ___ / _(_) | ___ _ __ |
6 | | | / _ \ / _` |/ _ \ | |_) | '__/ _ \| |_| | |/ _ \ '__| |
7 | | |__| (_) | (_| | __/ | __/| | | (_) | _| | | __/ | |
8 | \____\___/ \__,_|\___| |_| |_| \___/|_| |_|_|\___|_| |
9 | |
10 | (c) Jerome Bruandet ~ https://code-profiler.com/ |
11 +=====================================================================+
12 */
13
14 if (! defined('ABSPATH') ) {
15 die('Forbidden');
16 }
17
18 // ===================================================================== 2023-11-17
19 // Start the profiler.
20
21 add_action('wp_ajax_codeprofiler_start_profiler', 'codeprofiler_start_profiler');
22
23 function codeprofiler_start_profiler() {
24
25 $response = ['status' => 'error'];
26
27 code_profiler_hide_errors();
28
29 $cp_options = get_option('code-profiler');
30
31 code_profiler_log_debug(
32 esc_html__('Entering AJAX endpoint (profiler initialization)', 'code-profiler')
33 );
34
35 // If this is an AJAX call, make sure it comes from an admin/superadmin.
36 if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'codeprofiler_start_profiler') {
37 // Admin/Superadmin only
38 if (! is_super_admin() ) {
39 $msg = esc_html__('You are not allowed to performed this action', 'code-profiler');
40 $response['message'] = $msg;
41 code_profiler_log_error( $msg );
42 code_profiler_wp_send_json( $response );
43 }
44 }
45
46 code_profiler_log_debug(
47 esc_html__('Verifying security nonce', 'code-profiler')
48 );
49
50 // Verify the security nonce
51 if ( empty( $_POST['cp_nonce'] ) ||
52 ! wp_verify_nonce( $_POST['cp_nonce'], 'start_profiler_nonce') ) {
53
54 $msg = esc_html__(
55 'Missing or wrong security nonce. Reload the page and try again',
56 'code-profiler'
57 );
58 $response['message'] = $msg;
59 code_profiler_log_error( $msg );
60 code_profiler_wp_send_json( $response );
61 }
62
63 code_profiler_log_debug(
64 esc_html__('Checking MU plugin availability', 'code-profiler')
65 );
66
67 // Verify the MU plugin is loaded
68 if (! defined('CODE_PROFILER_MU_ON') ) {
69 $msg = esc_html__('The MU plugin is not loaded, please check the log', 'code-profiler');
70 $response['message'] = $msg;
71 code_profiler_log_error( $msg );
72 code_profiler_wp_send_json( $response );
73 }
74
75 code_profiler_log_debug(
76 esc_html__('Cleaning up the temporary folder', 'code-profiler')
77 );
78
79 // Clean-up temp files left in the profiles folder
80 code_profiler_cleantmpfiles();
81
82 code_profiler_log_debug(
83 esc_html__('Retrieving parameters #1', 'code-profiler')
84 );
85
86 // Frontend or backend
87 if ( empty( $_POST['where'] ) ||
88 ! in_array( $_POST['where'], ['frontend', 'backend', 'custom'] ) ) {
89
90 $msg = sprintf(
91 esc_html__('Missing or incorrect parameter (%s)', 'code-profiler'), 'where'
92 );
93 $response['message'] = $msg;
94 code_profiler_log_error( $msg );
95 code_profiler_wp_send_json( $response );
96 }
97 $cp_options['mem_where'] = $_POST['where'];
98
99 code_profiler_log_debug(
100 esc_html__('Retrieving parameters #2', 'code-profiler')
101 );
102
103 if ( empty( $_POST['post'] ) ) {
104 $msg = sprintf( esc_html__('Missing or incorrect parameter (%s)', 'code-profiler'), 'post');
105 $response['message'] = $msg;
106 code_profiler_log_error( $msg );
107 code_profiler_wp_send_json( $response );
108 }
109 $cp_options['mem_post'] = $_POST['post'];
110
111 // Make sure we have no more that 4 decimals, because when returning
112 // it via AJAX, it will display more decimals than that
113 $microtime = number_format( microtime( true ), 4, '.', '');
114
115 code_profiler_log_debug(
116 esc_html__('Retrieving parameters #3', 'code-profiler')
117 );
118
119 // Authentication
120 if ( empty( $_POST['user'] ) || $_POST['user'] != 'authenticated' ) {
121 $_POST['user'] = 'unauthenticated';
122 }
123 $cp_options['mem_user'] = $_POST['user'];
124
125 code_profiler_log_debug(
126 esc_html__('Retrieving parameters #4', 'code-profiler')
127 );
128
129 if ( empty( $_POST['profile'] ) || strlen( $_POST['profile'] ) > 100 ) {
130 $profile = code_profiler_profile_name();
131 } else {
132 $profile = sanitize_file_name( $_POST['profile'] );
133 }
134
135 // URI to profile
136 $url = esc_url_raw( $_POST['post'] );
137 $siteurl = esc_html( site_url() );
138 code_profiler_log_info( sprintf(
139 /* Translators: version, site url, profile name, profile url */
140 esc_html__('Initializing Code Profiler v%s on %s. Profile: %s - %s', 'code-profiler'),
141 CODE_PROFILER_VERSION,
142 $siteurl,
143 $profile,
144 $url
145 ) );
146
147 code_profiler_log_debug(
148 esc_html__('Retrieving parameters #5', 'code-profiler')
149 );
150
151 // User-agent
152 if ( empty( $_POST['ua'] ) ) {
153 $ua = 'Firefox';
154 } else {
155 $ua = sanitize_text_field( $_POST['ua'] );
156 }
157 foreach( CODE_PROFILER_UA as $types => $types_array ) {
158 foreach( $types_array as $name => $value ) {
159 if ( $ua == $name ) {
160 $ua_signature = $value;
161 break;
162 }
163 }
164 }
165 if ( empty( $ua_signature ) ) {
166 $ua_signature = CODE_PROFILER_UA['Desktop']['Firefox'];
167 }
168 $cp_options['ua'] = $ua;
169
170 // Theme
171 $themes = code_profiler_get_themes();
172 if ( empty( $_POST['theme'] ) || empty( $themes[ $_POST['theme'] ] ) ) {
173 $theme = '';
174 unset( $cp_options['mem_theme'] );
175 } else {
176 code_profiler_log_debug(
177 esc_html__('Retrieving parameters #6', 'code-profiler')
178 );
179 $theme = $_POST['theme'];
180 $cp_options['mem_theme'] = $theme;
181 // Append the template to the stylesheet
182 if (! empty( $themes[ $theme ]['t'] ) ) {
183 $theme .= "::{$themes[ $theme ]['t']}";
184 } else {
185 $theme .= "::$theme";
186 }
187 }
188
189 code_profiler_log_debug(
190 esc_html__('Creating security key', 'code-profiler')
191 );
192
193 // Create security key
194 $profiler_key = bin2hex( random_bytes( 16 ) );
195 $cp_options['hash'] = sha1( $profiler_key );
196
197 code_profiler_log_debug(
198 esc_html__('Building HTTP query', 'code-profiler')
199 );
200
201 // Build query
202 $url = add_query_arg( [
203 'CODE_PROFILER_ON' => $microtime,
204 'profiler_key' => $profiler_key
205 ], $url );
206
207 global $wp_version;
208 $headers = [
209 'Cache-Control' => 'no-cache, no-store, must-revalidate',
210 'Pragma' => 'no-cache',
211 'Expires' => '0',
212 'httpversion' => '1.1',
213 // Devs must be allowed to use it on localhost over TLS too
214 'sslverify' => apply_filters('https_local_ssl_verify', false ),
215 'timeout' => 300, // 300-second timeout instead of the default 5s
216 'redirection' => 0, // We don't want to be redirected
217 'headers' => [
218 // Lowercase header name
219 'code-profiler-key' => $profiler_key,
220 'accept-language' => 'en-US,en;q=0.5',
221 'user-agent' => $ua_signature,
222 'theme' => $theme
223 ]
224 ];
225
226 // Custom HTTP headers
227 if (! empty( $_POST['custom_headers'] ) ) {
228 $custom_headers = explode( PHP_EOL, trim( stripslashes( $_POST['custom_headers'] ) ) );
229 if (! empty( $custom_headers[0] ) ) {
230 code_profiler_log_debug(
231 esc_html__('Building custom HTTP headers', 'code-profiler')
232 );
233 $is_custom_headers = '';
234 foreach( $custom_headers as $custom_header ) {
235 list( $key, $value ) = explode( ':', "$custom_header:" );
236 // Lowercase header name
237 $key = trim( strtolower( $key ) );
238 $value = trim( $value );
239 // We want printable ASCII characters only
240 $value = preg_replace('/[\x00-\x1f\x7f-\xff]/', '', $value);
241 if (! empty( $key ) && ! empty( $value ) ) {
242 $headers['headers'][ $key ] = $value;
243 $is_custom_headers .= "$key: $value\n";
244 }
245 }
246 }
247 }
248 if (! empty( $is_custom_headers ) ) {
249 $cp_options['custom_headers'] = json_encode( $is_custom_headers );
250 } else {
251 unset( $cp_options['custom_headers'] );
252 }
253
254 code_profiler_log_debug(
255 esc_html__('Checking HTTP options', 'code-profiler')
256 );
257
258 // Forward basic authentication if any (not available from WP CLI)
259 if ( function_exists('apache_request_headers') ) {
260 $apache_headers = apache_request_headers();
261 if ( isset( $apache_headers['Authorization'] ) ) {
262 $headers['headers']['Authorization'] = $apache_headers['Authorization'];
263 }
264 // WP-CLI ($ wp code-profiler run --u=FOO --p=BAR)
265 } elseif ( defined('WP_CLI') && ! empty( $_POST['Authorization'] ) ) {
266 $headers['headers']['Authorization'] = $_POST['Authorization'];
267 }
268
269 if ( $_POST['user'] == 'authenticated') {
270
271 code_profiler_log_debug(
272 esc_html__('Creating authentication cookies', 'code-profiler')
273 );
274
275 // Used for authentication
276 if ( is_ssl() ) {
277 $cookie_auth = SECURE_AUTH_COOKIE;
278 $scheme = 'secure_auth';
279 } else {
280 $cookie_auth = AUTH_COOKIE;
281 $scheme = 'auth';
282 }
283
284 // Retrieve the user name (since 1.4.3)
285 if (! defined('WP_CLI') ) {
286 if ( empty( $_POST['username'] ) ) {
287 $msg = esc_html__('Missing authenticated username', 'code-profiler');
288 $response['message'] = $msg;
289 code_profiler_log_error( $msg );
290 code_profiler_wp_send_json( $response );
291 }
292 $username = sanitize_user( $_POST['username'] );
293 $user_object = get_user_by('login', $username );
294 if ( $user_object === false ) {
295 $msg = sprintf( esc_html__('User [%s] does not exist.', 'code-profiler'), $username);
296 $response['message'] = $msg;
297 code_profiler_log_error( $msg );
298 code_profiler_wp_send_json( $response );
299 }
300 $cp_options['mem_username'] = strtolower( $username );
301 $headers['cookies'][ $cookie_auth ] = wp_generate_auth_cookie(
302 $user_object->ID,
303 time() + 180,
304 $scheme
305 );
306 if ( empty( $headers['cookies'][ $cookie_auth ] ) ) {
307 $msg = esc_html__('Unable to create the authentication cookie', 'code-profiler');
308 code_profiler_log_error( $msg );
309 $response['message'] = $msg;
310 code_profiler_wp_send_json( $response );
311 }
312 $headers['cookies'][ LOGGED_IN_COOKIE ] = wp_generate_auth_cookie(
313 $user_object->ID,
314 time() + 180,
315 'logged_in'
316 );
317 if ( empty( $headers['cookies'][ LOGGED_IN_COOKIE ] ) ) {
318 $msg = esc_html__('Unable to create the "logged_in" cookie', 'code-profiler');
319 code_profiler_log_error( $msg );
320 $response['message'] = $msg;
321 code_profiler_wp_send_json( $response );
322 }
323 // WP CLI
324 } else {
325 $id = get_current_user_id();
326 $headers['cookies'][ $cookie_auth ] = wp_generate_auth_cookie(
327 $id,
328 time() + 180,
329 $scheme
330 );
331 if ( empty( $headers['cookies'][ $cookie_auth ] ) ) {
332 $msg = esc_html__('Unable to create the authentication cookie', 'code-profiler');
333 code_profiler_log_error( $msg );
334 $response['message'] = $msg;
335 code_profiler_wp_send_json( $response );
336 }
337 $headers['cookies'][ LOGGED_IN_COOKIE ] = wp_generate_auth_cookie(
338 $id,
339 time() + 180,
340 'logged_in'
341 );
342 if ( empty( $headers['cookies'][ LOGGED_IN_COOKIE ] ) ) {
343 $msg = esc_html__('Unable to create the "logged_in" cookie', 'code-profiler');
344 code_profiler_log_error( $msg );
345 $response['message'] = $msg;
346 code_profiler_wp_send_json( $response );
347 }
348 }
349 $session_id = session_id();
350 if ( $session_id !== false ) {
351 $session_name = session_name();
352 $headers['cookies'][ $session_name ] = $session_id;
353 }
354 }
355
356 if ( function_exists('opcache_reset') ) {
357 code_profiler_log_debug(
358 esc_html__('Clearing opcode cache', 'code-profiler')
359 );
360 opcache_reset();
361 }
362
363 // GET or POST method
364 if (! empty( $_POST['method'] ) && $_POST['method'] == 'post') {
365 $safe_method = 'wp_safe_remote_post';
366 $cp_options['mem_method'] = 'post';
367
368 // Content-type
369 $content_type = [
370 1 => 'application/x-www-form-urlencoded',
371 2 => 'application/json'
372 ];
373 if ( empty( $_POST['content_type'] ) ||
374 ! in_array( $_POST['content_type'], [ 1, 2 ] ) ) {
375
376 $cp_options['mem_content_type'] = 1;
377 } else {
378 $cp_options['mem_content_type'] = (int) $_POST['content_type'];
379 }
380 $headers['headers']['content-type'] = $content_type[ $cp_options['mem_content_type'] ];
381
382 // Optional POST payload
383 if (! empty( $_POST['payload'] ) ) {
384 $_payload = trim( stripslashes( $_POST['payload'] ) );
385
386 code_profiler_log_debug(
387 esc_html__('Building POST payload', 'code-profiler')
388 );
389
390 // application/x-www-form-urlencoded
391 if ( $cp_options['mem_content_type'] == 1 ) {
392 $payload_array = explode( PHP_EOL, $_payload );
393 foreach( $payload_array as $item ) {
394 $payload = explode('=', trim( $item ), 2 );
395 if ( isset( $payload[1] ) ) {
396 $payload[0] = trim( $payload[0] );
397 $payload[1] = trim( $payload[1] );
398 $headers['body'][ $payload[0] ] = $payload[1];
399 }
400 }
401 } else {
402
403 $headers['body'] = $_payload;
404 }
405 $cp_options['payload'] = json_encode( $_payload );
406
407 } else {
408 // POST request without a payload
409 unset( $cp_options['payload'] );
410 }
411
412 } else {
413 $safe_method = 'wp_safe_remote_get';
414 $cp_options['mem_method'] = 'get';
415 }
416
417 // Optional user-defined cookies
418 if (! empty( $_POST['cookies'] ) ) {
419
420 code_profiler_log_debug(
421 esc_html__('Building HTTP Cookies', 'code-profiler')
422 );
423
424 $cookies_array = explode( PHP_EOL, trim( stripslashes( $_POST['cookies'] ) ) );
425 foreach( $cookies_array as $item ) {
426 $cookie = explode('=', trim( $item ), 2 );
427 if ( isset( $cookie[1] ) ) {
428 $cookie[0] = trim( $cookie[0] );
429 $cookie[1] = trim( $cookie[1] );
430 $headers['cookies'][ $cookie[0] ] = $cookie[1];
431 }
432 }
433 $cp_options['cookies'] = json_encode( $_POST['cookies'] );
434 } else {
435 unset( $cp_options['cookies'] );
436 }
437
438 update_option('code-profiler', $cp_options );
439
440 code_profiler_log_debug(
441 esc_html__('Sending HTTP request', 'code-profiler')
442 );
443
444 // We must allow developers to run the profiler
445 // on a local IP (e.g, http://127.0.0.1/)
446 add_filter('http_request_host_is_external', '__return_true');
447 $res = $safe_method( $url, $headers );
448
449 // Connection error
450 if ( is_wp_error( $res ) ) {
451 $msg = esc_html__('Cannot connect to the requested page: %s', 'code-profiler');
452 $response['message'] = sprintf(
453 $msg,
454 esc_html( $res->get_error_message() )
455 );
456 code_profiler_log_error( sprintf( $msg, $res->get_error_message() ) );
457 code_profiler_wp_send_json( $response );
458 }
459
460 code_profiler_log_debug(
461 esc_html__('Fetching HTTP response', 'code-profiler')
462 );
463
464 // HTTP status code
465 if (! empty( $cp_options['http_response'] ) ) {
466 if ( preg_match( "/{$cp_options['http_response']}/", $res['response']['code'] ) ) {
467 $log = esc_html__(
468 'The website returned the following HTTP status code: %s %s.', 'code-profiler'
469 );
470 if ( $res['response']['code'] >= 500 ) {
471 $msg = $log .' '. esc_html__(
472 'You may find more details about this error in your PHP error log.',
473 'code-profiler'
474 );
475 } else {
476 $msg = $log .' '. esc_html__('By default, the profiler will always abort and throw an error '.
477 'if the server did not return a 200 HTTP status code. You can change that behaviour in '.
478 'the Settings section if the page you are profiling needs to return a different '.
479 'code (3xx, 4xx or 5xx).', 'code-profiler');
480 }
481 $response['message'] = sprintf(
482 $msg,
483 (int) $res['response']['code'],
484 $res['response']['message']
485 );
486 code_profiler_log_error(
487 sprintf( $log, $res['response']['code'], $res['response']['message'] )
488 );
489 code_profiler_wp_send_json( $response );
490 }
491 }
492
493 code_profiler_log_debug(
494 esc_html__('Decoding body', 'code-profiler')
495 );
496
497 // Check response
498 $message = json_decode( $res['body'], true );
499 if ( isset( $message['status'] ) && isset( $message['message'] ) ) {
500 $response['status'] = $message['status'];
501 $response['message'] = $message['message'];
502 code_profiler_wp_send_json( $response );
503 }
504 code_profiler_log_info(
505 esc_html__('Collecting data to analyze', 'code-profiler')
506 );
507 // Return success
508 $response = ['status' => 'success'];
509 $response['message'] = 'success';
510 $response['microtime'] = $microtime;
511
512 code_profiler_log_debug(
513 esc_html__('Leaving AJAX endpoint', 'code-profiler')
514 );
515
516 // AJAX action?
517 if ( defined('DOING_AJAX') && DOING_AJAX ) {
518 code_profiler_wp_send_json( $response );
519 }
520
521 return json_encode( $response );
522
523 }
524
525 // ===================================================================== 2023-11-17
526
527 add_action('wp_ajax_codeprofiler_prepare_report', 'codeprofiler_prepare_report');
528
529 function codeprofiler_prepare_report() {
530
531 $response = ['status' => 'error'];
532
533 code_profiler_log_debug(
534 esc_html__('Entering AJAX endpoint (report preparation)', 'code-profiler')
535 );
536
537 code_profiler_hide_errors();
538
539 // If this is an AJAX call, make sure it comes from an admin/superadmin.
540 if ( isset( $_REQUEST['action'] ) && $_REQUEST['action'] == 'codeprofiler_prepare_report') {
541 // Admin/Superadmin only
542 if (! is_super_admin() ) {
543 $msg = esc_html__('You are not allowed to performed this action', 'code-profiler');
544 $response['message'] = $msg;
545 code_profiler_log_error( $msg );
546 code_profiler_wp_send_json( $response );
547 }
548 }
549
550 code_profiler_log_debug(
551 esc_html__('Verifying security nonce', 'code-profiler')
552 );
553
554 // Verify the security nonce
555 if ( empty( $_POST['cp_nonce'] ) ||
556 ! wp_verify_nonce( $_POST['cp_nonce'], 'start_profiler_nonce') ) {
557
558 $msg = esc_html__('Missing or wrong security nonce. Reload the page and try again',
559 'code-profiler');
560 $response['message'] = $msg;
561 code_profiler_log_error( $msg );
562 code_profiler_wp_send_json( $response );
563 }
564
565 code_profiler_log_debug(
566 esc_html__('Retrieving profile ID', 'code-profiler')
567 );
568
569 if ( empty( $_POST['microtime'] ) || ! preg_match('/^\d{10}\.\d+$/', $_POST['microtime'] ) ) {
570 $msg = esc_html__('Missing parameter (microtime).', 'code-profiler');
571 $response['message'] = $msg;
572 code_profiler_log_error( $msg );
573 code_profiler_wp_send_json( $response );
574 }
575 $microtime = sanitize_text_field( $_POST['microtime'] );
576
577 code_profiler_log_debug(
578 esc_html__('Retrieving profile name', 'code-profiler')
579 );
580
581 $profile = sanitize_file_name( $_POST['profile'] );
582 if ( empty( $profile ) ) {
583 $msg = esc_html__('Missing profile name.', 'code-profiler');
584 $response['message'] = $msg;
585 code_profiler_log_error( $msg );
586 code_profiler_wp_send_json( $response );
587 }
588
589 code_profiler_log_info(
590 esc_html__('Preparing the report', 'code-profiler')
591 );
592 require 'class-report.php';
593 $report = new CodeProfiler_Report( $profile, $microtime );
594 $report->prepare_report();
595
596 // Take a 1s break so that we can spot any potential error
597 // in the backend before AJAX refresh the page
598 usleep( 1000000 );
599
600 // Clear hash
601 $cp_options = get_option('code-profiler');
602 unset( $cp_options['hash'] );
603 update_option('code-profiler', $cp_options );
604
605 code_profiler_log_info(
606 esc_html__('All done, exiting profiler', 'code-profiler')
607 );
608 $response['cp_profile'] = $microtime;
609 $response['status'] = 'success';
610 $response['message'] = 'success';
611
612 code_profiler_log_debug(
613 esc_html__('Leaving AJAX endpoint', 'code-profiler')
614 );
615
616 // AJAX action?
617 if ( defined('DOING_AJAX') && DOING_AJAX ) {
618 code_profiler_wp_send_json( $response );
619 }
620
621 return json_encode( $response );
622
623 }
624
625 // ===================================================================== 2023-11-17
626 // Rename a profile.
627
628 add_action('wp_ajax_codeprofiler_rename', 'codeprofiler_rename');
629
630 function codeprofiler_rename() {
631
632 $response = ['status' => 'error'];
633
634 code_profiler_hide_errors();
635
636 // Admin/Superadmin only
637 if (! is_super_admin() ) {
638 $response['message'] = esc_html__(
639 'You are not allowed to performed this action', 'code-profiler'
640 );
641 wp_send_json( $response );
642 }
643
644 // Verify the security nonce
645 if ( empty( $_POST['cp_nonce'] ) || ! wp_verify_nonce( $_POST['cp_nonce'], 'rename-profile') ) {
646 $response['message'] = esc_html__(
647 'Missing or wrong security nonce. Reload the page and try again', 'code-profiler'
648 );
649 wp_send_json( $response );
650 }
651
652 if ( empty( $_POST['new_name'] ) ) {
653 $response['message'] = esc_html__('Please enter a name for this profile.', 'code-profiler');
654 wp_send_json( $response );
655 }
656 $new_name = sanitize_file_name( $_POST['new_name'] );
657 if ( strlen( $new_name ) > 100 ) {
658 $new_name = substr( $new_name, 0, 100 );
659 }
660 if ( empty( $new_name ) ) {
661 $response['message'] = esc_html__('Please enter a name for this profile.', 'code-profiler');
662 wp_send_json( $response );
663 }
664
665 if ( empty( $_POST['profile'] ) || ! preg_match('/^\d{10}\.\d{4}$/', $_POST['profile'] ) ) {
666 $response['message'] = esc_html__('Missing profile identifier.', 'code-profiler');
667 wp_send_json( $response );
668 }
669 $profile = $_POST['profile'];
670
671 $glob = glob( CODE_PROFILER_UPLOAD_DIR ."/$profile*" );
672 if ( is_array( $glob ) ) {
673 foreach( $glob as $path ) {
674 // preg_quote is needed for Windows servers because ABSPATH will contain backslashes
675 if ( preg_match('`^'. preg_quote( CODE_PROFILER_UPLOAD_DIR ) .
676 '/(\d{10}\.\d{4})\..+?\.([a-z]+?\.profile)$`', $path, $match ) ) {
677
678 rename( $path, CODE_PROFILER_UPLOAD_DIR . "/{$match[1]}.$new_name.{$match[2]}" );
679 }
680 }
681 }
682
683 $response['status'] = 'success';
684 $response['newname'] = $new_name;
685 wp_send_json( $response );
686
687 }
688
689 // =====================================================================
690 // EOF
691