CoolFace
Apppublic

sdv2500/progettojava

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
packed.py204 linesDownload Raw Back to utils
1# Adapted for use in EasyProxy from:2#https://github.com/einars/js-beautify/blob/master/python/jsbeautifier/unpackers/packer.py3# Unpacker for Dean Edward's p.a.c.k.e.r, a part of javascript beautifier4# by Einar Lielmanis <einar@beautifier.io>5#6#     written by Stefano Sanfilippo <a.little.coder@gmail.com>7#8# usage:9#10# if detect(some_string):11#     unpacked = unpack(some_string)12#13"""Unpacker for Dean Edward's p.a.c.k.e.r"""14 15import re16from bs4 import BeautifulSoup, SoupStrainer17from urllib.parse import urljoin, urlparse18import logging19 20 21logger = logging.getLogger(__name__)22 23 24def detect(source):25    if "eval(function(p,a,c,k,e,d)" in source:26        mystr = "smth"27        return mystr is not None28 29 30def unpack(source):31    """Unpacks P.A.C.K.E.R. packed js code."""32    payload, symtab, radix, count = _filterargs(source)33 34    if count != len(symtab):35        raise UnpackingError("Malformed p.a.c.k.e.r. symtab.")36 37    try:38        unbase = Unbaser(radix)39    except TypeError:40        raise UnpackingError("Unknown p.a.c.k.e.r. encoding.")41 42    def lookup(match):43        """Look up symbols in the synthetic symtab."""44        word = match.group(0)45        return symtab[unbase(word)] or word46 47    payload = payload.replace("\\\\", "\\").replace("\\'", "'")48    source = re.sub(r"\b\w+\b", lookup, payload)49    return _replacestrings(source)50 51 52def _filterargs(source):53    """Juice from a source file the four args needed by decoder."""54    juicers = [55        (r"}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\), *(\d+), *(.*)\)\)"),56        (r"}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\)"),57    ]58    for juicer in juicers:59        args = re.search(juicer, source, re.DOTALL)60        if args:61            a = args.groups()62            if a[1] == "[]":63                a = list(a)64                a[1] = 6265                a = tuple(a)66            try:67                return a[0], a[3].split("|"), int(a[1]), int(a[2])68            except ValueError:69                raise UnpackingError("Corrupted p.a.c.k.e.r. data.")70 71    # could not find a satisfying regex72    raise UnpackingError(73        "Could not make sense of p.a.c.k.e.r data (unexpected code structure)"74    )75 76 77def _replacestrings(source):78    """Strip string lookup table (list) and replace values in source."""79    match = re.search(r'var *(_\w+)\=\["(.*?)"\];', source, re.DOTALL)80 81    if match:82        varname, strings = match.groups()83        startpoint = len(match.group(0))84        lookup = strings.split('","')85        variable = "%s[%%d]" % varname86        for index, value in enumerate(lookup):87            source = source.replace(variable % index, '"%s"' % value)88        return source[startpoint:]89    return source 90 91 92class Unbaser(object):93    """Functor for a given base. Will efficiently convert94    strings to natural numbers."""95 96    ALPHABET = {97        62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",98        95: (99            " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"100            "[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"101        ),102    }103 104    def __init__(self, base):105        self.base = base106 107        # fill elements 37...61, if necessary108        if 36 < base < 62:109            if not hasattr(self.ALPHABET, self.ALPHABET[62][:base]):110                self.ALPHABET[base] = self.ALPHABET[62][:base]111        # attrs = self.ALPHABET112        # print ', '.join("%s: %s" % item for item in attrs.items())113        # If base can be handled by int() builtin, let it do it for us114        if 2 <= base <= 36:115            self.unbase = lambda string: int(string, base)116        else:117            # Build conversion dictionary cache118            try:119                self.dictionary = dict(120                    (cipher, index) for index, cipher in enumerate(self.ALPHABET[base])121                )122            except KeyError:123                raise TypeError("Unsupported base encoding.")124 125            self.unbase = self._dictunbaser126 127    def __call__(self, string):128        return self.unbase(string)129 130    def _dictunbaser(self, string):131        """Decodes a  value to an integer."""132        ret = 0133        for index, cipher in enumerate(string[::-1]):134            ret += (self.base**index) * self.dictionary[cipher]135        return ret136 137class UnpackingError(Exception):138    """Badly packed source or general error. Argument is a139    meaningful description."""140    pass141 142async def eval_solver(session, url: str, headers: dict, patterns: list[str]) -> str:143    try:144        async with session.get(url, headers=headers) as response:145            text = await response.text()146        147        # Check for common error messages indicating video not found or unavailable148        error_indicators = [149            "can't find the video",150            "video you are looking for",151            "file was deleted",152            "file not found",153            "this file does not exist",154            "video not found"155        ]156        157        text_lower = text.lower()158        for indicator in error_indicators:159            if indicator in text_lower:160                logger.warning("Video not available at %s: detected '%s'", url, indicator)161                raise UnpackingError(f"Video not found or unavailable at {url}")162        163        # Try to find and unpack JavaScript164        soup = BeautifulSoup(text, "lxml", parse_only=SoupStrainer("script"))165        script_all = soup.find_all("script")166        167        packed_scripts = []168        for i in script_all:169            if i.text and detect(i.text):170                packed_scripts.append(i.text)171        172        if not packed_scripts:173            logger.warning("No packed JavaScript found at %s. Page may have changed structure.", url)174            raise UnpackingError(f"No packed JavaScript found at {url}. The video may not exist or the page structure has changed.")175        176        # Try to extract URL from packed scripts177        for script in packed_scripts:178            try:179                unpacked_code = unpack(script)180                logger.debug("Unpacked code snippet: %s", unpacked_code[:200])181                182                for pattern in patterns:183                    match = re.search(pattern, unpacked_code)184                    if match:185                        extracted_url = match.group(1)186                        if not urlparse(extracted_url).scheme:187                            extracted_url = urljoin(url, extracted_url)188                        189                        logger.info("Successfully extracted URL from %s", url)190                        return extracted_url191            except Exception as unpack_error:192                logger.debug("Failed to unpack script: %s", str(unpack_error))193                continue194        195        # If we got here, we found packed JS but couldn't extract the URL196        logger.warning("Found packed JavaScript but no patterns matched at %s. Patterns tried: %s", url, patterns)197        raise UnpackingError(f"Found packed JavaScript but could not extract video URL. The extraction patterns may need updating.")198        199    except UnpackingError:200        raise201    except Exception as e:202        logger.exception("Unexpected error in eval_solver for %s", url)203        raise UnpackingError(f"Error extracting from {url}: {str(e)}") from e204