    <?php
    /**
     * Güvenli WordPress Dosya Kilitleyici (Geliştirilmiş)
     *
     * LOCK modunda:
     * - Dosyalar: 0444 (değiştirilemez)
     * - Klasörler: 0555 (yazılamaz -> upload / delete / rename durur)
     * - WP içinden upload/silme: MU-Plugin ile ayrıca engellenir
     *
     * UNLOCK modunda:
     * - Dosyalar: 0644
     * - Klasörler: 0755
     * - MU-Plugin kaldırılır
     *
     * Kullanım:
     *   Web: file-lock.php?action=lock&pass=SENIN_SIFREN
     *   Web: file-lock.php?action=unlock&pass=SENIN_SIFREN
     *   CLI: php file-lock.php lock SENIN_SIFREN
     *   CLI: php file-lock.php unlock SENIN_SIFREN
     */

    // "arsene" için SHA-256 hash
    const PASSWORD_HASH = '9349097f960bfb8a44586a39c5143f0077738b709fecd030816407cb663e147d';

    // İstersen IP kısıtı ekleyebilirsin; boş ise tüm IP'ler (şifre doğruysa) kullanabilir
    $allowedIps = [
        // '1.2.3.4',
    ];

    // İZİN MODLARI
    $LOCK_FILE_MODE     = 0444;
    $UNLOCK_FILE_MODE   = 0644;

    $LOCK_DIR_MODE      = 0555; // kritik: upload/silme/rename'ı durdurur
    $UNLOCK_DIR_MODE    = 0755;

    // WordPress kök dizini (bu dosyanın bulunduğu dizin)
    $baseDir = __DIR__;

    /**
     * Asla dokunulmaması gereken klasörler
     * (hem lock hem unlock sırasında atlanır)
     */
    $excludePaths = [
        $baseDir . DIRECTORY_SEPARATOR . 'cgi-bin',
        $baseDir . DIRECTORY_SEPARATOR . '.git',
    ];

    /**
     * Lock modunda WP içi upload/silme blok MU-plugin yolu
     */
    $lockdownPlugin = $baseDir
        . DIRECTORY_SEPARATOR . 'wp-content'
        . DIRECTORY_SEPARATOR . 'mu-plugins'
        . DIRECTORY_SEPARATOR . 'file-lockdown.php';

    /**
     * İstemci IP'sini getir
     */
    function getClientIp(): string
    {
        if (PHP_SAPI === 'cli') return 'CLI';

        if (!empty($_SERVER['HTTP_CLIENT_IP'])) return $_SERVER['HTTP_CLIENT_IP'];

        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $parts = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            return trim($parts[0]);
        }

        return $_SERVER['REMOTE_ADDR'] ?? 'UNKNOWN';
    }

    /**
     * IP izinli mi kontrol et
     */
    function isIpAllowed(string $ip, array $allowedIps): bool
    {
        if (empty($allowedIps)) return true;
        if ($ip === 'CLI') return true;
        return in_array($ip, $allowedIps, true);
    }

    /**
     * Gönderilen şifre doğru mu? (HASH kontrollü)
     */
    function isPasswordValid(?string $input): bool
    {
        if ($input === null || $input === '') return false;
        $hash = hash('sha256', $input);
        return hash_equals(PASSWORD_HASH, $hash);
    }

    /**
     * Path exclude mu?
     */
    function isExcludedPath(string $path, array $excludePaths): bool
    {
        foreach ($excludePaths as $excluded) {
            if ($excluded && strpos($path, $excluded) === 0) {
                return true;
            }
        }
        return false;
    }

    function ensureDir(string $dir, array &$stats): bool
    {
        if (is_dir($dir)) return true;
        if (@mkdir($dir, 0755, true)) return true;
        $stats['dirs_fail'][] = $dir . ' (mkdir başarısız)';
        return false;
    }

    function writeLockdownMuPlugin(string $pluginPath, array &$stats): void
    {
        $muDir = dirname($pluginPath);
        if (!ensureDir($muDir, $stats)) return;

        $code = <<<'PHP'
    <?php
    /**
     * FILE LOCKDOWN (MU-Plugin)
     * - Upload (admin + REST + classic handlers) engeller
     * - Attachment silme engeller
     * - Tema/eklenti/dosya düzenleme & güncellemeleri engeller
     */
    if (!defined('ABSPATH')) { exit; }

    if (!defined('DISALLOW_FILE_MODS')) define('DISALLOW_FILE_MODS', true);
    if (!defined('DISALLOW_FILE_EDIT')) define('DISALLOW_FILE_EDIT', true);

    add_filter('wp_handle_upload_prefilter', function ($file) {
        return new WP_Error('file_lockdown_upload_blocked', 'Lock modu aktif: dosya yükleme kapalı.');
    }, 9999);

    add_filter('pre_handle_upload', function ($file) {
        return new WP_Error('file_lockdown_upload_blocked', 'Lock modu aktif: dosya yükleme kapalı.');
    }, 9999);

    add_filter('rest_pre_dispatch', function ($result, $server, $request) {
        $route  = (string) $request->get_route();
        $method = (string) $request->get_method();
        if ($method === 'POST' && strpos($route, '/wp/v2/media') !== false) {
            return new WP_Error('file_lockdown_rest_upload_blocked', 'Lock modu aktif: medya yükleme kapalı.', ['status' => 403]);
        }
        return $result;
    }, 9999, 3);

    add_filter('pre_delete_attachment', function ($delete, $post, $force_delete) {
        return false;
    }, 9999, 3);

    add_action('admin_init', function () {
        $script = $_SERVER['SCRIPT_NAME'] ?? '';
        if (stripos($script, 'async-upload.php') !== false) {
            wp_die('Lock modu aktif: dosya yükleme kapalı.', 403);
        }
    }, 1);

    add_filter('file_mod_allowed', '__return_false', 9999);
    PHP;

        if (@file_put_contents($pluginPath, $code, LOCK_EX) !== false) {
            $stats['lockdown_written'] = $pluginPath;
        } else {
            $stats['files_fail'][] = $pluginPath . ' (file_put_contents başarısız)';
        }
    }

    function removeLockdownMuPlugin(string $pluginPath, array &$stats): void
    {
        if (is_file($pluginPath)) {
            if (@unlink($pluginPath)) {
                $stats['lockdown_removed'] = $pluginPath;
            } else {
                $stats['files_fail'][] = $pluginPath . ' (unlink başarısız)';
            }
        }
    }

    /**
     * Recursive chmod:
     * - Dosyalara $fileMode uygular
     * - Klasörlere $dirMode uygular  (LOCK'ta 0555 -> upload/silme biter)
     * - Symlink dokunmaz
     * - Exclude yollar atlanır
     */
    function recursiveChmod(string $path, int $fileMode, int $dirMode, array $excludePaths, array &$stats): void
    {
        if (is_link($path)) return;
        if (isExcludedPath($path, $excludePaths)) return;

        if (is_dir($path)) {
            // önce çocukları işle (aksi halde bazı hostinglerde erişim kesilebilir)
            $items = @scandir($path);
            if ($items === false) {
                $stats['dirs_fail'][] = $path . ' (scandir başarısız)';
                return;
            }

            foreach ($items as $item) {
                if ($item === '.' || $item === '..') continue;
                $full = $path . DIRECTORY_SEPARATOR . $item;
                recursiveChmod($full, $fileMode, $dirMode, $excludePaths, $stats);
            }

            // sonra klasör iznini uygula
            if (@chmod($path, $dirMode)) {
                $stats['dirs_ok']++;
            } else {
                $stats['dirs_fail'][] = $path;
            }

        } elseif (is_file($path)) {
            if (@chmod($path, $fileMode)) {
                $stats['files_ok']++;
            } else {
                $stats['files_fail'][] = $path;
            }
        }
    }

    //////////////////////////////////////
    // ACTION & PARAMETRELER
    //////////////////////////////////////

    $isCli    = (PHP_SAPI === 'cli');
    $clientIp = getClientIp();

    if ($isCli) {
        $action = $argv[1] ?? null;
        $pass   = $argv[2] ?? null;
    } else {
        $action = $_GET['action'] ?? $_POST['action'] ?? null;
        $pass   = $_GET['pass']   ?? $_POST['pass']   ?? null;
        header('Content-Type: text/plain; charset=UTF-8');
    }

    // IP kontrolü
    if (!isIpAllowed($clientIp, $allowedIps)) {
        echo "Erişim reddedildi: IP yetkisiz.\n";
        echo "IP adresiniz: {$clientIp}\n";
        exit;
    }

    // Parametre ve şifre kontrolü
    if (!$action) {
        echo "Eksik parametre: action gerekli (lock/unlock).\n";
        exit;
    }

    if (!isPasswordValid($pass)) {
        echo "Yetkisiz erişim: şifre hatalı veya eksik.\n";
        exit;
    }

    $action = strtolower($action);
    if (!in_array($action, ['lock', 'unlock'], true)) {
        echo "Geçersiz action. 'lock' veya 'unlock' kullanın.\n";
        exit;
    }

    if ($action === 'lock') {
        $targetFileMode = $LOCK_FILE_MODE;
        $targetDirMode  = $LOCK_DIR_MODE;
    } else {
        $targetFileMode = $UNLOCK_FILE_MODE;
        $targetDirMode  = $UNLOCK_DIR_MODE;
    }

    set_time_limit(0);

    //////////////////////////////////////
    // ÇALIŞTIR
    //////////////////////////////////////

    $stats = [
        'files_ok'   => 0,
        'dirs_ok'    => 0,
        'files_fail' => [],
        'dirs_fail'  => [],
    ];

    $start = microtime(true);

    // LOCK ise MU-plugin yaz (WP içinden upload/silme de kapansın)
    if ($action === 'lock') {
        writeLockdownMuPlugin($lockdownPlugin, $stats);
    } else {
        removeLockdownMuPlugin($lockdownPlugin, $stats);
    }

    // Asıl izin güncelleme (dosya + klasör)
    recursiveChmod($baseDir, $targetFileMode, $targetDirMode, $excludePaths, $stats);

    $elapsed = round(microtime(true) - $start, 2);

    echo "İşlem tamamlandı.\n";
    echo "Kök dizin   : {$baseDir}\n";
    echo "IP          : {$clientIp}\n";
    echo "Action      : {$action}\n";
    echo "Dosya modu  : " . decoct($targetFileMode) . "\n";
    echo "Klasör modu : " . decoct($targetDirMode) . "\n\n";

    if (!empty($stats['lockdown_written'])) {
        echo "Lockdown MU-Plugin yazıldı : {$stats['lockdown_written']}\n";
    }
    if (!empty($stats['lockdown_removed'])) {
        echo "Lockdown MU-Plugin silindi : {$stats['lockdown_removed']}\n";
    }
    echo "\n";

    echo "Başarılı dosya sayısı   : {$stats['files_ok']}\n";
    echo "Başarılı klasör sayısı  : {$stats['dirs_ok']}\n";
    echo "Süre                    : {$elapsed} sn\n\n";

    if (!empty($stats['files_fail']) || !empty($stats['dirs_fail'])) {
        echo "İzin verilemeyen öğeler:\n";
        foreach ($stats['files_fail'] as $f) echo "  [FILE] $f\n";
        foreach ($stats['dirs_fail'] as $d) echo "  [DIR ] $d\n";
    } else {
        echo "Tüm dosya ve klasör izinleri başarıyla güncellendi.\n";
    }
