summaryrefslogtreecommitdiffstats
path: root/dom/base/nsTreeSanitizer.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /dom/base/nsTreeSanitizer.cpp
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/base/nsTreeSanitizer.cpp')
-rw-r--r--dom/base/nsTreeSanitizer.cpp1550
1 files changed, 1550 insertions, 0 deletions
diff --git a/dom/base/nsTreeSanitizer.cpp b/dom/base/nsTreeSanitizer.cpp
new file mode 100644
index 000000000..dc53ea5fa
--- /dev/null
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -0,0 +1,1550 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsTreeSanitizer.h"
+
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/StyleSheetInlines.h"
+#include "mozilla/css/Declaration.h"
+#include "mozilla/css/StyleRule.h"
+#include "mozilla/css/Rule.h"
+#include "nsCSSParser.h"
+#include "nsCSSPropertyID.h"
+#include "nsUnicharInputStream.h"
+#include "nsIDOMCSSRule.h"
+#include "nsAttrName.h"
+#include "nsIScriptSecurityManager.h"
+#include "nsNetUtil.h"
+#include "nsComponentManagerUtils.h"
+#include "nsNullPrincipal.h"
+#include "nsContentUtils.h"
+#include "nsIParserUtils.h"
+#include "nsIDocument.h"
+#include "nsQueryObject.h"
+
+using namespace mozilla;
+
+//
+// Thanks to Mark Pilgrim and Sam Ruby for the initial whitelist
+//
+nsIAtom** const kElementsHTML[] = {
+ &nsGkAtoms::a,
+ &nsGkAtoms::abbr,
+ &nsGkAtoms::acronym,
+ &nsGkAtoms::address,
+ &nsGkAtoms::area,
+ &nsGkAtoms::article,
+ &nsGkAtoms::aside,
+ &nsGkAtoms::audio,
+ &nsGkAtoms::b,
+ &nsGkAtoms::bdi,
+ &nsGkAtoms::bdo,
+ &nsGkAtoms::big,
+ &nsGkAtoms::blockquote,
+ // body checked specially
+ &nsGkAtoms::br,
+ &nsGkAtoms::button,
+ &nsGkAtoms::canvas,
+ &nsGkAtoms::caption,
+ &nsGkAtoms::center,
+ &nsGkAtoms::cite,
+ &nsGkAtoms::code,
+ &nsGkAtoms::col,
+ &nsGkAtoms::colgroup,
+ &nsGkAtoms::datalist,
+ &nsGkAtoms::dd,
+ &nsGkAtoms::del,
+ &nsGkAtoms::details,
+ &nsGkAtoms::dfn,
+ &nsGkAtoms::dir,
+ &nsGkAtoms::div,
+ &nsGkAtoms::dl,
+ &nsGkAtoms::dt,
+ &nsGkAtoms::em,
+ &nsGkAtoms::fieldset,
+ &nsGkAtoms::figcaption,
+ &nsGkAtoms::figure,
+ &nsGkAtoms::font,
+ &nsGkAtoms::footer,
+ &nsGkAtoms::form,
+ &nsGkAtoms::h1,
+ &nsGkAtoms::h2,
+ &nsGkAtoms::h3,
+ &nsGkAtoms::h4,
+ &nsGkAtoms::h5,
+ &nsGkAtoms::h6,
+ // head checked specially
+ &nsGkAtoms::header,
+ &nsGkAtoms::hgroup,
+ &nsGkAtoms::hr,
+ // html checked specially
+ &nsGkAtoms::i,
+ &nsGkAtoms::img,
+ &nsGkAtoms::input,
+ &nsGkAtoms::ins,
+ &nsGkAtoms::kbd,
+ &nsGkAtoms::label,
+ &nsGkAtoms::legend,
+ &nsGkAtoms::li,
+ &nsGkAtoms::link,
+ &nsGkAtoms::listing,
+ &nsGkAtoms::map,
+ &nsGkAtoms::mark,
+ &nsGkAtoms::menu,
+ &nsGkAtoms::meta,
+ &nsGkAtoms::meter,
+ &nsGkAtoms::nav,
+ &nsGkAtoms::nobr,
+ &nsGkAtoms::noscript,
+ &nsGkAtoms::ol,
+ &nsGkAtoms::optgroup,
+ &nsGkAtoms::option,
+ &nsGkAtoms::output,
+ &nsGkAtoms::p,
+ &nsGkAtoms::pre,
+ &nsGkAtoms::progress,
+ &nsGkAtoms::q,
+ &nsGkAtoms::rb,
+ &nsGkAtoms::rp,
+ &nsGkAtoms::rt,
+ &nsGkAtoms::rtc,
+ &nsGkAtoms::ruby,
+ &nsGkAtoms::s,
+ &nsGkAtoms::samp,
+ &nsGkAtoms::section,
+ &nsGkAtoms::select,
+ &nsGkAtoms::small,
+ &nsGkAtoms::source,
+ &nsGkAtoms::span,
+ &nsGkAtoms::strike,
+ &nsGkAtoms::strong,
+ &nsGkAtoms::sub,
+ &nsGkAtoms::summary,
+ &nsGkAtoms::sup,
+ // style checked specially
+ &nsGkAtoms::table,
+ &nsGkAtoms::tbody,
+ &nsGkAtoms::td,
+ &nsGkAtoms::textarea,
+ &nsGkAtoms::tfoot,
+ &nsGkAtoms::th,
+ &nsGkAtoms::thead,
+ &nsGkAtoms::time,
+ // title checked specially
+ &nsGkAtoms::tr,
+ &nsGkAtoms::track,
+ &nsGkAtoms::tt,
+ &nsGkAtoms::u,
+ &nsGkAtoms::ul,
+ &nsGkAtoms::var,
+ &nsGkAtoms::video,
+ &nsGkAtoms::wbr,
+ nullptr
+};
+
+nsIAtom** const kAttributesHTML[] = {
+ &nsGkAtoms::abbr,
+ &nsGkAtoms::accept,
+ &nsGkAtoms::acceptcharset,
+ &nsGkAtoms::accesskey,
+ &nsGkAtoms::action,
+ &nsGkAtoms::alt,
+ &nsGkAtoms::autocomplete,
+ &nsGkAtoms::autofocus,
+ &nsGkAtoms::autoplay,
+ &nsGkAtoms::axis,
+ &nsGkAtoms::_char,
+ &nsGkAtoms::charoff,
+ &nsGkAtoms::charset,
+ &nsGkAtoms::checked,
+ &nsGkAtoms::cite,
+ &nsGkAtoms::_class,
+ &nsGkAtoms::cols,
+ &nsGkAtoms::colspan,
+ &nsGkAtoms::content,
+ &nsGkAtoms::contenteditable,
+ &nsGkAtoms::contextmenu,
+ &nsGkAtoms::controls,
+ &nsGkAtoms::coords,
+ &nsGkAtoms::datetime,
+ &nsGkAtoms::dir,
+ &nsGkAtoms::disabled,
+ &nsGkAtoms::draggable,
+ &nsGkAtoms::enctype,
+ &nsGkAtoms::face,
+ &nsGkAtoms::_for,
+ &nsGkAtoms::frame,
+ &nsGkAtoms::headers,
+ &nsGkAtoms::height,
+ &nsGkAtoms::hidden,
+ &nsGkAtoms::high,
+ &nsGkAtoms::href,
+ &nsGkAtoms::hreflang,
+ &nsGkAtoms::icon,
+ &nsGkAtoms::id,
+ &nsGkAtoms::ismap,
+ &nsGkAtoms::itemid,
+ &nsGkAtoms::itemprop,
+ &nsGkAtoms::itemref,
+ &nsGkAtoms::itemscope,
+ &nsGkAtoms::itemtype,
+ &nsGkAtoms::kind,
+ &nsGkAtoms::label,
+ &nsGkAtoms::lang,
+ &nsGkAtoms::list,
+ &nsGkAtoms::longdesc,
+ &nsGkAtoms::loop,
+ &nsGkAtoms::low,
+ &nsGkAtoms::max,
+ &nsGkAtoms::maxlength,
+ &nsGkAtoms::media,
+ &nsGkAtoms::method,
+ &nsGkAtoms::min,
+ &nsGkAtoms::minlength,
+ &nsGkAtoms::multiple,
+ &nsGkAtoms::muted,
+ &nsGkAtoms::name,
+ &nsGkAtoms::nohref,
+ &nsGkAtoms::novalidate,
+ &nsGkAtoms::nowrap,
+ &nsGkAtoms::open,
+ &nsGkAtoms::optimum,
+ &nsGkAtoms::pattern,
+ &nsGkAtoms::placeholder,
+ &nsGkAtoms::playbackrate,
+ &nsGkAtoms::poster,
+ &nsGkAtoms::preload,
+ &nsGkAtoms::prompt,
+ &nsGkAtoms::pubdate,
+ &nsGkAtoms::radiogroup,
+ &nsGkAtoms::readonly,
+ &nsGkAtoms::rel,
+ &nsGkAtoms::required,
+ &nsGkAtoms::rev,
+ &nsGkAtoms::reversed,
+ &nsGkAtoms::role,
+ &nsGkAtoms::rows,
+ &nsGkAtoms::rowspan,
+ &nsGkAtoms::rules,
+ &nsGkAtoms::scoped,
+ &nsGkAtoms::scope,
+ &nsGkAtoms::selected,
+ &nsGkAtoms::shape,
+ &nsGkAtoms::span,
+ &nsGkAtoms::spellcheck,
+ &nsGkAtoms::src,
+ &nsGkAtoms::srclang,
+ &nsGkAtoms::start,
+ &nsGkAtoms::summary,
+ &nsGkAtoms::tabindex,
+ &nsGkAtoms::target,
+ &nsGkAtoms::title,
+ &nsGkAtoms::type,
+ &nsGkAtoms::usemap,
+ &nsGkAtoms::value,
+ &nsGkAtoms::width,
+ &nsGkAtoms::wrap,
+ nullptr
+};
+
+nsIAtom** const kPresAttributesHTML[] = {
+ &nsGkAtoms::align,
+ &nsGkAtoms::background,
+ &nsGkAtoms::bgcolor,
+ &nsGkAtoms::border,
+ &nsGkAtoms::cellpadding,
+ &nsGkAtoms::cellspacing,
+ &nsGkAtoms::color,
+ &nsGkAtoms::compact,
+ &nsGkAtoms::clear,
+ &nsGkAtoms::hspace,
+ &nsGkAtoms::noshade,
+ &nsGkAtoms::pointSize,
+ &nsGkAtoms::size,
+ &nsGkAtoms::valign,
+ &nsGkAtoms::vspace,
+ nullptr
+};
+
+nsIAtom** const kURLAttributesHTML[] = {
+ &nsGkAtoms::action,
+ &nsGkAtoms::href,
+ &nsGkAtoms::src,
+ &nsGkAtoms::longdesc,
+ &nsGkAtoms::cite,
+ &nsGkAtoms::background,
+ nullptr
+};
+
+nsIAtom** const kElementsSVG[] = {
+ &nsGkAtoms::a, // a
+ &nsGkAtoms::circle, // circle
+ &nsGkAtoms::clipPath, // clipPath
+ &nsGkAtoms::colorProfile, // color-profile
+ &nsGkAtoms::cursor, // cursor
+ &nsGkAtoms::defs, // defs
+ &nsGkAtoms::desc, // desc
+ &nsGkAtoms::ellipse, // ellipse
+ &nsGkAtoms::elevation, // elevation
+ &nsGkAtoms::erode, // erode
+ &nsGkAtoms::ex, // ex
+ &nsGkAtoms::exact, // exact
+ &nsGkAtoms::exponent, // exponent
+ &nsGkAtoms::feBlend, // feBlend
+ &nsGkAtoms::feColorMatrix, // feColorMatrix
+ &nsGkAtoms::feComponentTransfer, // feComponentTransfer
+ &nsGkAtoms::feComposite, // feComposite
+ &nsGkAtoms::feConvolveMatrix, // feConvolveMatrix
+ &nsGkAtoms::feDiffuseLighting, // feDiffuseLighting
+ &nsGkAtoms::feDisplacementMap, // feDisplacementMap
+ &nsGkAtoms::feDistantLight, // feDistantLight
+ &nsGkAtoms::feDropShadow, // feDropShadow
+ &nsGkAtoms::feFlood, // feFlood
+ &nsGkAtoms::feFuncA, // feFuncA
+ &nsGkAtoms::feFuncB, // feFuncB
+ &nsGkAtoms::feFuncG, // feFuncG
+ &nsGkAtoms::feFuncR, // feFuncR
+ &nsGkAtoms::feGaussianBlur, // feGaussianBlur
+ &nsGkAtoms::feImage, // feImage
+ &nsGkAtoms::feMerge, // feMerge
+ &nsGkAtoms::feMergeNode, // feMergeNode
+ &nsGkAtoms::feMorphology, // feMorphology
+ &nsGkAtoms::feOffset, // feOffset
+ &nsGkAtoms::fePointLight, // fePointLight
+ &nsGkAtoms::feSpecularLighting, // feSpecularLighting
+ &nsGkAtoms::feSpotLight, // feSpotLight
+ &nsGkAtoms::feTile, // feTile
+ &nsGkAtoms::feTurbulence, // feTurbulence
+ &nsGkAtoms::filter, // filter
+ &nsGkAtoms::font, // font
+ &nsGkAtoms::font_face, // font-face
+ &nsGkAtoms::font_face_format, // font-face-format
+ &nsGkAtoms::font_face_name, // font-face-name
+ &nsGkAtoms::font_face_src, // font-face-src
+ &nsGkAtoms::font_face_uri, // font-face-uri
+ &nsGkAtoms::foreignObject, // foreignObject
+ &nsGkAtoms::g, // g
+ // glyph
+ &nsGkAtoms::glyphRef, // glyphRef
+ // hkern
+ &nsGkAtoms::image, // image
+ &nsGkAtoms::line, // line
+ &nsGkAtoms::linearGradient, // linearGradient
+ &nsGkAtoms::marker, // marker
+ &nsGkAtoms::mask, // mask
+ &nsGkAtoms::metadata, // metadata
+ &nsGkAtoms::missingGlyph, // missingGlyph
+ &nsGkAtoms::mpath, // mpath
+ &nsGkAtoms::path, // path
+ &nsGkAtoms::pattern, // pattern
+ &nsGkAtoms::polygon, // polygon
+ &nsGkAtoms::polyline, // polyline
+ &nsGkAtoms::radialGradient, // radialGradient
+ &nsGkAtoms::rect, // rect
+ &nsGkAtoms::stop, // stop
+ &nsGkAtoms::svg, // svg
+ &nsGkAtoms::svgSwitch, // switch
+ &nsGkAtoms::symbol, // symbol
+ &nsGkAtoms::text, // text
+ &nsGkAtoms::textPath, // textPath
+ &nsGkAtoms::title, // title
+ &nsGkAtoms::tref, // tref
+ &nsGkAtoms::tspan, // tspan
+ &nsGkAtoms::use, // use
+ &nsGkAtoms::view, // view
+ // vkern
+ nullptr
+};
+
+nsIAtom** const kAttributesSVG[] = {
+ // accent-height
+ &nsGkAtoms::accumulate, // accumulate
+ &nsGkAtoms::additive, // additive
+ &nsGkAtoms::alignment_baseline, // alignment-baseline
+ // alphabetic
+ &nsGkAtoms::amplitude, // amplitude
+ // arabic-form
+ // ascent
+ &nsGkAtoms::attributeName, // attributeName
+ &nsGkAtoms::attributeType, // attributeType
+ &nsGkAtoms::azimuth, // azimuth
+ &nsGkAtoms::baseFrequency, // baseFrequency
+ &nsGkAtoms::baseline_shift, // baseline-shift
+ // baseProfile
+ // bbox
+ &nsGkAtoms::begin, // begin
+ &nsGkAtoms::bias, // bias
+ &nsGkAtoms::by, // by
+ &nsGkAtoms::calcMode, // calcMode
+ // cap-height
+ &nsGkAtoms::_class, // class
+ &nsGkAtoms::clip_path, // clip-path
+ &nsGkAtoms::clip_rule, // clip-rule
+ &nsGkAtoms::clipPathUnits, // clipPathUnits
+ &nsGkAtoms::color, // color
+ &nsGkAtoms::colorInterpolation, // color-interpolation
+ &nsGkAtoms::colorInterpolationFilters, // color-interpolation-filters
+ &nsGkAtoms::cursor, // cursor
+ &nsGkAtoms::cx, // cx
+ &nsGkAtoms::cy, // cy
+ &nsGkAtoms::d, // d
+ // descent
+ &nsGkAtoms::diffuseConstant, // diffuseConstant
+ &nsGkAtoms::direction, // direction
+ &nsGkAtoms::display, // display
+ &nsGkAtoms::divisor, // divisor
+ &nsGkAtoms::dominant_baseline, // dominant-baseline
+ &nsGkAtoms::dur, // dur
+ &nsGkAtoms::dx, // dx
+ &nsGkAtoms::dy, // dy
+ &nsGkAtoms::edgeMode, // edgeMode
+ &nsGkAtoms::elevation, // elevation
+ // enable-background
+ &nsGkAtoms::end, // end
+ &nsGkAtoms::fill, // fill
+ &nsGkAtoms::fill_opacity, // fill-opacity
+ &nsGkAtoms::fill_rule, // fill-rule
+ &nsGkAtoms::filter, // filter
+ &nsGkAtoms::filterUnits, // filterUnits
+ &nsGkAtoms::flood_color, // flood-color
+ &nsGkAtoms::flood_opacity, // flood-opacity
+ // XXX focusable
+ &nsGkAtoms::font, // font
+ &nsGkAtoms::font_family, // font-family
+ &nsGkAtoms::font_size, // font-size
+ &nsGkAtoms::font_size_adjust, // font-size-adjust
+ &nsGkAtoms::font_stretch, // font-stretch
+ &nsGkAtoms::font_style, // font-style
+ &nsGkAtoms::font_variant, // font-variant
+ &nsGkAtoms::fontWeight, // font-weight
+ &nsGkAtoms::format, // format
+ &nsGkAtoms::from, // from
+ &nsGkAtoms::fx, // fx
+ &nsGkAtoms::fy, // fy
+ // g1
+ // g2
+ // glyph-name
+ // glyphRef
+ // glyph-orientation-horizontal
+ // glyph-orientation-vertical
+ &nsGkAtoms::gradientTransform, // gradientTransform
+ &nsGkAtoms::gradientUnits, // gradientUnits
+ &nsGkAtoms::height, // height
+ // horiz-adv-x
+ // horiz-origin-x
+ // horiz-origin-y
+ &nsGkAtoms::id, // id
+ // ideographic
+ &nsGkAtoms::image_rendering, // image-rendering
+ &nsGkAtoms::in, // in
+ &nsGkAtoms::in2, // in2
+ &nsGkAtoms::intercept, // intercept
+ // k
+ &nsGkAtoms::k1, // k1
+ &nsGkAtoms::k2, // k2
+ &nsGkAtoms::k3, // k3
+ &nsGkAtoms::k4, // k4
+ // kerning
+ &nsGkAtoms::kernelMatrix, // kernelMatrix
+ &nsGkAtoms::kernelUnitLength, // kernelUnitLength
+ &nsGkAtoms::keyPoints, // keyPoints
+ &nsGkAtoms::keySplines, // keySplines
+ &nsGkAtoms::keyTimes, // keyTimes
+ &nsGkAtoms::lang, // lang
+ // lengthAdjust
+ &nsGkAtoms::letter_spacing, // letter-spacing
+ &nsGkAtoms::lighting_color, // lighting-color
+ &nsGkAtoms::limitingConeAngle, // limitingConeAngle
+ // local
+ &nsGkAtoms::marker, // marker
+ &nsGkAtoms::marker_end, // marker-end
+ &nsGkAtoms::marker_mid, // marker-mid
+ &nsGkAtoms::marker_start, // marker-start
+ &nsGkAtoms::markerHeight, // markerHeight
+ &nsGkAtoms::markerUnits, // markerUnits
+ &nsGkAtoms::markerWidth, // markerWidth
+ &nsGkAtoms::mask, // mask
+ &nsGkAtoms::maskContentUnits, // maskContentUnits
+ &nsGkAtoms::maskUnits, // maskUnits
+ // mathematical
+ &nsGkAtoms::max, // max
+ &nsGkAtoms::media, // media
+ &nsGkAtoms::method, // method
+ &nsGkAtoms::min, // min
+ &nsGkAtoms::mode, // mode
+ &nsGkAtoms::name, // name
+ &nsGkAtoms::numOctaves, // numOctaves
+ &nsGkAtoms::offset, // offset
+ &nsGkAtoms::opacity, // opacity
+ &nsGkAtoms::_operator, // operator
+ &nsGkAtoms::order, // order
+ &nsGkAtoms::orient, // orient
+ &nsGkAtoms::orientation, // orientation
+ // origin
+ // overline-position
+ // overline-thickness
+ &nsGkAtoms::overflow, // overflow
+ // panose-1
+ &nsGkAtoms::path, // path
+ &nsGkAtoms::pathLength, // pathLength
+ &nsGkAtoms::patternContentUnits, // patternContentUnits
+ &nsGkAtoms::patternTransform, // patternTransform
+ &nsGkAtoms::patternUnits, // patternUnits
+ &nsGkAtoms::pointer_events, // pointer-events XXX is this safe?
+ &nsGkAtoms::points, // points
+ &nsGkAtoms::pointsAtX, // pointsAtX
+ &nsGkAtoms::pointsAtY, // pointsAtY
+ &nsGkAtoms::pointsAtZ, // pointsAtZ
+ &nsGkAtoms::preserveAlpha, // preserveAlpha
+ &nsGkAtoms::preserveAspectRatio, // preserveAspectRatio
+ &nsGkAtoms::primitiveUnits, // primitiveUnits
+ &nsGkAtoms::r, // r
+ &nsGkAtoms::radius, // radius
+ &nsGkAtoms::refX, // refX
+ &nsGkAtoms::refY, // refY
+ &nsGkAtoms::repeatCount, // repeatCount
+ &nsGkAtoms::repeatDur, // repeatDur
+ &nsGkAtoms::requiredExtensions, // requiredExtensions
+ &nsGkAtoms::requiredFeatures, // requiredFeatures
+ &nsGkAtoms::restart, // restart
+ &nsGkAtoms::result, // result
+ &nsGkAtoms::rotate, // rotate
+ &nsGkAtoms::rx, // rx
+ &nsGkAtoms::ry, // ry
+ &nsGkAtoms::scale, // scale
+ &nsGkAtoms::seed, // seed
+ &nsGkAtoms::shape_rendering, // shape-rendering
+ &nsGkAtoms::slope, // slope
+ &nsGkAtoms::spacing, // spacing
+ &nsGkAtoms::specularConstant, // specularConstant
+ &nsGkAtoms::specularExponent, // specularExponent
+ &nsGkAtoms::spreadMethod, // spreadMethod
+ &nsGkAtoms::startOffset, // startOffset
+ &nsGkAtoms::stdDeviation, // stdDeviation
+ // stemh
+ // stemv
+ &nsGkAtoms::stitchTiles, // stitchTiles
+ &nsGkAtoms::stop_color, // stop-color
+ &nsGkAtoms::stop_opacity, // stop-opacity
+ // strikethrough-position
+ // strikethrough-thickness
+ &nsGkAtoms::string, // string
+ &nsGkAtoms::stroke, // stroke
+ &nsGkAtoms::stroke_dasharray, // stroke-dasharray
+ &nsGkAtoms::stroke_dashoffset, // stroke-dashoffset
+ &nsGkAtoms::stroke_linecap, // stroke-linecap
+ &nsGkAtoms::stroke_linejoin, // stroke-linejoin
+ &nsGkAtoms::stroke_miterlimit, // stroke-miterlimit
+ &nsGkAtoms::stroke_opacity, // stroke-opacity
+ &nsGkAtoms::stroke_width, // stroke-width
+ &nsGkAtoms::surfaceScale, // surfaceScale
+ &nsGkAtoms::systemLanguage, // systemLanguage
+ &nsGkAtoms::tableValues, // tableValues
+ &nsGkAtoms::target, // target
+ &nsGkAtoms::targetX, // targetX
+ &nsGkAtoms::targetY, // targetY
+ &nsGkAtoms::text_anchor, // text-anchor
+ &nsGkAtoms::text_decoration, // text-decoration
+ // textLength
+ &nsGkAtoms::text_rendering, // text-rendering
+ &nsGkAtoms::title, // title
+ &nsGkAtoms::to, // to
+ &nsGkAtoms::transform, // transform
+ &nsGkAtoms::type, // type
+ // u1
+ // u2
+ // underline-position
+ // underline-thickness
+ // unicode
+ &nsGkAtoms::unicode_bidi, // unicode-bidi
+ // unicode-range
+ // units-per-em
+ // v-alphabetic
+ // v-hanging
+ // v-ideographic
+ // v-mathematical
+ &nsGkAtoms::values, // values
+ &nsGkAtoms::vector_effect, // vector-effect
+ // vert-adv-y
+ // vert-origin-x
+ // vert-origin-y
+ &nsGkAtoms::viewBox, // viewBox
+ &nsGkAtoms::viewTarget, // viewTarget
+ &nsGkAtoms::visibility, // visibility
+ &nsGkAtoms::width, // width
+ // widths
+ &nsGkAtoms::word_spacing, // word-spacing
+ &nsGkAtoms::writing_mode, // writing-mode
+ &nsGkAtoms::x, // x
+ // x-height
+ &nsGkAtoms::x1, // x1
+ &nsGkAtoms::x2, // x2
+ &nsGkAtoms::xChannelSelector, // xChannelSelector
+ &nsGkAtoms::y, // y
+ &nsGkAtoms::y1, // y1
+ &nsGkAtoms::y2, // y2
+ &nsGkAtoms::yChannelSelector, // yChannelSelector
+ &nsGkAtoms::z, // z
+ &nsGkAtoms::zoomAndPan, // zoomAndPan
+ nullptr
+};
+
+nsIAtom** const kURLAttributesSVG[] = {
+ &nsGkAtoms::href,
+ nullptr
+};
+
+nsIAtom** const kElementsMathML[] = {
+ &nsGkAtoms::abs_, // abs
+ &nsGkAtoms::_and, // and
+ &nsGkAtoms::annotation_, // annotation
+ &nsGkAtoms::annotation_xml_, // annotation-xml
+ &nsGkAtoms::apply_, // apply
+ &nsGkAtoms::approx_, // approx
+ &nsGkAtoms::arccos_, // arccos
+ &nsGkAtoms::arccosh_, // arccosh
+ &nsGkAtoms::arccot_, // arccot
+ &nsGkAtoms::arccoth_, // arccoth
+ &nsGkAtoms::arccsc_, // arccsc
+ &nsGkAtoms::arccsch_, // arccsch
+ &nsGkAtoms::arcsec_, // arcsec
+ &nsGkAtoms::arcsech_, // arcsech
+ &nsGkAtoms::arcsin_, // arcsin
+ &nsGkAtoms::arcsinh_, // arcsinh
+ &nsGkAtoms::arctan_, // arctan
+ &nsGkAtoms::arctanh_, // arctanh
+ &nsGkAtoms::arg_, // arg
+ &nsGkAtoms::bind_, // bind
+ &nsGkAtoms::bvar_, // bvar
+ &nsGkAtoms::card_, // card
+ &nsGkAtoms::cartesianproduct_, // cartesianproduct
+ &nsGkAtoms::cbytes_, // cbytes
+ &nsGkAtoms::ceiling, // ceiling
+ &nsGkAtoms::cerror_, // cerror
+ &nsGkAtoms::ci_, // ci
+ &nsGkAtoms::cn_, // cn
+ &nsGkAtoms::codomain_, // codomain
+ &nsGkAtoms::complexes_, // complexes
+ &nsGkAtoms::compose_, // compose
+ &nsGkAtoms::condition_, // condition
+ &nsGkAtoms::conjugate_, // conjugate
+ &nsGkAtoms::cos_, // cos
+ &nsGkAtoms::cosh_, // cosh
+ &nsGkAtoms::cot_, // cot
+ &nsGkAtoms::coth_, // coth
+ &nsGkAtoms::cs_, // cs
+ &nsGkAtoms::csc_, // csc
+ &nsGkAtoms::csch_, // csch
+ &nsGkAtoms::csymbol_, // csymbol
+ &nsGkAtoms::curl_, // curl
+ &nsGkAtoms::declare, // declare
+ &nsGkAtoms::degree_, // degree
+ &nsGkAtoms::determinant_, // determinant
+ &nsGkAtoms::diff_, // diff
+ &nsGkAtoms::divergence_, // divergence
+ &nsGkAtoms::divide_, // divide
+ &nsGkAtoms::domain_, // domain
+ &nsGkAtoms::domainofapplication_, // domainofapplication
+ &nsGkAtoms::el_, // el
+ &nsGkAtoms::emptyset_, // emptyset
+ &nsGkAtoms::eq_, // eq
+ &nsGkAtoms::equivalent_, // equivalent
+ &nsGkAtoms::eulergamma_, // eulergamma
+ &nsGkAtoms::exists_, // exists
+ &nsGkAtoms::exp_, // exp
+ &nsGkAtoms::exponentiale_, // exponentiale
+ &nsGkAtoms::factorial_, // factorial
+ &nsGkAtoms::factorof_, // factorof
+ &nsGkAtoms::_false, // false
+ &nsGkAtoms::floor, // floor
+ &nsGkAtoms::fn_, // fn
+ &nsGkAtoms::forall_, // forall
+ &nsGkAtoms::gcd_, // gcd
+ &nsGkAtoms::geq_, // geq
+ &nsGkAtoms::grad, // grad
+ &nsGkAtoms::gt_, // gt
+ &nsGkAtoms::ident_, // ident
+ &nsGkAtoms::image, // image
+ &nsGkAtoms::imaginary_, // imaginary
+ &nsGkAtoms::imaginaryi_, // imaginaryi
+ &nsGkAtoms::implies_, // implies
+ &nsGkAtoms::in, // in
+ &nsGkAtoms::infinity, // infinity
+ &nsGkAtoms::int_, // int
+ &nsGkAtoms::integers_, // integers
+ &nsGkAtoms::intersect_, // intersect
+ &nsGkAtoms::interval_, // interval
+ &nsGkAtoms::inverse_, // inverse
+ &nsGkAtoms::lambda_, // lambda
+ &nsGkAtoms::laplacian_, // laplacian
+ &nsGkAtoms::lcm_, // lcm
+ &nsGkAtoms::leq_, // leq
+ &nsGkAtoms::limit_, // limit
+ &nsGkAtoms::list_, // list
+ &nsGkAtoms::ln_, // ln
+ &nsGkAtoms::log_, // log
+ &nsGkAtoms::logbase_, // logbase
+ &nsGkAtoms::lowlimit_, // lowlimit
+ &nsGkAtoms::lt_, // lt
+ &nsGkAtoms::maction_, // maction
+ &nsGkAtoms::maligngroup_, // maligngroup
+ &nsGkAtoms::malignmark_, // malignmark
+ &nsGkAtoms::math, // math
+ &nsGkAtoms::matrix, // matrix
+ &nsGkAtoms::matrixrow_, // matrixrow
+ &nsGkAtoms::max, // max
+ &nsGkAtoms::mean_, // mean
+ &nsGkAtoms::median_, // median
+ &nsGkAtoms::menclose_, // menclose
+ &nsGkAtoms::merror_, // merror
+ &nsGkAtoms::mfenced_, // mfenced
+ &nsGkAtoms::mfrac_, // mfrac
+ &nsGkAtoms::mglyph_, // mglyph
+ &nsGkAtoms::mi_, // mi
+ &nsGkAtoms::min, // min
+ &nsGkAtoms::minus_, // minus
+ &nsGkAtoms::mlabeledtr_, // mlabeledtr
+ &nsGkAtoms::mlongdiv_, // mlongdiv
+ &nsGkAtoms::mmultiscripts_, // mmultiscripts
+ &nsGkAtoms::mn_, // mn
+ &nsGkAtoms::mo_, // mo
+ &nsGkAtoms::mode, // mode
+ &nsGkAtoms::moment_, // moment
+ &nsGkAtoms::momentabout_, // momentabout
+ &nsGkAtoms::mover_, // mover
+ &nsGkAtoms::mpadded_, // mpadded
+ &nsGkAtoms::mphantom_, // mphantom
+ &nsGkAtoms::mprescripts_, // mprescripts
+ &nsGkAtoms::mroot_, // mroot
+ &nsGkAtoms::mrow_, // mrow
+ &nsGkAtoms::ms_, // ms
+ &nsGkAtoms::mscarries_, // mscarries
+ &nsGkAtoms::mscarry_, // mscarry
+ &nsGkAtoms::msgroup_, // msgroup
+ &nsGkAtoms::msline_, // msline
+ &nsGkAtoms::mspace_, // mspace
+ &nsGkAtoms::msqrt_, // msqrt
+ &nsGkAtoms::msrow_, // msrow
+ &nsGkAtoms::mstack_, // mstack
+ &nsGkAtoms::mstyle_, // mstyle
+ &nsGkAtoms::msub_, // msub
+ &nsGkAtoms::msubsup_, // msubsup
+ &nsGkAtoms::msup_, // msup
+ &nsGkAtoms::mtable_, // mtable
+ &nsGkAtoms::mtd_, // mtd
+ &nsGkAtoms::mtext_, // mtext
+ &nsGkAtoms::mtr_, // mtr
+ &nsGkAtoms::munder_, // munder
+ &nsGkAtoms::munderover_, // munderover
+ &nsGkAtoms::naturalnumbers_, // naturalnumbers
+ &nsGkAtoms::neq_, // neq
+ &nsGkAtoms::none, // none
+ &nsGkAtoms::_not, // not
+ &nsGkAtoms::notanumber_, // notanumber
+ &nsGkAtoms::note_, // note
+ &nsGkAtoms::notin_, // notin
+ &nsGkAtoms::notprsubset_, // notprsubset
+ &nsGkAtoms::notsubset_, // notsubset
+ &nsGkAtoms::_or, // or
+ &nsGkAtoms::otherwise, // otherwise
+ &nsGkAtoms::outerproduct_, // outerproduct
+ &nsGkAtoms::partialdiff_, // partialdiff
+ &nsGkAtoms::pi_, // pi
+ &nsGkAtoms::piece_, // piece
+ &nsGkAtoms::piecewise_, // piecewise
+ &nsGkAtoms::plus_, // plus
+ &nsGkAtoms::power_, // power
+ &nsGkAtoms::primes_, // primes
+ &nsGkAtoms::product_, // product
+ &nsGkAtoms::prsubset_, // prsubset
+ &nsGkAtoms::quotient_, // quotient
+ &nsGkAtoms::rationals_, // rationals
+ &nsGkAtoms::real_, // real
+ &nsGkAtoms::reals_, // reals
+ &nsGkAtoms::reln_, // reln
+ &nsGkAtoms::rem, // rem
+ &nsGkAtoms::root_, // root
+ &nsGkAtoms::scalarproduct_, // scalarproduct
+ &nsGkAtoms::sdev_, // sdev
+ &nsGkAtoms::sec_, // sec
+ &nsGkAtoms::sech_, // sech
+ &nsGkAtoms::selector_, // selector
+ &nsGkAtoms::semantics_, // semantics
+ &nsGkAtoms::sep_, // sep
+ &nsGkAtoms::set_, // set
+ &nsGkAtoms::setdiff_, // setdiff
+ &nsGkAtoms::share_, // share
+ &nsGkAtoms::sin_, // sin
+ &nsGkAtoms::sinh_, // sinh
+ &nsGkAtoms::subset_, // subset
+ &nsGkAtoms::sum, // sum
+ &nsGkAtoms::tan_, // tan
+ &nsGkAtoms::tanh_, // tanh
+ &nsGkAtoms::tendsto_, // tendsto
+ &nsGkAtoms::times_, // times
+ &nsGkAtoms::transpose_, // transpose
+ &nsGkAtoms::_true, // true
+ &nsGkAtoms::union_, // union
+ &nsGkAtoms::uplimit_, // uplimit
+ &nsGkAtoms::variance_, // variance
+ &nsGkAtoms::vector_, // vector
+ &nsGkAtoms::vectorproduct_, // vectorproduct
+ &nsGkAtoms::xor_, // xor
+ nullptr
+};
+
+nsIAtom** const kAttributesMathML[] = {
+ &nsGkAtoms::accent_, // accent
+ &nsGkAtoms::accentunder_, // accentunder
+ &nsGkAtoms::actiontype_, // actiontype
+ &nsGkAtoms::align, // align
+ &nsGkAtoms::alignmentscope_, // alignmentscope
+ &nsGkAtoms::alt, // alt
+ &nsGkAtoms::altimg_, // altimg
+ &nsGkAtoms::altimg_height_, // altimg-height
+ &nsGkAtoms::altimg_valign_, // altimg-valign
+ &nsGkAtoms::altimg_width_, // altimg-width
+ &nsGkAtoms::background, // background
+ &nsGkAtoms::base, // base
+ &nsGkAtoms::bevelled_, // bevelled
+ &nsGkAtoms::cd_, // cd
+ &nsGkAtoms::cdgroup_, // cdgroup
+ &nsGkAtoms::charalign_, // charalign
+ &nsGkAtoms::close, // close
+ &nsGkAtoms::closure_, // closure
+ &nsGkAtoms::color, // color
+ &nsGkAtoms::columnalign_, // columnalign
+ &nsGkAtoms::columnalignment_, // columnalignment
+ &nsGkAtoms::columnlines_, // columnlines
+ &nsGkAtoms::columnspacing_, // columnspacing
+ &nsGkAtoms::columnspan_, // columnspan
+ &nsGkAtoms::columnwidth_, // columnwidth
+ &nsGkAtoms::crossout_, // crossout
+ &nsGkAtoms::decimalpoint_, // decimalpoint
+ &nsGkAtoms::definitionURL_, // definitionURL
+ &nsGkAtoms::denomalign_, // denomalign
+ &nsGkAtoms::depth_, // depth
+ &nsGkAtoms::dir, // dir
+ &nsGkAtoms::display, // display
+ &nsGkAtoms::displaystyle_, // displaystyle
+ &nsGkAtoms::edge_, // edge
+ &nsGkAtoms::encoding, // encoding
+ &nsGkAtoms::equalcolumns_, // equalcolumns
+ &nsGkAtoms::equalrows_, // equalrows
+ &nsGkAtoms::fence_, // fence
+ &nsGkAtoms::fontfamily_, // fontfamily
+ &nsGkAtoms::fontsize_, // fontsize
+ &nsGkAtoms::fontstyle_, // fontstyle
+ &nsGkAtoms::fontweight_, // fontweight
+ &nsGkAtoms::form, // form
+ &nsGkAtoms::frame, // frame
+ &nsGkAtoms::framespacing_, // framespacing
+ &nsGkAtoms::groupalign_, // groupalign
+ &nsGkAtoms::height, // height
+ &nsGkAtoms::href, // href
+ &nsGkAtoms::id, // id
+ &nsGkAtoms::indentalign_, // indentalign
+ &nsGkAtoms::indentalignfirst_, // indentalignfirst
+ &nsGkAtoms::indentalignlast_, // indentalignlast
+ &nsGkAtoms::indentshift_, // indentshift
+ &nsGkAtoms::indentshiftfirst_, // indentshiftfirst
+ &nsGkAtoms::indenttarget_, // indenttarget
+ &nsGkAtoms::index, // index
+ &nsGkAtoms::integer, // integer
+ &nsGkAtoms::largeop_, // largeop
+ &nsGkAtoms::length, // length
+ &nsGkAtoms::linebreak_, // linebreak
+ &nsGkAtoms::linebreakmultchar_, // linebreakmultchar
+ &nsGkAtoms::linebreakstyle_, // linebreakstyle
+ &nsGkAtoms::linethickness_, // linethickness
+ &nsGkAtoms::location_, // location
+ &nsGkAtoms::longdivstyle_, // longdivstyle
+ &nsGkAtoms::lquote_, // lquote
+ &nsGkAtoms::lspace_, // lspace
+ &nsGkAtoms::ltr, // ltr
+ &nsGkAtoms::mathbackground_, // mathbackground
+ &nsGkAtoms::mathcolor_, // mathcolor
+ &nsGkAtoms::mathsize_, // mathsize
+ &nsGkAtoms::mathvariant_, // mathvariant
+ &nsGkAtoms::maxsize_, // maxsize
+ &nsGkAtoms::minlabelspacing_, // minlabelspacing
+ &nsGkAtoms::minsize_, // minsize
+ &nsGkAtoms::movablelimits_, // movablelimits
+ &nsGkAtoms::msgroup_, // msgroup
+ &nsGkAtoms::name, // name
+ &nsGkAtoms::newline, // newline
+ &nsGkAtoms::notation_, // notation
+ &nsGkAtoms::numalign_, // numalign
+ &nsGkAtoms::number, // number
+ &nsGkAtoms::open, // open
+ &nsGkAtoms::order, // order
+ &nsGkAtoms::other_, // other
+ &nsGkAtoms::overflow, // overflow
+ &nsGkAtoms::position, // position
+ &nsGkAtoms::role, // role
+ &nsGkAtoms::rowalign_, // rowalign
+ &nsGkAtoms::rowlines_, // rowlines
+ &nsGkAtoms::rowspacing_, // rowspacing
+ &nsGkAtoms::rowspan, // rowspan
+ &nsGkAtoms::rquote_, // rquote
+ &nsGkAtoms::rspace_, // rspace
+ &nsGkAtoms::schemaLocation_, // schemaLocation
+ &nsGkAtoms::scriptlevel_, // scriptlevel
+ &nsGkAtoms::scriptminsize_, // scriptminsize
+ &nsGkAtoms::scriptsize_, // scriptsize
+ &nsGkAtoms::scriptsizemultiplier_, // scriptsizemultiplier
+ &nsGkAtoms::selection_, // selection
+ &nsGkAtoms::separator_, // separator
+ &nsGkAtoms::separators_, // separators
+ &nsGkAtoms::shift_, // shift
+ &nsGkAtoms::side_, // side
+ &nsGkAtoms::src, // src
+ &nsGkAtoms::stackalign_, // stackalign
+ &nsGkAtoms::stretchy_, // stretchy
+ &nsGkAtoms::subscriptshift_, // subscriptshift
+ &nsGkAtoms::superscriptshift_, // superscriptshift
+ &nsGkAtoms::symmetric_, // symmetric
+ &nsGkAtoms::type, // type
+ &nsGkAtoms::voffset_, // voffset
+ &nsGkAtoms::width, // width
+ &nsGkAtoms::xref_, // xref
+ nullptr
+};
+
+nsIAtom** const kURLAttributesMathML[] = {
+ &nsGkAtoms::href,
+ &nsGkAtoms::src,
+ &nsGkAtoms::cdgroup_,
+ &nsGkAtoms::altimg_,
+ &nsGkAtoms::definitionURL_,
+ nullptr
+};
+
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsHTML = nullptr;
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesHTML = nullptr;
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sPresAttributesHTML = nullptr;
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsSVG = nullptr;
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesSVG = nullptr;
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsMathML = nullptr;
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesMathML = nullptr;
+nsIPrincipal* nsTreeSanitizer::sNullPrincipal = nullptr;
+
+nsTreeSanitizer::nsTreeSanitizer(uint32_t aFlags)
+ : mAllowStyles(aFlags & nsIParserUtils::SanitizerAllowStyle)
+ , mAllowComments(aFlags & nsIParserUtils::SanitizerAllowComments)
+ , mDropNonCSSPresentation(aFlags &
+ nsIParserUtils::SanitizerDropNonCSSPresentation)
+ , mDropForms(aFlags & nsIParserUtils::SanitizerDropForms)
+ , mCidEmbedsOnly(aFlags &
+ nsIParserUtils::SanitizerCidEmbedsOnly)
+ , mDropMedia(aFlags & nsIParserUtils::SanitizerDropMedia)
+ , mFullDocument(false)
+{
+ if (mCidEmbedsOnly) {
+ // Sanitizing styles for external references is not supported.
+ mAllowStyles = false;
+ }
+ if (!sElementsHTML) {
+ // Initialize lazily to avoid having to initialize at all if the user
+ // doesn't paste HTML or load feeds.
+ InitializeStatics();
+ }
+}
+
+bool
+nsTreeSanitizer::MustFlatten(int32_t aNamespace, nsIAtom* aLocal)
+{
+ if (aNamespace == kNameSpaceID_XHTML) {
+ if (mDropNonCSSPresentation && (nsGkAtoms::font == aLocal ||
+ nsGkAtoms::center == aLocal)) {
+ return true;
+ }
+ if (mDropForms && (nsGkAtoms::form == aLocal ||
+ nsGkAtoms::input == aLocal ||
+ nsGkAtoms::keygen == aLocal ||
+ nsGkAtoms::option == aLocal ||
+ nsGkAtoms::optgroup == aLocal)) {
+ return true;
+ }
+ if (mFullDocument && (nsGkAtoms::title == aLocal ||
+ nsGkAtoms::html == aLocal ||
+ nsGkAtoms::head == aLocal ||
+ nsGkAtoms::body == aLocal)) {
+ return false;
+ }
+ return !sElementsHTML->GetEntry(aLocal);
+ }
+ if (aNamespace == kNameSpaceID_SVG) {
+ if (mCidEmbedsOnly || mDropMedia) {
+ // Sanitizing CSS-based URL references inside SVG presentational
+ // attributes is not supported, so flattening for cid: embed case.
+ return true;
+ }
+ return !sElementsSVG->GetEntry(aLocal);
+ }
+ if (aNamespace == kNameSpaceID_MathML) {
+ return !sElementsMathML->GetEntry(aLocal);
+ }
+ return true;
+}
+
+bool
+nsTreeSanitizer::IsURL(nsIAtom*** aURLs, nsIAtom* aLocalName)
+{
+ nsIAtom** atomPtrPtr;
+ while ((atomPtrPtr = *aURLs)) {
+ if (*atomPtrPtr == aLocalName) {
+ return true;
+ }
+ ++aURLs;
+ }
+ return false;
+}
+
+bool
+nsTreeSanitizer::MustPrune(int32_t aNamespace,
+ nsIAtom* aLocal,
+ mozilla::dom::Element* aElement)
+{
+ // To avoid attacks where a MathML script becomes something that gets
+ // serialized in a way that it parses back as an HTML script, let's just
+ // drop elements with the local name 'script' regardless of namespace.
+ if (nsGkAtoms::script == aLocal) {
+ return true;
+ }
+ if (aNamespace == kNameSpaceID_XHTML) {
+ if (nsGkAtoms::title == aLocal && !mFullDocument) {
+ // emulate the quirks of the old parser
+ return true;
+ }
+ if (mDropForms && (nsGkAtoms::select == aLocal ||
+ nsGkAtoms::button == aLocal ||
+ nsGkAtoms::datalist == aLocal)) {
+ return true;
+ }
+ if (mDropMedia && (nsGkAtoms::img == aLocal ||
+ nsGkAtoms::video == aLocal ||
+ nsGkAtoms::audio == aLocal ||
+ nsGkAtoms::source == aLocal)) {
+ return true;
+ }
+ if (nsGkAtoms::meta == aLocal &&
+ (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::charset) ||
+ aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv))) {
+ // Throw away charset declarations even if they also have microdata
+ // which they can't validly have.
+ return true;
+ }
+ if (((!mFullDocument && nsGkAtoms::meta == aLocal) ||
+ nsGkAtoms::link == aLocal) &&
+ !(aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) ||
+ aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope))) {
+ // emulate old behavior for non-Microdata <meta> and <link> presumably
+ // in <head>. <meta> and <link> are whitelisted in order to avoid
+ // corrupting Microdata when they appear in <body>. Note that
+ // SanitizeAttributes() will remove the rel attribute from <link> and
+ // the name attribute from <meta>.
+ return true;
+ }
+ }
+ if (mAllowStyles) {
+ if (nsGkAtoms::style == aLocal && !(aNamespace == kNameSpaceID_XHTML
+ || aNamespace == kNameSpaceID_SVG)) {
+ return true;
+ }
+ return false;
+ }
+ if (nsGkAtoms::style == aLocal) {
+ return true;
+ }
+ return false;
+}
+
+bool
+nsTreeSanitizer::SanitizeStyleDeclaration(mozilla::css::Declaration* aDeclaration,
+ nsAutoString& aRuleText)
+{
+ bool didSanitize = aDeclaration->HasProperty(eCSSProperty_binding);
+ aDeclaration->RemovePropertyByID(eCSSProperty_binding);
+ aDeclaration->ToString(aRuleText);
+ return didSanitize;
+}
+
+bool
+nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
+ nsAString& aSanitized,
+ nsIDocument* aDocument,
+ nsIURI* aBaseURI)
+{
+ nsresult rv;
+ aSanitized.Truncate();
+ // aSanitized will hold the permitted CSS text.
+ // -moz-binding is blacklisted.
+ bool didSanitize = false;
+ // Create a sheet to hold the parsed CSS
+ RefPtr<CSSStyleSheet> sheet =
+ new CSSStyleSheet(mozilla::css::eAuthorSheetFeatures,
+ CORS_NONE, aDocument->GetReferrerPolicy());
+ sheet->SetURIs(aDocument->GetDocumentURI(), nullptr, aBaseURI);
+ sheet->SetPrincipal(aDocument->NodePrincipal());
+ // Create the CSS parser, and parse the CSS text.
+ nsCSSParser parser(nullptr, sheet);
+ rv = parser.ParseSheet(aOriginal, aDocument->GetDocumentURI(), aBaseURI,
+ aDocument->NodePrincipal(), 0);
+ NS_ENSURE_SUCCESS(rv, true);
+ // Mark the sheet as complete.
+ MOZ_ASSERT(!sheet->IsModified(),
+ "should not get marked modified during parsing");
+ sheet->SetComplete();
+ // Loop through all the rules found in the CSS text
+ int32_t ruleCount = sheet->StyleRuleCount();
+ for (int32_t i = 0; i < ruleCount; ++i) {
+ mozilla::css::Rule* rule = sheet->GetStyleRuleAt(i);
+ if (!rule)
+ continue;
+ switch (rule->GetType()) {
+ default:
+ didSanitize = true;
+ // Ignore these rule types.
+ break;
+ case mozilla::css::Rule::NAMESPACE_RULE:
+ case mozilla::css::Rule::FONT_FACE_RULE: {
+ // Append @namespace and @font-face rules verbatim.
+ nsAutoString cssText;
+ nsCOMPtr<nsIDOMCSSRule> styleRule = do_QueryInterface(rule);
+ if (styleRule) {
+ rv = styleRule->GetCssText(cssText);
+ if (NS_SUCCEEDED(rv)) {
+ aSanitized.Append(cssText);
+ }
+ }
+ break;
+ }
+ case mozilla::css::Rule::STYLE_RULE: {
+ // For style rules, we will just look for and remove the
+ // -moz-binding properties.
+ RefPtr<mozilla::css::StyleRule> styleRule = do_QueryObject(rule);
+ NS_ASSERTION(styleRule, "Must be a style rule");
+ nsAutoString decl;
+ bool sanitized =
+ SanitizeStyleDeclaration(styleRule->GetDeclaration(), decl);
+ didSanitize = sanitized || didSanitize;
+ if (!sanitized) {
+ styleRule->GetCssText(decl);
+ }
+ aSanitized.Append(decl);
+ }
+ }
+ }
+ return didSanitize;
+}
+
+void
+nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
+ nsTHashtable<nsISupportsHashKey>* aAllowed,
+ nsIAtom*** aURLs,
+ bool aAllowXLink,
+ bool aAllowStyle,
+ bool aAllowDangerousSrc)
+{
+ uint32_t ac = aElement->GetAttrCount();
+
+ for (int32_t i = ac - 1; i >= 0; --i) {
+ const nsAttrName* attrName = aElement->GetAttrNameAt(i);
+ int32_t attrNs = attrName->NamespaceID();
+ nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
+
+ if (kNameSpaceID_None == attrNs) {
+ if (aAllowStyle && nsGkAtoms::style == attrLocal) {
+ nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
+ nsIDocument* document = aElement->OwnerDoc();
+ // Pass the CSS Loader object to the parser, to allow parser error
+ // reports to include the outer window ID.
+ nsCSSParser parser(document->CSSLoader());
+ nsAutoString value;
+ aElement->GetAttr(attrNs, attrLocal, value);
+ RefPtr<mozilla::css::Declaration> decl =
+ parser.ParseStyleAttribute(value, document->GetDocumentURI(),
+ baseURI, document->NodePrincipal());
+ if (decl) {
+ nsAutoString cleanValue;
+ if (SanitizeStyleDeclaration(decl, cleanValue)) {
+ aElement->SetAttr(kNameSpaceID_None,
+ nsGkAtoms::style,
+ cleanValue,
+ false);
+ }
+ }
+ continue;
+ }
+ if (aAllowDangerousSrc && nsGkAtoms::src == attrLocal) {
+ continue;
+ }
+ if (IsURL(aURLs, attrLocal)) {
+ if (SanitizeURL(aElement, attrNs, attrLocal)) {
+ // in case the attribute removal shuffled the attribute order, start
+ // the loop again.
+ --ac;
+ i = ac; // i will be decremented immediately thanks to the for loop
+ continue;
+ }
+ // else fall through to see if there's another reason to drop this
+ // attribute (in particular if the attribute is background="" on an
+ // HTML element)
+ }
+ if (!mDropNonCSSPresentation &&
+ (aAllowed == sAttributesHTML) && // element is HTML
+ sPresAttributesHTML->GetEntry(attrLocal)) {
+ continue;
+ }
+ if (aAllowed->GetEntry(attrLocal) &&
+ !((attrLocal == nsGkAtoms::rel &&
+ aElement->IsHTMLElement(nsGkAtoms::link)) ||
+ (!mFullDocument &&
+ attrLocal == nsGkAtoms::name &&
+ aElement->IsHTMLElement(nsGkAtoms::meta)))) {
+ // name="" and rel="" are whitelisted, but treat them as blacklisted
+ // for <meta name> (fragment case) and <link rel> (all cases) to avoid
+ // document-wide metadata or styling overrides with non-conforming
+ // <meta name itemprop> or
+ // <link rel itemprop>
+ continue;
+ }
+ const char16_t* localStr = attrLocal->GetUTF16String();
+ // Allow underscore to cater to the MCE editor library.
+ // Allow data-* on SVG and MathML, too, as a forward-compat measure.
+ if (*localStr == '_' || (attrLocal->GetLength() > 5 && localStr[0] == 'd'
+ && localStr[1] == 'a' && localStr[2] == 't' && localStr[3] == 'a'
+ && localStr[4] == '-')) {
+ continue;
+ }
+ // else not allowed
+ } else if (kNameSpaceID_XML == attrNs) {
+ if (nsGkAtoms::base == attrLocal) {
+ if (SanitizeURL(aElement, attrNs, attrLocal)) {
+ // in case the attribute removal shuffled the attribute order, start
+ // the loop again.
+ --ac;
+ i = ac; // i will be decremented immediately thanks to the for loop
+ }
+ continue;
+ }
+ if (nsGkAtoms::lang == attrLocal || nsGkAtoms::space == attrLocal) {
+ continue;
+ }
+ // else not allowed
+ } else if (aAllowXLink && kNameSpaceID_XLink == attrNs) {
+ if (nsGkAtoms::href == attrLocal) {
+ if (SanitizeURL(aElement, attrNs, attrLocal)) {
+ // in case the attribute removal shuffled the attribute order, start
+ // the loop again.
+ --ac;
+ i = ac; // i will be decremented immediately thanks to the for loop
+ }
+ continue;
+ }
+ if (nsGkAtoms::type == attrLocal || nsGkAtoms::title == attrLocal
+ || nsGkAtoms::show == attrLocal || nsGkAtoms::actuate == attrLocal) {
+ continue;
+ }
+ // else not allowed
+ }
+ aElement->UnsetAttr(kNameSpaceID_None, attrLocal, false);
+ // in case the attribute removal shuffled the attribute order, start the
+ // loop again.
+ --ac;
+ i = ac; // i will be decremented immediately thanks to the for loop
+ }
+
+ // If we've got HTML audio or video, add the controls attribute, because
+ // otherwise the content is unplayable with scripts removed.
+ if (aElement->IsAnyOfHTMLElements(nsGkAtoms::video, nsGkAtoms::audio)) {
+ aElement->SetAttr(kNameSpaceID_None,
+ nsGkAtoms::controls,
+ EmptyString(),
+ false);
+ }
+}
+
+bool
+nsTreeSanitizer::SanitizeURL(mozilla::dom::Element* aElement,
+ int32_t aNamespace,
+ nsIAtom* aLocalName)
+{
+ nsAutoString value;
+ aElement->GetAttr(aNamespace, aLocalName, value);
+
+ // Get value and remove mandatory quotes
+ static const char* kWhitespace = "\n\r\t\b";
+ const nsAString& v =
+ nsContentUtils::TrimCharsInSet(kWhitespace, value);
+
+ nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
+ uint32_t flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL;
+
+ nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
+ nsCOMPtr<nsIURI> attrURI;
+ nsresult rv = NS_NewURI(getter_AddRefs(attrURI), v, nullptr, baseURI);
+ if (NS_SUCCEEDED(rv)) {
+ if (mCidEmbedsOnly &&
+ kNameSpaceID_None == aNamespace) {
+ if (nsGkAtoms::src == aLocalName || nsGkAtoms::background == aLocalName) {
+ // comm-central uses a hack that makes nsIURIs created with cid: specs
+ // actually have an about:blank spec. Therefore, nsIURI facilities are
+ // useless for cid: when comm-central code is participating.
+ if (!(v.Length() > 4 &&
+ (v[0] == 'c' || v[0] == 'C') &&
+ (v[1] == 'i' || v[1] == 'I') &&
+ (v[2] == 'd' || v[2] == 'D') &&
+ v[3] == ':')) {
+ rv = NS_ERROR_FAILURE;
+ }
+ } else if (nsGkAtoms::cdgroup_ == aLocalName ||
+ nsGkAtoms::altimg_ == aLocalName ||
+ nsGkAtoms::definitionURL_ == aLocalName) {
+ // Gecko doesn't fetch these now and shouldn't in the future, but
+ // in case someone goofs with these in the future, let's drop them.
+ rv = NS_ERROR_FAILURE;
+ } else {
+ rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
+ }
+ } else {
+ rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
+ }
+ }
+ if (NS_FAILED(rv)) {
+ aElement->UnsetAttr(aNamespace, aLocalName, false);
+ return true;
+ }
+ return false;
+}
+
+void
+nsTreeSanitizer::Sanitize(nsIContent* aFragment)
+{
+ // If you want to relax these preconditions, be sure to check the code in
+ // here that notifies / does not notify or that fires mutation events if
+ // in tree.
+ NS_PRECONDITION(aFragment->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT),
+ "Argument was not DOM fragment.");
+ NS_PRECONDITION(!aFragment->IsInUncomposedDoc(), "The fragment is in doc?");
+
+ mFullDocument = false;
+ SanitizeChildren(aFragment);
+}
+
+void
+nsTreeSanitizer::Sanitize(nsIDocument* aDocument)
+{
+ // If you want to relax these preconditions, be sure to check the code in
+ // here that notifies / does not notify or that fires mutation events if
+ // in tree.
+#ifdef DEBUG
+ NS_PRECONDITION(!aDocument->GetContainer(), "The document is in a shell.");
+ RefPtr<mozilla::dom::Element> root = aDocument->GetRootElement();
+ NS_PRECONDITION(root->IsHTMLElement(nsGkAtoms::html), "Not HTML root.");
+#endif
+
+ mFullDocument = true;
+ SanitizeChildren(aDocument);
+}
+
+void
+nsTreeSanitizer::SanitizeChildren(nsINode* aRoot)
+{
+ nsIContent* node = aRoot->GetFirstChild();
+ while (node) {
+ if (node->IsElement()) {
+ mozilla::dom::Element* elt = node->AsElement();
+ mozilla::dom::NodeInfo* nodeInfo = node->NodeInfo();
+ nsIAtom* localName = nodeInfo->NameAtom();
+ int32_t ns = nodeInfo->NamespaceID();
+
+ if (MustPrune(ns, localName, elt)) {
+ RemoveAllAttributes(node);
+ nsIContent* descendant = node;
+ while ((descendant = descendant->GetNextNode(node))) {
+ RemoveAllAttributes(descendant);
+ }
+ nsIContent* next = node->GetNextNonChildNode(aRoot);
+ node->RemoveFromParent();
+ node = next;
+ continue;
+ }
+ if (nsGkAtoms::style == localName) {
+ // If styles aren't allowed, style elements got pruned above. Even
+ // if styles are allowed, non-HTML, non-SVG style elements got pruned
+ // above.
+ NS_ASSERTION(ns == kNameSpaceID_XHTML || ns == kNameSpaceID_SVG,
+ "Should have only HTML or SVG here!");
+ nsAutoString styleText;
+ nsContentUtils::GetNodeTextContent(node, false, styleText);
+
+ nsAutoString sanitizedStyle;
+ nsCOMPtr<nsIURI> baseURI = node->GetBaseURI();
+ if (SanitizeStyleSheet(styleText,
+ sanitizedStyle,
+ aRoot->OwnerDoc(),
+ baseURI)) {
+ nsContentUtils::SetNodeTextContent(node, sanitizedStyle, true);
+ } else {
+ // If the node had non-text child nodes, this operation zaps those.
+ nsContentUtils::SetNodeTextContent(node, styleText, true);
+ }
+ if (ns == kNameSpaceID_XHTML) {
+ SanitizeAttributes(elt,
+ sAttributesHTML,
+ (nsIAtom***)kURLAttributesHTML,
+ false,
+ mAllowStyles,
+ false);
+ } else {
+ SanitizeAttributes(elt,
+ sAttributesSVG,
+ (nsIAtom***)kURLAttributesSVG,
+ true,
+ mAllowStyles,
+ false);
+ }
+ node = node->GetNextNonChildNode(aRoot);
+ continue;
+ }
+ if (MustFlatten(ns, localName)) {
+ RemoveAllAttributes(node);
+ nsCOMPtr<nsIContent> next = node->GetNextNode(aRoot);
+ nsCOMPtr<nsIContent> parent = node->GetParent();
+ nsCOMPtr<nsIContent> child; // Must keep the child alive during move
+ ErrorResult rv;
+ while ((child = node->GetFirstChild())) {
+ nsCOMPtr<nsINode> refNode = node;
+ parent->InsertBefore(*child, refNode, rv);
+ if (rv.Failed()) {
+ break;
+ }
+ }
+ node->RemoveFromParent();
+ node = next;
+ continue;
+ }
+ NS_ASSERTION(ns == kNameSpaceID_XHTML ||
+ ns == kNameSpaceID_SVG ||
+ ns == kNameSpaceID_MathML,
+ "Should have only HTML, MathML or SVG here!");
+ if (ns == kNameSpaceID_XHTML) {
+ SanitizeAttributes(elt,
+ sAttributesHTML,
+ (nsIAtom***)kURLAttributesHTML,
+ false, mAllowStyles,
+ (nsGkAtoms::img == localName) &&
+ !mCidEmbedsOnly);
+ } else if (ns == kNameSpaceID_SVG) {
+ SanitizeAttributes(elt,
+ sAttributesSVG,
+ (nsIAtom***)kURLAttributesSVG,
+ true,
+ mAllowStyles,
+ false);
+ } else {
+ SanitizeAttributes(elt,
+ sAttributesMathML,
+ (nsIAtom***)kURLAttributesMathML,
+ true,
+ false,
+ false);
+ }
+ node = node->GetNextNode(aRoot);
+ continue;
+ }
+ NS_ASSERTION(!node->GetFirstChild(), "How come non-element node had kids?");
+ nsIContent* next = node->GetNextNonChildNode(aRoot);
+ if (!mAllowComments && node->IsNodeOfType(nsINode::eCOMMENT)) {
+ node->RemoveFromParent();
+ }
+ node = next;
+ }
+}
+
+void
+nsTreeSanitizer::RemoveAllAttributes(nsIContent* aElement)
+{
+ const nsAttrName* attrName;
+ while ((attrName = aElement->GetAttrNameAt(0))) {
+ int32_t attrNs = attrName->NamespaceID();
+ nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
+ aElement->UnsetAttr(attrNs, attrLocal, false);
+ }
+}
+
+void
+nsTreeSanitizer::InitializeStatics()
+{
+ NS_PRECONDITION(!sElementsHTML, "Initializing a second time.");
+
+ sElementsHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsHTML));
+ for (uint32_t i = 0; kElementsHTML[i]; i++) {
+ sElementsHTML->PutEntry(*kElementsHTML[i]);
+ }
+
+ sAttributesHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesHTML));
+ for (uint32_t i = 0; kAttributesHTML[i]; i++) {
+ sAttributesHTML->PutEntry(*kAttributesHTML[i]);
+ }
+
+ sPresAttributesHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kPresAttributesHTML));
+ for (uint32_t i = 0; kPresAttributesHTML[i]; i++) {
+ sPresAttributesHTML->PutEntry(*kPresAttributesHTML[i]);
+ }
+
+ sElementsSVG = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsSVG));
+ for (uint32_t i = 0; kElementsSVG[i]; i++) {
+ sElementsSVG->PutEntry(*kElementsSVG[i]);
+ }
+
+ sAttributesSVG = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesSVG));
+ for (uint32_t i = 0; kAttributesSVG[i]; i++) {
+ sAttributesSVG->PutEntry(*kAttributesSVG[i]);
+ }
+
+ sElementsMathML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsMathML));
+ for (uint32_t i = 0; kElementsMathML[i]; i++) {
+ sElementsMathML->PutEntry(*kElementsMathML[i]);
+ }
+
+ sAttributesMathML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesMathML));
+ for (uint32_t i = 0; kAttributesMathML[i]; i++) {
+ sAttributesMathML->PutEntry(*kAttributesMathML[i]);
+ }
+
+ nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
+ principal.forget(&sNullPrincipal);
+}
+
+void
+nsTreeSanitizer::ReleaseStatics()
+{
+ delete sElementsHTML;
+ sElementsHTML = nullptr;
+
+ delete sAttributesHTML;
+ sAttributesHTML = nullptr;
+
+ delete sPresAttributesHTML;
+ sPresAttributesHTML = nullptr;
+
+ delete sElementsSVG;
+ sElementsSVG = nullptr;
+
+ delete sAttributesSVG;
+ sAttributesSVG = nullptr;
+
+ delete sElementsMathML;
+ sElementsMathML = nullptr;
+
+ delete sAttributesMathML;
+ sAttributesMathML = nullptr;
+
+ NS_IF_RELEASE(sNullPrincipal);
+}