Js2Py
Js2Py copied to clipboard
Fix the escape and unescape functions behaving differently from JavaScript
Overview
When using CryptoJS to encode non-ASCII characters, the resulting encrypted output cannot be decrypted properly.
import js2py
CryptoJS = js2py.require('crypto-js')
print(CryptoJS.AES.encrypt("你好世界!", "test").toString())
Problem
During the encryption process, CryptoJS utilizes the deprecated unescape function.
Investigation revealed that the escape and unescape functions in the Python environment operate inconsistently with those in the JavaScript environment.
According to the documentation, unescape() should not be used for decoding URIs. The unescape() function replaces any escape sequences with the characters they represent. Specifically, it replaces any escape sequences in the form of %XX or %uXXXX (where X represents a hexadecimal digit) with the character having the hexadecimal value XX/XXXX. If the escape sequence is not a valid one (for example, if % is followed by one or no hexadecimal digits), it is left unchanged.
fix
A new implementation method for the escape and unescape functions has been provided.
@Js
def escape(text):
def replacer(match):
char = match.group()
code = ord(char)
if code <= 0xff:
return f'%{code:02X}'
else:
return f'%u{code:04X}'
return re.sub(r'[^A-Za-z0-9@*_+\-./]', replacer, text.to_python())
@Js
def unescape(text):
def replacer(match):
u_group = match.group(1)
hex_group = match.group(2)
if u_group is not None:
return chr(int(u_group, 16))
elif hex_group is not None:
return chr(int(hex_group, 16))
return match.group()
return re.sub(r'%u([0-9A-Fa-f]{4})|%([0-9A-Fa-f]{2})', replacer, text.to_python(), flags=re.IGNORECASE)