'warning', 'message' => __('Git Code Viewer: Wordfence detected. Please ensure the following URLs are whitelisted in Wordfence settings: api.github.com, gitlab.com, api.bitbucket.org, codeberg.org', 'maple-code-blocks'), 'dismissible' => true ); } // WooCommerce compatibility (informational) if (class_exists('WooCommerce')) { // No issues, just log for debugging error_log('GCV: WooCommerce detected - compatibility mode active'); } // LearnDash compatibility (informational) if (defined('LEARNDASH_VERSION')) { // No issues, just log for debugging error_log('GCV: LearnDash detected - compatibility mode active'); } // Memory limit warning $memory_limit = ini_get('memory_limit'); if ($memory_limit && self::convert_to_bytes($memory_limit) < 67108864) { // 64MB $notices[] = array( 'type' => 'warning', 'message' => __('Git Code Viewer: Low memory limit detected. Consider increasing memory_limit to at least 64MB for optimal performance.', 'maple-code-blocks'), 'dismissible' => true ); } // Display notices foreach ($notices as $notice) { $dismissible = $notice['dismissible'] ? 'is-dismissible' : ''; printf( '

%s

', esc_attr($notice['type']), esc_attr($dismissible), esc_html($notice['message']) ); } } /** * Optimize plugin loading */ public static function optimize_loading() { // Hook into admin_init for screen-specific optimizations if (is_admin()) { add_action('admin_init', function() { // Check screen only after it's available add_action('current_screen', function($screen) { if ($screen && $screen->id !== 'settings_page_maple-code-blocks') { remove_action('admin_enqueue_scripts', array('Maple_Code_Blocks', 'enqueue_scripts')); } }); }); } // Optimize transient cleanup if (!wp_next_scheduled('mcb_cleanup_transients')) { wp_schedule_event(time(), 'daily', 'mcb_cleanup_transients'); } add_action('mcb_cleanup_transients', function() { global $wpdb; // Use WordPress function instead of direct query if (function_exists('delete_expired_transients')) { delete_expired_transients(); } else { // Fallback for older WordPress versions $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_mcb_%' AND option_value < UNIX_TIMESTAMP()" ); } }); } /** * Helper: Check if IP is in range */ private static function ip_in_range($ip, $range) { if (strpos($range, '/') === false) { $range .= '/32'; } list($subnet, $bits) = explode('/', $range); // IPv4 if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) && filter_var($subnet, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { $ip = ip2long($ip); $subnet = ip2long($subnet); $mask = -1 << (32 - $bits); $subnet &= $mask; return ($ip & $mask) == $subnet; } // IPv6 if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) && filter_var($subnet, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $ip_bin = inet_pton($ip); $subnet_bin = inet_pton($subnet); $bytes = $bits / 8; $remainder = $bits % 8; if ($bytes > 0) { if (substr($ip_bin, 0, $bytes) !== substr($subnet_bin, 0, $bytes)) { return false; } } if ($remainder > 0 && $bytes < 16) { $mask = 0xFF << (8 - $remainder); $ip_byte = ord($ip_bin[$bytes]); $subnet_byte = ord($subnet_bin[$bytes]); if (($ip_byte & $mask) !== ($subnet_byte & $mask)) { return false; } } return true; } return false; } /** * Helper: Convert memory string to bytes */ private static function convert_to_bytes($val) { $val = trim($val); $last = strtolower($val[strlen($val)-1]); $val = (int)$val; switch($last) { case 'g': $val *= 1024; case 'm': $val *= 1024; case 'k': $val *= 1024; } return $val; } } // Initialize security fixes add_action('plugins_loaded', array('MCB_Security_Fixes', 'init'), 5); add_action('rest_api_init', function() { register_rest_route('maple-code-blocks/v1', '/health', array( 'methods' => 'GET', 'callback' => function() { $health = array( 'status' => 'healthy', 'version' => '2.0.0', 'php_version' => PHP_VERSION, 'wordpress_version' => get_bloginfo('version'), 'memory_usage' => memory_get_usage(true), 'memory_limit' => ini_get('memory_limit'), 'wordfence_active' => defined('WORDFENCE_VERSION'), 'woocommerce_active' => class_exists('WooCommerce'), 'learndash_active' => defined('LEARNDASH_VERSION'), 'cache_size' => count(get_transient('mcb_security_logs') ?: array()), 'rate_limit_active' => !defined('WORDFENCE_VERSION') ); return new WP_REST_Response($health, 200); }, 'permission_callback' => function() { return current_user_can('manage_options'); } )); });