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