Changeset 3451291
- Timestamp:
- 02/01/2026 09:15:18 AM (5 weeks ago)
- Location:
- 0-day-analytics
- Files:
-
- 38 edited
- 1 copied
-
tags/4.7.0 (copied) (copied from 0-day-analytics/trunk)
-
tags/4.7.0/advanced-analytics.php (modified) (2 diffs)
-
tags/4.7.0/classes/migration/class-migration.php (modified) (2 diffs)
-
tags/4.7.0/classes/vendor/controllers/class-hooks-capture.php (modified) (1 diff)
-
tags/4.7.0/classes/vendor/controllers/class-reverse-line-reader.php (modified) (13 diffs)
-
tags/4.7.0/classes/vendor/controllers/classes-snippets-controller.php (modified) (2 diffs)
-
tags/4.7.0/classes/vendor/entities/class-hooks-management-entity.php (modified) (1 diff)
-
tags/4.7.0/classes/vendor/entities/class-snippet-entity.php (modified) (1 diff)
-
tags/4.7.0/classes/vendor/entities/class-wp-fatals-entity.php (modified) (1 diff)
-
tags/4.7.0/classes/vendor/helpers/class-ajax-helper.php (modified) (5 diffs)
-
tags/4.7.0/classes/vendor/helpers/class-hook-parameter-renderer.php (modified) (7 diffs)
-
tags/4.7.0/classes/vendor/lists/class-fatals-list.php (modified) (4 diffs)
-
tags/4.7.0/classes/vendor/lists/class-hooks-capture-list.php (modified) (1 diff)
-
tags/4.7.0/classes/vendor/lists/class-hooks-management-list.php (modified) (4 diffs)
-
tags/4.7.0/classes/vendor/lists/class-logs-list.php (modified) (3 diffs)
-
tags/4.7.0/classes/vendor/lists/class-table-list.php (modified) (4 diffs)
-
tags/4.7.0/classes/vendor/lists/entity/class-common-table.php (modified) (1 diff)
-
tags/4.7.0/classes/vendor/lists/views/class-hooks-management-view.php (modified) (1 diff)
-
tags/4.7.0/classes/vendor/lists/views/class-logs-list-view.php (modified) (3 diffs)
-
tags/4.7.0/readme.txt (modified) (2 diffs)
-
trunk/advanced-analytics.php (modified) (2 diffs)
-
trunk/classes/migration/class-migration.php (modified) (2 diffs)
-
trunk/classes/vendor/controllers/class-hooks-capture.php (modified) (1 diff)
-
trunk/classes/vendor/controllers/class-reverse-line-reader.php (modified) (13 diffs)
-
trunk/classes/vendor/controllers/classes-snippets-controller.php (modified) (2 diffs)
-
trunk/classes/vendor/entities/class-hooks-management-entity.php (modified) (1 diff)
-
trunk/classes/vendor/entities/class-snippet-entity.php (modified) (1 diff)
-
trunk/classes/vendor/entities/class-wp-fatals-entity.php (modified) (1 diff)
-
trunk/classes/vendor/helpers/class-ajax-helper.php (modified) (5 diffs)
-
trunk/classes/vendor/helpers/class-hook-parameter-renderer.php (modified) (7 diffs)
-
trunk/classes/vendor/lists/class-fatals-list.php (modified) (4 diffs)
-
trunk/classes/vendor/lists/class-hooks-capture-list.php (modified) (1 diff)
-
trunk/classes/vendor/lists/class-hooks-management-list.php (modified) (4 diffs)
-
trunk/classes/vendor/lists/class-logs-list.php (modified) (3 diffs)
-
trunk/classes/vendor/lists/class-table-list.php (modified) (4 diffs)
-
trunk/classes/vendor/lists/entity/class-common-table.php (modified) (1 diff)
-
trunk/classes/vendor/lists/views/class-hooks-management-view.php (modified) (1 diff)
-
trunk/classes/vendor/lists/views/class-logs-list-view.php (modified) (3 diffs)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
0-day-analytics/tags/4.7.0/advanced-analytics.php
r3448917 r3451291 11 11 * Plugin Name: 0 Day Analytics 12 12 * Description: Take full control of error log, crons, transients, plugins, requests, mails and DB tables. 13 * Version: 4. 6.013 * Version: 4.7.0 14 14 * Author: Stoil Dobrev 15 15 * Author URI: https://github.com/sdobreff/ … … 39 39 // Constants. 40 40 if ( ! defined( 'ADVAN_VERSION' ) ) { 41 define( 'ADVAN_VERSION', '4. 6.0' );41 define( 'ADVAN_VERSION', '4.7.0' ); 42 42 define( 'ADVAN_TEXTDOMAIN', '0-day-analytics' ); 43 43 define( 'ADVAN_NAME', '0 Day Analytics' ); -
0-day-analytics/tags/4.7.0/classes/migration/class-migration.php
r3448917 r3451291 14 14 15 15 use ADVAN\Helpers\Settings; 16 use ADVAN\Entities\WP_Mail_Entity; 17 use ADVAN\Entities\WP_Fatals_Entity; 18 use ADVAN\Entities\Requests_Log_Entity; 16 19 use ADVAN\Entities_Global\Common_Table; 17 use ADVAN\Entities\WP_Mail_Entity;18 use ADVAN\Entities\Requests_Log_Entity;19 20 use ADVAN\Migration\Abstract_Migration; 20 21 … … 267 268 } 268 269 } 270 271 /** 272 * Migrates the plugin up-to version 4.7.0 (adds performance indexes to fatals table). 273 * 274 * @return void 275 * 276 * @since 4.7.0 277 */ 278 public static function migrate_up_to_470() { 279 if ( \class_exists( '\\ADVAN\\Entities\\WP_Fatals_Entity' ) ) { 280 if ( Common_Table::check_table_exists( WP_Fatals_Entity::get_table_name() ) ) { 281 WP_Fatals_Entity::alter_table_470(); 282 } 283 } 284 } 269 285 } 270 286 } -
0-day-analytics/tags/4.7.0/classes/vendor/controllers/class-hooks-capture.php
r3448917 r3451291 192 192 193 193 // In WP-CLI context, ensure hooks are attached properly. 194 if ( defined( 'WP_CLI' ) && WP_CLI ) {194 if ( defined( 'WP_CLI' ) && \WP_CLI ) { 195 195 self::attach_hooks_cli(); 196 196 } else { -
0-day-analytics/tags/4.7.0/classes/vendor/controllers/class-reverse-line-reader.php
r3393178 r3451291 28 28 29 29 /** 30 * Memory limit in MB before triggering cleanup or termination 31 */ 32 const MEMORY_LIMIT_MB = 32; 33 34 /** 35 * Time limit in seconds for processing 36 */ 37 const TIME_LIMIT_SECONDS = 25; 38 39 /** 40 * Maximum number of collected items to prevent memory exhaustion 41 */ 42 const MAX_COLLECTED_ITEMS = 1000; 43 44 /** 30 45 * Keeps track of of the current position in the file. 31 46 * … … 80 95 */ 81 96 private static $memory_handle = null; 97 98 /** 99 * Stores the overflow file handle for spilling data to disk when memory is critical. 100 * 101 * @var resource|null 102 * 103 * @since 1.9.3 104 */ 105 private static $overflow_handle = null; 82 106 83 107 /** … … 146 170 } 147 171 172 // Adaptive buffer sizing based on available memory. 173 $available_memory = self::get_available_memory_mb(); 174 if ( $available_memory < 50 ) { // Low memory system. 175 self::$buffer_size = min( self::$buffer_size, 4096 ); // Use smaller buffer. 176 } elseif ( $available_memory < 100 ) { // Medium memory system. 177 self::$buffer_size = min( self::$buffer_size, 8192 ); // Use medium buffer. 178 } 179 // Otherwise use default BUFFER_SIZE. 180 148 181 self::$file_size = - (int) $size; 149 182 } 183 184 // Initialize memory and time monitoring. 185 $start_time = time(); 186 $start_memory = memory_get_usage( true ); 187 $processed_lines = 0; 150 188 151 189 $line = self::readline(); … … 165 203 } 166 204 $result = $callback( $line, self::$pos ); 205 206 // Memory and time safety checks. 207 ++$processed_lines; 208 $current_memory_mb = ( memory_get_usage( true ) - $start_memory ) / 1024 / 1024; 209 $elapsed_time = time() - $start_time; 210 211 // Terminate if memory limit exceeded. 212 if ( $current_memory_mb > self::MEMORY_LIMIT_MB ) { 213 if ( function_exists( 'error_log' ) ) { 214 error_log( 'Reverse_Line_Reader: Memory limit exceeded (' . round( $current_memory_mb, 2 ) . 'MB), terminating processing' ); 215 } 216 self::reset_class_globals(); 217 $max_lines = 0; 218 return false; 219 } 220 221 // Create overflow file if memory is getting critical (80% of limit). 222 if ( $current_memory_mb > ( self::MEMORY_LIMIT_MB * 0.8 ) && null === self::$overflow_handle ) { 223 self::$overflow_handle = self::create_overflow_temp_file(); 224 if ( self::$overflow_handle && function_exists( 'error_log' ) ) { 225 error_log( 'Reverse_Line_Reader: Created overflow file due to high memory usage (' . round( $current_memory_mb, 2 ) . 'MB)' ); 226 } 227 } 228 229 // Terminate if time limit exceeded. 230 if ( $elapsed_time > self::TIME_LIMIT_SECONDS ) { 231 if ( function_exists( 'error_log' ) ) { 232 error_log( 'Reverse_Line_Reader: Time limit exceeded (' . $elapsed_time . 's), terminating processing' ); 233 } 234 self::reset_class_globals(); 235 $max_lines = 0; 236 return false; 237 } 167 238 168 239 if ( true === $result['close'] ) { … … 283 354 */ 284 355 public static function write_memory_file( string $line ) { 356 // If overflow file is active, write to it instead of memory. 357 if ( null !== self::$overflow_handle ) { 358 fwrite( self::$overflow_handle, $line ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite 359 return; 360 } 361 285 362 if ( null === self::$memory_handle ) { 286 363 self::$memory_handle = fopen( 'php://memory', 'w+' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen … … 301 378 rewind( self::$temp_handle ); // resets the position of pointer. 302 379 380 // Content is pre-escaped with esc_html() before being written to temp file 303 381 echo fread( self::$temp_handle, fstat( self::$temp_handle )['size'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread, WordPress.Security.EscapeOutput.OutputNotEscaped 304 382 … … 315 393 */ 316 394 public static function read_memory_file() { 317 if ( \is_resource( self::$memory_handle ) && ( 'handle' === get_resource_type( self::$memory_handle ) || 'stream' === get_resource_type( self::$memory_handle ) ) ) { 395 // If overflow file exists, read from it instead. 396 if ( \is_resource( self::$overflow_handle ) && ( 'handle' === get_resource_type( self::$overflow_handle ) || 'stream' === get_resource_type( self::$overflow_handle ) ) ) { 397 rewind( self::$overflow_handle ); // resets the position of pointer. 398 399 // Content is pre-escaped with esc_html() before being written to overflow file. 400 echo fread( self::$overflow_handle, fstat( self::$overflow_handle )['size'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread, WordPress.Security.EscapeOutput.OutputNotEscaped 401 402 fclose( self::$overflow_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 403 self::$overflow_handle = null; 404 } elseif ( \is_resource( self::$memory_handle ) && ( 'handle' === get_resource_type( self::$memory_handle ) || 'stream' === get_resource_type( self::$memory_handle ) ) ) { 318 405 rewind( self::$memory_handle ); // resets the position of pointer. 319 406 407 // Content is pre-escaped with esc_html() before being written to memory file. 320 408 echo fread( self::$memory_handle, fstat( self::$memory_handle )['size'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread, WordPress.Security.EscapeOutput.OutputNotEscaped 321 409 … … 334 422 */ 335 423 public static function flush_memory_file_to_temp() { 336 if ( \is_resource( self::$memory_handle ) && ( 'handle' === get_resource_type( self::$memory_handle ) || 'stream' === get_resource_type( self::$memory_handle ) ) ) {337 424 // Handle overflow file first if it exists. 425 if ( \is_resource( self::$overflow_handle ) && ( 'handle' === get_resource_type( self::$overflow_handle ) || 'stream' === get_resource_type( self::$overflow_handle ) ) ) { 338 426 $line = ''; 339 for ( $x_pos = 0; fseek( self::$ memory_handle, $x_pos, SEEK_END ) !== -1; $x_pos-- ) { // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed340 $char = fgetc( self::$ memory_handle );427 for ( $x_pos = 0; fseek( self::$overflow_handle, $x_pos, SEEK_END ) !== -1; $x_pos-- ) { // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed 428 $char = fgetc( self::$overflow_handle ); 341 429 342 430 if ( PHP_EOL === $char ) { … … 351 439 self::write_temp_file( $line . PHP_EOL ); 352 440 } 441 fclose( self::$overflow_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 442 self::$overflow_handle = null; 443 } elseif ( \is_resource( self::$memory_handle ) && ( 'handle' === get_resource_type( self::$memory_handle ) || 'stream' === get_resource_type( self::$memory_handle ) ) ) { 444 $line = ''; 445 for ( $x_pos = 0; fseek( self::$memory_handle, $x_pos, SEEK_END ) !== -1; $x_pos-- ) { // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed 446 $char = fgetc( self::$memory_handle ); 447 448 if ( PHP_EOL === $char ) { 449 self::write_temp_file( $line . PHP_EOL ); 450 $line = ''; 451 continue; 452 } else { 453 $line = $char . $line; 454 } 455 } 456 if ( ! empty( $line ) ) { 457 self::write_temp_file( $line . PHP_EOL ); 458 } 353 459 fclose( self::$memory_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 354 355 460 self::$memory_handle = null; 356 461 } … … 375 480 self::$memory_handle = null; 376 481 } 482 if ( \is_resource( self::$overflow_handle ) && ( 'handle' === get_resource_type( self::$overflow_handle ) || 'stream' === get_resource_type( self::$overflow_handle ) ) ) { 483 fclose( self::$overflow_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 484 485 self::$overflow_handle = null; 486 } 377 487 } 378 488 … … 387 497 if ( \is_resource( self::$error_log_handle ) && ( 'handle' === get_resource_type( self::$error_log_handle ) || 'stream' === get_resource_type( self::$error_log_handle ) ) ) { 388 498 \fclose( self::$error_log_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 499 } 500 501 if ( \is_resource( self::$overflow_handle ) ) { 502 \fclose( self::$overflow_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 389 503 } 390 504 … … 393 507 self::$pos = null; 394 508 self::$error_log_handle = null; 509 self::$overflow_handle = null; 510 } 511 512 /** 513 * Get available memory in MB 514 * 515 * @return int Available memory in MB 516 * 517 * @since latest 518 */ 519 public static function get_available_memory_mb() { 520 $memory_limit = ini_get( 'memory_limit' ); 521 if ( '-1' === $memory_limit ) { 522 return 256; // Assume 256MB if no limit. 523 } 524 525 $memory_limit_bytes = wp_convert_hr_to_bytes( $memory_limit ); 526 $current_usage = memory_get_usage( true ); 527 $available = max( 0, $memory_limit_bytes - $current_usage ); 528 529 return (int) ( $available / 1024 / 1024 ); 530 } 531 532 /** 533 * Check if available memory is below critical threshold 534 * 535 * @return bool True if memory is critical, false otherwise 536 * 537 * @since latest 538 */ 539 public static function is_memory_critical() { 540 $available_mb = self::get_available_memory_mb(); 541 return $available_mb < 10; // Less than 10MB available. 395 542 } 396 543 … … 451 598 return self::$temp_handle; 452 599 } 600 601 /** 602 * Create a temporary file for overflow data when memory is critical 603 * 604 * @return resource|false File handle or false on failure 605 * 606 * @since latest 607 */ 608 public static function create_overflow_temp_file() { 609 $temp_dir = get_temp_dir(); 610 $temp_file = tempnam( $temp_dir, 'advana_overflow_' ); 611 612 if ( $temp_file && is_writable( $temp_file ) ) { 613 return fopen( $temp_file, 'w+' ); 614 } 615 616 return false; 617 } 618 619 /** 620 * Clean up temporary overflow files 621 * 622 * @return void 623 * 624 * @since latest 625 */ 626 public static function cleanup_overflow_files() { 627 $temp_dir = get_temp_dir(); 628 $pattern = $temp_dir . '/advana_overflow_*'; 629 630 foreach ( glob( $pattern ) as $file ) { 631 if ( is_file( $file ) && filemtime( $file ) < time() - 3600 ) { // Older than 1 hour. 632 unlink( $file ); 633 } 634 } 635 } 453 636 } 454 637 } -
0-day-analytics/tags/4.7.0/classes/vendor/controllers/classes-snippets-controller.php
r3413502 r3451291 141 141 } 142 142 } 143 143 144 /** 144 145 * Fetch and cache runtime snippets list. … … 153 154 } 154 155 155 $wpdb = Snippet_Entity::get_connection(); 156 $table = Snippet_Entity::get_table_name( $wpdb ); 157 158 $query = $wpdb->prepare( 159 'SELECT * FROM ' . $table . ' WHERE blog_id = %d AND status = %d AND type = %s', 160 \get_current_blog_id(), 161 Snippet_Entity::STATUS_ENABLED, 162 'php' 163 ); 164 165 $wpdb->suppress_errors( true ); 166 $results = $wpdb->get_results( $query, ARRAY_A ); 167 if ( '' !== $wpdb->last_error ) { 168 if ( 1146 === Snippet_Entity::get_last_sql_error( $wpdb ) ) { 169 if ( Snippet_Entity::create_table( $wpdb ) ) { 170 $results = array(); 171 } 172 } 173 } 174 $wpdb->suppress_errors( false ); 175 176 self::$runtime_snippets = is_array( $results ) ? $results : array(); 156 self::$runtime_snippets = Snippet_Entity::get_runtime_snippets(); 177 157 178 158 return self::$runtime_snippets; -
0-day-analytics/tags/4.7.0/classes/vendor/entities/class-hooks-management-entity.php
r3442473 r3451291 2474 2474 } 2475 2475 2476 // Add the ID to the data for the update operation. 2477 $data['id'] = $id; 2478 2479 $result = self::insert( $data ); 2476 // Load current record. 2477 $current = self::load( 'id = %d', $id ); 2478 if ( ! $current ) { 2479 return false; 2480 } 2481 2482 // Merge new data with existing data. 2483 $current = array_merge( $current, $data ); 2484 2485 $result = self::insert( $current ); 2480 2486 2481 2487 // Clear cache. 2482 2488 \wp_cache_delete( 'advan_enabled_hooks', 'advan' ); 2489 self::clear_hook_labels_cache(); 2483 2490 2484 2491 return $result > 0; 2492 } 2493 2494 /** 2495 * Set enabled status for a hook. 2496 * 2497 * @param int $id Hook ID. 2498 * @param bool $enabled Enabled status. 2499 * 2500 * @return bool 2501 * 2502 * @since 4.7.0 2503 */ 2504 public static function set_enabled( int $id, bool $enabled ): bool { 2505 return self::update( 2506 $id, 2507 array( 2508 'enabled' => $enabled ? 1 : 0, 2509 'date_modified' => microtime( true ), 2510 ) 2511 ); 2512 } 2513 2514 /** 2515 * Set group ID for a hook. 2516 * 2517 * @param int $id Hook ID. 2518 * @param int $group_id Group ID. 2519 * 2520 * @return bool 2521 * 2522 * @since 4.7.0 2523 */ 2524 public static function set_group_id( int $id, int $group_id ): bool { 2525 return self::update( 2526 $id, 2527 array( 2528 'group_id' => $group_id, 2529 'date_modified' => microtime( true ), 2530 ) 2531 ); 2532 } 2533 2534 /** 2535 * Get hook parameters by hook name. 2536 * 2537 * @param string $hook_name Hook name. 2538 * 2539 * @return string 2540 * 2541 * @since 4.7.0 2542 */ 2543 public static function get_hook_parameters( string $hook_name ): string { 2544 $hook = self::load( 'hook_name = %s', array( $hook_name ) ); 2545 return $hook && isset( $hook['hook_parameters'] ) ? $hook['hook_parameters'] : ''; 2485 2546 } 2486 2547 } -
0-day-analytics/tags/4.7.0/classes/vendor/entities/class-snippet-entity.php
r3413502 r3451291 640 640 ); 641 641 } 642 643 /** 644 * Get runtime snippets (enabled PHP snippets for current blog). 645 * 646 * @return array 647 * 648 * @since 4.3.0 649 */ 650 public static function get_runtime_snippets(): array { 651 $wpdb = self::get_connection(); 652 $table = self::get_table_name( $wpdb ); 653 $blog_id = \get_current_blog_id(); 654 655 $query = $wpdb->prepare( 656 'SELECT * FROM ' . $table . ' WHERE blog_id = %d AND status = %d AND type = %s', 657 $blog_id, 658 self::STATUS_ENABLED, 659 'php' 660 ); 661 662 $wpdb->suppress_errors( true ); 663 $results = $wpdb->get_results( $query, ARRAY_A ); 664 if ( '' !== $wpdb->last_error ) { 665 if ( 1146 === self::get_last_sql_error( $wpdb ) ) { 666 if ( self::create_table( $wpdb ) ) { 667 $results = array(); 668 } 669 } 670 } 671 $wpdb->suppress_errors( false ); 672 673 return is_array( $results ) ? $results : array(); 674 } 675 676 /** 677 * Get snippets with filters for AJAX listing. 678 * 679 * @param array $filters Array of filters (search, status, type, etc.). 680 * @param int $offset Pagination offset. 681 * @param int $limit Pagination limit. 682 * 683 * @return array 684 * 685 * @since 4.3.0 686 */ 687 public static function get_snippets_with_filters( array $filters = array(), int $offset = 0, int $limit = 50 ): array { 688 $wpdb = self::get_connection(); 689 $table = self::get_table_name( $wpdb ); 690 $blog_id = \get_current_blog_id(); 691 692 $where = array( 'blog_id = %d' ); 693 $bindings = array( $blog_id ); 694 695 // Search filter 696 if ( ! empty( $filters['search'] ) ) { 697 $search = '%' . $wpdb->esc_like( $filters['search'] ) . '%'; 698 $where[] = '(name LIKE %s OR tags LIKE %s)'; 699 $bindings[] = $search; 700 $bindings[] = $search; 701 } 702 703 // Status filter 704 if ( isset( $filters['status'] ) ) { 705 $status_map = array( 706 'enabled' => self::STATUS_ENABLED, 707 'disabled' => self::STATUS_DISABLED, 708 'trash' => self::STATUS_TRASHED, 709 ); 710 711 if ( isset( $status_map[ $filters['status'] ] ) ) { 712 $where[] = 'status = %d'; 713 $bindings[] = $status_map[ $filters['status'] ]; 714 } else { 715 $where[] = 'status >= %d'; 716 $bindings[] = self::STATUS_DISABLED; 717 } 718 } 719 720 // Type filter 721 if ( ! empty( $filters['type'] ) && in_array( $filters['type'], array_keys( self::get_supported_types() ), true ) ) { 722 $where[] = 'type = %s'; 723 $bindings[] = $filters['type']; 724 } 725 726 $where_sql = $where ? 'WHERE ' . implode( ' AND ', $where ) : ''; 727 $orderby = 'updated_at'; 728 $order = 'DESC'; 729 730 $query = 'SELECT * FROM ' . $table . ' ' . $where_sql . ' ORDER BY ' . $orderby . ' ' . $order . ' LIMIT %d OFFSET %d'; 731 $bindings[] = $limit; 732 $bindings[] = $offset; 733 734 $wpdb->suppress_errors( true ); 735 $results = $wpdb->get_results( $wpdb->prepare( $query, $bindings ), ARRAY_A ); 736 if ( '' !== $wpdb->last_error ) { 737 if ( 1146 === self::get_last_sql_error( $wpdb ) ) { 738 if ( self::create_table( $wpdb ) ) { 739 $results = array(); 740 } 741 } 742 } 743 $wpdb->suppress_errors( false ); 744 745 return is_array( $results ) ? $results : array(); 746 } 747 748 /** 749 * Get total count of snippets with filters. 750 * 751 * @param array $filters Array of filters (search, status, type, etc.). 752 * 753 * @return int 754 * 755 * @since 4.3.0 756 */ 757 public static function get_snippets_count_with_filters( array $filters = array() ): int { 758 $wpdb = self::get_connection(); 759 $table = self::get_table_name( $wpdb ); 760 $blog_id = \get_current_blog_id(); 761 762 $where = array( 'blog_id = %d' ); 763 $bindings = array( $blog_id ); 764 765 // Search filter. 766 if ( ! empty( $filters['search'] ) ) { 767 $search = '%' . $wpdb->esc_like( $filters['search'] ) . '%'; 768 $where[] = '(name LIKE %s OR tags LIKE %s)'; 769 $bindings[] = $search; 770 $bindings[] = $search; 771 } 772 773 // Status filter. 774 if ( isset( $filters['status'] ) ) { 775 $status_map = array( 776 'enabled' => self::STATUS_ENABLED, 777 'disabled' => self::STATUS_DISABLED, 778 'trash' => self::STATUS_TRASHED, 779 ); 780 781 if ( isset( $status_map[ $filters['status'] ] ) ) { 782 $where[] = 'status = %d'; 783 $bindings[] = $status_map[ $filters['status'] ]; 784 } else { 785 $where[] = 'status >= %d'; 786 $bindings[] = self::STATUS_DISABLED; 787 } 788 } 789 790 // Type filter. 791 if ( ! empty( $filters['type'] ) && in_array( $filters['type'], array_keys( self::get_supported_types() ), true ) ) { 792 $where[] = 'type = %s'; 793 $bindings[] = $filters['type']; 794 } 795 796 $where_sql = $where ? 'WHERE ' . implode( ' AND ', $where ) : ''; 797 $query = 'SELECT COUNT(*) FROM ' . $table . ' ' . $where_sql; 798 799 $wpdb->suppress_errors( true ); 800 $count = (int) $wpdb->get_var( $wpdb->prepare( $query, $bindings ) ); 801 if ( '' !== $wpdb->last_error ) { 802 if ( 1146 === self::get_last_sql_error( $wpdb ) ) { 803 if ( self::create_table( $wpdb ) ) { 804 $count = 0; 805 } 806 } 807 } 808 $wpdb->suppress_errors( false ); 809 810 return $count; 811 } 642 812 } 643 813 } -
0-day-analytics/tags/4.7.0/classes/vendor/entities/class-wp-fatals-entity.php
r3393178 r3451291 651 651 652 652 /** 653 * Alters the table for version 4.7.0 - adds performance indexes 654 * 655 * @return bool 656 * 657 * @since 4.7.0 658 */ 659 public static function alter_table_470(): bool { 660 $table_name = self::get_table_name(); 661 $indexes = array( 662 'severity' => 'ADD KEY severity (severity)', 663 'source_slug' => 'ADD KEY source_slug (source_slug)', 664 'source_type' => 'ADD KEY source_type (source_type)', 665 ); 666 667 foreach ( $indexes as $index_sql ) { 668 $sql = "ALTER TABLE `$table_name` $index_sql"; 669 // Use try-catch or check if index exists by attempting the alter 670 // Since MySQL ignores duplicate key errors, we can safely run this. 671 self::get_connection()->query( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- DDL operation, no caching needed. 672 } 673 674 return true; 675 } 676 677 /** 678 * Prunes old fatal error records based on retention settings 679 * 680 * @param int $retention_days - Number of days to keep records (default 90) 681 * 682 * @return int Number of records deleted 683 * 684 * @since 4.7.0 685 */ 686 public static function prune_old_records( int $retention_days = 90 ): int { 687 global $wpdb; 688 $cutoff_time = time() - ( $retention_days * 24 * 60 * 60 ); 689 $table_name = self::get_table_name(); 690 691 $sql = $wpdb->prepare( 692 "DELETE FROM `$table_name` WHERE datetime < %d", 693 $cutoff_time 694 ); 695 696 $result = $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Bulk delete operation. 697 698 return (int) $result; 699 } 700 701 /** 653 702 * Generates drop down with all the subsites that have mail logs. 654 703 * -
0-day-analytics/tags/4.7.0/classes/vendor/helpers/class-ajax-helper.php
r3442115 r3451291 153 153 \add_action( 'wp_ajax_aadvana_export_large_csv', array( __CLASS__, 'export_large_csv' ) ); 154 154 \add_action( 'wp_ajax_aadvana_export_large_csv_cleanup', array( __CLASS__, 'export_large_csv_cleanup' ) ); 155 \add_action( 'wp_ajax_aadvana_get_table_info', array( __CLASS__, 'get_table_info' ) ); 155 156 156 157 if ( Settings::get_option( 'server_info_module_enabled' ) ) { … … 975 976 $snippet_type = isset( $_POST['snippet_type'] ) ? \sanitize_text_field( wp_unslash( $_POST['snippet_type'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing 976 977 977 $extra_file_name = '_snippets_'; 978 979 $wpdb = \ADVAN\Entities\Snippet_Entity::get_connection(); 980 $table = \ADVAN\Entities\Snippet_Entity::get_table_name( $wpdb ); 981 982 $where = array( 'blog_id = %d' ); 983 $bindings = array( get_current_blog_id() ); 978 $filters = array(); 984 979 985 980 if ( '' !== $search ) { 986 $like = '%' . $wpdb->esc_like( $search ) . '%'; 987 $where[] = '( name LIKE %s OR tags LIKE %s )'; 988 $bindings[] = $like; 989 $bindings[] = $like; 981 $filters['search'] = $search; 990 982 } 991 983 992 $status_map = array( 993 'enabled' => \ADVAN\Entities\Snippet_Entity::STATUS_ENABLED, 994 'disabled' => \ADVAN\Entities\Snippet_Entity::STATUS_DISABLED, 995 'trash' => \ADVAN\Entities\Snippet_Entity::STATUS_TRASHED, 996 ); 997 998 if ( isset( $status_map[ $snippet_status ] ) ) { 999 $where[] = 'status = %d'; 1000 $bindings[] = $status_map[ $snippet_status ]; 1001 } else { 1002 $where[] = 'status >= %d'; 1003 $bindings[] = \ADVAN\Entities\Snippet_Entity::STATUS_DISABLED; 984 if ( '' !== $snippet_status ) { 985 $filters['status'] = $snippet_status; 1004 986 } 1005 987 1006 $types = array_keys( \ADVAN\Entities\Snippet_Entity::get_supported_types() ); 1007 if ( '' !== $snippet_type && in_array( $snippet_type, $types, true ) ) { 1008 $where[] = 'type = %s'; 1009 $bindings[] = $snippet_type; 988 if ( '' !== $snippet_type ) { 989 $filters['type'] = $snippet_type; 1010 990 } 1011 991 1012 $where_sql = $where ? 'WHERE ' . implode( ' AND ', $where ) : ''; 1013 1014 $count_sql = 'SELECT COUNT(*) FROM ' . $table . ' ' . $where_sql; 1015 $total = (int) $wpdb->get_var( $wpdb->prepare( $count_sql, $bindings ) ); 1016 1017 $orderby = 'updated_at'; 1018 $order = 'DESC'; 1019 1020 $list_sql = 'SELECT * FROM ' . $table . ' ' . $where_sql . ' ORDER BY ' . $orderby . ' ' . $order . ' LIMIT %d OFFSET %d'; 1021 $list_items = $wpdb->get_results( 1022 $wpdb->prepare( 1023 $list_sql, 1024 array_merge( $bindings, array( (int) $batch_size, (int) $offset ) ) 1025 ), 1026 ARRAY_A 1027 ); 1028 1029 $rows = $list_items ?: array(); 992 $total = \ADVAN\Entities\Snippet_Entity::get_snippets_count_with_filters( $filters ); 993 $rows = \ADVAN\Entities\Snippet_Entity::get_snippets_with_filters( $filters, $offset, $batch_size ); 1030 994 } 1031 995 } else { … … 1176 1140 */ 1177 1141 public static function save_hook_group() { 1178 if ( ! \current_user_can( 'manage_options' ) ) { 1179 \wp_send_json_error( 'Unauthorized' ); 1180 } 1181 1182 \check_ajax_referer( 'advan_hook_groups', 'nonce' ); 1142 WP_Helper::verify_admin_nonce( 'advan_hook_groups', 'nonce' ); 1183 1143 1184 1144 if ( ! class_exists( 'ADVAN\Entities\Hook_Groups_Entity' ) ) { … … 1218 1178 */ 1219 1179 public static function delete_hook_group() { 1220 if ( ! \current_user_can( 'manage_options' ) ) { 1221 \wp_send_json_error( 'Unauthorized' ); 1222 } 1223 1224 \check_ajax_referer( 'advan_hook_groups', 'nonce' ); 1180 WP_Helper::verify_admin_nonce( 'advan_hook_groups', 'nonce' ); 1225 1181 1226 1182 if ( ! class_exists( 'ADVAN\Entities\Hook_Groups_Entity' ) ) { … … 1242 1198 } 1243 1199 } 1200 1201 /** 1202 * Get detailed table information including structure, indexes, foreign keys, and health. 1203 * 1204 * @return void 1205 * 1206 * @since 4.7.0 1207 */ 1208 public static function get_table_info() { 1209 WP_Helper::verify_admin_nonce( 'get_table_info', 'security' ); 1210 1211 $table_name = isset( $_POST['table_name'] ) ? \sanitize_text_field( \wp_unslash( $_POST['table_name'] ) ) : ''; 1212 1213 if ( empty( $table_name ) ) { 1214 \wp_send_json_error( 'Invalid table name' ); 1215 } 1216 1217 $table_info = Common_Table::get_table_info( $table_name ); 1218 1219 if ( \is_wp_error( $table_info ) ) { 1220 \wp_send_json_error( $table_info->get_error_message() ); 1221 } 1222 1223 \wp_send_json_success( $table_info ); 1224 } 1244 1225 } 1245 1226 } -
0-day-analytics/tags/4.7.0/classes/vendor/helpers/class-hook-parameter-renderer.php
r3442473 r3451291 13 13 namespace ADVAN\Helpers; 14 14 15 use ADVAN\Entities\Hooks_Management_Entity; 16 15 17 // Exit if accessed directly. 16 18 if ( ! defined( 'ABSPATH' ) ) { … … 37 39 */ 38 40 public static function render_parameters( string $hook_name, string $parameters ): string { 39 global $wpdb;40 41 41 // Get hook definition from hooks_management table. 42 $management_table = $wpdb->prefix . ADVAN_PREFIX . 'hooks_management'; 43 44 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 45 $hook_config = $wpdb->get_row( 46 $wpdb->prepare( 47 "SELECT hook_parameters FROM `{$management_table}` WHERE hook_name = %s LIMIT 1", 48 $hook_name 49 ), 50 ARRAY_A 51 ); 42 $hook_parameters = Hooks_Management_Entity::get_hook_parameters( $hook_name ); 52 43 53 44 // Decode captured parameters. … … 59 50 // Get parameter definitions. 60 51 $param_defs = array(); 61 if ( $hook_config && ! empty( $hook_config['hook_parameters']) ) {62 $param_defs = json_decode( $hook_ config['hook_parameters'], true );52 if ( ! empty( $hook_parameters ) ) { 53 $param_defs = json_decode( $hook_parameters, true ); 63 54 if ( ! is_array( $param_defs ) ) { 64 55 $param_defs = array(); … … 146 137 } 147 138 } 139 } 140 141 if ( \is_array( $value ) && ! \in_array( $type, array( 'array', 'object' ), true ) ) { 142 $type = 'array'; 148 143 } 149 144 // Override type if actual value type differs significantly. … … 216 211 * 217 212 * @throws \Throwable If code execution fails. 213 * @throws \Exception If unsafe code is detected. 218 214 * 219 215 * @since 4.5.0 … … 564 560 $bool_val = filter_var( $value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ); 565 561 if ( is_null( $bool_val ) ) { 566 return '<code>' . \esc_html( $value ) . '</code>';562 return '<code>' . \esc_html( (string) $value ) . '</code>'; 567 563 } 568 564 return $bool_val ? '<span style="color: green;">✓ true</span>' : '<span style="color: #999;">✗ false</span>'; … … 586 582 return '<code>' . \esc_html( $str ) . '</code>'; 587 583 } 588 return '<code>' . \esc_html( print_r( $value, true ) ) . '</code>';584 return '<code>' . \esc_html( print_r( (array) $value, true ) ) . '</code>'; 589 585 } 590 586 -
0-day-analytics/tags/4.7.0/classes/vendor/lists/class-fatals-list.php
r3442115 r3451291 81 81 82 82 /** 83 * Maximum stack trace lines to display in details 84 * 85 * @var int 86 * 87 * @since 4.7.0 88 */ 89 protected const MAX_STACK_TRACE_LINES = 50; 90 91 /** 83 92 * Holds the prepared options for speeding the process 84 93 * … … 222 231 $plugin = -1; 223 232 } else { 224 $plugin = \sanitize_text_field( \wp_unslash( $_REQUEST['plugin'] ) ); 233 $plugin_raw = \sanitize_text_field( \wp_unslash( $_REQUEST['plugin'] ) ); 234 // Validate plugin slug format (alphanumeric, dashes, underscores, max 255 chars). 235 if ( preg_match( '/^[a-zA-Z0-9\-_]{1,255}$/', $plugin_raw ) ) { 236 $plugin = $plugin_raw; 237 } else { 238 $plugin = ''; 239 } 225 240 } 226 241 } else { … … 469 484 'action' => 'log_source_view', 470 485 ); 486 $line_count = 0; 471 487 foreach ( $reversed_details as $val ) { 488 if ( $line_count >= self::MAX_STACK_TRACE_LINES ) { 489 $message .= '<br>... (' . ( count( $reversed_details ) - $line_count ) . ' more lines truncated)'; 490 break; 491 } 472 492 473 493 $source_link = ''; … … 503 523 504 524 $message = \rtrim( $message, ' - ' ); 525 $line_count++; 505 526 } 506 527 $message .= '</pre></div>'; -
0-day-analytics/tags/4.7.0/classes/vendor/lists/class-hooks-capture-list.php
r3448917 r3451291 746 746 $hook_name = '<code>' . \esc_html( $item[ $column_name ] ) . '</code>'; 747 747 748 // Make hook name a link to hooks management if hooks_management_id is available 748 // Make hook name a link to hooks management if hooks_management_id is available. 749 749 if ( ! empty( $item['hooks_management_id'] ) ) { 750 750 $edit_url = \network_admin_url( 'admin.php?page=advan_hooks_management&action=edit&id=' . absint( $item['hooks_management_id'] ) ); -
0-day-analytics/tags/4.7.0/classes/vendor/lists/class-hooks-management-list.php
r3442115 r3451291 22 22 use ADVAN\Entities_Global\Common_Table; 23 23 use ADVAN\Entities\Hooks_Management_Entity; 24 use ADVAN\Entities\Hook_Groups_Entity; 24 25 use ADVAN\Lists\Views\Hooks_Management_View; 25 26 … … 452 453 */ 453 454 public function get_bulk_actions() { 454 returnarray(455 $actions = array( 455 456 'delete' => \esc_html__( 'Delete', '0-day-analytics' ), 456 457 'enable' => \esc_html__( 'Enable', '0-day-analytics' ), 457 458 'disable' => \esc_html__( 'Disable', '0-day-analytics' ), 458 459 ); 460 461 // Add group assignment actions. 462 $groups = Hook_Groups_Entity::get_groups_array(); 463 if ( ! empty( $groups ) ) { 464 foreach ( $groups as $group_id => $group ) { 465 $actions[ 'assign_group_' . $group_id ] = sprintf( 466 /* translators: %s: Group name */ 467 \esc_html__( 'Assign to group: %s', '0-day-analytics' ), 468 $group['name'] 469 ); 470 } 471 } 472 473 return $actions; 459 474 } 460 475 … … 539 554 540 555 // Handle bulk actions. 541 if ( in_array( $action, array( 'delete', 'enable', 'disable' ), true ) ) {556 if ( in_array( $action, array( 'delete', 'enable', 'disable' ), true ) || ( is_string( $action ) && strpos( $action, 'assign_group_' ) === 0 ) ) { 542 557 $nonce = isset( $_REQUEST['_wpnonce'] ) ? \sanitize_text_field( \wp_unslash( $_REQUEST['_wpnonce'] ) ) : ''; 543 558 … … 550 565 551 566 if ( ! empty( $ids ) ) { 552 global $wpdb;553 $table = Hooks_Management_Entity::get_table_name();554 555 567 foreach ( $ids as $id ) { 556 568 if ( 'delete' === $action ) { 557 569 Hooks_Management_Entity::delete_by_id( $id ); 558 570 } elseif ( 'enable' === $action ) { 559 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 560 $wpdb->query( 561 $wpdb->prepare( 562 "UPDATE `{$table}` SET enabled = 1, date_modified = %f WHERE id = %d", 563 microtime( true ), 564 $id 565 ) 566 ); 571 Hooks_Management_Entity::set_enabled( $id, true ); 567 572 } elseif ( 'disable' === $action ) { 568 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching569 $wpdb->query(570 $wpdb->prepare(571 "UPDATE `{$table}` SET enabled = 0, date_modified = %f WHERE id = %d",572 microtime( true ),573 $id 574 )575 );573 Hooks_Management_Entity::set_enabled( $id, false ); 574 } elseif ( is_string( $action ) && strpos( $action, 'assign_group_' ) === 0 ) { 575 // Extract group ID from action. 576 $group_id = str_replace( 'assign_group_', '', $action ); 577 $group_id = absint( $group_id ); 578 579 // Update the group_id for this hook. 580 Hooks_Management_Entity::set_group_id( $id, $group_id ); 576 581 } 577 582 } -
0-day-analytics/tags/4.7.0/classes/vendor/lists/class-logs-list.php
r3442115 r3451291 365 365 $result = Reverse_Line_Reader::read_file_from_end( 366 366 $file, 367 function( $line, $pos ) use ( &$collected_items, &$errors, &$position ) {367 function( $line, $pos ) use ( &$collected_items, &$errors, &$position, $items, $write_temp ) { 368 368 369 369 $position = $pos; 370 371 // Prevent memory exhaustion from extremely large multi-line errors. 372 if ( count( $collected_items ) > 500 ) { // Reasonable limit for stack traces. 373 $collected_items = array_slice( $collected_items, -100 ); // Keep last 100 items. 374 // if ( function_exists( 'error_log' ) ) { 375 // error_log( 'Logs_List: Truncated collected_items due to size limit (' . count( $collected_items ) . ' items)' ); 376 // } 377 } 370 378 371 379 // Flag that holds the status of the error - are there more lines to read or not. … … 387 395 $errors[] = $parsed_data; 388 396 $more_to_error = false; 397 398 // Prevent memory exhaustion from too many errors. 399 if ( count( $errors ) >= $items * 2 ) { // Allow some buffer. 400 return array( 401 'close' => true, 402 'line_done' => true, 403 'no_flush' => false, 404 ); 405 } 389 406 } elseif ( \is_array( $parsed_data ) ) { 390 407 if ( isset( $parsed_data['call'] ) && str_starts_with( trim( $parsed_data['call'] ), 'made by' ) ) { … … 1233 1250 } 1234 1251 ?> 1235 <option <?php echo ( $selected ); ?> value="<?php echo \esc_attr( $name ); ?>"><?php echo \esc_ attr( $name ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped?></option>1252 <option <?php echo ( $selected ); ?> value="<?php echo \esc_attr( $name ); ?>"><?php echo \esc_html( $name ); ?></option> 1236 1253 <?php 1237 1254 } -
0-day-analytics/tags/4.7.0/classes/vendor/lists/class-table-list.php
r3442115 r3451291 643 643 644 644 </select> 645 <?php if ( 'top' === $which ) : ?> 646 <button id="table-info-btn" class="button button-secondary" title="<?php esc_attr_e( 'View table information', '0-day-analytics' ); ?>"> 647 <span class="dashicons dashicons-info"></span> 648 <?php esc_html_e( 'Info', '0-day-analytics' ); ?> 649 </button> 650 <?php endif; ?> 645 651 646 652 </div> … … 667 673 <?php 668 674 } 675 676 // Table info modal - only for top navigation 677 if ( 'top' === $which ) : 678 ?> 679 <div id="table-info-modal" class="table-info-modal" style="display: none;"> 680 <div class="table-info-modal-content"> 681 <div class="table-info-modal-header"> 682 <h3><?php printf( esc_html__( 'Table Information: %s', '0-day-analytics' ), esc_html( self::$table::get_name() ) ); ?></h3> 683 <button type="button" class="table-info-modal-close">×</button> 684 </div> 685 <div class="table-info-modal-body"> 686 <div class="table-info-loading"> 687 <span class="spinner is-active"></span> 688 <?php esc_html_e( 'Loading table information...', '0-day-analytics' ); ?> 689 </div> 690 <div class="table-info-content" style="display: none;"> 691 <div class="table-info-section"> 692 <h4><?php esc_html_e( 'Table Structure', '0-day-analytics' ); ?></h4> 693 <div class="table-structure-info"></div> 694 </div> 695 <div class="table-info-section"> 696 <h4><?php esc_html_e( 'Indexes', '0-day-analytics' ); ?></h4> 697 <div class="table-indexes-info"></div> 698 </div> 699 <div class="table-info-section"> 700 <h4><?php esc_html_e( 'Foreign Keys', '0-day-analytics' ); ?></h4> 701 <div class="table-foreign-keys-info"></div> 702 </div> 703 <div class="table-info-section"> 704 <h4><?php esc_html_e( 'Table Health', '0-day-analytics' ); ?></h4> 705 <div class="table-health-info"></div> 706 </div> 707 </div> 708 </div> 709 </div> 710 </div> 711 <?php endif; ?> 712 713 <?php 669 714 // if ( 'top' === $which ) { 670 715 global $wpdb; … … 836 881 makeSearchableDropdown(document.getElementById("table_filter_<?php echo \esc_attr( $which ); ?>")); 837 882 883 <?php if ( 'top' === $which ) { ?> 884 // Table info modal functionality 885 const tableInfoBtn = document.getElementById('table-info-btn'); 886 const tableInfoModal = document.getElementById('table-info-modal'); 887 const tableInfoClose = document.querySelector('.table-info-modal-close'); 888 889 if (tableInfoBtn && tableInfoModal) { 890 tableInfoBtn.addEventListener('click', function(e) { 891 e.preventDefault(); 892 loadTableInfo(); 893 tableInfoModal.style.display = 'block'; 894 }); 895 896 tableInfoClose.addEventListener('click', function() { 897 tableInfoModal.style.display = 'none'; 898 }); 899 900 window.addEventListener('click', function(e) { 901 if (e.target === tableInfoModal) { 902 tableInfoModal.style.display = 'none'; 903 } 904 }); 905 } 906 907 function loadTableInfo() { 908 const loadingEl = document.querySelector('.table-info-loading'); 909 const contentEl = document.querySelector('.table-info-content'); 910 911 loadingEl.style.display = 'block'; 912 contentEl.style.display = 'none'; 913 914 fetch('<?php echo esc_url(admin_url('admin-ajax.php')); ?>', { 915 method: 'POST', 916 headers: { 917 'Content-Type': 'application/x-www-form-urlencoded', 918 }, 919 body: new URLSearchParams({ 920 action: 'aadvana_get_table_info', 921 table_name: '<?php echo esc_js(self::$table::get_name()); ?>', 922 security: '<?php echo wp_create_nonce('get_table_info'); ?>' 923 }) 924 }) 925 .then(response => response.json()) 926 .then(data => { 927 loadingEl.style.display = 'none'; 928 if (data.success) { 929 displayTableInfo(data.data); 930 contentEl.style.display = 'block'; 931 } else { 932 alert('<?php esc_html_e('Error loading table information', '0-day-analytics'); ?>: ' + data.data); 933 } 934 }) 935 .catch(error => { 936 loadingEl.style.display = 'none'; 937 alert('<?php esc_html_e('Error loading table information', '0-day-analytics'); ?>: ' + error.message); 938 }); 939 } 940 941 function displayTableInfo(info) { 942 // Table Structure 943 const structureEl = document.querySelector('.table-structure-info'); 944 if (info.structure && info.structure.length > 0) { 945 let html = '<table class="widefat striped"><thead><tr><th><?php esc_html_e('Column', '0-day-analytics'); ?></th><th><?php esc_html_e('Type', '0-day-analytics'); ?></th><th><?php esc_html_e('Null', '0-day-analytics'); ?></th><th><?php esc_html_e('Key', '0-day-analytics'); ?></th><th><?php esc_html_e('Default', '0-day-analytics'); ?></th><th><?php esc_html_e('Extra', '0-day-analytics'); ?></th></tr></thead><tbody>'; 946 info.structure.forEach(col => { 947 html += `<tr> 948 <td><code>${escapeHtml(col.Field)}</code></td> 949 <td><code>${escapeHtml(col.Type)}</code></td> 950 <td>${escapeHtml(col.Null)}</td> 951 <td>${escapeHtml(col.Key || '')}</td> 952 <td>${escapeHtml(col.Default || '')}</td> 953 <td>${escapeHtml(col.Extra || '')}</td> 954 </tr>`; 955 }); 956 html += '</tbody></table>'; 957 structureEl.innerHTML = html; 958 } else { 959 structureEl.innerHTML = '<p><?php esc_html_e('No column information available', '0-day-analytics'); ?></p>'; 960 } 961 962 // Indexes 963 const indexesEl = document.querySelector('.table-indexes-info'); 964 if (info.indexes && info.indexes.length > 0) { 965 let html = '<table class="widefat striped"><thead><tr><th><?php esc_html_e('Key Name', '0-day-analytics'); ?></th><th><?php esc_html_e('Column', '0-day-analytics'); ?></th><th><?php esc_html_e('Unique', '0-day-analytics'); ?></th><th><?php esc_html_e('Type', '0-day-analytics'); ?></th></tr></thead><tbody>'; 966 info.indexes.forEach(idx => { 967 html += `<tr> 968 <td><code>${escapeHtml(idx.Key_name)}</code></td> 969 <td><code>${escapeHtml(idx.Column_name)}</code></td> 970 <td>${idx.Non_unique === '0' ? '<?php esc_html_e('Yes', '0-day-analytics'); ?>' : '<?php esc_html_e('No', '0-day-analytics'); ?>'}</td> 971 <td>${escapeHtml(idx.Index_type)}</td> 972 </tr>`; 973 }); 974 html += '</tbody></table>'; 975 indexesEl.innerHTML = html; 976 } else { 977 indexesEl.innerHTML = '<p><?php esc_html_e('No indexes found', '0-day-analytics'); ?></p>'; 978 } 979 980 // Foreign Keys 981 const fkEl = document.querySelector('.table-foreign-keys-info'); 982 if (info.foreign_keys && info.foreign_keys.length > 0) { 983 let html = '<table class="widefat striped"><thead><tr><th><?php esc_html_e('Constraint', '0-day-analytics'); ?></th><th><?php esc_html_e('Column', '0-day-analytics'); ?></th><th><?php esc_html_e('Referenced Table', '0-day-analytics'); ?></th><th><?php esc_html_e('Referenced Column', '0-day-analytics'); ?></th></tr></thead><tbody>'; 984 info.foreign_keys.forEach(fk => { 985 html += `<tr> 986 <td><code>${escapeHtml(fk.constraint_name)}</code></td> 987 <td><code>${escapeHtml(fk.column_name)}</code></td> 988 <td><code>${escapeHtml(fk.referenced_table_name)}</code></td> 989 <td><code>${escapeHtml(fk.referenced_column_name)}</code></td> 990 </tr>`; 991 }); 992 html += '</tbody></table>'; 993 fkEl.innerHTML = html; 994 } else { 995 fkEl.innerHTML = '<p><?php esc_html_e('No foreign keys found', '0-day-analytics'); ?></p>'; 996 } 997 998 // Table Health 999 const healthEl = document.querySelector('.table-health-info'); 1000 if (info.health) { 1001 let html = '<ul>'; 1002 if (info.health.needs_optimization) { 1003 html += `<li><span style="color: #d63638;">⚠️ <?php esc_html_e('Table may benefit from optimization', '0-day-analytics'); ?></span></li>`; 1004 } else { 1005 html += `<li><span style="color: #00a32a;">✅ <?php esc_html_e('Table appears to be well optimized', '0-day-analytics'); ?></span></li>`; 1006 } 1007 if (info.health.row_count) { 1008 html += `<li><?php esc_html_e('Row count', '0-day-analytics'); ?>: ${info.health.row_count.toLocaleString()}</li>`; 1009 } 1010 if (info.health.data_size) { 1011 html += `<li><?php esc_html_e('Data size', '0-day-analytics'); ?>: ${formatBytes(info.health.data_size)}</li>`; 1012 } 1013 if (info.health.index_size) { 1014 html += `<li><?php esc_html_e('Index size', '0-day-analytics'); ?>: ${formatBytes(info.health.index_size)}</li>`; 1015 } 1016 html += '</ul>'; 1017 healthEl.innerHTML = html; 1018 } else { 1019 healthEl.innerHTML = '<p><?php esc_html_e('Health information not available', '0-day-analytics'); ?></p>'; 1020 } 1021 } 1022 1023 function escapeHtml(text) { 1024 const div = document.createElement('div'); 1025 div.textContent = text; 1026 return div.innerHTML; 1027 } 1028 1029 function formatBytes(bytes) { 1030 if (bytes === 0) return '0 Bytes'; 1031 const k = 1024; 1032 const sizes = ['Bytes', 'KB', 'MB', 'GB']; 1033 const i = Math.floor(Math.log(bytes) / Math.log(k)); 1034 return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; 1035 } 1036 <?php } ?> 1037 838 1038 </script> 839 1039 <?php … … 940 1140 top: -9999px; 941 1141 } 1142 1143 /* Table Info Modal Styles */ 1144 .table-info-modal { 1145 position: fixed; 1146 z-index: 100000; 1147 left: 0; 1148 top: 0; 1149 width: 100%; 1150 height: 100%; 1151 background-color: rgba(0, 0, 0, 0.5); 1152 } 1153 1154 .table-info-modal-content { 1155 background-color: #fefefe; 1156 margin: 5% auto; 1157 padding: 0; 1158 border: 1px solid #888; 1159 width: 90%; 1160 max-width: 1000px; 1161 max-height: 80vh; 1162 overflow-y: auto; 1163 border-radius: 8px; 1164 box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); 1165 } 1166 1167 .aadvana-darkskin .table-info-modal-content { 1168 background-color: #1d456b !important; 1169 border-color: #555; 1170 } 1171 1172 .table-info-modal-header { 1173 padding: 15px 20px; 1174 /* background: #f8f9fa; */ 1175 border-bottom: 1px solid #dee2e6; 1176 display: flex; 1177 justify-content: space-between; 1178 align-items: center; 1179 border-radius: 8px 8px 0 0; 1180 } 1181 1182 .table-info-modal-header h3 { 1183 margin: 0; 1184 /* color: #333; */ 1185 font-size: 18px; 1186 font-weight: 600; 1187 } 1188 1189 .table-info-modal-close { 1190 background: none; 1191 border: none; 1192 font-size: 24px; 1193 font-weight: bold; 1194 /* color: #666; */ 1195 cursor: pointer; 1196 padding: 0; 1197 width: 30px; 1198 height: 30px; 1199 display: flex; 1200 align-items: center; 1201 justify-content: center; 1202 border-radius: 50%; 1203 transition: background-color 0.2s; 1204 } 1205 1206 .table-info-modal-close:hover { 1207 /* background-color: #e9ecef; */ 1208 /* color: #333; */ 1209 } 1210 1211 .table-info-modal-body { 1212 padding: 20px; 1213 } 1214 1215 .table-info-loading { 1216 text-align: center; 1217 padding: 40px; 1218 } 1219 1220 .table-info-loading .spinner { 1221 float: none; 1222 margin: 0 auto 10px; 1223 } 1224 1225 .table-info-section { 1226 margin-bottom: 30px; 1227 } 1228 1229 .table-info-section h4 { 1230 margin: 0 0 15px 0; 1231 padding: 10px 15px; 1232 /* background: #f8f9fa; */ 1233 border-left: 4px solid #007cba; 1234 font-size: 16px; 1235 font-weight: 600; 1236 /* color: #333; */ 1237 } 1238 1239 .table-info-section table { 1240 margin: 0; 1241 } 1242 1243 .table-info-section table code { 1244 /* background: #f8f9fa; */ 1245 padding: 2px 6px; 1246 border-radius: 3px; 1247 font-size: 12px; 1248 /* color: #495057; */ 1249 } 1250 1251 .table-info-section ul { 1252 margin: 0; 1253 padding-left: 20px; 1254 } 1255 1256 .table-info-section li { 1257 margin-bottom: 8px; 1258 } 1259 1260 @media (max-width: 768px) { 1261 .table-info-modal-content { 1262 margin: 2% auto; 1263 width: 95%; 1264 max-height: 90vh; 1265 } 1266 1267 .table-info-modal-body { 1268 padding: 15px; 1269 } 1270 1271 .table-info-section table { 1272 font-size: 12px; 1273 } 1274 1275 .table-info-section table th, 1276 .table-info-section table td { 1277 padding: 8px 4px; 1278 } 1279 } 942 1280 </style> 943 1281 <?php } ?> -
0-day-analytics/tags/4.7.0/classes/vendor/lists/entity/class-common-table.php
r3442115 r3451291 2081 2081 } 2082 2082 } 2083 2084 /** 2085 * Get detailed table information including structure, indexes, foreign keys, and health. 2086 * 2087 * @param string $table_name The table name to get information for. 2088 * @param \wpdb $connection Optional database connection. 2089 * 2090 * @return array|\WP_Error Array of table information or WP_Error on failure. 2091 * 2092 * @since 4.7.0 2093 */ 2094 public static function get_table_info( string $table_name, $connection = null ) { 2095 if ( null !== $connection ) { 2096 if ( $connection instanceof \wpdb ) { 2097 $_wpdb = $connection; 2098 } else { 2099 global $wpdb; 2100 $_wpdb = $wpdb; 2101 } 2102 } else { 2103 global $wpdb; 2104 $_wpdb = $wpdb; 2105 } 2106 2107 // Validate table name. 2108 if ( ! self::validate_table_name( $table_name ) ) { 2109 return new \WP_Error( 'invalid_table', 'Invalid table name.' ); 2110 } 2111 2112 // Check if table exists. 2113 if ( ! self::check_table_exists( $table_name, $_wpdb ) ) { 2114 return new \WP_Error( 'table_not_found', 'Table does not exist.' ); 2115 } 2116 2117 $table_info = array(); 2118 2119 try { 2120 // Get table structure (columns) - using DESC command like other methods. 2121 $table_info['structure'] = $_wpdb->get_results( 2122 $_wpdb->prepare( 'DESC %i', $table_name ), 2123 ARRAY_A 2124 ); 2125 2126 // Get indexes - using SHOW INDEX command. 2127 $table_info['indexes'] = $_wpdb->get_results( 2128 $_wpdb->prepare( 'SHOW INDEX FROM %i', $table_name ), 2129 ARRAY_A 2130 ); 2131 2132 // Get foreign keys from information_schema - using prepared query. 2133 $table_info['foreign_keys'] = $_wpdb->get_results( 2134 $_wpdb->prepare( 2135 'SELECT 2136 kcu.constraint_name, 2137 kcu.column_name, 2138 kcu.referenced_table_name, 2139 kcu.referenced_column_name 2140 FROM information_schema.key_column_usage kcu 2141 JOIN information_schema.table_constraints tc 2142 ON kcu.constraint_name = tc.constraint_name 2143 AND kcu.table_schema = tc.table_schema 2144 WHERE kcu.table_schema = %s 2145 AND kcu.table_name = %s 2146 AND tc.constraint_type = %s', 2147 $_wpdb->dbname, 2148 $table_name, 2149 'FOREIGN KEY' 2150 ), 2151 ARRAY_A 2152 ); 2153 2154 // Get table health information from information_schema - using prepared query. 2155 $health_info = $_wpdb->get_row( 2156 $_wpdb->prepare( 2157 'SELECT 2158 table_rows as row_count, 2159 data_length as data_size, 2160 index_length as index_size, 2161 data_free as fragmentation 2162 FROM information_schema.tables 2163 WHERE table_schema = %s AND table_name = %s', 2164 $_wpdb->dbname, 2165 $table_name 2166 ), 2167 ARRAY_A 2168 ); 2169 2170 $table_info['health'] = array( 2171 'row_count' => $health_info ? (int) $health_info['row_count'] : 0, 2172 'data_size' => $health_info ? (int) $health_info['data_size'] : 0, 2173 'index_size' => $health_info ? (int) $health_info['index_size'] : 0, 2174 'needs_optimization' => $health_info && (int) $health_info['fragmentation'] > 0, 2175 ); 2176 2177 } catch ( \Exception $e ) { 2178 return new \WP_Error( 'database_error', 'Database error: ' . $e->getMessage() ); 2179 } 2180 2181 return $table_info; 2182 } 2083 2183 } 2084 2184 } -
0-day-analytics/tags/4.7.0/classes/vendor/lists/views/class-hooks-management-view.php
r3442115 r3451291 172 172 173 173 if ( $id ) { 174 global $wpdb; 175 $table = Hooks_Management_Entity::get_table_name(); 176 177 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 178 $hook = $wpdb->get_row( 179 $wpdb->prepare( 'SELECT * FROM `' . $table . '` WHERE id = %d', $id ), 180 ARRAY_A 181 ); 174 $hook = Hooks_Management_Entity::load( 'id = %d', array( $id ) ); 182 175 183 176 if ( ! $hook ) { -
0-day-analytics/tags/4.7.0/classes/vendor/lists/views/class-logs-list-view.php
r3391413 r3451291 31 31 */ 32 32 class Logs_List_View { 33 34 33 /** 35 34 * Displays the settings page. … … 59 58 <?php 60 59 61 $plugin_filter = $_REQUEST['plugin_filter'] ?? ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 60 // Verify nonce for security 61 if ( isset( $_REQUEST['advanced-analytics-security'] ) && \wp_verify_nonce( \sanitize_key( \wp_unslash( $_REQUEST['advanced-analytics-security'] ) ), 'advan-plugin-data' ) ) { 62 $plugin_filter = isset( $_REQUEST['plugin_filter'] ) ? \sanitize_text_field( \wp_unslash( $_REQUEST['plugin_filter'] ) ) : ''; 63 } else { 64 $plugin_filter = ''; 65 } 62 66 63 $plugin_filter = \sanitize_text_field( \wp_unslash( $plugin_filter ) ); 64 $events_list = new Logs_List( 67 $events_list = new Logs_List( 65 68 array( 66 69 'plugin_filter' => $plugin_filter, … … 103 106 } 104 107 105 if ( ! empty( $_GET['single_severity_filter_top'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Verified via WP_Helper::verify_admin_nonce below.108 if ( ! empty( $_GET['single_severity_filter_top'] ) ) { 106 109 WP_Helper::verify_admin_nonce( 'advan-plugin-data', 'advanced-analytics-security' ); 107 110 108 111 // Validate and strictly compare plugin filter against known plugin bases. 109 if ( isset( $_GET['plugin_filter'] ) && '' !== $_GET['plugin_filter'] && -1 !== (int) $_GET['plugin_filter'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified above.110 $raw_plugin_filter = \sanitize_text_field( \wp_unslash( (string) $_GET['plugin_filter'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified above.112 if ( isset( $_GET['plugin_filter'] ) && '' !== $_GET['plugin_filter'] && -1 !== (int) $_GET['plugin_filter'] ) { 113 $raw_plugin_filter = \sanitize_text_field( \wp_unslash( (string) $_GET['plugin_filter'] ) ); 111 114 if ( ! \in_array( $raw_plugin_filter, Plugin_Theme_Helper::get_plugins_bases(), true ) ) { 112 \wp_safe_redirect( 113 \remove_query_arg( 114 array( 'severity_filter', 'bulk_action', 'single_severity_filter_top', 'filter_action', 'plugin_filter' ), 115 isset( $_SERVER['REQUEST_URI'] ) ? \esc_url_raw( \wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' 116 ) 117 ); 118 exit; 115 if ( ! \in_array( $raw_plugin_filter, Plugin_Theme_Helper::get_plugins_bases(), true ) ) { 116 \wp_safe_redirect( 117 \remove_query_arg( 118 array( 'severity_filter', 'bulk_action', 'single_severity_filter_top', 'filter_action', 'plugin_filter' ), 119 isset( $_SERVER['REQUEST_URI'] ) ? \esc_url_raw( \wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' 120 ) 121 ); 122 exit; 123 } 119 124 } 125 126 \wp_safe_redirect( 127 \remove_query_arg( array( 'severity_filter', 'bulk_action', 'single_severity_filter_top', 'filter_action' ), isset( $_SERVER['REQUEST_URI'] ) ? \esc_url_raw( \wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' ) 128 ); 129 exit; 120 130 } 121 122 \wp_safe_redirect(123 \remove_query_arg( array( 'severity_filter', 'bulk_action', 'single_severity_filter_top', 'filter_action' ), isset( $_SERVER['REQUEST_URI'] ) ? \esc_url_raw( \wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' )124 );125 exit;126 131 } 127 132 } -
0-day-analytics/tags/4.7.0/readme.txt
r3448917 r3451291 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 4. 6.07 Stable tag: 4.7.0 8 8 License: GPLv3 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-3.0.txt … … 93 93 == Changelog == 94 94 95 = 4.7.0 = 96 * Hooks module improvements - group assignment in bulk. Bug fixes and code optimizations. 97 95 98 = 4.6.0 = 96 99 * Hooks module improvements and small styling issues fixed. -
0-day-analytics/trunk/advanced-analytics.php
r3448917 r3451291 11 11 * Plugin Name: 0 Day Analytics 12 12 * Description: Take full control of error log, crons, transients, plugins, requests, mails and DB tables. 13 * Version: 4. 6.013 * Version: 4.7.0 14 14 * Author: Stoil Dobrev 15 15 * Author URI: https://github.com/sdobreff/ … … 39 39 // Constants. 40 40 if ( ! defined( 'ADVAN_VERSION' ) ) { 41 define( 'ADVAN_VERSION', '4. 6.0' );41 define( 'ADVAN_VERSION', '4.7.0' ); 42 42 define( 'ADVAN_TEXTDOMAIN', '0-day-analytics' ); 43 43 define( 'ADVAN_NAME', '0 Day Analytics' ); -
0-day-analytics/trunk/classes/migration/class-migration.php
r3448917 r3451291 14 14 15 15 use ADVAN\Helpers\Settings; 16 use ADVAN\Entities\WP_Mail_Entity; 17 use ADVAN\Entities\WP_Fatals_Entity; 18 use ADVAN\Entities\Requests_Log_Entity; 16 19 use ADVAN\Entities_Global\Common_Table; 17 use ADVAN\Entities\WP_Mail_Entity;18 use ADVAN\Entities\Requests_Log_Entity;19 20 use ADVAN\Migration\Abstract_Migration; 20 21 … … 267 268 } 268 269 } 270 271 /** 272 * Migrates the plugin up-to version 4.7.0 (adds performance indexes to fatals table). 273 * 274 * @return void 275 * 276 * @since 4.7.0 277 */ 278 public static function migrate_up_to_470() { 279 if ( \class_exists( '\\ADVAN\\Entities\\WP_Fatals_Entity' ) ) { 280 if ( Common_Table::check_table_exists( WP_Fatals_Entity::get_table_name() ) ) { 281 WP_Fatals_Entity::alter_table_470(); 282 } 283 } 284 } 269 285 } 270 286 } -
0-day-analytics/trunk/classes/vendor/controllers/class-hooks-capture.php
r3448917 r3451291 192 192 193 193 // In WP-CLI context, ensure hooks are attached properly. 194 if ( defined( 'WP_CLI' ) && WP_CLI ) {194 if ( defined( 'WP_CLI' ) && \WP_CLI ) { 195 195 self::attach_hooks_cli(); 196 196 } else { -
0-day-analytics/trunk/classes/vendor/controllers/class-reverse-line-reader.php
r3393178 r3451291 28 28 29 29 /** 30 * Memory limit in MB before triggering cleanup or termination 31 */ 32 const MEMORY_LIMIT_MB = 32; 33 34 /** 35 * Time limit in seconds for processing 36 */ 37 const TIME_LIMIT_SECONDS = 25; 38 39 /** 40 * Maximum number of collected items to prevent memory exhaustion 41 */ 42 const MAX_COLLECTED_ITEMS = 1000; 43 44 /** 30 45 * Keeps track of of the current position in the file. 31 46 * … … 80 95 */ 81 96 private static $memory_handle = null; 97 98 /** 99 * Stores the overflow file handle for spilling data to disk when memory is critical. 100 * 101 * @var resource|null 102 * 103 * @since 1.9.3 104 */ 105 private static $overflow_handle = null; 82 106 83 107 /** … … 146 170 } 147 171 172 // Adaptive buffer sizing based on available memory. 173 $available_memory = self::get_available_memory_mb(); 174 if ( $available_memory < 50 ) { // Low memory system. 175 self::$buffer_size = min( self::$buffer_size, 4096 ); // Use smaller buffer. 176 } elseif ( $available_memory < 100 ) { // Medium memory system. 177 self::$buffer_size = min( self::$buffer_size, 8192 ); // Use medium buffer. 178 } 179 // Otherwise use default BUFFER_SIZE. 180 148 181 self::$file_size = - (int) $size; 149 182 } 183 184 // Initialize memory and time monitoring. 185 $start_time = time(); 186 $start_memory = memory_get_usage( true ); 187 $processed_lines = 0; 150 188 151 189 $line = self::readline(); … … 165 203 } 166 204 $result = $callback( $line, self::$pos ); 205 206 // Memory and time safety checks. 207 ++$processed_lines; 208 $current_memory_mb = ( memory_get_usage( true ) - $start_memory ) / 1024 / 1024; 209 $elapsed_time = time() - $start_time; 210 211 // Terminate if memory limit exceeded. 212 if ( $current_memory_mb > self::MEMORY_LIMIT_MB ) { 213 if ( function_exists( 'error_log' ) ) { 214 error_log( 'Reverse_Line_Reader: Memory limit exceeded (' . round( $current_memory_mb, 2 ) . 'MB), terminating processing' ); 215 } 216 self::reset_class_globals(); 217 $max_lines = 0; 218 return false; 219 } 220 221 // Create overflow file if memory is getting critical (80% of limit). 222 if ( $current_memory_mb > ( self::MEMORY_LIMIT_MB * 0.8 ) && null === self::$overflow_handle ) { 223 self::$overflow_handle = self::create_overflow_temp_file(); 224 if ( self::$overflow_handle && function_exists( 'error_log' ) ) { 225 error_log( 'Reverse_Line_Reader: Created overflow file due to high memory usage (' . round( $current_memory_mb, 2 ) . 'MB)' ); 226 } 227 } 228 229 // Terminate if time limit exceeded. 230 if ( $elapsed_time > self::TIME_LIMIT_SECONDS ) { 231 if ( function_exists( 'error_log' ) ) { 232 error_log( 'Reverse_Line_Reader: Time limit exceeded (' . $elapsed_time . 's), terminating processing' ); 233 } 234 self::reset_class_globals(); 235 $max_lines = 0; 236 return false; 237 } 167 238 168 239 if ( true === $result['close'] ) { … … 283 354 */ 284 355 public static function write_memory_file( string $line ) { 356 // If overflow file is active, write to it instead of memory. 357 if ( null !== self::$overflow_handle ) { 358 fwrite( self::$overflow_handle, $line ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite 359 return; 360 } 361 285 362 if ( null === self::$memory_handle ) { 286 363 self::$memory_handle = fopen( 'php://memory', 'w+' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen … … 301 378 rewind( self::$temp_handle ); // resets the position of pointer. 302 379 380 // Content is pre-escaped with esc_html() before being written to temp file 303 381 echo fread( self::$temp_handle, fstat( self::$temp_handle )['size'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread, WordPress.Security.EscapeOutput.OutputNotEscaped 304 382 … … 315 393 */ 316 394 public static function read_memory_file() { 317 if ( \is_resource( self::$memory_handle ) && ( 'handle' === get_resource_type( self::$memory_handle ) || 'stream' === get_resource_type( self::$memory_handle ) ) ) { 395 // If overflow file exists, read from it instead. 396 if ( \is_resource( self::$overflow_handle ) && ( 'handle' === get_resource_type( self::$overflow_handle ) || 'stream' === get_resource_type( self::$overflow_handle ) ) ) { 397 rewind( self::$overflow_handle ); // resets the position of pointer. 398 399 // Content is pre-escaped with esc_html() before being written to overflow file. 400 echo fread( self::$overflow_handle, fstat( self::$overflow_handle )['size'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread, WordPress.Security.EscapeOutput.OutputNotEscaped 401 402 fclose( self::$overflow_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 403 self::$overflow_handle = null; 404 } elseif ( \is_resource( self::$memory_handle ) && ( 'handle' === get_resource_type( self::$memory_handle ) || 'stream' === get_resource_type( self::$memory_handle ) ) ) { 318 405 rewind( self::$memory_handle ); // resets the position of pointer. 319 406 407 // Content is pre-escaped with esc_html() before being written to memory file. 320 408 echo fread( self::$memory_handle, fstat( self::$memory_handle )['size'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fread, WordPress.Security.EscapeOutput.OutputNotEscaped 321 409 … … 334 422 */ 335 423 public static function flush_memory_file_to_temp() { 336 if ( \is_resource( self::$memory_handle ) && ( 'handle' === get_resource_type( self::$memory_handle ) || 'stream' === get_resource_type( self::$memory_handle ) ) ) {337 424 // Handle overflow file first if it exists. 425 if ( \is_resource( self::$overflow_handle ) && ( 'handle' === get_resource_type( self::$overflow_handle ) || 'stream' === get_resource_type( self::$overflow_handle ) ) ) { 338 426 $line = ''; 339 for ( $x_pos = 0; fseek( self::$ memory_handle, $x_pos, SEEK_END ) !== -1; $x_pos-- ) { // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed340 $char = fgetc( self::$ memory_handle );427 for ( $x_pos = 0; fseek( self::$overflow_handle, $x_pos, SEEK_END ) !== -1; $x_pos-- ) { // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed 428 $char = fgetc( self::$overflow_handle ); 341 429 342 430 if ( PHP_EOL === $char ) { … … 351 439 self::write_temp_file( $line . PHP_EOL ); 352 440 } 441 fclose( self::$overflow_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 442 self::$overflow_handle = null; 443 } elseif ( \is_resource( self::$memory_handle ) && ( 'handle' === get_resource_type( self::$memory_handle ) || 'stream' === get_resource_type( self::$memory_handle ) ) ) { 444 $line = ''; 445 for ( $x_pos = 0; fseek( self::$memory_handle, $x_pos, SEEK_END ) !== -1; $x_pos-- ) { // phpcs:ignore Generic.CodeAnalysis.ForLoopWithTestFunctionCall.NotAllowed 446 $char = fgetc( self::$memory_handle ); 447 448 if ( PHP_EOL === $char ) { 449 self::write_temp_file( $line . PHP_EOL ); 450 $line = ''; 451 continue; 452 } else { 453 $line = $char . $line; 454 } 455 } 456 if ( ! empty( $line ) ) { 457 self::write_temp_file( $line . PHP_EOL ); 458 } 353 459 fclose( self::$memory_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 354 355 460 self::$memory_handle = null; 356 461 } … … 375 480 self::$memory_handle = null; 376 481 } 482 if ( \is_resource( self::$overflow_handle ) && ( 'handle' === get_resource_type( self::$overflow_handle ) || 'stream' === get_resource_type( self::$overflow_handle ) ) ) { 483 fclose( self::$overflow_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 484 485 self::$overflow_handle = null; 486 } 377 487 } 378 488 … … 387 497 if ( \is_resource( self::$error_log_handle ) && ( 'handle' === get_resource_type( self::$error_log_handle ) || 'stream' === get_resource_type( self::$error_log_handle ) ) ) { 388 498 \fclose( self::$error_log_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 499 } 500 501 if ( \is_resource( self::$overflow_handle ) ) { 502 \fclose( self::$overflow_handle ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose 389 503 } 390 504 … … 393 507 self::$pos = null; 394 508 self::$error_log_handle = null; 509 self::$overflow_handle = null; 510 } 511 512 /** 513 * Get available memory in MB 514 * 515 * @return int Available memory in MB 516 * 517 * @since latest 518 */ 519 public static function get_available_memory_mb() { 520 $memory_limit = ini_get( 'memory_limit' ); 521 if ( '-1' === $memory_limit ) { 522 return 256; // Assume 256MB if no limit. 523 } 524 525 $memory_limit_bytes = wp_convert_hr_to_bytes( $memory_limit ); 526 $current_usage = memory_get_usage( true ); 527 $available = max( 0, $memory_limit_bytes - $current_usage ); 528 529 return (int) ( $available / 1024 / 1024 ); 530 } 531 532 /** 533 * Check if available memory is below critical threshold 534 * 535 * @return bool True if memory is critical, false otherwise 536 * 537 * @since latest 538 */ 539 public static function is_memory_critical() { 540 $available_mb = self::get_available_memory_mb(); 541 return $available_mb < 10; // Less than 10MB available. 395 542 } 396 543 … … 451 598 return self::$temp_handle; 452 599 } 600 601 /** 602 * Create a temporary file for overflow data when memory is critical 603 * 604 * @return resource|false File handle or false on failure 605 * 606 * @since latest 607 */ 608 public static function create_overflow_temp_file() { 609 $temp_dir = get_temp_dir(); 610 $temp_file = tempnam( $temp_dir, 'advana_overflow_' ); 611 612 if ( $temp_file && is_writable( $temp_file ) ) { 613 return fopen( $temp_file, 'w+' ); 614 } 615 616 return false; 617 } 618 619 /** 620 * Clean up temporary overflow files 621 * 622 * @return void 623 * 624 * @since latest 625 */ 626 public static function cleanup_overflow_files() { 627 $temp_dir = get_temp_dir(); 628 $pattern = $temp_dir . '/advana_overflow_*'; 629 630 foreach ( glob( $pattern ) as $file ) { 631 if ( is_file( $file ) && filemtime( $file ) < time() - 3600 ) { // Older than 1 hour. 632 unlink( $file ); 633 } 634 } 635 } 453 636 } 454 637 } -
0-day-analytics/trunk/classes/vendor/controllers/classes-snippets-controller.php
r3413502 r3451291 141 141 } 142 142 } 143 143 144 /** 144 145 * Fetch and cache runtime snippets list. … … 153 154 } 154 155 155 $wpdb = Snippet_Entity::get_connection(); 156 $table = Snippet_Entity::get_table_name( $wpdb ); 157 158 $query = $wpdb->prepare( 159 'SELECT * FROM ' . $table . ' WHERE blog_id = %d AND status = %d AND type = %s', 160 \get_current_blog_id(), 161 Snippet_Entity::STATUS_ENABLED, 162 'php' 163 ); 164 165 $wpdb->suppress_errors( true ); 166 $results = $wpdb->get_results( $query, ARRAY_A ); 167 if ( '' !== $wpdb->last_error ) { 168 if ( 1146 === Snippet_Entity::get_last_sql_error( $wpdb ) ) { 169 if ( Snippet_Entity::create_table( $wpdb ) ) { 170 $results = array(); 171 } 172 } 173 } 174 $wpdb->suppress_errors( false ); 175 176 self::$runtime_snippets = is_array( $results ) ? $results : array(); 156 self::$runtime_snippets = Snippet_Entity::get_runtime_snippets(); 177 157 178 158 return self::$runtime_snippets; -
0-day-analytics/trunk/classes/vendor/entities/class-hooks-management-entity.php
r3442473 r3451291 2474 2474 } 2475 2475 2476 // Add the ID to the data for the update operation. 2477 $data['id'] = $id; 2478 2479 $result = self::insert( $data ); 2476 // Load current record. 2477 $current = self::load( 'id = %d', $id ); 2478 if ( ! $current ) { 2479 return false; 2480 } 2481 2482 // Merge new data with existing data. 2483 $current = array_merge( $current, $data ); 2484 2485 $result = self::insert( $current ); 2480 2486 2481 2487 // Clear cache. 2482 2488 \wp_cache_delete( 'advan_enabled_hooks', 'advan' ); 2489 self::clear_hook_labels_cache(); 2483 2490 2484 2491 return $result > 0; 2492 } 2493 2494 /** 2495 * Set enabled status for a hook. 2496 * 2497 * @param int $id Hook ID. 2498 * @param bool $enabled Enabled status. 2499 * 2500 * @return bool 2501 * 2502 * @since 4.7.0 2503 */ 2504 public static function set_enabled( int $id, bool $enabled ): bool { 2505 return self::update( 2506 $id, 2507 array( 2508 'enabled' => $enabled ? 1 : 0, 2509 'date_modified' => microtime( true ), 2510 ) 2511 ); 2512 } 2513 2514 /** 2515 * Set group ID for a hook. 2516 * 2517 * @param int $id Hook ID. 2518 * @param int $group_id Group ID. 2519 * 2520 * @return bool 2521 * 2522 * @since 4.7.0 2523 */ 2524 public static function set_group_id( int $id, int $group_id ): bool { 2525 return self::update( 2526 $id, 2527 array( 2528 'group_id' => $group_id, 2529 'date_modified' => microtime( true ), 2530 ) 2531 ); 2532 } 2533 2534 /** 2535 * Get hook parameters by hook name. 2536 * 2537 * @param string $hook_name Hook name. 2538 * 2539 * @return string 2540 * 2541 * @since 4.7.0 2542 */ 2543 public static function get_hook_parameters( string $hook_name ): string { 2544 $hook = self::load( 'hook_name = %s', array( $hook_name ) ); 2545 return $hook && isset( $hook['hook_parameters'] ) ? $hook['hook_parameters'] : ''; 2485 2546 } 2486 2547 } -
0-day-analytics/trunk/classes/vendor/entities/class-snippet-entity.php
r3413502 r3451291 640 640 ); 641 641 } 642 643 /** 644 * Get runtime snippets (enabled PHP snippets for current blog). 645 * 646 * @return array 647 * 648 * @since 4.3.0 649 */ 650 public static function get_runtime_snippets(): array { 651 $wpdb = self::get_connection(); 652 $table = self::get_table_name( $wpdb ); 653 $blog_id = \get_current_blog_id(); 654 655 $query = $wpdb->prepare( 656 'SELECT * FROM ' . $table . ' WHERE blog_id = %d AND status = %d AND type = %s', 657 $blog_id, 658 self::STATUS_ENABLED, 659 'php' 660 ); 661 662 $wpdb->suppress_errors( true ); 663 $results = $wpdb->get_results( $query, ARRAY_A ); 664 if ( '' !== $wpdb->last_error ) { 665 if ( 1146 === self::get_last_sql_error( $wpdb ) ) { 666 if ( self::create_table( $wpdb ) ) { 667 $results = array(); 668 } 669 } 670 } 671 $wpdb->suppress_errors( false ); 672 673 return is_array( $results ) ? $results : array(); 674 } 675 676 /** 677 * Get snippets with filters for AJAX listing. 678 * 679 * @param array $filters Array of filters (search, status, type, etc.). 680 * @param int $offset Pagination offset. 681 * @param int $limit Pagination limit. 682 * 683 * @return array 684 * 685 * @since 4.3.0 686 */ 687 public static function get_snippets_with_filters( array $filters = array(), int $offset = 0, int $limit = 50 ): array { 688 $wpdb = self::get_connection(); 689 $table = self::get_table_name( $wpdb ); 690 $blog_id = \get_current_blog_id(); 691 692 $where = array( 'blog_id = %d' ); 693 $bindings = array( $blog_id ); 694 695 // Search filter 696 if ( ! empty( $filters['search'] ) ) { 697 $search = '%' . $wpdb->esc_like( $filters['search'] ) . '%'; 698 $where[] = '(name LIKE %s OR tags LIKE %s)'; 699 $bindings[] = $search; 700 $bindings[] = $search; 701 } 702 703 // Status filter 704 if ( isset( $filters['status'] ) ) { 705 $status_map = array( 706 'enabled' => self::STATUS_ENABLED, 707 'disabled' => self::STATUS_DISABLED, 708 'trash' => self::STATUS_TRASHED, 709 ); 710 711 if ( isset( $status_map[ $filters['status'] ] ) ) { 712 $where[] = 'status = %d'; 713 $bindings[] = $status_map[ $filters['status'] ]; 714 } else { 715 $where[] = 'status >= %d'; 716 $bindings[] = self::STATUS_DISABLED; 717 } 718 } 719 720 // Type filter 721 if ( ! empty( $filters['type'] ) && in_array( $filters['type'], array_keys( self::get_supported_types() ), true ) ) { 722 $where[] = 'type = %s'; 723 $bindings[] = $filters['type']; 724 } 725 726 $where_sql = $where ? 'WHERE ' . implode( ' AND ', $where ) : ''; 727 $orderby = 'updated_at'; 728 $order = 'DESC'; 729 730 $query = 'SELECT * FROM ' . $table . ' ' . $where_sql . ' ORDER BY ' . $orderby . ' ' . $order . ' LIMIT %d OFFSET %d'; 731 $bindings[] = $limit; 732 $bindings[] = $offset; 733 734 $wpdb->suppress_errors( true ); 735 $results = $wpdb->get_results( $wpdb->prepare( $query, $bindings ), ARRAY_A ); 736 if ( '' !== $wpdb->last_error ) { 737 if ( 1146 === self::get_last_sql_error( $wpdb ) ) { 738 if ( self::create_table( $wpdb ) ) { 739 $results = array(); 740 } 741 } 742 } 743 $wpdb->suppress_errors( false ); 744 745 return is_array( $results ) ? $results : array(); 746 } 747 748 /** 749 * Get total count of snippets with filters. 750 * 751 * @param array $filters Array of filters (search, status, type, etc.). 752 * 753 * @return int 754 * 755 * @since 4.3.0 756 */ 757 public static function get_snippets_count_with_filters( array $filters = array() ): int { 758 $wpdb = self::get_connection(); 759 $table = self::get_table_name( $wpdb ); 760 $blog_id = \get_current_blog_id(); 761 762 $where = array( 'blog_id = %d' ); 763 $bindings = array( $blog_id ); 764 765 // Search filter. 766 if ( ! empty( $filters['search'] ) ) { 767 $search = '%' . $wpdb->esc_like( $filters['search'] ) . '%'; 768 $where[] = '(name LIKE %s OR tags LIKE %s)'; 769 $bindings[] = $search; 770 $bindings[] = $search; 771 } 772 773 // Status filter. 774 if ( isset( $filters['status'] ) ) { 775 $status_map = array( 776 'enabled' => self::STATUS_ENABLED, 777 'disabled' => self::STATUS_DISABLED, 778 'trash' => self::STATUS_TRASHED, 779 ); 780 781 if ( isset( $status_map[ $filters['status'] ] ) ) { 782 $where[] = 'status = %d'; 783 $bindings[] = $status_map[ $filters['status'] ]; 784 } else { 785 $where[] = 'status >= %d'; 786 $bindings[] = self::STATUS_DISABLED; 787 } 788 } 789 790 // Type filter. 791 if ( ! empty( $filters['type'] ) && in_array( $filters['type'], array_keys( self::get_supported_types() ), true ) ) { 792 $where[] = 'type = %s'; 793 $bindings[] = $filters['type']; 794 } 795 796 $where_sql = $where ? 'WHERE ' . implode( ' AND ', $where ) : ''; 797 $query = 'SELECT COUNT(*) FROM ' . $table . ' ' . $where_sql; 798 799 $wpdb->suppress_errors( true ); 800 $count = (int) $wpdb->get_var( $wpdb->prepare( $query, $bindings ) ); 801 if ( '' !== $wpdb->last_error ) { 802 if ( 1146 === self::get_last_sql_error( $wpdb ) ) { 803 if ( self::create_table( $wpdb ) ) { 804 $count = 0; 805 } 806 } 807 } 808 $wpdb->suppress_errors( false ); 809 810 return $count; 811 } 642 812 } 643 813 } -
0-day-analytics/trunk/classes/vendor/entities/class-wp-fatals-entity.php
r3393178 r3451291 651 651 652 652 /** 653 * Alters the table for version 4.7.0 - adds performance indexes 654 * 655 * @return bool 656 * 657 * @since 4.7.0 658 */ 659 public static function alter_table_470(): bool { 660 $table_name = self::get_table_name(); 661 $indexes = array( 662 'severity' => 'ADD KEY severity (severity)', 663 'source_slug' => 'ADD KEY source_slug (source_slug)', 664 'source_type' => 'ADD KEY source_type (source_type)', 665 ); 666 667 foreach ( $indexes as $index_sql ) { 668 $sql = "ALTER TABLE `$table_name` $index_sql"; 669 // Use try-catch or check if index exists by attempting the alter 670 // Since MySQL ignores duplicate key errors, we can safely run this. 671 self::get_connection()->query( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- DDL operation, no caching needed. 672 } 673 674 return true; 675 } 676 677 /** 678 * Prunes old fatal error records based on retention settings 679 * 680 * @param int $retention_days - Number of days to keep records (default 90) 681 * 682 * @return int Number of records deleted 683 * 684 * @since 4.7.0 685 */ 686 public static function prune_old_records( int $retention_days = 90 ): int { 687 global $wpdb; 688 $cutoff_time = time() - ( $retention_days * 24 * 60 * 60 ); 689 $table_name = self::get_table_name(); 690 691 $sql = $wpdb->prepare( 692 "DELETE FROM `$table_name` WHERE datetime < %d", 693 $cutoff_time 694 ); 695 696 $result = $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Bulk delete operation. 697 698 return (int) $result; 699 } 700 701 /** 653 702 * Generates drop down with all the subsites that have mail logs. 654 703 * -
0-day-analytics/trunk/classes/vendor/helpers/class-ajax-helper.php
r3442115 r3451291 153 153 \add_action( 'wp_ajax_aadvana_export_large_csv', array( __CLASS__, 'export_large_csv' ) ); 154 154 \add_action( 'wp_ajax_aadvana_export_large_csv_cleanup', array( __CLASS__, 'export_large_csv_cleanup' ) ); 155 \add_action( 'wp_ajax_aadvana_get_table_info', array( __CLASS__, 'get_table_info' ) ); 155 156 156 157 if ( Settings::get_option( 'server_info_module_enabled' ) ) { … … 975 976 $snippet_type = isset( $_POST['snippet_type'] ) ? \sanitize_text_field( wp_unslash( $_POST['snippet_type'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing 976 977 977 $extra_file_name = '_snippets_'; 978 979 $wpdb = \ADVAN\Entities\Snippet_Entity::get_connection(); 980 $table = \ADVAN\Entities\Snippet_Entity::get_table_name( $wpdb ); 981 982 $where = array( 'blog_id = %d' ); 983 $bindings = array( get_current_blog_id() ); 978 $filters = array(); 984 979 985 980 if ( '' !== $search ) { 986 $like = '%' . $wpdb->esc_like( $search ) . '%'; 987 $where[] = '( name LIKE %s OR tags LIKE %s )'; 988 $bindings[] = $like; 989 $bindings[] = $like; 981 $filters['search'] = $search; 990 982 } 991 983 992 $status_map = array( 993 'enabled' => \ADVAN\Entities\Snippet_Entity::STATUS_ENABLED, 994 'disabled' => \ADVAN\Entities\Snippet_Entity::STATUS_DISABLED, 995 'trash' => \ADVAN\Entities\Snippet_Entity::STATUS_TRASHED, 996 ); 997 998 if ( isset( $status_map[ $snippet_status ] ) ) { 999 $where[] = 'status = %d'; 1000 $bindings[] = $status_map[ $snippet_status ]; 1001 } else { 1002 $where[] = 'status >= %d'; 1003 $bindings[] = \ADVAN\Entities\Snippet_Entity::STATUS_DISABLED; 984 if ( '' !== $snippet_status ) { 985 $filters['status'] = $snippet_status; 1004 986 } 1005 987 1006 $types = array_keys( \ADVAN\Entities\Snippet_Entity::get_supported_types() ); 1007 if ( '' !== $snippet_type && in_array( $snippet_type, $types, true ) ) { 1008 $where[] = 'type = %s'; 1009 $bindings[] = $snippet_type; 988 if ( '' !== $snippet_type ) { 989 $filters['type'] = $snippet_type; 1010 990 } 1011 991 1012 $where_sql = $where ? 'WHERE ' . implode( ' AND ', $where ) : ''; 1013 1014 $count_sql = 'SELECT COUNT(*) FROM ' . $table . ' ' . $where_sql; 1015 $total = (int) $wpdb->get_var( $wpdb->prepare( $count_sql, $bindings ) ); 1016 1017 $orderby = 'updated_at'; 1018 $order = 'DESC'; 1019 1020 $list_sql = 'SELECT * FROM ' . $table . ' ' . $where_sql . ' ORDER BY ' . $orderby . ' ' . $order . ' LIMIT %d OFFSET %d'; 1021 $list_items = $wpdb->get_results( 1022 $wpdb->prepare( 1023 $list_sql, 1024 array_merge( $bindings, array( (int) $batch_size, (int) $offset ) ) 1025 ), 1026 ARRAY_A 1027 ); 1028 1029 $rows = $list_items ?: array(); 992 $total = \ADVAN\Entities\Snippet_Entity::get_snippets_count_with_filters( $filters ); 993 $rows = \ADVAN\Entities\Snippet_Entity::get_snippets_with_filters( $filters, $offset, $batch_size ); 1030 994 } 1031 995 } else { … … 1176 1140 */ 1177 1141 public static function save_hook_group() { 1178 if ( ! \current_user_can( 'manage_options' ) ) { 1179 \wp_send_json_error( 'Unauthorized' ); 1180 } 1181 1182 \check_ajax_referer( 'advan_hook_groups', 'nonce' ); 1142 WP_Helper::verify_admin_nonce( 'advan_hook_groups', 'nonce' ); 1183 1143 1184 1144 if ( ! class_exists( 'ADVAN\Entities\Hook_Groups_Entity' ) ) { … … 1218 1178 */ 1219 1179 public static function delete_hook_group() { 1220 if ( ! \current_user_can( 'manage_options' ) ) { 1221 \wp_send_json_error( 'Unauthorized' ); 1222 } 1223 1224 \check_ajax_referer( 'advan_hook_groups', 'nonce' ); 1180 WP_Helper::verify_admin_nonce( 'advan_hook_groups', 'nonce' ); 1225 1181 1226 1182 if ( ! class_exists( 'ADVAN\Entities\Hook_Groups_Entity' ) ) { … … 1242 1198 } 1243 1199 } 1200 1201 /** 1202 * Get detailed table information including structure, indexes, foreign keys, and health. 1203 * 1204 * @return void 1205 * 1206 * @since 4.7.0 1207 */ 1208 public static function get_table_info() { 1209 WP_Helper::verify_admin_nonce( 'get_table_info', 'security' ); 1210 1211 $table_name = isset( $_POST['table_name'] ) ? \sanitize_text_field( \wp_unslash( $_POST['table_name'] ) ) : ''; 1212 1213 if ( empty( $table_name ) ) { 1214 \wp_send_json_error( 'Invalid table name' ); 1215 } 1216 1217 $table_info = Common_Table::get_table_info( $table_name ); 1218 1219 if ( \is_wp_error( $table_info ) ) { 1220 \wp_send_json_error( $table_info->get_error_message() ); 1221 } 1222 1223 \wp_send_json_success( $table_info ); 1224 } 1244 1225 } 1245 1226 } -
0-day-analytics/trunk/classes/vendor/helpers/class-hook-parameter-renderer.php
r3442473 r3451291 13 13 namespace ADVAN\Helpers; 14 14 15 use ADVAN\Entities\Hooks_Management_Entity; 16 15 17 // Exit if accessed directly. 16 18 if ( ! defined( 'ABSPATH' ) ) { … … 37 39 */ 38 40 public static function render_parameters( string $hook_name, string $parameters ): string { 39 global $wpdb;40 41 41 // Get hook definition from hooks_management table. 42 $management_table = $wpdb->prefix . ADVAN_PREFIX . 'hooks_management'; 43 44 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 45 $hook_config = $wpdb->get_row( 46 $wpdb->prepare( 47 "SELECT hook_parameters FROM `{$management_table}` WHERE hook_name = %s LIMIT 1", 48 $hook_name 49 ), 50 ARRAY_A 51 ); 42 $hook_parameters = Hooks_Management_Entity::get_hook_parameters( $hook_name ); 52 43 53 44 // Decode captured parameters. … … 59 50 // Get parameter definitions. 60 51 $param_defs = array(); 61 if ( $hook_config && ! empty( $hook_config['hook_parameters']) ) {62 $param_defs = json_decode( $hook_ config['hook_parameters'], true );52 if ( ! empty( $hook_parameters ) ) { 53 $param_defs = json_decode( $hook_parameters, true ); 63 54 if ( ! is_array( $param_defs ) ) { 64 55 $param_defs = array(); … … 146 137 } 147 138 } 139 } 140 141 if ( \is_array( $value ) && ! \in_array( $type, array( 'array', 'object' ), true ) ) { 142 $type = 'array'; 148 143 } 149 144 // Override type if actual value type differs significantly. … … 216 211 * 217 212 * @throws \Throwable If code execution fails. 213 * @throws \Exception If unsafe code is detected. 218 214 * 219 215 * @since 4.5.0 … … 564 560 $bool_val = filter_var( $value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ); 565 561 if ( is_null( $bool_val ) ) { 566 return '<code>' . \esc_html( $value ) . '</code>';562 return '<code>' . \esc_html( (string) $value ) . '</code>'; 567 563 } 568 564 return $bool_val ? '<span style="color: green;">✓ true</span>' : '<span style="color: #999;">✗ false</span>'; … … 586 582 return '<code>' . \esc_html( $str ) . '</code>'; 587 583 } 588 return '<code>' . \esc_html( print_r( $value, true ) ) . '</code>';584 return '<code>' . \esc_html( print_r( (array) $value, true ) ) . '</code>'; 589 585 } 590 586 -
0-day-analytics/trunk/classes/vendor/lists/class-fatals-list.php
r3442115 r3451291 81 81 82 82 /** 83 * Maximum stack trace lines to display in details 84 * 85 * @var int 86 * 87 * @since 4.7.0 88 */ 89 protected const MAX_STACK_TRACE_LINES = 50; 90 91 /** 83 92 * Holds the prepared options for speeding the process 84 93 * … … 222 231 $plugin = -1; 223 232 } else { 224 $plugin = \sanitize_text_field( \wp_unslash( $_REQUEST['plugin'] ) ); 233 $plugin_raw = \sanitize_text_field( \wp_unslash( $_REQUEST['plugin'] ) ); 234 // Validate plugin slug format (alphanumeric, dashes, underscores, max 255 chars). 235 if ( preg_match( '/^[a-zA-Z0-9\-_]{1,255}$/', $plugin_raw ) ) { 236 $plugin = $plugin_raw; 237 } else { 238 $plugin = ''; 239 } 225 240 } 226 241 } else { … … 469 484 'action' => 'log_source_view', 470 485 ); 486 $line_count = 0; 471 487 foreach ( $reversed_details as $val ) { 488 if ( $line_count >= self::MAX_STACK_TRACE_LINES ) { 489 $message .= '<br>... (' . ( count( $reversed_details ) - $line_count ) . ' more lines truncated)'; 490 break; 491 } 472 492 473 493 $source_link = ''; … … 503 523 504 524 $message = \rtrim( $message, ' - ' ); 525 $line_count++; 505 526 } 506 527 $message .= '</pre></div>'; -
0-day-analytics/trunk/classes/vendor/lists/class-hooks-capture-list.php
r3448917 r3451291 746 746 $hook_name = '<code>' . \esc_html( $item[ $column_name ] ) . '</code>'; 747 747 748 // Make hook name a link to hooks management if hooks_management_id is available 748 // Make hook name a link to hooks management if hooks_management_id is available. 749 749 if ( ! empty( $item['hooks_management_id'] ) ) { 750 750 $edit_url = \network_admin_url( 'admin.php?page=advan_hooks_management&action=edit&id=' . absint( $item['hooks_management_id'] ) ); -
0-day-analytics/trunk/classes/vendor/lists/class-hooks-management-list.php
r3442115 r3451291 22 22 use ADVAN\Entities_Global\Common_Table; 23 23 use ADVAN\Entities\Hooks_Management_Entity; 24 use ADVAN\Entities\Hook_Groups_Entity; 24 25 use ADVAN\Lists\Views\Hooks_Management_View; 25 26 … … 452 453 */ 453 454 public function get_bulk_actions() { 454 returnarray(455 $actions = array( 455 456 'delete' => \esc_html__( 'Delete', '0-day-analytics' ), 456 457 'enable' => \esc_html__( 'Enable', '0-day-analytics' ), 457 458 'disable' => \esc_html__( 'Disable', '0-day-analytics' ), 458 459 ); 460 461 // Add group assignment actions. 462 $groups = Hook_Groups_Entity::get_groups_array(); 463 if ( ! empty( $groups ) ) { 464 foreach ( $groups as $group_id => $group ) { 465 $actions[ 'assign_group_' . $group_id ] = sprintf( 466 /* translators: %s: Group name */ 467 \esc_html__( 'Assign to group: %s', '0-day-analytics' ), 468 $group['name'] 469 ); 470 } 471 } 472 473 return $actions; 459 474 } 460 475 … … 539 554 540 555 // Handle bulk actions. 541 if ( in_array( $action, array( 'delete', 'enable', 'disable' ), true ) ) {556 if ( in_array( $action, array( 'delete', 'enable', 'disable' ), true ) || ( is_string( $action ) && strpos( $action, 'assign_group_' ) === 0 ) ) { 542 557 $nonce = isset( $_REQUEST['_wpnonce'] ) ? \sanitize_text_field( \wp_unslash( $_REQUEST['_wpnonce'] ) ) : ''; 543 558 … … 550 565 551 566 if ( ! empty( $ids ) ) { 552 global $wpdb;553 $table = Hooks_Management_Entity::get_table_name();554 555 567 foreach ( $ids as $id ) { 556 568 if ( 'delete' === $action ) { 557 569 Hooks_Management_Entity::delete_by_id( $id ); 558 570 } elseif ( 'enable' === $action ) { 559 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 560 $wpdb->query( 561 $wpdb->prepare( 562 "UPDATE `{$table}` SET enabled = 1, date_modified = %f WHERE id = %d", 563 microtime( true ), 564 $id 565 ) 566 ); 571 Hooks_Management_Entity::set_enabled( $id, true ); 567 572 } elseif ( 'disable' === $action ) { 568 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching569 $wpdb->query(570 $wpdb->prepare(571 "UPDATE `{$table}` SET enabled = 0, date_modified = %f WHERE id = %d",572 microtime( true ),573 $id 574 )575 );573 Hooks_Management_Entity::set_enabled( $id, false ); 574 } elseif ( is_string( $action ) && strpos( $action, 'assign_group_' ) === 0 ) { 575 // Extract group ID from action. 576 $group_id = str_replace( 'assign_group_', '', $action ); 577 $group_id = absint( $group_id ); 578 579 // Update the group_id for this hook. 580 Hooks_Management_Entity::set_group_id( $id, $group_id ); 576 581 } 577 582 } -
0-day-analytics/trunk/classes/vendor/lists/class-logs-list.php
r3442115 r3451291 365 365 $result = Reverse_Line_Reader::read_file_from_end( 366 366 $file, 367 function( $line, $pos ) use ( &$collected_items, &$errors, &$position ) {367 function( $line, $pos ) use ( &$collected_items, &$errors, &$position, $items, $write_temp ) { 368 368 369 369 $position = $pos; 370 371 // Prevent memory exhaustion from extremely large multi-line errors. 372 if ( count( $collected_items ) > 500 ) { // Reasonable limit for stack traces. 373 $collected_items = array_slice( $collected_items, -100 ); // Keep last 100 items. 374 // if ( function_exists( 'error_log' ) ) { 375 // error_log( 'Logs_List: Truncated collected_items due to size limit (' . count( $collected_items ) . ' items)' ); 376 // } 377 } 370 378 371 379 // Flag that holds the status of the error - are there more lines to read or not. … … 387 395 $errors[] = $parsed_data; 388 396 $more_to_error = false; 397 398 // Prevent memory exhaustion from too many errors. 399 if ( count( $errors ) >= $items * 2 ) { // Allow some buffer. 400 return array( 401 'close' => true, 402 'line_done' => true, 403 'no_flush' => false, 404 ); 405 } 389 406 } elseif ( \is_array( $parsed_data ) ) { 390 407 if ( isset( $parsed_data['call'] ) && str_starts_with( trim( $parsed_data['call'] ), 'made by' ) ) { … … 1233 1250 } 1234 1251 ?> 1235 <option <?php echo ( $selected ); ?> value="<?php echo \esc_attr( $name ); ?>"><?php echo \esc_ attr( $name ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped?></option>1252 <option <?php echo ( $selected ); ?> value="<?php echo \esc_attr( $name ); ?>"><?php echo \esc_html( $name ); ?></option> 1236 1253 <?php 1237 1254 } -
0-day-analytics/trunk/classes/vendor/lists/class-table-list.php
r3442115 r3451291 643 643 644 644 </select> 645 <?php if ( 'top' === $which ) : ?> 646 <button id="table-info-btn" class="button button-secondary" title="<?php esc_attr_e( 'View table information', '0-day-analytics' ); ?>"> 647 <span class="dashicons dashicons-info"></span> 648 <?php esc_html_e( 'Info', '0-day-analytics' ); ?> 649 </button> 650 <?php endif; ?> 645 651 646 652 </div> … … 667 673 <?php 668 674 } 675 676 // Table info modal - only for top navigation 677 if ( 'top' === $which ) : 678 ?> 679 <div id="table-info-modal" class="table-info-modal" style="display: none;"> 680 <div class="table-info-modal-content"> 681 <div class="table-info-modal-header"> 682 <h3><?php printf( esc_html__( 'Table Information: %s', '0-day-analytics' ), esc_html( self::$table::get_name() ) ); ?></h3> 683 <button type="button" class="table-info-modal-close">×</button> 684 </div> 685 <div class="table-info-modal-body"> 686 <div class="table-info-loading"> 687 <span class="spinner is-active"></span> 688 <?php esc_html_e( 'Loading table information...', '0-day-analytics' ); ?> 689 </div> 690 <div class="table-info-content" style="display: none;"> 691 <div class="table-info-section"> 692 <h4><?php esc_html_e( 'Table Structure', '0-day-analytics' ); ?></h4> 693 <div class="table-structure-info"></div> 694 </div> 695 <div class="table-info-section"> 696 <h4><?php esc_html_e( 'Indexes', '0-day-analytics' ); ?></h4> 697 <div class="table-indexes-info"></div> 698 </div> 699 <div class="table-info-section"> 700 <h4><?php esc_html_e( 'Foreign Keys', '0-day-analytics' ); ?></h4> 701 <div class="table-foreign-keys-info"></div> 702 </div> 703 <div class="table-info-section"> 704 <h4><?php esc_html_e( 'Table Health', '0-day-analytics' ); ?></h4> 705 <div class="table-health-info"></div> 706 </div> 707 </div> 708 </div> 709 </div> 710 </div> 711 <?php endif; ?> 712 713 <?php 669 714 // if ( 'top' === $which ) { 670 715 global $wpdb; … … 836 881 makeSearchableDropdown(document.getElementById("table_filter_<?php echo \esc_attr( $which ); ?>")); 837 882 883 <?php if ( 'top' === $which ) { ?> 884 // Table info modal functionality 885 const tableInfoBtn = document.getElementById('table-info-btn'); 886 const tableInfoModal = document.getElementById('table-info-modal'); 887 const tableInfoClose = document.querySelector('.table-info-modal-close'); 888 889 if (tableInfoBtn && tableInfoModal) { 890 tableInfoBtn.addEventListener('click', function(e) { 891 e.preventDefault(); 892 loadTableInfo(); 893 tableInfoModal.style.display = 'block'; 894 }); 895 896 tableInfoClose.addEventListener('click', function() { 897 tableInfoModal.style.display = 'none'; 898 }); 899 900 window.addEventListener('click', function(e) { 901 if (e.target === tableInfoModal) { 902 tableInfoModal.style.display = 'none'; 903 } 904 }); 905 } 906 907 function loadTableInfo() { 908 const loadingEl = document.querySelector('.table-info-loading'); 909 const contentEl = document.querySelector('.table-info-content'); 910 911 loadingEl.style.display = 'block'; 912 contentEl.style.display = 'none'; 913 914 fetch('<?php echo esc_url(admin_url('admin-ajax.php')); ?>', { 915 method: 'POST', 916 headers: { 917 'Content-Type': 'application/x-www-form-urlencoded', 918 }, 919 body: new URLSearchParams({ 920 action: 'aadvana_get_table_info', 921 table_name: '<?php echo esc_js(self::$table::get_name()); ?>', 922 security: '<?php echo wp_create_nonce('get_table_info'); ?>' 923 }) 924 }) 925 .then(response => response.json()) 926 .then(data => { 927 loadingEl.style.display = 'none'; 928 if (data.success) { 929 displayTableInfo(data.data); 930 contentEl.style.display = 'block'; 931 } else { 932 alert('<?php esc_html_e('Error loading table information', '0-day-analytics'); ?>: ' + data.data); 933 } 934 }) 935 .catch(error => { 936 loadingEl.style.display = 'none'; 937 alert('<?php esc_html_e('Error loading table information', '0-day-analytics'); ?>: ' + error.message); 938 }); 939 } 940 941 function displayTableInfo(info) { 942 // Table Structure 943 const structureEl = document.querySelector('.table-structure-info'); 944 if (info.structure && info.structure.length > 0) { 945 let html = '<table class="widefat striped"><thead><tr><th><?php esc_html_e('Column', '0-day-analytics'); ?></th><th><?php esc_html_e('Type', '0-day-analytics'); ?></th><th><?php esc_html_e('Null', '0-day-analytics'); ?></th><th><?php esc_html_e('Key', '0-day-analytics'); ?></th><th><?php esc_html_e('Default', '0-day-analytics'); ?></th><th><?php esc_html_e('Extra', '0-day-analytics'); ?></th></tr></thead><tbody>'; 946 info.structure.forEach(col => { 947 html += `<tr> 948 <td><code>${escapeHtml(col.Field)}</code></td> 949 <td><code>${escapeHtml(col.Type)}</code></td> 950 <td>${escapeHtml(col.Null)}</td> 951 <td>${escapeHtml(col.Key || '')}</td> 952 <td>${escapeHtml(col.Default || '')}</td> 953 <td>${escapeHtml(col.Extra || '')}</td> 954 </tr>`; 955 }); 956 html += '</tbody></table>'; 957 structureEl.innerHTML = html; 958 } else { 959 structureEl.innerHTML = '<p><?php esc_html_e('No column information available', '0-day-analytics'); ?></p>'; 960 } 961 962 // Indexes 963 const indexesEl = document.querySelector('.table-indexes-info'); 964 if (info.indexes && info.indexes.length > 0) { 965 let html = '<table class="widefat striped"><thead><tr><th><?php esc_html_e('Key Name', '0-day-analytics'); ?></th><th><?php esc_html_e('Column', '0-day-analytics'); ?></th><th><?php esc_html_e('Unique', '0-day-analytics'); ?></th><th><?php esc_html_e('Type', '0-day-analytics'); ?></th></tr></thead><tbody>'; 966 info.indexes.forEach(idx => { 967 html += `<tr> 968 <td><code>${escapeHtml(idx.Key_name)}</code></td> 969 <td><code>${escapeHtml(idx.Column_name)}</code></td> 970 <td>${idx.Non_unique === '0' ? '<?php esc_html_e('Yes', '0-day-analytics'); ?>' : '<?php esc_html_e('No', '0-day-analytics'); ?>'}</td> 971 <td>${escapeHtml(idx.Index_type)}</td> 972 </tr>`; 973 }); 974 html += '</tbody></table>'; 975 indexesEl.innerHTML = html; 976 } else { 977 indexesEl.innerHTML = '<p><?php esc_html_e('No indexes found', '0-day-analytics'); ?></p>'; 978 } 979 980 // Foreign Keys 981 const fkEl = document.querySelector('.table-foreign-keys-info'); 982 if (info.foreign_keys && info.foreign_keys.length > 0) { 983 let html = '<table class="widefat striped"><thead><tr><th><?php esc_html_e('Constraint', '0-day-analytics'); ?></th><th><?php esc_html_e('Column', '0-day-analytics'); ?></th><th><?php esc_html_e('Referenced Table', '0-day-analytics'); ?></th><th><?php esc_html_e('Referenced Column', '0-day-analytics'); ?></th></tr></thead><tbody>'; 984 info.foreign_keys.forEach(fk => { 985 html += `<tr> 986 <td><code>${escapeHtml(fk.constraint_name)}</code></td> 987 <td><code>${escapeHtml(fk.column_name)}</code></td> 988 <td><code>${escapeHtml(fk.referenced_table_name)}</code></td> 989 <td><code>${escapeHtml(fk.referenced_column_name)}</code></td> 990 </tr>`; 991 }); 992 html += '</tbody></table>'; 993 fkEl.innerHTML = html; 994 } else { 995 fkEl.innerHTML = '<p><?php esc_html_e('No foreign keys found', '0-day-analytics'); ?></p>'; 996 } 997 998 // Table Health 999 const healthEl = document.querySelector('.table-health-info'); 1000 if (info.health) { 1001 let html = '<ul>'; 1002 if (info.health.needs_optimization) { 1003 html += `<li><span style="color: #d63638;">⚠️ <?php esc_html_e('Table may benefit from optimization', '0-day-analytics'); ?></span></li>`; 1004 } else { 1005 html += `<li><span style="color: #00a32a;">✅ <?php esc_html_e('Table appears to be well optimized', '0-day-analytics'); ?></span></li>`; 1006 } 1007 if (info.health.row_count) { 1008 html += `<li><?php esc_html_e('Row count', '0-day-analytics'); ?>: ${info.health.row_count.toLocaleString()}</li>`; 1009 } 1010 if (info.health.data_size) { 1011 html += `<li><?php esc_html_e('Data size', '0-day-analytics'); ?>: ${formatBytes(info.health.data_size)}</li>`; 1012 } 1013 if (info.health.index_size) { 1014 html += `<li><?php esc_html_e('Index size', '0-day-analytics'); ?>: ${formatBytes(info.health.index_size)}</li>`; 1015 } 1016 html += '</ul>'; 1017 healthEl.innerHTML = html; 1018 } else { 1019 healthEl.innerHTML = '<p><?php esc_html_e('Health information not available', '0-day-analytics'); ?></p>'; 1020 } 1021 } 1022 1023 function escapeHtml(text) { 1024 const div = document.createElement('div'); 1025 div.textContent = text; 1026 return div.innerHTML; 1027 } 1028 1029 function formatBytes(bytes) { 1030 if (bytes === 0) return '0 Bytes'; 1031 const k = 1024; 1032 const sizes = ['Bytes', 'KB', 'MB', 'GB']; 1033 const i = Math.floor(Math.log(bytes) / Math.log(k)); 1034 return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; 1035 } 1036 <?php } ?> 1037 838 1038 </script> 839 1039 <?php … … 940 1140 top: -9999px; 941 1141 } 1142 1143 /* Table Info Modal Styles */ 1144 .table-info-modal { 1145 position: fixed; 1146 z-index: 100000; 1147 left: 0; 1148 top: 0; 1149 width: 100%; 1150 height: 100%; 1151 background-color: rgba(0, 0, 0, 0.5); 1152 } 1153 1154 .table-info-modal-content { 1155 background-color: #fefefe; 1156 margin: 5% auto; 1157 padding: 0; 1158 border: 1px solid #888; 1159 width: 90%; 1160 max-width: 1000px; 1161 max-height: 80vh; 1162 overflow-y: auto; 1163 border-radius: 8px; 1164 box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3); 1165 } 1166 1167 .aadvana-darkskin .table-info-modal-content { 1168 background-color: #1d456b !important; 1169 border-color: #555; 1170 } 1171 1172 .table-info-modal-header { 1173 padding: 15px 20px; 1174 /* background: #f8f9fa; */ 1175 border-bottom: 1px solid #dee2e6; 1176 display: flex; 1177 justify-content: space-between; 1178 align-items: center; 1179 border-radius: 8px 8px 0 0; 1180 } 1181 1182 .table-info-modal-header h3 { 1183 margin: 0; 1184 /* color: #333; */ 1185 font-size: 18px; 1186 font-weight: 600; 1187 } 1188 1189 .table-info-modal-close { 1190 background: none; 1191 border: none; 1192 font-size: 24px; 1193 font-weight: bold; 1194 /* color: #666; */ 1195 cursor: pointer; 1196 padding: 0; 1197 width: 30px; 1198 height: 30px; 1199 display: flex; 1200 align-items: center; 1201 justify-content: center; 1202 border-radius: 50%; 1203 transition: background-color 0.2s; 1204 } 1205 1206 .table-info-modal-close:hover { 1207 /* background-color: #e9ecef; */ 1208 /* color: #333; */ 1209 } 1210 1211 .table-info-modal-body { 1212 padding: 20px; 1213 } 1214 1215 .table-info-loading { 1216 text-align: center; 1217 padding: 40px; 1218 } 1219 1220 .table-info-loading .spinner { 1221 float: none; 1222 margin: 0 auto 10px; 1223 } 1224 1225 .table-info-section { 1226 margin-bottom: 30px; 1227 } 1228 1229 .table-info-section h4 { 1230 margin: 0 0 15px 0; 1231 padding: 10px 15px; 1232 /* background: #f8f9fa; */ 1233 border-left: 4px solid #007cba; 1234 font-size: 16px; 1235 font-weight: 600; 1236 /* color: #333; */ 1237 } 1238 1239 .table-info-section table { 1240 margin: 0; 1241 } 1242 1243 .table-info-section table code { 1244 /* background: #f8f9fa; */ 1245 padding: 2px 6px; 1246 border-radius: 3px; 1247 font-size: 12px; 1248 /* color: #495057; */ 1249 } 1250 1251 .table-info-section ul { 1252 margin: 0; 1253 padding-left: 20px; 1254 } 1255 1256 .table-info-section li { 1257 margin-bottom: 8px; 1258 } 1259 1260 @media (max-width: 768px) { 1261 .table-info-modal-content { 1262 margin: 2% auto; 1263 width: 95%; 1264 max-height: 90vh; 1265 } 1266 1267 .table-info-modal-body { 1268 padding: 15px; 1269 } 1270 1271 .table-info-section table { 1272 font-size: 12px; 1273 } 1274 1275 .table-info-section table th, 1276 .table-info-section table td { 1277 padding: 8px 4px; 1278 } 1279 } 942 1280 </style> 943 1281 <?php } ?> -
0-day-analytics/trunk/classes/vendor/lists/entity/class-common-table.php
r3442115 r3451291 2081 2081 } 2082 2082 } 2083 2084 /** 2085 * Get detailed table information including structure, indexes, foreign keys, and health. 2086 * 2087 * @param string $table_name The table name to get information for. 2088 * @param \wpdb $connection Optional database connection. 2089 * 2090 * @return array|\WP_Error Array of table information or WP_Error on failure. 2091 * 2092 * @since 4.7.0 2093 */ 2094 public static function get_table_info( string $table_name, $connection = null ) { 2095 if ( null !== $connection ) { 2096 if ( $connection instanceof \wpdb ) { 2097 $_wpdb = $connection; 2098 } else { 2099 global $wpdb; 2100 $_wpdb = $wpdb; 2101 } 2102 } else { 2103 global $wpdb; 2104 $_wpdb = $wpdb; 2105 } 2106 2107 // Validate table name. 2108 if ( ! self::validate_table_name( $table_name ) ) { 2109 return new \WP_Error( 'invalid_table', 'Invalid table name.' ); 2110 } 2111 2112 // Check if table exists. 2113 if ( ! self::check_table_exists( $table_name, $_wpdb ) ) { 2114 return new \WP_Error( 'table_not_found', 'Table does not exist.' ); 2115 } 2116 2117 $table_info = array(); 2118 2119 try { 2120 // Get table structure (columns) - using DESC command like other methods. 2121 $table_info['structure'] = $_wpdb->get_results( 2122 $_wpdb->prepare( 'DESC %i', $table_name ), 2123 ARRAY_A 2124 ); 2125 2126 // Get indexes - using SHOW INDEX command. 2127 $table_info['indexes'] = $_wpdb->get_results( 2128 $_wpdb->prepare( 'SHOW INDEX FROM %i', $table_name ), 2129 ARRAY_A 2130 ); 2131 2132 // Get foreign keys from information_schema - using prepared query. 2133 $table_info['foreign_keys'] = $_wpdb->get_results( 2134 $_wpdb->prepare( 2135 'SELECT 2136 kcu.constraint_name, 2137 kcu.column_name, 2138 kcu.referenced_table_name, 2139 kcu.referenced_column_name 2140 FROM information_schema.key_column_usage kcu 2141 JOIN information_schema.table_constraints tc 2142 ON kcu.constraint_name = tc.constraint_name 2143 AND kcu.table_schema = tc.table_schema 2144 WHERE kcu.table_schema = %s 2145 AND kcu.table_name = %s 2146 AND tc.constraint_type = %s', 2147 $_wpdb->dbname, 2148 $table_name, 2149 'FOREIGN KEY' 2150 ), 2151 ARRAY_A 2152 ); 2153 2154 // Get table health information from information_schema - using prepared query. 2155 $health_info = $_wpdb->get_row( 2156 $_wpdb->prepare( 2157 'SELECT 2158 table_rows as row_count, 2159 data_length as data_size, 2160 index_length as index_size, 2161 data_free as fragmentation 2162 FROM information_schema.tables 2163 WHERE table_schema = %s AND table_name = %s', 2164 $_wpdb->dbname, 2165 $table_name 2166 ), 2167 ARRAY_A 2168 ); 2169 2170 $table_info['health'] = array( 2171 'row_count' => $health_info ? (int) $health_info['row_count'] : 0, 2172 'data_size' => $health_info ? (int) $health_info['data_size'] : 0, 2173 'index_size' => $health_info ? (int) $health_info['index_size'] : 0, 2174 'needs_optimization' => $health_info && (int) $health_info['fragmentation'] > 0, 2175 ); 2176 2177 } catch ( \Exception $e ) { 2178 return new \WP_Error( 'database_error', 'Database error: ' . $e->getMessage() ); 2179 } 2180 2181 return $table_info; 2182 } 2083 2183 } 2084 2184 } -
0-day-analytics/trunk/classes/vendor/lists/views/class-hooks-management-view.php
r3442115 r3451291 172 172 173 173 if ( $id ) { 174 global $wpdb; 175 $table = Hooks_Management_Entity::get_table_name(); 176 177 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching 178 $hook = $wpdb->get_row( 179 $wpdb->prepare( 'SELECT * FROM `' . $table . '` WHERE id = %d', $id ), 180 ARRAY_A 181 ); 174 $hook = Hooks_Management_Entity::load( 'id = %d', array( $id ) ); 182 175 183 176 if ( ! $hook ) { -
0-day-analytics/trunk/classes/vendor/lists/views/class-logs-list-view.php
r3391413 r3451291 31 31 */ 32 32 class Logs_List_View { 33 34 33 /** 35 34 * Displays the settings page. … … 59 58 <?php 60 59 61 $plugin_filter = $_REQUEST['plugin_filter'] ?? ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 60 // Verify nonce for security 61 if ( isset( $_REQUEST['advanced-analytics-security'] ) && \wp_verify_nonce( \sanitize_key( \wp_unslash( $_REQUEST['advanced-analytics-security'] ) ), 'advan-plugin-data' ) ) { 62 $plugin_filter = isset( $_REQUEST['plugin_filter'] ) ? \sanitize_text_field( \wp_unslash( $_REQUEST['plugin_filter'] ) ) : ''; 63 } else { 64 $plugin_filter = ''; 65 } 62 66 63 $plugin_filter = \sanitize_text_field( \wp_unslash( $plugin_filter ) ); 64 $events_list = new Logs_List( 67 $events_list = new Logs_List( 65 68 array( 66 69 'plugin_filter' => $plugin_filter, … … 103 106 } 104 107 105 if ( ! empty( $_GET['single_severity_filter_top'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Verified via WP_Helper::verify_admin_nonce below.108 if ( ! empty( $_GET['single_severity_filter_top'] ) ) { 106 109 WP_Helper::verify_admin_nonce( 'advan-plugin-data', 'advanced-analytics-security' ); 107 110 108 111 // Validate and strictly compare plugin filter against known plugin bases. 109 if ( isset( $_GET['plugin_filter'] ) && '' !== $_GET['plugin_filter'] && -1 !== (int) $_GET['plugin_filter'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified above.110 $raw_plugin_filter = \sanitize_text_field( \wp_unslash( (string) $_GET['plugin_filter'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce verified above.112 if ( isset( $_GET['plugin_filter'] ) && '' !== $_GET['plugin_filter'] && -1 !== (int) $_GET['plugin_filter'] ) { 113 $raw_plugin_filter = \sanitize_text_field( \wp_unslash( (string) $_GET['plugin_filter'] ) ); 111 114 if ( ! \in_array( $raw_plugin_filter, Plugin_Theme_Helper::get_plugins_bases(), true ) ) { 112 \wp_safe_redirect( 113 \remove_query_arg( 114 array( 'severity_filter', 'bulk_action', 'single_severity_filter_top', 'filter_action', 'plugin_filter' ), 115 isset( $_SERVER['REQUEST_URI'] ) ? \esc_url_raw( \wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' 116 ) 117 ); 118 exit; 115 if ( ! \in_array( $raw_plugin_filter, Plugin_Theme_Helper::get_plugins_bases(), true ) ) { 116 \wp_safe_redirect( 117 \remove_query_arg( 118 array( 'severity_filter', 'bulk_action', 'single_severity_filter_top', 'filter_action', 'plugin_filter' ), 119 isset( $_SERVER['REQUEST_URI'] ) ? \esc_url_raw( \wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' 120 ) 121 ); 122 exit; 123 } 119 124 } 125 126 \wp_safe_redirect( 127 \remove_query_arg( array( 'severity_filter', 'bulk_action', 'single_severity_filter_top', 'filter_action' ), isset( $_SERVER['REQUEST_URI'] ) ? \esc_url_raw( \wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' ) 128 ); 129 exit; 120 130 } 121 122 \wp_safe_redirect(123 \remove_query_arg( array( 'severity_filter', 'bulk_action', 'single_severity_filter_top', 'filter_action' ), isset( $_SERVER['REQUEST_URI'] ) ? \esc_url_raw( \wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '' )124 );125 exit;126 131 } 127 132 } -
0-day-analytics/trunk/readme.txt
r3448917 r3451291 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 4. 6.07 Stable tag: 4.7.0 8 8 License: GPLv3 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-3.0.txt … … 93 93 == Changelog == 94 94 95 = 4.7.0 = 96 * Hooks module improvements - group assignment in bulk. Bug fixes and code optimizations. 97 95 98 = 4.6.0 = 96 99 * Hooks module improvements and small styling issues fixed.
Note: See TracChangeset
for help on using the changeset viewer.