$comment_line) { if ($idx === 0 && $current_line !== '') { // First line of comment - complete current line $lines[] = $current_line; $current_line = ''; } elseif ($idx > 0) { // Additional comment lines $lines[] = ''; } } } else { // Add non-comment content $content_parts = explode("\n", $token_content); foreach ($content_parts as $idx => $part) { if ($idx > 0) { $lines[] = $current_line; $current_line = $part; } else { $current_line .= $part; } } } } else { // Single character tokens $current_line .= $token; } } // Add the last line if any if ($current_line !== '' || count($lines) === 0) { $lines[] = $current_line; } $sanitized_content = implode("\n", $lines); return [ 'content' => $sanitized_content, 'lines' => $lines, 'original_lines' => explode("\n", $content), ]; } /** * Get sanitized JavaScript content for checking * Removes comments and string contents to avoid false positives * Uses external Node.js script (from line 769 of monolith) */ public static function sanitize_javascript(string $file_path): array { // Create cache directory if it doesn't exist if (function_exists('storage_path')) { $cache_dir = storage_path('rsx-tmp/cache/js-sanitized'); } else { $cache_dir = '/var/www/html/storage/rsx-tmp/cache/js-sanitized'; } if (!is_dir($cache_dir)) { mkdir($cache_dir, 0755, true); } // Generate cache path based on relative file path $base_path = function_exists('base_path') ? base_path() : '/var/www/html'; $relative_path = str_replace($base_path . '/', '', $file_path); $cache_path = $cache_dir . '/' . str_replace('/', '_', $relative_path) . '.sanitized'; // Check if cache is valid if (file_exists($cache_path)) { $source_mtime = filemtime($file_path); $cache_mtime = filemtime($cache_path); if ($cache_mtime >= $source_mtime) { // Cache is valid, return cached content $sanitized_content = file_get_contents($cache_path); return [ 'content' => $sanitized_content, 'lines' => explode("\n", $sanitized_content), 'original_lines' => explode("\n", file_get_contents($file_path)), ]; } } // Run sanitizer to generate fresh cache $sanitizer_path = $base_path . '/bin/js-sanitizer.js'; $command = sprintf('node %s %s 2>/dev/null', escapeshellarg($sanitizer_path), escapeshellarg($file_path) ); $sanitized = shell_exec($command); // If sanitization failed, fall back to original content if ($sanitized === null || $sanitized === '') { $sanitized = file_get_contents($file_path); } // Save to cache file_put_contents($cache_path, $sanitized); return [ 'content' => $sanitized, 'lines' => explode("\n", $sanitized), 'original_lines' => explode("\n", file_get_contents($file_path)), ]; } /** * Sanitize file based on extension * Note: PHP takes content, JavaScript takes file_path (matching monolith behavior) */ public static function sanitize(string $file_path, ?string $content = null): array { $extension = pathinfo($file_path, PATHINFO_EXTENSION); if ($extension === 'php') { if ($content === null) { $content = file_get_contents($file_path); } return self::sanitize_php($content); } elseif (in_array($extension, ['js', 'jsx', 'ts', 'tsx'])) { // JavaScript sanitization needs file path, not content return self::sanitize_javascript($file_path); } else { // For other files, return as-is if ($content === null) { $content = file_get_contents($file_path); } return [ 'content' => $content, 'lines' => explode("\n", $content), 'original_lines' => explode("\n", $content), ]; } } }