summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/packer.py
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.11/site-packages/jsbeautifier/unpackers/packer.py')
-rw-r--r--venv/lib/python3.11/site-packages/jsbeautifier/unpackers/packer.py161
1 files changed, 161 insertions, 0 deletions
diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/packer.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/packer.py
new file mode 100644
index 0000000..117ff58
--- /dev/null
+++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/packer.py
@@ -0,0 +1,161 @@
+#
+# Unpacker for Dean Edward's p.a.c.k.e.r, a part of javascript beautifier
+# by Einar Lielmanis <einar@beautifier.io>
+#
+# written by Stefano Sanfilippo <a.little.coder@gmail.com>
+#
+# usage:
+#
+# if detect(some_string):
+# unpacked = unpack(some_string)
+#
+
+"""Unpacker for Dean Edward's p.a.c.k.e.r"""
+
+import re
+import string
+import sys
+from jsbeautifier.unpackers import UnpackingError
+
+PRIORITY = 1
+
+
+def detect(source):
+ global beginstr
+ global endstr
+ beginstr = ""
+ endstr = ""
+ begin_offset = -1
+ """Detects whether `source` is P.A.C.K.E.R. coded."""
+ mystr = re.search(
+ r"eval[ ]*\([ ]*function[ ]*\([ ]*p[ ]*,[ ]*a[ ]*,[ ]*c["
+ " ]*,[ ]*k[ ]*,[ ]*e[ ]*,[ ]*",
+ source,
+ )
+ if mystr:
+ begin_offset = mystr.start()
+ beginstr = source[:begin_offset]
+ if begin_offset != -1:
+ """Find endstr"""
+ source_end = source[begin_offset:]
+ if source_end.split("')))", 1)[0] == source_end:
+ try:
+ endstr = source_end.split("}))", 1)[1]
+ except IndexError:
+ endstr = ""
+ else:
+ endstr = source_end.split("')))", 1)[1]
+ return mystr is not None
+
+
+def unpack(source):
+ """Unpacks P.A.C.K.E.R. packed js code."""
+ payload, symtab, radix, count = _filterargs(source)
+
+ if count != len(symtab):
+ raise UnpackingError("Malformed p.a.c.k.e.r. symtab.")
+
+ try:
+ unbase = Unbaser(radix)
+ except TypeError:
+ raise UnpackingError("Unknown p.a.c.k.e.r. encoding.")
+
+ def lookup(match):
+ """Look up symbols in the synthetic symtab."""
+ word = match.group(0)
+ return symtab[unbase(word)] or word
+
+ payload = payload.replace("\\\\", "\\").replace("\\'", "'")
+ if sys.version_info.major == 2:
+ source = re.sub(r"\b\w+\b", lookup, payload)
+ else:
+ source = re.sub(r"\b\w+\b", lookup, payload, flags=re.ASCII)
+ return _replacestrings(source)
+
+
+def _filterargs(source):
+ """Juice from a source file the four args needed by decoder."""
+ juicers = [
+ (r"}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\), *(\d+), *(.*)\)\)"),
+ (r"}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\)"),
+ ]
+ for juicer in juicers:
+ args = re.search(juicer, source, re.DOTALL)
+ if args:
+ a = args.groups()
+ if a[1] == "[]":
+ a = list(a)
+ a[1] = 62
+ a = tuple(a)
+ try:
+ return a[0], a[3].split("|"), int(a[1]), int(a[2])
+ except ValueError:
+ raise UnpackingError("Corrupted p.a.c.k.e.r. data.")
+
+ # could not find a satisfying regex
+ raise UnpackingError(
+ "Could not make sense of p.a.c.k.e.r data (unexpected code structure)"
+ )
+
+
+def _replacestrings(source):
+ global beginstr
+ global endstr
+ """Strip string lookup table (list) and replace values in source."""
+ match = re.search(r'var *(_\w+)\=\["(.*?)"\];', source, re.DOTALL)
+
+ if match:
+ varname, strings = match.groups()
+ startpoint = len(match.group(0))
+ lookup = strings.split('","')
+ variable = "%s[%%d]" % varname
+ for index, value in enumerate(lookup):
+ source = source.replace(variable % index, '"%s"' % value)
+ return source[startpoint:]
+ return beginstr + source + endstr
+
+
+class Unbaser(object):
+ """Functor for a given base. Will efficiently convert
+ strings to natural numbers."""
+
+ ALPHABET = {
+ 62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ 95: (
+ " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
+ ),
+ }
+
+ def __init__(self, base):
+ self.base = base
+
+ # fill elements 37...61, if necessary
+ if 36 < base < 62:
+ if not hasattr(self.ALPHABET, self.ALPHABET[62][:base]):
+ self.ALPHABET[base] = self.ALPHABET[62][:base]
+ # attrs = self.ALPHABET
+ # print ', '.join("%s: %s" % item for item in attrs.items())
+ # If base can be handled by int() builtin, let it do it for us
+ if 2 <= base <= 36:
+ self.unbase = lambda string: int(string, base)
+ else:
+ # Build conversion dictionary cache
+ try:
+ self.dictionary = dict(
+ (cipher, index) for index, cipher in enumerate(self.ALPHABET[base])
+ )
+ except KeyError:
+ raise TypeError("Unsupported base encoding.")
+
+ self.unbase = self._dictunbaser
+
+ def __call__(self, string):
+ return self.unbase(string)
+
+ def _dictunbaser(self, string):
+ """Decodes a value to an integer."""
+ ret = 0
+ for index, cipher in enumerate(string[::-1]):
+ ret += (self.base**index) * self.dictionary[cipher]
+ return ret