def handle_endtag(self, tag): tag = tag.lower() if DEBUG: # pragma: no cover print "E: ", tag, self.xml_state if not self.xml_state: if "closing_tags" in self.reported or not self.strict: if DEBUG: print "Unstrict; extra closing tags ------" return self.err.warning( err_id=("markup", "handle_endtag", "extra_closing_tags"), warning="Markup parsing error", description="The markup file has more closing tags than it " "has opening tags.", filename=self.filename, line=self.line, context=self.context, tier=2) self.reported.add("closing_tags") if DEBUG: # pragma: no cover print "Too many closing tags ------" return elif "script" in self.xml_state[:-1]: # If we're in a script tag, nothing else matters. Just rush # everything possible into the xml buffer. self._save_to_buffer("</%s>" % tag) if DEBUG: print "Markup as text in script ------" return elif tag not in self.xml_state: # If the tag we're processing isn't on the stack, then # something is wrong. self.err.warning( err_id=("markup", "handle_endtag", "extra_closing_tags"), warning="Parse error: tag closed before opened", description=["Markup tags cannot be closed before they are " "opened. Perhaps you were just a little " "overzealous with forward-slashes?", 'Tag `%s` closed before it was opened' % tag], filename=self.filename, line=self.line, context=self.context, tier=2) if DEBUG: # pragma: no cover print "Tag closed before opened ------" return data_buffer = self.xml_buffer.pop() old_state = self.xml_state.pop() old_line = self.xml_line_stack.pop() # If the tag on the stack isn't what's being closed and it also # classifies as a self-closing tag, we just recursively close # down to the level of the tag we're actualy closing. if old_state != tag and old_state in SELF_CLOSING_TAGS: if DEBUG: print "Self closing tag cascading down ------" return self.handle_endtag(tag) # If this is an XML-derived language, everything must nest # properly. No overlapping tags. if (old_state != tag and self.extension[0] == 'x' and not self.strict): self.err.warning( err_id=("testcases_markup_markuptester", "handle_endtag", "invalid_nesting"), warning="Markup invalidly nested", description="It has been determined that the document " "invalidly nests its tags. This is not permitted " "in the specified document type.", filename=self.filename, line=self.line, context=self.context, tier=2) if DEBUG: # pragma: no cover print "Invalid markup nesting ------" data_buffer = data_buffer.strip() # Perform analysis on collected data. if data_buffer: if tag == "script": message_csp(err=self.err, filename=self.filename, line=self.line, column=None, context=self.context, violation_type="inline_script", severity="error") elif tag == "style": csstester.test_css_file(self.err, self.filename, data_buffer, old_line)
def handle_starttag(self, tag, attrs, self_closing=False): # Normalize! tag = tag.lower() # Be extra sure it's not a self-closing tag. if not self_closing: self_closing = tag in SELF_CLOSING_TAGS if DEBUG: # pragma: no cover print "S: ", self.xml_state, tag, self_closing attr_dict = dict([(a[0].lower(), a[1]) for a in attrs if a[1]]) if "style" in attr_dict: csstester.test_css_snippet(self.err, self.filename, attr_dict["style"], self.line) script_attributes = dict( (k, v) for k, v in attr_dict.iteritems() if k.startswith("on")) if script_attributes: if any(k in DOM_MUTATION_HANDLERS for k in script_attributes): self.err.error( err_id=("testcases_markup_markuptester", "handle_starttag", "dom_manipulation_handler"), error="DOM Mutation Events Prohibited", description="DOM mutation events are flagged because of " "their deprecated status, as well as thier " "extreme inefficiency. Consider using a " "different event.", filename=self.filename, line=self.line, context=self.context) message_csp(err=self.err, filename=self.filename, line=self.line, column=None, context=self.context, violation_type="script_attribute", severity="error") # When the dev forgets their <!-- --> on a script tag, bad # things happen. if "script" in self.xml_state and tag != "script": self._save_to_buffer("<" + tag + self._format_args(attrs) + ">") return elif (tag == "script" and ("type" not in attr_dict or any(a[0] == "type" and "javascript" in a[1].lower() for a in attrs))): # Inspect scripts which either have no type or have a type which # is JS. if "src" not in attr_dict: # CSP warnings for inline scripts message_csp(err=self.err, filename=self.filename, line=self.line, column=None, context=self.context, violation_type="inline_script", severity="error") elif not self._is_url_local(attr_dict.get("src", "")): # If there's a remote SRC, then that's a CSP violation. message_csp(err=self.err, filename=self.filename, line=self.line, column=None, context=self.context, violation_type="remote_script", severity="error") self.xml_state.append(tag) self.xml_line_stack.append(self.line) self.xml_buffer.append(u"")
def handle_starttag(self, tag, attrs, self_closing=False): # Normalize! tag = tag.lower() orig_tag = tag # Be extra sure it's not a self-closing tag. if not self_closing: self_closing = tag in SELF_CLOSING_TAGS if DEBUG: # pragma: no cover print "S: ", self.xml_state, tag, self_closing # Find CSS and JS attributes and handle their values like they # would otherwise be handled by the standard parser flow. for attr in attrs: attr_name, attr_value = attr[0].lower(), attr[1] # We don't care about valueless attributes. if attr_value is None: continue if attr_name == "style": csstester.test_css_snippet(self.err, self.filename, attr_value, self.line) elif attr_name.startswith("on"): # JS attribute # Warn about DOM mutation event handlers. if attr_name in DOM_MUTATION_HANDLERS: self.err.error( err_id=("testcases_markup_markuptester", "handle_starttag", "dom_manipulation_handler"), error="DOM Mutation Events Prohibited", description="DOM mutation events are flagged because " "of their deprecated status, as well as " "their extreme inefficiency. Consider " "using a different event.", filename=self.filename, line=self.line, context=self.context) message_csp(err=self.err, filename=self.filename, line=self.line, column=None, context=self.context, violation_type="script_attribute", severity="error") elif attr_name == "src" and tag == "script": if not self._is_url_local(attr_value): message_csp(err=self.err, filename=self.filename, line=self.line, column=None, context=self.context, violation_type="remote_script", severity="error") # When the dev forgets their <!-- --> on a script tag, bad # things happen. if "script" in self.xml_state and tag != "script": self._save_to_buffer("<" + tag + self._format_args(attrs) + ">") return self.xml_state.append(orig_tag) self.xml_line_stack.append(self.line) self.xml_buffer.append(unicode(""))
def handle_starttag(self, tag, attrs, self_closing=False): # Normalize! tag = tag.lower() # Be extra sure it's not a self-closing tag. if not self_closing: self_closing = tag in SELF_CLOSING_TAGS if DEBUG: # pragma: no cover print "S: ", self.xml_state, tag, self_closing attr_dict = dict([(a[0].lower(), a[1]) for a in attrs if a[1]]) if "style" in attr_dict: csstester.test_css_snippet( self.err, self.filename, attr_dict["style"], self.line) script_attributes = dict( (k, v) for k, v in attr_dict.iteritems() if k.startswith("on")) if script_attributes: if any(k in DOM_MUTATION_HANDLERS for k in script_attributes): self.err.error( err_id=("testcases_markup_markuptester", "handle_starttag", "dom_manipulation_handler"), error="DOM Mutation Events Prohibited", description="DOM mutation events are flagged because of " "their deprecated status, as well as thier " "extreme inefficiency. Consider using a " "different event.", filename=self.filename, line=self.line, context=self.context) message_csp(err=self.err, filename=self.filename, line=self.line, column=None, context=self.context, violation_type="script_attribute", severity="error") # When the dev forgets their <!-- --> on a script tag, bad # things happen. if "script" in self.xml_state and tag != "script": self._save_to_buffer("<" + tag + self._format_args(attrs) + ">") return elif (tag == "script" and ("type" not in attr_dict or any(a[0] == "type" and "javascript" in a[1].lower() for a in attrs))): # Inspect scripts which either have no type or have a type which # is JS. if "src" not in attr_dict: # CSP warnings for inline scripts message_csp(err=self.err, filename=self.filename, line=self.line, column=None, context=self.context, violation_type="inline_script", severity="error") elif not self._is_url_local(attr_dict.get("src", "")): # If there's a remote SRC, then that's a CSP violation. message_csp(err=self.err, filename=self.filename, line=self.line, column=None, context=self.context, violation_type="remote_script", severity="error") self.xml_state.append(tag) self.xml_line_stack.append(self.line) self.xml_buffer.append(u"")