1from django.utils.html import mark_safe, format_html 2from django.utils.translation import gettext_lazy 3 4try: 5 import bleach 6 7 clean_html = lambda body: mark_safe(bleach.clean( 8 body, 9 tags=[ 10 'a', 11 'abbr', 12 'acronym', 13 'b', 14 'blockquote', 15 'br', 16 'caption', 17 'center', 18 'code', 19 'em', 20 'div', 21 'font', 22 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 23 'head', 24 'hr', 25 'i', 26 'img', 27 'label', 28 'li', 29 'ol', 30 'p', 31 'pre', 32 'span', 33 'strong', 34 'table', 'tbody', 'tfoot', 'td', 'th', 'thead', 'tr', 35 'u', 36 'ul', 37 ], 38 attributes={ 39 'a': ['class', 'href', 'id', 'style', 'target'], 40 'abbr': ['class', 'id', 'style'], 41 'acronym': ['class', 'id', 'style'], 42 'b': ['class', 'id', 'style'], 43 'blockquote': ['class', 'id', 'style'], 44 'br': ['class', 'id', 'style'], 45 'caption': ['class', 'id', 'style'], 46 'center': ['class', 'id', 'style'], 47 'code': ['class', 'id', 'style'], 48 'em': ['class', 'id', 'style'], 49 'div': ['class', 'id', 'style', 'align', 'dir'], 50 'font': ['class', 'id', 'style', 'color', 'face', 'size'], 51 'h1': ['class', 'id', 'style', 'align', 'dir'], 52 'h2': ['class', 'id', 'style', 'align', 'dir'], 53 'h3': ['class', 'id', 'style', 'align', 'dir'], 54 'h4': ['class', 'id', 'style', 'align', 'dir'], 55 'h5': ['class', 'id', 'style', 'align', 'dir'], 56 'h6': ['class', 'id', 'style', 'align', 'dir'], 57 'head': ['dir', 'lang'], 58 'hr': ['align', 'size', 'width'], 59 'i': ['class', 'id', 'style'], 60 'img': ['class', 'id', 'style', 'align', 'border', 'height', 'hspace', 'src', 'usemap', 'vspace', 'width'], 61 'label': ['class', 'id', 'style'], 62 'li': ['class', 'id', 'style', 'dir', 'type'], 63 'ol': ['class', 'id', 'style', 'dir', 'type'], 64 'p': ['class', 'id', 'style', 'align', 'dir'], 65 'pre': ['class', 'id', 'style'], 66 'span': ['class', 'id', 'style'], 67 'strong': ['class', 'id', 'style'], 68 'table': ['class', 'id', 'style', 'align', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'dir', 'frame', 'rules', 'width'], 69 'tbody': ['class', 'id', 'style'], 70 'tfoot': ['class', 'id', 'style'], 71 'td': ['class', 'id', 'style', 'abbr', 'align', 'bgcolor', 'colspan', 'dir', 'height', 'lang', 'rowspan', 'scope', 'style', 'valign', 'width'], 72 'th': ['class', 'id', 'style', 'abbr', 'align', 'background', 'bgcolor', 'colspan', 'dir', 'height', 'lang', 'scope', 'style', 'valign', 'width'], 73 'thead': ['class', 'id', 'style'], 74 'tr': ['class', 'id', 'style', 'align', 'bgcolor', 'dir', 'style', 'valign'], 75 'u': ['class', 'id', 'style'], 76 'ul': ['class', 'id', 'style', 'dir', 'type'], 77 }, 78 strip=True, 79 strip_comments=True, 80 styles=[ 81 'border', 'border-top', 'border-right', 'border-bottom', 'border-left', 82 'border-radius', 83 'box-shadow', 84 'height', 85 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left', 86 'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left', 87 'width', 88 'max-width', 89 'min-width', 90 'border-collapse', 91 'border-spacing', 92 'caption-side', 93 'empty-cells', 94 'table-layout', 95 'direction', 96 'font', 97 'font-family', 98 'font-style', 99 'font-variant', 100 'font-size', 101 'font-weight', 102 'letter-spacing', 103 'line-height', 104 'text-align', 105 'text-decoration', 106 'text-indent', 107 'text-overflow', 108 'text-shadow', 109 'text-transform', 110 'white-space', 111 'word-spacing', 112 'word-wrap', 113 'vertical-align', 114 'color', 115 'background', 116 'background-color', 117 'background-image', 118 'background-position', 119 'background-repeat', 120 'bottom', 121 'clear', 122 'cursor', 123 'display', 124 'float', 125 'left', 126 'opacity', 127 'outline', 128 'overflow', 129 'position', 130 'resize', 131 'right', 132 'top', 133 'visibility', 134 'z-index', 135 'list-style-position', 136 'list-style-tyle', 137 ], 138 )) 139except ImportError: 140 # if bleach is not installed, render HTML as escaped text to prevent XSS attacks 141 heading = gettext_lazy("Install 'bleach' to render HTML properly.") 142 clean_html = lambda body: format_html('<p><em>{heading}</em></p>\n<div>{body}</div>', 143 heading=heading, body=body) 144