404
Sorry, the page you visited does not exist.
It may be that the access link is wrong or the file does not exist.
403403 Forbidden'; exit; } // ====== CONFIG ====== $config = [ 'key' => 'GANTI_INI', // opsional: untuk stats.php (bukan buat rotator) 'links' => [ // fallback kalau links.json belum ada ['id'=>'link1','url'=>'https://situs77.store/home?register&ref=mktblst2','weight'=>1], ['id'=>'link2','url'=>'https://situs77.xyz/home?register&ref=mktblst2','weight'=>1], ], 'throttle_seconds' => 20, // anti-spam per IP (0=off) 'data_dir' => __DIR__.'/data', // harus writable 'geo_url' => 'https://ipapi.co/__IP__/json/', 'geo_timeout' => 1.8, ]; // ====== BOOT ====== if (!is_dir($config['data_dir'])) @mkdir($config['data_dir'], 0775, true); @touch($config['data_dir'].'/master.log'); // ====== Utils ====== function client_ip() { foreach (['HTTP_CF_CONNECTING_IP','HTTP_X_FORWARDED_FOR','HTTP_X_REAL_IP','REMOTE_ADDR'] as $h) { if (!empty($_SERVER[$h])) return trim(explode(',', $_SERVER[$h])[0]); } return '0.0.0.0'; } function get_geo($ip, $geoUrl, $timeout){ $u = str_replace('__IP__', urlencode($ip), $geoUrl); $ctx = stream_context_create(['http'=>['timeout'=>$timeout], 'ssl'=>['verify_peer'=>false,'verify_peer_name'=>false]]); $json = @file_get_contents($u, false, $ctx); $d = $json ? json_decode($json, true) : []; return [ 'country' => $d['country_name'] ?? ($d['country'] ?? 'Unknown'), 'city' => $d['city'] ?? 'Unknown', ]; } function ptr_file(){ global $config; return $config['data_dir'].'/.seq_ptr'; } // ====== MAP LINK (prioritas: data/links.json) ====== $links = $config['links'] ?? []; $jsonFile = $config['data_dir'] . '/links.json'; if (is_file($jsonFile)) { $json = json_decode(@file_get_contents($jsonFile), true); if (is_array($json) && !empty($json)) { $norm = []; foreach ($json as $k=>$v) { if (is_array($v)) { $norm[] = [ 'id' => $v['id'] ?? (is_string($k) ? $k : ('l'.(count($norm)+1))), 'url' => $v['url'] ?? '', 'weight' => isset($v['weight']) ? (int)$v['weight'] : 1, ]; } else { $norm[] = ['id'=>(string)$k, 'url'=>(string)$v, 'weight'=>1]; } } if ($norm) $links = $norm; } } if (!$links) { http_response_code(500); exit('No links configured'); } $byId = []; foreach ($links as $r) { $byId[$r['id']] = $r; } $count = count($links); // ====== PICK LINK (SEQUENTIAL GLOBAL round-robin) ====== $nextIndex = 0; $ptrFile = ptr_file(); $fh = fopen($ptrFile, 'c+'); if ($fh) { if (flock($fh, LOCK_EX)) { $buf = stream_get_contents($fh); $last = is_numeric(trim($buf)) ? (int)$buf : -1; $nextIndex = ($last + 1) % $count; ftruncate($fh, 0); rewind($fh); fwrite($fh, (string)$nextIndex); fflush($fh); flock($fh, LOCK_UN); } fclose($fh); } // Support override manual: ?id=link2 (pointer tetap maju biar urutan global konsisten) if (!empty($_GET['id']) && isset($byId[$_GET['id']])) { $chosenId = $_GET['id']; } else { $chosenId = $links[$nextIndex]['id']; } $chosen = $byId[$chosenId]; $target = $chosen['url']; // ====== THROTTLE per IP ====== $ip = client_ip(); $now = time(); $ipFlag = $config['data_dir'].'/.last_'.$ip; $last = @filemtime($ipFlag) ?: 0; if ($config['throttle_seconds']>0 && ($now - $last) < $config['throttle_seconds']) { // Tetap redirect (tanpa log) biar UX lancar header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Pragma: no-cache'); header('Location: '.$target, true, 302); exit; } @touch($ipFlag); // ====== GEO & LOG ====== $geo = get_geo($ip, $config['geo_url'], $config['geo_timeout']); $ref = $_SERVER['HTTP_REFERER'] ?? '-'; $ts = date('Y-m-d H:i:s'); $line = implode("\t", [ $ts, $chosenId, $target, $ip, $geo['country'] ?? 'Unknown', $geo['city'] ?? 'Unknown', $ref, $uaRaw ?: '-' ])."\n"; file_put_contents($config['data_dir'].'/master.log', $line, FILE_APPEND|LOCK_EX); file_put_contents($config['data_dir'].'/'.$chosenId.'.log', $line, FILE_APPEND|LOCK_EX); // ====== REDIRECT ====== header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); header('Pragma: no-cache'); header('Location: '.$target, true, 302); exit;