Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=2 et tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/ArrayUtils.h"
9 #include "nsTreeSanitizer.h"
10 #include "nsCSSParser.h"
11 #include "nsCSSProperty.h"
12 #include "mozilla/css/Declaration.h"
13 #include "mozilla/css/StyleRule.h"
14 #include "mozilla/css/Rule.h"
15 #include "nsUnicharInputStream.h"
16 #include "nsCSSStyleSheet.h"
17 #include "nsIDOMCSSRule.h"
18 #include "nsAttrName.h"
19 #include "nsIScriptSecurityManager.h"
20 #include "nsNetUtil.h"
21 #include "nsComponentManagerUtils.h"
22 #include "nsNullPrincipal.h"
23 #include "nsContentUtils.h"
24 #include "nsIParserUtils.h"
25 #include "nsIDocument.h"
27 using namespace mozilla;
29 //
30 // Thanks to Mark Pilgrim and Sam Ruby for the initial whitelist
31 //
32 nsIAtom** const kElementsHTML[] = {
33 &nsGkAtoms::a,
34 &nsGkAtoms::abbr,
35 &nsGkAtoms::acronym,
36 &nsGkAtoms::address,
37 &nsGkAtoms::area,
38 &nsGkAtoms::article,
39 &nsGkAtoms::aside,
40 &nsGkAtoms::audio,
41 &nsGkAtoms::b,
42 &nsGkAtoms::bdi,
43 &nsGkAtoms::bdo,
44 &nsGkAtoms::big,
45 &nsGkAtoms::blockquote,
46 // body checked specially
47 &nsGkAtoms::br,
48 &nsGkAtoms::button,
49 &nsGkAtoms::canvas,
50 &nsGkAtoms::caption,
51 &nsGkAtoms::center,
52 &nsGkAtoms::cite,
53 &nsGkAtoms::code,
54 &nsGkAtoms::col,
55 &nsGkAtoms::colgroup,
56 &nsGkAtoms::command,
57 &nsGkAtoms::datalist,
58 &nsGkAtoms::dd,
59 &nsGkAtoms::del,
60 &nsGkAtoms::details,
61 &nsGkAtoms::dfn,
62 &nsGkAtoms::dir,
63 &nsGkAtoms::div,
64 &nsGkAtoms::dl,
65 &nsGkAtoms::dt,
66 &nsGkAtoms::em,
67 &nsGkAtoms::fieldset,
68 &nsGkAtoms::figcaption,
69 &nsGkAtoms::figure,
70 &nsGkAtoms::font,
71 &nsGkAtoms::footer,
72 &nsGkAtoms::form,
73 &nsGkAtoms::h1,
74 &nsGkAtoms::h2,
75 &nsGkAtoms::h3,
76 &nsGkAtoms::h4,
77 &nsGkAtoms::h5,
78 &nsGkAtoms::h6,
79 // head checked specially
80 &nsGkAtoms::header,
81 &nsGkAtoms::hgroup,
82 &nsGkAtoms::hr,
83 // html checked specially
84 &nsGkAtoms::i,
85 &nsGkAtoms::img,
86 &nsGkAtoms::input,
87 &nsGkAtoms::ins,
88 &nsGkAtoms::kbd,
89 &nsGkAtoms::label,
90 &nsGkAtoms::legend,
91 &nsGkAtoms::li,
92 &nsGkAtoms::link,
93 &nsGkAtoms::listing,
94 &nsGkAtoms::map,
95 &nsGkAtoms::mark,
96 &nsGkAtoms::menu,
97 &nsGkAtoms::meta,
98 &nsGkAtoms::meter,
99 &nsGkAtoms::nav,
100 &nsGkAtoms::nobr,
101 &nsGkAtoms::noscript,
102 &nsGkAtoms::ol,
103 &nsGkAtoms::optgroup,
104 &nsGkAtoms::option,
105 &nsGkAtoms::output,
106 &nsGkAtoms::p,
107 &nsGkAtoms::pre,
108 &nsGkAtoms::progress,
109 &nsGkAtoms::q,
110 &nsGkAtoms::rp,
111 &nsGkAtoms::rt,
112 &nsGkAtoms::ruby,
113 &nsGkAtoms::s,
114 &nsGkAtoms::samp,
115 &nsGkAtoms::section,
116 &nsGkAtoms::select,
117 &nsGkAtoms::small,
118 &nsGkAtoms::source,
119 &nsGkAtoms::span,
120 &nsGkAtoms::strike,
121 &nsGkAtoms::strong,
122 &nsGkAtoms::sub,
123 &nsGkAtoms::summary,
124 &nsGkAtoms::sup,
125 // style checked specially
126 &nsGkAtoms::table,
127 &nsGkAtoms::tbody,
128 &nsGkAtoms::td,
129 &nsGkAtoms::textarea,
130 &nsGkAtoms::tfoot,
131 &nsGkAtoms::th,
132 &nsGkAtoms::thead,
133 &nsGkAtoms::time,
134 // title checked specially
135 &nsGkAtoms::tr,
136 &nsGkAtoms::track,
137 &nsGkAtoms::tt,
138 &nsGkAtoms::u,
139 &nsGkAtoms::ul,
140 &nsGkAtoms::var,
141 &nsGkAtoms::video,
142 &nsGkAtoms::wbr,
143 nullptr
144 };
146 nsIAtom** const kAttributesHTML[] = {
147 &nsGkAtoms::abbr,
148 &nsGkAtoms::accept,
149 &nsGkAtoms::acceptcharset,
150 &nsGkAtoms::accesskey,
151 &nsGkAtoms::action,
152 &nsGkAtoms::alt,
153 &nsGkAtoms::autocomplete,
154 &nsGkAtoms::autofocus,
155 &nsGkAtoms::autoplay,
156 &nsGkAtoms::axis,
157 &nsGkAtoms::_char,
158 &nsGkAtoms::charoff,
159 &nsGkAtoms::charset,
160 &nsGkAtoms::checked,
161 &nsGkAtoms::cite,
162 &nsGkAtoms::_class,
163 &nsGkAtoms::cols,
164 &nsGkAtoms::colspan,
165 &nsGkAtoms::content,
166 &nsGkAtoms::contenteditable,
167 &nsGkAtoms::contextmenu,
168 &nsGkAtoms::controls,
169 &nsGkAtoms::coords,
170 &nsGkAtoms::datetime,
171 &nsGkAtoms::dir,
172 &nsGkAtoms::disabled,
173 &nsGkAtoms::draggable,
174 &nsGkAtoms::enctype,
175 &nsGkAtoms::face,
176 &nsGkAtoms::_for,
177 &nsGkAtoms::frame,
178 &nsGkAtoms::headers,
179 &nsGkAtoms::height,
180 &nsGkAtoms::hidden,
181 &nsGkAtoms::high,
182 &nsGkAtoms::href,
183 &nsGkAtoms::hreflang,
184 &nsGkAtoms::icon,
185 &nsGkAtoms::id,
186 &nsGkAtoms::ismap,
187 &nsGkAtoms::itemid,
188 &nsGkAtoms::itemprop,
189 &nsGkAtoms::itemref,
190 &nsGkAtoms::itemscope,
191 &nsGkAtoms::itemtype,
192 &nsGkAtoms::kind,
193 &nsGkAtoms::label,
194 &nsGkAtoms::lang,
195 &nsGkAtoms::list,
196 &nsGkAtoms::longdesc,
197 &nsGkAtoms::loop,
198 &nsGkAtoms::low,
199 &nsGkAtoms::max,
200 &nsGkAtoms::maxlength,
201 &nsGkAtoms::media,
202 &nsGkAtoms::method,
203 &nsGkAtoms::min,
204 &nsGkAtoms::mozdonotsend,
205 &nsGkAtoms::multiple,
206 &nsGkAtoms::muted,
207 &nsGkAtoms::name,
208 &nsGkAtoms::nohref,
209 &nsGkAtoms::novalidate,
210 &nsGkAtoms::nowrap,
211 &nsGkAtoms::open,
212 &nsGkAtoms::optimum,
213 &nsGkAtoms::pattern,
214 &nsGkAtoms::placeholder,
215 &nsGkAtoms::playbackrate,
216 &nsGkAtoms::poster,
217 &nsGkAtoms::preload,
218 &nsGkAtoms::prompt,
219 &nsGkAtoms::pubdate,
220 &nsGkAtoms::radiogroup,
221 &nsGkAtoms::readonly,
222 &nsGkAtoms::rel,
223 &nsGkAtoms::required,
224 &nsGkAtoms::rev,
225 &nsGkAtoms::reversed,
226 &nsGkAtoms::role,
227 &nsGkAtoms::rows,
228 &nsGkAtoms::rowspan,
229 &nsGkAtoms::rules,
230 &nsGkAtoms::scoped,
231 &nsGkAtoms::scope,
232 &nsGkAtoms::selected,
233 &nsGkAtoms::shape,
234 &nsGkAtoms::span,
235 &nsGkAtoms::spellcheck,
236 &nsGkAtoms::src,
237 &nsGkAtoms::srclang,
238 &nsGkAtoms::start,
239 &nsGkAtoms::summary,
240 &nsGkAtoms::tabindex,
241 &nsGkAtoms::target,
242 &nsGkAtoms::title,
243 &nsGkAtoms::type,
244 &nsGkAtoms::usemap,
245 &nsGkAtoms::value,
246 &nsGkAtoms::width,
247 &nsGkAtoms::wrap,
248 nullptr
249 };
251 nsIAtom** const kPresAttributesHTML[] = {
252 &nsGkAtoms::align,
253 &nsGkAtoms::background,
254 &nsGkAtoms::bgcolor,
255 &nsGkAtoms::border,
256 &nsGkAtoms::cellpadding,
257 &nsGkAtoms::cellspacing,
258 &nsGkAtoms::color,
259 &nsGkAtoms::compact,
260 &nsGkAtoms::clear,
261 &nsGkAtoms::hspace,
262 &nsGkAtoms::noshade,
263 &nsGkAtoms::pointSize,
264 &nsGkAtoms::size,
265 &nsGkAtoms::valign,
266 &nsGkAtoms::vspace,
267 nullptr
268 };
270 nsIAtom** const kURLAttributesHTML[] = {
271 &nsGkAtoms::action,
272 &nsGkAtoms::href,
273 &nsGkAtoms::src,
274 &nsGkAtoms::longdesc,
275 &nsGkAtoms::cite,
276 &nsGkAtoms::background,
277 nullptr
278 };
280 nsIAtom** const kElementsSVG[] = {
281 &nsGkAtoms::a, // a
282 &nsGkAtoms::altGlyph, // altGlyph
283 &nsGkAtoms::altGlyphDef, // altGlyphDef
284 &nsGkAtoms::altGlyphItem, // altGlyphItem
285 &nsGkAtoms::animate, // animate
286 &nsGkAtoms::animateColor, // animateColor
287 &nsGkAtoms::animateMotion, // animateMotion
288 &nsGkAtoms::animateTransform, // animateTransform
289 &nsGkAtoms::circle, // circle
290 &nsGkAtoms::clipPath, // clipPath
291 &nsGkAtoms::colorProfile, // color-profile
292 &nsGkAtoms::cursor, // cursor
293 &nsGkAtoms::defs, // defs
294 &nsGkAtoms::desc, // desc
295 &nsGkAtoms::ellipse, // ellipse
296 &nsGkAtoms::elevation, // elevation
297 &nsGkAtoms::erode, // erode
298 &nsGkAtoms::ex, // ex
299 &nsGkAtoms::exact, // exact
300 &nsGkAtoms::exponent, // exponent
301 &nsGkAtoms::feBlend, // feBlend
302 &nsGkAtoms::feColorMatrix, // feColorMatrix
303 &nsGkAtoms::feComponentTransfer, // feComponentTransfer
304 &nsGkAtoms::feComposite, // feComposite
305 &nsGkAtoms::feConvolveMatrix, // feConvolveMatrix
306 &nsGkAtoms::feDiffuseLighting, // feDiffuseLighting
307 &nsGkAtoms::feDisplacementMap, // feDisplacementMap
308 &nsGkAtoms::feDistantLight, // feDistantLight
309 &nsGkAtoms::feDropShadow, // feDropShadow
310 &nsGkAtoms::feFlood, // feFlood
311 &nsGkAtoms::feFuncA, // feFuncA
312 &nsGkAtoms::feFuncB, // feFuncB
313 &nsGkAtoms::feFuncG, // feFuncG
314 &nsGkAtoms::feFuncR, // feFuncR
315 &nsGkAtoms::feGaussianBlur, // feGaussianBlur
316 &nsGkAtoms::feImage, // feImage
317 &nsGkAtoms::feMerge, // feMerge
318 &nsGkAtoms::feMergeNode, // feMergeNode
319 &nsGkAtoms::feMorphology, // feMorphology
320 &nsGkAtoms::feOffset, // feOffset
321 &nsGkAtoms::fePointLight, // fePointLight
322 &nsGkAtoms::feSpecularLighting, // feSpecularLighting
323 &nsGkAtoms::feSpotLight, // feSpotLight
324 &nsGkAtoms::feTile, // feTile
325 &nsGkAtoms::feTurbulence, // feTurbulence
326 &nsGkAtoms::filter, // filter
327 &nsGkAtoms::font, // font
328 &nsGkAtoms::font_face, // font-face
329 &nsGkAtoms::font_face_format, // font-face-format
330 &nsGkAtoms::font_face_name, // font-face-name
331 &nsGkAtoms::font_face_src, // font-face-src
332 &nsGkAtoms::font_face_uri, // font-face-uri
333 &nsGkAtoms::foreignObject, // foreignObject
334 &nsGkAtoms::g, // g
335 &nsGkAtoms::glyph, // glyph
336 &nsGkAtoms::glyphRef, // glyphRef
337 &nsGkAtoms::hkern, // hkern
338 &nsGkAtoms::image, // image
339 &nsGkAtoms::line, // line
340 &nsGkAtoms::linearGradient, // linearGradient
341 &nsGkAtoms::marker, // marker
342 &nsGkAtoms::mask, // mask
343 &nsGkAtoms::metadata, // metadata
344 &nsGkAtoms::missingGlyph, // missingGlyph
345 &nsGkAtoms::mpath, // mpath
346 &nsGkAtoms::path, // path
347 &nsGkAtoms::pattern, // pattern
348 &nsGkAtoms::polygon, // polygon
349 &nsGkAtoms::polyline, // polyline
350 &nsGkAtoms::radialGradient, // radialGradient
351 &nsGkAtoms::rect, // rect
352 &nsGkAtoms::set, // set
353 &nsGkAtoms::stop, // stop
354 &nsGkAtoms::svg, // svg
355 &nsGkAtoms::svgSwitch, // switch
356 &nsGkAtoms::symbol, // symbol
357 &nsGkAtoms::text, // text
358 &nsGkAtoms::textPath, // textPath
359 &nsGkAtoms::title, // title
360 &nsGkAtoms::tref, // tref
361 &nsGkAtoms::tspan, // tspan
362 &nsGkAtoms::use, // use
363 &nsGkAtoms::view, // view
364 &nsGkAtoms::vkern, // vkern
365 nullptr
366 };
368 nsIAtom** const kAttributesSVG[] = {
369 // accent-height
370 &nsGkAtoms::accumulate, // accumulate
371 &nsGkAtoms::additive, // additive
372 &nsGkAtoms::alignment_baseline, // alignment-baseline
373 // alphabetic
374 &nsGkAtoms::amplitude, // amplitude
375 // arabic-form
376 // ascent
377 &nsGkAtoms::attributeName, // attributeName
378 &nsGkAtoms::attributeType, // attributeType
379 &nsGkAtoms::azimuth, // azimuth
380 &nsGkAtoms::baseFrequency, // baseFrequency
381 &nsGkAtoms::baseline_shift, // baseline-shift
382 // baseProfile
383 // bbox
384 &nsGkAtoms::begin, // begin
385 &nsGkAtoms::bias, // bias
386 &nsGkAtoms::by, // by
387 &nsGkAtoms::calcMode, // calcMode
388 // cap-height
389 &nsGkAtoms::_class, // class
390 &nsGkAtoms::clip_path, // clip-path
391 &nsGkAtoms::clip_rule, // clip-rule
392 &nsGkAtoms::clipPathUnits, // clipPathUnits
393 &nsGkAtoms::color, // color
394 &nsGkAtoms::colorInterpolation, // color-interpolation
395 &nsGkAtoms::colorInterpolationFilters, // color-interpolation-filters
396 // contentScriptType
397 // contentStyleType
398 &nsGkAtoms::cursor, // cursor
399 &nsGkAtoms::cx, // cx
400 &nsGkAtoms::cy, // cy
401 &nsGkAtoms::d, // d
402 // descent
403 &nsGkAtoms::diffuseConstant, // diffuseConstant
404 &nsGkAtoms::direction, // direction
405 &nsGkAtoms::display, // display
406 &nsGkAtoms::divisor, // divisor
407 &nsGkAtoms::dominant_baseline, // dominant-baseline
408 &nsGkAtoms::dur, // dur
409 &nsGkAtoms::dx, // dx
410 &nsGkAtoms::dy, // dy
411 &nsGkAtoms::edgeMode, // edgeMode
412 &nsGkAtoms::elevation, // elevation
413 // enable-background
414 &nsGkAtoms::end, // end
415 &nsGkAtoms::fill, // fill
416 &nsGkAtoms::fill_opacity, // fill-opacity
417 &nsGkAtoms::fill_rule, // fill-rule
418 &nsGkAtoms::filter, // filter
419 &nsGkAtoms::filterRes, // filterRes
420 &nsGkAtoms::filterUnits, // filterUnits
421 &nsGkAtoms::flood_color, // flood-color
422 &nsGkAtoms::flood_opacity, // flood-opacity
423 // XXX focusable
424 &nsGkAtoms::font, // font
425 &nsGkAtoms::font_family, // font-family
426 &nsGkAtoms::font_size, // font-size
427 &nsGkAtoms::font_size_adjust, // font-size-adjust
428 &nsGkAtoms::font_stretch, // font-stretch
429 &nsGkAtoms::font_style, // font-style
430 &nsGkAtoms::font_variant, // font-variant
431 &nsGkAtoms::fontWeight, // font-weight
432 &nsGkAtoms::format, // format
433 &nsGkAtoms::from, // from
434 &nsGkAtoms::fx, // fx
435 &nsGkAtoms::fy, // fy
436 // g1
437 // g2
438 // glyph-name
439 // glyphRef
440 &nsGkAtoms::glyph_orientation_horizontal, // glyph-orientation-horizontal
441 &nsGkAtoms::glyph_orientation_vertical, // glyph-orientation-vertical
442 &nsGkAtoms::gradientTransform, // gradientTransform
443 &nsGkAtoms::gradientUnits, // gradientUnits
444 &nsGkAtoms::height, // height
445 // horiz-adv-x
446 // horiz-origin-x
447 // horiz-origin-y
448 &nsGkAtoms::id, // id
449 // ideographic
450 &nsGkAtoms::image_rendering, // image-rendering
451 &nsGkAtoms::in, // in
452 &nsGkAtoms::in2, // in2
453 &nsGkAtoms::intercept, // intercept
454 // k
455 &nsGkAtoms::k1, // k1
456 &nsGkAtoms::k2, // k2
457 &nsGkAtoms::k3, // k3
458 &nsGkAtoms::k4, // k4
459 &nsGkAtoms::kerning, // kerning
460 &nsGkAtoms::kernelMatrix, // kernelMatrix
461 &nsGkAtoms::kernelUnitLength, // kernelUnitLength
462 &nsGkAtoms::keyPoints, // keyPoints
463 &nsGkAtoms::keySplines, // keySplines
464 &nsGkAtoms::keyTimes, // keyTimes
465 &nsGkAtoms::lang, // lang
466 // lengthAdjust
467 &nsGkAtoms::letter_spacing, // letter-spacing
468 &nsGkAtoms::lighting_color, // lighting-color
469 &nsGkAtoms::limitingConeAngle, // limitingConeAngle
470 // local
471 &nsGkAtoms::marker, // marker
472 &nsGkAtoms::marker_end, // marker-end
473 &nsGkAtoms::marker_mid, // marker-mid
474 &nsGkAtoms::marker_start, // marker-start
475 &nsGkAtoms::markerHeight, // markerHeight
476 &nsGkAtoms::markerUnits, // markerUnits
477 &nsGkAtoms::markerWidth, // markerWidth
478 &nsGkAtoms::mask, // mask
479 &nsGkAtoms::maskContentUnits, // maskContentUnits
480 &nsGkAtoms::maskUnits, // maskUnits
481 // mathematical
482 &nsGkAtoms::max, // max
483 &nsGkAtoms::media, // media
484 &nsGkAtoms::method, // method
485 &nsGkAtoms::min, // min
486 &nsGkAtoms::mode, // mode
487 &nsGkAtoms::name, // name
488 &nsGkAtoms::numOctaves, // numOctaves
489 &nsGkAtoms::offset, // offset
490 &nsGkAtoms::opacity, // opacity
491 &nsGkAtoms::_operator, // operator
492 &nsGkAtoms::order, // order
493 &nsGkAtoms::orient, // orient
494 &nsGkAtoms::orientation, // orientation
495 // origin
496 // overline-position
497 // overline-thickness
498 &nsGkAtoms::overflow, // overflow
499 // panose-1
500 &nsGkAtoms::path, // path
501 &nsGkAtoms::pathLength, // pathLength
502 &nsGkAtoms::patternContentUnits, // patternContentUnits
503 &nsGkAtoms::patternTransform, // patternTransform
504 &nsGkAtoms::patternUnits, // patternUnits
505 &nsGkAtoms::pointer_events, // pointer-events XXX is this safe?
506 &nsGkAtoms::points, // points
507 &nsGkAtoms::pointsAtX, // pointsAtX
508 &nsGkAtoms::pointsAtY, // pointsAtY
509 &nsGkAtoms::pointsAtZ, // pointsAtZ
510 &nsGkAtoms::preserveAlpha, // preserveAlpha
511 &nsGkAtoms::preserveAspectRatio, // preserveAspectRatio
512 &nsGkAtoms::primitiveUnits, // primitiveUnits
513 &nsGkAtoms::r, // r
514 &nsGkAtoms::radius, // radius
515 &nsGkAtoms::refX, // refX
516 &nsGkAtoms::refY, // refY
517 &nsGkAtoms::repeatCount, // repeatCount
518 &nsGkAtoms::repeatDur, // repeatDur
519 &nsGkAtoms::requiredExtensions, // requiredExtensions
520 &nsGkAtoms::requiredFeatures, // requiredFeatures
521 &nsGkAtoms::restart, // restart
522 &nsGkAtoms::result, // result
523 &nsGkAtoms::rotate, // rotate
524 &nsGkAtoms::rx, // rx
525 &nsGkAtoms::ry, // ry
526 &nsGkAtoms::scale, // scale
527 &nsGkAtoms::seed, // seed
528 &nsGkAtoms::shape_rendering, // shape-rendering
529 &nsGkAtoms::slope, // slope
530 &nsGkAtoms::spacing, // spacing
531 &nsGkAtoms::specularConstant, // specularConstant
532 &nsGkAtoms::specularExponent, // specularExponent
533 &nsGkAtoms::spreadMethod, // spreadMethod
534 &nsGkAtoms::startOffset, // startOffset
535 &nsGkAtoms::stdDeviation, // stdDeviation
536 // stemh
537 // stemv
538 &nsGkAtoms::stitchTiles, // stitchTiles
539 &nsGkAtoms::stop_color, // stop-color
540 &nsGkAtoms::stop_opacity, // stop-opacity
541 // strikethrough-position
542 // strikethrough-thickness
543 &nsGkAtoms::string, // string
544 &nsGkAtoms::stroke, // stroke
545 &nsGkAtoms::stroke_dasharray, // stroke-dasharray
546 &nsGkAtoms::stroke_dashoffset, // stroke-dashoffset
547 &nsGkAtoms::stroke_linecap, // stroke-linecap
548 &nsGkAtoms::stroke_linejoin, // stroke-linejoin
549 &nsGkAtoms::stroke_miterlimit, // stroke-miterlimit
550 &nsGkAtoms::stroke_opacity, // stroke-opacity
551 &nsGkAtoms::stroke_width, // stroke-width
552 &nsGkAtoms::surfaceScale, // surfaceScale
553 &nsGkAtoms::systemLanguage, // systemLanguage
554 &nsGkAtoms::tableValues, // tableValues
555 &nsGkAtoms::target, // target
556 &nsGkAtoms::targetX, // targetX
557 &nsGkAtoms::targetY, // targetY
558 &nsGkAtoms::text_anchor, // text-anchor
559 &nsGkAtoms::text_decoration, // text-decoration
560 // textLength
561 &nsGkAtoms::text_rendering, // text-rendering
562 &nsGkAtoms::title, // title
563 &nsGkAtoms::to, // to
564 &nsGkAtoms::transform, // transform
565 &nsGkAtoms::type, // type
566 // u1
567 // u2
568 // underline-position
569 // underline-thickness
570 // unicode
571 &nsGkAtoms::unicode_bidi, // unicode-bidi
572 // unicode-range
573 // units-per-em
574 // v-alphabetic
575 // v-hanging
576 // v-ideographic
577 // v-mathematical
578 &nsGkAtoms::values, // values
579 &nsGkAtoms::vector_effect, // vector-effect
580 // vert-adv-y
581 // vert-origin-x
582 // vert-origin-y
583 &nsGkAtoms::viewBox, // viewBox
584 &nsGkAtoms::viewTarget, // viewTarget
585 &nsGkAtoms::visibility, // visibility
586 &nsGkAtoms::width, // width
587 // widths
588 &nsGkAtoms::word_spacing, // word-spacing
589 // writing-mode
590 &nsGkAtoms::x, // x
591 // x-height
592 &nsGkAtoms::x1, // x1
593 &nsGkAtoms::x2, // x2
594 &nsGkAtoms::xChannelSelector, // xChannelSelector
595 &nsGkAtoms::y, // y
596 &nsGkAtoms::y1, // y1
597 &nsGkAtoms::y2, // y2
598 &nsGkAtoms::yChannelSelector, // yChannelSelector
599 &nsGkAtoms::z, // z
600 &nsGkAtoms::zoomAndPan, // zoomAndPan
601 nullptr
602 };
604 nsIAtom** const kURLAttributesSVG[] = {
605 nullptr
606 };
608 nsIAtom** const kElementsMathML[] = {
609 &nsGkAtoms::abs_, // abs
610 &nsGkAtoms::_and, // and
611 &nsGkAtoms::annotation_, // annotation
612 &nsGkAtoms::annotation_xml_, // annotation-xml
613 &nsGkAtoms::apply_, // apply
614 &nsGkAtoms::approx_, // approx
615 &nsGkAtoms::arccos_, // arccos
616 &nsGkAtoms::arccosh_, // arccosh
617 &nsGkAtoms::arccot_, // arccot
618 &nsGkAtoms::arccoth_, // arccoth
619 &nsGkAtoms::arccsc_, // arccsc
620 &nsGkAtoms::arccsch_, // arccsch
621 &nsGkAtoms::arcsec_, // arcsec
622 &nsGkAtoms::arcsech_, // arcsech
623 &nsGkAtoms::arcsin_, // arcsin
624 &nsGkAtoms::arcsinh_, // arcsinh
625 &nsGkAtoms::arctan_, // arctan
626 &nsGkAtoms::arctanh_, // arctanh
627 &nsGkAtoms::arg_, // arg
628 &nsGkAtoms::bind_, // bind
629 &nsGkAtoms::bvar_, // bvar
630 &nsGkAtoms::card_, // card
631 &nsGkAtoms::cartesianproduct_, // cartesianproduct
632 &nsGkAtoms::cbytes_, // cbytes
633 &nsGkAtoms::ceiling, // ceiling
634 &nsGkAtoms::cerror_, // cerror
635 &nsGkAtoms::ci_, // ci
636 &nsGkAtoms::cn_, // cn
637 &nsGkAtoms::codomain_, // codomain
638 &nsGkAtoms::complexes_, // complexes
639 &nsGkAtoms::compose_, // compose
640 &nsGkAtoms::condition_, // condition
641 &nsGkAtoms::conjugate_, // conjugate
642 &nsGkAtoms::cos_, // cos
643 &nsGkAtoms::cosh_, // cosh
644 &nsGkAtoms::cot_, // cot
645 &nsGkAtoms::coth_, // coth
646 &nsGkAtoms::cs_, // cs
647 &nsGkAtoms::csc_, // csc
648 &nsGkAtoms::csch_, // csch
649 &nsGkAtoms::csymbol_, // csymbol
650 &nsGkAtoms::curl_, // curl
651 &nsGkAtoms::declare, // declare
652 &nsGkAtoms::degree_, // degree
653 &nsGkAtoms::determinant_, // determinant
654 &nsGkAtoms::diff_, // diff
655 &nsGkAtoms::divergence_, // divergence
656 &nsGkAtoms::divide_, // divide
657 &nsGkAtoms::domain_, // domain
658 &nsGkAtoms::domainofapplication_, // domainofapplication
659 &nsGkAtoms::el_, // el
660 &nsGkAtoms::emptyset_, // emptyset
661 &nsGkAtoms::eq_, // eq
662 &nsGkAtoms::equivalent_, // equivalent
663 &nsGkAtoms::eulergamma_, // eulergamma
664 &nsGkAtoms::exists_, // exists
665 &nsGkAtoms::exp_, // exp
666 &nsGkAtoms::exponentiale_, // exponentiale
667 &nsGkAtoms::factorial_, // factorial
668 &nsGkAtoms::factorof_, // factorof
669 &nsGkAtoms::_false, // false
670 &nsGkAtoms::floor, // floor
671 &nsGkAtoms::fn_, // fn
672 &nsGkAtoms::forall_, // forall
673 &nsGkAtoms::gcd_, // gcd
674 &nsGkAtoms::geq_, // geq
675 &nsGkAtoms::grad, // grad
676 &nsGkAtoms::gt_, // gt
677 &nsGkAtoms::ident_, // ident
678 &nsGkAtoms::image, // image
679 &nsGkAtoms::imaginary_, // imaginary
680 &nsGkAtoms::imaginaryi_, // imaginaryi
681 &nsGkAtoms::implies_, // implies
682 &nsGkAtoms::in, // in
683 &nsGkAtoms::infinity, // infinity
684 &nsGkAtoms::int_, // int
685 &nsGkAtoms::integers_, // integers
686 &nsGkAtoms::intersect_, // intersect
687 &nsGkAtoms::interval_, // interval
688 &nsGkAtoms::inverse_, // inverse
689 &nsGkAtoms::lambda_, // lambda
690 &nsGkAtoms::laplacian_, // laplacian
691 &nsGkAtoms::lcm_, // lcm
692 &nsGkAtoms::leq_, // leq
693 &nsGkAtoms::limit_, // limit
694 &nsGkAtoms::list_, // list
695 &nsGkAtoms::ln_, // ln
696 &nsGkAtoms::log_, // log
697 &nsGkAtoms::logbase_, // logbase
698 &nsGkAtoms::lowlimit_, // lowlimit
699 &nsGkAtoms::lt_, // lt
700 &nsGkAtoms::maction_, // maction
701 &nsGkAtoms::maligngroup_, // maligngroup
702 &nsGkAtoms::malignmark_, // malignmark
703 &nsGkAtoms::math, // math
704 &nsGkAtoms::matrix, // matrix
705 &nsGkAtoms::matrixrow_, // matrixrow
706 &nsGkAtoms::max, // max
707 &nsGkAtoms::mean_, // mean
708 &nsGkAtoms::median_, // median
709 &nsGkAtoms::menclose_, // menclose
710 &nsGkAtoms::merror_, // merror
711 &nsGkAtoms::mfenced_, // mfenced
712 &nsGkAtoms::mfrac_, // mfrac
713 &nsGkAtoms::mglyph_, // mglyph
714 &nsGkAtoms::mi_, // mi
715 &nsGkAtoms::min, // min
716 &nsGkAtoms::minus_, // minus
717 &nsGkAtoms::mlabeledtr_, // mlabeledtr
718 &nsGkAtoms::mlongdiv_, // mlongdiv
719 &nsGkAtoms::mmultiscripts_, // mmultiscripts
720 &nsGkAtoms::mn_, // mn
721 &nsGkAtoms::mo_, // mo
722 &nsGkAtoms::mode, // mode
723 &nsGkAtoms::moment_, // moment
724 &nsGkAtoms::momentabout_, // momentabout
725 &nsGkAtoms::mover_, // mover
726 &nsGkAtoms::mpadded_, // mpadded
727 &nsGkAtoms::mphantom_, // mphantom
728 &nsGkAtoms::mprescripts_, // mprescripts
729 &nsGkAtoms::mroot_, // mroot
730 &nsGkAtoms::mrow_, // mrow
731 &nsGkAtoms::ms_, // ms
732 &nsGkAtoms::mscarries_, // mscarries
733 &nsGkAtoms::mscarry_, // mscarry
734 &nsGkAtoms::msgroup_, // msgroup
735 &nsGkAtoms::msline_, // msline
736 &nsGkAtoms::mspace_, // mspace
737 &nsGkAtoms::msqrt_, // msqrt
738 &nsGkAtoms::msrow_, // msrow
739 &nsGkAtoms::mstack_, // mstack
740 &nsGkAtoms::mstyle_, // mstyle
741 &nsGkAtoms::msub_, // msub
742 &nsGkAtoms::msubsup_, // msubsup
743 &nsGkAtoms::msup_, // msup
744 &nsGkAtoms::mtable_, // mtable
745 &nsGkAtoms::mtd_, // mtd
746 &nsGkAtoms::mtext_, // mtext
747 &nsGkAtoms::mtr_, // mtr
748 &nsGkAtoms::munder_, // munder
749 &nsGkAtoms::munderover_, // munderover
750 &nsGkAtoms::naturalnumbers_, // naturalnumbers
751 &nsGkAtoms::neq_, // neq
752 &nsGkAtoms::none, // none
753 &nsGkAtoms::_not, // not
754 &nsGkAtoms::notanumber_, // notanumber
755 &nsGkAtoms::note_, // note
756 &nsGkAtoms::notin_, // notin
757 &nsGkAtoms::notprsubset_, // notprsubset
758 &nsGkAtoms::notsubset_, // notsubset
759 &nsGkAtoms::_or, // or
760 &nsGkAtoms::otherwise, // otherwise
761 &nsGkAtoms::outerproduct_, // outerproduct
762 &nsGkAtoms::partialdiff_, // partialdiff
763 &nsGkAtoms::pi_, // pi
764 &nsGkAtoms::piece_, // piece
765 &nsGkAtoms::piecewise_, // piecewise
766 &nsGkAtoms::plus_, // plus
767 &nsGkAtoms::power_, // power
768 &nsGkAtoms::primes_, // primes
769 &nsGkAtoms::product_, // product
770 &nsGkAtoms::prsubset_, // prsubset
771 &nsGkAtoms::quotient_, // quotient
772 &nsGkAtoms::rationals_, // rationals
773 &nsGkAtoms::real_, // real
774 &nsGkAtoms::reals_, // reals
775 &nsGkAtoms::reln_, // reln
776 &nsGkAtoms::rem, // rem
777 &nsGkAtoms::root_, // root
778 &nsGkAtoms::scalarproduct_, // scalarproduct
779 &nsGkAtoms::sdev_, // sdev
780 &nsGkAtoms::sec_, // sec
781 &nsGkAtoms::sech_, // sech
782 &nsGkAtoms::selector_, // selector
783 &nsGkAtoms::semantics_, // semantics
784 &nsGkAtoms::sep_, // sep
785 &nsGkAtoms::set_, // set
786 &nsGkAtoms::setdiff_, // setdiff
787 &nsGkAtoms::share_, // share
788 &nsGkAtoms::sin_, // sin
789 &nsGkAtoms::sinh_, // sinh
790 &nsGkAtoms::subset_, // subset
791 &nsGkAtoms::sum, // sum
792 &nsGkAtoms::tan_, // tan
793 &nsGkAtoms::tanh_, // tanh
794 &nsGkAtoms::tendsto_, // tendsto
795 &nsGkAtoms::times_, // times
796 &nsGkAtoms::transpose_, // transpose
797 &nsGkAtoms::_true, // true
798 &nsGkAtoms::union_, // union
799 &nsGkAtoms::uplimit_, // uplimit
800 &nsGkAtoms::variance_, // variance
801 &nsGkAtoms::vector_, // vector
802 &nsGkAtoms::vectorproduct_, // vectorproduct
803 &nsGkAtoms::xor_, // xor
804 nullptr
805 };
807 nsIAtom** const kAttributesMathML[] = {
808 &nsGkAtoms::accent_, // accent
809 &nsGkAtoms::accentunder_, // accentunder
810 &nsGkAtoms::actiontype_, // actiontype
811 &nsGkAtoms::align, // align
812 &nsGkAtoms::alignmentscope_, // alignmentscope
813 &nsGkAtoms::alt, // alt
814 &nsGkAtoms::altimg_, // altimg
815 &nsGkAtoms::altimg_height_, // altimg-height
816 &nsGkAtoms::altimg_valign_, // altimg-valign
817 &nsGkAtoms::altimg_width_, // altimg-width
818 &nsGkAtoms::background, // background
819 &nsGkAtoms::base, // base
820 &nsGkAtoms::bevelled_, // bevelled
821 &nsGkAtoms::cd_, // cd
822 &nsGkAtoms::cdgroup_, // cdgroup
823 &nsGkAtoms::charalign_, // charalign
824 &nsGkAtoms::close, // close
825 &nsGkAtoms::closure_, // closure
826 &nsGkAtoms::color, // color
827 &nsGkAtoms::columnalign_, // columnalign
828 &nsGkAtoms::columnalignment_, // columnalignment
829 &nsGkAtoms::columnlines_, // columnlines
830 &nsGkAtoms::columnspacing_, // columnspacing
831 &nsGkAtoms::columnspan_, // columnspan
832 &nsGkAtoms::columnwidth_, // columnwidth
833 &nsGkAtoms::crossout_, // crossout
834 &nsGkAtoms::decimalpoint_, // decimalpoint
835 &nsGkAtoms::definitionURL_, // definitionURL
836 &nsGkAtoms::denomalign_, // denomalign
837 &nsGkAtoms::depth_, // depth
838 &nsGkAtoms::dir, // dir
839 &nsGkAtoms::display, // display
840 &nsGkAtoms::displaystyle_, // displaystyle
841 &nsGkAtoms::edge_, // edge
842 &nsGkAtoms::encoding, // encoding
843 &nsGkAtoms::equalcolumns_, // equalcolumns
844 &nsGkAtoms::equalrows_, // equalrows
845 &nsGkAtoms::fence_, // fence
846 &nsGkAtoms::fontfamily_, // fontfamily
847 &nsGkAtoms::fontsize_, // fontsize
848 &nsGkAtoms::fontstyle_, // fontstyle
849 &nsGkAtoms::fontweight_, // fontweight
850 &nsGkAtoms::form, // form
851 &nsGkAtoms::frame, // frame
852 &nsGkAtoms::framespacing_, // framespacing
853 &nsGkAtoms::groupalign_, // groupalign
854 &nsGkAtoms::height, // height
855 &nsGkAtoms::href, // href
856 &nsGkAtoms::id, // id
857 &nsGkAtoms::indentalign_, // indentalign
858 &nsGkAtoms::indentalignfirst_, // indentalignfirst
859 &nsGkAtoms::indentalignlast_, // indentalignlast
860 &nsGkAtoms::indentshift_, // indentshift
861 &nsGkAtoms::indentshiftfirst_, // indentshiftfirst
862 &nsGkAtoms::indenttarget_, // indenttarget
863 &nsGkAtoms::index, // index
864 &nsGkAtoms::integer, // integer
865 &nsGkAtoms::largeop_, // largeop
866 &nsGkAtoms::length, // length
867 &nsGkAtoms::linebreak_, // linebreak
868 &nsGkAtoms::linebreakmultchar_, // linebreakmultchar
869 &nsGkAtoms::linebreakstyle_, // linebreakstyle
870 &nsGkAtoms::linethickness_, // linethickness
871 &nsGkAtoms::location_, // location
872 &nsGkAtoms::longdivstyle_, // longdivstyle
873 &nsGkAtoms::lquote_, // lquote
874 &nsGkAtoms::lspace_, // lspace
875 &nsGkAtoms::ltr, // ltr
876 &nsGkAtoms::mathbackground_, // mathbackground
877 &nsGkAtoms::mathcolor_, // mathcolor
878 &nsGkAtoms::mathsize_, // mathsize
879 &nsGkAtoms::mathvariant_, // mathvariant
880 &nsGkAtoms::maxsize_, // maxsize
881 &nsGkAtoms::minlabelspacing_, // minlabelspacing
882 &nsGkAtoms::minsize_, // minsize
883 &nsGkAtoms::movablelimits_, // movablelimits
884 &nsGkAtoms::msgroup_, // msgroup
885 &nsGkAtoms::name, // name
886 &nsGkAtoms::newline, // newline
887 &nsGkAtoms::notation_, // notation
888 &nsGkAtoms::numalign_, // numalign
889 &nsGkAtoms::number, // number
890 &nsGkAtoms::open, // open
891 &nsGkAtoms::order, // order
892 &nsGkAtoms::other_, // other
893 &nsGkAtoms::overflow, // overflow
894 &nsGkAtoms::position, // position
895 &nsGkAtoms::role, // role
896 &nsGkAtoms::rowalign_, // rowalign
897 &nsGkAtoms::rowlines_, // rowlines
898 &nsGkAtoms::rowspacing_, // rowspacing
899 &nsGkAtoms::rowspan, // rowspan
900 &nsGkAtoms::rquote_, // rquote
901 &nsGkAtoms::rspace_, // rspace
902 &nsGkAtoms::schemaLocation_, // schemaLocation
903 &nsGkAtoms::scriptlevel_, // scriptlevel
904 &nsGkAtoms::scriptminsize_, // scriptminsize
905 &nsGkAtoms::scriptsize_, // scriptsize
906 &nsGkAtoms::scriptsizemultiplier_, // scriptsizemultiplier
907 &nsGkAtoms::selection_, // selection
908 &nsGkAtoms::separator_, // separator
909 &nsGkAtoms::separators_, // separators
910 &nsGkAtoms::shift_, // shift
911 &nsGkAtoms::side_, // side
912 &nsGkAtoms::src, // src
913 &nsGkAtoms::stackalign_, // stackalign
914 &nsGkAtoms::stretchy_, // stretchy
915 &nsGkAtoms::subscriptshift_, // subscriptshift
916 &nsGkAtoms::superscriptshift_, // superscriptshift
917 &nsGkAtoms::symmetric_, // symmetric
918 &nsGkAtoms::type, // type
919 &nsGkAtoms::voffset_, // voffset
920 &nsGkAtoms::width, // width
921 &nsGkAtoms::xref_, // xref
922 nullptr
923 };
925 nsIAtom** const kURLAttributesMathML[] = {
926 &nsGkAtoms::href,
927 &nsGkAtoms::src,
928 &nsGkAtoms::cdgroup_,
929 &nsGkAtoms::altimg_,
930 &nsGkAtoms::definitionURL_,
931 nullptr
932 };
934 nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsHTML = nullptr;
935 nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesHTML = nullptr;
936 nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sPresAttributesHTML = nullptr;
937 nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsSVG = nullptr;
938 nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesSVG = nullptr;
939 nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsMathML = nullptr;
940 nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesMathML = nullptr;
941 nsIPrincipal* nsTreeSanitizer::sNullPrincipal = nullptr;
943 nsTreeSanitizer::nsTreeSanitizer(uint32_t aFlags)
944 : mAllowStyles(aFlags & nsIParserUtils::SanitizerAllowStyle)
945 , mAllowComments(aFlags & nsIParserUtils::SanitizerAllowComments)
946 , mDropNonCSSPresentation(aFlags &
947 nsIParserUtils::SanitizerDropNonCSSPresentation)
948 , mDropForms(aFlags & nsIParserUtils::SanitizerDropForms)
949 , mCidEmbedsOnly(aFlags &
950 nsIParserUtils::SanitizerCidEmbedsOnly)
951 , mDropMedia(aFlags & nsIParserUtils::SanitizerDropMedia)
952 , mFullDocument(false)
953 {
954 if (mCidEmbedsOnly) {
955 // Sanitizing styles for external references is not supported.
956 mAllowStyles = false;
957 }
958 if (!sElementsHTML) {
959 // Initialize lazily to avoid having to initialize at all if the user
960 // doesn't paste HTML or load feeds.
961 InitializeStatics();
962 }
963 }
965 bool
966 nsTreeSanitizer::MustFlatten(int32_t aNamespace, nsIAtom* aLocal)
967 {
968 if (aNamespace == kNameSpaceID_XHTML) {
969 if (mDropNonCSSPresentation && (nsGkAtoms::font == aLocal ||
970 nsGkAtoms::center == aLocal)) {
971 return true;
972 }
973 if (mDropForms && (nsGkAtoms::form == aLocal ||
974 nsGkAtoms::input == aLocal ||
975 nsGkAtoms::keygen == aLocal ||
976 nsGkAtoms::option == aLocal ||
977 nsGkAtoms::optgroup == aLocal)) {
978 return true;
979 }
980 if (mFullDocument && (nsGkAtoms::title == aLocal ||
981 nsGkAtoms::html == aLocal ||
982 nsGkAtoms::head == aLocal ||
983 nsGkAtoms::body == aLocal)) {
984 return false;
985 }
986 return !sElementsHTML->GetEntry(aLocal);
987 }
988 if (aNamespace == kNameSpaceID_SVG) {
989 if (mCidEmbedsOnly || mDropMedia) {
990 // Sanitizing CSS-based URL references inside SVG presentational
991 // attributes is not supported, so flattening for cid: embed case.
992 return true;
993 }
994 return !sElementsSVG->GetEntry(aLocal);
995 }
996 if (aNamespace == kNameSpaceID_MathML) {
997 return !sElementsMathML->GetEntry(aLocal);
998 }
999 return true;
1000 }
1002 bool
1003 nsTreeSanitizer::IsURL(nsIAtom*** aURLs, nsIAtom* aLocalName)
1004 {
1005 nsIAtom** atomPtrPtr;
1006 while ((atomPtrPtr = *aURLs)) {
1007 if (*atomPtrPtr == aLocalName) {
1008 return true;
1009 }
1010 ++aURLs;
1011 }
1012 return false;
1013 }
1015 bool
1016 nsTreeSanitizer::MustPrune(int32_t aNamespace,
1017 nsIAtom* aLocal,
1018 mozilla::dom::Element* aElement)
1019 {
1020 // To avoid attacks where a MathML script becomes something that gets
1021 // serialized in a way that it parses back as an HTML script, let's just
1022 // drop elements with the local name 'script' regardless of namespace.
1023 if (nsGkAtoms::script == aLocal) {
1024 return true;
1025 }
1026 if (aNamespace == kNameSpaceID_XHTML) {
1027 if (nsGkAtoms::title == aLocal && !mFullDocument) {
1028 // emulate the quirks of the old parser
1029 return true;
1030 }
1031 if (mDropForms && (nsGkAtoms::select == aLocal ||
1032 nsGkAtoms::button == aLocal ||
1033 nsGkAtoms::datalist == aLocal)) {
1034 return true;
1035 }
1036 if (mDropMedia && (nsGkAtoms::img == aLocal ||
1037 nsGkAtoms::video == aLocal ||
1038 nsGkAtoms::audio == aLocal ||
1039 nsGkAtoms::source == aLocal)) {
1040 return true;
1041 }
1042 if (nsGkAtoms::meta == aLocal &&
1043 (aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::charset) ||
1044 aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::httpEquiv))) {
1045 // Throw away charset declarations even if they also have microdata
1046 // which they can't validly have.
1047 return true;
1048 }
1049 if (((!mFullDocument && nsGkAtoms::meta == aLocal) ||
1050 nsGkAtoms::link == aLocal) &&
1051 !(aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) ||
1052 aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope))) {
1053 // emulate old behavior for non-Microdata <meta> and <link> presumably
1054 // in <head>. <meta> and <link> are whitelisted in order to avoid
1055 // corrupting Microdata when they appear in <body>. Note that
1056 // SanitizeAttributes() will remove the rel attribute from <link> and
1057 // the name attribute from <meta>.
1058 return true;
1059 }
1060 }
1061 if (mAllowStyles) {
1062 if (nsGkAtoms::style == aLocal && !(aNamespace == kNameSpaceID_XHTML
1063 || aNamespace == kNameSpaceID_SVG)) {
1064 return true;
1065 }
1066 return false;
1067 }
1068 if (nsGkAtoms::style == aLocal) {
1069 return true;
1070 }
1071 return false;
1072 }
1074 bool
1075 nsTreeSanitizer::SanitizeStyleRule(mozilla::css::StyleRule *aRule,
1076 nsAutoString &aRuleText)
1077 {
1078 bool didSanitize = false;
1079 aRuleText.Truncate();
1080 mozilla::css::Declaration* style = aRule->GetDeclaration();
1081 if (style) {
1082 didSanitize = style->HasProperty(eCSSProperty_binding);
1083 style->RemoveProperty(eCSSProperty_binding);
1084 style->ToString(aRuleText);
1085 }
1086 return didSanitize;
1087 }
1089 bool
1090 nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
1091 nsAString& aSanitized,
1092 nsIDocument* aDocument,
1093 nsIURI* aBaseURI)
1094 {
1095 nsresult rv;
1096 aSanitized.Truncate();
1097 // aSanitized will hold the permitted CSS text.
1098 // -moz-binding is blacklisted.
1099 bool didSanitize = false;
1100 // Create a sheet to hold the parsed CSS
1101 nsRefPtr<nsCSSStyleSheet> sheet = new nsCSSStyleSheet(CORS_NONE);
1102 sheet->SetURIs(aDocument->GetDocumentURI(), nullptr, aBaseURI);
1103 sheet->SetPrincipal(aDocument->NodePrincipal());
1104 // Create the CSS parser, and parse the CSS text.
1105 nsCSSParser parser(nullptr, sheet);
1106 rv = parser.ParseSheet(aOriginal, aDocument->GetDocumentURI(), aBaseURI,
1107 aDocument->NodePrincipal(), 0, false);
1108 NS_ENSURE_SUCCESS(rv, true);
1109 // Mark the sheet as complete.
1110 NS_ABORT_IF_FALSE(!sheet->IsModified(),
1111 "should not get marked modified during parsing");
1112 sheet->SetComplete();
1113 // Loop through all the rules found in the CSS text
1114 int32_t ruleCount = sheet->StyleRuleCount();
1115 for (int32_t i = 0; i < ruleCount; ++i) {
1116 mozilla::css::Rule* rule = sheet->GetStyleRuleAt(i);
1117 if (!rule)
1118 continue;
1119 switch (rule->GetType()) {
1120 default:
1121 didSanitize = true;
1122 // Ignore these rule types.
1123 break;
1124 case mozilla::css::Rule::NAMESPACE_RULE:
1125 case mozilla::css::Rule::FONT_FACE_RULE: {
1126 // Append @namespace and @font-face rules verbatim.
1127 nsAutoString cssText;
1128 nsCOMPtr<nsIDOMCSSRule> styleRule = do_QueryInterface(rule);
1129 if (styleRule) {
1130 rv = styleRule->GetCssText(cssText);
1131 if (NS_SUCCEEDED(rv)) {
1132 aSanitized.Append(cssText);
1133 }
1134 }
1135 break;
1136 }
1137 case mozilla::css::Rule::STYLE_RULE: {
1138 // For style rules, we will just look for and remove the
1139 // -moz-binding properties.
1140 nsRefPtr<mozilla::css::StyleRule> styleRule = do_QueryObject(rule);
1141 NS_ASSERTION(styleRule, "Must be a style rule");
1142 nsAutoString decl;
1143 bool sanitized = SanitizeStyleRule(styleRule, decl);
1144 didSanitize = sanitized || didSanitize;
1145 if (!sanitized) {
1146 styleRule->GetCssText(decl);
1147 }
1148 aSanitized.Append(decl);
1149 }
1150 }
1151 }
1152 return didSanitize;
1153 }
1155 void
1156 nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
1157 nsTHashtable<nsISupportsHashKey>* aAllowed,
1158 nsIAtom*** aURLs,
1159 bool aAllowXLink,
1160 bool aAllowStyle,
1161 bool aAllowDangerousSrc)
1162 {
1163 uint32_t ac = aElement->GetAttrCount();
1165 nsresult rv;
1167 for (int32_t i = ac - 1; i >= 0; --i) {
1168 rv = NS_OK;
1169 const nsAttrName* attrName = aElement->GetAttrNameAt(i);
1170 int32_t attrNs = attrName->NamespaceID();
1171 nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
1173 if (kNameSpaceID_None == attrNs) {
1174 if (aAllowStyle && nsGkAtoms::style == attrLocal) {
1175 nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
1176 nsIDocument* document = aElement->OwnerDoc();
1177 // Pass the CSS Loader object to the parser, to allow parser error
1178 // reports to include the outer window ID.
1179 nsCSSParser parser(document->CSSLoader());
1180 nsRefPtr<mozilla::css::StyleRule> rule;
1181 nsAutoString value;
1182 aElement->GetAttr(attrNs, attrLocal, value);
1183 rv = parser.ParseStyleAttribute(value,
1184 document->GetDocumentURI(),
1185 baseURI,
1186 document->NodePrincipal(),
1187 getter_AddRefs(rule));
1188 if (NS_SUCCEEDED(rv)) {
1189 nsAutoString cleanValue;
1190 if (SanitizeStyleRule(rule, cleanValue)) {
1191 aElement->SetAttr(kNameSpaceID_None,
1192 nsGkAtoms::style,
1193 cleanValue,
1194 false);
1195 }
1196 }
1197 continue;
1198 }
1199 if (aAllowDangerousSrc && nsGkAtoms::src == attrLocal) {
1200 continue;
1201 }
1202 if (IsURL(aURLs, attrLocal)) {
1203 if (SanitizeURL(aElement, attrNs, attrLocal)) {
1204 // in case the attribute removal shuffled the attribute order, start
1205 // the loop again.
1206 --ac;
1207 i = ac; // i will be decremented immediately thanks to the for loop
1208 continue;
1209 }
1210 // else fall through to see if there's another reason to drop this
1211 // attribute (in particular if the attribute is background="" on an
1212 // HTML element)
1213 }
1214 if (!mDropNonCSSPresentation &&
1215 (aAllowed == sAttributesHTML) && // element is HTML
1216 sPresAttributesHTML->GetEntry(attrLocal)) {
1217 continue;
1218 }
1219 if (aAllowed->GetEntry(attrLocal) &&
1220 !((attrLocal == nsGkAtoms::rel &&
1221 aElement->IsHTML(nsGkAtoms::link)) ||
1222 (!mFullDocument &&
1223 attrLocal == nsGkAtoms::name &&
1224 aElement->IsHTML(nsGkAtoms::meta)))) {
1225 // name="" and rel="" are whitelisted, but treat them as blacklisted
1226 // for <meta name> (fragment case) and <link rel> (all cases) to avoid
1227 // document-wide metadata or styling overrides with non-conforming
1228 // <meta name itemprop> or
1229 // <link rel itemprop>
1230 continue;
1231 }
1232 const char16_t* localStr = attrLocal->GetUTF16String();
1233 // Allow underscore to cater to the MCE editor library.
1234 // Allow data-* on SVG and MathML, too, as a forward-compat measure.
1235 if (*localStr == '_' || (attrLocal->GetLength() > 5 && localStr[0] == 'd'
1236 && localStr[1] == 'a' && localStr[2] == 't' && localStr[3] == 'a'
1237 && localStr[4] == '-')) {
1238 continue;
1239 }
1240 // else not allowed
1241 } else if (kNameSpaceID_XML == attrNs) {
1242 if (nsGkAtoms::base == attrLocal) {
1243 if (SanitizeURL(aElement, attrNs, attrLocal)) {
1244 // in case the attribute removal shuffled the attribute order, start
1245 // the loop again.
1246 --ac;
1247 i = ac; // i will be decremented immediately thanks to the for loop
1248 }
1249 continue;
1250 }
1251 if (nsGkAtoms::lang == attrLocal || nsGkAtoms::space == attrLocal) {
1252 continue;
1253 }
1254 // else not allowed
1255 } else if (aAllowXLink && kNameSpaceID_XLink == attrNs) {
1256 if (nsGkAtoms::href == attrLocal) {
1257 if (SanitizeURL(aElement, attrNs, attrLocal)) {
1258 // in case the attribute removal shuffled the attribute order, start
1259 // the loop again.
1260 --ac;
1261 i = ac; // i will be decremented immediately thanks to the for loop
1262 }
1263 continue;
1264 }
1265 if (nsGkAtoms::type == attrLocal || nsGkAtoms::title == attrLocal
1266 || nsGkAtoms::show == attrLocal || nsGkAtoms::actuate == attrLocal) {
1267 continue;
1268 }
1269 // else not allowed
1270 }
1271 aElement->UnsetAttr(kNameSpaceID_None, attrLocal, false);
1272 // in case the attribute removal shuffled the attribute order, start the
1273 // loop again.
1274 --ac;
1275 i = ac; // i will be decremented immediately thanks to the for loop
1276 }
1278 // If we've got HTML audio or video, add the controls attribute, because
1279 // otherwise the content is unplayable with scripts removed.
1280 if (aElement->IsHTML(nsGkAtoms::video) ||
1281 aElement->IsHTML(nsGkAtoms::audio)) {
1282 aElement->SetAttr(kNameSpaceID_None,
1283 nsGkAtoms::controls,
1284 EmptyString(),
1285 false);
1286 }
1287 }
1289 bool
1290 nsTreeSanitizer::SanitizeURL(mozilla::dom::Element* aElement,
1291 int32_t aNamespace,
1292 nsIAtom* aLocalName)
1293 {
1294 nsAutoString value;
1295 aElement->GetAttr(aNamespace, aLocalName, value);
1297 // Get value and remove mandatory quotes
1298 static const char* kWhitespace = "\n\r\t\b";
1299 const nsAString& v =
1300 nsContentUtils::TrimCharsInSet(kWhitespace, value);
1302 nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
1303 uint32_t flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL;
1305 nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
1306 nsCOMPtr<nsIURI> attrURI;
1307 nsresult rv = NS_NewURI(getter_AddRefs(attrURI), v, nullptr, baseURI);
1308 if (NS_SUCCEEDED(rv)) {
1309 if (mCidEmbedsOnly &&
1310 kNameSpaceID_None == aNamespace) {
1311 if (nsGkAtoms::src == aLocalName || nsGkAtoms::background == aLocalName) {
1312 // comm-central uses a hack that makes nsIURIs created with cid: specs
1313 // actually have an about:blank spec. Therefore, nsIURI facilities are
1314 // useless for cid: when comm-central code is participating.
1315 if (!(v.Length() > 4 &&
1316 (v[0] == 'c' || v[0] == 'C') &&
1317 (v[1] == 'i' || v[1] == 'I') &&
1318 (v[2] == 'd' || v[2] == 'D') &&
1319 v[3] == ':')) {
1320 rv = NS_ERROR_FAILURE;
1321 }
1322 } else if (nsGkAtoms::cdgroup_ == aLocalName ||
1323 nsGkAtoms::altimg_ == aLocalName ||
1324 nsGkAtoms::definitionURL_ == aLocalName) {
1325 // Gecko doesn't fetch these now and shouldn't in the future, but
1326 // in case someone goofs with these in the future, let's drop them.
1327 rv = NS_ERROR_FAILURE;
1328 } else {
1329 rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
1330 }
1331 } else {
1332 rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
1333 }
1334 }
1335 if (NS_FAILED(rv)) {
1336 aElement->UnsetAttr(aNamespace, aLocalName, false);
1337 return true;
1338 }
1339 return false;
1340 }
1342 void
1343 nsTreeSanitizer::Sanitize(nsIContent* aFragment)
1344 {
1345 // If you want to relax these preconditions, be sure to check the code in
1346 // here that notifies / does not notify or that fires mutation events if
1347 // in tree.
1348 NS_PRECONDITION(aFragment->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT),
1349 "Argument was not DOM fragment.");
1350 NS_PRECONDITION(!aFragment->IsInDoc(), "The fragment is in doc?");
1352 mFullDocument = false;
1353 SanitizeChildren(aFragment);
1354 }
1356 void
1357 nsTreeSanitizer::Sanitize(nsIDocument* aDocument)
1358 {
1359 // If you want to relax these preconditions, be sure to check the code in
1360 // here that notifies / does not notify or that fires mutation events if
1361 // in tree.
1362 #ifdef DEBUG
1363 NS_PRECONDITION(!aDocument->GetContainer(), "The document is in a shell.");
1364 nsRefPtr<mozilla::dom::Element> root = aDocument->GetRootElement();
1365 NS_PRECONDITION(root->IsHTML(nsGkAtoms::html), "Not HTML root.");
1366 #endif
1368 mFullDocument = true;
1369 SanitizeChildren(aDocument);
1370 }
1372 void
1373 nsTreeSanitizer::SanitizeChildren(nsINode* aRoot)
1374 {
1375 nsIContent* node = aRoot->GetFirstChild();
1376 while (node) {
1377 if (node->IsElement()) {
1378 mozilla::dom::Element* elt = node->AsElement();
1379 nsINodeInfo* nodeInfo = node->NodeInfo();
1380 nsIAtom* localName = nodeInfo->NameAtom();
1381 int32_t ns = nodeInfo->NamespaceID();
1383 if (MustPrune(ns, localName, elt)) {
1384 RemoveAllAttributes(node);
1385 nsIContent* descendant = node;
1386 while ((descendant = descendant->GetNextNode(node))) {
1387 RemoveAllAttributes(descendant);
1388 }
1389 nsIContent* next = node->GetNextNonChildNode(aRoot);
1390 node->RemoveFromParent();
1391 node = next;
1392 continue;
1393 }
1394 if (nsGkAtoms::style == localName) {
1395 // If styles aren't allowed, style elements got pruned above. Even
1396 // if styles are allowed, non-HTML, non-SVG style elements got pruned
1397 // above.
1398 NS_ASSERTION(ns == kNameSpaceID_XHTML || ns == kNameSpaceID_SVG,
1399 "Should have only HTML or SVG here!");
1400 nsAutoString styleText;
1401 if (!nsContentUtils::GetNodeTextContent(node, false, styleText)) {
1402 NS_RUNTIMEABORT("OOM");
1403 }
1404 nsAutoString sanitizedStyle;
1405 nsCOMPtr<nsIURI> baseURI = node->GetBaseURI();
1406 if (SanitizeStyleSheet(styleText,
1407 sanitizedStyle,
1408 aRoot->OwnerDoc(),
1409 baseURI)) {
1410 nsContentUtils::SetNodeTextContent(node, sanitizedStyle, true);
1411 } else {
1412 // If the node had non-text child nodes, this operation zaps those.
1413 nsContentUtils::SetNodeTextContent(node, styleText, true);
1414 }
1415 if (ns == kNameSpaceID_XHTML) {
1416 SanitizeAttributes(elt,
1417 sAttributesHTML,
1418 (nsIAtom***)kURLAttributesHTML,
1419 false,
1420 mAllowStyles,
1421 false);
1422 } else {
1423 SanitizeAttributes(elt,
1424 sAttributesSVG,
1425 (nsIAtom***)kURLAttributesSVG,
1426 true,
1427 mAllowStyles,
1428 false);
1429 }
1430 node = node->GetNextNonChildNode(aRoot);
1431 continue;
1432 }
1433 if (MustFlatten(ns, localName)) {
1434 RemoveAllAttributes(node);
1435 nsIContent* next = node->GetNextNode(aRoot);
1436 nsIContent* parent = node->GetParent();
1437 nsCOMPtr<nsIContent> child; // Must keep the child alive during move
1438 ErrorResult rv;
1439 while ((child = node->GetFirstChild())) {
1440 parent->InsertBefore(*child, node, rv);
1441 if (rv.Failed()) {
1442 break;
1443 }
1444 }
1445 node->RemoveFromParent();
1446 node = next;
1447 continue;
1448 }
1449 NS_ASSERTION(ns == kNameSpaceID_XHTML ||
1450 ns == kNameSpaceID_SVG ||
1451 ns == kNameSpaceID_MathML,
1452 "Should have only HTML, MathML or SVG here!");
1453 if (ns == kNameSpaceID_XHTML) {
1454 SanitizeAttributes(elt,
1455 sAttributesHTML,
1456 (nsIAtom***)kURLAttributesHTML,
1457 false, mAllowStyles,
1458 (nsGkAtoms::img == localName) &&
1459 !mCidEmbedsOnly);
1460 } else if (ns == kNameSpaceID_SVG) {
1461 SanitizeAttributes(elt,
1462 sAttributesSVG,
1463 (nsIAtom***)kURLAttributesSVG,
1464 true,
1465 mAllowStyles,
1466 false);
1467 } else {
1468 SanitizeAttributes(elt,
1469 sAttributesMathML,
1470 (nsIAtom***)kURLAttributesMathML,
1471 true,
1472 false,
1473 false);
1474 }
1475 node = node->GetNextNode(aRoot);
1476 continue;
1477 }
1478 NS_ASSERTION(!node->GetFirstChild(), "How come non-element node had kids?");
1479 nsIContent* next = node->GetNextNonChildNode(aRoot);
1480 if (!mAllowComments && node->IsNodeOfType(nsINode::eCOMMENT)) {
1481 node->RemoveFromParent();
1482 }
1483 node = next;
1484 }
1485 }
1487 void
1488 nsTreeSanitizer::RemoveAllAttributes(nsIContent* aElement)
1489 {
1490 const nsAttrName* attrName;
1491 while ((attrName = aElement->GetAttrNameAt(0))) {
1492 int32_t attrNs = attrName->NamespaceID();
1493 nsCOMPtr<nsIAtom> attrLocal = attrName->LocalName();
1494 aElement->UnsetAttr(attrNs, attrLocal, false);
1495 }
1496 }
1498 void
1499 nsTreeSanitizer::InitializeStatics()
1500 {
1501 NS_PRECONDITION(!sElementsHTML, "Initializing a second time.");
1503 sElementsHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsHTML));
1504 for (uint32_t i = 0; kElementsHTML[i]; i++) {
1505 sElementsHTML->PutEntry(*kElementsHTML[i]);
1506 }
1508 sAttributesHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesHTML));
1509 for (uint32_t i = 0; kAttributesHTML[i]; i++) {
1510 sAttributesHTML->PutEntry(*kAttributesHTML[i]);
1511 }
1513 sPresAttributesHTML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kPresAttributesHTML));
1514 for (uint32_t i = 0; kPresAttributesHTML[i]; i++) {
1515 sPresAttributesHTML->PutEntry(*kPresAttributesHTML[i]);
1516 }
1518 sElementsSVG = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsSVG));
1519 for (uint32_t i = 0; kElementsSVG[i]; i++) {
1520 sElementsSVG->PutEntry(*kElementsSVG[i]);
1521 }
1523 sAttributesSVG = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesSVG));
1524 for (uint32_t i = 0; kAttributesSVG[i]; i++) {
1525 sAttributesSVG->PutEntry(*kAttributesSVG[i]);
1526 }
1528 sElementsMathML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kElementsMathML));
1529 for (uint32_t i = 0; kElementsMathML[i]; i++) {
1530 sElementsMathML->PutEntry(*kElementsMathML[i]);
1531 }
1533 sAttributesMathML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesMathML));
1534 for (uint32_t i = 0; kAttributesMathML[i]; i++) {
1535 sAttributesMathML->PutEntry(*kAttributesMathML[i]);
1536 }
1538 nsCOMPtr<nsIPrincipal> principal =
1539 do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID);
1540 principal.forget(&sNullPrincipal);
1541 }
1543 void
1544 nsTreeSanitizer::ReleaseStatics()
1545 {
1546 delete sElementsHTML;
1547 sElementsHTML = nullptr;
1549 delete sAttributesHTML;
1550 sAttributesHTML = nullptr;
1552 delete sPresAttributesHTML;
1553 sPresAttributesHTML = nullptr;
1555 delete sElementsSVG;
1556 sElementsSVG = nullptr;
1558 delete sAttributesSVG;
1559 sAttributesSVG = nullptr;
1561 delete sElementsMathML;
1562 sElementsMathML = nullptr;
1564 delete sAttributesMathML;
1565 sAttributesMathML = nullptr;
1567 NS_IF_RELEASE(sNullPrincipal);
1568 }