def get_throttling_plan(js: str): """Extract the "throttling plan". The "throttling plan" is a list of tuples used for calling functions in the c array. The first element of the tuple is the index of the function to call, and any remaining elements of the tuple are arguments to pass to that function. :param str js: The contents of the base.js asset file. :returns: The full function code for computing the throttlign parameter. """ raw_code = get_throttling_function_code(js) transform_start = r"try{" plan_regex = re.compile(transform_start) match = plan_regex.search(raw_code) transform_plan_raw = find_object_from_startpoint(raw_code, match.span()[1] - 1) # Steps are either c[x](c[y]) or c[x](c[y],c[z]) step_start = r"c\[(\d+)\]\(c\[(\d+)\](,c(\[(\d+)\]))?\)" step_regex = re.compile(step_start) matches = step_regex.findall(transform_plan_raw) transform_steps = [] for match in matches: if match[4] != '': transform_steps.append((match[0], match[1], match[4])) else: transform_steps.append((match[0], match[1])) return transform_steps
def get_throttling_function_code(js: str) -> str: """Extract the raw code for the throttling function. :param str js: The contents of the base.js asset file. :rtype: str :returns: The name of the function used to compute the throttling parameter. """ # Begin by extracting the correct function name name = re.escape(get_throttling_function_name(js)) # Identify where the function is defined pattern_start = r"%s=function\(\w\)" % name regex = re.compile(pattern_start) match = regex.search(js) # Extract the code within curly braces for the function itself, and merge any split lines code_lines_list = find_object_from_startpoint(js, match.span()[1]).split('\n') joined_lines = "".join(code_lines_list) # Prepend function definition (e.g. `Dea=function(a)`) return match.group(0) + joined_lines
def get_throttling_function_array(js: str) -> List[Any]: """Extract the "c" array. :param str js: The contents of the base.js asset file. :returns: The array of various integers, arrays, and functions. """ raw_code = get_throttling_function_code(js) array_start = r",c=\[" array_regex = re.compile(array_start) match = array_regex.search(raw_code) array_raw = find_object_from_startpoint(raw_code, match.span()[1] - 1) str_array = throttling_array_split(array_raw) converted_array = [] for el in str_array: try: converted_array.append(int(el)) continue except ValueError: # Not an integer value. pass if el == 'null': converted_array.append(None) continue if el.startswith('"') and el.endswith('"'): # Convert e.g. '"abcdef"' to string without quotation marks, 'abcdef' converted_array.append(el[1:-1]) continue if el.startswith('function'): mapper = ( (r"{for\(\w=\(\w%\w\.length\+\w\.length\)%\w\.length;\w--;\)\w\.unshift\(\w.pop\(\)\)}", throttling_unshift), # noqa:E501 (r"{\w\.reverse\(\)}", throttling_reverse), (r"{\w\.push\(\w\)}", throttling_push), (r";var\s\w=\w\[0\];\w\[0\]=\w\[\w\];\w\[\w\]=\w}", throttling_swap), (r"case\s\d+", throttling_cipher_function), (r"\w\.splice\(0,1,\w\.splice\(\w,1,\w\[0\]\)\[0\]\)", throttling_nested_splice), # noqa:E501 (r";\w\.splice\(\w,1\)}", js_splice), (r"\w\.splice\(-\w\)\.reverse\(\)\.forEach\(function\(\w\){\w\.unshift\(\w\)}\)", throttling_prepend), # noqa:E501 (r"for\(var \w=\w\.length;\w;\)\w\.push\(\w\.splice\(--\w,1\)\[0\]\)}", throttling_reverse), # noqa:E501 ) found = False for pattern, fn in mapper: if re.search(pattern, el): converted_array.append(fn) found = True if found: continue converted_array.append(el) # Replace null elements with array itself for i in range(len(converted_array)): if converted_array[i] is None: converted_array[i] = converted_array return converted_array