def test_generate_report(self): num_clickables = { 'unexamined': 5, 'true': 10, 'false': 30 } form1 = FormField('form1') form1.add_input(InputField('username', '//*[@id="username"]', 'castman')) form1.add_input(InputField('password', '', 'p@ssw0rd')) form_list = [{ 'state': 1, 'form': form1, 'execution_seq': [Clickable('exe1', '//html/body/button[1]'), Clickable('exe2', '//html/body/button[1]')], 'clickable': [Clickable('btn1', '//html/body/button[1]'), Clickable('btn2', '//html/body/button[1]')] }] inv_violation = [{ 'state': 2, 'name': '{"name": "file-not-found"}', 'sequence': [Clickable('inv-btn1', '//html/body/button[1]'), Clickable('inv-btn2', '//html/body/button[1]')] }] Visualizer.generate_report( 'web', 'trace/example-app-4-webide', 'automata.json', 3, num_clickables, form_list, inv_violation, 9.987 )
def setUp(self): dom1 = ''' <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body>dom1</body> </html> ''' state = State(dom1) self.automata = Automata() self.automata.add_state(state) self.assertEqual(len(self.automata.get_states()), 1) self.assertEqual(self.automata.get_initial_state().get_id(), self.automata.get_current_state().get_id()) self.assertEqual(self.automata.get_current_state().get_id(), '0') # test adding and removing inputs and forms form1 = FormField('form1') form1.add_input(InputField('username', '//*[@id="username"]', 'castman')) form1.add_input(InputField('password', '', 'p@ssw0rd')) form1.add_input(InputField('password', '', 'p@ssw0rd')) self.assertEqual(len(form1.get_inputs()), 2) form1.remove_input(InputField('username', '//*[@id="username"]', 'castman')) self.assertEqual(len(form1.get_inputs()), 1) form2 = FormField('', '//*[@id="lst-ib"]') clickable = Clickable('', '//*[@id="btn1"]') clickable.add_form(form1) clickable.add_form(FormField('form1')) clickable.add_form(form2) self.assertEqual(len(clickable.get_forms()), 2) clickable.remove_form(FormField('', '//*[@id="lst-ib"]')) self.assertEqual(len(clickable.get_forms()), 1) # add the clickable into state 0 self.automata.get_current_state().add_clickable(clickable)
def __init__(self, fname=None, load_dom=False): self._states = [] self._edges = [] self._initial_state = None self._current_state = None if fname: assert os.path.isfile(fname) and os.path.exists(fname) t_start = time.time() with open(fname) as f: data = json.load(f) for state in data['state']: if load_dom: with open( os.path.join( os.path.dirname(os.path.realpath(fname)), state['dom_path']), 'r') as df: s = State(df.read()) else: s = State(state['id']) s.set_id(state['id']) for form in state['form']: f = FormField(form['id'], form['xpath']) for the_input in form['input']: f.add_input( InputField(the_input['id'], the_input['xpath'], the_input['type'], the_input['value'])) s.add_form(f) for clickable in state['clickable']: c = Clickable(clickable['id'], clickable['xpath'], clickable['tag']) for form in clickable['form']: f = s.get_form_by_id(form['id']) assert f c.add_form(f) s.add_clickable(c) self.add_state(s) for edge in data['edge']: from_state = self.get_state_by_id(edge['from']) to_state = self.get_state_by_id(edge['to']) clickable = from_state.get_clickable_by_id( edge['clickable']) assert from_state and to_state and clickable self.add_edge(from_state, to_state, clickable) logger.info('automata loaded. loading time: %f sec', time.time() - t_start)
def __init__(self, fname=None, load_dom=False): self._states = [] self._edges = [] self._initial_state = None self._current_state = None if fname: assert os.path.isfile(fname) and os.path.exists(fname) t_start = time.time() with open(fname) as f: data = json.load(f) for state in data['state']: if load_dom: with open(os.path.join(os.path.dirname(os.path.realpath(fname)), state['dom_path']), 'r') as df: s = State(df.read()) else: s = State(state['id']) s.set_id(state['id']) for form in state['form']: f = FormField(form['id'], form['xpath']) for the_input in form['input']: f.add_input(InputField(the_input['id'], the_input['xpath'], the_input['type'], the_input['value'])) s.add_form(f) for clickable in state['clickable']: c = Clickable(clickable['id'], clickable['xpath'], clickable['tag']) for form in clickable['form']: f = s.get_form_by_id(form['id']) assert f c.add_form(f) s.add_clickable(c) self.add_state(s) for edge in data['edge']: from_state = self.get_state_by_id(edge['from']) to_state = self.get_state_by_id(edge['to']) clickable = from_state.get_clickable_by_id(edge['clickable']) assert from_state and to_state and clickable self.add_edge(from_state, to_state, clickable) logger.info('automata loaded. loading time: %f sec', time.time() - t_start)
def get_clickables(cls, dom, prev_dom=None): # only return newly discovered clickables and forms, i.e. clickables not in prev_clickables prev_clickables = [] prev_forms = [] if prev_dom: prev_soup = BeautifulSoup(prev_dom, 'html.parser') for tag in cls._clickable_tags: if tag.get_attr(): for attr, value in tag.get_attr().items(): prev_clickables += prev_soup.find_all( tag.get_name(), attrs={attr: value}) else: prev_clickables += prev_soup.find_all(tag.get_name()) prev_forms = prev_soup.find_all('form') soup = BeautifulSoup(dom, 'html.parser') forms = soup.find_all('form') clickables = [] # clickables with forms and inputs attached for form in forms: if form in prev_forms: continue form_id = form.get('id') if not form_id: form_id = cls.serial_prefix + str(cls._serial_num) cls._serial_num += 1 f = FormField(form_id, cls._get_xpath(form)) for input_type in cls.input_types: inputs = form.find_all('input', attrs={'type': input_type}) for my_input in inputs: data_set = InlineDataBank.get_data(input_type) if data_set: value = random.choice(list(data_set)) else: value = ''.join( random.choice(string.lowercase) for i in xrange(8)) input_id = my_input.get('id') if not input_id: input_id = cls.serial_prefix + str(cls._serial_num) cls._serial_num += 1 f.add_input( InputField(input_id, cls._get_xpath(my_input), input_type, value)) for tag in cls._clickable_tags: if tag.get_attr(): for attr, value in tag.get_attr().items(): candidate_clickables = form.find_all( tag.get_name(), attrs={attr: value}) else: candidate_clickables = form.find_all(tag.get_name()) for candidate_clickable in candidate_clickables: if candidate_clickable in prev_clickables: continue clickable_id = candidate_clickable.get('id') if not clickable_id: clickable_id = cls.serial_prefix + str(cls._serial_num) cls._serial_num += 1 c = Clickable(clickable_id, cls._get_xpath(candidate_clickable), tag.get_name()) c.add_form(f) clickables.append(c) # other clickables for tag in cls._clickable_tags: if tag.get_attr(): for attr, value in tag.get_attr().items(): candidate_clickables = soup.find_all(tag.get_name(), attrs={attr: value}) else: candidate_clickables = soup.find_all(tag.get_name()) for candidate_clickable in candidate_clickables: #print candidate_clickable if candidate_clickable in prev_clickables: continue if not cls._is_duplicate(clickables, candidate_clickable): clickable_id = candidate_clickable.get('id') if not clickable_id: clickable_id = cls.serial_prefix + str(cls._serial_num) cls._serial_num += 1 clickables.append( Clickable(clickable_id, cls._get_xpath(candidate_clickable), tag.get_name())) return clickables
def get_clickables(cls, dom, prev_dom=None): # only return newly discovered clickables and forms, i.e. clickables not in prev_clickables prev_clickables = [] prev_forms = [] if prev_dom: prev_soup = BeautifulSoup(prev_dom, 'html.parser') for tag in cls._clickable_tags: if tag.get_attr(): for attr, value in tag.get_attr().items(): prev_clickables += prev_soup.find_all(tag.get_name(), attrs={attr: value}) else: prev_clickables += prev_soup.find_all(tag.get_name()) prev_forms = prev_soup.find_all('form') soup = BeautifulSoup(dom, 'html.parser') forms = soup.find_all('form') clickables = [] # clickables with forms and inputs attached for form in forms: if form in prev_forms: continue form_id = form.get('id') if not form_id: form_id = cls.serial_prefix + str(cls._serial_num) cls._serial_num += 1 f = FormField(form_id, cls._get_xpath(form)) for input_type in cls.input_types: inputs = form.find_all('input', attrs={'type': input_type}) for my_input in inputs: data_set = InlineDataBank.get_data(input_type) if data_set: value = random.choice(list(data_set)) else: value = ''.join(random.choice(string.lowercase) for i in xrange(8)) input_id = my_input.get('id') if not input_id: input_id = cls.serial_prefix + str(cls._serial_num) cls._serial_num += 1 f.add_input(InputField(input_id, cls._get_xpath(my_input), input_type, value)) for tag in cls._clickable_tags: if tag.get_attr(): for attr, value in tag.get_attr().items(): candidate_clickables = form.find_all(tag.get_name(), attrs={attr: value}) else: candidate_clickables = form.find_all(tag.get_name()) for candidate_clickable in candidate_clickables: if candidate_clickable in prev_clickables: continue clickable_id = candidate_clickable.get('id') if not clickable_id: clickable_id = cls.serial_prefix + str(cls._serial_num) cls._serial_num += 1 c = Clickable(clickable_id, cls._get_xpath(candidate_clickable), tag.get_name()) c.add_form(f) clickables.append(c) # other clickables for tag in cls._clickable_tags: if tag.get_attr(): for attr, value in tag.get_attr().items(): candidate_clickables = soup.find_all(tag.get_name(), attrs={attr: value}) else: candidate_clickables = soup.find_all(tag.get_name()) for candidate_clickable in candidate_clickables: #print candidate_clickable if candidate_clickable in prev_clickables: continue if not cls._is_duplicate(clickables, candidate_clickable): clickable_id = candidate_clickable.get('id') if not clickable_id: clickable_id = cls.serial_prefix + str(cls._serial_num) cls._serial_num += 1 clickables.append(Clickable(clickable_id, cls._get_xpath(candidate_clickable), tag.get_name())) return clickables