第41批收尾:正则层残留 Unicode 转义全部字面化(可见字符写字面量/不可见字符用具名常量)
This commit is contained in:
@@ -1301,8 +1301,8 @@ public class AreaProtection implements Listener {
|
||||
List<String> result = new ArrayList<>();
|
||||
if (s == null || s.isEmpty()) return result;
|
||||
String trimmed = s.trim();
|
||||
// ★ 支持JSON数组格式(PHP端存储格式),如 ["速度","急迫"] 或 ["\\u8bd5\\u70bc..."]
|
||||
// (PHP 端 JSON 存储时中文会被转义成 \\uXXXX 形式,此处展示的是 PHP 侧原样)
|
||||
// ★ 支持JSON数组格式(PHP端存储格式),如 ["速度","急迫"]
|
||||
// (PHP 端 JSON 存储时中文会被转义成 U+XXXX 形式,例如 "试" 对应 U+8BD5,此处展示的是 PHP 侧原样)
|
||||
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
||||
try {
|
||||
String inner = trimmed.substring(1, trimmed.length() - 1);
|
||||
|
||||
@@ -689,7 +689,9 @@ public class ChatFilterManager {
|
||||
/** 点周带空白的变形域名:baidu . com(2026-10-08 加强拦截) */
|
||||
private static final Pattern SPACED_DOT_URL =
|
||||
Pattern.compile(
|
||||
"(?i)(?:[\\p{L}0-9](?:[\\p{L}0-9\\-]*[\\p{L}0-9])?[\\s\\u3000]*\\.)+[\\s\\u3000]*[\\p{L}]{2,}");
|
||||
"(?i)(?:[\\p{L}0-9](?:[\\p{L}0-9\\-]*[\\p{L}0-9])?[\\s"
|
||||
+ UnicodeChars.IDEOGRAPHIC_SPACE_TEXT + "]*\\.)+[\\s"
|
||||
+ UnicodeChars.IDEOGRAPHIC_SPACE_TEXT + "]*[\\p{L}]{2,}");
|
||||
private static final Pattern COLOR_CODES =
|
||||
Pattern.compile(
|
||||
"§[0-9a-fk-orA-FK-OR]");
|
||||
|
||||
@@ -181,7 +181,7 @@ public class DurationParser {
|
||||
|
||||
/** 中文日期+时间:2026年10月8日 14:43(“日”已界定日期边界,时间可紧贴) */
|
||||
private static final Pattern DT_CN = Pattern.compile(
|
||||
"(\\d{4})年(\\d{1,2})月(\\d{1,2})日(?:[ T\\u3000]+)?"
|
||||
"(\\d{4})年(\\d{1,2})月(\\d{1,2})日(?:[ T" + UnicodeChars.IDEOGRAPHIC_SPACE_TEXT + "]+)?"
|
||||
+ "(\\d{1,2}):(\\d{2})(?::(\\d{2}))?(?!\\d|[A-Za-z])");
|
||||
|
||||
/** 分隔日期+时间:26-10-08 14:43 / 2026-10-08 14:43 / 2026.10.08T14:43:00
|
||||
@@ -189,7 +189,7 @@ public class DurationParser {
|
||||
* 防止 2026-1-8 14:43 被粘连误读成「日=81、时=4」 */
|
||||
private static final Pattern DT_SEP = Pattern.compile(
|
||||
"(?<!\\d)(\\d{4}|\\d{2})[-/.](\\d{1,2})[-/.](\\d{1,2})"
|
||||
+ "[ T\\u3000]+(\\d{1,2}):(\\d{2})(?::(\\d{2}))?(?!\\d|[A-Za-z])");
|
||||
+ "[ T" + UnicodeChars.IDEOGRAPHIC_SPACE_TEXT + "]+(\\d{1,2}):(\\d{2})(?::(\\d{2}))?(?!\\d|[A-Za-z])");
|
||||
|
||||
/** 两位年份无时间:26-10-08
|
||||
* lookbehind 防止吃掉 4 位年份的后半段(2026-07-09 不能被读成 07-09) */
|
||||
|
||||
@@ -69,7 +69,8 @@ public class MaintenanceManager implements Listener {
|
||||
"&c&l[服务器维护] &7服务器正在维护中,请稍后再试&7(结束时间: &e{结束时间}&7)";
|
||||
|
||||
private static final Pattern NUM_PAT = Pattern.compile("\\d+");
|
||||
private static final Pattern DUR_PAT = Pattern.compile("(\\d+(?:\\.\\d+)?)\\s*([a-zA-Z\\u4e00-\\u9fa5]*)");
|
||||
/** 时长单位正则:单位部分匹配「字母 + 汉字区(一~龥)」,例:10秒 / 5分 / 2小时 */
|
||||
private static final Pattern DUR_PAT = Pattern.compile("(\\d+(?:\\.\\d+)?)\\s*([a-zA-Z一-龥]*)");
|
||||
private static final Pattern AMP_COLOR_PAT = Pattern.compile("&([0-9a-fk-orA-FK-OR])");
|
||||
|
||||
private final Main plugin;
|
||||
@@ -701,8 +702,7 @@ public class MaintenanceManager implements Listener {
|
||||
String body = s.replaceAll("^[=\\-_::·*#\\s]+|[=\\-_::·*#\\s]+$", "");
|
||||
if (body.indexOf('=') >= 0) return false;
|
||||
// 剥离各类括号与装饰符号(含全角【】〔〕「」『』()),只留标题正文
|
||||
String stripped = s.replaceAll("[\\[\\]\\u3010\\u3011\\u3014\\u3015\\u300c\\u300d\\u300e\\u300f"
|
||||
+ "\\uff08\\uff09()\\-=_::·*#\\s]+", "");
|
||||
String stripped = s.replaceAll("[\\[\\]【】〔〕「」『』()()\\-=_::·*#\\s]+", "");
|
||||
String low = stripped.toLowerCase(Locale.ROOT);
|
||||
// 精确匹配常见写法;再兜底 endsWith 兼容「玩家白名单」「ALLOWLIST」这类变体标题
|
||||
//(有了上面的 = 门槛,endsWith 已经不会再吞掉控制段键值对)
|
||||
@@ -781,7 +781,7 @@ public class MaintenanceManager implements Listener {
|
||||
s = s.substring(0, c).trim();
|
||||
}
|
||||
// 列表装饰前缀:- > * · •(合法 MC 名不会以这些字符开头)
|
||||
String noDecor = s.replaceFirst("^[-*>\\u00b7\\u2022]\\s+", "");
|
||||
String noDecor = s.replaceFirst("^[-*>·•]\\s+", "");
|
||||
if (!noDecor.equals(s)) {
|
||||
warn(log, "白名单条目前缀符号已忽略: [" + s + "] -> [" + noDecor + "]");
|
||||
s = noDecor;
|
||||
@@ -801,7 +801,7 @@ public class MaintenanceManager implements Listener {
|
||||
/** 去掉肉眼看不见却会让匹配失败的字符:零宽/BOM/不间断空格/全角空格 */
|
||||
private static String stripInvisible(String s) {
|
||||
if (s == null) return null;
|
||||
return s.replaceAll("[\\u200B-\\u200D\\u2060\\uFEFF\\u00A0\\u3000]", "");
|
||||
return s.replaceAll(UnicodeChars.INVISIBLE_STRIP_CLASS, "");
|
||||
}
|
||||
|
||||
/** 行内注释起点(# / # / //),返回 -1 表示没有 */
|
||||
|
||||
@@ -3,8 +3,8 @@ package Sdf1_login;
|
||||
/**
|
||||
* Unicode 特殊字符常量表。
|
||||
*
|
||||
* <p>背景:项目里原先大量使用 {@code \\uXXXX} 形式的 Unicode 转义字面量,
|
||||
* 读代码的人必须逐个心算码位才能看懂(例如 {@code \\u00a7} 其实是 MC 颜色码 §)。
|
||||
* <p>背景:项目里原先大量使用 Unicode 转义字面量(写成 U+XXXX 形式),
|
||||
* 读代码的人必须逐个心算码位才能看懂(例如 U+00A7 其实是 MC 颜色码 §)。
|
||||
* 尤其不可见字符(零宽空格、BOM、全角空格…)直接写成字面量后
|
||||
* 在编辑器里根本"看不见",反而更难排查。</p>
|
||||
*
|
||||
@@ -16,9 +16,10 @@ package Sdf1_login;
|
||||
* 统一引用本类的具名常量,既可读又不会因"看不见"而误判。</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>注意:正则表达式字符串里的 {@code \\uXXXX} 属于<b>正则层</b>转义
|
||||
* <p>注意:正则表达式字符串里的 Unicode 转义属于<b>正则层</b>转义
|
||||
* (Java 字符串里存的是字面反斜杠+u,由正则引擎在运行期解释),
|
||||
* 改写会改变正则语义,故保持原样不动。</p>
|
||||
* 改写会改变正则语义。本项目已把正则层里<b>可见</b>的转义全部改写成
|
||||
* 真实字符或本类的具名常量;<b>不可见</b>的转义则通过本类常量参与拼接。</p>
|
||||
*/
|
||||
public final class UnicodeChars {
|
||||
|
||||
@@ -75,118 +76,118 @@ public final class UnicodeChars {
|
||||
// ==================== 区间常量(不可见/边界判定用) ====================
|
||||
|
||||
/** CJK 基本汉字区起点 U+4E00(一) */
|
||||
public static final char CJK_START = '\u4E00';
|
||||
public static final char CJK_START = '一';
|
||||
|
||||
/** CJK 基本汉字区终点 U+9FFF */
|
||||
public static final char CJK_END = '\u9FFF';
|
||||
public static final char CJK_END = '鿿';
|
||||
|
||||
/** CJK 兼容汉字常用终点 U+9FA5(龥) */
|
||||
public static final char CJK_COMPAT_END = '\u9FA5';
|
||||
public static final char CJK_COMPAT_END = '龥';
|
||||
|
||||
/** CJK 扩展 A 区起点 U+3400(㐀) */
|
||||
public static final char CJK_EXT_A_START = '\u3400';
|
||||
public static final char CJK_EXT_A_START = '㐀';
|
||||
|
||||
/** CJK 扩展 A 区终点 U+4DBF(䶿) */
|
||||
public static final char CJK_EXT_A_END = '\u4DBF';
|
||||
public static final char CJK_EXT_A_END = '䶿';
|
||||
|
||||
/** 全角 ASCII 起点 U+FF01(!) */
|
||||
public static final char FULLWIDTH_START = '\uFF01';
|
||||
public static final char FULLWIDTH_START = '!';
|
||||
|
||||
/** 全角 ASCII 终点 U+FF5E(~) */
|
||||
public static final char FULLWIDTH_END = '\uFF5E';
|
||||
public static final char FULLWIDTH_END = '~';
|
||||
|
||||
/** 全角数字 0 U+FF10 */
|
||||
public static final char FULLWIDTH_ZERO = '\uFF10';
|
||||
public static final char FULLWIDTH_ZERO = '0';
|
||||
|
||||
/** 全角数字 9 U+FF19 */
|
||||
public static final char FULLWIDTH_NINE = '\uFF19';
|
||||
public static final char FULLWIDTH_NINE = '9';
|
||||
|
||||
/** 全角大写 A U+FF21 */
|
||||
public static final char FULLWIDTH_A_UPPER = '\uFF21';
|
||||
public static final char FULLWIDTH_A_UPPER = 'A';
|
||||
|
||||
/** 全角大写 Z U+FF3A */
|
||||
public static final char FULLWIDTH_Z_UPPER = '\uFF3A';
|
||||
public static final char FULLWIDTH_Z_UPPER = 'Z';
|
||||
|
||||
/** 全角小写 a U+FF41 */
|
||||
public static final char FULLWIDTH_A_LOWER = '\uFF41';
|
||||
public static final char FULLWIDTH_A_LOWER = 'a';
|
||||
|
||||
/** 全角小写 z U+FF5A */
|
||||
public static final char FULLWIDTH_Z_LOWER = '\uFF5A';
|
||||
public static final char FULLWIDTH_Z_LOWER = 'z';
|
||||
|
||||
/** 全角左括号 U+FF08 */
|
||||
public static final char FULLWIDTH_LPAREN = '\uFF08';
|
||||
public static final char FULLWIDTH_LPAREN = '(';
|
||||
|
||||
/** 全角右括号 U+FF09 */
|
||||
public static final char FULLWIDTH_RPAREN = '\uFF09';
|
||||
public static final char FULLWIDTH_RPAREN = ')';
|
||||
|
||||
/** 全角井号 U+FF03 */
|
||||
public static final char FULLWIDTH_HASH = '\uFF03';
|
||||
public static final char FULLWIDTH_HASH = '#';
|
||||
|
||||
/** 全角逗号 U+FF0C */
|
||||
public static final char FULLWIDTH_COMMA = '\uFF0C';
|
||||
public static final char FULLWIDTH_COMMA = ',';
|
||||
|
||||
/** 全角分号 U+FF1B */
|
||||
public static final char FULLWIDTH_SEMICOLON = '\uFF1B';
|
||||
public static final char FULLWIDTH_SEMICOLON = ';';
|
||||
|
||||
/** 全角冒号 U+FF1A */
|
||||
public static final char FULLWIDTH_COLON = '\uFF1A';
|
||||
public static final char FULLWIDTH_COLON = ':';
|
||||
|
||||
/** 全角句点 U+FF0E */
|
||||
public static final char FULLWIDTH_STOP = '\uFF0E';
|
||||
public static final char FULLWIDTH_STOP = '.';
|
||||
|
||||
/** 全角波浪号 U+FF5E */
|
||||
public static final char FULLWIDTH_TILDE = '\uFF5E';
|
||||
public static final char FULLWIDTH_TILDE = '~';
|
||||
|
||||
/** 半角片假名中点 U+FF65 */
|
||||
public static final char HALFWIDTH_KATAKANA_MIDDLE_DOT = '\uFF65';
|
||||
public static final char HALFWIDTH_KATAKANA_MIDDLE_DOT = '・';
|
||||
|
||||
/** 小型句点 U+FE52 */
|
||||
public static final char SMALL_FULL_STOP = '\uFE52';
|
||||
public static final char SMALL_FULL_STOP = '﹒';
|
||||
|
||||
/** 二点引导符 U+2025 */
|
||||
public static final char TWO_DOT_LEADER = '\u2025';
|
||||
public static final char TWO_DOT_LEADER = '‥';
|
||||
|
||||
/** 水平省略号 U+2026 */
|
||||
public static final char HORIZONTAL_ELLIPSIS = '\u2026';
|
||||
public static final char HORIZONTAL_ELLIPSIS = '…';
|
||||
|
||||
/** 中点 U+00B7 */
|
||||
public static final char MIDDLE_DOT = '\u00B7';
|
||||
public static final char MIDDLE_DOT = '·';
|
||||
|
||||
/** 项目符号 U+2022 */
|
||||
public static final char BULLET = '\u2022';
|
||||
public static final char BULLET = '•';
|
||||
|
||||
/** 表意句点 U+3002 */
|
||||
public static final char IDEOGRAPHIC_STOP = '\u3002';
|
||||
public static final char IDEOGRAPHIC_STOP = '。';
|
||||
|
||||
/** 表意逗号 U+3001 */
|
||||
public static final char IDEOGRAPHIC_COMMA = '\u3001';
|
||||
public static final char IDEOGRAPHIC_COMMA = '、';
|
||||
|
||||
/** 表意数字零 U+3007(〇) */
|
||||
public static final char IDEOGRAPHIC_ZERO = '\u3007';
|
||||
public static final char IDEOGRAPHIC_ZERO = '〇';
|
||||
|
||||
/** 左黑 lenticular 方括号 U+3010(【) */
|
||||
public static final char LEFT_BLACK_LENTICULAR = '\u3010';
|
||||
public static final char LEFT_BLACK_LENTICULAR = '【';
|
||||
|
||||
/** 右黑 lenticular 方括号 U+3011(】) */
|
||||
public static final char RIGHT_BLACK_LENTICULAR = '\u3011';
|
||||
public static final char RIGHT_BLACK_LENTICULAR = '】';
|
||||
|
||||
/** 左 tortoise shell 括号 U+3014(〔) */
|
||||
public static final char LEFT_TORTOISE_SHELL = '\u3014';
|
||||
public static final char LEFT_TORTOISE_SHELL = '〔';
|
||||
|
||||
/** 右 tortoise shell 括号 U+3015(〕) */
|
||||
public static final char RIGHT_TORTOISE_SHELL = '\u3015';
|
||||
public static final char RIGHT_TORTOISE_SHELL = '〕';
|
||||
|
||||
/** 左直角引号 U+300C(「) */
|
||||
public static final char LEFT_CORNER_BRACKET = '\u300C';
|
||||
public static final char LEFT_CORNER_BRACKET = '「';
|
||||
|
||||
/** 右直角引号 U+300D」(」) */
|
||||
public static final char RIGHT_CORNER_BRACKET = '\u300D';
|
||||
public static final char RIGHT_CORNER_BRACKET = '」';
|
||||
|
||||
/** 左白直角引号 U+300E(『) */
|
||||
public static final char LEFT_WHITE_CORNER_BRACKET = '\u300E';
|
||||
public static final char LEFT_WHITE_CORNER_BRACKET = '『';
|
||||
|
||||
/** 右白直角引号 U+300F(』) */
|
||||
public static final char RIGHT_WHITE_CORNER_BRACKET = '\u300F';
|
||||
public static final char RIGHT_WHITE_CORNER_BRACKET = '』';
|
||||
|
||||
// ==================== 常用字符串常量 ====================
|
||||
|
||||
@@ -214,4 +215,26 @@ public final class UnicodeChars {
|
||||
* 含:零宽空格、零宽非连接、零宽连接、字连接符、BOM、软连字符。
|
||||
*/
|
||||
public static final String INVISIBLE_CHARS = "\u200B\u200C\u200D\u2060\uFEFF\u00AD";
|
||||
|
||||
/** U+200B 零宽空格的字符串版 */
|
||||
public static final String ZERO_WIDTH_SPACE_TEXT = "\u200B";
|
||||
|
||||
/** U+200D 零宽连接符的字符串版 */
|
||||
public static final String ZERO_WIDTH_JOINER_TEXT = "\u200D";
|
||||
|
||||
/** U+2060 字连接符的字符串版 */
|
||||
public static final String WORD_JOINER_TEXT = "\u2060";
|
||||
|
||||
/** U+00A0 不间断空格的字符串版 */
|
||||
public static final String NBSP_TEXT = "\u00A0";
|
||||
|
||||
/**
|
||||
* 需要剔除的不可见字符(正则字符类形式,净化玩家输入用)。
|
||||
* 含:零宽空格~零宽连接(区间)、字连接符、BOM、不间断空格、全角空格。
|
||||
* <p>这里用具名常量拼接,而不是转义写法——这样源码里能直接看出
|
||||
* 每个字符的用途,读代码的人不必去心算码位。</p>
|
||||
*/
|
||||
public static final String INVISIBLE_STRIP_CLASS =
|
||||
"[" + ZERO_WIDTH_SPACE_TEXT + "-" + ZERO_WIDTH_JOINER_TEXT
|
||||
+ WORD_JOINER_TEXT + BOM_TEXT + NBSP_TEXT + IDEOGRAPHIC_SPACE_TEXT + "]";
|
||||
}
|
||||
|
||||
@@ -3990,6 +3990,8 @@ public class WebManager {
|
||||
* 解码JSON中的 Unicode转义序列
|
||||
*/
|
||||
private static String decodeUnicodeEscapes(String str) {
|
||||
// 这里的 "\\u" 是「反斜杠 + u」两个字符(PHP 端 JSON 的转义标记),
|
||||
// 不是 Java 的 Unicode 转义——探测原始字符串里是否带转义标记。
|
||||
if (str == null || !str.contains("\\u")) return str;
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder(str.length());
|
||||
@@ -6000,9 +6002,10 @@ public class WebManager {
|
||||
}
|
||||
}
|
||||
|
||||
/** 解码JSON中的 Unicode 转义(\\uXXXX 形式,如 \\u00a7 → §) */
|
||||
/** 解码JSON中的 Unicode 转义(U+XXXX 形式,如 U+00A7 即 §) */
|
||||
private String decodeJsonUnicode(String s) {
|
||||
if (s == null || s.isEmpty()) return s;
|
||||
// 同上:这里探测的是 JSON 里的反斜杠+u 转义标记,不是 Java Unicode 转义。
|
||||
if (!s.contains("\\u")) return s;
|
||||
StringBuilder sb = new StringBuilder(s.length());
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
|
||||
Reference in New Issue
Block a user