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