def test_scripting_snippet(): "Asserts that JS snippets are treated equally" err = ErrorBundle() err.supported_versions = {} scripting.test_js_snippet(err, "alert(1 + 1 == 2)", "bar.zap") assert not err.failed() err = ErrorBundle() err.supported_versions = {} scripting.test_js_snippet(err, "eval('foo');", "bar.zap") assert err.failed()
def test_scripting_snippet(): 'Assert that JS snippets are treated equally.' err = ErrorBundle() err.supported_versions = {} scripting.test_js_snippet(err, 'alert(1 + 1 == 2)', 'bar.zap') assert not err.failed() err = ErrorBundle() err.supported_versions = {} scripting.test_js_snippet(err, "eval('foo');", 'bar.zap') assert err.failed()
def handle_endtag(self, tag): tag = tag.lower() if tag == "xul:script": tag = "script" 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(("testcases_markup_markuptester", "handle_endtag", "extra_closing_tags"), "Markup parsing error", "The markup file has more closing tags than it " "has opening tags.", 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("</" + 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(("testcases_markup_markuptester", "handle_endtag", "extra_closing_tags"), "Parse error: tag closed before opened", ["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], 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(("testcases_markup_markuptester", "handle_endtag", "invalid_nesting"), "Markup invalidly nested", "It has been determined that the document " "invalidly nests its tags. This is not permitted " "in the specified document type.", 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": scripting.test_js_snippet(err=self.err, data=data_buffer, filename=self.filename, line=old_line, context=self.context) 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() # XUL scripts are identical to normal scripts. Treat them the same. if tag == "xul:script": tag = "script" 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 # A fictional tag for testing purposes. if tag == "xbannedxtestx": self.err.error(("testcases_markup_markuptester", "handle_starttag", "banned_element"), "Banned element", "A banned element was detected", self.filename, line=self.line, context=self.context) # Test for banned XBL in themes. if self.err.detected_type == PACKAGE_THEME: if tag.startswith("xbl:"): self.xbl = True tag = tag[4:] # Find XBL elements. if self.xbl: if tag in UNSAFE_THEME_XBL: self.err.warning( err_id=("testcases_markup_markuptester", "handle_starttag", "unsafe_theme_xbl_element"), warning="Banned XBL element in theme.", description=["Certain XBL elements are disallowed in " "themes.", "Element: <xbl:%s>" % tag], filename=self.filename, line=self.line, context=self.context) elif (tag == "property" and any(a[0] in (u"onset", u"onget") for a in attrs)): self.err.warning( err_id=("testcases_markup_markuptester", "handle_starttag", "theme_xbl_property"), warning="Themes are not allowed to use XBL properties", description="XBL properties cannot be used in themes.", filename=self.filename, line=self.line, context=self.context) # Test for banned elements in language pack and theme markup. if self.err.detected_type in (PACKAGE_LANGPACK, PACKAGE_THEME): if (tag in UNSAFE_TAGS or (self.err.detected_type == PACKAGE_THEME and tag in UNSAFE_THEME_TAGS)): self.err.warning(("testcases_markup_markuptester", "handle_starttag", "unsafe_langpack_theme"), "Unsafe tag for add-on type", ["A tag in your markup has been marked as " "being potentially unsafe. Consider " "alternate means of accomplishing what the " "code executed by this tag performs.", 'Tag "%s" is disallowed.' % tag], self.filename, line=self.line, context=self.context) if DEBUG: # pragma: no cover print "Unsafe Tag ------" # Make sure all src/href attributes are local for attr in attrs: if attr[0].lower() in ("src", "href") and \ not self._is_url_local(attr[1].lower()): self.err.warning(("testcases_markup_markuptester", "handle_starttag", "remote_src_href"), "src/href attributes must be local.", "Language packs require that all src and " "href attributes are relative URLs.", self.filename, line=self.line, context=self.context) self.err.reject = True if tag in ("iframe", "browser") and self.extension == "xul": # Bork if XUL iframe has no type attribute type_ = None src = None for attr in attrs: attr_name = attr[0].lower() if attr_name == "type": type_ = attr[1].lower() elif attr_name == "src": src = attr[1].lower() # We say it's true by default to catch elements that are # type="chrome" without an src="" attribute. remote_src = True if isinstance(src, types.StringTypes): remote_src = not self._is_url_local(src) if (type_ and not (type_ in SAFE_IFRAME_TYPES or not remote_src)): self.err.warning(("testcases_markup_markuptester", "handle_starttag", "iframe_type_unsafe"), "iframe/browser missing 'type' attribute", "All iframe and browser elements must have " "either a valid `type` attribute or a `src` " "attribute that points to a local file.", self.filename, line=self.line, context=self.context) elif ((not type_ or type_ not in SAFE_IFRAME_TYPES) and remote_src): self.err.warning(("testcases_markup_markuptester", "handle_starttag", "iframe_type_unsafe"), "Typeless iframes/browsers must be local.", "iframe and browser elements that lack a type " "attribute must always have src attributes " "that reference local resources.", self.filename, line=self.line, context=self.context) elif tag == "script" and self.extension == "xul": # Per the Addon Validator Spec (v2), scripts in XUL # must not be remote. src = None for attr in attrs: if attr[0].lower() == "src": src = attr[1].lower() if src and not self._is_url_local(src): self.err.warning(("testcases_markup_markuptester", "handle_starttag", "banned_remote_scripts"), "Scripts must not be remote in XUL", "In XUL, <script> tags must not be referenced " "to script files that are hosted remotely.", self.filename, line=self.line, context=self.context) # 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] if (attr_name == "xmlns:xbl" and attr_value == "http://www.mozilla.org/xbl"): self.xbl = True if (self.err.detected_type == PACKAGE_THEME and attr_value.startswith(("data:", "javascript:"))): self.err.warning( err_id=("testcases_markup_markuptester", "handle_starttag", "theme_attr_prefix"), warning="Attribute contains banned prefix", description=["A mark element's attribute contains a " "prefix which is not allowed in themes.", "Attribute: %s" % attr_name], filename=self.filename, line=self.line, context=self.context) 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.warning( err_id=("testcases_markup_markuptester", "handle_starttag", "dom_manipulation_handler"), warning="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) scripting.test_js_snippet(err=self.err, data=attr_value, filename=self.filename, line=self.line, context=self.context) elif (self.extension == "xul" and attr_name in ("insertbefore", "insertafter") and any((id in attr[1]) for id in ("menu_pageSource", "menu_pageinspect", "javascriptConsole", "webConsole"))): self.err.notice( err_id=("testcases_markup_markuptester", "handle_starttag", "incompatible_menu_items"), notice="Menu item has been moved", description="Your add-on has an overlay that uses the " "insertbefore or insertafter attribute " "pointing to menuitems that have been moved " "to a different menu item. Your overlay items " "may appear in unexpected locations because " "of this. See " "https://bugzilla.mozilla.org/show_bug.cgi?id=653221" " for more information.", filename=self.filename, line=self.line, context=self.context, for_appversions={ "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}": version_range("firefox", "6.0a1", "7.0a1")}, compatibility_type="warning") # 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_endtag(self, tag): tag = tag.lower() if tag == "xul:script": tag = "script" if tag == "script" and len(self.xml_buffer[-1]) > 1000: self.err.warning(("markup", "complex_script"), "Long inline script", "Please store complex scripts in .js files " "rather than inline script nodes.", self.filename, line=self.line, context=self.context, tier=2) 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(("markup", "endtag", "extra_closing_tags"), "Markup parsing error", "The markup file has more closing tags than it " "has opening tags.", 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("</" + 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( ("markup", "endtag", "extra_closing_tags"), "Parse error: tag closed before opened", [ "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 ], 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() script_type = True if old_state == "script": script_type = self.xml_state_scripts.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(("markup", "endtag", "invalid_nesting"), "Markup invalidly nested", "It has been determined that the document " "invalidly nests its tags. This is not permitted " "in the specified document type.", 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" and not script_type: scripting.test_js_snippet(err=self.err, data=data_buffer, filename=self.filename, line=old_line, context=self.context) 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() # XUL scripts are identical to normal scripts. Treat them the same. if tag == "xul:script": tag = "script" 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 # A fictional tag for testing purposes. if tag == "xbannedxtestx": self.err.error(err_id=("markup", "starttag", "banned_element"), error="Banned markup element", description="A banned markup element was found.", filename=self.filename, line=self.line, context=self.context) # Test for banned XBL in themes. if self.err.detected_type == PACKAGE_THEME: if tag.startswith("xbl:"): self.xbl = True tag = tag[4:] # Find XBL elements. if self.xbl: if tag in UNSAFE_THEME_XBL: self.err.warning( err_id=("markup", "starttag", "unsafe_theme_xbl_element"), warning="Banned XBL element in theme.", description=[ "Certain XBL elements are disallowed in " "full themes.", "Element: <xbl:%s>" % tag ], filename=self.filename, line=self.line, context=self.context) elif (tag == "property" and any(a[0] in (u"onset", u"onget") for a in attrs)): self.err.warning( err_id=("markup", "starttag", "theme_xbl_property"), warning="Themes are not allowed to use XBL properties", description="XBL properties cannot be used in themes.", filename=self.filename, line=self.line, context=self.context) # Test for banned elements in language pack and theme markup. if self.err.detected_type in (PACKAGE_LANGPACK, PACKAGE_THEME): if (tag in UNSAFE_TAGS or (self.err.detected_type == PACKAGE_THEME and tag in UNSAFE_THEME_TAGS)): self.err.warning( err_id=("markup", "starttag", "unsafe_langpack_theme"), warning="Unsafe tag for add-on type", description=[ "A tag in your markup has been marked as " "being potentially unsafe. Consider " "alternate means of accomplishing what the " "code executed by this tag performs.", 'Tag "%s" is disallowed.' % tag ], filename=self.filename, line=self.line, context=self.context) # Make sure all src/href attributes are local if any(not self._is_url_local(attr[1]) for attr in attrs if attr[0] in ("src", "href")): self.err.warning( err_id=("markup", "starttag", "remote_src_href"), warning="`src`/`href` attributes must be local.", description="Full Themes and language packs may not " "reference remote resources.", filename=self.filename, line=self.line, context=self.context) if tag == "prefwindow": # Flag <prefwindow> elements without IDs. if not any((key == "id") for key, val in attrs): self.err.warning( err_id=("markup", "starttag", "prefwindow_id"), warning="`<prefwindow>` elements must have IDs.", description="`<prefwindow>` elements without `id` " "attributes cause errors to be reported " "in the error console and prevent " "persistence of certain properties of the " "dialog.", filename=self.filename, line=self.line, context=self.context) elif tag in ("iframe", "browser") and self.extension == "xul": # Bork if XUL iframe has no type attribute type_ = None src = None for attr in attrs: attr_name = attr[0].lower() if attr_name == "type": type_ = attr[1].lower() elif attr_name == "src": src = attr[1].lower() # We say it's true by default to catch elements that are # type="chrome" without an src="" attribute. remote_src = True if isinstance(src, types.StringTypes): remote_src = not self._is_url_local(src) if (type_ and not (type_ in SAFE_IFRAME_TYPES or not remote_src)): self.err.warning(("markup", "starttag", "iframe_type_unsafe"), "iframe/browser missing 'type' attribute", "All iframe and browser elements must have " "either a valid `type` attribute or a `src` " "attribute that points to a local file.", self.filename, line=self.line, context=self.context) elif ((not type_ or type_ not in SAFE_IFRAME_TYPES) and remote_src): self.err.warning( ("markup", "starttag", "iframe_type_unsafe"), "Typeless iframes/browsers must be local.", "iframe and browser elements that lack a type " "attribute must always have src attributes " "that reference local resources.", self.filename, line=self.line, context=self.context) elif tag == "script": # Per the Addon Validator Spec (v2), scripts # must not be remote. src = None for attr in attrs: if attr[0].lower() == "src": src = attr[1].lower() break if src: if not self._is_url_local(src): self.err.warning( err_id=("markup", "starttag", "banned_remote_scripts"), warning="Scripts must not be remote", description="<script> tags must not be referenced to " "script files that are hosted remotely.", filename=self.filename, line=self.line, context=self.context) else: self.found_scripts.add(src) # 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 == "xmlns:xbl" and attr_value == "http://www.mozilla.org/xbl"): self.xbl = True # Test that an absolute URI isn't referenced in Jetpack 1.4. if (self.is_jetpack and attr_value.startswith("resource://") and "-data/" in attr_value): self.err.warning( err_id=("markup", "starttag", "jetpack_abs_uri"), warning="Absolute URI referenced in Jetpack 1.4", description=[ "As of Jetpack 1.4, absolute URIs are no " "longer allowed within add-ons.", "See %s for more information." % JETPACK_URI_URL ], filename=self.filename, line=self.line, context=self.context, compatibility_type="error") if (self.err.detected_type == PACKAGE_THEME and attr_value.startswith(("data:", "javascript:"))): self.err.warning(err_id=("markup", "starttag", "theme_attr_prefix"), warning="Attribute contains banned prefix", description=[ "A mark element's attribute contains a " "prefix which is not allowed in full " "themes.", "Attribute: %s" % attr_name ], filename=self.filename, line=self.line, context=self.context) 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.warning( err_id=("markup", "starttag", "dom_manipulation_handler"), warning="DOM Mutation Events Prohibited", description="DOM mutation events are deprecated and " "have severe performance implications. " "Please use mutation observers instead: " "https://developer.mozilla.org/docs/Web/" "API/MutationObserver", filename=self.filename, line=self.line, context=self.context) scripting.test_js_snippet(err=self.err, data=attr_value, filename=self.filename, line=self.line, context=self.context) elif (self.extension == "xul" and attr_name in ("insertbefore", "insertafter") and any( (id in attr_value) for id in ("menu_pageSource", "menu_pageinspect", "javascriptConsole", "webConsole"))): self.err.notice( err_id=("markup", "starttag", "incompatible_menu_items"), notice="Menu item has been moved", description="Your add-on has an overlay that uses the " "insertbefore or insertafter attribute " "pointing to menuitems that have been moved " "to a different menu item. Your overlay items " "may appear in unexpected locations because " "of this. See https://bugzil.lz/653221 " "for more information.", filename=self.filename, line=self.line, context=self.context, for_appversions=FX6_DEFINITION, compatibility_type="warning") # Test for generic IDs if attr_name == "id" and attr_value in GENERIC_IDS: self.err.warning( err_id=("markup", "starttag", "generic_ids"), warning="Overlay contains generically-named IDs", description="An overlay is using a generically-named ID " "that could cause compatibility problems with " "other add-ons. Add-ons must namespace all IDs " "in the overlay, in the same way that " "JavaScript objects must be namespaced.", filename=self.filename, line=self.line, context=self.context) if tag == "script": self.xml_state_scripts.append( any((x[0] == "type" and "javascript" not in x[1]) for x in attrs)) # 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() # XUL scripts are identical to normal scripts. Treat them the same. if tag == 'xul:script': tag = 'script' 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 # A fictional tag for testing purposes. if tag == 'xbannedxtestx': self.err.error(err_id=('markup', 'starttag', 'banned_element'), error='Banned markup element', description='A banned markup element was found.', filename=self.filename, line=self.line, context=self.context) # Test for banned XBL in themes. if self.err.detected_type == PACKAGE_THEME: if tag.startswith('xbl:'): self.xbl = True tag = tag[4:] # Find XBL elements. if self.xbl: if tag in UNSAFE_THEME_XBL: self.err.warning( err_id=('markup', 'starttag', 'unsafe_theme_xbl_element'), warning='Banned XBL element in theme.', description=('Certain XBL elements are disallowed in ' 'full themes.', 'Element: <xbl:%s>' % tag), filename=self.filename, line=self.line, context=self.context) elif (tag == 'property' and any(a[0] in (u'onset', u'onget') for a in attrs)): self.err.warning( err_id=('markup', 'starttag', 'theme_xbl_property'), warning='Themes are not allowed to use XBL properties', description='XBL properties cannot be used in themes.', filename=self.filename, line=self.line, context=self.context) # Test for banned elements in language pack and theme markup. if self.err.detected_type in (PACKAGE_LANGPACK, PACKAGE_THEME): if (tag in UNSAFE_TAGS or (self.err.detected_type == PACKAGE_THEME and tag in UNSAFE_THEME_TAGS)): self.err.warning( err_id=('markup', 'starttag', 'unsafe_langpack_theme'), warning='Unsafe tag for add-on type', description=('A tag in your markup has been marked as ' 'being potentially unsafe. Consider ' 'alternate means of accomplishing what the ' 'code executed by this tag performs.', 'Tag "%s" is disallowed.' % tag), filename=self.filename, line=self.line, context=self.context) # Make sure all src/href attributes are local if any(not self._is_url_local(attr[1]) for attr in attrs if attr[0] in ('src', 'href')): self.err.warning( err_id=('markup', 'starttag', 'remote_src_href'), warning='`src`/`href` attributes must be local.', description='Full Themes and language packs may not ' 'reference remote resources.', filename=self.filename, line=self.line, context=self.context) if tag == 'prefwindow': # Flag <prefwindow> elements without IDs. if not any((key == 'id') for key, val in attrs): self.err.warning( err_id=('markup', 'starttag', 'prefwindow_id'), warning='`<prefwindow>` elements must have IDs.', description='`<prefwindow>` elements without `id` ' 'attributes cause errors to be reported ' 'in the error console and prevent ' 'persistence of certain properties of the ' 'dialog.', filename=self.filename, line=self.line, context=self.context) elif tag in ('iframe', 'browser') and self.extension == 'xul': # Bork if XUL iframe has no type attribute type_ = None src = None for attr in attrs: attr_name = attr[0].lower() if attr_name == 'type': type_ = attr[1].lower() elif attr_name == 'src': src = attr[1].lower() # We say it's true by default to catch elements that are # type="chrome" without an src="" attribute. remote_src = True if isinstance(src, types.StringTypes): remote_src = not self._is_url_local(src) if (type_ and not (type_ in SAFE_IFRAME_TYPES or not remote_src)): self.err.warning( ('markup', 'starttag', 'iframe_type_unsafe'), 'iframe/browser missing or unsafe `type` ' 'attribute', 'All iframe and browser elements must have ' 'either a valid and safe `type` attribute or a' '`src` attribute that points to a local file.', self.filename, line=self.line, context=self.context) elif ((not type_ or type_ not in SAFE_IFRAME_TYPES) and remote_src): self.err.warning( ('markup', 'starttag', 'iframe_type_unsafe'), 'Typeless iframes/browsers must be local.', 'iframe and browser elements that lack a type ' 'attribute must always have src attributes ' 'that reference local resources.', self.filename, line=self.line, context=self.context) elif tag == 'script': # Per the Addon Validator Spec (v2), scripts # must not be remote. src = None for attr in attrs: if attr[0].lower() == 'src': src = attr[1].lower() break if src: if not self._is_url_local(src): self.err.warning( err_id=('markup', 'starttag', 'banned_remote_scripts'), warning='Scripts must not be remote', description='<script> tags must not be referenced to ' 'script files that are hosted remotely.', signing_help='Please do not attempt to load remote ' 'scripts into any privileged contexts. ' 'If you cannot avoid using remote ' 'scripts, please consider loading a ' 'remote document into an iframe, and ' 'allow that document to load the ' 'remote scripts that you need.', signing_severity='high', filename=self.filename, line=self.line, context=self.context) else: self.found_scripts.add(src) # 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 == 'xmlns:xbl' and attr_value == 'http://www.mozilla.org/xbl'): self.xbl = True # Test that an absolute URI isn't referenced in Jetpack 1.4. if (self.is_jetpack and attr_value.startswith('resource://') and '-data/' in attr_value): self.err.warning( err_id=('markup', 'starttag', 'jetpack_abs_uri'), warning='Absolute URI referenced in Jetpack 1.4', description=('As of Jetpack 1.4, absolute URIs are no ' 'longer allowed within add-ons.', 'See %s for more information.' % JETPACK_URI_URL), filename=self.filename, line=self.line, context=self.context, compatibility_type='error') if (self.err.detected_type == PACKAGE_THEME and attr_value.startswith(('data:', 'javascript:'))): self.err.warning( err_id=('markup', 'starttag', 'theme_attr_prefix'), warning='Attribute contains banned prefix', description=("A mark element's attribute contains a " 'prefix which is not allowed in full ' 'themes.', 'Attribute: %s' % attr_name), filename=self.filename, line=self.line, context=self.context) 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.warning( err_id=('markup', 'starttag', 'dom_manipulation_handler'), warning='DOM Mutation Events Prohibited', description='DOM mutation events are deprecated and ' 'have severe performance implications. ' 'Please use mutation observers instead: ' 'https://developer.mozilla.org/docs/Web/' 'API/MutationObserver', filename=self.filename, line=self.line, context=self.context) scripting.test_js_snippet(err=self.err, data=attr_value, filename=self.filename, line=self.line, context=self.context) # Test for generic IDs if attr_name == 'id' and attr_value in GENERIC_IDS: self.err.warning( err_id=('markup', 'starttag', 'generic_ids'), warning='Overlay contains generically-named IDs', description='An overlay is using a generically-named ID ' 'that could cause compatibility problems with ' 'other add-ons. Add-ons must namespace all IDs ' 'in the overlay, in the same way that ' 'JavaScript objects must be namespaced.', filename=self.filename, line=self.line, context=self.context) if tag == 'script': self.xml_state_scripts.append( any((x[0] == 'type' and 'javascript' not in x[1]) for x in attrs)) # 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() # XUL scripts are identical to normal scripts. Treat them the same. if tag == "xul:script": tag = "script" 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 # A fictional tag for testing purposes. if tag == "xbannedxtestx": self.err.error( err_id=("markup", "starttag", "banned_element"), error="Banned markup element", description="A banned markup element was found.", filename=self.filename, line=self.line, context=self.context) # Test for banned XBL in themes. if self.err.detected_type == PACKAGE_THEME: if tag.startswith("xbl:"): self.xbl = True tag = tag[4:] # Find XBL elements. if self.xbl: if tag in UNSAFE_THEME_XBL: self.err.warning( err_id=("markup", "starttag", "unsafe_theme_xbl_element"), warning="Banned XBL element in theme.", description=["Certain XBL elements are disallowed in " "full themes.", "Element: <xbl:%s>" % tag], filename=self.filename, line=self.line, context=self.context) elif (tag == "property" and any(a[0] in (u"onset", u"onget") for a in attrs)): self.err.warning( err_id=("markup", "starttag", "theme_xbl_property"), warning="Themes are not allowed to use XBL properties", description="XBL properties cannot be used in themes.", filename=self.filename, line=self.line, context=self.context) # Test for banned elements in language pack and theme markup. if self.err.detected_type in (PACKAGE_LANGPACK, PACKAGE_THEME): if (tag in UNSAFE_TAGS or (self.err.detected_type == PACKAGE_THEME and tag in UNSAFE_THEME_TAGS)): self.err.warning( err_id=("markup", "starttag", "unsafe_langpack_theme"), warning="Unsafe tag for add-on type", description=["A tag in your markup has been marked as " "being potentially unsafe. Consider " "alternate means of accomplishing what the " "code executed by this tag performs.", 'Tag "%s" is disallowed.' % tag], filename=self.filename, line=self.line, context=self.context) # Make sure all src/href attributes are local if any(not self._is_url_local(attr[1]) for attr in attrs if attr[0] in ("src", "href")): self.err.warning( err_id=("markup", "starttag", "remote_src_href"), warning="`src`/`href` attributes must be local.", description="Full Themes and language packs may not " "reference remote resources.", filename=self.filename, line=self.line, context=self.context) if tag == "prefwindow": # Flag <prefwindow> elements without IDs. if not any((key == "id") for key, val in attrs): self.err.warning( err_id=("markup", "starttag", "prefwindow_id"), warning="`<prefwindow>` elements must have IDs.", description="`<prefwindow>` elements without `id` " "attributes cause errors to be reported " "in the error console and prevent " "persistence of certain properties of the " "dialog.", filename=self.filename, line=self.line, context=self.context) elif tag in ("iframe", "browser") and self.extension == "xul": # Bork if XUL iframe has no type attribute type_ = None src = None for attr in attrs: attr_name = attr[0].lower() if attr_name == "type": type_ = attr[1].lower() elif attr_name == "src": src = attr[1].lower() # We say it's true by default to catch elements that are # type="chrome" without an src="" attribute. remote_src = True if isinstance(src, types.StringTypes): remote_src = not self._is_url_local(src) if (type_ and not (type_ in SAFE_IFRAME_TYPES or not remote_src)): self.err.warning(("markup", "starttag", "iframe_type_unsafe"), "iframe/browser missing 'type' attribute", "All iframe and browser elements must have " "either a valid `type` attribute or a `src` " "attribute that points to a local file.", self.filename, line=self.line, context=self.context) elif ((not type_ or type_ not in SAFE_IFRAME_TYPES) and remote_src): self.err.warning(("markup", "starttag", "iframe_type_unsafe"), "Typeless iframes/browsers must be local.", "iframe and browser elements that lack a type " "attribute must always have src attributes " "that reference local resources.", self.filename, line=self.line, context=self.context) elif tag == "script" and self.extension == "xul": # Per the Addon Validator Spec (v2), scripts in XUL # must not be remote. src = None for attr in attrs: if attr[0].lower() == "src": src = attr[1].lower() break if src: if not self._is_url_local(src): self.err.warning( err_id=("markup", "starttag", "banned_remote_scripts"), warning="Scripts must not be remote in XUL", description="In XUL, <script> tags must not be " "referenced to script files that are " "hosted remotely.", filename=self.filename, line=self.line, context=self.context) else: self.found_scripts.add(src) # 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 == "xmlns:xbl" and attr_value == "http://www.mozilla.org/xbl"): self.xbl = True # Test that an absolute URI isn't referenced in Jetpack 1.4. if (self.is_jetpack and attr_value.startswith("resource://") and "-data/" in attr_value): self.err.warning( err_id=("markup", "starttag", "jetpack_abs_uri"), warning="Absolute URI referenced in Jetpack 1.4", description=["As of Jetpack 1.4, absolute URIs are no " "longer allowed within add-ons.", "See %s for more information." % JETPACK_URI_URL], filename=self.filename, line=self.line, context=self.context, compatibility_type="error") if (self.err.detected_type == PACKAGE_THEME and attr_value.startswith(("data:", "javascript:"))): self.err.warning( err_id=("markup", "starttag", "theme_attr_prefix"), warning="Attribute contains banned prefix", description=["A mark element's attribute contains a " "prefix which is not allowed in full " "themes.", "Attribute: %s" % attr_name], filename=self.filename, line=self.line, context=self.context) 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.warning( err_id=("markup", "starttag", "dom_manipulation_handler"), warning="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) scripting.test_js_snippet( err=self.err, data=attr_value, filename=self.filename, line=self.line, context=self.context) elif (self.extension == "xul" and attr_name in ("insertbefore", "insertafter") and any((id in attr_value) for id in ("menu_pageSource", "menu_pageinspect", "javascriptConsole", "webConsole"))): self.err.notice( err_id=("markup", "starttag", "incompatible_menu_items"), notice="Menu item has been moved", description="Your add-on has an overlay that uses the " "insertbefore or insertafter attribute " "pointing to menuitems that have been moved " "to a different menu item. Your overlay items " "may appear in unexpected locations because " "of this. See " "https://bugzilla.mozilla.org/show_bug.cgi?id=653221" " for more information.", filename=self.filename, line=self.line, context=self.context, for_appversions=FX6_DEFINITION, compatibility_type="warning") # Test for generic IDs if attr_name == "id" and attr_value in GENERIC_IDS: self.err.warning( err_id=("markup", "starttag", "generic_ids"), warning="Overlay contains generically-named IDs", description="An overlay is using a generically-named ID " "that could cause compatibility problems with " "other add-ons. Add-ons must namespace all IDs " "in the overlay, in the same way that " "JavaScript objects must be namespaced.", filename=self.filename, line=self.line, context=self.context) if tag == "script": self.xml_state_scripts.append(any( (x[0] == "type" and "javascript" not in x[1]) for x in attrs)) # 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() # XUL scripts are identical to normal scripts. Treat them the same. if tag == 'xul:script': tag = 'script' 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 # A fictional tag for testing purposes. if tag == 'xbannedxtestx': self.err.error( err_id=('markup', 'starttag', 'banned_element'), error='Banned markup element', description='A banned markup element was found.', filename=self.filename, line=self.line, context=self.context) # Test for banned XBL in themes. if self.err.detected_type == PACKAGE_THEME: if tag.startswith('xbl:'): self.xbl = True tag = tag[4:] # Find XBL elements. if self.xbl: if tag in UNSAFE_THEME_XBL: self.err.warning( err_id=('markup', 'starttag', 'unsafe_theme_xbl_element'), warning='Banned XBL element in theme.', description=('Certain XBL elements are disallowed in ' 'full themes.', 'Element: <xbl:%s>' % tag), filename=self.filename, line=self.line, context=self.context) elif (tag == 'property' and any(a[0] in (u'onset', u'onget') for a in attrs)): self.err.warning( err_id=('markup', 'starttag', 'theme_xbl_property'), warning='Themes are not allowed to use XBL properties', description='XBL properties cannot be used in themes.', filename=self.filename, line=self.line, context=self.context) # Test for banned elements in language pack and theme markup. if self.err.detected_type in (PACKAGE_LANGPACK, PACKAGE_THEME): if (tag in UNSAFE_TAGS or (self.err.detected_type == PACKAGE_THEME and tag in UNSAFE_THEME_TAGS)): self.err.warning( err_id=('markup', 'starttag', 'unsafe_langpack_theme'), warning='Unsafe tag for add-on type', description=('A tag in your markup has been marked as ' 'being potentially unsafe. Consider ' 'alternate means of accomplishing what the ' 'code executed by this tag performs.', 'Tag "%s" is disallowed.' % tag), filename=self.filename, line=self.line, context=self.context) # Make sure all src/href attributes are local if any(not self._is_url_local(attr[1]) for attr in attrs if attr[0] in ('src', 'href')): self.err.warning( err_id=('markup', 'starttag', 'remote_src_href'), warning='`src`/`href` attributes must be local.', description='Full Themes and language packs may not ' 'reference remote resources.', filename=self.filename, line=self.line, context=self.context) if tag == 'prefwindow': # Flag <prefwindow> elements without IDs. if not any((key == 'id') for key, val, pos in attrs): self.err.warning( err_id=('markup', 'starttag', 'prefwindow_id'), warning='`<prefwindow>` elements must have IDs.', description='`<prefwindow>` elements without `id` ' 'attributes cause errors to be reported ' 'in the error console and prevent ' 'persistence of certain properties of the ' 'dialog.', filename=self.filename, line=self.line, context=self.context) elif tag in ('iframe', 'browser') and self.extension == 'xul': # Bork if XUL iframe has no type attribute type_ = None src = None for attr in attrs: attr_name = attr[0].lower() if attr_name == 'type': type_ = attr[1].lower() elif attr_name == 'src': src = attr[1].lower() # We say it's true by default to catch elements that are # type="chrome" without an src="" attribute. remote_src = True if isinstance(src, types.StringTypes): remote_src = not self._is_url_local(src) if (type_ and not (type_ in SAFE_IFRAME_TYPES or not remote_src)): self.err.warning(('markup', 'starttag', 'iframe_type_unsafe'), "iframe/browser missing 'type' attribute", 'All iframe and browser elements must have ' 'either a valid `type` attribute or a `src` ' 'attribute that points to a local file.', self.filename, line=self.line, context=self.context) elif ((not type_ or type_ not in SAFE_IFRAME_TYPES) and remote_src): self.err.warning(('markup', 'starttag', 'iframe_type_unsafe'), 'Typeless iframes/browsers must be local.', 'iframe and browser elements that lack a ' 'type attribute must always have src ' 'attributes that reference local resources.', self.filename, line=self.line, context=self.context) elif tag == 'script': # Per the Addon Validator Spec (v2), scripts # must not be remote. src = None for attr in attrs: if attr[0].lower() == 'src': src = attr[1].lower() break if src: if not self._is_url_local(src): self.err.warning( err_id=('markup', 'starttag', 'banned_remote_scripts'), warning='Scripts must not be remote', description='<script> tags must not be referenced to ' 'script files that are hosted remotely.', signing_help='Please do not attempt to load remote ' 'scripts into any privileged contexts. ' 'If you cannot avoid using remote ' 'scripts, please consider loading a ' 'remote document into an iframe, and ' 'allow that document to load the ' 'remote scripts that you need.', signing_severity='high', filename=self.filename, line=self.line, context=self.context) else: self.err.add_script_load(self.filename, src) self.found_scripts.add(src) # 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] position = attr[2] # We don't care about valueless attributes. if attr_value is None: continue if (attr_name == 'xmlns:xbl' and attr_value == 'http://www.mozilla.org/xbl'): self.xbl = True if (self.err.detected_type == PACKAGE_THEME and attr_value.startswith(('data:', 'javascript:'))): self.err.warning( err_id=('markup', 'starttag', 'theme_attr_prefix'), warning='Attribute contains banned prefix', description=("A mark element's attribute contains a " 'prefix which is not allowed in full ' 'themes.', 'Attribute: %s' % attr_name), filename=self.filename, line=self.line, context=self.context) 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.warning( err_id=('markup', 'starttag', 'dom_manipulation_handler'), warning='DOM Mutation Events Prohibited', description='DOM mutation events are deprecated and ' 'have severe performance implications. ' 'Please use mutation observers instead: ' 'https://developer.mozilla.org/docs/Web/' 'API/MutationObserver', filename=self.filename, line=self.line, context=self.context) self.err.add_script_load(self.filename, self.filename) scripting.test_js_snippet( err=self.err, data=attr_value, filename=self.filename, line=position[0], column=position[1], context=self.context) # Test for generic IDs if attr_name == 'id' and attr_value in GENERIC_IDS: self.err.warning( err_id=('markup', 'starttag', 'generic_ids'), warning='Overlay contains generically-named IDs', description='An overlay is using a generically-named ID ' 'that could cause compatibility problems with ' 'other add-ons. Add-ons must namespace all ' 'IDs in the overlay, in the same way that ' 'JavaScript objects must be namespaced.', filename=self.filename, line=self.line, context=self.context) if tag == 'script': self.xml_state_scripts.append(any( (x[0] == 'type' and 'javascript' not in x[1]) for x in attrs)) # 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_position_stack.append(None) 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 self.xml_state, tag, self_closing # A fictional tag for testing purposes. if tag == "xbannedxtestx": self.err.error(("testcases_markup_markuptester", "handle_starttag", "banned_element"), "Banned element", "A banned element was detected", self.filename, line=self.line, context=self.context) if self.err.detected_type == PACKAGE_LANGPACK: if tag in UNSAFE_TAGS: self.err.warning(("testcases_markup_markuptester", "handle_starttag", "unsafe_langpack"), "Unsafe tag in language pack", ["""A tag in your markup has been marked as being potentially unsafe. Consider alternate means of accomplishing what the code executed by this tag performs.""", 'Tag "%s" is disallowed.' % tag], self.filename, line=self.line, context=self.context) if DEBUG: # pragma: no cover print "Unsafe Tag ------" # Make sure all src/href attributes are local for attr in attrs: if attr[0].lower() in ("src", "href") and \ not self._is_url_local(attr[1].lower()): self.err.warning(("testcases_markup_markuptester", "handle_starttag", "remote_src_href"), "src/href attributes must be local.", "Language packs require that all src and " "href attributes are relative URLs.", self.filename, line=self.line, context=self.context) self.err.reject = True if tag in ("iframe", "browser") and self.extension == "xul": # Bork if XUL iframe has no type attribute type_ = None src = None for attr in attrs: attr_name = attr[0].lower() if attr_name == "type": type_ = attr[1].lower() elif attr_name == "src": src = attr[1].lower() # We say it's true by default to catch elements that are # type="chrome" without an src="" attribute. remote_src = True if isinstance(src, str): remote_src = not self._is_url_local(src) if type_ and \ not (type_ in SAFE_IFRAME_TYPES or not remote_src): self.err.warning(("testcases_markup_markuptester", "handle_starttag", "iframe_type_unsafe"), "iframe/browser missing 'type' attribute", """All iframe and browser elements must have either a valid `type` attribute or a `src` attribute that points to a local file.""", self.filename, line=self.line, context=self.context) elif (not type_ or type_ not in SAFE_IFRAME_TYPES) and \ remote_src: self.err.warning(("testcases_markup_markuptester", "handle_starttag", "iframe_type_unsafe"), "Typeless iframes/browsers must be local.", """iframe and browser elements that lack a type attribute must always have src attributes that reference local resources.""", self.filename, line=self.line, context=self.context) elif tag == "script" and self.extension == "xul": # Per the Addon Validator Spec (v2), scripts in XUL # must not be remote. src = None for attr in attrs: if attr[0].lower() == "src": src = attr[1].lower() if src and not self._is_url_local(src): self.err.warning(("testcases_markup_markuptester", "handle_starttag", "banned_remote_scripts"), "Scripts must not be remote in XUL", """In XUL, <script> tags must not be referenced to script files that are hosted remotely.""", self.filename, line=self.line, context=self.context) # 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[0].lower() if attr_name == "style": csstester.test_css_snippet(self.err, self.filename, attr[1], self.line) elif attr_name.startswith("on"): # JS attribute scripting.test_js_snippet(err=self.err, data=attr[1], filename=self.filename) # 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(tag) self.xml_buffer.append("")
def handle_endtag(self, tag): tag = tag.lower() if tag == 'xul:script': tag = 'script' if tag == 'script' and len(self.xml_buffer[-1]) > 1000: self.err.warning(('markup', 'complex_script'), 'Long inline script', 'Please store complex scripts in .js files ' 'rather than inline script nodes.', self.filename, line=self.line, context=self.context, tier=2) 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(('markup', 'endtag', 'extra_closing_tags'), 'Markup parsing error', 'The markup file has more closing tags than it ' 'has opening tags.', 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('</' + 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(('markup', 'endtag', 'extra_closing_tags'), 'Parse error: tag closed before opened', ['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], 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() script_type = True if old_state == 'script': script_type = self.xml_state_scripts.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(('markup', 'endtag', 'invalid_nesting'), 'Markup invalidly nested', 'It has been determined that the document ' 'invalidly nests its tags. This is not permitted ' 'in the specified document type.', 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' and not script_type: scripting.test_js_snippet(err=self.err, data=data_buffer, filename=self.filename, line=old_line, context=self.context) elif tag == 'style': csstester.test_css_file(self.err, self.filename, data_buffer, old_line)