105 lines
2.5 KiB
Python
105 lines
2.5 KiB
Python
|
import tinycss2
|
||
|
|
||
|
|
||
|
ALLOWED_CSS_PROPERTIES = frozenset(
|
||
|
(
|
||
|
"azimuth",
|
||
|
"background-color",
|
||
|
"border-bottom-color",
|
||
|
"border-collapse",
|
||
|
"border-color",
|
||
|
"border-left-color",
|
||
|
"border-right-color",
|
||
|
"border-top-color",
|
||
|
"clear",
|
||
|
"color",
|
||
|
"cursor",
|
||
|
"direction",
|
||
|
"display",
|
||
|
"elevation",
|
||
|
"float",
|
||
|
"font",
|
||
|
"font-family",
|
||
|
"font-size",
|
||
|
"font-style",
|
||
|
"font-variant",
|
||
|
"font-weight",
|
||
|
"height",
|
||
|
"letter-spacing",
|
||
|
"line-height",
|
||
|
"overflow",
|
||
|
"pause",
|
||
|
"pause-after",
|
||
|
"pause-before",
|
||
|
"pitch",
|
||
|
"pitch-range",
|
||
|
"richness",
|
||
|
"speak",
|
||
|
"speak-header",
|
||
|
"speak-numeral",
|
||
|
"speak-punctuation",
|
||
|
"speech-rate",
|
||
|
"stress",
|
||
|
"text-align",
|
||
|
"text-decoration",
|
||
|
"text-indent",
|
||
|
"unicode-bidi",
|
||
|
"vertical-align",
|
||
|
"voice-family",
|
||
|
"volume",
|
||
|
"white-space",
|
||
|
"width",
|
||
|
)
|
||
|
)
|
||
|
|
||
|
|
||
|
ALLOWED_SVG_PROPERTIES = frozenset(
|
||
|
(
|
||
|
"fill",
|
||
|
"fill-opacity",
|
||
|
"fill-rule",
|
||
|
"stroke",
|
||
|
"stroke-width",
|
||
|
"stroke-linecap",
|
||
|
"stroke-linejoin",
|
||
|
"stroke-opacity",
|
||
|
)
|
||
|
)
|
||
|
|
||
|
|
||
|
class CSSSanitizer:
|
||
|
def __init__(
|
||
|
self,
|
||
|
allowed_css_properties=ALLOWED_CSS_PROPERTIES,
|
||
|
allowed_svg_properties=ALLOWED_SVG_PROPERTIES,
|
||
|
):
|
||
|
self.allowed_css_properties = allowed_css_properties
|
||
|
self.allowed_svg_properties = allowed_svg_properties
|
||
|
|
||
|
def sanitize_css(self, style):
|
||
|
"""Sanitizes css in style tags"""
|
||
|
parsed = tinycss2.parse_declaration_list(style)
|
||
|
|
||
|
if not parsed:
|
||
|
return ""
|
||
|
|
||
|
new_tokens = []
|
||
|
for token in parsed:
|
||
|
if token.type == "declaration":
|
||
|
if (
|
||
|
token.lower_name in self.allowed_css_properties
|
||
|
or token.lower_name in self.allowed_svg_properties
|
||
|
):
|
||
|
new_tokens.append(token)
|
||
|
elif token.type in ("comment", "whitespace"):
|
||
|
if new_tokens and new_tokens[-1].type != token.type:
|
||
|
new_tokens.append(token)
|
||
|
|
||
|
# NOTE(willkg): We currently don't handle AtRule or ParseError and
|
||
|
# so both get silently thrown out
|
||
|
|
||
|
if not new_tokens:
|
||
|
return ""
|
||
|
|
||
|
return tinycss2.serialize(new_tokens).strip()
|