sdv2500/progettojava
0
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 