diff --git a/dashboard.php b/dashboard.php
index 9317a1f..b011596 100755
--- a/dashboard.php
+++ b/dashboard.php
@@ -1,6 +1,7 @@
alert('已开启国家条件,请填写允许的国家代码(如 US,GB,CA)。');history.back();";
+ exit();
+ }
+
if (!empty($methods)) {
ConfigWriter::save($check_name, [
'methods' => $methods,
@@ -889,9 +897,26 @@ $_d = function($name, $default) { return defined($name) ? constant($name) : $def
- | 指定国家访问真实页(逗号分隔国家代码) |
- |
-
+
+ 国家条件
+ 开启后仅允许填写的国家访问真实页;关闭则不做国家拦截。
+ |
+
+
+ |
+
+ >
+ | 允许的国家代码(多个使用英文逗号隔开) |
+
+
+ |
+
| 广告策略 ID |
|
@@ -1210,6 +1235,16 @@ $_d = function($name, $default) { return defined($name) ? constant($name) : $def
$(target).slideToggle(180);
});
+ function syncCountryCodesRow() {
+ var on = $('input[name="country_on"]:checked').val() === 'ON';
+ $('#countryCodesRow').toggle(on);
+ if (!on) {
+ $('input[name="country"]').val('');
+ }
+ }
+ $(document).on('change', 'input[name="country_on"]', syncCountryCodesRow);
+ syncCountryCodesRow();
+
// 动态添加链接
var linkIdx = 1;
$(document).on('click', '#addNewLinkBtn', function() {
diff --git a/ip_check.php b/ip_check.php
index 7404218..aa939c8 100755
--- a/ip_check.php
+++ b/ip_check.php
@@ -55,7 +55,7 @@ if (!function_exists('cloak_dbg_record')) {
//-----------------------------------------------ip check bof-----------------------------------------------
$v_info = new visitorInfo();
- $v_info->get_visitor_Info(COSTM_IP_SCORE, CHECK_KEY, SHOW_SITE_COUNTRY);
+ $v_info->get_visitor_Info(COSTM_IP_SCORE, CHECK_KEY, CountryAllowlist::resolvedConfig());
$reason = '';
diff --git a/lib/Cloak/CountryAllowlist.php b/lib/Cloak/CountryAllowlist.php
index b1d88ad..8723994 100755
--- a/lib/Cloak/CountryAllowlist.php
+++ b/lib/Cloak/CountryAllowlist.php
@@ -6,18 +6,56 @@ require_once __DIR__ . '/CountryCodeNormalizer.php';
class CountryAllowlist
{
+ /**
+ * SHOW_SITE_COUNTRY 是否已配置(非空允许列表 = 开启国家条件)
+ *
+ * @param string|null $config 默认读取 SHOW_SITE_COUNTRY
+ */
+ public static function isEnabled($config = null)
+ {
+ if ($config === null) {
+ $config = defined('SHOW_SITE_COUNTRY') ? SHOW_SITE_COUNTRY : '';
+ }
+ return self::parse($config) !== [];
+ }
+
+ /**
+ * 保存前规范化用户输入:兼容中文逗号/分号、顿号、全角空格及多余空白。
+ *
+ * @param string $config
+ */
+ public static function normalizeInput($config)
+ {
+ $config = trim((string) $config);
+ if ($config === '') {
+ return '';
+ }
+
+ // 全角空格、不间断空格
+ $config = preg_replace('/[\x{3000}\x{00A0}]/u', ' ', $config);
+
+ // 常见误输入分隔符统一为英文逗号
+ $config = str_replace([',', ';', ';', '、'], ',', $config);
+
+ // 去掉分隔符两侧空白,合并连续逗号
+ $config = preg_replace('/\s*,\s*/', ',', $config);
+ $config = preg_replace('/,+/', ',', $config);
+
+ return trim($config, " \t\n\r,");
+ }
+
/**
* @param string $config 逗号分隔国家码,如 US,GB,CA
* @return string[]
*/
public static function parse($config)
{
- $config = trim((string) $config);
+ $config = self::normalizeInput($config);
if ($config === '') {
return [];
}
- // 支持英文逗号、中文逗号、分号分隔
- $parts = preg_split('/\s*[,,;]\s*/u', $config);
+
+ $parts = explode(',', $config);
$out = [];
foreach ($parts as $part) {
$part = trim($part);
@@ -33,10 +71,23 @@ class CountryAllowlist
}
/**
- * 保存配置前规范化国家列表字符串(dashboard 写入用)
+ * 读取并规范化 SHOW_SITE_COUNTRY(大写 ISO2,逗号分隔)
+ *
+ * @param string|null $config 默认 SHOW_SITE_COUNTRY
+ */
+ public static function resolvedConfig($config = null)
+ {
+ if ($config === null) {
+ $config = defined('SHOW_SITE_COUNTRY') ? SHOW_SITE_COUNTRY : '';
+ }
+ return self::formatForConfig($config);
+ }
+
+ /**
+ * 保存配置前规范化国家列表字符串(dashboard 写入用,输出大写如 US,GB)
*
* @param string $config
- * @return string 如 BR,CN
+ * @return string 如 US,GB
*/
public static function formatForConfig($config)
{
diff --git a/lib/Cloak/Pipeline/CheckPipeline.php b/lib/Cloak/Pipeline/CheckPipeline.php
index aa23427..360dde0 100755
--- a/lib/Cloak/Pipeline/CheckPipeline.php
+++ b/lib/Cloak/Pipeline/CheckPipeline.php
@@ -2,6 +2,7 @@
require_once __DIR__ . '/../WhitelistGate.php';
require_once __DIR__ . '/../CloakJudgmentCache.php';
require_once __DIR__ . '/../RiskSecondaryGate.php';
+require_once __DIR__ . '/../CountryAllowlist.php';
/**
* 流量判定主流水线
@@ -88,11 +89,15 @@ class CheckPipeline
return;
}
- CloakPipelineTimer::stage('GeoIP国家判定');
- include __DIR__ . '/stages/check_country_geoip.inc.php';
- if (!empty($_SESSION['check_result'])) {
- CloakPipelineTimer::finish();
- return;
+ if (CountryAllowlist::isEnabled()) {
+ CloakPipelineTimer::stage('GeoIP国家判定');
+ include __DIR__ . '/stages/check_country_geoip.inc.php';
+ if (!empty($_SESSION['check_result'])) {
+ CloakPipelineTimer::finish();
+ return;
+ }
+ } elseif ($__cloak_debug_on) {
+ cloak_dbg_step(__LINE__, 'GeoIP国家判定', 'skip', '未开启国家条件');
}
CloakPipelineTimer::stage('广告来源限制');
diff --git a/lib/Cloak/Pipeline/stages/apply_geoip_country_log_only.inc.php b/lib/Cloak/Pipeline/stages/apply_geoip_country_log_only.inc.php
index 622492a..89d69d9 100755
--- a/lib/Cloak/Pipeline/stages/apply_geoip_country_log_only.inc.php
+++ b/lib/Cloak/Pipeline/stages/apply_geoip_country_log_only.inc.php
@@ -1,9 +1,20 @@
v_ip = $ip;
diff --git a/lib/Cloak/Pipeline/stages/check_country_geoip.inc.php b/lib/Cloak/Pipeline/stages/check_country_geoip.inc.php
index 2b73099..381dd27 100755
--- a/lib/Cloak/Pipeline/stages/check_country_geoip.inc.php
+++ b/lib/Cloak/Pipeline/stages/check_country_geoip.inc.php
@@ -1,9 +1,11 @@
v_ip = $ip;
@@ -53,7 +62,7 @@ if (!CountryAllowlist::isAllowed($countryCode, $allowlist)) {
}
if (!empty($GLOBALS['__cloak_debug_on'])) {
- cloak_dbg_step(__LINE__, 'GeoIP国家判定', 'pass', '国家允许或列表为空', [
+ cloak_dbg_step(__LINE__, 'GeoIP国家判定', 'pass', '国家在允许列表内', [
'ip' => $ip,
'country' => $countryCode,
'allowlist' => $allowlist,
diff --git a/lib/Cloak/VisitorSimulationRunner.php b/lib/Cloak/VisitorSimulationRunner.php
index 7eb8757..65c547d 100755
--- a/lib/Cloak/VisitorSimulationRunner.php
+++ b/lib/Cloak/VisitorSimulationRunner.php
@@ -230,7 +230,7 @@ class VisitorSimulationRunner
global $v_info, $reason, $config_name;
$config_name = $configName;
$v_info = new visitorInfo();
- $v_info->get_visitor_Info(COSTM_IP_SCORE, CHECK_KEY, SHOW_SITE_COUNTRY);
+ $v_info->get_visitor_Info(COSTM_IP_SCORE, CHECK_KEY, CountryAllowlist::resolvedConfig());
$reason = '';
CheckPipeline::run();
diff --git a/lib/CloakAdSourceGuard.php b/lib/CloakAdSourceGuard.php
index 073d460..1e8e224 100755
--- a/lib/CloakAdSourceGuard.php
+++ b/lib/CloakAdSourceGuard.php
@@ -52,9 +52,9 @@ class CloakAdSourceGuard
];
private static $fullTemplates = [
- self::PLATFORM_FB => 'utm_source=facebook&utm_medium=paid_social&utm_campaign={{campaign.name}}&utm_content={{ad.name}}&campaign_id={{campaign.id}}&adset_id={{adset.id}}&ad_id={{ad.id}}&site_source={{site_source_name}}&placement={{placement}}',
- self::PLATFORM_GOOGLE => 'utm_source=google&utm_medium=cpc&utm_campaign={campaignid}&utm_content={adgroupid}&utm_term={keyword}&ad_id={creative}&network={network}&placement={placement}',
- self::PLATFORM_TIKTOK => 'utm_source=tiktok&utm_medium=video_ad&utm_campaign=__CAMPAIGN_ID__&utm_content=__AID__&adgroup_id=__CID__&placement=__PLACEMENT__',
+ self::PLATFORM_FB => 'utm_source=facebook&site_source={{site_source_name}}&placement={{placement}}',
+ self::PLATFORM_GOOGLE => 'utm_source=google&utm_term={keyword}&network={network}&placement={placement}',
+ self::PLATFORM_TIKTOK => 'utm_source=tiktok&placement=__PLACEMENT__',
];
private static $multiPlatformParams = [
diff --git a/tools/regression_test.php b/tools/regression_test.php
index a6d6294..466c829 100755
--- a/tools/regression_test.php
+++ b/tools/regression_test.php
@@ -286,6 +286,10 @@ $cfDomainOut = shell_exec(escapeshellarg(PHP_BINARY) . ' ' . escapeshellarg($roo
$cfDomainJson = json_decode((string) $cfDomainOut, true);
reg_assert('Cloudflare 域名自动化 Mock 流转', ($cfDomainJson['ok'] ?? false) === true, (string) $cfDomainOut);
+$countryAllowOut = shell_exec(escapeshellarg(PHP_BINARY) . ' ' . escapeshellarg($root . '/tools/verify_country_allowlist.php') . ' 2>/dev/null');
+$countryAllowJson = json_decode((string) $countryAllowOut, true);
+reg_assert('国家条件允许列表与 GeoIP 开关', ($countryAllowJson['ok'] ?? false) === true, (string) $countryAllowOut);
+
$geoOut = shell_exec(escapeshellarg(PHP_BINARY) . ' ' . escapeshellarg($root . '/tools/verify_geoip.php') . ' 2>/dev/null');
$geoJson = json_decode((string) $geoOut, true);
if (($geoJson['tests']['db_file_exists'] ?? false) === true) {
diff --git a/tools/verify_country_allowlist.php b/tools/verify_country_allowlist.php
new file mode 100644
index 0000000..22f2ff8
--- /dev/null
+++ b/tools/verify_country_allowlist.php
@@ -0,0 +1,43 @@
+#!/usr/bin/env php
+ $ok, 'tests' => $tests], JSON_UNESCAPED_UNICODE) . "\n";
+exit($ok ? 0 : 1);
diff --git a/tools/verify_geoip.php b/tools/verify_geoip.php
index 4c54426..ec987a5 100755
--- a/tools/verify_geoip.php
+++ b/tools/verify_geoip.php
@@ -56,9 +56,16 @@ if ($tests['resolver_available']) {
$tests['normalize_name'] = CountryCodeNormalizer::toAlpha2('United States') === 'US';
$tests['allowlist_name'] = CountryAllowlist::isAllowed('United Kingdom', CountryAllowlist::parse('GB,US'));
$tests['allowlist_fullwidth_comma'] = CountryAllowlist::isAllowed('BR', CountryAllowlist::parse('BR,CN'));
+ $tests['allowlist_semicolon'] = CountryAllowlist::isAllowed('GB', CountryAllowlist::parse('US;GB;CA'));
$tests['allowlist_country_name'] = CountryAllowlist::isAllowed('BR', CountryAllowlist::parse('Brazil,China'));
if (!$tests['normalize_iso2'] || !$tests['normalize_name'] || !$tests['allowlist_name']
- || !$tests['allowlist_fullwidth_comma'] || !$tests['allowlist_country_name']) {
+ || !$tests['allowlist_fullwidth_comma'] || !$tests['allowlist_semicolon'] || !$tests['allowlist_country_name']) {
+ $ok = false;
+ }
+
+ $tests['is_enabled_empty'] = CountryAllowlist::isEnabled('') === false;
+ $tests['is_enabled_us'] = CountryAllowlist::isEnabled('US,GB') === true;
+ if (!$tests['is_enabled_empty'] || !$tests['is_enabled_us']) {
$ok = false;
}
}