|
|
|
@ -997,15 +997,13 @@ export class RankBoardManager { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* 授权昵称转 UTF-8 Base64,避免特殊字符破坏存档。 |
|
|
|
* 授权昵称转 UTF-8 Base64,避免特殊字符破坏存档。 |
|
|
|
* 抖音等小游戏环境无 btoa,用自实现兜底。 |
|
|
|
* 不依赖 btoa/atob(抖音等小游戏环境没有),统一走自实现。 |
|
|
|
* @returns 编码结果;失败返回空串 |
|
|
|
* @returns 编码结果;失败返回空串 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private static _encodeNick(nick: string): string { |
|
|
|
private static _encodeNick(nick: string): string { |
|
|
|
if (!nick) return ''; |
|
|
|
if (!nick) return ''; |
|
|
|
try { |
|
|
|
try { |
|
|
|
const binary = this._utf8ToBinary(nick); |
|
|
|
return this._base64Encode(this._utf8ToBinary(nick)); |
|
|
|
if (typeof btoa === 'function') return btoa(binary); |
|
|
|
|
|
|
|
return this._base64Encode(binary); |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
} catch (e) { |
|
|
|
console.warn('[RankBoardManager] 昵称 Base64 编码异常', e); |
|
|
|
console.warn('[RankBoardManager] 昵称 Base64 编码异常', e); |
|
|
|
return ''; |
|
|
|
return ''; |
|
|
|
@ -1020,7 +1018,7 @@ export class RankBoardManager { |
|
|
|
if (!raw) return ''; |
|
|
|
if (!raw) return ''; |
|
|
|
if (!this._isBase64Text(raw)) return raw; |
|
|
|
if (!this._isBase64Text(raw)) return raw; |
|
|
|
try { |
|
|
|
try { |
|
|
|
const binary = typeof atob === 'function' ? atob(raw) : this._base64Decode(raw); |
|
|
|
const binary = this._base64Decode(raw); |
|
|
|
if (!binary) return raw; |
|
|
|
if (!binary) return raw; |
|
|
|
const text = this._binaryToUtf8(binary); |
|
|
|
const text = this._binaryToUtf8(binary); |
|
|
|
// 解码出控制字符/替换符说明不是有效编码昵称(误判的明文),按明文返回
|
|
|
|
// 解码出控制字符/替换符说明不是有效编码昵称(误判的明文),按明文返回
|
|
|
|
@ -1032,7 +1030,7 @@ export class RankBoardManager { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** latin1 字符串(每字符码 0-255)转 Base64;自实现兜底,不依赖 btoa */ |
|
|
|
/** latin1 字符串(每字符码 0-255)转 Base64;纯手写实现,不依赖 btoa */ |
|
|
|
private static _base64Encode(binary: string): string { |
|
|
|
private static _base64Encode(binary: string): string { |
|
|
|
const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; |
|
|
|
const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; |
|
|
|
let out = ''; |
|
|
|
let out = ''; |
|
|
|
@ -1056,7 +1054,7 @@ export class RankBoardManager { |
|
|
|
return out; |
|
|
|
return out; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Base64 转 latin1 字符串;自实现兜底,不依赖 atob。非法输入返回空串 */ |
|
|
|
/** Base64 转 latin1 字符串;纯手写实现,不依赖 atob。非法输入返回空串 */ |
|
|
|
private static _base64Decode(b64: string): string { |
|
|
|
private static _base64Decode(b64: string): string { |
|
|
|
const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; |
|
|
|
const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; |
|
|
|
const lookup: Record<string, number> = {}; |
|
|
|
const lookup: Record<string, number> = {}; |
|
|
|
@ -1098,7 +1096,7 @@ export class RankBoardManager { |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** UTF-8 字符串转 latin1 二进制(供 btoa) */ |
|
|
|
/** UTF-8 字符串转 latin1 二进制(供 _base64Encode) */ |
|
|
|
private static _utf8ToBinary(text: string): string { |
|
|
|
private static _utf8ToBinary(text: string): string { |
|
|
|
const encoded = encodeURIComponent(text); |
|
|
|
const encoded = encodeURIComponent(text); |
|
|
|
let binary = ''; |
|
|
|
let binary = ''; |
|
|
|
@ -1114,7 +1112,7 @@ export class RankBoardManager { |
|
|
|
return binary; |
|
|
|
return binary; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** latin1 二进制转 UTF-8 字符串(供 atob 结果) */ |
|
|
|
/** latin1 二进制转 UTF-8 字符串(供 _base64Decode 结果) */ |
|
|
|
private static _binaryToUtf8(binary: string): string { |
|
|
|
private static _binaryToUtf8(binary: string): string { |
|
|
|
let pct = ''; |
|
|
|
let pct = ''; |
|
|
|
for (let i = 0; i < binary.length; i++) { |
|
|
|
for (let i = 0; i < binary.length; i++) { |
|
|
|
|