129 lines
3.7 KiB
PHP
Executable File
129 lines
3.7 KiB
PHP
Executable File
<?php
|
||
/**
|
||
* MySQL 辅助(PHP 8 兼容:禁止向 mysqli 传入 null)
|
||
*/
|
||
|
||
if (!function_exists('cloak_db_string')) {
|
||
/**
|
||
* 将任意值转为可写入 SQL 的字符串(null → 空串)
|
||
*
|
||
* @param mixed $value
|
||
*/
|
||
function cloak_db_string($value): string
|
||
{
|
||
if ($value === null) {
|
||
return '';
|
||
}
|
||
return (string) $value;
|
||
}
|
||
}
|
||
|
||
if (!function_exists('cloak_db_escape')) {
|
||
/**
|
||
* @param mysqli $conn
|
||
* @param mixed $value
|
||
*/
|
||
function cloak_db_escape(mysqli $conn, $value): string
|
||
{
|
||
return mysqli_real_escape_string($conn, cloak_db_string($value));
|
||
}
|
||
}
|
||
|
||
if (!function_exists('cloak_visitor_log_format_timing')) {
|
||
/**
|
||
* @param mixed $raw JSON 或已格式化的摘要
|
||
*/
|
||
function cloak_visitor_log_format_timing($raw)
|
||
{
|
||
$raw = trim((string) $raw);
|
||
if ($raw === '') {
|
||
return '';
|
||
}
|
||
if (!class_exists('CloakPipelineTimer', false)) {
|
||
require_once __DIR__ . '/Cloak/PipelineTimer.php';
|
||
}
|
||
$decoded = json_decode($raw, true);
|
||
if (is_array($decoded)) {
|
||
return CloakPipelineTimer::formatText($decoded);
|
||
}
|
||
return $raw;
|
||
}
|
||
}
|
||
|
||
if (!function_exists('cloak_visitor_log_format_fp_hdata')) {
|
||
/**
|
||
* 指纹 hdata JSON 单行摘要(表格展示用)
|
||
*
|
||
* @param mixed $raw
|
||
*/
|
||
function cloak_visitor_log_format_fp_hdata($raw)
|
||
{
|
||
$raw = trim((string) $raw);
|
||
if ($raw === '') {
|
||
return '';
|
||
}
|
||
$decoded = json_decode($raw, true);
|
||
if (!is_array($decoded)) {
|
||
return $raw;
|
||
}
|
||
$parts = [];
|
||
foreach (['domain', 'ip', 'ciso', 'referer', 'log_id', 'risk_enhanced'] as $key) {
|
||
if (!empty($decoded[$key])) {
|
||
$parts[] = $key . '=' . $decoded[$key];
|
||
}
|
||
}
|
||
if (!empty($decoded['automation']) && is_array($decoded['automation'])) {
|
||
$auto = [];
|
||
foreach ($decoded['automation'] as $k => $v) {
|
||
if ($v) {
|
||
$auto[] = $k;
|
||
}
|
||
}
|
||
if ($auto !== []) {
|
||
$parts[] = 'automation=' . implode(',', $auto);
|
||
}
|
||
}
|
||
if ($parts !== []) {
|
||
return implode(' | ', $parts);
|
||
}
|
||
return json_encode($decoded, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||
}
|
||
}
|
||
|
||
if (!function_exists('cloak_visitor_log_fp_risk_explain')) {
|
||
/**
|
||
* 二次风控 hdata + reason 判定过程解析
|
||
*
|
||
* @return array{summary:string,html:string,data:array}
|
||
*/
|
||
function cloak_visitor_log_fp_risk_explain($fpHdata, $reason, $result, $domain = '')
|
||
{
|
||
if (!class_exists('FpRiskExplain', false)) {
|
||
require_once __DIR__ . '/Cloak/FpRiskExplain.php';
|
||
}
|
||
return FpRiskExplain::build($fpHdata, $reason, $result, $domain);
|
||
}
|
||
}
|
||
|
||
if (!function_exists('cloak_visitor_log_apply_result_filter')) {
|
||
/**
|
||
* 日志列表 result 筛选:默认显示全部(含 wait/检测中);显式筛选时精确匹配
|
||
*
|
||
* @return string SQL 片段(含前导 AND)
|
||
*/
|
||
function cloak_visitor_log_apply_result_filter(mysqli $conn, $resultParam): string
|
||
{
|
||
$resultParam = trim((string) $resultParam);
|
||
if ($resultParam === '') {
|
||
return '';
|
||
}
|
||
if ($resultParam === 'wait' || $resultParam === '检测中') {
|
||
return " AND `result` = 'wait'";
|
||
}
|
||
if ($resultParam === 'true' || $resultParam === 'false') {
|
||
return " AND `result` = '" . cloak_db_escape($conn, $resultParam) . "'";
|
||
}
|
||
return '';
|
||
}
|
||
}
|