Files
Viper_VRTE/binascii.vp
T
2026-09-11 18:57:39 +08:00

352 lines
15 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import t, c
import stdlib
HEX_CHARS: t.CArray[t.CChar, None] = "0123456789abcdef"
HEX_VALS: t.CArray[t.CInt, 256]
B64_CHARS: t.CArray[t.CChar, None] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
B64_VALS: t.CArray[t.CInt, 256]
# HQX (BinHex 4.0) Alphabet — The standard 64-character table from RFC 1741, where the index corresponds to the 6-bit value (0..63).
# Note: There must be exactly 64 elements (previously, 67 were given → compiler fail-fast
# "Array initialization element count 67 exceeds array declared length 64"). This table is the authoritative source,
# init_binascii builds HQX_VALS based on this alone, and this table must not be rewritten.
HQX_CHARS: t.CArray[t.CChar, 64] = [
'!', chr(34), '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '0', '1', '2',
'3', '4', '5', '6', '8', '9', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'X', 'Y', 'Z', '[',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'h', 'i', 'j', 'k', 'l', 'm', 'p', 'q', 'r'
]
HQX_VALS: t.CArray[t.CInt, 256]
UU_CHARS: t.CArray[t.CChar, None] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
CRC32_TABLE: t.CArray[t.CUnsignedInt, 256] = [
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
]
CRC_HQX_TABLE: t.CArray[t.CUnsignedShort, 256] = [
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
]
def init_binascii():
i: t.CInt
for i in range(256):
HEX_VALS[i] = -1
B64_VALS[i] = -1
HQX_VALS[i] = -1
for i in range(16):
HEX_VALS[t.CInt(HEX_CHARS[i])] = i
HEX_VALS[t.CInt(HEX_CHARS[i] - 32)] = i
for i in range(64):
B64_VALS[t.CInt(B64_CHARS[i])] = i
# HQX_VALS 由标准 BinHex 字母表(见 HQX_CHARS 静态初值,RFC 1741)反查建立。
# 注意:此处【不得】再重写 HQX_CHARS——此前用 `chr(32 + i)` 覆盖 0..63,
# 会把标准 BinHex 表整张冲掉,导致 b2a_hqx/a2b_hqx 与 RFC 1741 不兼容。
for i in range(64):
HQX_VALS[t.CUnsignedChar(HQX_CHARS[i])] = i
def crc32(data: str, length: t.CInt, crc: t.CUnsignedInt) -> t.CUnsignedInt:
i: t.CInt
s: t.CUnsignedInt = crc ^ 0xFFFFFFFF
for i in range(length):
s = CRC32_TABLE[(s ^ t.CUnsignedChar(data[i])) & 0xFF] ^ (s >> 8)
return s ^ 0xFFFFFFFF
def crc_hqx(data: str, length: t.CInt, crc: t.CUnsignedShort) -> t.CUnsignedShort:
i: t.CInt
s: t.CUnsignedShort = crc
for i in range(length):
s = CRC_HQX_TABLE[t.CUnsignedChar(s >> 8)] ^ (s << 1 | (data[i] & 0xFF))
return s
def hexlify(data: str, length: t.CInt) -> str:
if not data or length < 0: return None
out: str = str(stdlib.malloc(length * 2 + 1))
if not out: return None
oi: t.CInt = 0
for i in range(length):
s: t.CUnsignedChar = t.CUnsignedChar(data[i])
out[oi] = HEX_CHARS[(s >> 4) & 0x0F]
oi += 1
out[oi] = HEX_CHARS[(s >> 0) & 0x0F]
oi += 1
out[oi] = '\0'
return out
def b2a_hex(data: str, length: t.CInt) -> str:
return hexlify(data, length)
def a2b_hex(hexstr: str, length: t.CInt) -> str:
if not hexstr or length < 0 or length % 2 != 0: return None
out_len: t.CInt = length // 2
out: str = str(stdlib.malloc(out_len + 1))
if not out: return None
oi: t.CInt = 0
for i in range(0, length, 2):
hi: t.CInt = HEX_VALS[t.CUnsignedChar(hexstr[i])]
lo: t.CInt = HEX_VALS[t.CUnsignedChar(hexstr[i + 1])]
if hi < 0 or lo < 0:
stdlib.free(out)
return None
out[oi] = t.CChar((hi << 4) | lo)
oi += 1
out[oi] = '\0'
return out
def unhexlify(data: str, length: t.CInt) -> bytes:
return a2b_hex(data, length)
def b2a_base64(data: str, length: t.CInt) -> str:
if not data or length < 0: return None
olen: t.CInt = (length // 3) * 4
if length % 3 != 0:
olen += 4
olen += 1
out: str = str(stdlib.malloc(olen + 1))
if not out: return None
oi: t.CInt = 0
for i in range(0, length, 3):
b0: t.CUnsignedChar = t.CUnsignedChar(data[i])
b1: t.CUnsignedChar = 0
b2: t.CUnsignedChar = 0
if i + 1 < length:
b1 = t.CUnsignedChar(data[i + 1])
if i + 2 < length:
b2 = t.CUnsignedChar(data[i + 2])
out[oi] = B64_CHARS[(b0 >> 2) & 0x3F]
oi += 1
out[oi] = B64_CHARS[((b0 & 0x03) << 4) | ((b1 >> 4) & 0x0F)]
oi += 1
if i + 1 < length:
out[oi] = B64_CHARS[((b1 & 0x0F) << 2) | ((b2 >> 6) & 0x03)]
else:
out[oi] = '='
oi += 1
if i + 2 < length:
out[oi] = B64_CHARS[b2 & 0x3F]
else:
out[oi] = '='
oi += 1
out[oi] = '\0'
return out
def a2b_base64(data: str, length: t.CInt) -> str:
if not data or length < 4: return None
olen: t.CInt = (length // 4) * 3
if length >= 4 and data[length - 1] == '=':
olen -= 1
if length >= 4 and data[length - 2] == '=':
olen -= 1
out: str = str(stdlib.malloc(olen + 1))
if not out: return None
oi: t.CInt = 0
for i in range(0, length, 4):
v0: t.CInt = 0
v1: t.CInt = 0
v2: t.CInt = 0
v3: t.CInt = 0
j: t.CInt
for j in range(4):
c: t.CChar = data[i + j]
if c == '=':
pass
else:
k: t.CInt
for k in range(64):
if B64_CHARS[k] == c:
if j == 0: v0 = k
elif j == 1: v1 = k
elif j == 2: v2 = k
elif j == 3: v3 = k
break
out[oi] = t.CChar((v0 << 2) | (v1 >> 4))
oi += 1
if data[i + 2] != '=':
out[oi] = t.CChar(((v1 & 0x0F) << 4) | (v2 >> 2))
oi += 1
if data[i + 3] != '=':
out[oi] = t.CChar(((v2 & 0x03) << 6) | v3)
oi += 1
out[oi] = '\0'
return out
def b2a_uu(data: str, length: t.CInt) -> str:
if not data or length < 1 or length > 45: return None
out: str = str(stdlib.malloc(length * 2 + 2))
if not out: return None
oi: t.CInt = 0
out[oi] = UU_CHARS[length]
oi += 1
for i in range(0, length, 3):
b0: t.CUnsignedChar = t.CUnsignedChar(data[i])
b1: t.CUnsignedChar = 0
b2: t.CUnsignedChar = 0
if i + 1 < length:
b1 = t.CUnsignedChar(data[i + 1])
if i + 2 < length:
b2 = t.CUnsignedChar(data[i + 2])
m: t.CUnsignedInt = (t.CUnsignedInt(b0) << 16) | (t.CUnsignedInt(b1) << 8) | t.CUnsignedInt(b2)
out[oi] = UU_CHARS[(m >> 18) & 0x3F]
oi += 1
out[oi] = UU_CHARS[(m >> 12) & 0x3F]
oi += 1
out[oi] = UU_CHARS[(m >> 6) & 0x3F]
oi += 1
out[oi] = UU_CHARS[m & 0x3F]
oi += 1
out[oi] = '\n'
oi += 1
out[oi] = '\0'
return out
def a2b_uu(data: str) -> str:
if not data or data[0] == ' ' or data[0] == '`': return None
length: t.CInt = t.CInt(data[0]) - 32
if length < 0 or length > 45: return None
out: str = str(stdlib.malloc(length + 1))
if not out: return None
oi: t.CInt = 0
i: t.CInt = 1
while oi < length:
v0: t.CInt = data[i] - 32
v1: t.CInt = data[i + 1] - 32
v2: t.CInt = data[i + 2] - 32
v3: t.CInt = data[i + 3] - 32
if v0 < 0 or v0 > 63: v0 = 0
if v1 < 0 or v1 > 63: v1 = 0
if v2 < 0 or v2 > 63: v2 = 0
if v3 < 0 or v3 > 63: v3 = 0
m: t.CUnsignedInt = (t.CUnsignedInt(v0) << 18) | (t.CUnsignedInt(v1) << 12) | (t.CUnsignedInt(v2) << 6) | t.CUnsignedInt(v3)
if oi < length:
out[oi] = t.CChar((m >> 16) & 0xFF)
oi += 1
if oi < length:
out[oi] = t.CChar((m >> 8) & 0xFF)
oi += 1
if oi < length:
out[oi] = t.CChar(m & 0xFF)
oi += 1
i += 4
out[oi] = '\0'
return out
def b2a_hqx(data: str, length: t.CInt, crc: t.CUnsignedShort = 0) -> tuple[str, t.CUnsignedShort]:
if not data or length != 3:
return None, crc
out: str = str(stdlib.malloc(5))
if not out:
return None, crc
# 3字节 → 4字节 HQX
m: t.CUnsignedInt = (t.CUnsignedChar(data[0]) << 16) | (t.CUnsignedChar(data[1]) << 8) | t.CUnsignedChar(data[2])
out[0] = HQX_CHARS[(m >> 18) & 0x3F]
out[1] = HQX_CHARS[(m >> 12) & 0x3F]
out[2] = HQX_CHARS[(m >> 6) & 0x3F]
out[3] = HQX_CHARS[m & 0x3F]
out[4] = '\0'
# CRC 初始化 + 正确计算
s: t.CUnsignedShort = crc
for i in range(3):
byte: t.CUnsignedChar = t.CUnsignedChar(data[i])
s = (s << 8) ^ CRC_HQX_TABLE[((s >> 8) ^ byte) & 0xFF]
return out, s
def a2b_hqx(data: str, crc: t.CUnsignedShort = 0) -> tuple[str, t.CUnsignedShort]:
if not data:
return None, crc
# 检查字符是否有效
for i in range(4):
cchar: t.CUnsignedChar = t.CUnsignedChar(data[i])
if HQX_VALS[cchar] < 0:
return None, crc
# 解码
m: t.CUnsignedInt = 0
for i in range(4):
m = (m << 6) | t.CUnsignedInt(HQX_VALS[t.CUnsignedChar(data[i])])
out: str = str(stdlib.malloc(4))
if not out:
return None, crc
out[0] = t.CChar((m >> 16) & 0xFF)
out[1] = t.CChar((m >> 8) & 0xFF)
out[2] = t.CChar(m & 0xFF)
out[3] = '\0'
# CRC 初始化 + 正确计算
s: t.CUnsignedShort = crc
for i in range(3):
byte: t.CUnsignedChar = t.CUnsignedChar(out[i])
s = (s << 8) ^ CRC_HQX_TABLE[((s >> 8) ^ byte) & 0xFF]
return out, s
def adler32(data: str, length: t.CInt, adler: t.CUnsignedInt) -> t.CUnsignedInt:
a: t.CUnsignedInt = adler & 0xFFFF
b: t.CUnsignedInt = (adler >> 16) & 0xFFFF
i: t.CInt
for i in range(length):
a = (a + t.CUnsignedChar(data[i])) % 65521
b = (b + a) % 65521
return (b << 16) | a