Source code for kotti.sanitizers

""" For a high level introduction and available configuration options
see :ref:`sanitizers`.
"""
from typing import Dict
from typing import Union

from bleach import clean
from bleach_whitelist.bleach_whitelist import all_styles
from bleach_whitelist.bleach_whitelist import generally_xss_safe
from bleach_whitelist.bleach_whitelist import markdown_attrs
from bleach_whitelist.bleach_whitelist import markdown_tags
from bleach_whitelist.bleach_whitelist import print_attrs
from bleach_whitelist.bleach_whitelist import print_tags
from pyramid.config import Configurator
from pyramid.util import DottedNameResolver

from kotti import get_settings
from kotti.events import ObjectInsert
from kotti.events import ObjectUpdate
from kotti.events import objectevent_listeners


[docs]def sanitize(html: str, sanitizer: str) -> str: """ Sanitize HTML :param html: HTML to be sanitized :type html: basestring :param sanitizer: name of the sanitizer to use :type sanitizer: str :result: sanitized HTML :rtype: str """ sanitized = get_settings()["kotti.sanitizers"][sanitizer](html) return sanitized
[docs]def xss_protection(html: str) -> str: """ Sanitizer that removes tags that are not considered XSS safe. See ``bleach_whitelist.generally_xss_unsafe`` for a complete list of tags that are removed. Attributes and styles are left untouched. :param html: HTML to be sanitized :type html: basestring :result: sanitized HTML :rtype: str """ sanitized = clean( html, tags=generally_xss_safe, attributes=lambda self, key, value: True, styles=all_styles, strip=True, ) return sanitized
[docs]def minimal_html(html: str) -> str: """ Sanitizer that only leaves a basic set of tags and attributes. See ``bleach_whitelist.markdown_tags``, ``bleach_whitelist.print_tags``, ``bleach_whitelist.markdown_attrs``, ``bleach_whitelist.print_attrs`` for a complete list of tags and attributes that are allowed. All styles are completely removed. :param html: HTML to be sanitized :type html: basestring :result: sanitized HTML :rtype: str """ attributes = dict( zip( list(markdown_attrs.keys()) + list(print_attrs.keys()), list(markdown_attrs.values()) + list(print_attrs.values()), ) ) sanitized = clean( html, tags=markdown_tags + print_tags, attributes=attributes, styles=[], strip=True, ) return sanitized
[docs]def no_html(html: str) -> str: """ Sanitizer that removes **all** tags. :param html: HTML to be sanitized :type html: basestring :result: plain text :rtype: str """ sanitized = clean(html, tags=[], attributes={}, styles=[], strip=True) return sanitized
def _setup_sanitizers(settings: Dict[str, Union[str, bool]]) -> None: # step 1: resolve sanitizer functions and make ``kotti.sanitizers`` a # dictionary containing resolved functions if not isinstance(settings["kotti.sanitizers"], str): return sanitizers = {} for s in settings["kotti.sanitizers"].split(): name, dottedname = s.split(":") sanitizers[name.strip()] = DottedNameResolver().resolve(dottedname) settings["kotti.sanitizers"] = sanitizers def _setup_listeners(settings): # step 2: setup listeners for s in settings["kotti.sanitize_on_write"].split(): dotted, sanitizers = s.split(":") classname, attributename = dotted.rsplit(".", 1) _class = DottedNameResolver().resolve(classname) def _create_handler(attributename, sanitizers): def handler(event): value = getattr(event.object, attributename) for sanitizer_name in sanitizers.split(","): value = settings["kotti.sanitizers"][sanitizer_name](value) setattr(event.object, attributename, value) return handler objectevent_listeners[(ObjectInsert, _class)].append( _create_handler(attributename, sanitizers) ) objectevent_listeners[(ObjectUpdate, _class)].append( _create_handler(attributename, sanitizers) )
[docs]def includeme(config: Configurator) -> None: """ Pyramid includeme hook. :param config: app config :type config: :class:`pyramid.config.Configurator` """ _setup_sanitizers(config.registry.settings) _setup_listeners(config.registry.settings)