Js2Py icon indicating copy to clipboard operation
Js2Py copied to clipboard

Fix the escape and unescape functions behaving differently from JavaScript

Open wojiaoyishang opened this issue 3 weeks ago • 0 comments

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())

image

Problem

During the encryption process, CryptoJS utilizes the deprecated unescape function.

image

Investigation revealed that the escape and unescape functions in the Python environment operate inconsistently with those in the JavaScript environment.

image

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)

wojiaoyishang avatar Feb 03 '25 12:02 wojiaoyishang