|
| 1 | +# -*- coding: UTF-8 -*- |
| 2 | +"""AAEncode Codec - aaencode content encoding. |
| 3 | +
|
| 4 | +AAEncode, created by Yosuke Hasegawa, converts JavaScript code into a JavaScript program made of Japanese-style |
| 5 | + emoticons ("kaomoji", e.g. "゚ω゚ノ" or "(゚Д゚)") that runs the code. The program builds the digits and the letters it |
| 6 | + needs from the string representations of JavaScript values (e.g. "false" or "undefined"), gets the Function constructor |
| 7 | + through "(3).constructor.constructor" and calls it on a string literal holding the code, each character being written |
| 8 | + as an octal ("\\NNN") or Unicode ("\\uXXXX") escape sequence of its UTF-16 code unit. |
| 9 | +
|
| 10 | +Encoding gives the same program as the reference encoder. Decoding parses the program (without running it), whatever its |
| 11 | + whitespaces, and returns the code. Malformed programs are reported whatever the errors handling. |
| 12 | +
|
| 13 | +This codec: |
| 14 | +- en/decodes strings from str to str |
| 15 | +- en/decodes strings from bytes to bytes |
| 16 | +- decodes file content to str (read) |
| 17 | +- encodes file content from str to bytes (write) |
| 18 | +
|
| 19 | +Reference: https://utf-8.jp/public/aaencode.html |
| 20 | +""" |
| 21 | +from ._javascript import * |
| 22 | +from ..__common__ import * |
| 23 | + |
| 24 | + |
| 25 | +__examples__ = { |
| 26 | + 'enc(aaencode|aa_encode)': { |
| 27 | + 'alert(1)': "゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o" |
| 28 | + "^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚=" |
| 29 | + "=3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚" |
| 30 | + "Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +" |
| 31 | + "'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д" |
| 32 | + "゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [" |
| 33 | + "゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -" |
| 34 | + "゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚" |
| 35 | + "ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\\\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д" |
| 36 | + "゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚" |
| 37 | + ")+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ" |
| 38 | + "゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+((o^_^o) +(o^_^o))+" |
| 39 | + " (゚Θ゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');", |
| 40 | + }, |
| 41 | + 'enc-dec(aaencode)': ["", "alert(\"Hello, World!\")", "@random{256}", "caf\xe9 \u20ac \U0001f600", |
| 42 | + "\x00\x01\n\\\"'"], |
| 43 | + 'dec(aaencode)': {'': None, 'alert(1)': None}, |
| 44 | +} |
| 45 | + |
| 46 | + |
| 47 | +DIGITS = ["(c^_^o)", "(゚Θ゚)", "((o^_^o) - (゚Θ゚))", "(o^_^o)", "(゚ー゚)", "((゚ー゚) + (゚Θ゚))", "((o^_^o) +(o^_^o))", |
| 48 | + "((゚ー゚) + (o^_^o))", "((゚ー゚) + (゚ー゚))", "((゚ー゚) + (゚ー゚) + (゚Θ゚))", "(゚Д゚) .゚ω゚ノ", "(゚Д゚) .゚Θ゚ノ", |
| 49 | + "(゚Д゚) ['c']", "(゚Д゚) .゚ー゚ノ", "(゚Д゚) .゚Д゚ノ", "(゚Д゚) [゚Θ゚]"] |
| 50 | +HEADER = "゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); " |
| 51 | +# easter egg of the reference encoder |
| 52 | +EASTER_EGG = (re.compile(r"ひだまりスケッチ×(365|356)\s*来週も見てくださいね[!!]"), |
| 53 | + "X=_=3; \r\n\r\n X / _ / X < \"来週も見てくださいね!\";\r\n\r\n") |
| 54 | +PROLOGUE = "(゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')" \ |
| 55 | + "[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = " \ |
| 56 | + "((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+" \ |
| 57 | + "(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+" \ |
| 58 | + "((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+" \ |
| 59 | + "((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+" \ |
| 60 | + "((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; " \ |
| 61 | + "(゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];" \ |
| 62 | + "(゚Д゚) [゚o゚]='\\\"';" |
| 63 | +# Function(Function("return\"" + <escaped code> + "\"")(1))("_") |
| 64 | +START = "(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ " |
| 65 | +BACKSLASH, QUOTE, U = "(゚Д゚)[゚ε゚]+", "(゚Д゚)[゚o゚]", "(o゚ー゚o)+ " |
| 66 | +EPILOGUE = QUOTE + ") (゚Θ゚)) ('_');" |
| 67 | +# for decoding, whitespaces are removed from the program and from its tokens |
| 68 | +_ws = lambda s: re.sub(r"\s+", "", s) |
| 69 | +_START, _END = _ws(START), _ws(EPILOGUE).rstrip(";") |
| 70 | +_TOKENS = {_ws(BACKSLASH): "\\", _ws(U): "u", **{_ws(d) + "+": "0123456789abcdef"[i] for i, d in enumerate(DIGITS)}} |
| 71 | +_TOKEN = re.compile("|".join(map(re.escape, sorted(_TOKENS, key=len, reverse=True)))) |
| 72 | + |
| 73 | + |
| 74 | +def _err(msg): |
| 75 | + raise AaencodeDecodeError(f"'aaencode' codec can't decode: {msg}") |
| 76 | + |
| 77 | + |
| 78 | +def aaencode_encode(text, errors="strict"): |
| 79 | + t = ensure_str(text) |
| 80 | + r = HEADER + [EASTER_EGG[1], ""][EASTER_EGG[0].search(t) is None] + PROLOGUE + START |
| 81 | + for n in utf16_units(t): |
| 82 | + r += BACKSLASH + ("".join(DIGITS[int(c)] + "+ " for c in f"{n:o}") if n <= 127 else |
| 83 | + U + "".join(DIGITS[int(c, 16)] + "+ " for c in f"{n:04x}")) |
| 84 | + return r + EPILOGUE, len(text) |
| 85 | + |
| 86 | + |
| 87 | +def aaencode_decode(text, errors="strict"): |
| 88 | + p = _ws(ensure_str(text)) |
| 89 | + if (i := p.find(_START)) < 0: |
| 90 | + _err("payload not found") |
| 91 | + p = p[i+len(_START):].rstrip(";") |
| 92 | + if not p.endswith(_END): |
| 93 | + _err("end of payload not found") |
| 94 | + p, body, i = p[:-len(_END)], "", 0 |
| 95 | + # the payload is the source of a string literal, made of backslashes, "u"'s and hexadecimal digits |
| 96 | + while i < len(p): |
| 97 | + if (m := _TOKEN.match(p, i)) is None: |
| 98 | + _err(f"unexpected token at position {i} of the payload") |
| 99 | + body, i = body + _TOKENS[m.group()], m.end() |
| 100 | + return (r := js_unescape(body, _err)), len(r) |
| 101 | + |
| 102 | + |
| 103 | +add("aaencode", aaencode_encode, aaencode_decode, r"^aa[-_]?encode$", expansion_factor=None) |
0 commit comments