diff options
Diffstat (limited to 'src/hydrilla/proxy/policies/rule.py')
-rw-r--r-- | src/hydrilla/proxy/policies/rule.py | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/hydrilla/proxy/policies/rule.py b/src/hydrilla/proxy/policies/rule.py new file mode 100644 index 0000000..e318a7f --- /dev/null +++ b/src/hydrilla/proxy/policies/rule.py @@ -0,0 +1,122 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +# Policies for blocking and allowing JS in pages fetched with HTTP. +# +# This file is part of Hydrilla&Haketilo. +# +# Copyright (C) 2022 Wojtek Kosior +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +# +# I, Wojtek Kosior, thereby promise not to sue for violation of this +# file's license. Although I request that you do not make use of this +# code in a proprietary program, I am not going to enforce this in +# court. + +""" +..... +""" + +import dataclasses as dc +import typing as t + +from ...url_patterns import ParsedPattern +from .. import csp +from .. import state +from ..import http_messages +from . import base + + +class AllowPolicy(base.Policy): + priority = base.PolicyPriority._TWO + + +script_csp_directives = ('script-src', 'script-src-elem', 'script-src-attr') + +class BlockPolicy(base.Policy): + _process_response = base.MsgProcessOpt.MUST + + priority = base.PolicyPriority._TWO + + @property + def current_popup_settings(self) -> state.PopupSettings: + return self.haketilo_settings.default_popup_jsblocked + + def _csp_to_clear(self, http_info: http_messages.FullHTTPInfo) \ + -> t.Sequence[str]: + return script_csp_directives + + def _csp_to_add(self, http_info: http_messages.FullHTTPInfo) \ + -> t.Mapping[str, t.Sequence[str]]: + return dict((d, ["'none'"]) for d in script_csp_directives) + + +@dc.dataclass(frozen=True) +class RuleAllowPolicy(AllowPolicy): + pattern: ParsedPattern + + def make_info_page(self, http_info: http_messages.FullHTTPInfo) \ + -> t.Optional[str]: + template = self._get_info_template('js_rule_allowed_info.html.jinja') + return template.render( + url = http_info.request_info.url.orig_url, + pattern = self.pattern.orig_url + ) + + +@dc.dataclass(frozen=True) +class RuleBlockPolicy(BlockPolicy): + pattern: ParsedPattern + + def make_info_page(self, http_info: http_messages.FullHTTPInfo) \ + -> t.Optional[str]: + template = self._get_info_template('js_rule_blocked_info.html.jinja') + return template.render( + url = http_info.request_info.url.orig_url, + pattern = self.pattern.orig_url + ) + + +@dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc] +class RulePolicyFactory(base.PolicyFactory): + """....""" + pattern: ParsedPattern + + def __lt__(self, other: base.PolicyFactory) -> bool: + """....""" + if type(other) is not type(self): + return super().__lt__(other) + + assert isinstance(other, RulePolicyFactory) + + return self.pattern < other.pattern + + +@dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc] +class RuleBlockPolicyFactory(RulePolicyFactory): + """....""" + def make_policy(self, haketilo_state: state.HaketiloState) \ + -> RuleBlockPolicy: + """....""" + return RuleBlockPolicy(haketilo_state.get_settings(), self.pattern) + + +@dc.dataclass(frozen=True, unsafe_hash=True) # type: ignore[misc] +class RuleAllowPolicyFactory(RulePolicyFactory): + """....""" + def make_policy(self, haketilo_state: state.HaketiloState) \ + -> RuleAllowPolicy: + """....""" + return RuleAllowPolicy(haketilo_state.get_settings(), self.pattern) |