@oat-sa/tao-core-ui 3.24.0 → 3.24.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animable/pulsable/pulsable.js +0 -1
- package/dist/autocomplete/css/autocomplete.css +1 -1
- package/dist/autocomplete/css/autocomplete.css.map +1 -1
- package/dist/badge/css/badge.css +6 -6
- package/dist/badge/css/badge.css.map +1 -1
- package/dist/breadcrumbs/css/breadcrumbs.css +2 -2
- package/dist/breadcrumbs/css/breadcrumbs.css.map +1 -1
- package/dist/calculator/css/calculator.css +8 -6
- package/dist/calculator/css/calculator.css.map +1 -1
- package/dist/class/css/selector.css +4 -4
- package/dist/class/css/selector.css.map +1 -1
- package/dist/component/css/components.css +5 -5
- package/dist/component/css/components.css.map +1 -1
- package/dist/component/css/windowComponent.css +1 -1
- package/dist/component/css/windowComponent.css.map +1 -1
- package/dist/component/draggable.js +0 -1
- package/dist/component/resizable.js +0 -1
- package/dist/contextualPopup/css/contextualPopup.css +1 -1
- package/dist/contextualPopup/css/contextualPopup.css.map +1 -1
- package/dist/datatable/css/datatable.css +3 -3
- package/dist/datatable/css/datatable.css.map +1 -1
- package/dist/datatable.js +1 -2
- package/dist/datetime/css/picker.css +13 -13
- package/dist/datetime/css/picker.css.map +1 -1
- package/dist/documentViewer/css/documentViewer.css +10 -10
- package/dist/documentViewer/css/documentViewer.css.map +1 -1
- package/dist/documentViewer/providers/pdfViewer/pdfjs/searchEngine.js +0 -1
- package/dist/dynamicComponent/css/dynamicComponent.css +1 -1
- package/dist/dynamicComponent/css/dynamicComponent.css.map +1 -1
- package/dist/dynamicComponent.js +1 -4
- package/dist/figure/FigureStateActive.js +20 -23
- package/dist/form/css/dropdownForm.css +1 -1
- package/dist/form/css/dropdownForm.css.map +1 -1
- package/dist/form/widget/widget.js +1 -4
- package/dist/highlighter.js +0 -2
- package/dist/image/ImgStateActive.js +13 -15
- package/dist/interactUtils.js +7 -8
- package/dist/itemButtonList/css/item-button-list.css +9 -3
- package/dist/itemButtonList/css/item-button-list.css.map +1 -1
- package/dist/itemButtonList.js +1 -2
- package/dist/keyNavigation/navigableDomElement.js +3 -4
- package/dist/keyNavigation/navigator.js +1 -2
- package/dist/listbox/css/listbox.css +1 -1
- package/dist/listbox/css/listbox.css.map +1 -1
- package/dist/maths/calculator/core/board.js +58 -127
- package/dist/maths/calculator/core/labels.js +1 -6
- package/dist/maths/calculator/css/calculator.css +18 -18
- package/dist/maths/calculator/css/calculator.css.map +1 -1
- package/dist/maths/calculator/plugins/screen/simpleScreen/simpleScreen.js +1 -6
- package/dist/mediaplayer/css/player.css +7 -7
- package/dist/mediaplayer/css/player.css.map +1 -1
- package/dist/mediaplayer/players/html5.js +3 -14
- package/dist/mediaplayer/players/youtube.js +3 -12
- package/dist/mediaplayer/utils/crossOrigin.js +1 -1
- package/dist/mediaplayer/utils/timeObserver.js +1 -2
- package/dist/mediaplayer/youtubeManager.js +1 -2
- package/dist/mediaplayer.js +2 -8
- package/dist/mediasizer.js +0 -1
- package/dist/resizeObserver.js +1 -3
- package/dist/resource/css/selector.css +31 -23
- package/dist/resource/css/selector.css.map +1 -1
- package/dist/resource/list.js +239 -203
- package/dist/resource/selector.js +0 -1
- package/dist/resource/tree.js +239 -203
- package/dist/resourcemgr/assetSearch.js +3 -3
- package/dist/resourcemgr/assetSearchContract.js +40 -12
- package/dist/resourcemgr/css/resourcemgr.css +113 -21
- package/dist/resourcemgr/css/resourcemgr.css.map +1 -1
- package/dist/resourcemgr/fileBrowser.js +370 -17
- package/dist/resourcemgr/filePreview.js +42 -3
- package/dist/resourcemgr/fileSelector.js +15 -0
- package/dist/resourcemgr.js +15 -10
- package/dist/searchModal/advancedSearch.js +3 -4
- package/dist/searchModal/css/searchModal.css +14 -14
- package/dist/searchModal/css/searchModal.css.map +1 -1
- package/dist/searchModal.js +42 -53
- package/dist/switch/css/switch.css +2 -2
- package/dist/switch/css/switch.css.map +1 -1
- package/dist/tabs/css/tabs.css +2 -2
- package/dist/tabs/css/tabs.css.map +1 -1
- package/dist/taskQueue/css/taskQueue.css +4 -4
- package/dist/taskQueue/css/taskQueue.css.map +1 -1
- package/dist/taskQueue/taskQueueModel.js +1 -2
- package/dist/taskQueueButton/taskable.js +1 -2
- package/dist/validator/validators.js +0 -1
- package/dist/waitingDialog/css/waitingDialog.css +2 -2
- package/dist/waitingDialog/css/waitingDialog.css.map +1 -1
- package/package.json +1 -1
- package/src/autocomplete/css/autocomplete.css +1 -1
- package/src/autocomplete/css/autocomplete.css.map +1 -1
- package/src/badge/css/badge.css +6 -6
- package/src/badge/css/badge.css.map +1 -1
- package/src/breadcrumbs/css/breadcrumbs.css +2 -2
- package/src/breadcrumbs/css/breadcrumbs.css.map +1 -1
- package/src/calculator/css/calculator.css +8 -6
- package/src/calculator/css/calculator.css.map +1 -1
- package/src/class/css/selector.css +4 -4
- package/src/class/css/selector.css.map +1 -1
- package/src/component/css/components.css +5 -5
- package/src/component/css/components.css.map +1 -1
- package/src/component/css/windowComponent.css +1 -1
- package/src/component/css/windowComponent.css.map +1 -1
- package/src/contextualPopup/css/contextualPopup.css +1 -1
- package/src/contextualPopup/css/contextualPopup.css.map +1 -1
- package/src/css/basic.css +123 -113
- package/src/css/basic.css.map +1 -1
- package/src/datatable/css/datatable.css +3 -3
- package/src/datatable/css/datatable.css.map +1 -1
- package/src/datetime/css/picker.css +13 -13
- package/src/datetime/css/picker.css.map +1 -1
- package/src/documentViewer/css/documentViewer.css +10 -10
- package/src/documentViewer/css/documentViewer.css.map +1 -1
- package/src/dynamicComponent/css/dynamicComponent.css +1 -1
- package/src/dynamicComponent/css/dynamicComponent.css.map +1 -1
- package/src/form/css/dropdownForm.css +1 -1
- package/src/form/css/dropdownForm.css.map +1 -1
- package/src/itemButtonList/css/item-button-list.css +9 -3
- package/src/itemButtonList/css/item-button-list.css.map +1 -1
- package/src/listbox/css/listbox.css +1 -1
- package/src/listbox/css/listbox.css.map +1 -1
- package/src/maths/calculator/css/calculator.css +18 -18
- package/src/maths/calculator/css/calculator.css.map +1 -1
- package/src/mediaplayer/css/player.css +7 -7
- package/src/mediaplayer/css/player.css.map +1 -1
- package/src/resource/css/selector.css +31 -23
- package/src/resource/css/selector.css.map +1 -1
- package/src/resourcemgr/assetSearch.js +3 -3
- package/src/resourcemgr/assetSearchContract.js +40 -18
- package/src/resourcemgr/css/resourcemgr.css +113 -21
- package/src/resourcemgr/css/resourcemgr.css.map +1 -1
- package/src/resourcemgr/fileBrowser.js +434 -33
- package/src/resourcemgr/filePreview.js +43 -4
- package/src/resourcemgr/fileSelector.js +18 -0
- package/src/resourcemgr/scss/resourcemgr.scss +103 -5
- package/src/resourcemgr/tpl/layout.tpl +30 -18
- package/src/resourcemgr.js +9 -4
- package/src/searchModal/css/searchModal.css +14 -14
- package/src/searchModal/css/searchModal.css.map +1 -1
- package/src/switch/css/switch.css +2 -2
- package/src/switch/css/switch.css.map +1 -1
- package/src/tabs/css/tabs.css +2 -2
- package/src/tabs/css/tabs.css.map +1 -1
- package/src/taskQueue/css/taskQueue.css +4 -4
- package/src/taskQueue/css/taskQueue.css.map +1 -1
- package/src/waitingDialog/css/waitingDialog.css +2 -2
- package/src/waitingDialog/css/waitingDialog.css.map +1 -1
package/dist/resource/list.js
CHANGED
|
@@ -96,7 +96,7 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
96
96
|
return (asString || true) ? html : $(html);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
/*! @license DOMPurify 2.
|
|
99
|
+
/*! @license DOMPurify 2.5.9 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.5.9/LICENSE */
|
|
100
100
|
|
|
101
101
|
function _typeof(obj) {
|
|
102
102
|
"@babel/helpers - typeof";
|
|
@@ -173,7 +173,6 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
173
173
|
var freeze = Object.freeze,
|
|
174
174
|
seal = Object.seal,
|
|
175
175
|
create = Object.create; // eslint-disable-line import/no-mutable-exports
|
|
176
|
-
|
|
177
176
|
var _ref = typeof Reflect !== 'undefined' && Reflect,
|
|
178
177
|
apply = _ref.apply,
|
|
179
178
|
construct = _ref.construct;
|
|
@@ -224,10 +223,11 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
224
223
|
return construct(func, args);
|
|
225
224
|
};
|
|
226
225
|
}
|
|
227
|
-
/* Add properties to a lookup table */
|
|
228
226
|
|
|
227
|
+
/* Add properties to a lookup table */
|
|
229
228
|
function addToSet(set, array, transformCaseFunc) {
|
|
230
|
-
|
|
229
|
+
var _transformCaseFunc;
|
|
230
|
+
transformCaseFunc = (_transformCaseFunc = transformCaseFunc) !== null && _transformCaseFunc !== void 0 ? _transformCaseFunc : stringToLowerCase;
|
|
231
231
|
if (setPrototypeOf) {
|
|
232
232
|
// Make 'in' and truthy checks like Boolean(set.constructor)
|
|
233
233
|
// independent of any properties defined on Object.prototype.
|
|
@@ -251,23 +251,23 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
251
251
|
}
|
|
252
252
|
return set;
|
|
253
253
|
}
|
|
254
|
-
/* Shallow clone an object */
|
|
255
254
|
|
|
255
|
+
/* Shallow clone an object */
|
|
256
256
|
function clone(object) {
|
|
257
257
|
var newObject = create(null);
|
|
258
258
|
var property;
|
|
259
259
|
for (property in object) {
|
|
260
|
-
if (apply(hasOwnProperty, object, [property])) {
|
|
260
|
+
if (apply(hasOwnProperty, object, [property]) === true) {
|
|
261
261
|
newObject[property] = object[property];
|
|
262
262
|
}
|
|
263
263
|
}
|
|
264
264
|
return newObject;
|
|
265
265
|
}
|
|
266
|
+
|
|
266
267
|
/* IE10 doesn't support __lookupGetter__ so lets'
|
|
267
268
|
* simulate it. It also automatically checks
|
|
268
269
|
* if the prop is function or getter and behaves
|
|
269
270
|
* accordingly. */
|
|
270
|
-
|
|
271
271
|
function lookupGetter(object, prop) {
|
|
272
272
|
while (object !== null) {
|
|
273
273
|
var desc = getOwnPropertyDescriptor(object, prop);
|
|
@@ -287,43 +287,45 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
287
287
|
}
|
|
288
288
|
return fallbackValue;
|
|
289
289
|
}
|
|
290
|
-
var html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
|
|
290
|
+
var html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
|
|
291
291
|
|
|
292
|
+
// SVG
|
|
292
293
|
var svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
|
|
293
|
-
var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
|
|
294
|
+
var svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
|
|
295
|
+
|
|
296
|
+
// List of SVG elements that are disallowed by default.
|
|
294
297
|
// We still need to know them so that we can do namespace
|
|
295
298
|
// checks properly in case one wants to add them to
|
|
296
299
|
// allow-list.
|
|
297
|
-
|
|
298
300
|
var svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'fedropshadow', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);
|
|
299
|
-
var mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);
|
|
300
|
-
// even those that we disallow by default.
|
|
301
|
+
var mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);
|
|
301
302
|
|
|
303
|
+
// Similarly to SVG, we want to know all MathML elements,
|
|
304
|
+
// even those that we disallow by default.
|
|
302
305
|
var mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
303
306
|
var text = freeze(['#text']);
|
|
304
307
|
var html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns', 'slot']);
|
|
305
308
|
var svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
|
|
306
309
|
var mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
|
|
307
310
|
var xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
308
|
-
var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
|
|
309
311
|
|
|
312
|
+
// eslint-disable-next-line unicorn/better-regex
|
|
313
|
+
var MUSTACHE_EXPR = seal(/\{\{[\w\W]*|[\w\W]*\}\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode
|
|
310
314
|
var ERB_EXPR = seal(/<%[\w\W]*|[\w\W]*%>/gm);
|
|
311
315
|
var TMPLIT_EXPR = seal(/\${[\w\W]*}/gm);
|
|
312
|
-
var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]
|
|
313
|
-
|
|
316
|
+
var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
|
|
314
317
|
var ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
|
|
315
|
-
|
|
316
318
|
var IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
|
|
317
319
|
);
|
|
318
|
-
|
|
319
320
|
var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
|
|
320
321
|
var ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
|
|
321
322
|
);
|
|
322
|
-
|
|
323
323
|
var DOCTYPE_NAME = seal(/^html$/i);
|
|
324
|
+
var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
|
|
324
325
|
var getGlobal = function getGlobal() {
|
|
325
326
|
return typeof window === 'undefined' ? null : window;
|
|
326
327
|
};
|
|
328
|
+
|
|
327
329
|
/**
|
|
328
330
|
* Creates a no-op policy for internal use only.
|
|
329
331
|
* Don't export this function outside this module!
|
|
@@ -332,14 +334,14 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
332
334
|
* @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types
|
|
333
335
|
* are not supported).
|
|
334
336
|
*/
|
|
335
|
-
|
|
336
337
|
var _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {
|
|
337
338
|
if (_typeof(trustedTypes) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
|
|
338
339
|
return null;
|
|
339
|
-
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Allow the callers to control the unique policy name
|
|
340
343
|
// by adding a data-tt-policy-suffix to the script element with the DOMPurify.
|
|
341
344
|
// Policy creation with duplicate names throws in Trusted Types.
|
|
342
|
-
|
|
343
345
|
var suffix = null;
|
|
344
346
|
var ATTR_NAME = 'data-tt-policy-suffix';
|
|
345
347
|
if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {
|
|
@@ -368,17 +370,17 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
368
370
|
var DOMPurify = function DOMPurify(root) {
|
|
369
371
|
return createDOMPurify(root);
|
|
370
372
|
};
|
|
373
|
+
|
|
371
374
|
/**
|
|
372
375
|
* Version label, exposed for easier checks
|
|
373
376
|
* if DOMPurify is up to date or not
|
|
374
377
|
*/
|
|
378
|
+
DOMPurify.version = '2.5.9';
|
|
375
379
|
|
|
376
|
-
DOMPurify.version = '2.4.1';
|
|
377
380
|
/**
|
|
378
381
|
* Array of elements that DOMPurify removed during sanitation.
|
|
379
382
|
* Empty if nothing was removed.
|
|
380
383
|
*/
|
|
381
|
-
|
|
382
384
|
DOMPurify.removed = [];
|
|
383
385
|
if (!window || !window.document || window.document.nodeType !== 9) {
|
|
384
386
|
// Not running in a browser, provide a factory function
|
|
@@ -402,13 +404,14 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
402
404
|
var cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
|
|
403
405
|
var getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
|
|
404
406
|
var getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
|
|
405
|
-
var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
|
|
407
|
+
var getParentNode = lookupGetter(ElementPrototype, 'parentNode');
|
|
408
|
+
|
|
409
|
+
// As per issue #47, the web-components registry is inherited by a
|
|
406
410
|
// new document created via createHTMLDocument. As per the spec
|
|
407
411
|
// (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
|
|
408
412
|
// a new empty registry is used when creating a template contents owner
|
|
409
413
|
// document, so we use that as our parent document to ensure nothing
|
|
410
414
|
// is inherited.
|
|
411
|
-
|
|
412
415
|
if (typeof HTMLTemplateElement === 'function') {
|
|
413
416
|
var template = document.createElement('template');
|
|
414
417
|
if (template.content && template.content.ownerDocument) {
|
|
@@ -428,39 +431,40 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
428
431
|
documentMode = clone(document).documentMode ? document.documentMode : {};
|
|
429
432
|
} catch (_) {}
|
|
430
433
|
var hooks = {};
|
|
434
|
+
|
|
431
435
|
/**
|
|
432
436
|
* Expose whether this browser supports running the full DOMPurify.
|
|
433
437
|
*/
|
|
434
|
-
|
|
435
|
-
DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;
|
|
438
|
+
DOMPurify.isSupported = typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined && documentMode !== 9;
|
|
436
439
|
var MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
|
|
437
440
|
ERB_EXPR$1 = ERB_EXPR,
|
|
438
441
|
TMPLIT_EXPR$1 = TMPLIT_EXPR,
|
|
439
442
|
DATA_ATTR$1 = DATA_ATTR,
|
|
440
443
|
ARIA_ATTR$1 = ARIA_ATTR,
|
|
441
444
|
IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
|
|
442
|
-
ATTR_WHITESPACE$1 = ATTR_WHITESPACE
|
|
445
|
+
ATTR_WHITESPACE$1 = ATTR_WHITESPACE,
|
|
446
|
+
CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
|
|
443
447
|
var IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
|
|
448
|
+
|
|
444
449
|
/**
|
|
445
450
|
* We consider the elements and attributes below to be safe. Ideally
|
|
446
451
|
* don't add any new ones but feel free to remove unwanted ones.
|
|
447
452
|
*/
|
|
448
453
|
|
|
449
454
|
/* allowed element names */
|
|
450
|
-
|
|
451
455
|
var ALLOWED_TAGS = null;
|
|
452
456
|
var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(svgFilters), _toConsumableArray(mathMl$1), _toConsumableArray(text)));
|
|
453
|
-
/* Allowed attribute names */
|
|
454
457
|
|
|
458
|
+
/* Allowed attribute names */
|
|
455
459
|
var ALLOWED_ATTR = null;
|
|
456
460
|
var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(mathMl), _toConsumableArray(xml)));
|
|
461
|
+
|
|
457
462
|
/*
|
|
458
463
|
* Configure how DOMPUrify should handle custom elements and their attributes as well as customized built-in elements.
|
|
459
464
|
* @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
|
|
460
465
|
* @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)
|
|
461
466
|
* @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
|
|
462
467
|
*/
|
|
463
|
-
|
|
464
468
|
var CUSTOM_ELEMENT_HANDLING = Object.seal(Object.create(null, {
|
|
465
469
|
tagNameCheck: {
|
|
466
470
|
writable: true,
|
|
@@ -481,55 +485,65 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
481
485
|
value: false
|
|
482
486
|
}
|
|
483
487
|
}));
|
|
484
|
-
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
|
|
485
488
|
|
|
489
|
+
/* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
|
|
486
490
|
var FORBID_TAGS = null;
|
|
487
|
-
/* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
|
|
488
491
|
|
|
492
|
+
/* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
|
|
489
493
|
var FORBID_ATTR = null;
|
|
490
|
-
/* Decide if ARIA attributes are okay */
|
|
491
494
|
|
|
495
|
+
/* Decide if ARIA attributes are okay */
|
|
492
496
|
var ALLOW_ARIA_ATTR = true;
|
|
493
|
-
/* Decide if custom data attributes are okay */
|
|
494
497
|
|
|
498
|
+
/* Decide if custom data attributes are okay */
|
|
495
499
|
var ALLOW_DATA_ATTR = true;
|
|
496
|
-
/* Decide if unknown protocols are okay */
|
|
497
500
|
|
|
501
|
+
/* Decide if unknown protocols are okay */
|
|
498
502
|
var ALLOW_UNKNOWN_PROTOCOLS = false;
|
|
503
|
+
|
|
504
|
+
/* Decide if self-closing tags in attributes are allowed.
|
|
505
|
+
* Usually removed due to a mXSS issue in jQuery 3.0 */
|
|
506
|
+
var ALLOW_SELF_CLOSE_IN_ATTR = true;
|
|
507
|
+
|
|
499
508
|
/* Output should be safe for common template engines.
|
|
500
509
|
* This means, DOMPurify removes data attributes, mustaches and ERB
|
|
501
510
|
*/
|
|
502
|
-
|
|
503
511
|
var SAFE_FOR_TEMPLATES = false;
|
|
504
|
-
/* Decide if document with <html>... should be returned */
|
|
505
512
|
|
|
513
|
+
/* Output should be safe even for XML used within HTML and alike.
|
|
514
|
+
* This means, DOMPurify removes comments when containing risky content.
|
|
515
|
+
*/
|
|
516
|
+
var SAFE_FOR_XML = true;
|
|
517
|
+
|
|
518
|
+
/* Decide if document with <html>... should be returned */
|
|
506
519
|
var WHOLE_DOCUMENT = false;
|
|
507
|
-
/* Track whether config is already set on this instance of DOMPurify. */
|
|
508
520
|
|
|
521
|
+
/* Track whether config is already set on this instance of DOMPurify. */
|
|
509
522
|
var SET_CONFIG = false;
|
|
523
|
+
|
|
510
524
|
/* Decide if all elements (e.g. style, script) must be children of
|
|
511
525
|
* document.body. By default, browsers might move them to document.head */
|
|
512
|
-
|
|
513
526
|
var FORCE_BODY = false;
|
|
527
|
+
|
|
514
528
|
/* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
|
|
515
529
|
* string (or a TrustedHTML object if Trusted Types are supported).
|
|
516
530
|
* If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
|
|
517
531
|
*/
|
|
518
|
-
|
|
519
532
|
var RETURN_DOM = false;
|
|
533
|
+
|
|
520
534
|
/* Decide if a DOM `DocumentFragment` should be returned, instead of a html
|
|
521
535
|
* string (or a TrustedHTML object if Trusted Types are supported) */
|
|
522
|
-
|
|
523
536
|
var RETURN_DOM_FRAGMENT = false;
|
|
537
|
+
|
|
524
538
|
/* Try to return a Trusted Type object instead of a string, return a string in
|
|
525
539
|
* case Trusted Types are not supported */
|
|
526
|
-
|
|
527
540
|
var RETURN_TRUSTED_TYPE = false;
|
|
541
|
+
|
|
528
542
|
/* Output should be free from DOM clobbering attacks?
|
|
529
543
|
* This sanitizes markups named with colliding, clobberable built-in DOM APIs.
|
|
530
544
|
*/
|
|
531
|
-
|
|
532
545
|
var SANITIZE_DOM = true;
|
|
546
|
+
|
|
533
547
|
/* Achieve full DOM Clobbering protection by isolating the namespace of named
|
|
534
548
|
* properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.
|
|
535
549
|
*
|
|
@@ -543,85 +557,84 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
543
557
|
* Namespace isolation is implemented by prefixing `id` and `name` attributes
|
|
544
558
|
* with a constant string, i.e., `user-content-`
|
|
545
559
|
*/
|
|
546
|
-
|
|
547
560
|
var SANITIZE_NAMED_PROPS = false;
|
|
548
561
|
var SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';
|
|
549
|
-
/* Keep element content when removing element? */
|
|
550
562
|
|
|
563
|
+
/* Keep element content when removing element? */
|
|
551
564
|
var KEEP_CONTENT = true;
|
|
565
|
+
|
|
552
566
|
/* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
|
|
553
567
|
* of importing it into a new Document and returning a sanitized copy */
|
|
554
|
-
|
|
555
568
|
var IN_PLACE = false;
|
|
556
|
-
/* Allow usage of profiles like html, svg and mathMl */
|
|
557
569
|
|
|
570
|
+
/* Allow usage of profiles like html, svg and mathMl */
|
|
558
571
|
var USE_PROFILES = {};
|
|
559
|
-
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
560
572
|
|
|
573
|
+
/* Tags to ignore content of when KEEP_CONTENT is true */
|
|
561
574
|
var FORBID_CONTENTS = null;
|
|
562
575
|
var DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);
|
|
563
|
-
/* Tags that are safe for data: URIs */
|
|
564
576
|
|
|
577
|
+
/* Tags that are safe for data: URIs */
|
|
565
578
|
var DATA_URI_TAGS = null;
|
|
566
579
|
var DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);
|
|
567
|
-
/* Attributes safe for values like "javascript:" */
|
|
568
580
|
|
|
581
|
+
/* Attributes safe for values like "javascript:" */
|
|
569
582
|
var URI_SAFE_ATTRIBUTES = null;
|
|
570
583
|
var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
|
|
571
584
|
var MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
|
|
572
585
|
var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
573
586
|
var HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
|
|
574
587
|
/* Document namespace */
|
|
575
|
-
|
|
576
588
|
var NAMESPACE = HTML_NAMESPACE;
|
|
577
589
|
var IS_EMPTY_INPUT = false;
|
|
578
|
-
/* Allowed XHTML+XML namespaces */
|
|
579
590
|
|
|
591
|
+
/* Allowed XHTML+XML namespaces */
|
|
580
592
|
var ALLOWED_NAMESPACES = null;
|
|
581
593
|
var DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
|
|
582
|
-
/* Parsing of strict XHTML documents */
|
|
583
594
|
|
|
595
|
+
/* Parsing of strict XHTML documents */
|
|
584
596
|
var PARSER_MEDIA_TYPE;
|
|
585
597
|
var SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
|
|
586
598
|
var DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
|
|
587
599
|
var transformCaseFunc;
|
|
588
|
-
/* Keep a reference to config to pass to hooks */
|
|
589
600
|
|
|
601
|
+
/* Keep a reference to config to pass to hooks */
|
|
590
602
|
var CONFIG = null;
|
|
591
|
-
/* Ideally, do not touch anything below this line */
|
|
592
603
|
|
|
604
|
+
/* Ideally, do not touch anything below this line */
|
|
593
605
|
/* ______________________________________________ */
|
|
594
606
|
|
|
595
607
|
var formElement = document.createElement('form');
|
|
596
608
|
var isRegexOrFunction = function isRegexOrFunction(testValue) {
|
|
597
609
|
return testValue instanceof RegExp || testValue instanceof Function;
|
|
598
610
|
};
|
|
611
|
+
|
|
599
612
|
/**
|
|
600
613
|
* _parseConfig
|
|
601
614
|
*
|
|
602
615
|
* @param {Object} cfg optional config literal
|
|
603
616
|
*/
|
|
604
617
|
// eslint-disable-next-line complexity
|
|
605
|
-
|
|
606
618
|
var _parseConfig = function _parseConfig(cfg) {
|
|
607
619
|
if (CONFIG && CONFIG === cfg) {
|
|
608
620
|
return;
|
|
609
621
|
}
|
|
610
|
-
/* Shield configuration object from tampering */
|
|
611
622
|
|
|
623
|
+
/* Shield configuration object from tampering */
|
|
612
624
|
if (!cfg || _typeof(cfg) !== 'object') {
|
|
613
625
|
cfg = {};
|
|
614
626
|
}
|
|
615
|
-
/* Shield configuration object from prototype pollution */
|
|
616
627
|
|
|
628
|
+
/* Shield configuration object from prototype pollution */
|
|
617
629
|
cfg = clone(cfg);
|
|
618
630
|
PARSER_MEDIA_TYPE =
|
|
619
631
|
// eslint-disable-next-line unicorn/prefer-includes
|
|
620
|
-
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
|
|
632
|
+
SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? PARSER_MEDIA_TYPE = DEFAULT_PARSER_MEDIA_TYPE : PARSER_MEDIA_TYPE = cfg.PARSER_MEDIA_TYPE;
|
|
621
633
|
|
|
634
|
+
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
622
635
|
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
|
|
623
|
-
/* Set configuration parameters */
|
|
624
636
|
|
|
637
|
+
/* Set configuration parameters */
|
|
625
638
|
ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
|
|
626
639
|
ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
|
|
627
640
|
ALLOWED_NAMESPACES = 'ALLOWED_NAMESPACES' in cfg ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
|
|
@@ -644,33 +657,23 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
644
657
|
FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : {};
|
|
645
658
|
USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;
|
|
646
659
|
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
|
|
647
|
-
|
|
648
660
|
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
|
|
649
|
-
|
|
650
661
|
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
|
|
651
|
-
|
|
662
|
+
ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true
|
|
652
663
|
SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
|
|
653
|
-
|
|
664
|
+
SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true
|
|
654
665
|
WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
|
|
655
|
-
|
|
656
666
|
RETURN_DOM = cfg.RETURN_DOM || false; // Default false
|
|
657
|
-
|
|
658
667
|
RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
|
|
659
|
-
|
|
660
668
|
RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
|
|
661
|
-
|
|
662
669
|
FORCE_BODY = cfg.FORCE_BODY || false; // Default false
|
|
663
|
-
|
|
664
670
|
SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
|
|
665
|
-
|
|
666
671
|
SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
|
|
667
|
-
|
|
668
672
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
669
|
-
|
|
670
673
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
671
|
-
|
|
672
674
|
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$1;
|
|
673
675
|
NAMESPACE = cfg.NAMESPACE || HTML_NAMESPACE;
|
|
676
|
+
CUSTOM_ELEMENT_HANDLING = cfg.CUSTOM_ELEMENT_HANDLING || {};
|
|
674
677
|
if (cfg.CUSTOM_ELEMENT_HANDLING && isRegexOrFunction(cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck)) {
|
|
675
678
|
CUSTOM_ELEMENT_HANDLING.tagNameCheck = cfg.CUSTOM_ELEMENT_HANDLING.tagNameCheck;
|
|
676
679
|
}
|
|
@@ -686,8 +689,8 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
686
689
|
if (RETURN_DOM_FRAGMENT) {
|
|
687
690
|
RETURN_DOM = true;
|
|
688
691
|
}
|
|
689
|
-
/* Parse profile info */
|
|
690
692
|
|
|
693
|
+
/* Parse profile info */
|
|
691
694
|
if (USE_PROFILES) {
|
|
692
695
|
ALLOWED_TAGS = addToSet({}, _toConsumableArray(text));
|
|
693
696
|
ALLOWED_ATTR = [];
|
|
@@ -711,8 +714,8 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
711
714
|
addToSet(ALLOWED_ATTR, xml);
|
|
712
715
|
}
|
|
713
716
|
}
|
|
714
|
-
/* Merge configuration parameters */
|
|
715
717
|
|
|
718
|
+
/* Merge configuration parameters */
|
|
716
719
|
if (cfg.ADD_TAGS) {
|
|
717
720
|
if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
|
718
721
|
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
@@ -734,45 +737,48 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
734
737
|
}
|
|
735
738
|
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
|
|
736
739
|
}
|
|
737
|
-
/* Add #text in case KEEP_CONTENT is set to true */
|
|
738
740
|
|
|
741
|
+
/* Add #text in case KEEP_CONTENT is set to true */
|
|
739
742
|
if (KEEP_CONTENT) {
|
|
740
743
|
ALLOWED_TAGS['#text'] = true;
|
|
741
744
|
}
|
|
742
|
-
/* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
|
|
743
745
|
|
|
746
|
+
/* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
|
|
744
747
|
if (WHOLE_DOCUMENT) {
|
|
745
748
|
addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
|
|
746
749
|
}
|
|
747
|
-
/* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
|
|
748
750
|
|
|
751
|
+
/* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
|
|
749
752
|
if (ALLOWED_TAGS.table) {
|
|
750
753
|
addToSet(ALLOWED_TAGS, ['tbody']);
|
|
751
754
|
delete FORBID_TAGS.tbody;
|
|
752
|
-
}
|
|
753
|
-
// Not available in IE8, Safari 5, etc.
|
|
755
|
+
}
|
|
754
756
|
|
|
757
|
+
// Prevent further manipulation of configuration.
|
|
758
|
+
// Not available in IE8, Safari 5, etc.
|
|
755
759
|
if (freeze) {
|
|
756
760
|
freeze(cfg);
|
|
757
761
|
}
|
|
758
762
|
CONFIG = cfg;
|
|
759
763
|
};
|
|
760
764
|
var MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);
|
|
761
|
-
var HTML_INTEGRATION_POINTS = addToSet({}, ['
|
|
765
|
+
var HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);
|
|
766
|
+
|
|
767
|
+
// Certain elements are allowed in both SVG and HTML
|
|
762
768
|
// namespace. We need to specify them explicitly
|
|
763
769
|
// so that they don't get erroneously deleted from
|
|
764
770
|
// HTML namespace.
|
|
765
|
-
|
|
766
771
|
var COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
|
|
772
|
+
|
|
767
773
|
/* Keep track of all possible SVG and MathML tags
|
|
768
774
|
* so that we can perform the namespace checks
|
|
769
775
|
* correctly. */
|
|
770
|
-
|
|
771
776
|
var ALL_SVG_TAGS = addToSet({}, svg$1);
|
|
772
777
|
addToSet(ALL_SVG_TAGS, svgFilters);
|
|
773
778
|
addToSet(ALL_SVG_TAGS, svgDisallowed);
|
|
774
779
|
var ALL_MATHML_TAGS = addToSet({}, mathMl$1);
|
|
775
780
|
addToSet(ALL_MATHML_TAGS, mathMlDisallowed);
|
|
781
|
+
|
|
776
782
|
/**
|
|
777
783
|
*
|
|
778
784
|
*
|
|
@@ -781,11 +787,11 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
781
787
|
* namespace that a spec-compliant parser would never
|
|
782
788
|
* return. Return true otherwise.
|
|
783
789
|
*/
|
|
784
|
-
|
|
785
790
|
var _checkValidNamespace = function _checkValidNamespace(element) {
|
|
786
|
-
var parent = getParentNode(element);
|
|
787
|
-
// can be null. We just simulate parent in this case.
|
|
791
|
+
var parent = getParentNode(element);
|
|
788
792
|
|
|
793
|
+
// In JSDOM, if we're inside shadow DOM, then parentNode
|
|
794
|
+
// can be null. We just simulate parent in this case.
|
|
789
795
|
if (!parent || !parent.tagName) {
|
|
790
796
|
parent = {
|
|
791
797
|
namespaceURI: NAMESPACE,
|
|
@@ -803,15 +809,17 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
803
809
|
// it should be killed.
|
|
804
810
|
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
805
811
|
return tagName === 'svg';
|
|
806
|
-
}
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// The only way to switch from MathML to SVG is via`
|
|
807
815
|
// svg if parent is either <annotation-xml> or MathML
|
|
808
816
|
// text integration points.
|
|
809
|
-
|
|
810
817
|
if (parent.namespaceURI === MATHML_NAMESPACE) {
|
|
811
818
|
return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
|
|
812
|
-
}
|
|
813
|
-
// spec. All others are disallowed in SVG namespace.
|
|
819
|
+
}
|
|
814
820
|
|
|
821
|
+
// We only allow elements that are defined in SVG
|
|
822
|
+
// spec. All others are disallowed in SVG namespace.
|
|
815
823
|
return Boolean(ALL_SVG_TAGS[tagName]);
|
|
816
824
|
}
|
|
817
825
|
if (element.namespaceURI === MATHML_NAMESPACE) {
|
|
@@ -820,14 +828,16 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
820
828
|
// it should be killed.
|
|
821
829
|
if (parent.namespaceURI === HTML_NAMESPACE) {
|
|
822
830
|
return tagName === 'math';
|
|
823
|
-
}
|
|
824
|
-
// <math> and HTML integration points
|
|
831
|
+
}
|
|
825
832
|
|
|
833
|
+
// The only way to switch from SVG to MathML is via
|
|
834
|
+
// <math> and HTML integration points
|
|
826
835
|
if (parent.namespaceURI === SVG_NAMESPACE) {
|
|
827
836
|
return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
|
|
828
|
-
}
|
|
829
|
-
// spec. All others are disallowed in MathML namespace.
|
|
837
|
+
}
|
|
830
838
|
|
|
839
|
+
// We only allow elements that are defined in MathML
|
|
840
|
+
// spec. All others are disallowed in MathML namespace.
|
|
831
841
|
return Boolean(ALL_MATHML_TAGS[tagName]);
|
|
832
842
|
}
|
|
833
843
|
if (element.namespaceURI === HTML_NAMESPACE) {
|
|
@@ -839,27 +849,30 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
839
849
|
}
|
|
840
850
|
if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
|
|
841
851
|
return false;
|
|
842
|
-
}
|
|
843
|
-
// or SVG and should never appear in HTML namespace
|
|
852
|
+
}
|
|
844
853
|
|
|
854
|
+
// We disallow tags that are specific for MathML
|
|
855
|
+
// or SVG and should never appear in HTML namespace
|
|
845
856
|
return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
|
|
846
|
-
}
|
|
857
|
+
}
|
|
847
858
|
|
|
859
|
+
// For XHTML and XML documents that support custom namespaces
|
|
848
860
|
if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
|
|
849
861
|
return true;
|
|
850
|
-
}
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
// The code should never reach this place (this means
|
|
851
865
|
// that the element somehow got namespace that is not
|
|
852
866
|
// HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).
|
|
853
867
|
// Return false just in case.
|
|
854
|
-
|
|
855
868
|
return false;
|
|
856
869
|
};
|
|
870
|
+
|
|
857
871
|
/**
|
|
858
872
|
* _forceRemove
|
|
859
873
|
*
|
|
860
874
|
* @param {Node} node a DOM node
|
|
861
875
|
*/
|
|
862
|
-
|
|
863
876
|
var _forceRemove = function _forceRemove(node) {
|
|
864
877
|
arrayPush(DOMPurify.removed, {
|
|
865
878
|
element: node
|
|
@@ -875,13 +888,13 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
875
888
|
}
|
|
876
889
|
}
|
|
877
890
|
};
|
|
891
|
+
|
|
878
892
|
/**
|
|
879
893
|
* _removeAttribute
|
|
880
894
|
*
|
|
881
895
|
* @param {String} name an Attribute name
|
|
882
896
|
* @param {Node} node a DOM node
|
|
883
897
|
*/
|
|
884
|
-
|
|
885
898
|
var _removeAttribute = function _removeAttribute(name, node) {
|
|
886
899
|
try {
|
|
887
900
|
arrayPush(DOMPurify.removed, {
|
|
@@ -894,8 +907,9 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
894
907
|
from: node
|
|
895
908
|
});
|
|
896
909
|
}
|
|
897
|
-
node.removeAttribute(name);
|
|
910
|
+
node.removeAttribute(name);
|
|
898
911
|
|
|
912
|
+
// We void attribute values for unremovable "is"" attributes
|
|
899
913
|
if (name === 'is' && !ALLOWED_ATTR[name]) {
|
|
900
914
|
if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
|
|
901
915
|
try {
|
|
@@ -908,13 +922,13 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
908
922
|
}
|
|
909
923
|
}
|
|
910
924
|
};
|
|
925
|
+
|
|
911
926
|
/**
|
|
912
927
|
* _initDocument
|
|
913
928
|
*
|
|
914
929
|
* @param {String} dirty a string of dirty markup
|
|
915
930
|
* @return {Document} a DOM, filled with the dirty markup
|
|
916
931
|
*/
|
|
917
|
-
|
|
918
932
|
var _initDocument = function _initDocument(dirty) {
|
|
919
933
|
/* Create a HTML document */
|
|
920
934
|
var doc;
|
|
@@ -935,64 +949,65 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
935
949
|
* Use the DOMParser API by default, fallback later if needs be
|
|
936
950
|
* DOMParser not work for svg when has multiple root element.
|
|
937
951
|
*/
|
|
938
|
-
|
|
939
952
|
if (NAMESPACE === HTML_NAMESPACE) {
|
|
940
953
|
try {
|
|
941
954
|
doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
|
|
942
955
|
} catch (_) {}
|
|
943
956
|
}
|
|
944
|
-
/* Use createHTMLDocument in case DOMParser is not available */
|
|
945
957
|
|
|
958
|
+
/* Use createHTMLDocument in case DOMParser is not available */
|
|
946
959
|
if (!doc || !doc.documentElement) {
|
|
947
960
|
doc = implementation.createDocument(NAMESPACE, 'template', null);
|
|
948
961
|
try {
|
|
949
|
-
doc.documentElement.innerHTML = IS_EMPTY_INPUT ?
|
|
950
|
-
} catch (_) {
|
|
962
|
+
doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
|
|
963
|
+
} catch (_) {
|
|
964
|
+
// Syntax error if dirtyPayload is invalid xml
|
|
951
965
|
}
|
|
952
966
|
}
|
|
953
967
|
var body = doc.body || doc.documentElement;
|
|
954
968
|
if (dirty && leadingWhitespace) {
|
|
955
969
|
body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
|
|
956
970
|
}
|
|
957
|
-
/* Work on whole document or just its body */
|
|
958
971
|
|
|
972
|
+
/* Work on whole document or just its body */
|
|
959
973
|
if (NAMESPACE === HTML_NAMESPACE) {
|
|
960
974
|
return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
|
|
961
975
|
}
|
|
962
976
|
return WHOLE_DOCUMENT ? doc.documentElement : body;
|
|
963
977
|
};
|
|
978
|
+
|
|
964
979
|
/**
|
|
965
980
|
* _createIterator
|
|
966
981
|
*
|
|
967
982
|
* @param {Document} root document/fragment to create iterator for
|
|
968
983
|
* @return {Iterator} iterator instance
|
|
969
984
|
*/
|
|
970
|
-
|
|
971
985
|
var _createIterator = function _createIterator(root) {
|
|
972
986
|
return createNodeIterator.call(root.ownerDocument || root, root,
|
|
973
987
|
// eslint-disable-next-line no-bitwise
|
|
974
|
-
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, null, false);
|
|
988
|
+
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null, false);
|
|
975
989
|
};
|
|
990
|
+
|
|
976
991
|
/**
|
|
977
992
|
* _isClobbered
|
|
978
993
|
*
|
|
979
994
|
* @param {Node} elm element to check for clobbering attacks
|
|
980
995
|
* @return {Boolean} true if clobbered, false if safe
|
|
981
996
|
*/
|
|
982
|
-
|
|
983
997
|
var _isClobbered = function _isClobbered(elm) {
|
|
984
998
|
return elm instanceof HTMLFormElement && (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string' || typeof elm.insertBefore !== 'function' || typeof elm.hasChildNodes !== 'function');
|
|
985
999
|
};
|
|
1000
|
+
|
|
986
1001
|
/**
|
|
987
1002
|
* _isNode
|
|
988
1003
|
*
|
|
989
1004
|
* @param {Node} obj object to check whether it's a DOM node
|
|
990
1005
|
* @return {Boolean} true is object is a DOM node
|
|
991
1006
|
*/
|
|
992
|
-
|
|
993
1007
|
var _isNode = function _isNode(object) {
|
|
994
1008
|
return _typeof(Node) === 'object' ? object instanceof Node : object && _typeof(object) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';
|
|
995
1009
|
};
|
|
1010
|
+
|
|
996
1011
|
/**
|
|
997
1012
|
* _executeHook
|
|
998
1013
|
* Execute user configurable hooks
|
|
@@ -1001,7 +1016,6 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1001
1016
|
* @param {Node} currentNode node to work on with the hook
|
|
1002
1017
|
* @param {Object} data additional hook parameters
|
|
1003
1018
|
*/
|
|
1004
|
-
|
|
1005
1019
|
var _executeHook = function _executeHook(entryPoint, currentNode, data) {
|
|
1006
1020
|
if (!hooks[entryPoint]) {
|
|
1007
1021
|
return;
|
|
@@ -1010,6 +1024,7 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1010
1024
|
hook.call(DOMPurify, currentNode, data, CONFIG);
|
|
1011
1025
|
});
|
|
1012
1026
|
};
|
|
1027
|
+
|
|
1013
1028
|
/**
|
|
1014
1029
|
* _sanitizeElements
|
|
1015
1030
|
*
|
|
@@ -1020,80 +1035,95 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1020
1035
|
* @param {Node} currentNode to check for permission to exist
|
|
1021
1036
|
* @return {Boolean} true if node was killed, false if left alive
|
|
1022
1037
|
*/
|
|
1023
|
-
|
|
1024
1038
|
var _sanitizeElements = function _sanitizeElements(currentNode) {
|
|
1025
1039
|
var content;
|
|
1026
|
-
/* Execute a hook if present */
|
|
1027
1040
|
|
|
1041
|
+
/* Execute a hook if present */
|
|
1028
1042
|
_executeHook('beforeSanitizeElements', currentNode, null);
|
|
1029
|
-
/* Check if element is clobbered or can clobber */
|
|
1030
1043
|
|
|
1044
|
+
/* Check if element is clobbered or can clobber */
|
|
1031
1045
|
if (_isClobbered(currentNode)) {
|
|
1032
1046
|
_forceRemove(currentNode);
|
|
1033
1047
|
return true;
|
|
1034
1048
|
}
|
|
1035
|
-
/* Check if tagname contains Unicode */
|
|
1036
1049
|
|
|
1050
|
+
/* Check if tagname contains Unicode */
|
|
1037
1051
|
if (regExpTest(/[\u0080-\uFFFF]/, currentNode.nodeName)) {
|
|
1038
1052
|
_forceRemove(currentNode);
|
|
1039
1053
|
return true;
|
|
1040
1054
|
}
|
|
1041
|
-
/* Now let's check the element's type and name */
|
|
1042
1055
|
|
|
1056
|
+
/* Now let's check the element's type and name */
|
|
1043
1057
|
var tagName = transformCaseFunc(currentNode.nodeName);
|
|
1044
|
-
/* Execute a hook if present */
|
|
1045
1058
|
|
|
1059
|
+
/* Execute a hook if present */
|
|
1046
1060
|
_executeHook('uponSanitizeElement', currentNode, {
|
|
1047
1061
|
tagName: tagName,
|
|
1048
1062
|
allowedTags: ALLOWED_TAGS
|
|
1049
1063
|
});
|
|
1050
|
-
/* Detect mXSS attempts abusing namespace confusion */
|
|
1051
1064
|
|
|
1065
|
+
/* Detect mXSS attempts abusing namespace confusion */
|
|
1052
1066
|
if (currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[/\w]/g, currentNode.innerHTML) && regExpTest(/<[/\w]/g, currentNode.textContent)) {
|
|
1053
1067
|
_forceRemove(currentNode);
|
|
1054
1068
|
return true;
|
|
1055
1069
|
}
|
|
1056
|
-
/* Mitigate a problem with templates inside select */
|
|
1057
1070
|
|
|
1071
|
+
/* Mitigate a problem with templates inside select */
|
|
1058
1072
|
if (tagName === 'select' && regExpTest(/<template/i, currentNode.innerHTML)) {
|
|
1059
1073
|
_forceRemove(currentNode);
|
|
1060
1074
|
return true;
|
|
1061
1075
|
}
|
|
1062
|
-
/* Remove element if anything forbids its presence */
|
|
1063
1076
|
|
|
1077
|
+
/* Remove any ocurrence of processing instructions */
|
|
1078
|
+
if (currentNode.nodeType === 7) {
|
|
1079
|
+
_forceRemove(currentNode);
|
|
1080
|
+
return true;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
/* Remove any kind of possibly harmful comments */
|
|
1084
|
+
if (SAFE_FOR_XML && currentNode.nodeType === 8 && regExpTest(/<[/\w]/g, currentNode.data)) {
|
|
1085
|
+
_forceRemove(currentNode);
|
|
1086
|
+
return true;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
/* Remove element if anything forbids its presence */
|
|
1064
1090
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
1065
1091
|
/* Check if we have a custom element to handle */
|
|
1066
1092
|
if (!FORBID_TAGS[tagName] && _basicCustomElementTest(tagName)) {
|
|
1067
1093
|
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) return false;
|
|
1068
1094
|
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) return false;
|
|
1069
1095
|
}
|
|
1070
|
-
/* Keep content except for bad-listed elements */
|
|
1071
1096
|
|
|
1097
|
+
/* Keep content except for bad-listed elements */
|
|
1072
1098
|
if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
|
|
1073
1099
|
var parentNode = getParentNode(currentNode) || currentNode.parentNode;
|
|
1074
1100
|
var childNodes = getChildNodes(currentNode) || currentNode.childNodes;
|
|
1075
1101
|
if (childNodes && parentNode) {
|
|
1076
1102
|
var childCount = childNodes.length;
|
|
1077
1103
|
for (var i = childCount - 1; i >= 0; --i) {
|
|
1078
|
-
|
|
1104
|
+
var childClone = cloneNode(childNodes[i], true);
|
|
1105
|
+
childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
|
|
1106
|
+
parentNode.insertBefore(childClone, getNextSibling(currentNode));
|
|
1079
1107
|
}
|
|
1080
1108
|
}
|
|
1081
1109
|
}
|
|
1082
1110
|
_forceRemove(currentNode);
|
|
1083
1111
|
return true;
|
|
1084
1112
|
}
|
|
1085
|
-
/* Check whether element has a valid namespace */
|
|
1086
1113
|
|
|
1114
|
+
/* Check whether element has a valid namespace */
|
|
1087
1115
|
if (currentNode instanceof Element && !_checkValidNamespace(currentNode)) {
|
|
1088
1116
|
_forceRemove(currentNode);
|
|
1089
1117
|
return true;
|
|
1090
1118
|
}
|
|
1091
|
-
|
|
1119
|
+
|
|
1120
|
+
/* Make sure that older browsers don't get fallback-tag mXSS */
|
|
1121
|
+
if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(/<\/no(script|embed|frames)/i, currentNode.innerHTML)) {
|
|
1092
1122
|
_forceRemove(currentNode);
|
|
1093
1123
|
return true;
|
|
1094
1124
|
}
|
|
1095
|
-
/* Sanitize element content to be template-safe */
|
|
1096
1125
|
|
|
1126
|
+
/* Sanitize element content to be template-safe */
|
|
1097
1127
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {
|
|
1098
1128
|
/* Get the element's text content */
|
|
1099
1129
|
content = currentNode.textContent;
|
|
@@ -1107,11 +1137,12 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1107
1137
|
currentNode.textContent = content;
|
|
1108
1138
|
}
|
|
1109
1139
|
}
|
|
1110
|
-
/* Execute a hook if present */
|
|
1111
1140
|
|
|
1141
|
+
/* Execute a hook if present */
|
|
1112
1142
|
_executeHook('afterSanitizeElements', currentNode, null);
|
|
1113
1143
|
return false;
|
|
1114
1144
|
};
|
|
1145
|
+
|
|
1115
1146
|
/**
|
|
1116
1147
|
* _isValidAttribute
|
|
1117
1148
|
*
|
|
@@ -1121,17 +1152,16 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1121
1152
|
* @return {Boolean} Returns true if `value` is valid, otherwise false.
|
|
1122
1153
|
*/
|
|
1123
1154
|
// eslint-disable-next-line complexity
|
|
1124
|
-
|
|
1125
1155
|
var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
1126
1156
|
/* Make sure attribute cannot clobber */
|
|
1127
1157
|
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
1128
1158
|
return false;
|
|
1129
1159
|
}
|
|
1160
|
+
|
|
1130
1161
|
/* Allow valid data-* attributes: At least one character after "-"
|
|
1131
1162
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
1132
1163
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
1133
1164
|
We don't need to check the value; it's always URI safe. */
|
|
1134
|
-
|
|
1135
1165
|
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName)) ;else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ;else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
1136
1166
|
if (
|
|
1137
1167
|
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
@@ -1144,21 +1174,22 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1144
1174
|
return false;
|
|
1145
1175
|
}
|
|
1146
1176
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
1147
|
-
} else if (URI_SAFE_ATTRIBUTES[lcName]) ;else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ;else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ;else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ;else if (
|
|
1177
|
+
} else if (URI_SAFE_ATTRIBUTES[lcName]) ;else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ;else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ;else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ;else if (value) {
|
|
1148
1178
|
return false;
|
|
1149
1179
|
}
|
|
1150
1180
|
return true;
|
|
1151
1181
|
};
|
|
1182
|
+
|
|
1152
1183
|
/**
|
|
1153
1184
|
* _basicCustomElementCheck
|
|
1154
1185
|
* checks if at least one dash is included in tagName, and it's not the first char
|
|
1155
1186
|
* for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
|
|
1156
1187
|
* @param {string} tagName name of the tag of the node to sanitize
|
|
1157
1188
|
*/
|
|
1158
|
-
|
|
1159
1189
|
var _basicCustomElementTest = function _basicCustomElementTest(tagName) {
|
|
1160
|
-
return tagName
|
|
1190
|
+
return tagName !== 'annotation-xml' && stringMatch(tagName, CUSTOM_ELEMENT$1);
|
|
1161
1191
|
};
|
|
1192
|
+
|
|
1162
1193
|
/**
|
|
1163
1194
|
* _sanitizeAttributes
|
|
1164
1195
|
*
|
|
@@ -1169,19 +1200,17 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1169
1200
|
*
|
|
1170
1201
|
* @param {Node} currentNode to sanitize
|
|
1171
1202
|
*/
|
|
1172
|
-
|
|
1173
1203
|
var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
1174
1204
|
var attr;
|
|
1175
1205
|
var value;
|
|
1176
1206
|
var lcName;
|
|
1177
1207
|
var l;
|
|
1178
1208
|
/* Execute a hook if present */
|
|
1179
|
-
|
|
1180
1209
|
_executeHook('beforeSanitizeAttributes', currentNode, null);
|
|
1181
1210
|
var attributes = currentNode.attributes;
|
|
1182
|
-
/* Check if we have attributes; if not we might have a text node */
|
|
1183
1211
|
|
|
1184
|
-
if
|
|
1212
|
+
/* Check if we have attributes; if not we might have a text node */
|
|
1213
|
+
if (!attributes || _isClobbered(currentNode)) {
|
|
1185
1214
|
return;
|
|
1186
1215
|
}
|
|
1187
1216
|
var hookEvent = {
|
|
@@ -1191,8 +1220,8 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1191
1220
|
allowedAttributes: ALLOWED_ATTR
|
|
1192
1221
|
};
|
|
1193
1222
|
l = attributes.length;
|
|
1194
|
-
/* Go backwards over all attributes; safely remove bad ones */
|
|
1195
1223
|
|
|
1224
|
+
/* Go backwards over all attributes; safely remove bad ones */
|
|
1196
1225
|
while (l--) {
|
|
1197
1226
|
attr = attributes[l];
|
|
1198
1227
|
var _attr = attr,
|
|
@@ -1200,73 +1229,83 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1200
1229
|
namespaceURI = _attr.namespaceURI;
|
|
1201
1230
|
value = name === 'value' ? attr.value : stringTrim(attr.value);
|
|
1202
1231
|
lcName = transformCaseFunc(name);
|
|
1203
|
-
/* Execute a hook if present */
|
|
1204
1232
|
|
|
1233
|
+
/* Execute a hook if present */
|
|
1205
1234
|
hookEvent.attrName = lcName;
|
|
1206
1235
|
hookEvent.attrValue = value;
|
|
1207
1236
|
hookEvent.keepAttr = true;
|
|
1208
1237
|
hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
|
|
1209
|
-
|
|
1210
1238
|
_executeHook('uponSanitizeAttribute', currentNode, hookEvent);
|
|
1211
1239
|
value = hookEvent.attrValue;
|
|
1212
|
-
/* Did the hooks approve of the attribute? */
|
|
1213
1240
|
|
|
1241
|
+
/* Did the hooks approve of the attribute? */
|
|
1214
1242
|
if (hookEvent.forceKeepAttr) {
|
|
1215
1243
|
continue;
|
|
1216
1244
|
}
|
|
1217
|
-
/* Remove attribute */
|
|
1218
1245
|
|
|
1246
|
+
/* Remove attribute */
|
|
1219
1247
|
_removeAttribute(name, currentNode);
|
|
1220
|
-
/* Did the hooks approve of the attribute? */
|
|
1221
1248
|
|
|
1249
|
+
/* Did the hooks approve of the attribute? */
|
|
1222
1250
|
if (!hookEvent.keepAttr) {
|
|
1223
1251
|
continue;
|
|
1224
1252
|
}
|
|
1225
|
-
/* Work around a security issue in jQuery 3.0 */
|
|
1226
1253
|
|
|
1227
|
-
|
|
1254
|
+
/* Work around a security issue in jQuery 3.0 */
|
|
1255
|
+
if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(/\/>/i, value)) {
|
|
1228
1256
|
_removeAttribute(name, currentNode);
|
|
1229
1257
|
continue;
|
|
1230
1258
|
}
|
|
1231
|
-
/* Sanitize attribute content to be template-safe */
|
|
1232
1259
|
|
|
1260
|
+
/* Sanitize attribute content to be template-safe */
|
|
1233
1261
|
if (SAFE_FOR_TEMPLATES) {
|
|
1234
1262
|
value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
|
|
1235
1263
|
value = stringReplace(value, ERB_EXPR$1, ' ');
|
|
1236
1264
|
value = stringReplace(value, TMPLIT_EXPR$1, ' ');
|
|
1237
1265
|
}
|
|
1238
|
-
/* Is `value` valid for this attribute? */
|
|
1239
1266
|
|
|
1267
|
+
/* Is `value` valid for this attribute? */
|
|
1240
1268
|
var lcTag = transformCaseFunc(currentNode.nodeName);
|
|
1241
1269
|
if (!_isValidAttribute(lcTag, lcName, value)) {
|
|
1242
1270
|
continue;
|
|
1243
1271
|
}
|
|
1272
|
+
|
|
1244
1273
|
/* Full DOM Clobbering protection via namespace isolation,
|
|
1245
1274
|
* Prefix id and name attributes with `user-content-`
|
|
1246
1275
|
*/
|
|
1247
|
-
|
|
1248
1276
|
if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
|
|
1249
1277
|
// Remove the attribute with this value
|
|
1250
|
-
_removeAttribute(name, currentNode);
|
|
1278
|
+
_removeAttribute(name, currentNode);
|
|
1251
1279
|
|
|
1280
|
+
// Prefix the value and later re-create the attribute with the sanitized value
|
|
1252
1281
|
value = SANITIZE_NAMED_PROPS_PREFIX + value;
|
|
1253
1282
|
}
|
|
1254
|
-
/* Handle attributes that require Trusted Types */
|
|
1255
1283
|
|
|
1284
|
+
/* Work around a security issue with comments inside attributes */
|
|
1285
|
+
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
|
|
1286
|
+
_removeAttribute(name, currentNode);
|
|
1287
|
+
continue;
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
/* Handle attributes that require Trusted Types */
|
|
1256
1291
|
if (trustedTypesPolicy && _typeof(trustedTypes) === 'object' && typeof trustedTypes.getAttributeType === 'function') {
|
|
1257
1292
|
if (namespaceURI) ;else {
|
|
1258
1293
|
switch (trustedTypes.getAttributeType(lcTag, lcName)) {
|
|
1259
1294
|
case 'TrustedHTML':
|
|
1260
|
-
|
|
1261
|
-
|
|
1295
|
+
{
|
|
1296
|
+
value = trustedTypesPolicy.createHTML(value);
|
|
1297
|
+
break;
|
|
1298
|
+
}
|
|
1262
1299
|
case 'TrustedScriptURL':
|
|
1263
|
-
|
|
1264
|
-
|
|
1300
|
+
{
|
|
1301
|
+
value = trustedTypesPolicy.createScriptURL(value);
|
|
1302
|
+
break;
|
|
1303
|
+
}
|
|
1265
1304
|
}
|
|
1266
1305
|
}
|
|
1267
1306
|
}
|
|
1268
|
-
/* Handle invalid data-* attribute set by try-catching it */
|
|
1269
1307
|
|
|
1308
|
+
/* Handle invalid data-* attribute set by try-catching it */
|
|
1270
1309
|
try {
|
|
1271
1310
|
if (namespaceURI) {
|
|
1272
1311
|
currentNode.setAttributeNS(namespaceURI, name, value);
|
|
@@ -1274,46 +1313,48 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1274
1313
|
/* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
|
|
1275
1314
|
currentNode.setAttribute(name, value);
|
|
1276
1315
|
}
|
|
1277
|
-
|
|
1316
|
+
if (_isClobbered(currentNode)) {
|
|
1317
|
+
_forceRemove(currentNode);
|
|
1318
|
+
} else {
|
|
1319
|
+
arrayPop(DOMPurify.removed);
|
|
1320
|
+
}
|
|
1278
1321
|
} catch (_) {}
|
|
1279
1322
|
}
|
|
1280
|
-
/* Execute a hook if present */
|
|
1281
1323
|
|
|
1324
|
+
/* Execute a hook if present */
|
|
1282
1325
|
_executeHook('afterSanitizeAttributes', currentNode, null);
|
|
1283
1326
|
};
|
|
1327
|
+
|
|
1284
1328
|
/**
|
|
1285
1329
|
* _sanitizeShadowDOM
|
|
1286
1330
|
*
|
|
1287
1331
|
* @param {DocumentFragment} fragment to iterate over recursively
|
|
1288
1332
|
*/
|
|
1289
|
-
|
|
1290
1333
|
var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {
|
|
1291
1334
|
var shadowNode;
|
|
1292
1335
|
var shadowIterator = _createIterator(fragment);
|
|
1293
|
-
/* Execute a hook if present */
|
|
1294
1336
|
|
|
1337
|
+
/* Execute a hook if present */
|
|
1295
1338
|
_executeHook('beforeSanitizeShadowDOM', fragment, null);
|
|
1296
1339
|
while (shadowNode = shadowIterator.nextNode()) {
|
|
1297
1340
|
/* Execute a hook if present */
|
|
1298
1341
|
_executeHook('uponSanitizeShadowNode', shadowNode, null);
|
|
1299
1342
|
/* Sanitize tags and elements */
|
|
1343
|
+
_sanitizeElements(shadowNode);
|
|
1300
1344
|
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
}
|
|
1304
|
-
/* Deep shadow DOM detected */
|
|
1345
|
+
/* Check attributes next */
|
|
1346
|
+
_sanitizeAttributes(shadowNode);
|
|
1305
1347
|
|
|
1348
|
+
/* Deep shadow DOM detected */
|
|
1306
1349
|
if (shadowNode.content instanceof DocumentFragment) {
|
|
1307
1350
|
_sanitizeShadowDOM(shadowNode.content);
|
|
1308
1351
|
}
|
|
1309
|
-
/* Check attributes, sanitize if necessary */
|
|
1310
|
-
|
|
1311
|
-
_sanitizeAttributes(shadowNode);
|
|
1312
1352
|
}
|
|
1313
|
-
/* Execute a hook if present */
|
|
1314
1353
|
|
|
1354
|
+
/* Execute a hook if present */
|
|
1315
1355
|
_executeHook('afterSanitizeShadowDOM', fragment, null);
|
|
1316
1356
|
};
|
|
1357
|
+
|
|
1317
1358
|
/**
|
|
1318
1359
|
* Sanitize
|
|
1319
1360
|
* Public method providing core sanitation functionality
|
|
@@ -1322,7 +1363,6 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1322
1363
|
* @param {Object} configuration object
|
|
1323
1364
|
*/
|
|
1324
1365
|
// eslint-disable-next-line complexity
|
|
1325
|
-
|
|
1326
1366
|
DOMPurify.sanitize = function (dirty) {
|
|
1327
1367
|
var cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
1328
1368
|
var body;
|
|
@@ -1333,26 +1373,24 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1333
1373
|
/* Make sure we have a string to sanitize.
|
|
1334
1374
|
DO NOT return early, as this will return the wrong type if
|
|
1335
1375
|
the user has requested a DOM object rather than a string */
|
|
1336
|
-
|
|
1337
1376
|
IS_EMPTY_INPUT = !dirty;
|
|
1338
1377
|
if (IS_EMPTY_INPUT) {
|
|
1339
1378
|
dirty = '<!-->';
|
|
1340
1379
|
}
|
|
1341
|
-
/* Stringify, in case dirty is an object */
|
|
1342
1380
|
|
|
1381
|
+
/* Stringify, in case dirty is an object */
|
|
1343
1382
|
if (typeof dirty !== 'string' && !_isNode(dirty)) {
|
|
1344
|
-
|
|
1345
|
-
if (typeof dirty.toString !== 'function') {
|
|
1346
|
-
throw typeErrorCreate('toString is not a function');
|
|
1347
|
-
} else {
|
|
1383
|
+
if (typeof dirty.toString === 'function') {
|
|
1348
1384
|
dirty = dirty.toString();
|
|
1349
1385
|
if (typeof dirty !== 'string') {
|
|
1350
1386
|
throw typeErrorCreate('dirty is not a string, aborting');
|
|
1351
1387
|
}
|
|
1388
|
+
} else {
|
|
1389
|
+
throw typeErrorCreate('toString is not a function');
|
|
1352
1390
|
}
|
|
1353
1391
|
}
|
|
1354
|
-
/* Check we can run. Otherwise fall back or ignore */
|
|
1355
1392
|
|
|
1393
|
+
/* Check we can run. Otherwise fall back or ignore */
|
|
1356
1394
|
if (!DOMPurify.isSupported) {
|
|
1357
1395
|
if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {
|
|
1358
1396
|
if (typeof dirty === 'string') {
|
|
@@ -1364,16 +1402,16 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1364
1402
|
}
|
|
1365
1403
|
return dirty;
|
|
1366
1404
|
}
|
|
1367
|
-
/* Assign config vars */
|
|
1368
1405
|
|
|
1406
|
+
/* Assign config vars */
|
|
1369
1407
|
if (!SET_CONFIG) {
|
|
1370
1408
|
_parseConfig(cfg);
|
|
1371
1409
|
}
|
|
1372
|
-
/* Clean up removed elements */
|
|
1373
1410
|
|
|
1411
|
+
/* Clean up removed elements */
|
|
1374
1412
|
DOMPurify.removed = [];
|
|
1375
|
-
/* Check if dirty is correctly typed for IN_PLACE */
|
|
1376
1413
|
|
|
1414
|
+
/* Check if dirty is correctly typed for IN_PLACE */
|
|
1377
1415
|
if (typeof dirty === 'string') {
|
|
1378
1416
|
IN_PLACE = false;
|
|
1379
1417
|
}
|
|
@@ -1406,53 +1444,51 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1406
1444
|
dirty.indexOf('<') === -1) {
|
|
1407
1445
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;
|
|
1408
1446
|
}
|
|
1409
|
-
/* Initialize the document to work on */
|
|
1410
1447
|
|
|
1448
|
+
/* Initialize the document to work on */
|
|
1411
1449
|
body = _initDocument(dirty);
|
|
1412
|
-
/* Check we have a DOM node from the data */
|
|
1413
1450
|
|
|
1451
|
+
/* Check we have a DOM node from the data */
|
|
1414
1452
|
if (!body) {
|
|
1415
1453
|
return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
|
|
1416
1454
|
}
|
|
1417
1455
|
}
|
|
1418
|
-
/* Remove first element node (ours) if FORCE_BODY is set */
|
|
1419
1456
|
|
|
1457
|
+
/* Remove first element node (ours) if FORCE_BODY is set */
|
|
1420
1458
|
if (body && FORCE_BODY) {
|
|
1421
1459
|
_forceRemove(body.firstChild);
|
|
1422
1460
|
}
|
|
1423
|
-
/* Get node iterator */
|
|
1424
1461
|
|
|
1462
|
+
/* Get node iterator */
|
|
1425
1463
|
var nodeIterator = _createIterator(IN_PLACE ? dirty : body);
|
|
1426
|
-
/* Now start iterating over the created document */
|
|
1427
1464
|
|
|
1465
|
+
/* Now start iterating over the created document */
|
|
1428
1466
|
while (currentNode = nodeIterator.nextNode()) {
|
|
1429
1467
|
/* Fix IE's strange behavior with manipulated textNodes #89 */
|
|
1430
1468
|
if (currentNode.nodeType === 3 && currentNode === oldNode) {
|
|
1431
1469
|
continue;
|
|
1432
1470
|
}
|
|
1471
|
+
|
|
1433
1472
|
/* Sanitize tags and elements */
|
|
1473
|
+
_sanitizeElements(currentNode);
|
|
1434
1474
|
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
}
|
|
1438
|
-
/* Shadow DOM detected, sanitize it */
|
|
1475
|
+
/* Check attributes next */
|
|
1476
|
+
_sanitizeAttributes(currentNode);
|
|
1439
1477
|
|
|
1478
|
+
/* Shadow DOM detected, sanitize it */
|
|
1440
1479
|
if (currentNode.content instanceof DocumentFragment) {
|
|
1441
1480
|
_sanitizeShadowDOM(currentNode.content);
|
|
1442
1481
|
}
|
|
1443
|
-
/* Check attributes, sanitize if necessary */
|
|
1444
|
-
|
|
1445
|
-
_sanitizeAttributes(currentNode);
|
|
1446
1482
|
oldNode = currentNode;
|
|
1447
1483
|
}
|
|
1448
1484
|
oldNode = null;
|
|
1449
|
-
/* If we sanitized `dirty` in-place, return it. */
|
|
1450
1485
|
|
|
1486
|
+
/* If we sanitized `dirty` in-place, return it. */
|
|
1451
1487
|
if (IN_PLACE) {
|
|
1452
1488
|
return dirty;
|
|
1453
1489
|
}
|
|
1454
|
-
/* Return sanitized string or DOM */
|
|
1455
1490
|
|
|
1491
|
+
/* Return sanitized string or DOM */
|
|
1456
1492
|
if (RETURN_DOM) {
|
|
1457
1493
|
if (RETURN_DOM_FRAGMENT) {
|
|
1458
1494
|
returnNode = createDocumentFragment.call(body.ownerDocument);
|
|
@@ -1463,7 +1499,7 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1463
1499
|
} else {
|
|
1464
1500
|
returnNode = body;
|
|
1465
1501
|
}
|
|
1466
|
-
if (ALLOWED_ATTR.shadowroot) {
|
|
1502
|
+
if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmod) {
|
|
1467
1503
|
/*
|
|
1468
1504
|
AdoptNode() is not used because internal state is not reset
|
|
1469
1505
|
(e.g. the past names map of a HTMLFormElement), this is safe
|
|
@@ -1476,13 +1512,13 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1476
1512
|
return returnNode;
|
|
1477
1513
|
}
|
|
1478
1514
|
var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
|
|
1479
|
-
/* Serialize doctype if allowed */
|
|
1480
1515
|
|
|
1516
|
+
/* Serialize doctype if allowed */
|
|
1481
1517
|
if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
|
|
1482
1518
|
serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
|
|
1483
1519
|
}
|
|
1484
|
-
/* Sanitize final string template-safe */
|
|
1485
1520
|
|
|
1521
|
+
/* Sanitize final string template-safe */
|
|
1486
1522
|
if (SAFE_FOR_TEMPLATES) {
|
|
1487
1523
|
serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$1, ' ');
|
|
1488
1524
|
serializedHTML = stringReplace(serializedHTML, ERB_EXPR$1, ' ');
|
|
@@ -1490,27 +1526,28 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1490
1526
|
}
|
|
1491
1527
|
return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;
|
|
1492
1528
|
};
|
|
1529
|
+
|
|
1493
1530
|
/**
|
|
1494
1531
|
* Public method to set the configuration once
|
|
1495
1532
|
* setConfig
|
|
1496
1533
|
*
|
|
1497
1534
|
* @param {Object} cfg configuration object
|
|
1498
1535
|
*/
|
|
1499
|
-
|
|
1500
1536
|
DOMPurify.setConfig = function (cfg) {
|
|
1501
1537
|
_parseConfig(cfg);
|
|
1502
1538
|
SET_CONFIG = true;
|
|
1503
1539
|
};
|
|
1540
|
+
|
|
1504
1541
|
/**
|
|
1505
1542
|
* Public method to remove the configuration
|
|
1506
1543
|
* clearConfig
|
|
1507
1544
|
*
|
|
1508
1545
|
*/
|
|
1509
|
-
|
|
1510
1546
|
DOMPurify.clearConfig = function () {
|
|
1511
1547
|
CONFIG = null;
|
|
1512
1548
|
SET_CONFIG = false;
|
|
1513
1549
|
};
|
|
1550
|
+
|
|
1514
1551
|
/**
|
|
1515
1552
|
* Public method to check if an attribute value is valid.
|
|
1516
1553
|
* Uses last set config, if any. Otherwise, uses config defaults.
|
|
@@ -1521,7 +1558,6 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1521
1558
|
* @param {string} value Attribute value.
|
|
1522
1559
|
* @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.
|
|
1523
1560
|
*/
|
|
1524
|
-
|
|
1525
1561
|
DOMPurify.isValidAttribute = function (tag, attr, value) {
|
|
1526
1562
|
/* Initialize shared config vars if necessary. */
|
|
1527
1563
|
if (!CONFIG) {
|
|
@@ -1531,6 +1567,7 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1531
1567
|
var lcName = transformCaseFunc(attr);
|
|
1532
1568
|
return _isValidAttribute(lcTag, lcName, value);
|
|
1533
1569
|
};
|
|
1570
|
+
|
|
1534
1571
|
/**
|
|
1535
1572
|
* AddHook
|
|
1536
1573
|
* Public method to add DOMPurify hooks
|
|
@@ -1538,7 +1575,6 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1538
1575
|
* @param {String} entryPoint entry point for the hook to add
|
|
1539
1576
|
* @param {Function} hookFunction function to execute
|
|
1540
1577
|
*/
|
|
1541
|
-
|
|
1542
1578
|
DOMPurify.addHook = function (entryPoint, hookFunction) {
|
|
1543
1579
|
if (typeof hookFunction !== 'function') {
|
|
1544
1580
|
return;
|
|
@@ -1546,6 +1582,7 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1546
1582
|
hooks[entryPoint] = hooks[entryPoint] || [];
|
|
1547
1583
|
arrayPush(hooks[entryPoint], hookFunction);
|
|
1548
1584
|
};
|
|
1585
|
+
|
|
1549
1586
|
/**
|
|
1550
1587
|
* RemoveHook
|
|
1551
1588
|
* Public method to remove a DOMPurify hook at a given entryPoint
|
|
@@ -1554,30 +1591,29 @@ define(['jquery', 'lodash', 'ui/component', 'ui/resource/selectable', 'ui/hider'
|
|
|
1554
1591
|
* @param {String} entryPoint entry point for the hook to remove
|
|
1555
1592
|
* @return {Function} removed(popped) hook
|
|
1556
1593
|
*/
|
|
1557
|
-
|
|
1558
1594
|
DOMPurify.removeHook = function (entryPoint) {
|
|
1559
1595
|
if (hooks[entryPoint]) {
|
|
1560
1596
|
return arrayPop(hooks[entryPoint]);
|
|
1561
1597
|
}
|
|
1562
1598
|
};
|
|
1599
|
+
|
|
1563
1600
|
/**
|
|
1564
1601
|
* RemoveHooks
|
|
1565
1602
|
* Public method to remove all DOMPurify hooks at a given entryPoint
|
|
1566
1603
|
*
|
|
1567
1604
|
* @param {String} entryPoint entry point for the hooks to remove
|
|
1568
1605
|
*/
|
|
1569
|
-
|
|
1570
1606
|
DOMPurify.removeHooks = function (entryPoint) {
|
|
1571
1607
|
if (hooks[entryPoint]) {
|
|
1572
1608
|
hooks[entryPoint] = [];
|
|
1573
1609
|
}
|
|
1574
1610
|
};
|
|
1611
|
+
|
|
1575
1612
|
/**
|
|
1576
1613
|
* RemoveAllHooks
|
|
1577
1614
|
* Public method to remove all DOMPurify hooks
|
|
1578
1615
|
*
|
|
1579
1616
|
*/
|
|
1580
|
-
|
|
1581
1617
|
DOMPurify.removeAllHooks = function () {
|
|
1582
1618
|
hooks = {};
|
|
1583
1619
|
};
|