Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/werkzeug/datastructures/csp.py: 75%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

52 statements  

1from __future__ import annotations 

2 

3import collections.abc as cabc 

4import typing as t 

5 

6from .structures import CallbackDict 

7 

8 

9def csp_property(key: str) -> t.Any: 

10 """Return a new property object for a content security policy header. 

11 Useful if you want to add support for a csp extension in a 

12 subclass. 

13 """ 

14 return property( 

15 lambda x: x._get_value(key), 

16 lambda x, v: x._set_value(key, v), 

17 lambda x: x._del_value(key), 

18 f"accessor for {key!r}", 

19 ) 

20 

21 

22class ContentSecurityPolicy(CallbackDict[str, str]): 

23 """Subclass of a dict that stores values for a Content Security Policy 

24 header. It has accessors for all the level 3 policies. 

25 

26 Because the csp directives in the HTTP header use dashes the 

27 python descriptors use underscores for that. 

28 

29 To get a header of the :class:`ContentSecuirtyPolicy` object again 

30 you can convert the object into a string or call the 

31 :meth:`to_header` method. If you plan to subclass it and add your 

32 own items have a look at the sourcecode for that class. 

33 

34 .. versionadded:: 1.0.0 

35 Support for Content Security Policy headers was added. 

36 

37 """ 

38 

39 base_uri: str | None = csp_property("base-uri") 

40 child_src: str | None = csp_property("child-src") 

41 connect_src: str | None = csp_property("connect-src") 

42 default_src: str | None = csp_property("default-src") 

43 font_src: str | None = csp_property("font-src") 

44 form_action: str | None = csp_property("form-action") 

45 frame_ancestors: str | None = csp_property("frame-ancestors") 

46 frame_src: str | None = csp_property("frame-src") 

47 img_src: str | None = csp_property("img-src") 

48 manifest_src: str | None = csp_property("manifest-src") 

49 media_src: str | None = csp_property("media-src") 

50 navigate_to: str | None = csp_property("navigate-to") 

51 object_src: str | None = csp_property("object-src") 

52 prefetch_src: str | None = csp_property("prefetch-src") 

53 plugin_types: str | None = csp_property("plugin-types") 

54 report_to: str | None = csp_property("report-to") 

55 report_uri: str | None = csp_property("report-uri") 

56 sandbox: str | None = csp_property("sandbox") 

57 script_src: str | None = csp_property("script-src") 

58 script_src_attr: str | None = csp_property("script-src-attr") 

59 script_src_elem: str | None = csp_property("script-src-elem") 

60 style_src: str | None = csp_property("style-src") 

61 style_src_attr: str | None = csp_property("style-src-attr") 

62 style_src_elem: str | None = csp_property("style-src-elem") 

63 worker_src: str | None = csp_property("worker-src") 

64 

65 def __init__( 

66 self, 

67 values: cabc.Mapping[str, str] | cabc.Iterable[tuple[str, str]] | None = (), 

68 on_update: cabc.Callable[[ContentSecurityPolicy], None] | None = None, 

69 ) -> None: 

70 super().__init__(values, on_update) 

71 self.provided = values is not None 

72 

73 def _get_value(self, key: str) -> str | None: 

74 """Used internally by the accessor properties.""" 

75 return self.get(key) 

76 

77 def _set_value(self, key: str, value: str | None) -> None: 

78 """Used internally by the accessor properties.""" 

79 if value is None: 

80 self.pop(key, None) 

81 else: 

82 self[key] = value 

83 

84 def _del_value(self, key: str) -> None: 

85 """Used internally by the accessor properties.""" 

86 if key in self: 

87 del self[key] 

88 

89 def to_header(self) -> str: 

90 """Convert the stored values into a cache control header.""" 

91 from ..http import dump_csp_header 

92 

93 return dump_csp_header(self) 

94 

95 def __str__(self) -> str: 

96 return self.to_header() 

97 

98 def __repr__(self) -> str: 

99 kv_str = " ".join(f"{k}={v!r}" for k, v in sorted(self.items())) 

100 return f"<{type(self).__name__} {kv_str}>"