""" Saneado del HTML de los posts del foro (el editor del cliente puede enviar HTML). El proyecto original guardaba el HTML sin sanear y lo renderizaba con |raw (XSS almacenado). Aquí lo saneamos con nh3 (allowlist) al guardar, de modo que la plantilla puede renderizarlo con |safe sin riesgo. """ import nh3 # Etiquetas permitidas (formato básico de foro) _ALLOWED_TAGS = { "p", "br", "hr", "span", "div", "strong", "b", "em", "i", "u", "s", "strike", "sub", "sup", "ul", "ol", "li", "blockquote", "code", "pre", "h1", "h2", "h3", "h4", "h5", "h6", "a", "img", "table", "thead", "tbody", "tr", "th", "td", } _ALLOWED_ATTRIBUTES = { "a": {"href", "title", "target"}, "img": {"src", "alt", "title", "width", "height"}, "span": {"style"}, "div": {"style"}, "td": {"colspan", "rowspan"}, "th": {"colspan", "rowspan"}, } # Solo esquemas de URL seguros _ALLOWED_URL_SCHEMES = {"http", "https", "mailto"} def clean_post_html(html): """Devuelve el HTML saneado y seguro para renderizar con |safe.""" if not html: return "" return nh3.clean( html, tags=_ALLOWED_TAGS, attributes=_ALLOWED_ATTRIBUTES, url_schemes=_ALLOWED_URL_SCHEMES, link_rel="noopener noreferrer nofollow", ) def plain_length(html): """Longitud del texto plano (sin etiquetas), para validar longitud mínima.""" if not html: return 0 text = nh3.clean(html, tags=set(), attributes={}) return len(text.strip())