connect_error) { return []; } $out = []; $sql = 'SELECT ip_address FROM ip_list WHERE group_id = ' . $groupId; if ($res = $conn->query($sql)) { while ($row = $res->fetch_assoc()) { $out[] = $row['ip_address']; } $res->free(); } $conn->close(); return $out; } } if (!function_exists('ip_visitor_matches_list_entry')) { function ip_visitor_matches_list_entry($visitorIp, $entry) { $entry = trim($entry); if ($entry === '') { return false; } if ($visitorIp === $entry) { return true; } if (mb_substr($entry, -1) === '*') { return strpos($visitorIp, rtrim($entry, '*')) === 0; } return false; } } if (!function_exists('ip_visitor_in_blacklist_entries')) { function ip_visitor_in_blacklist_entries($visitorIp, array $entries) { foreach ($entries as $buffer) { if (ip_visitor_matches_list_entry($visitorIp, $buffer)) { return true; } } return false; } } if (!function_exists('cloak_visitor_log_request_meta')) { function cloak_visitor_log_request_meta() { return [ 'user_agent' => get_SERVER_value('HTTP_USER_AGENT'), 'http_referer' => get_SERVER_value('HTTP_REFERER'), 'accept_language_raw' => get_SERVER_value('HTTP_ACCEPT_LANGUAGE'), ]; } } if (!function_exists('cloak_visitor_log_enrich')) { function cloak_visitor_log_enrich(array $logs) { $meta = cloak_visitor_log_request_meta(); foreach ($meta as $key => $value) { if (!array_key_exists($key, $logs) || $logs[$key] === null || $logs[$key] === '') { $logs[$key] = $value; } } if (empty($logs['judge_timing']) && !empty($GLOBALS['__cloak_judge_timing'])) { $logs['judge_timing'] = $GLOBALS['__cloak_judge_timing']; } return VisitorApiAudit::mergeIntoLogs($logs); } } if (!function_exists('cloak_visitor_log_async_enabled')) { function cloak_visitor_log_async_enabled() { return defined('VISITOR_LOG_ASYNC') && strtoupper(VISITOR_LOG_ASYNC) === 'ON'; } } if (!function_exists('cloak_visitor_log_register_shutdown_drain')) { function cloak_visitor_log_register_shutdown_drain() { static $registered = false; if ($registered || !cloak_visitor_log_async_enabled()) { return; } $registered = true; register_shutdown_function(static function () { if (function_exists('fastcgi_finish_request')) { @fastcgi_finish_request(); } VisitorLogQueue::drain(5); }); } } if (!function_exists('cloak_write_log_db_sync')) { function cloak_write_log_db_sync($logs) { return VisitorLogWorker::insertFull($logs); } } if (!function_exists('cloak_write_log_db')) { function cloak_write_log_db($logs) { $logs = cloak_visitor_log_enrich($logs); if (!empty($GLOBALS['__cloak_force_sync_log'])) { if (($logs['result'] ?? '') === 'wait') { $logId = VisitorLogWorker::insertMinimal($logs); if ($logId !== null) { VisitorLogWorker::enrich($logId, $logs); } return $logId; } return cloak_write_log_db_sync($logs); } if (defined('WRITE_LOG') && WRITE_LOG == '1') { $my_url = $_SERVER['PHP_SELF'] ?? ''; $my_file_name = substr($my_url, strrpos($my_url, '/') + 1); $config_name = str_replace('.php', '', $my_file_name); $fp = fopen(dirname(__DIR__, 2) . '/jump.txt', 'a+'); fwrite($fp, date('Y-m-d H:i:s') . ' | 写入数据库 ' . ' | ' . ($_SESSION['check_result'] ?? '') . ' | ' . $config_name . ' | async=' . (cloak_visitor_log_async_enabled() ? '1' : '0') . "\n"); fclose($fp); } $result = isset($logs['result']) ? (string) $logs['result'] : ''; // 二次风控 wait:同步最小 INSERT 获取 log_id,TEXT 字段异步 enrich if ($result === 'wait') { $logId = VisitorLogWorker::insertMinimal($logs); if ($logId === null) { return cloak_write_log_db_sync($logs); } if (cloak_visitor_log_async_enabled()) { VisitorLogQueue::push([ 'type' => 'enrich', 'log_id' => $logId, 'logs' => $logs, ]); } else { VisitorLogWorker::enrich($logId, $logs); } return $logId; } if (!cloak_visitor_log_async_enabled()) { $conn = new mysqli('localhost', DB_USERNAME, DB_PASSWORD, DB_NAME); if ($conn->connect_error) { $error = 'Connection failed: ' . $conn->connect_error; $handle = fopen(dirname(__DIR__, 2) . '/err.txt', 'a+'); fwrite($handle, date('Y-m-d H:i:s') . ' | ' . $error . "\n"); fclose($handle); return null; } VisitorLogSchema::ensureColumns($conn); VisitorLogSchema::ensureIndexes($conn); $logs = VisitorLogVtimes::mergeIntoLogs($logs, $conn); $data = []; foreach ($logs as $key => $value) { $data[$key] = cloak_db_escape($conn, $value); } $d = static function ($key) use ($data, $conn) { return array_key_exists($key, $data) ? $data[$key] : cloak_db_escape($conn, ''); }; $simCols = ''; $simVals = ''; if (!empty($data['is_simulation']) || array_key_exists('sim_source_log_id', $data)) { $simCols = ', `is_simulation`, `sim_source_log_id`'; $isSim = (int) ($data['is_simulation'] ?? 0); if (!empty($data['sim_source_log_id'])) { $simVals = ", '{$isSim}', '" . (int) $data['sim_source_log_id'] . "'"; } else { $simVals = ", '{$isSim}', NULL"; } } $sql = "INSERT INTO `visitor_logs`(`campagin_id`, `visit_md5_code`, `domain`, `visit_date`, `IP`, `country`, `result`, `reason`, `referer`, `vtimes`, `client`, `browser`, `page`, `language`, `user_agent`, `http_referer`, `accept_language_raw`, `judge_timing`, `fp_url`, `device`, `api_by_request`, `api_by_response`, `api_risk_request`, `api_risk_response`{$simCols}) VALUES ('" . $d('campagin_id') . "','" . $d('visit_md5_code') . "','" . $d('site_name') . "','" . date('Y-m-d H:i:s') . "','" . $d('customers_ip') . "','" . $d('country') . "','" . $d('result') . "','" . $d('reason') . "','" . $d('v_referer') . "','" . (int) ($data['vtimes'] ?? 1) . "','" . $d('Client') . "','" . $d('v_Browser') . "','" . $d('v_PageURL') . "','" . $d('accept_language') . "','" . $d('user_agent') . "','" . $d('http_referer') . "','" . $d('accept_language_raw') . "','" . $d('judge_timing') . "','" . $d('fp_url') . "','" . $d('device') . "','" . $d('api_by_request') . "','" . $d('api_by_response') . "','" . $d('api_risk_request') . "','" . $d('api_risk_response') . "'" . $simVals . ')'; if ($conn->query($sql) === true) { $last_id = $conn->insert_id; $conn->close(); return $last_id; } $handle = fopen(dirname(__DIR__, 2) . '/err.txt', 'a+'); fwrite($handle, date('Y-m-d H:i:s') . ' | ' . 'Error: ' . $sql . '
' . $conn->error . "\n"); fclose($handle); $conn->close(); return null; } if (!VisitorLogQueue::push(['type' => 'insert_full', 'logs' => $logs])) { return cloak_write_log_db_sync($logs); } cloak_visitor_log_register_shutdown_drain(); return null; } } if (!function_exists('write_log_db')) { function write_log_db($logs) { return cloak_write_log_db($logs); } } if (!function_exists('cloak_howmanytimesbyip')) { function cloak_howmanytimesbyip($ip) { $row = ['total' => 0]; $conn = new mysqli('localhost', DB_USERNAME, DB_PASSWORD, DB_NAME); if ($conn->connect_error) { $handle = fopen(dirname(__DIR__, 2) . '/err.txt', 'a+'); fwrite($handle, date('Y-m-d H:i:s') . ' | Connection failed: ' . $conn->connect_error . "\n"); fclose($handle); return 0; } $ipEsc = cloak_db_escape($conn, $ip); $sql = "SELECT count(*) as `total` FROM `visitor_logs` WHERE `IP`='" . $ipEsc . "'"; if ($conn->query($sql) == true) { $result = $conn->query($sql); $row = $result->fetch_array(); $conn->close(); } else { $handle = fopen(dirname(__DIR__, 2) . '/err.txt', 'a+'); fwrite($handle, date('Y-m-d H:i:s') . ' | Error: ' . $sql . '
' . $conn->error . "\n"); fclose($handle); $conn->close(); return 0; } return $row['total']; } } if (!function_exists('howmanytimesbyip')) { function howmanytimesbyip($ip) { return cloak_howmanytimesbyip($ip); } } if (!function_exists('cloak_write_black_list')) { function cloak_write_black_list($ip) { if (!defined('BLACKLIST_GROUP_ID') || (int) BLACKLIST_GROUP_ID <= 0) { return; } $gid = (int) BLACKLIST_GROUP_ID; $conn = @new mysqli('localhost', DB_USERNAME, DB_PASSWORD, DB_NAME); if ($conn->connect_error) { return; } $stmt = $conn->prepare('INSERT IGNORE INTO ip_list (group_id, ip_address) VALUES (?, ?)'); if ($stmt) { $stmt->bind_param('is', $gid, $ip); $stmt->execute(); $stmt->close(); } $conn->close(); } } if (!function_exists('write_black_list')) { function write_black_list($ip) { cloak_write_black_list($ip); } } if (!function_exists('browser_headers')) { function browser_headers() { $headers = []; foreach ($_SERVER as $name => $value) { if (preg_match('/^HTTP_/', $name)) { $name = strtolower(strtr(substr($name, 5), '_', '-')); $headers[$name] = $value; } } return $headers; } } if (!function_exists('accept_lang_zh')) { function accept_lang_zh() { if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { return false; } $lang = substr((string) $_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 4); if (preg_match('/zh-c/i', $lang) or preg_match('/zh/i', $lang)) { return true; } return false; } } if (!function_exists('is_https')) { function is_https() { return cloak_request_is_https(); } }