add: санитайзинг плейсхолдеров
This commit is contained in:
@@ -102,8 +102,7 @@ CHAR_PLACEHOLDER = '\uFFFC' # Уникальная строка-заполн
|
|||||||
CHAR_AMP_PLACEHOLDER = '\uFFFD' # Маркер-плейсхолдер для амперсанда (&), чтобы избежать его двойного кодирования в & при замене на мнемонику.
|
CHAR_AMP_PLACEHOLDER = '\uFFFD' # Маркер-плейсхолдер для амперсанда (&), чтобы избежать его двойного кодирования в & при замене на мнемонику.
|
||||||
CHAR_NODE_SEPARATOR = '\uFFFF' # Маркер границы текстовых узлов (Non-character).
|
CHAR_NODE_SEPARATOR = '\uFFFF' # Маркер границы текстовых узлов (Non-character).
|
||||||
|
|
||||||
# === КОНСТАНТЫ ДЛЯ САНИТИЗАЦИИ ===
|
# === ПЛЕЙСХОЛДЕРЫ (ДЛЯ САНИТАЙЗИНГА НА ХОДЕ) ===
|
||||||
# TODO: Их обработку (очистку) нужно добавить в модуль sanitization.py на входе.
|
|
||||||
CHARS_SYMBOLS_TO_BAN = frozenset([
|
CHARS_SYMBOLS_TO_BAN = frozenset([
|
||||||
CHAR_UNIT_SEPARATOR, CHAR_PLACEHOLDER, CHAR_AMP_PLACEHOLDER, CHAR_NODE_SEPARATOR
|
CHAR_UNIT_SEPARATOR, CHAR_PLACEHOLDER, CHAR_AMP_PLACEHOLDER, CHAR_NODE_SEPARATOR
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
import logging
|
import logging
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from .config import (SANITIZE_ALL_HTML, SANITIZE_ETPGRF, SANITIZE_NONE,
|
from .config import (SANITIZE_ALL_HTML, SANITIZE_ETPGRF, SANITIZE_NONE,
|
||||||
HANGING_PUNCTUATION_CLASSES, PROTECTED_HTML_TAGS,
|
PROTECTED_HTML_TAGS,
|
||||||
HANGING_PUNCTUATION_SYMBOLS_CLASSES,
|
HANGING_PUNCTUATION_SYMBOLS_CLASSES,
|
||||||
HANGING_PUNCTUATION_SPACE_CLASSES_FLAT)
|
HANGING_PUNCTUATION_SPACE_CLASSES_FLAT,
|
||||||
|
CHARS_SYMBOLS_TO_BAN)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ class SanitizerProcessor:
|
|||||||
"""
|
"""
|
||||||
if self.mode == SANITIZE_ETPGRF:
|
if self.mode == SANITIZE_ETPGRF:
|
||||||
if not self._etp_selector:
|
if not self._etp_selector:
|
||||||
|
self._strip_banned_chars_from_soup(soup)
|
||||||
return soup
|
return soup
|
||||||
|
|
||||||
# Используем CSS-селектор для быстрого поиска всех нужных элементов
|
# Используем CSS-селектор для быстрого поиска всех нужных элементов
|
||||||
@@ -60,6 +62,7 @@ class SanitizerProcessor:
|
|||||||
for span in spans_to_clean:
|
for span in spans_to_clean:
|
||||||
span.unwrap()
|
span.unwrap()
|
||||||
|
|
||||||
|
self._strip_banned_chars_from_soup(soup)
|
||||||
return soup
|
return soup
|
||||||
|
|
||||||
elif self.mode == SANITIZE_ALL_HTML:
|
elif self.mode == SANITIZE_ALL_HTML:
|
||||||
@@ -74,7 +77,31 @@ class SanitizerProcessor:
|
|||||||
|
|
||||||
# 2. Извлекаем чистый текст из оставшегося дерева.
|
# 2. Извлекаем чистый текст из оставшегося дерева.
|
||||||
# get_text() работает на уровне C (в lxml) и намного быстрее ручного обхода.
|
# get_text() работает на уровне C (в lxml) и намного быстрее ручного обхода.
|
||||||
return soup.get_text()
|
text = soup.get_text()
|
||||||
|
return self._strip_banned_chars_from_string(text)
|
||||||
|
|
||||||
# Если режим не задан, ничего не делаем
|
# Если режим не задан, ничего не делаем
|
||||||
return soup
|
return soup
|
||||||
|
|
||||||
|
def _strip_banned_chars_from_soup(self, soup: BeautifulSoup) -> None:
|
||||||
|
"""
|
||||||
|
Удаляет запрещенные символы из всего содержимого soup-объекта.
|
||||||
|
|
||||||
|
:param soup: Объект BeautifulSoup для обработки.
|
||||||
|
"""
|
||||||
|
for element in soup.find_all(string=True):
|
||||||
|
if isinstance(element, str):
|
||||||
|
new_string = self._strip_banned_chars_from_string(element)
|
||||||
|
element.replace_with(new_string)
|
||||||
|
|
||||||
|
def _strip_banned_chars_from_string(self, text: str) -> str:
|
||||||
|
"""
|
||||||
|
Удаляет запрещенные символы из строки.
|
||||||
|
|
||||||
|
:param text: Исходная строка.
|
||||||
|
:return: Строка без запрещенных символов.
|
||||||
|
"""
|
||||||
|
# Удаляем все символы, которые есть в CHARS_SYMBOLS_TO_BAN
|
||||||
|
for char in CHARS_SYMBOLS_TO_BAN:
|
||||||
|
text = text.replace(char, "")
|
||||||
|
return text
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from etpgrf.sanitizer import SanitizerProcessor
|
from etpgrf.sanitizer import SanitizerProcessor
|
||||||
from etpgrf.config import SANITIZE_NONE, SANITIZE_ETPGRF, SANITIZE_ALL_HTML
|
from etpgrf.config import SANITIZE_NONE, SANITIZE_ETPGRF, SANITIZE_ALL_HTML, CHARS_SYMBOLS_TO_BAN
|
||||||
|
|
||||||
|
|
||||||
def test_sanitizer_mode_none():
|
def test_sanitizer_mode_none():
|
||||||
@@ -84,3 +84,19 @@ def test_sanitizer_mode_etpgrf(case_id, description, html_input, expected_html):
|
|||||||
result_soup = processor.process(soup)
|
result_soup = processor.process(soup)
|
||||||
|
|
||||||
assert str(result_soup) == expected_html
|
assert str(result_soup) == expected_html
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("mode", [SANITIZE_ETPGRF, SANITIZE_ALL_HTML])
|
||||||
|
def test_sanitizer_strips_service_placeholders(mode):
|
||||||
|
"""
|
||||||
|
Проверяет, что в обоих режимах удаляются запрещенные символы (плейсхолдеры, используемые внутри типографа).
|
||||||
|
Это важно для защиты от потенциальных XSS-атак или других проблем с безопасностью, связанных с этими символами.
|
||||||
|
"""
|
||||||
|
placeholder = next(iter(CHARS_SYMBOLS_TO_BAN))
|
||||||
|
html_input = f'<p>Start{placeholder}End</p>'
|
||||||
|
soup = BeautifulSoup(html_input, 'html.parser')
|
||||||
|
processor = SanitizerProcessor(mode=mode)
|
||||||
|
result = processor.process(soup)
|
||||||
|
output = str(result) if isinstance(result, BeautifulSoup) else result
|
||||||
|
assert placeholder not in output
|
||||||
|
assert 'StartEnd' in output
|
||||||
|
|||||||
Reference in New Issue
Block a user