def scan(self, file_object, options): self.metadata.setdefault("literals", []) self.metadata.setdefault("functions", []) self.metadata.setdefault("variables", []) try: p = pyjsparser.PyJsParser() parsed = p.parse(file_object.data.decode()) self._javascript_recursion(self, parsed) except AttributeError: file_object.flags.append(f"{self.scanner_name}::attribute_error") except IndexError: file_object.flags.append(f"{self.scanner_name}::index_error") except KeyError: file_object.flags.append(f"{self.scanner_name}::key_error") except NotImplementedError: file_object.flags.append( f"{self.scanner_name}::not_implemented_error") except RecursionError: file_object.flags.append( f"{self.scanner_name}::recursion_depth_exceeded") except UnicodeDecodeError: file_object.flags.append( f"{self.scanner_name}::unicode_decode_error") except pyjsparser.pyjsparserdata.JsSyntaxError: file_object.flags.append(f"{self.scanner_name}::js_syntax_error")
def test_parse_number(js_test_path, typ_expected, value_expected): js_test_path = os.path.join(PASSING_DIR, js_test_path) code = get_js_code(js_test_path) result = pyjsparser.PyJsParser().parse(code) value = result['body'][0]['expression']['right']['properties'][0]['value'][ 'value'] assert value == value_expected assert isinstance(value, typ_expected)
def organize_js(js, HEADER=DEFAULT_HEADER): parser = pyjsparser.PyJsParser() parsed = parser.parse(js) # js to esprima syntax tree # Another way of doing that would be with my auto esprima translation but its much slower and causes import problems: # parsed = esprima.parse(js).to_dict() translating_nodes.clean_stacks() translating_nodes.trans(parsed) # syntax tree to python code print(translating_nodes.root_scope.toJSON()) return translating_nodes.root_scope
def translate_js(js, HEADER=DEFAULT_HEADER): """js has to be a javascript source code. returns equivalent python code.""" parser = pyjsparser.PyJsParser() parsed = parser.parse(js) # js to esprima syntax tree # Another way of doing that would be with my auto esprima translation but its much slower and causes import problems: # parsed = esprima.parse(js).to_dict() translating_nodes.clean_stacks() return HEADER + translating_nodes.trans( parsed) # syntax tree to python code
def translate_js(js, HEADER=DEFAULT_HEADER, use_compilation_plan=False): """js has to be a javascript source code. returns equivalent python code.""" if use_compilation_plan and not '//' in js and not '/*' in js: return translate_js_with_compilation_plan(js, HEADER=HEADER) parser = pyjsparser.PyJsParser() parsed = parser.parse(js) # js to esprima syntax tree # Another way of doing that would be with my auto esprima translation but its much slower and causes import problems: # parsed = esprima.parse(js).to_dict() translating_nodes.clean_stacks() ret = HEADER + translating_nodes.trans( parsed) # syntax tree to python code print(translating_nodes.root_scope.toJSON()) return ret
def translate_js_with_compilation_plan(js, HEADER=DEFAULT_HEADER): """js has to be a javascript source code. returns equivalent python code. compile plans only work with the following restrictions: - only enabled for oneliner expressions - when there are comments in the js code string substitution is disabled - when there nested escaped quotes string substitution is disabled, so cacheable: Q1 == 1 && name == 'harry' not cacheable: Q1 == 1 && name == 'harry' // some comment not cacheable: Q1 == 1 && name == 'o\'Reilly' not cacheable: Q1 == 1 && name /* some comment */ == 'o\'Reilly' """ match_increaser_str, match_increaser_num, compilation_plan = get_compilation_plan( js) cp_hash = hashlib.md5(compilation_plan.encode('utf-8')).digest() try: python_code = cache[cp_hash]['proto_python_code'] except: parser = pyjsparser.PyJsParser() parsed = parser.parse(compilation_plan) # js to esprima syntax tree # Another way of doing that would be with my auto esprima translation but its much slower and causes import problems: # parsed = esprima.parse(js).to_dict() translating_nodes.clean_stacks() python_code = translating_nodes.trans( parsed) # syntax tree to python code cache[cp_hash] = { 'compilation_plan': compilation_plan, 'proto_python_code': python_code, } python_code = match_increaser_str.wrap_up(python_code) python_code = match_increaser_num.wrap_up(python_code) return HEADER + python_code
def scan(self, file_object, options): beautify = options.get("beautify", True) self.metadata.setdefault("literals", []) self.metadata.setdefault("functions", []) self.metadata.setdefault("variables", []) self.metadata["beautified"] = False js = None try: if beautify: js = jsbeautifier.beautify(file_object.data.decode()) self.metadata["beautified"] = True except: # noqa file_object.flags.append( f"{self.scanner_name}::beautify_exception") if js is None: js = file_object.data.decode() try: parser = pyjsparser.PyJsParser() parsed = parser.parse(js) self._javascript_recursion(self, parsed) except AttributeError: file_object.flags.append(f"{self.scanner_name}::attribute_error") except IndexError: file_object.flags.append(f"{self.scanner_name}::index_error") except KeyError: file_object.flags.append(f"{self.scanner_name}::key_error") except NotImplementedError: file_object.flags.append( f"{self.scanner_name}::not_implemented_error") except RecursionError: file_object.flags.append( f"{self.scanner_name}::recursion_depth_exceeded") except UnicodeDecodeError: file_object.flags.append( f"{self.scanner_name}::unicode_decode_error") except pyjsparser.pyjsparserdata.JsSyntaxError: file_object.flags.append(f"{self.scanner_name}::js_syntax_error")
def parse_example(prefix): def fmt(value): return pprint.pformat(value, width=120) + "\n" def output(out_dir, prefix, contents): pathlib.Path(out_dir).mkdir(parents=True, exist_ok=True) path = "{}/{}.txt".format(out_dir, prefix) with open(path, "w") as f: f.write(contents) js_path = "examples/{}_data.js".format(prefix) js = open(js_path).read() doc = pyjsparser.PyJsParser().parse(js) output("examples_doc", prefix, fmt(doc)) metrics_of = globals()["metrics_of_{}".format(prefix)] metrics = list(metrics_of(doc)) output("examples_metrics", prefix, fmt(metrics)) return
def metrics_of_host(host): address = host["address"] hostname = host["hostname"] def log_in(): data = {"password": host["password"]} r = requests.post("http://{}/login.cgi".format(address), data=data) assert 200 == r.status_code if "Incorrect password, please try again." in r.text: raise ValueError("Wrong password for switch at {}".format(address)) log_in() for prefix in ("link", "poe", "system"): r = requests.get("http://{}/{}_data.js".format(address, prefix)) assert 200 == r.status_code assert not r.text.startswith("<") doc = pyjsparser.PyJsParser().parse(r.text) metrics_of = globals()["metrics_of_{}".format(prefix)] for m in metrics_of(doc): m["host"] = hostname yield m
# restore context Context = previous_context # define in upper context inline_stack.define(PyName, whole_code) return PyName LogicalExpression = BinaryExpression PostfixExpression = UpdateExpression clean_stacks() if __name__ == '__main__': import codecs import time import pyjsparser c = None #'''`ijfdij`''' if not c: with codecs.open("esp.js", "r", "utf-8") as f: c = f.read() print('Started') t = time.time() res = trans(pyjsparser.PyJsParser().parse(c)) dt = time.time() - t + 0.000000001 print(('Translated everyting in', round(dt, 5), 'seconds.')) print(('Thats %d characters per second' % int(len(c) / dt))) with open('res.py', 'w') as f: f.write(res)
def _check_directive_scope(all_files): """This function checks that all directives have an explicit scope: {} and it should not be scope: true. """ print 'Starting directive scope check' print '----------------------------------------' summary_messages = [] # Select JS files which need to be checked. files_to_check = [ filename for filename in all_files if not any(fnmatch.fnmatch(filename, pattern) for pattern in EXCLUDED_PATHS) and filename.endswith('.js')] failed = False summary_messages = [] # Use Pyjsparser to parse a JS file as a Python dictionary. parser = pyjsparser.PyJsParser() for filename in files_to_check: with open(filename) as f: content = f.read() # Parse the body of the content as nodes. parsed_nodes = parser.parse(content)['body'] for parsed_node in parsed_nodes: # Check the type of the node. if parsed_node['type'] != 'ExpressionStatement': continue # Separate the expression part of the node. expression = parsed_node['expression'] # Check whether the expression belongs to a directive. expression_type_is_not_call = ( expression['type'] != 'CallExpression') if expression_type_is_not_call: continue expression_callee_type_is_not_member = ( expression['callee']['type'] != 'MemberExpression') if expression_callee_type_is_not_member: continue expression_callee_property_name_is_not_directive = ( expression['callee']['property']['name'] != 'directive') if expression_callee_property_name_is_not_directive: continue # Separate the arguments of the expression. arguments = expression['arguments'] # The first argument of the expression is the # name of the directive. if arguments[0]['type'] == 'Literal': directive_name = str(arguments[0]['value']) arguments = arguments[1:] for argument in arguments: # Check the type of an argument. if argument['type'] != 'ArrayExpression': continue # Separate out the elements for the argument. elements = argument['elements'] for element in elements: # Check the type of an element. if element['type'] != 'FunctionExpression': continue # Separate out the body of the element. body = element['body'] if body['type'] != 'BlockStatement': continue # Further separate the body elements from the body. body_elements = body['body'] for body_element in body_elements: # Check if the body element is a return statement. body_element_type_is_not_return = ( body_element['type'] != 'ReturnStatement') body_element_argument_type_is_not_object = ( body_element['argument']['type'] != ( 'ObjectExpression')) if (body_element_type_is_not_return or ( body_element_argument_type_is_not_object)): continue # Separate the properties of the return node. return_node_properties = ( body_element['argument']['properties']) # Loop over all the properties of the return node # to find out the scope key. for return_node_property in return_node_properties: # Check whether the property is scope. property_key_is_an_identifier = ( return_node_property['key']['type'] == ( 'Identifier')) property_key_name_is_scope = ( return_node_property['key']['name'] == ( 'scope')) if ( property_key_is_an_identifier and ( property_key_name_is_scope)): # Separate the scope value and # check if it is an Object Expression. # If it is not, then check for scope: true # and report the error message. scope_value = return_node_property['value'] if scope_value['type'] == 'Literal' and ( scope_value['value']): failed = True print ( 'Please ensure that %s ' 'directive in %s file ' 'does not have scope set to ' 'true.' % (directive_name, filename)) elif scope_value['type'] != 'ObjectExpression': # Check whether the directive has scope: {} # else report the error message. failed = True print ( 'Please ensure that %s directive ' 'in %s file has a scope: {}.' % ( directive_name, filename)) if failed: summary_message = '%s Directive scope check failed' % ( _MESSAGE_TYPE_FAILED) print summary_message summary_messages.append(summary_message) else: summary_message = '%s Directive scope check passed' % ( _MESSAGE_TYPE_SUCCESS) print summary_message summary_messages.append(summary_message) print '' print '----------------------------------------' print '' return summary_messages
def __init__(self): self.parser = pyjsparser.PyJsParser()
def pyjsparser_parse_fn(code): parser = pyjsparser.PyJsParser() return parser.parse(code)