content/base/src/nsTreeSanitizer.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/base/src/nsTreeSanitizer.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1568 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim: set sw=2 ts=2 et tw=80: */
     1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#include "mozilla/ArrayUtils.h"
    1.11 +
    1.12 +#include "nsTreeSanitizer.h"
    1.13 +#include "nsCSSParser.h"
    1.14 +#include "nsCSSProperty.h"
    1.15 +#include "mozilla/css/Declaration.h"
    1.16 +#include "mozilla/css/StyleRule.h"
    1.17 +#include "mozilla/css/Rule.h"
    1.18 +#include "nsUnicharInputStream.h"
    1.19 +#include "nsCSSStyleSheet.h"
    1.20 +#include "nsIDOMCSSRule.h"
    1.21 +#include "nsAttrName.h"
    1.22 +#include "nsIScriptSecurityManager.h"
    1.23 +#include "nsNetUtil.h"
    1.24 +#include "nsComponentManagerUtils.h"
    1.25 +#include "nsNullPrincipal.h"
    1.26 +#include "nsContentUtils.h"
    1.27 +#include "nsIParserUtils.h"
    1.28 +#include "nsIDocument.h"
    1.29 +
    1.30 +using namespace mozilla;
    1.31 +
    1.32 +//
    1.33 +// Thanks to Mark Pilgrim and Sam Ruby for the initial whitelist
    1.34 +//
    1.35 +nsIAtom** const kElementsHTML[] = {
    1.36 +  &nsGkAtoms::a,
    1.37 +  &nsGkAtoms::abbr,
    1.38 +  &nsGkAtoms::acronym,
    1.39 +  &nsGkAtoms::address,
    1.40 +  &nsGkAtoms::area,
    1.41 +  &nsGkAtoms::article,
    1.42 +  &nsGkAtoms::aside,
    1.43 +  &nsGkAtoms::audio,
    1.44 +  &nsGkAtoms::b,
    1.45 +  &nsGkAtoms::bdi,
    1.46 +  &nsGkAtoms::bdo,
    1.47 +  &nsGkAtoms::big,
    1.48 +  &nsGkAtoms::blockquote,
    1.49 +  // body checked specially
    1.50 +  &nsGkAtoms::br,
    1.51 +  &nsGkAtoms::button,
    1.52 +  &nsGkAtoms::canvas,
    1.53 +  &nsGkAtoms::caption,
    1.54 +  &nsGkAtoms::center,
    1.55 +  &nsGkAtoms::cite,
    1.56 +  &nsGkAtoms::code,
    1.57 +  &nsGkAtoms::col,
    1.58 +  &nsGkAtoms::colgroup,
    1.59 +  &nsGkAtoms::command,
    1.60 +  &nsGkAtoms::datalist,
    1.61 +  &nsGkAtoms::dd,
    1.62 +  &nsGkAtoms::del,
    1.63 +  &nsGkAtoms::details,
    1.64 +  &nsGkAtoms::dfn,
    1.65 +  &nsGkAtoms::dir,
    1.66 +  &nsGkAtoms::div,
    1.67 +  &nsGkAtoms::dl,
    1.68 +  &nsGkAtoms::dt,
    1.69 +  &nsGkAtoms::em,
    1.70 +  &nsGkAtoms::fieldset,
    1.71 +  &nsGkAtoms::figcaption,
    1.72 +  &nsGkAtoms::figure,
    1.73 +  &nsGkAtoms::font,
    1.74 +  &nsGkAtoms::footer,
    1.75 +  &nsGkAtoms::form,
    1.76 +  &nsGkAtoms::h1,
    1.77 +  &nsGkAtoms::h2,
    1.78 +  &nsGkAtoms::h3,
    1.79 +  &nsGkAtoms::h4,
    1.80 +  &nsGkAtoms::h5,
    1.81 +  &nsGkAtoms::h6,
    1.82 +  // head checked specially
    1.83 +  &nsGkAtoms::header,
    1.84 +  &nsGkAtoms::hgroup,
    1.85 +  &nsGkAtoms::hr,
    1.86 +  // html checked specially
    1.87 +  &nsGkAtoms::i,
    1.88 +  &nsGkAtoms::img,
    1.89 +  &nsGkAtoms::input,
    1.90 +  &nsGkAtoms::ins,
    1.91 +  &nsGkAtoms::kbd,
    1.92 +  &nsGkAtoms::label,
    1.93 +  &nsGkAtoms::legend,
    1.94 +  &nsGkAtoms::li,
    1.95 +  &nsGkAtoms::link,
    1.96 +  &nsGkAtoms::listing,
    1.97 +  &nsGkAtoms::map,
    1.98 +  &nsGkAtoms::mark,
    1.99 +  &nsGkAtoms::menu,
   1.100 +  &nsGkAtoms::meta,
   1.101 +  &nsGkAtoms::meter,
   1.102 +  &nsGkAtoms::nav,
   1.103 +  &nsGkAtoms::nobr,
   1.104 +  &nsGkAtoms::noscript,
   1.105 +  &nsGkAtoms::ol,
   1.106 +  &nsGkAtoms::optgroup,
   1.107 +  &nsGkAtoms::option,
   1.108 +  &nsGkAtoms::output,
   1.109 +  &nsGkAtoms::p,
   1.110 +  &nsGkAtoms::pre,
   1.111 +  &nsGkAtoms::progress,
   1.112 +  &nsGkAtoms::q,
   1.113 +  &nsGkAtoms::rp,
   1.114 +  &nsGkAtoms::rt,
   1.115 +  &nsGkAtoms::ruby,
   1.116 +  &nsGkAtoms::s,
   1.117 +  &nsGkAtoms::samp,
   1.118 +  &nsGkAtoms::section,
   1.119 +  &nsGkAtoms::select,
   1.120 +  &nsGkAtoms::small,
   1.121 +  &nsGkAtoms::source,
   1.122 +  &nsGkAtoms::span,
   1.123 +  &nsGkAtoms::strike,
   1.124 +  &nsGkAtoms::strong,
   1.125 +  &nsGkAtoms::sub,
   1.126 +  &nsGkAtoms::summary,
   1.127 +  &nsGkAtoms::sup,
   1.128 +  // style checked specially
   1.129 +  &nsGkAtoms::table,
   1.130 +  &nsGkAtoms::tbody,
   1.131 +  &nsGkAtoms::td,
   1.132 +  &nsGkAtoms::textarea,
   1.133 +  &nsGkAtoms::tfoot,
   1.134 +  &nsGkAtoms::th,
   1.135 +  &nsGkAtoms::thead,
   1.136 +  &nsGkAtoms::time,
   1.137 +  // title checked specially
   1.138 +  &nsGkAtoms::tr,
   1.139 +  &nsGkAtoms::track,
   1.140 +  &nsGkAtoms::tt,
   1.141 +  &nsGkAtoms::u,
   1.142 +  &nsGkAtoms::ul,
   1.143 +  &nsGkAtoms::var,
   1.144 +  &nsGkAtoms::video,
   1.145 +  &nsGkAtoms::wbr,
   1.146 +  nullptr
   1.147 +};
   1.148 +
   1.149 +nsIAtom** const kAttributesHTML[] = {
   1.150 +  &nsGkAtoms::abbr,
   1.151 +  &nsGkAtoms::accept,
   1.152 +  &nsGkAtoms::acceptcharset,
   1.153 +  &nsGkAtoms::accesskey,
   1.154 +  &nsGkAtoms::action,
   1.155 +  &nsGkAtoms::alt,
   1.156 +  &nsGkAtoms::autocomplete,
   1.157 +  &nsGkAtoms::autofocus,
   1.158 +  &nsGkAtoms::autoplay,
   1.159 +  &nsGkAtoms::axis,
   1.160 +  &nsGkAtoms::_char,
   1.161 +  &nsGkAtoms::charoff,
   1.162 +  &nsGkAtoms::charset,
   1.163 +  &nsGkAtoms::checked,
   1.164 +  &nsGkAtoms::cite,
   1.165 +  &nsGkAtoms::_class,
   1.166 +  &nsGkAtoms::cols,
   1.167 +  &nsGkAtoms::colspan,
   1.168 +  &nsGkAtoms::content,
   1.169 +  &nsGkAtoms::contenteditable,
   1.170 +  &nsGkAtoms::contextmenu,
   1.171 +  &nsGkAtoms::controls,
   1.172 +  &nsGkAtoms::coords,
   1.173 +  &nsGkAtoms::datetime,
   1.174 +  &nsGkAtoms::dir,
   1.175 +  &nsGkAtoms::disabled,
   1.176 +  &nsGkAtoms::draggable,
   1.177 +  &nsGkAtoms::enctype,
   1.178 +  &nsGkAtoms::face,
   1.179 +  &nsGkAtoms::_for,
   1.180 +  &nsGkAtoms::frame,
   1.181 +  &nsGkAtoms::headers,
   1.182 +  &nsGkAtoms::height,
   1.183 +  &nsGkAtoms::hidden,
   1.184 +  &nsGkAtoms::high,
   1.185 +  &nsGkAtoms::href,
   1.186 +  &nsGkAtoms::hreflang,
   1.187 +  &nsGkAtoms::icon,
   1.188 +  &nsGkAtoms::id,
   1.189 +  &nsGkAtoms::ismap,
   1.190 +  &nsGkAtoms::itemid,
   1.191 +  &nsGkAtoms::itemprop,
   1.192 +  &nsGkAtoms::itemref,
   1.193 +  &nsGkAtoms::itemscope,
   1.194 +  &nsGkAtoms::itemtype,
   1.195 +  &nsGkAtoms::kind,
   1.196 +  &nsGkAtoms::label,
   1.197 +  &nsGkAtoms::lang,
   1.198 +  &nsGkAtoms::list,
   1.199 +  &nsGkAtoms::longdesc,
   1.200 +  &nsGkAtoms::loop,
   1.201 +  &nsGkAtoms::low,
   1.202 +  &nsGkAtoms::max,
   1.203 +  &nsGkAtoms::maxlength,
   1.204 +  &nsGkAtoms::media,
   1.205 +  &nsGkAtoms::method,
   1.206 +  &nsGkAtoms::min,
   1.207 +  &nsGkAtoms::mozdonotsend,
   1.208 +  &nsGkAtoms::multiple,
   1.209 +  &nsGkAtoms::muted,
   1.210 +  &nsGkAtoms::name,
   1.211 +  &nsGkAtoms::nohref,
   1.212 +  &nsGkAtoms::novalidate,
   1.213 +  &nsGkAtoms::nowrap,
   1.214 +  &nsGkAtoms::open,
   1.215 +  &nsGkAtoms::optimum,
   1.216 +  &nsGkAtoms::pattern,
   1.217 +  &nsGkAtoms::placeholder,
   1.218 +  &nsGkAtoms::playbackrate,
   1.219 +  &nsGkAtoms::poster,
   1.220 +  &nsGkAtoms::preload,
   1.221 +  &nsGkAtoms::prompt,
   1.222 +  &nsGkAtoms::pubdate,
   1.223 +  &nsGkAtoms::radiogroup,
   1.224 +  &nsGkAtoms::readonly,
   1.225 +  &nsGkAtoms::rel,
   1.226 +  &nsGkAtoms::required,
   1.227 +  &nsGkAtoms::rev,
   1.228 +  &nsGkAtoms::reversed,
   1.229 +  &nsGkAtoms::role,
   1.230 +  &nsGkAtoms::rows,
   1.231 +  &nsGkAtoms::rowspan,
   1.232 +  &nsGkAtoms::rules,
   1.233 +  &nsGkAtoms::scoped,
   1.234 +  &nsGkAtoms::scope,
   1.235 +  &nsGkAtoms::selected,
   1.236 +  &nsGkAtoms::shape,
   1.237 +  &nsGkAtoms::span,
   1.238 +  &nsGkAtoms::spellcheck,
   1.239 +  &nsGkAtoms::src,
   1.240 +  &nsGkAtoms::srclang,
   1.241 +  &nsGkAtoms::start,
   1.242 +  &nsGkAtoms::summary,
   1.243 +  &nsGkAtoms::tabindex,
   1.244 +  &nsGkAtoms::target,
   1.245 +  &nsGkAtoms::title,
   1.246 +  &nsGkAtoms::type,
   1.247 +  &nsGkAtoms::usemap,
   1.248 +  &nsGkAtoms::value,
   1.249 +  &nsGkAtoms::width,
   1.250 +  &nsGkAtoms::wrap,
   1.251 +  nullptr
   1.252 +};
   1.253 +
   1.254 +nsIAtom** const kPresAttributesHTML[] = {
   1.255 +  &nsGkAtoms::align,
   1.256 +  &nsGkAtoms::background,
   1.257 +  &nsGkAtoms::bgcolor,
   1.258 +  &nsGkAtoms::border,
   1.259 +  &nsGkAtoms::cellpadding,
   1.260 +  &nsGkAtoms::cellspacing,
   1.261 +  &nsGkAtoms::color,
   1.262 +  &nsGkAtoms::compact,
   1.263 +  &nsGkAtoms::clear,
   1.264 +  &nsGkAtoms::hspace,
   1.265 +  &nsGkAtoms::noshade,
   1.266 +  &nsGkAtoms::pointSize,
   1.267 +  &nsGkAtoms::size,
   1.268 +  &nsGkAtoms::valign,
   1.269 +  &nsGkAtoms::vspace,
   1.270 +  nullptr
   1.271 +};
   1.272 +
   1.273 +nsIAtom** const kURLAttributesHTML[] = {
   1.274 +  &nsGkAtoms::action,
   1.275 +  &nsGkAtoms::href,
   1.276 +  &nsGkAtoms::src,
   1.277 +  &nsGkAtoms::longdesc,
   1.278 +  &nsGkAtoms::cite,
   1.279 +  &nsGkAtoms::background,
   1.280 +  nullptr
   1.281 +};
   1.282 +
   1.283 +nsIAtom** const kElementsSVG[] = {
   1.284 +  &nsGkAtoms::a, // a
   1.285 +  &nsGkAtoms::altGlyph, // altGlyph
   1.286 +  &nsGkAtoms::altGlyphDef, // altGlyphDef
   1.287 +  &nsGkAtoms::altGlyphItem, // altGlyphItem
   1.288 +  &nsGkAtoms::animate, // animate
   1.289 +  &nsGkAtoms::animateColor, // animateColor
   1.290 +  &nsGkAtoms::animateMotion, // animateMotion
   1.291 +  &nsGkAtoms::animateTransform, // animateTransform
   1.292 +  &nsGkAtoms::circle, // circle
   1.293 +  &nsGkAtoms::clipPath, // clipPath
   1.294 +  &nsGkAtoms::colorProfile, // color-profile
   1.295 +  &nsGkAtoms::cursor, // cursor
   1.296 +  &nsGkAtoms::defs, // defs
   1.297 +  &nsGkAtoms::desc, // desc
   1.298 +  &nsGkAtoms::ellipse, // ellipse
   1.299 +  &nsGkAtoms::elevation, // elevation
   1.300 +  &nsGkAtoms::erode, // erode
   1.301 +  &nsGkAtoms::ex, // ex
   1.302 +  &nsGkAtoms::exact, // exact
   1.303 +  &nsGkAtoms::exponent, // exponent
   1.304 +  &nsGkAtoms::feBlend, // feBlend
   1.305 +  &nsGkAtoms::feColorMatrix, // feColorMatrix
   1.306 +  &nsGkAtoms::feComponentTransfer, // feComponentTransfer
   1.307 +  &nsGkAtoms::feComposite, // feComposite
   1.308 +  &nsGkAtoms::feConvolveMatrix, // feConvolveMatrix
   1.309 +  &nsGkAtoms::feDiffuseLighting, // feDiffuseLighting
   1.310 +  &nsGkAtoms::feDisplacementMap, // feDisplacementMap
   1.311 +  &nsGkAtoms::feDistantLight, // feDistantLight
   1.312 +  &nsGkAtoms::feDropShadow, // feDropShadow
   1.313 +  &nsGkAtoms::feFlood, // feFlood
   1.314 +  &nsGkAtoms::feFuncA, // feFuncA
   1.315 +  &nsGkAtoms::feFuncB, // feFuncB
   1.316 +  &nsGkAtoms::feFuncG, // feFuncG
   1.317 +  &nsGkAtoms::feFuncR, // feFuncR
   1.318 +  &nsGkAtoms::feGaussianBlur, // feGaussianBlur
   1.319 +  &nsGkAtoms::feImage, // feImage
   1.320 +  &nsGkAtoms::feMerge, // feMerge
   1.321 +  &nsGkAtoms::feMergeNode, // feMergeNode
   1.322 +  &nsGkAtoms::feMorphology, // feMorphology
   1.323 +  &nsGkAtoms::feOffset, // feOffset
   1.324 +  &nsGkAtoms::fePointLight, // fePointLight
   1.325 +  &nsGkAtoms::feSpecularLighting, // feSpecularLighting
   1.326 +  &nsGkAtoms::feSpotLight, // feSpotLight
   1.327 +  &nsGkAtoms::feTile, // feTile
   1.328 +  &nsGkAtoms::feTurbulence, // feTurbulence
   1.329 +  &nsGkAtoms::filter, // filter
   1.330 +  &nsGkAtoms::font, // font
   1.331 +  &nsGkAtoms::font_face, // font-face
   1.332 +  &nsGkAtoms::font_face_format, // font-face-format
   1.333 +  &nsGkAtoms::font_face_name, // font-face-name
   1.334 +  &nsGkAtoms::font_face_src, // font-face-src
   1.335 +  &nsGkAtoms::font_face_uri, // font-face-uri
   1.336 +  &nsGkAtoms::foreignObject, // foreignObject
   1.337 +  &nsGkAtoms::g, // g
   1.338 +  &nsGkAtoms::glyph, // glyph
   1.339 +  &nsGkAtoms::glyphRef, // glyphRef
   1.340 +  &nsGkAtoms::hkern, // hkern
   1.341 +  &nsGkAtoms::image, // image
   1.342 +  &nsGkAtoms::line, // line
   1.343 +  &nsGkAtoms::linearGradient, // linearGradient
   1.344 +  &nsGkAtoms::marker, // marker
   1.345 +  &nsGkAtoms::mask, // mask
   1.346 +  &nsGkAtoms::metadata, // metadata
   1.347 +  &nsGkAtoms::missingGlyph, // missingGlyph
   1.348 +  &nsGkAtoms::mpath, // mpath
   1.349 +  &nsGkAtoms::path, // path
   1.350 +  &nsGkAtoms::pattern, // pattern
   1.351 +  &nsGkAtoms::polygon, // polygon
   1.352 +  &nsGkAtoms::polyline, // polyline
   1.353 +  &nsGkAtoms::radialGradient, // radialGradient
   1.354 +  &nsGkAtoms::rect, // rect
   1.355 +  &nsGkAtoms::set, // set
   1.356 +  &nsGkAtoms::stop, // stop
   1.357 +  &nsGkAtoms::svg, // svg
   1.358 +  &nsGkAtoms::svgSwitch, // switch
   1.359 +  &nsGkAtoms::symbol, // symbol
   1.360 +  &nsGkAtoms::text, // text
   1.361 +  &nsGkAtoms::textPath, // textPath
   1.362 +  &nsGkAtoms::title, // title
   1.363 +  &nsGkAtoms::tref, // tref
   1.364 +  &nsGkAtoms::tspan, // tspan
   1.365 +  &nsGkAtoms::use, // use
   1.366 +  &nsGkAtoms::view, // view
   1.367 +  &nsGkAtoms::vkern, // vkern
   1.368 +  nullptr
   1.369 +};
   1.370 +
   1.371 +nsIAtom** const kAttributesSVG[] = {
   1.372 +  // accent-height
   1.373 +  &nsGkAtoms::accumulate, // accumulate
   1.374 +  &nsGkAtoms::additive, // additive
   1.375 +  &nsGkAtoms::alignment_baseline, // alignment-baseline
   1.376 +  // alphabetic
   1.377 +  &nsGkAtoms::amplitude, // amplitude
   1.378 +  // arabic-form
   1.379 +  // ascent
   1.380 +  &nsGkAtoms::attributeName, // attributeName
   1.381 +  &nsGkAtoms::attributeType, // attributeType
   1.382 +  &nsGkAtoms::azimuth, // azimuth
   1.383 +  &nsGkAtoms::baseFrequency, // baseFrequency
   1.384 +  &nsGkAtoms::baseline_shift, // baseline-shift
   1.385 +  // baseProfile
   1.386 +  // bbox
   1.387 +  &nsGkAtoms::begin, // begin
   1.388 +  &nsGkAtoms::bias, // bias
   1.389 +  &nsGkAtoms::by, // by
   1.390 +  &nsGkAtoms::calcMode, // calcMode
   1.391 +  // cap-height
   1.392 +  &nsGkAtoms::_class, // class
   1.393 +  &nsGkAtoms::clip_path, // clip-path
   1.394 +  &nsGkAtoms::clip_rule, // clip-rule
   1.395 +  &nsGkAtoms::clipPathUnits, // clipPathUnits
   1.396 +  &nsGkAtoms::color, // color
   1.397 +  &nsGkAtoms::colorInterpolation, // color-interpolation
   1.398 +  &nsGkAtoms::colorInterpolationFilters, // color-interpolation-filters
   1.399 +  // contentScriptType
   1.400 +  // contentStyleType
   1.401 +  &nsGkAtoms::cursor, // cursor
   1.402 +  &nsGkAtoms::cx, // cx
   1.403 +  &nsGkAtoms::cy, // cy
   1.404 +  &nsGkAtoms::d, // d
   1.405 +  // descent
   1.406 +  &nsGkAtoms::diffuseConstant, // diffuseConstant
   1.407 +  &nsGkAtoms::direction, // direction
   1.408 +  &nsGkAtoms::display, // display
   1.409 +  &nsGkAtoms::divisor, // divisor
   1.410 +  &nsGkAtoms::dominant_baseline, // dominant-baseline
   1.411 +  &nsGkAtoms::dur, // dur
   1.412 +  &nsGkAtoms::dx, // dx
   1.413 +  &nsGkAtoms::dy, // dy
   1.414 +  &nsGkAtoms::edgeMode, // edgeMode
   1.415 +  &nsGkAtoms::elevation, // elevation
   1.416 +  // enable-background
   1.417 +  &nsGkAtoms::end, // end
   1.418 +  &nsGkAtoms::fill, // fill
   1.419 +  &nsGkAtoms::fill_opacity, // fill-opacity
   1.420 +  &nsGkAtoms::fill_rule, // fill-rule
   1.421 +  &nsGkAtoms::filter, // filter
   1.422 +  &nsGkAtoms::filterRes, // filterRes
   1.423 +  &nsGkAtoms::filterUnits, // filterUnits
   1.424 +  &nsGkAtoms::flood_color, // flood-color
   1.425 +  &nsGkAtoms::flood_opacity, // flood-opacity
   1.426 +  // XXX focusable
   1.427 +  &nsGkAtoms::font, // font
   1.428 +  &nsGkAtoms::font_family, // font-family
   1.429 +  &nsGkAtoms::font_size, // font-size
   1.430 +  &nsGkAtoms::font_size_adjust, // font-size-adjust
   1.431 +  &nsGkAtoms::font_stretch, // font-stretch
   1.432 +  &nsGkAtoms::font_style, // font-style
   1.433 +  &nsGkAtoms::font_variant, // font-variant
   1.434 +  &nsGkAtoms::fontWeight, // font-weight
   1.435 +  &nsGkAtoms::format, // format
   1.436 +  &nsGkAtoms::from, // from
   1.437 +  &nsGkAtoms::fx, // fx
   1.438 +  &nsGkAtoms::fy, // fy
   1.439 +  // g1
   1.440 +  // g2
   1.441 +  // glyph-name
   1.442 +  // glyphRef
   1.443 +  &nsGkAtoms::glyph_orientation_horizontal, // glyph-orientation-horizontal
   1.444 +  &nsGkAtoms::glyph_orientation_vertical, // glyph-orientation-vertical
   1.445 +  &nsGkAtoms::gradientTransform, // gradientTransform
   1.446 +  &nsGkAtoms::gradientUnits, // gradientUnits
   1.447 +  &nsGkAtoms::height, // height
   1.448 +  // horiz-adv-x
   1.449 +  // horiz-origin-x
   1.450 +  // horiz-origin-y
   1.451 +  &nsGkAtoms::id, // id
   1.452 +  // ideographic
   1.453 +  &nsGkAtoms::image_rendering, // image-rendering
   1.454 +  &nsGkAtoms::in, // in
   1.455 +  &nsGkAtoms::in2, // in2
   1.456 +  &nsGkAtoms::intercept, // intercept
   1.457 +  // k
   1.458 +  &nsGkAtoms::k1, // k1
   1.459 +  &nsGkAtoms::k2, // k2
   1.460 +  &nsGkAtoms::k3, // k3
   1.461 +  &nsGkAtoms::k4, // k4
   1.462 +  &nsGkAtoms::kerning, // kerning
   1.463 +  &nsGkAtoms::kernelMatrix, // kernelMatrix
   1.464 +  &nsGkAtoms::kernelUnitLength, // kernelUnitLength
   1.465 +  &nsGkAtoms::keyPoints, // keyPoints
   1.466 +  &nsGkAtoms::keySplines, // keySplines
   1.467 +  &nsGkAtoms::keyTimes, // keyTimes
   1.468 +  &nsGkAtoms::lang, // lang
   1.469 +  // lengthAdjust
   1.470 +  &nsGkAtoms::letter_spacing, // letter-spacing
   1.471 +  &nsGkAtoms::lighting_color, // lighting-color
   1.472 +  &nsGkAtoms::limitingConeAngle, // limitingConeAngle
   1.473 +  // local
   1.474 +  &nsGkAtoms::marker, // marker
   1.475 +  &nsGkAtoms::marker_end, // marker-end
   1.476 +  &nsGkAtoms::marker_mid, // marker-mid
   1.477 +  &nsGkAtoms::marker_start, // marker-start
   1.478 +  &nsGkAtoms::markerHeight, // markerHeight
   1.479 +  &nsGkAtoms::markerUnits, // markerUnits
   1.480 +  &nsGkAtoms::markerWidth, // markerWidth
   1.481 +  &nsGkAtoms::mask, // mask
   1.482 +  &nsGkAtoms::maskContentUnits, // maskContentUnits
   1.483 +  &nsGkAtoms::maskUnits, // maskUnits
   1.484 +  // mathematical
   1.485 +  &nsGkAtoms::max, // max
   1.486 +  &nsGkAtoms::media, // media
   1.487 +  &nsGkAtoms::method, // method
   1.488 +  &nsGkAtoms::min, // min
   1.489 +  &nsGkAtoms::mode, // mode
   1.490 +  &nsGkAtoms::name, // name
   1.491 +  &nsGkAtoms::numOctaves, // numOctaves
   1.492 +  &nsGkAtoms::offset, // offset
   1.493 +  &nsGkAtoms::opacity, // opacity
   1.494 +  &nsGkAtoms::_operator, // operator
   1.495 +  &nsGkAtoms::order, // order
   1.496 +  &nsGkAtoms::orient, // orient
   1.497 +  &nsGkAtoms::orientation, // orientation
   1.498 +  // origin
   1.499 +  // overline-position
   1.500 +  // overline-thickness
   1.501 +  &nsGkAtoms::overflow, // overflow
   1.502 +  // panose-1
   1.503 +  &nsGkAtoms::path, // path
   1.504 +  &nsGkAtoms::pathLength, // pathLength
   1.505 +  &nsGkAtoms::patternContentUnits, // patternContentUnits
   1.506 +  &nsGkAtoms::patternTransform, // patternTransform
   1.507 +  &nsGkAtoms::patternUnits, // patternUnits
   1.508 +  &nsGkAtoms::pointer_events, // pointer-events XXX is this safe?
   1.509 +  &nsGkAtoms::points, // points
   1.510 +  &nsGkAtoms::pointsAtX, // pointsAtX
   1.511 +  &nsGkAtoms::pointsAtY, // pointsAtY
   1.512 +  &nsGkAtoms::pointsAtZ, // pointsAtZ
   1.513 +  &nsGkAtoms::preserveAlpha, // preserveAlpha
   1.514 +  &nsGkAtoms::preserveAspectRatio, // preserveAspectRatio
   1.515 +  &nsGkAtoms::primitiveUnits, // primitiveUnits
   1.516 +  &nsGkAtoms::r, // r
   1.517 +  &nsGkAtoms::radius, // radius
   1.518 +  &nsGkAtoms::refX, // refX
   1.519 +  &nsGkAtoms::refY, // refY
   1.520 +  &nsGkAtoms::repeatCount, // repeatCount
   1.521 +  &nsGkAtoms::repeatDur, // repeatDur
   1.522 +  &nsGkAtoms::requiredExtensions, // requiredExtensions
   1.523 +  &nsGkAtoms::requiredFeatures, // requiredFeatures
   1.524 +  &nsGkAtoms::restart, // restart
   1.525 +  &nsGkAtoms::result, // result
   1.526 +  &nsGkAtoms::rotate, // rotate
   1.527 +  &nsGkAtoms::rx, // rx
   1.528 +  &nsGkAtoms::ry, // ry
   1.529 +  &nsGkAtoms::scale, // scale
   1.530 +  &nsGkAtoms::seed, // seed
   1.531 +  &nsGkAtoms::shape_rendering, // shape-rendering
   1.532 +  &nsGkAtoms::slope, // slope
   1.533 +  &nsGkAtoms::spacing, // spacing
   1.534 +  &nsGkAtoms::specularConstant, // specularConstant
   1.535 +  &nsGkAtoms::specularExponent, // specularExponent
   1.536 +  &nsGkAtoms::spreadMethod, // spreadMethod
   1.537 +  &nsGkAtoms::startOffset, // startOffset
   1.538 +  &nsGkAtoms::stdDeviation, // stdDeviation
   1.539 +  // stemh
   1.540 +  // stemv
   1.541 +  &nsGkAtoms::stitchTiles, // stitchTiles
   1.542 +  &nsGkAtoms::stop_color, // stop-color
   1.543 +  &nsGkAtoms::stop_opacity, // stop-opacity
   1.544 +  // strikethrough-position
   1.545 +  // strikethrough-thickness
   1.546 +  &nsGkAtoms::string, // string
   1.547 +  &nsGkAtoms::stroke, // stroke
   1.548 +  &nsGkAtoms::stroke_dasharray, // stroke-dasharray
   1.549 +  &nsGkAtoms::stroke_dashoffset, // stroke-dashoffset
   1.550 +  &nsGkAtoms::stroke_linecap, // stroke-linecap
   1.551 +  &nsGkAtoms::stroke_linejoin, // stroke-linejoin
   1.552 +  &nsGkAtoms::stroke_miterlimit, // stroke-miterlimit
   1.553 +  &nsGkAtoms::stroke_opacity, // stroke-opacity
   1.554 +  &nsGkAtoms::stroke_width, // stroke-width
   1.555 +  &nsGkAtoms::surfaceScale, // surfaceScale
   1.556 +  &nsGkAtoms::systemLanguage, // systemLanguage
   1.557 +  &nsGkAtoms::tableValues, // tableValues
   1.558 +  &nsGkAtoms::target, // target
   1.559 +  &nsGkAtoms::targetX, // targetX
   1.560 +  &nsGkAtoms::targetY, // targetY
   1.561 +  &nsGkAtoms::text_anchor, // text-anchor
   1.562 +  &nsGkAtoms::text_decoration, // text-decoration
   1.563 +  // textLength
   1.564 +  &nsGkAtoms::text_rendering, // text-rendering
   1.565 +  &nsGkAtoms::title, // title
   1.566 +  &nsGkAtoms::to, // to
   1.567 +  &nsGkAtoms::transform, // transform
   1.568 +  &nsGkAtoms::type, // type
   1.569 +  // u1
   1.570 +  // u2
   1.571 +  // underline-position
   1.572 +  // underline-thickness
   1.573 +  // unicode
   1.574 +  &nsGkAtoms::unicode_bidi, // unicode-bidi
   1.575 +  // unicode-range
   1.576 +  // units-per-em
   1.577 +  // v-alphabetic
   1.578 +  // v-hanging
   1.579 +  // v-ideographic
   1.580 +  // v-mathematical
   1.581 +  &nsGkAtoms::values, // values
   1.582 +  &nsGkAtoms::vector_effect, // vector-effect
   1.583 +  // vert-adv-y
   1.584 +  // vert-origin-x
   1.585 +  // vert-origin-y
   1.586 +  &nsGkAtoms::viewBox, // viewBox
   1.587 +  &nsGkAtoms::viewTarget, // viewTarget
   1.588 +  &nsGkAtoms::visibility, // visibility
   1.589 +  &nsGkAtoms::width, // width
   1.590 +  // widths
   1.591 +  &nsGkAtoms::word_spacing, // word-spacing
   1.592 +  // writing-mode
   1.593 +  &nsGkAtoms::x, // x
   1.594 +  // x-height
   1.595 +  &nsGkAtoms::x1, // x1
   1.596 +  &nsGkAtoms::x2, // x2
   1.597 +  &nsGkAtoms::xChannelSelector, // xChannelSelector
   1.598 +  &nsGkAtoms::y, // y
   1.599 +  &nsGkAtoms::y1, // y1
   1.600 +  &nsGkAtoms::y2, // y2
   1.601 +  &nsGkAtoms::yChannelSelector, // yChannelSelector
   1.602 +  &nsGkAtoms::z, // z
   1.603 +  &nsGkAtoms::zoomAndPan, // zoomAndPan
   1.604 +  nullptr
   1.605 +};
   1.606 +
   1.607 +nsIAtom** const kURLAttributesSVG[] = {
   1.608 +  nullptr
   1.609 +};
   1.610 +
   1.611 +nsIAtom** const kElementsMathML[] = {
   1.612 +   &nsGkAtoms::abs_, // abs
   1.613 +   &nsGkAtoms::_and, // and
   1.614 +   &nsGkAtoms::annotation_, // annotation
   1.615 +   &nsGkAtoms::annotation_xml_, // annotation-xml
   1.616 +   &nsGkAtoms::apply_, // apply
   1.617 +   &nsGkAtoms::approx_, // approx
   1.618 +   &nsGkAtoms::arccos_, // arccos
   1.619 +   &nsGkAtoms::arccosh_, // arccosh
   1.620 +   &nsGkAtoms::arccot_, // arccot
   1.621 +   &nsGkAtoms::arccoth_, // arccoth
   1.622 +   &nsGkAtoms::arccsc_, // arccsc
   1.623 +   &nsGkAtoms::arccsch_, // arccsch
   1.624 +   &nsGkAtoms::arcsec_, // arcsec
   1.625 +   &nsGkAtoms::arcsech_, // arcsech
   1.626 +   &nsGkAtoms::arcsin_, // arcsin
   1.627 +   &nsGkAtoms::arcsinh_, // arcsinh
   1.628 +   &nsGkAtoms::arctan_, // arctan
   1.629 +   &nsGkAtoms::arctanh_, // arctanh
   1.630 +   &nsGkAtoms::arg_, // arg
   1.631 +   &nsGkAtoms::bind_, // bind
   1.632 +   &nsGkAtoms::bvar_, // bvar
   1.633 +   &nsGkAtoms::card_, // card
   1.634 +   &nsGkAtoms::cartesianproduct_, // cartesianproduct
   1.635 +   &nsGkAtoms::cbytes_, // cbytes
   1.636 +   &nsGkAtoms::ceiling, // ceiling
   1.637 +   &nsGkAtoms::cerror_, // cerror
   1.638 +   &nsGkAtoms::ci_, // ci
   1.639 +   &nsGkAtoms::cn_, // cn
   1.640 +   &nsGkAtoms::codomain_, // codomain
   1.641 +   &nsGkAtoms::complexes_, // complexes
   1.642 +   &nsGkAtoms::compose_, // compose
   1.643 +   &nsGkAtoms::condition_, // condition
   1.644 +   &nsGkAtoms::conjugate_, // conjugate
   1.645 +   &nsGkAtoms::cos_, // cos
   1.646 +   &nsGkAtoms::cosh_, // cosh
   1.647 +   &nsGkAtoms::cot_, // cot
   1.648 +   &nsGkAtoms::coth_, // coth
   1.649 +   &nsGkAtoms::cs_, // cs
   1.650 +   &nsGkAtoms::csc_, // csc
   1.651 +   &nsGkAtoms::csch_, // csch
   1.652 +   &nsGkAtoms::csymbol_, // csymbol
   1.653 +   &nsGkAtoms::curl_, // curl
   1.654 +   &nsGkAtoms::declare, // declare
   1.655 +   &nsGkAtoms::degree_, // degree
   1.656 +   &nsGkAtoms::determinant_, // determinant
   1.657 +   &nsGkAtoms::diff_, // diff
   1.658 +   &nsGkAtoms::divergence_, // divergence
   1.659 +   &nsGkAtoms::divide_, // divide
   1.660 +   &nsGkAtoms::domain_, // domain
   1.661 +   &nsGkAtoms::domainofapplication_, // domainofapplication
   1.662 +   &nsGkAtoms::el_, // el
   1.663 +   &nsGkAtoms::emptyset_, // emptyset
   1.664 +   &nsGkAtoms::eq_, // eq
   1.665 +   &nsGkAtoms::equivalent_, // equivalent
   1.666 +   &nsGkAtoms::eulergamma_, // eulergamma
   1.667 +   &nsGkAtoms::exists_, // exists
   1.668 +   &nsGkAtoms::exp_, // exp
   1.669 +   &nsGkAtoms::exponentiale_, // exponentiale
   1.670 +   &nsGkAtoms::factorial_, // factorial
   1.671 +   &nsGkAtoms::factorof_, // factorof
   1.672 +   &nsGkAtoms::_false, // false
   1.673 +   &nsGkAtoms::floor, // floor
   1.674 +   &nsGkAtoms::fn_, // fn
   1.675 +   &nsGkAtoms::forall_, // forall
   1.676 +   &nsGkAtoms::gcd_, // gcd
   1.677 +   &nsGkAtoms::geq_, // geq
   1.678 +   &nsGkAtoms::grad, // grad
   1.679 +   &nsGkAtoms::gt_, // gt
   1.680 +   &nsGkAtoms::ident_, // ident
   1.681 +   &nsGkAtoms::image, // image
   1.682 +   &nsGkAtoms::imaginary_, // imaginary
   1.683 +   &nsGkAtoms::imaginaryi_, // imaginaryi
   1.684 +   &nsGkAtoms::implies_, // implies
   1.685 +   &nsGkAtoms::in, // in
   1.686 +   &nsGkAtoms::infinity, // infinity
   1.687 +   &nsGkAtoms::int_, // int
   1.688 +   &nsGkAtoms::integers_, // integers
   1.689 +   &nsGkAtoms::intersect_, // intersect
   1.690 +   &nsGkAtoms::interval_, // interval
   1.691 +   &nsGkAtoms::inverse_, // inverse
   1.692 +   &nsGkAtoms::lambda_, // lambda
   1.693 +   &nsGkAtoms::laplacian_, // laplacian
   1.694 +   &nsGkAtoms::lcm_, // lcm
   1.695 +   &nsGkAtoms::leq_, // leq
   1.696 +   &nsGkAtoms::limit_, // limit
   1.697 +   &nsGkAtoms::list_, // list
   1.698 +   &nsGkAtoms::ln_, // ln
   1.699 +   &nsGkAtoms::log_, // log
   1.700 +   &nsGkAtoms::logbase_, // logbase
   1.701 +   &nsGkAtoms::lowlimit_, // lowlimit
   1.702 +   &nsGkAtoms::lt_, // lt
   1.703 +   &nsGkAtoms::maction_, // maction
   1.704 +   &nsGkAtoms::maligngroup_, // maligngroup
   1.705 +   &nsGkAtoms::malignmark_, // malignmark
   1.706 +   &nsGkAtoms::math, // math
   1.707 +   &nsGkAtoms::matrix, // matrix
   1.708 +   &nsGkAtoms::matrixrow_, // matrixrow
   1.709 +   &nsGkAtoms::max, // max
   1.710 +   &nsGkAtoms::mean_, // mean
   1.711 +   &nsGkAtoms::median_, // median
   1.712 +   &nsGkAtoms::menclose_, // menclose
   1.713 +   &nsGkAtoms::merror_, // merror
   1.714 +   &nsGkAtoms::mfenced_, // mfenced
   1.715 +   &nsGkAtoms::mfrac_, // mfrac
   1.716 +   &nsGkAtoms::mglyph_, // mglyph
   1.717 +   &nsGkAtoms::mi_, // mi
   1.718 +   &nsGkAtoms::min, // min
   1.719 +   &nsGkAtoms::minus_, // minus
   1.720 +   &nsGkAtoms::mlabeledtr_, // mlabeledtr
   1.721 +   &nsGkAtoms::mlongdiv_, // mlongdiv
   1.722 +   &nsGkAtoms::mmultiscripts_, // mmultiscripts
   1.723 +   &nsGkAtoms::mn_, // mn
   1.724 +   &nsGkAtoms::mo_, // mo
   1.725 +   &nsGkAtoms::mode, // mode
   1.726 +   &nsGkAtoms::moment_, // moment
   1.727 +   &nsGkAtoms::momentabout_, // momentabout
   1.728 +   &nsGkAtoms::mover_, // mover
   1.729 +   &nsGkAtoms::mpadded_, // mpadded
   1.730 +   &nsGkAtoms::mphantom_, // mphantom
   1.731 +   &nsGkAtoms::mprescripts_, // mprescripts
   1.732 +   &nsGkAtoms::mroot_, // mroot
   1.733 +   &nsGkAtoms::mrow_, // mrow
   1.734 +   &nsGkAtoms::ms_, // ms
   1.735 +   &nsGkAtoms::mscarries_, // mscarries
   1.736 +   &nsGkAtoms::mscarry_, // mscarry
   1.737 +   &nsGkAtoms::msgroup_, // msgroup
   1.738 +   &nsGkAtoms::msline_, // msline
   1.739 +   &nsGkAtoms::mspace_, // mspace
   1.740 +   &nsGkAtoms::msqrt_, // msqrt
   1.741 +   &nsGkAtoms::msrow_, // msrow
   1.742 +   &nsGkAtoms::mstack_, // mstack
   1.743 +   &nsGkAtoms::mstyle_, // mstyle
   1.744 +   &nsGkAtoms::msub_, // msub
   1.745 +   &nsGkAtoms::msubsup_, // msubsup
   1.746 +   &nsGkAtoms::msup_, // msup
   1.747 +   &nsGkAtoms::mtable_, // mtable
   1.748 +   &nsGkAtoms::mtd_, // mtd
   1.749 +   &nsGkAtoms::mtext_, // mtext
   1.750 +   &nsGkAtoms::mtr_, // mtr
   1.751 +   &nsGkAtoms::munder_, // munder
   1.752 +   &nsGkAtoms::munderover_, // munderover
   1.753 +   &nsGkAtoms::naturalnumbers_, // naturalnumbers
   1.754 +   &nsGkAtoms::neq_, // neq
   1.755 +   &nsGkAtoms::none, // none
   1.756 +   &nsGkAtoms::_not, // not
   1.757 +   &nsGkAtoms::notanumber_, // notanumber
   1.758 +   &nsGkAtoms::note_, // note
   1.759 +   &nsGkAtoms::notin_, // notin
   1.760 +   &nsGkAtoms::notprsubset_, // notprsubset
   1.761 +   &nsGkAtoms::notsubset_, // notsubset
   1.762 +   &nsGkAtoms::_or, // or
   1.763 +   &nsGkAtoms::otherwise, // otherwise
   1.764 +   &nsGkAtoms::outerproduct_, // outerproduct
   1.765 +   &nsGkAtoms::partialdiff_, // partialdiff
   1.766 +   &nsGkAtoms::pi_, // pi
   1.767 +   &nsGkAtoms::piece_, // piece
   1.768 +   &nsGkAtoms::piecewise_, // piecewise
   1.769 +   &nsGkAtoms::plus_, // plus
   1.770 +   &nsGkAtoms::power_, // power
   1.771 +   &nsGkAtoms::primes_, // primes
   1.772 +   &nsGkAtoms::product_, // product
   1.773 +   &nsGkAtoms::prsubset_, // prsubset
   1.774 +   &nsGkAtoms::quotient_, // quotient
   1.775 +   &nsGkAtoms::rationals_, // rationals
   1.776 +   &nsGkAtoms::real_, // real
   1.777 +   &nsGkAtoms::reals_, // reals
   1.778 +   &nsGkAtoms::reln_, // reln
   1.779 +   &nsGkAtoms::rem, // rem
   1.780 +   &nsGkAtoms::root_, // root
   1.781 +   &nsGkAtoms::scalarproduct_, // scalarproduct
   1.782 +   &nsGkAtoms::sdev_, // sdev
   1.783 +   &nsGkAtoms::sec_, // sec
   1.784 +   &nsGkAtoms::sech_, // sech
   1.785 +   &nsGkAtoms::selector_, // selector
   1.786 +   &nsGkAtoms::semantics_, // semantics
   1.787 +   &nsGkAtoms::sep_, // sep
   1.788 +   &nsGkAtoms::set_, // set
   1.789 +   &nsGkAtoms::setdiff_, // setdiff
   1.790 +   &nsGkAtoms::share_, // share
   1.791 +   &nsGkAtoms::sin_, // sin
   1.792 +   &nsGkAtoms::sinh_, // sinh
   1.793 +   &nsGkAtoms::subset_, // subset
   1.794 +   &nsGkAtoms::sum, // sum
   1.795 +   &nsGkAtoms::tan_, // tan
   1.796 +   &nsGkAtoms::tanh_, // tanh
   1.797 +   &nsGkAtoms::tendsto_, // tendsto
   1.798 +   &nsGkAtoms::times_, // times
   1.799 +   &nsGkAtoms::transpose_, // transpose
   1.800 +   &nsGkAtoms::_true, // true
   1.801 +   &nsGkAtoms::union_, // union
   1.802 +   &nsGkAtoms::uplimit_, // uplimit
   1.803 +   &nsGkAtoms::variance_, // variance
   1.804 +   &nsGkAtoms::vector_, // vector
   1.805 +   &nsGkAtoms::vectorproduct_, // vectorproduct
   1.806 +   &nsGkAtoms::xor_, // xor
   1.807 +  nullptr
   1.808 +};
   1.809 +
   1.810 +nsIAtom** const kAttributesMathML[] = {
   1.811 +   &nsGkAtoms::accent_, // accent
   1.812 +   &nsGkAtoms::accentunder_, // accentunder
   1.813 +   &nsGkAtoms::actiontype_, // actiontype
   1.814 +   &nsGkAtoms::align, // align
   1.815 +   &nsGkAtoms::alignmentscope_, // alignmentscope
   1.816 +   &nsGkAtoms::alt, // alt
   1.817 +   &nsGkAtoms::altimg_, // altimg
   1.818 +   &nsGkAtoms::altimg_height_, // altimg-height
   1.819 +   &nsGkAtoms::altimg_valign_, // altimg-valign
   1.820 +   &nsGkAtoms::altimg_width_, // altimg-width
   1.821 +   &nsGkAtoms::background, // background
   1.822 +   &nsGkAtoms::base, // base
   1.823 +   &nsGkAtoms::bevelled_, // bevelled
   1.824 +   &nsGkAtoms::cd_, // cd
   1.825 +   &nsGkAtoms::cdgroup_, // cdgroup
   1.826 +   &nsGkAtoms::charalign_, // charalign
   1.827 +   &nsGkAtoms::close, // close
   1.828 +   &nsGkAtoms::closure_, // closure
   1.829 +   &nsGkAtoms::color, // color
   1.830 +   &nsGkAtoms::columnalign_, // columnalign
   1.831 +   &nsGkAtoms::columnalignment_, // columnalignment
   1.832 +   &nsGkAtoms::columnlines_, // columnlines
   1.833 +   &nsGkAtoms::columnspacing_, // columnspacing
   1.834 +   &nsGkAtoms::columnspan_, // columnspan
   1.835 +   &nsGkAtoms::columnwidth_, // columnwidth
   1.836 +   &nsGkAtoms::crossout_, // crossout
   1.837 +   &nsGkAtoms::decimalpoint_, // decimalpoint
   1.838 +   &nsGkAtoms::definitionURL_, // definitionURL
   1.839 +   &nsGkAtoms::denomalign_, // denomalign
   1.840 +   &nsGkAtoms::depth_, // depth
   1.841 +   &nsGkAtoms::dir, // dir
   1.842 +   &nsGkAtoms::display, // display
   1.843 +   &nsGkAtoms::displaystyle_, // displaystyle
   1.844 +   &nsGkAtoms::edge_, // edge
   1.845 +   &nsGkAtoms::encoding, // encoding
   1.846 +   &nsGkAtoms::equalcolumns_, // equalcolumns
   1.847 +   &nsGkAtoms::equalrows_, // equalrows
   1.848 +   &nsGkAtoms::fence_, // fence
   1.849 +   &nsGkAtoms::fontfamily_, // fontfamily
   1.850 +   &nsGkAtoms::fontsize_, // fontsize
   1.851 +   &nsGkAtoms::fontstyle_, // fontstyle
   1.852 +   &nsGkAtoms::fontweight_, // fontweight
   1.853 +   &nsGkAtoms::form, // form
   1.854 +   &nsGkAtoms::frame, // frame
   1.855 +   &nsGkAtoms::framespacing_, // framespacing
   1.856 +   &nsGkAtoms::groupalign_, // groupalign
   1.857 +   &nsGkAtoms::height, // height
   1.858 +   &nsGkAtoms::href, // href
   1.859 +   &nsGkAtoms::id, // id
   1.860 +   &nsGkAtoms::indentalign_, // indentalign
   1.861 +   &nsGkAtoms::indentalignfirst_, // indentalignfirst
   1.862 +   &nsGkAtoms::indentalignlast_, // indentalignlast
   1.863 +   &nsGkAtoms::indentshift_, // indentshift
   1.864 +   &nsGkAtoms::indentshiftfirst_, // indentshiftfirst
   1.865 +   &nsGkAtoms::indenttarget_, // indenttarget
   1.866 +   &nsGkAtoms::index, // index
   1.867 +   &nsGkAtoms::integer, // integer
   1.868 +   &nsGkAtoms::largeop_, // largeop
   1.869 +   &nsGkAtoms::length, // length
   1.870 +   &nsGkAtoms::linebreak_, // linebreak
   1.871 +   &nsGkAtoms::linebreakmultchar_, // linebreakmultchar
   1.872 +   &nsGkAtoms::linebreakstyle_, // linebreakstyle
   1.873 +   &nsGkAtoms::linethickness_, // linethickness
   1.874 +   &nsGkAtoms::location_, // location
   1.875 +   &nsGkAtoms::longdivstyle_, // longdivstyle
   1.876 +   &nsGkAtoms::lquote_, // lquote
   1.877 +   &nsGkAtoms::lspace_, // lspace
   1.878 +   &nsGkAtoms::ltr, // ltr
   1.879 +   &nsGkAtoms::mathbackground_, // mathbackground
   1.880 +   &nsGkAtoms::mathcolor_, // mathcolor
   1.881 +   &nsGkAtoms::mathsize_, // mathsize
   1.882 +   &nsGkAtoms::mathvariant_, // mathvariant
   1.883 +   &nsGkAtoms::maxsize_, // maxsize
   1.884 +   &nsGkAtoms::minlabelspacing_, // minlabelspacing
   1.885 +   &nsGkAtoms::minsize_, // minsize
   1.886 +   &nsGkAtoms::movablelimits_, // movablelimits
   1.887 +   &nsGkAtoms::msgroup_, // msgroup
   1.888 +   &nsGkAtoms::name, // name
   1.889 +   &nsGkAtoms::newline, // newline
   1.890 +   &nsGkAtoms::notation_, // notation
   1.891 +   &nsGkAtoms::numalign_, // numalign
   1.892 +   &nsGkAtoms::number, // number
   1.893 +   &nsGkAtoms::open, // open
   1.894 +   &nsGkAtoms::order, // order
   1.895 +   &nsGkAtoms::other_, // other
   1.896 +   &nsGkAtoms::overflow, // overflow
   1.897 +   &nsGkAtoms::position, // position
   1.898 +   &nsGkAtoms::role, // role
   1.899 +   &nsGkAtoms::rowalign_, // rowalign
   1.900 +   &nsGkAtoms::rowlines_, // rowlines
   1.901 +   &nsGkAtoms::rowspacing_, // rowspacing
   1.902 +   &nsGkAtoms::rowspan, // rowspan
   1.903 +   &nsGkAtoms::rquote_, // rquote
   1.904 +   &nsGkAtoms::rspace_, // rspace
   1.905 +   &nsGkAtoms::schemaLocation_, // schemaLocation
   1.906 +   &nsGkAtoms::scriptlevel_, // scriptlevel
   1.907 +   &nsGkAtoms::scriptminsize_, // scriptminsize
   1.908 +   &nsGkAtoms::scriptsize_, // scriptsize
   1.909 +   &nsGkAtoms::scriptsizemultiplier_, // scriptsizemultiplier
   1.910 +   &nsGkAtoms::selection_, // selection
   1.911 +   &nsGkAtoms::separator_, // separator
   1.912 +   &nsGkAtoms::separators_, // separators
   1.913 +   &nsGkAtoms::shift_, // shift
   1.914 +   &nsGkAtoms::side_, // side
   1.915 +   &nsGkAtoms::src, // src
   1.916 +   &nsGkAtoms::stackalign_, // stackalign
   1.917 +   &nsGkAtoms::stretchy_, // stretchy
   1.918 +   &nsGkAtoms::subscriptshift_, // subscriptshift
   1.919 +   &nsGkAtoms::superscriptshift_, // superscriptshift
   1.920 +   &nsGkAtoms::symmetric_, // symmetric
   1.921 +   &nsGkAtoms::type, // type
   1.922 +   &nsGkAtoms::voffset_, // voffset
   1.923 +   &nsGkAtoms::width, // width
   1.924 +   &nsGkAtoms::xref_, // xref
   1.925 +  nullptr
   1.926 +};
   1.927 +
   1.928 +nsIAtom** const kURLAttributesMathML[] = {
   1.929 +  &nsGkAtoms::href,
   1.930 +  &nsGkAtoms::src,
   1.931 +  &nsGkAtoms::cdgroup_,
   1.932 +  &nsGkAtoms::altimg_,
   1.933 +  &nsGkAtoms::definitionURL_,
   1.934 +  nullptr
   1.935 +};
   1.936 +
   1.937 +nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsHTML = nullptr;
   1.938 +nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesHTML = nullptr;
   1.939 +nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sPresAttributesHTML = nullptr;
   1.940 +nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsSVG = nullptr;
   1.941 +nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesSVG = nullptr;
   1.942 +nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsMathML = nullptr;
   1.943 +nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesMathML = nullptr;
   1.944 +nsIPrincipal* nsTreeSanitizer::sNullPrincipal = nullptr;
   1.945 +
   1.946 +nsTreeSanitizer::nsTreeSanitizer(uint32_t aFlags)
   1.947 + : mAllowStyles(aFlags & nsIParserUtils::SanitizerAllowStyle)
   1.948 + , mAllowComments(aFlags & nsIParserUtils::SanitizerAllowComments)
   1.949 + , mDropNonCSSPresentation(aFlags &
   1.950 +     nsIParserUtils::SanitizerDropNonCSSPresentation)
   1.951 + , mDropForms(aFlags & nsIParserUtils::SanitizerDropForms)
   1.952 + , mCidEmbedsOnly(aFlags &
   1.953 +     nsIParserUtils::SanitizerCidEmbedsOnly)
   1.954 + , mDropMedia(aFlags & nsIParserUtils::SanitizerDropMedia)
   1.955 + , mFullDocument(false)
   1.956 +{
   1.957 +  if (mCidEmbedsOnly) {
   1.958 +    // Sanitizing styles for external references is not supported.
   1.959 +    mAllowStyles = false;
   1.960 +  }
   1.961 +  if (!sElementsHTML) {
   1.962 +    // Initialize lazily to avoid having to initialize at all if the user
   1.963 +    // doesn't paste HTML or load feeds.
   1.964 +    InitializeStatics();
   1.965 +  }
   1.966 +}
   1.967 +
   1.968 +bool
   1.969 +nsTreeSanitizer::MustFlatten(int32_t aNamespace, nsIAtom* aLocal)
   1.970 +{
   1.971 +  if (aNamespace == kNameSpaceID_XHTML) {
   1.972 +    if (mDropNonCSSPresentation && (nsGkAtoms::font == aLocal ||
   1.973 +                                    nsGkAtoms::center == aLocal)) {
   1.974 +      return true;
   1.975 +    }
   1.976 +    if (mDropForms && (nsGkAtoms::form == aLocal ||
   1.977 +                       nsGkAtoms::input == aLocal ||
   1.978 +                       nsGkAtoms::keygen == aLocal ||
   1.979 +                       nsGkAtoms::option == aLocal ||
   1.980 +                       nsGkAtoms::optgroup == aLocal)) {
   1.981 +      return true;
   1.982 +    }
   1.983 +    if (mFullDocument && (nsGkAtoms::title == aLocal ||
   1.984 +                          nsGkAtoms::html == aLocal ||
   1.985 +                          nsGkAtoms::head == aLocal ||
   1.986 +                          nsGkAtoms::body == aLocal)) {
   1.987 +      return false;
   1.988 +    }
   1.989 +    return !sElementsHTML->GetEntry(aLocal);
   1.990 +  }
   1.991 +  if (aNamespace == kNameSpaceID_SVG) {
   1.992 +    if (mCidEmbedsOnly || mDropMedia) {
   1.993 +      // Sanitizing CSS-based URL references inside SVG presentational
   1.994 +      // attributes is not supported, so flattening for cid: embed case.
   1.995 +      return true;
   1.996 +    }
   1.997 +    return !sElementsSVG->GetEntry(aLocal);
   1.998 +  }
   1.999 +  if (aNamespace == kNameSpaceID_MathML) {
  1.1000 +    return !sElementsMathML->GetEntry(aLocal);
  1.1001 +  }
  1.1002 +  return true;
  1.1003 +}
  1.1004 +
  1.1005 +bool
  1.1006 +nsTreeSanitizer::IsURL(nsIAtom*** aURLs, nsIAtom* aLocalName)
  1.1007 +{
  1.1008 +  nsIAtom** atomPtrPtr;
  1.1009 +  while ((atomPtrPtr = *aURLs)) {
  1.1010 +    if (*atomPtrPtr == aLocalName) {
  1.1011 +      return true;
  1.1012 +    }
  1.1013 +    ++aURLs;
  1.1014 +  }
  1.1015 +  return false;
  1.1016 +}
  1.1017 +
  1.1018 +bool
  1.1019 +nsTreeSanitizer::MustPrune(int32_t aNamespace,
  1.1020 +                           nsIAtom* aLocal,
  1.1021 +                           mozilla::dom::Element* aElement)
  1.1022 +{
  1.1023 +  // To avoid attacks where a MathML script becomes something that gets
  1.1024 +  // serialized in a way that it parses back as an HTML script, let's just
  1.1025 +  // drop elements with the local name 'script' regardless of namespace.
  1.1026 +  if (nsGkAtoms::script == aLocal) {
  1.1027 +    return true;
  1.1028 +  }
  1.1029 +  if (aNamespace == kNameSpaceID_XHTML) {
  1.1030 +    if (nsGkAtoms::title == aLocal && !mFullDocument) {
  1.1031 +      // emulate the quirks of the old parser
  1.1032 +      return true;
  1.1033 +    }
  1.1034 +    if (mDropForms && (nsGkAtoms::select == aLocal ||
  1.1035 +                       nsGkAtoms::button == aLocal ||
  1.1036 +                       nsGkAtoms::datalist == aLocal)) {
  1.1037 +      return true;
  1.1038 +    }
  1.1039 +    if (mDropMedia && (nsGkAtoms::img == aLocal ||
  1.1040 +                       nsGkAtoms::video == aLocal ||
  1.1041 +                       nsGkAtoms::audio == aLocal ||
  1.1042 +                       nsGkAtoms::source == aLocal)) {
  1.1043 +      return true;
  1.1044 +    }
  1.1045 +    if (nsGkAtoms::meta == aLocal &&
  1.1046 +        (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::charset) ||
  1.1047 +         aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv))) {
  1.1048 +      // Throw away charset declarations even if they also have microdata
  1.1049 +      // which they can't validly have.
  1.1050 +      return true;
  1.1051 +    }
  1.1052 +    if (((!mFullDocument && nsGkAtoms::meta == aLocal) ||
  1.1053 +        nsGkAtoms::link == aLocal) &&
  1.1054 +        !(aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) ||
  1.1055 +          aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope))) {
  1.1056 +      // emulate old behavior for non-Microdata <meta> and <link> presumably
  1.1057 +      // in <head>. <meta> and <link> are whitelisted in order to avoid
  1.1058 +      // corrupting Microdata when they appear in <body>. Note that
  1.1059 +      // SanitizeAttributes() will remove the rel attribute from <link> and
  1.1060 +      // the name attribute from <meta>.
  1.1061 +      return true;
  1.1062 +    }
  1.1063 +  }
  1.1064 +  if (mAllowStyles) {
  1.1065 +    if (nsGkAtoms::style == aLocal && !(aNamespace == kNameSpaceID_XHTML
  1.1066 +        || aNamespace == kNameSpaceID_SVG)) {
  1.1067 +      return true;
  1.1068 +    }
  1.1069 +    return false;
  1.1070 +  }
  1.1071 +  if (nsGkAtoms::style == aLocal) {
  1.1072 +    return true;
  1.1073 +  }
  1.1074 +  return false;
  1.1075 +}
  1.1076 +
  1.1077 +bool
  1.1078 +nsTreeSanitizer::SanitizeStyleRule(mozilla::css::StyleRule *aRule,
  1.1079 +                                   nsAutoString &aRuleText)
  1.1080 +{
  1.1081 +  bool didSanitize = false;
  1.1082 +  aRuleText.Truncate();
  1.1083 +  mozilla::css::Declaration* style = aRule->GetDeclaration();
  1.1084 +  if (style) {
  1.1085 +    didSanitize = style->HasProperty(eCSSProperty_binding);
  1.1086 +    style->RemoveProperty(eCSSProperty_binding);
  1.1087 +    style->ToString(aRuleText);
  1.1088 +  }
  1.1089 +  return didSanitize;
  1.1090 +}
  1.1091 +
  1.1092 +bool
  1.1093 +nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
  1.1094 +                                    nsAString& aSanitized,
  1.1095 +                                    nsIDocument* aDocument,
  1.1096 +                                    nsIURI* aBaseURI)
  1.1097 +{
  1.1098 +  nsresult rv;
  1.1099 +  aSanitized.Truncate();
  1.1100 +  // aSanitized will hold the permitted CSS text.
  1.1101 +  // -moz-binding is blacklisted.
  1.1102 +  bool didSanitize = false;
  1.1103 +  // Create a sheet to hold the parsed CSS
  1.1104 +  nsRefPtr<nsCSSStyleSheet> sheet = new nsCSSStyleSheet(CORS_NONE);
  1.1105 +  sheet->SetURIs(aDocument->GetDocumentURI(), nullptr, aBaseURI);
  1.1106 +  sheet->SetPrincipal(aDocument->NodePrincipal());
  1.1107 +  // Create the CSS parser, and parse the CSS text.
  1.1108 +  nsCSSParser parser(nullptr, sheet);
  1.1109 +  rv = parser.ParseSheet(aOriginal, aDocument->GetDocumentURI(), aBaseURI,
  1.1110 +                         aDocument->NodePrincipal(), 0, false);
  1.1111 +  NS_ENSURE_SUCCESS(rv, true);
  1.1112 +  // Mark the sheet as complete.
  1.1113 +  NS_ABORT_IF_FALSE(!sheet->IsModified(),
  1.1114 +      "should not get marked modified during parsing");
  1.1115 +  sheet->SetComplete();
  1.1116 +  // Loop through all the rules found in the CSS text
  1.1117 +  int32_t ruleCount = sheet->StyleRuleCount();
  1.1118 +  for (int32_t i = 0; i < ruleCount; ++i) {
  1.1119 +    mozilla::css::Rule* rule = sheet->GetStyleRuleAt(i);
  1.1120 +    if (!rule)
  1.1121 +      continue;
  1.1122 +    switch (rule->GetType()) {
  1.1123 +      default:
  1.1124 +        didSanitize = true;
  1.1125 +        // Ignore these rule types.
  1.1126 +        break;
  1.1127 +      case mozilla::css::Rule::NAMESPACE_RULE:
  1.1128 +      case mozilla::css::Rule::FONT_FACE_RULE: {
  1.1129 +        // Append @namespace and @font-face rules verbatim.
  1.1130 +        nsAutoString cssText;
  1.1131 +        nsCOMPtr<nsIDOMCSSRule> styleRule = do_QueryInterface(rule);
  1.1132 +        if (styleRule) {
  1.1133 +          rv = styleRule->GetCssText(cssText);
  1.1134 +          if (NS_SUCCEEDED(rv)) {
  1.1135 +            aSanitized.Append(cssText);
  1.1136 +          }
  1.1137 +        }
  1.1138 +        break;
  1.1139 +      }
  1.1140 +      case mozilla::css::Rule::STYLE_RULE: {
  1.1141 +        // For style rules, we will just look for and remove the
  1.1142 +        // -moz-binding properties.
  1.1143 +        nsRefPtr<mozilla::css::StyleRule> styleRule = do_QueryObject(rule);
  1.1144 +        NS_ASSERTION(styleRule, "Must be a style rule");
  1.1145 +        nsAutoString decl;
  1.1146 +        bool sanitized = SanitizeStyleRule(styleRule, decl);
  1.1147 +        didSanitize = sanitized || didSanitize;
  1.1148 +        if (!sanitized) {
  1.1149 +          styleRule->GetCssText(decl);
  1.1150 +        }
  1.1151 +        aSanitized.Append(decl);
  1.1152 +      }
  1.1153 +    }
  1.1154 +  }
  1.1155 +  return didSanitize;
  1.1156 +}
  1.1157 +
  1.1158 +void
  1.1159 +nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
  1.1160 +                                    nsTHashtable<nsISupportsHashKey>* aAllowed,
  1.1161 +                                    nsIAtom*** aURLs,
  1.1162 +                                    bool aAllowXLink,
  1.1163 +                                    bool aAllowStyle,
  1.1164 +                                    bool aAllowDangerousSrc)
  1.1165 +{
  1.1166 +  uint32_t ac = aElement->GetAttrCount();
  1.1167 +
  1.1168 +  nsresult rv;
  1.1169 +
  1.1170 +  for (int32_t i = ac - 1; i >= 0; --i) {
  1.1171 +    rv = NS_OK;
  1.1172 +    const nsAttrName* attrName = aElement->GetAttrNameAt(i);
  1.1173 +    int32_t attrNs = attrName->NamespaceID();
  1.1174 +    nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
  1.1175 +
  1.1176 +    if (kNameSpaceID_None == attrNs) {
  1.1177 +      if (aAllowStyle && nsGkAtoms::style == attrLocal) {
  1.1178 +        nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
  1.1179 +        nsIDocument* document = aElement->OwnerDoc();
  1.1180 +        // Pass the CSS Loader object to the parser, to allow parser error
  1.1181 +        // reports to include the outer window ID.
  1.1182 +        nsCSSParser parser(document->CSSLoader());
  1.1183 +        nsRefPtr<mozilla::css::StyleRule> rule;
  1.1184 +        nsAutoString value;
  1.1185 +        aElement->GetAttr(attrNs, attrLocal, value);
  1.1186 +        rv = parser.ParseStyleAttribute(value,
  1.1187 +                                        document->GetDocumentURI(),
  1.1188 +                                        baseURI,
  1.1189 +                                        document->NodePrincipal(),
  1.1190 +                                        getter_AddRefs(rule));
  1.1191 +        if (NS_SUCCEEDED(rv)) {
  1.1192 +          nsAutoString cleanValue;
  1.1193 +          if (SanitizeStyleRule(rule, cleanValue)) {
  1.1194 +            aElement->SetAttr(kNameSpaceID_None,
  1.1195 +                              nsGkAtoms::style,
  1.1196 +                              cleanValue,
  1.1197 +                              false);
  1.1198 +          }
  1.1199 +        }
  1.1200 +        continue;
  1.1201 +      }
  1.1202 +      if (aAllowDangerousSrc && nsGkAtoms::src == attrLocal) {
  1.1203 +        continue;
  1.1204 +      }
  1.1205 +      if (IsURL(aURLs, attrLocal)) {
  1.1206 +        if (SanitizeURL(aElement, attrNs, attrLocal)) {
  1.1207 +          // in case the attribute removal shuffled the attribute order, start
  1.1208 +          // the loop again.
  1.1209 +          --ac;
  1.1210 +          i = ac; // i will be decremented immediately thanks to the for loop
  1.1211 +          continue;
  1.1212 +        }
  1.1213 +        // else fall through to see if there's another reason to drop this
  1.1214 +        // attribute (in particular if the attribute is background="" on an
  1.1215 +        // HTML element)
  1.1216 +      }
  1.1217 +      if (!mDropNonCSSPresentation &&
  1.1218 +          (aAllowed == sAttributesHTML) && // element is HTML
  1.1219 +          sPresAttributesHTML->GetEntry(attrLocal)) {
  1.1220 +        continue;
  1.1221 +      }
  1.1222 +      if (aAllowed->GetEntry(attrLocal) &&
  1.1223 +          !((attrLocal == nsGkAtoms::rel &&
  1.1224 +             aElement->IsHTML(nsGkAtoms::link)) ||
  1.1225 +            (!mFullDocument &&
  1.1226 +             attrLocal == nsGkAtoms::name &&
  1.1227 +             aElement->IsHTML(nsGkAtoms::meta)))) {
  1.1228 +        // name="" and rel="" are whitelisted, but treat them as blacklisted
  1.1229 +        // for <meta name> (fragment case) and <link rel> (all cases) to avoid
  1.1230 +        // document-wide metadata or styling overrides with non-conforming
  1.1231 +        // <meta name itemprop> or
  1.1232 +        // <link rel itemprop>
  1.1233 +        continue;
  1.1234 +      }
  1.1235 +      const char16_t* localStr = attrLocal->GetUTF16String();
  1.1236 +      // Allow underscore to cater to the MCE editor library.
  1.1237 +      // Allow data-* on SVG and MathML, too, as a forward-compat measure.
  1.1238 +      if (*localStr == '_' || (attrLocal->GetLength() > 5 && localStr[0] == 'd'
  1.1239 +          && localStr[1] == 'a' && localStr[2] == 't' && localStr[3] == 'a'
  1.1240 +          && localStr[4] == '-')) {
  1.1241 +        continue;
  1.1242 +      }
  1.1243 +      // else not allowed
  1.1244 +    } else if (kNameSpaceID_XML == attrNs) {
  1.1245 +      if (nsGkAtoms::base == attrLocal) {
  1.1246 +        if (SanitizeURL(aElement, attrNs, attrLocal)) {
  1.1247 +          // in case the attribute removal shuffled the attribute order, start
  1.1248 +          // the loop again.
  1.1249 +          --ac;
  1.1250 +          i = ac; // i will be decremented immediately thanks to the for loop
  1.1251 +        }
  1.1252 +        continue;
  1.1253 +      }
  1.1254 +      if (nsGkAtoms::lang == attrLocal || nsGkAtoms::space == attrLocal) {
  1.1255 +        continue;
  1.1256 +      }
  1.1257 +      // else not allowed
  1.1258 +    } else if (aAllowXLink && kNameSpaceID_XLink == attrNs) {
  1.1259 +      if (nsGkAtoms::href == attrLocal) {
  1.1260 +        if (SanitizeURL(aElement, attrNs, attrLocal)) {
  1.1261 +          // in case the attribute removal shuffled the attribute order, start
  1.1262 +          // the loop again.
  1.1263 +          --ac;
  1.1264 +          i = ac; // i will be decremented immediately thanks to the for loop
  1.1265 +        }
  1.1266 +        continue;
  1.1267 +      }
  1.1268 +      if (nsGkAtoms::type == attrLocal || nsGkAtoms::title == attrLocal
  1.1269 +          || nsGkAtoms::show == attrLocal || nsGkAtoms::actuate == attrLocal) {
  1.1270 +        continue;
  1.1271 +      }
  1.1272 +      // else not allowed
  1.1273 +    }
  1.1274 +    aElement->UnsetAttr(kNameSpaceID_None, attrLocal, false);
  1.1275 +    // in case the attribute removal shuffled the attribute order, start the
  1.1276 +    // loop again.
  1.1277 +    --ac;
  1.1278 +    i = ac; // i will be decremented immediately thanks to the for loop
  1.1279 +  }
  1.1280 +
  1.1281 +  // If we've got HTML audio or video, add the controls attribute, because
  1.1282 +  // otherwise the content is unplayable with scripts removed.
  1.1283 +  if (aElement->IsHTML(nsGkAtoms::video) ||
  1.1284 +      aElement->IsHTML(nsGkAtoms::audio)) {
  1.1285 +    aElement->SetAttr(kNameSpaceID_None,
  1.1286 +                      nsGkAtoms::controls,
  1.1287 +                      EmptyString(),
  1.1288 +                      false);
  1.1289 +  }
  1.1290 +}
  1.1291 +
  1.1292 +bool
  1.1293 +nsTreeSanitizer::SanitizeURL(mozilla::dom::Element* aElement,
  1.1294 +                             int32_t aNamespace,
  1.1295 +                             nsIAtom* aLocalName)
  1.1296 +{
  1.1297 +  nsAutoString value;
  1.1298 +  aElement->GetAttr(aNamespace, aLocalName, value);
  1.1299 +
  1.1300 +  // Get value and remove mandatory quotes
  1.1301 +  static const char* kWhitespace = "\n\r\t\b";
  1.1302 +  const nsAString& v =
  1.1303 +    nsContentUtils::TrimCharsInSet(kWhitespace, value);
  1.1304 +
  1.1305 +  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
  1.1306 +  uint32_t flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL;
  1.1307 +
  1.1308 +  nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
  1.1309 +  nsCOMPtr<nsIURI> attrURI;
  1.1310 +  nsresult rv = NS_NewURI(getter_AddRefs(attrURI), v, nullptr, baseURI);
  1.1311 +  if (NS_SUCCEEDED(rv)) { 
  1.1312 +    if (mCidEmbedsOnly &&
  1.1313 +        kNameSpaceID_None == aNamespace) {
  1.1314 +      if (nsGkAtoms::src == aLocalName || nsGkAtoms::background == aLocalName) {
  1.1315 +        // comm-central uses a hack that makes nsIURIs created with cid: specs
  1.1316 +        // actually have an about:blank spec. Therefore, nsIURI facilities are
  1.1317 +        // useless for cid: when comm-central code is participating.
  1.1318 +        if (!(v.Length() > 4 &&
  1.1319 +              (v[0] == 'c' || v[0] == 'C') &&
  1.1320 +              (v[1] == 'i' || v[1] == 'I') &&
  1.1321 +              (v[2] == 'd' || v[2] == 'D') &&
  1.1322 +              v[3] == ':')) {
  1.1323 +          rv = NS_ERROR_FAILURE;
  1.1324 +        }
  1.1325 +      } else if (nsGkAtoms::cdgroup_ == aLocalName ||
  1.1326 +                 nsGkAtoms::altimg_ == aLocalName ||
  1.1327 +                 nsGkAtoms::definitionURL_ == aLocalName) {
  1.1328 +        // Gecko doesn't fetch these now and shouldn't in the future, but
  1.1329 +        // in case someone goofs with these in the future, let's drop them.
  1.1330 +        rv = NS_ERROR_FAILURE;
  1.1331 +      } else {
  1.1332 +        rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
  1.1333 +      }
  1.1334 +    } else {
  1.1335 +      rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
  1.1336 +    }
  1.1337 +  }
  1.1338 +  if (NS_FAILED(rv)) {
  1.1339 +    aElement->UnsetAttr(aNamespace, aLocalName, false);
  1.1340 +    return true;
  1.1341 +  }
  1.1342 +  return false;
  1.1343 +}
  1.1344 +
  1.1345 +void
  1.1346 +nsTreeSanitizer::Sanitize(nsIContent* aFragment)
  1.1347 +{
  1.1348 +  // If you want to relax these preconditions, be sure to check the code in
  1.1349 +  // here that notifies / does not notify or that fires mutation events if
  1.1350 +  // in tree.
  1.1351 +  NS_PRECONDITION(aFragment->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT),
  1.1352 +      "Argument was not DOM fragment.");
  1.1353 +  NS_PRECONDITION(!aFragment->IsInDoc(), "The fragment is in doc?");
  1.1354 +
  1.1355 +  mFullDocument = false;
  1.1356 +  SanitizeChildren(aFragment);
  1.1357 +}
  1.1358 +
  1.1359 +void
  1.1360 +nsTreeSanitizer::Sanitize(nsIDocument* aDocument)
  1.1361 +{
  1.1362 +  // If you want to relax these preconditions, be sure to check the code in
  1.1363 +  // here that notifies / does not notify or that fires mutation events if
  1.1364 +  // in tree.
  1.1365 +#ifdef DEBUG
  1.1366 +  NS_PRECONDITION(!aDocument->GetContainer(), "The document is in a shell.");
  1.1367 +  nsRefPtr<mozilla::dom::Element> root = aDocument->GetRootElement();
  1.1368 +  NS_PRECONDITION(root->IsHTML(nsGkAtoms::html), "Not HTML root.");
  1.1369 +#endif
  1.1370 +
  1.1371 +  mFullDocument = true;
  1.1372 +  SanitizeChildren(aDocument);
  1.1373 +}
  1.1374 +
  1.1375 +void
  1.1376 +nsTreeSanitizer::SanitizeChildren(nsINode* aRoot)
  1.1377 +{
  1.1378 +  nsIContent* node = aRoot->GetFirstChild();
  1.1379 +  while (node) {
  1.1380 +    if (node->IsElement()) {
  1.1381 +      mozilla::dom::Element* elt = node->AsElement();
  1.1382 +      nsINodeInfo* nodeInfo = node->NodeInfo();
  1.1383 +      nsIAtom* localName = nodeInfo->NameAtom();
  1.1384 +      int32_t ns = nodeInfo->NamespaceID();
  1.1385 +
  1.1386 +      if (MustPrune(ns, localName, elt)) {
  1.1387 +        RemoveAllAttributes(node);
  1.1388 +        nsIContent* descendant = node;
  1.1389 +        while ((descendant = descendant->GetNextNode(node))) {
  1.1390 +          RemoveAllAttributes(descendant);
  1.1391 +        }
  1.1392 +        nsIContent* next = node->GetNextNonChildNode(aRoot);
  1.1393 +        node->RemoveFromParent();
  1.1394 +        node = next;
  1.1395 +        continue;
  1.1396 +      }
  1.1397 +      if (nsGkAtoms::style == localName) {
  1.1398 +        // If styles aren't allowed, style elements got pruned above. Even
  1.1399 +        // if styles are allowed, non-HTML, non-SVG style elements got pruned
  1.1400 +        // above.
  1.1401 +        NS_ASSERTION(ns == kNameSpaceID_XHTML || ns == kNameSpaceID_SVG,
  1.1402 +            "Should have only HTML or SVG here!");
  1.1403 +        nsAutoString styleText;
  1.1404 +        if (!nsContentUtils::GetNodeTextContent(node, false, styleText)) {
  1.1405 +          NS_RUNTIMEABORT("OOM");
  1.1406 +        }
  1.1407 +        nsAutoString sanitizedStyle;
  1.1408 +        nsCOMPtr<nsIURI> baseURI = node->GetBaseURI();
  1.1409 +        if (SanitizeStyleSheet(styleText,
  1.1410 +                               sanitizedStyle,
  1.1411 +                               aRoot->OwnerDoc(),
  1.1412 +                               baseURI)) {
  1.1413 +          nsContentUtils::SetNodeTextContent(node, sanitizedStyle, true);
  1.1414 +        } else {
  1.1415 +          // If the node had non-text child nodes, this operation zaps those.
  1.1416 +          nsContentUtils::SetNodeTextContent(node, styleText, true);
  1.1417 +        }
  1.1418 +        if (ns == kNameSpaceID_XHTML) {
  1.1419 +          SanitizeAttributes(elt,
  1.1420 +                             sAttributesHTML,
  1.1421 +                             (nsIAtom***)kURLAttributesHTML,
  1.1422 +                             false,
  1.1423 +                             mAllowStyles,
  1.1424 +                             false);
  1.1425 +        } else {
  1.1426 +          SanitizeAttributes(elt,
  1.1427 +                             sAttributesSVG,
  1.1428 +                             (nsIAtom***)kURLAttributesSVG,
  1.1429 +                             true,
  1.1430 +                             mAllowStyles,
  1.1431 +                             false);
  1.1432 +        }
  1.1433 +        node = node->GetNextNonChildNode(aRoot);
  1.1434 +        continue;
  1.1435 +      }
  1.1436 +      if (MustFlatten(ns, localName)) {
  1.1437 +        RemoveAllAttributes(node);
  1.1438 +        nsIContent* next = node->GetNextNode(aRoot);
  1.1439 +        nsIContent* parent = node->GetParent();
  1.1440 +        nsCOMPtr<nsIContent> child; // Must keep the child alive during move
  1.1441 +        ErrorResult rv;
  1.1442 +        while ((child = node->GetFirstChild())) {
  1.1443 +          parent->InsertBefore(*child, node, rv);
  1.1444 +          if (rv.Failed()) {
  1.1445 +            break;
  1.1446 +          }
  1.1447 +        }
  1.1448 +        node->RemoveFromParent();
  1.1449 +        node = next;
  1.1450 +        continue;
  1.1451 +      }
  1.1452 +      NS_ASSERTION(ns == kNameSpaceID_XHTML ||
  1.1453 +                   ns == kNameSpaceID_SVG ||
  1.1454 +                   ns == kNameSpaceID_MathML,
  1.1455 +          "Should have only HTML, MathML or SVG here!");
  1.1456 +      if (ns == kNameSpaceID_XHTML) {
  1.1457 +        SanitizeAttributes(elt,
  1.1458 +                           sAttributesHTML,
  1.1459 +                           (nsIAtom***)kURLAttributesHTML,
  1.1460 +                           false, mAllowStyles,
  1.1461 +                           (nsGkAtoms::img == localName) &&
  1.1462 +                           !mCidEmbedsOnly);
  1.1463 +      } else if (ns == kNameSpaceID_SVG) {
  1.1464 +        SanitizeAttributes(elt,
  1.1465 +                           sAttributesSVG,
  1.1466 +                           (nsIAtom***)kURLAttributesSVG,
  1.1467 +                           true,
  1.1468 +                           mAllowStyles,
  1.1469 +                           false);
  1.1470 +      } else {
  1.1471 +        SanitizeAttributes(elt,
  1.1472 +                           sAttributesMathML,
  1.1473 +                           (nsIAtom***)kURLAttributesMathML,
  1.1474 +                           true,
  1.1475 +                           false,
  1.1476 +                           false);
  1.1477 +      }
  1.1478 +      node = node->GetNextNode(aRoot);
  1.1479 +      continue;
  1.1480 +    }
  1.1481 +    NS_ASSERTION(!node->GetFirstChild(), "How come non-element node had kids?");
  1.1482 +    nsIContent* next = node->GetNextNonChildNode(aRoot);
  1.1483 +    if (!mAllowComments && node->IsNodeOfType(nsINode::eCOMMENT)) {
  1.1484 +      node->RemoveFromParent();
  1.1485 +    }
  1.1486 +    node = next;
  1.1487 +  }
  1.1488 +}
  1.1489 +
  1.1490 +void
  1.1491 +nsTreeSanitizer::RemoveAllAttributes(nsIContent* aElement)
  1.1492 +{
  1.1493 +  const nsAttrName* attrName;
  1.1494 +  while ((attrName = aElement->GetAttrNameAt(0))) {
  1.1495 +    int32_t attrNs = attrName->NamespaceID();
  1.1496 +    nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
  1.1497 +    aElement->UnsetAttr(attrNs, attrLocal, false);
  1.1498 +  }
  1.1499 +}
  1.1500 +
  1.1501 +void
  1.1502 +nsTreeSanitizer::InitializeStatics()
  1.1503 +{
  1.1504 +  NS_PRECONDITION(!sElementsHTML, "Initializing a second time.");
  1.1505 +
  1.1506 +  sElementsHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsHTML));
  1.1507 +  for (uint32_t i = 0; kElementsHTML[i]; i++) {
  1.1508 +    sElementsHTML->PutEntry(*kElementsHTML[i]);
  1.1509 +  }
  1.1510 +
  1.1511 +  sAttributesHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesHTML));
  1.1512 +  for (uint32_t i = 0; kAttributesHTML[i]; i++) {
  1.1513 +    sAttributesHTML->PutEntry(*kAttributesHTML[i]);
  1.1514 +  }
  1.1515 +
  1.1516 +  sPresAttributesHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kPresAttributesHTML));
  1.1517 +  for (uint32_t i = 0; kPresAttributesHTML[i]; i++) {
  1.1518 +    sPresAttributesHTML->PutEntry(*kPresAttributesHTML[i]);
  1.1519 +  }
  1.1520 +
  1.1521 +  sElementsSVG = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsSVG));
  1.1522 +  for (uint32_t i = 0; kElementsSVG[i]; i++) {
  1.1523 +    sElementsSVG->PutEntry(*kElementsSVG[i]);
  1.1524 +  }
  1.1525 +
  1.1526 +  sAttributesSVG = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesSVG));
  1.1527 +  for (uint32_t i = 0; kAttributesSVG[i]; i++) {
  1.1528 +    sAttributesSVG->PutEntry(*kAttributesSVG[i]);
  1.1529 +  }
  1.1530 +
  1.1531 +  sElementsMathML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsMathML));
  1.1532 +  for (uint32_t i = 0; kElementsMathML[i]; i++) {
  1.1533 +    sElementsMathML->PutEntry(*kElementsMathML[i]);
  1.1534 +  }
  1.1535 +
  1.1536 +  sAttributesMathML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesMathML));
  1.1537 +  for (uint32_t i = 0; kAttributesMathML[i]; i++) {
  1.1538 +    sAttributesMathML->PutEntry(*kAttributesMathML[i]);
  1.1539 +  }
  1.1540 +
  1.1541 +  nsCOMPtr<nsIPrincipal> principal =
  1.1542 +      do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID);
  1.1543 +  principal.forget(&sNullPrincipal);
  1.1544 +}
  1.1545 +
  1.1546 +void
  1.1547 +nsTreeSanitizer::ReleaseStatics()
  1.1548 +{
  1.1549 +  delete sElementsHTML;
  1.1550 +  sElementsHTML = nullptr;
  1.1551 +
  1.1552 +  delete sAttributesHTML;
  1.1553 +  sAttributesHTML = nullptr;
  1.1554 +
  1.1555 +  delete sPresAttributesHTML;
  1.1556 +  sPresAttributesHTML = nullptr;
  1.1557 +
  1.1558 +  delete sElementsSVG;
  1.1559 +  sElementsSVG = nullptr;
  1.1560 +
  1.1561 +  delete sAttributesSVG;
  1.1562 +  sAttributesSVG = nullptr;
  1.1563 +
  1.1564 +  delete sElementsMathML;
  1.1565 +  sElementsMathML = nullptr;
  1.1566 +
  1.1567 +  delete sAttributesMathML;
  1.1568 +  sAttributesMathML = nullptr;
  1.1569 +
  1.1570 +  NS_IF_RELEASE(sNullPrincipal);
  1.1571 +}

mercurial