diff options
author | Olivier Paroz <github@oparoz.com> | 2015-09-08 03:55:12 +0300 |
---|---|---|
committer | Olivier Paroz <github@oparoz.com> | 2015-09-24 11:23:45 +0300 |
commit | 011bf95bf03a7ea75672a399f8787df5d2aea37c (patch) | |
tree | 1be67904a1aec38d1a835332f1d394a80e8534ae /js | |
parent | 957419d7f0c6eb7417d34ce1bd245505c1326651 (diff) |
Customise DOMPurify to only allow certain HTML tags
Diffstat (limited to 'js')
-rw-r--r-- | js/galleryinfobox.js | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/js/galleryinfobox.js b/js/galleryinfobox.js index cb192cfb..d07c0614 100644 --- a/js/galleryinfobox.js +++ b/js/galleryinfobox.js @@ -10,6 +10,7 @@ this.infoContentContainer = $('.album-info-container'); this.infoContentSpinner = this.infoContentContainer.children('.album-info-loader'); this.infoContentElement = this.infoContentContainer.children('.album-info-content'); + this._initCustomSanitizer(); }; InfoBox.prototype = { @@ -17,6 +18,7 @@ infoContentSpinner: null, infoContentElement: null, albumInfo: null, + allowedTags: null, /** * Shows an information box to the user @@ -66,7 +68,9 @@ content = DOMPurify.sanitize(marked(content, { gfm: false, sanitize: true - })); + }), { + ALLOWED_TAGS: this.allowedTags + }); } catch (exception) { content = t('gallery', 'Could not load the description: ' + exception.message); @@ -107,7 +111,9 @@ copyright = DOMPurify.sanitize(marked(this.albumInfo.copyright, { gfm: false, sanitize: true - })); + }), { + ALLOWED_TAGS: this.allowedTags + }); } catch (exception) { copyright = t('gallery', @@ -121,6 +127,7 @@ this._addCopyrightLink(copyright); } else { this.infoContentElement.append(copyright); + this.infoContentElement.find('a').attr("target", "_blank"); } } }, @@ -145,6 +152,54 @@ target: "_blank" }); this.infoContentElement.append(copyrightLink); + }, + + /** + * Adds custom tags and rules to DomPurify + * + * @link https://github.com/cure53/DOMPurify/blob/master/demos/hooks-scheme-whitelist.html + * @private + */ + _initCustomSanitizer: function () { + this.allowedTags = + ['p', 'b', 'em', 'i', 'pre', 'sup', 'sub', 'strong', 'strike', 'br', 'hr', + 'h1', 'h2', 'h3', 'li', 'ul', 'ol', 'a', 'img', 'blockquote', 'code' + ]; + + // allowed URI schemes + var whitelist = ['http', 'https']; + + // build fitting regex + var regex = new RegExp('^(' + whitelist.join('|') + '):', 'gim'); + + // Add a hook to enforce URI scheme whitelist + DOMPurify.addHook('afterSanitizeAttributes', function (node) { + + // build an anchor to map URLs to + var anchor = document.createElement('a'); + + // check all href attributes for validity + if (node.hasAttribute('href')) { + anchor.href = node.getAttribute('href'); + if (anchor.protocol && !anchor.protocol.match(regex)) { + node.removeAttribute('href'); + } + } + // check all action attributes for validity + if (node.hasAttribute('action')) { + anchor.href = node.getAttribute('action'); + if (anchor.protocol && !anchor.protocol.match(regex)) { + node.removeAttribute('action'); + } + } + // check all xlink:href attributes for validity + if (node.hasAttribute('xlink:href')) { + anchor.href = node.getAttribute('xlink:href'); + if (anchor.protocol && !anchor.protocol.match(regex)) { + node.removeAttribute('xlink:href'); + } + } + }); } }; |