diff --git a/uncoder-core/app/translator/core/str_value_manager.py b/uncoder-core/app/translator/core/str_value_manager.py index 5ee02312..1151d7a3 100644 --- a/uncoder-core/app/translator/core/str_value_manager.py +++ b/uncoder-core/app/translator/core/str_value_manager.py @@ -182,7 +182,11 @@ class StrValueManager: container_spec_symbols_map: ClassVar[dict[type[BaseSpecSymbol], str]] = CONTAINER_SPEC_SYMBOLS_MAP @staticmethod - def from_str_to_container(value: str) -> StrValue: + def from_str_to_container( + value: str, + value_type: str = ValueType.value, # noqa: ARG004 + escape_symbol: Optional[str] = None, # noqa: ARG004 + ) -> StrValue: return StrValue(value=value, split_value=[value]) def from_re_str_to_container(self, value: str) -> StrValue: diff --git a/uncoder-core/app/translator/core/tokenizer.py b/uncoder-core/app/translator/core/tokenizer.py index 5273829c..9a963473 100644 --- a/uncoder-core/app/translator/core/tokenizer.py +++ b/uncoder-core/app/translator/core/tokenizer.py @@ -162,8 +162,7 @@ def search_multi_value( def _get_field_value_match(self, query: str, operator: str, field_name: str, value_pattern: str) -> re.Match: field_value_pattern = self.get_field_value_pattern(operator, field_name, value_pattern) - field_value_regex = re.compile(field_value_pattern, re.IGNORECASE) - field_value_match = re.match(field_value_regex, query) + field_value_match = re.match(field_value_pattern, query, re.IGNORECASE) if field_value_match is None: raise TokenizerGeneralException(error=f"Value couldn't be found in query part: {query}") diff --git a/uncoder-core/app/translator/platforms/anomali/renders/anomali.py b/uncoder-core/app/translator/platforms/anomali/renders/anomali.py index 1da26ab7..6f9e89f6 100644 --- a/uncoder-core/app/translator/platforms/anomali/renders/anomali.py +++ b/uncoder-core/app/translator/platforms/anomali/renders/anomali.py @@ -17,65 +17,37 @@ ----------------------------------------------------------------- """ from app.translator.const import DEFAULT_VALUE_TYPE -from app.translator.core.custom_types.values import ValueType from app.translator.core.models.platform_details import PlatformDetails -from app.translator.core.render import BaseFieldValueRender, PlatformQueryRender +from app.translator.core.render import PlatformQueryRender from app.translator.managers import render_manager from app.translator.platforms.anomali.const import anomali_query_details from app.translator.platforms.anomali.mapping import AnomaliMappings, anomali_query_mappings -from app.translator.platforms.base.sql.str_value_manager import sql_str_value_manager +from app.translator.platforms.base.sql.renders.sql import SqlFieldValueRender -class AnomaliFieldValueRender(BaseFieldValueRender): +class AnomaliFieldValueRender(SqlFieldValueRender): details: PlatformDetails = anomali_query_details - str_value_manager = sql_str_value_manager - - @staticmethod - def _wrap_str_value(value: str) -> str: - return f"'{value}'" - - def equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: - if isinstance(value, list): - return f"({self.or_token.join([self.equal_modifier(field=field, value=v) for v in value])})" - return f"{field} = {self._pre_process_value(field, value, wrap_str=True)}" - - def not_equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: - if isinstance(value, list): - return f"({self.or_token.join([self.not_equal_modifier(field=field, value=v) for v in value])})" - return f"{field} != {self._pre_process_value(field, value, wrap_str=True)}" - - def less_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: - return f"{field} < {self._pre_process_value(field, value, wrap_str=True)}" - - def less_or_equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: - return f"{field} <= {self._pre_process_value(field, value, wrap_str=True)}" - - def greater_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: - return f"{field} > {self._pre_process_value(field, value, wrap_str=True)}" - - def greater_or_equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: - return f"{field} >= {self._pre_process_value(field, value, wrap_str=True)}" def contains_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: if isinstance(value, list): return f"({self.or_token.join(self.contains_modifier(field=field, value=v) for v in value)})" - return f"{field} like '%{self._pre_process_value(field, value)}%'" + + value = f"'%{self._pre_process_value(field, value)}%'" + return f"{field} like {value}" def endswith_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: if isinstance(value, list): return f"({self.or_token.join(self.endswith_modifier(field=field, value=v) for v in value)})" - return f"{field} like '%{self._pre_process_value(field, value)}'" + + value = f"'%{self._pre_process_value(field, value)}'" + return f"{field} like {value}" def startswith_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: if isinstance(value, list): return f"({self.or_token.join(self.startswith_modifier(field=field, value=v) for v in value)})" - return f"{field} like '{self._pre_process_value(field, value)}%'" - def regex_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: - if isinstance(value, list): - return f"({self.or_token.join(self.regex_modifier(field=field, value=v) for v in value)})" - regex_str = self._pre_process_value(field, value, value_type=ValueType.regex_value, wrap_str=True) - return f"regexp_like({field}, {regex_str})" + value = f"'{self._pre_process_value(field, value)}%'" + return f"{field} like {value}" def keywords(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: return f'message contains "{self._pre_process_value(field, value)}"' diff --git a/uncoder-core/app/translator/platforms/base/aql/str_value_manager.py b/uncoder-core/app/translator/platforms/base/aql/str_value_manager.py index 6c2a071b..2f13931b 100644 --- a/uncoder-core/app/translator/platforms/base/aql/str_value_manager.py +++ b/uncoder-core/app/translator/platforms/base/aql/str_value_manager.py @@ -18,7 +18,7 @@ """ import copy -from typing import ClassVar +from typing import ClassVar, Optional from app.translator.core.custom_types.values import ValueType from app.translator.core.str_value_manager import ( @@ -55,7 +55,12 @@ class AQLStrValueManager(StrValueManager): "%": UnboundLenWildCard, } - def from_str_to_container(self, value: str) -> StrValue: + def from_str_to_container( + self, + value: str, + value_type: str = ValueType.value, # noqa: ARG002 + escape_symbol: Optional[str] = None, # noqa: ARG002 + ) -> StrValue: split = [] prev_char = None for char in value: diff --git a/uncoder-core/app/translator/platforms/base/lucene/str_value_manager.py b/uncoder-core/app/translator/platforms/base/lucene/str_value_manager.py index 9eb8e6bc..bad77b6f 100644 --- a/uncoder-core/app/translator/platforms/base/lucene/str_value_manager.py +++ b/uncoder-core/app/translator/platforms/base/lucene/str_value_manager.py @@ -17,8 +17,9 @@ ----------------------------------------------------------------- """ -from typing import ClassVar +from typing import ClassVar, Optional +from app.translator.core.custom_types.values import ValueType from app.translator.core.str_value_manager import ( BaseSpecSymbol, ReAnySymbol, @@ -68,7 +69,12 @@ class LuceneStrValueManager(StrValueManager): } re_str_spec_symbols_map = RE_STR_SPEC_SYMBOLS_MAP - def from_str_to_container(self, value: str) -> StrValue: + def from_str_to_container( + self, + value: str, + value_type: str = ValueType.value, # noqa: ARG002 + escape_symbol: Optional[str] = None, # noqa: ARG002 + ) -> StrValue: split = [] prev_char = None for char in value: diff --git a/uncoder-core/app/translator/platforms/base/spl/renders/spl.py b/uncoder-core/app/translator/platforms/base/spl/renders/spl.py index c8dffa70..c3c36675 100644 --- a/uncoder-core/app/translator/platforms/base/spl/renders/spl.py +++ b/uncoder-core/app/translator/platforms/base/spl/renders/spl.py @@ -34,7 +34,12 @@ def _wrap_str_value(value: str) -> str: return f'"{value}"' def _pre_process_value( - self, field: str, value: Union[int, str, StrValue], value_type: str = ValueType.value, wrap_str: bool = False + self, + field: str, + value: Union[bool, int, str, StrValue], + value_type: str = ValueType.value, + wrap_str: bool = False, + wrap_int: bool = False, # noqa: ARG002 ) -> Union[int, str]: value = super()._pre_process_value(field, value, value_type=value_type, wrap_str=wrap_str) return self._wrap_str_value(str(value)) if not isinstance(value, str) else value diff --git a/uncoder-core/app/translator/platforms/base/spl/str_value_manager.py b/uncoder-core/app/translator/platforms/base/spl/str_value_manager.py index 84ebaab7..ef638d6c 100644 --- a/uncoder-core/app/translator/platforms/base/spl/str_value_manager.py +++ b/uncoder-core/app/translator/platforms/base/spl/str_value_manager.py @@ -16,8 +16,9 @@ limitations under the License. ----------------------------------------------------------------- """ -from typing import ClassVar +from typing import ClassVar, Optional +from app.translator.core.custom_types.values import ValueType from app.translator.core.str_value_manager import BaseSpecSymbol, StrValue, StrValueManager, UnboundLenWildCard from app.translator.platforms.base.spl.escape_manager import spl_escape_manager @@ -26,7 +27,12 @@ class SplStrValueManager(StrValueManager): escape_manager = spl_escape_manager str_spec_symbols_map: ClassVar[dict[str, type[BaseSpecSymbol]]] = {"*": UnboundLenWildCard} - def from_str_to_container(self, value: str) -> StrValue: + def from_str_to_container( + self, + value: str, + value_type: str = ValueType.value, # noqa: ARG002 + escape_symbol: Optional[str] = None, # noqa: ARG002 + ) -> StrValue: split = [] prev_char = None for char in value: diff --git a/uncoder-core/app/translator/platforms/base/sql/custom_types/__init__.py b/uncoder-core/app/translator/platforms/base/sql/custom_types/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/uncoder-core/app/translator/platforms/base/sql/custom_types/values.py b/uncoder-core/app/translator/platforms/base/sql/custom_types/values.py new file mode 100644 index 00000000..4edc6215 --- /dev/null +++ b/uncoder-core/app/translator/platforms/base/sql/custom_types/values.py @@ -0,0 +1,5 @@ +from app.translator.core.custom_types.values import ValueType + + +class SQLValueType(ValueType): + like_value = "like_value" diff --git a/uncoder-core/app/translator/platforms/base/sql/escape_manager.py b/uncoder-core/app/translator/platforms/base/sql/escape_manager.py index 8e5be92a..e542d898 100644 --- a/uncoder-core/app/translator/platforms/base/sql/escape_manager.py +++ b/uncoder-core/app/translator/platforms/base/sql/escape_manager.py @@ -1,14 +1,15 @@ from typing import ClassVar -from app.translator.core.custom_types.values import ValueType from app.translator.core.escape_manager import EscapeManager from app.translator.core.models.escape_details import EscapeDetails +from app.translator.platforms.base.sql.custom_types.values import SQLValueType class SQLEscapeManager(EscapeManager): escape_map: ClassVar[dict[str, list[EscapeDetails]]] = { - ValueType.value: [EscapeDetails(pattern=r"(')", escape_symbols=r"'\1")], - ValueType.regex_value: [ + SQLValueType.value: [EscapeDetails(pattern=r"(')", escape_symbols=r"'\1")], + SQLValueType.like_value: [EscapeDetails(pattern=r"(['%_\\])", escape_symbols=r"\\\1")], + SQLValueType.regex_value: [ EscapeDetails(pattern=r"([$^*+()\[\]{}|.?\-\\])", escape_symbols=r"\\\1"), EscapeDetails(pattern=r"(')", escape_symbols=r"'\1"), ], diff --git a/uncoder-core/app/translator/platforms/base/sql/renders/sql.py b/uncoder-core/app/translator/platforms/base/sql/renders/sql.py index 9426c0cc..e7178922 100644 --- a/uncoder-core/app/translator/platforms/base/sql/renders/sql.py +++ b/uncoder-core/app/translator/platforms/base/sql/renders/sql.py @@ -17,55 +17,69 @@ ----------------------------------------------------------------- """ -from typing import Union - from app.translator.const import DEFAULT_VALUE_TYPE +from app.translator.core.custom_types.values import ValueType from app.translator.core.mapping import LogSourceSignature from app.translator.core.render import BaseFieldValueRender, PlatformQueryRender +from app.translator.platforms.base.sql.custom_types.values import SQLValueType +from app.translator.platforms.base.sql.str_value_manager import sql_str_value_manager class SqlFieldValueRender(BaseFieldValueRender): + str_value_manager = sql_str_value_manager + + @staticmethod + def _wrap_str_value(value: str) -> str: + return f"'{value}'" + def equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: if isinstance(value, list): return f"({self.or_token.join([self.equal_modifier(field=field, value=v) for v in value])})" - return f"{field} = '{value}'" + return f"{field} = {self._pre_process_value(field, value, wrap_str=True)}" - def less_modifier(self, field: str, value: Union[int, str]) -> str: - return f"{field} < '{value}'" + def not_equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: + if isinstance(value, list): + return f"({self.or_token.join([self.not_equal_modifier(field=field, value=v) for v in value])})" + return f"{field} != {self._pre_process_value(field, value, wrap_str=True)}" - def less_or_equal_modifier(self, field: str, value: Union[int, str]) -> str: - return f"{field} <= '{value}'" + def less_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: + return f"{field} < {self._pre_process_value(field, value, wrap_str=True)}" - def greater_modifier(self, field: str, value: Union[int, str]) -> str: - return f"{field} > '{value}'" + def less_or_equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: + return f"{field} <= {self._pre_process_value(field, value, wrap_str=True)}" - def greater_or_equal_modifier(self, field: str, value: Union[int, str]) -> str: - return f"{field} >= '{value}'" + def greater_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: + return f"{field} > {self._pre_process_value(field, value, wrap_str=True)}" - def not_equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: - if isinstance(value, list): - return f"({self.or_token.join([self.not_equal_modifier(field=field, value=v) for v in value])})" - return f"{field} != '{value}'" + def greater_or_equal_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: + return f"{field} >= {self._pre_process_value(field, value, wrap_str=True)}" def contains_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: if isinstance(value, list): return f"({self.or_token.join(self.contains_modifier(field=field, value=v) for v in value)})" - return f"{field} ILIKE '%{value}%' ESCAPE '\\'" + + value = f"'%{self._pre_process_value(field, value, value_type=SQLValueType.like_value)}%' escape '\\'" + return f"{field} like {value}" def endswith_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: if isinstance(value, list): return f"({self.or_token.join(self.endswith_modifier(field=field, value=v) for v in value)})" - return f"{field} ILIKE '%{value}' ESCAPE '\\'" + + value = f"'%{self._pre_process_value(field, value, value_type=SQLValueType.like_value)}' escape '\\'" + return f"{field} like {value}" def startswith_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: if isinstance(value, list): return f"({self.or_token.join(self.startswith_modifier(field=field, value=v) for v in value)})" - return f"{field} ILIKE '{value}%' ESCAPE '\\'" + + value = f"'{self._pre_process_value(field, value, value_type=SQLValueType.like_value)}%' escape '\\'" + return f"{field} like {value}" def regex_modifier(self, field: str, value: DEFAULT_VALUE_TYPE) -> str: if isinstance(value, list): return f"({self.or_token.join(self.regex_modifier(field=field, value=v) for v in value)})" - return f"{field} ILIKE '{value}' ESCAPE '\\'" + regex_str = self._pre_process_value(field, value, value_type=ValueType.regex_value, wrap_str=True) + return f"regexp_like({field}, {regex_str})" class SqlQueryRender(PlatformQueryRender): diff --git a/uncoder-core/app/translator/platforms/base/sql/str_value_manager.py b/uncoder-core/app/translator/platforms/base/sql/str_value_manager.py index 0c2f03ba..5f47b8be 100644 --- a/uncoder-core/app/translator/platforms/base/sql/str_value_manager.py +++ b/uncoder-core/app/translator/platforms/base/sql/str_value_manager.py @@ -18,9 +18,8 @@ """ import copy -from typing import ClassVar +from typing import ClassVar, Optional -from app.translator.core.custom_types.values import ValueType from app.translator.core.str_value_manager import ( CONTAINER_SPEC_SYMBOLS_MAP, RE_STR_SPEC_SYMBOLS_MAP, @@ -34,6 +33,7 @@ StrValueManager, UnboundLenWildCard, ) +from app.translator.platforms.base.sql.custom_types.values import SQLValueType from app.translator.platforms.base.sql.escape_manager import sql_escape_manager SQL_CONTAINER_SPEC_SYMBOLS_MAP = copy.copy(CONTAINER_SPEC_SYMBOLS_MAP) @@ -55,18 +55,30 @@ class SQLStrValueManager(StrValueManager): "%": UnboundLenWildCard, } - def from_str_to_container(self, value: str) -> StrValue: + def from_str_to_container( + self, value: str, value_type: str = SQLValueType.value, escape_symbol: Optional[str] = None + ) -> StrValue: split = [] prev_char = None for char in value: - if char in self.str_spec_symbols_map: - split.append(self.str_spec_symbols_map[char]()) - else: - if char == "'": - if prev_char == "'": - split.append(char) - prev_char = char + if escape_symbol and char == escape_symbol: + if prev_char == escape_symbol: + split.append(char) + prev_char = None + continue + prev_char = char + continue + if not escape_symbol and char == "'": + if prev_char == "'": + split.append(char) + prev_char = None continue + elif char in ("'", "_", "%") and value_type == SQLValueType.like_value: + if escape_symbol and prev_char == escape_symbol: + split.append(char) + elif char in self.str_spec_symbols_map: + split.append(self.str_spec_symbols_map[char]()) + else: split.append(char) prev_char = char @@ -77,13 +89,13 @@ def from_re_str_to_container(self, value: str) -> StrValue: value = value.replace("''", "'") return super().from_re_str_to_container(value) - def from_container_to_str(self, container: StrValue, value_type: str = ValueType.value) -> str: + def from_container_to_str(self, container: StrValue, value_type: str = SQLValueType.value) -> str: result = "" for el in container.split_value: if isinstance(el, str): result += self.escape_manager.escape(el, value_type) elif isinstance(el, BaseSpecSymbol): - if value_type == ValueType.regex_value: + if value_type == SQLValueType.regex_value: if isinstance(el, SingleSymbolWildCard): result += "." continue diff --git a/uncoder-core/app/translator/platforms/base/sql/tokenizer.py b/uncoder-core/app/translator/platforms/base/sql/tokenizer.py index 8292ca14..fe92c8f6 100644 --- a/uncoder-core/app/translator/platforms/base/sql/tokenizer.py +++ b/uncoder-core/app/translator/platforms/base/sql/tokenizer.py @@ -22,10 +22,16 @@ from app.translator.core.custom_types.tokens import OperatorType from app.translator.core.custom_types.values import ValueType from app.translator.core.models.query_tokens.field_value import FieldValue +from app.translator.core.models.query_tokens.function_value import FunctionValue from app.translator.core.models.query_tokens.identifier import Identifier +from app.translator.core.models.query_tokens.keyword import Keyword from app.translator.core.tokenizer import QueryTokenizer +from app.translator.platforms.base.sql.custom_types.values import SQLValueType +from app.translator.platforms.base.sql.str_value_manager import sql_str_value_manager from app.translator.tools.utils import get_match_group +_ESCAPE_SYMBOL_GROUP_NAME = "escape_symbol" + class SqlTokenizer(QueryTokenizer): single_value_operators_map: ClassVar[dict[str, str]] = { @@ -43,14 +49,15 @@ class SqlTokenizer(QueryTokenizer): field_pattern = r'(?P"[a-zA-Z\._\-\s]+"|[a-zA-Z\._\-]+)' num_value_pattern = rf"(?P<{ValueType.number_value}>\d+(?:\.\d+)*)\s*" bool_value_pattern = rf"(?P<{ValueType.bool_value}>true|false)\s*" - single_quotes_value_pattern = ( - rf"""'(?P<{ValueType.single_quotes_value}>(?:[:a-zA-Z\*0-9=+%#\-\/\\,_".$&^@!\(\)\{{\}}\s]|'')*)'""" - ) + single_quotes_value_pattern = rf"""'(?P<{ValueType.single_quotes_value}>(?:[:a-zA-Z\*0-9=+%#\-\/,_".$&^@!\(\)\{{\}}\s]|''|\\\'|\\\%|\\\_|\\\\|\\)*)'(?:\s+escape\s+'(?P<{_ESCAPE_SYMBOL_GROUP_NAME}>.)')?""" # noqa: E501 _value_pattern = rf"{num_value_pattern}|{bool_value_pattern}|{single_quotes_value_pattern}" multi_value_pattern = rf"""\((?P<{ValueType.multi_value}>\d+(?:,\s*\d+)*|'(?:[:a-zA-Z\*0-9=+%#\-\/\\,_".$&^@!\(\)\{{\}}\s]|'')*'(?:,\s*'(?:[:a-zA-Z\*0-9=+%#\-\/\\,_".$&^@!\(\)\{{\}}\s]|'')*')*)\)""" # noqa: E501 + re_field_value_pattern = rf"""regexp_like\({field_pattern},\s*'(?P<{ValueType.regex_value}>(?:[:a-zA-Z\*\?0-9=+%#№;\-_,"\.$&^@!\{{\}}\[\]\s?<>|]|\\\'|\\)+)'\)""" # noqa: E501 wildcard_symbol = "%" + str_value_manager = sql_str_value_manager + @staticmethod def should_process_value_wildcards(operator: Optional[str]) -> bool: return operator and operator.lower() in ("like",) @@ -65,7 +72,12 @@ def get_operator_and_value( return mapped_operator, bool_value if (s_q_value := get_match_group(match, group_name=ValueType.single_quotes_value)) is not None: - return mapped_operator, s_q_value + escape_symbol = get_match_group(match, group_name=_ESCAPE_SYMBOL_GROUP_NAME) + should_process_value_wildcards = self.should_process_value_wildcards(operator) + value_type = SQLValueType.like_value if should_process_value_wildcards else SQLValueType.value + return mapped_operator, self.str_value_manager.from_str_to_container( + s_q_value, value_type=value_type, escape_symbol=escape_symbol + ) return super().get_operator_and_value(match, mapped_operator, operator) @@ -74,6 +86,18 @@ def create_field_value(field_name: str, operator: Identifier, value: Union[str, field_name = field_name.strip('"') return FieldValue(source_name=field_name, operator=operator, value=value) - def tokenize(self, query: str) -> list: - query = re.sub(r"\s*ESCAPE\s*'.'", "", query) # remove `ESCAPE 'escape_char'` in LIKE expr - return super().tokenize(query) + def _search_re_field_value(self, query: str) -> Optional[tuple[FieldValue, str]]: + if match := re.match(self.re_field_value_pattern, query, re.IGNORECASE): + group_dict = match.groupdict() + field_name = group_dict["field_name"] + value = self.str_value_manager.from_re_str_to_container(group_dict[ValueType.regex_value]) + operator = Identifier(token_type=OperatorType.REGEX) + return self.create_field_value(field_name, operator, value), query[match.end() :] + + def _get_next_token( + self, query: str + ) -> tuple[Union[FieldValue, FunctionValue, Keyword, Identifier, list[Union[FieldValue, Identifier]]], str]: + query = query.strip("\n").strip(" ").strip("\n") + if search_result := self._search_re_field_value(query): + return search_result + return super()._get_next_token(query) diff --git a/uncoder-core/app/translator/platforms/elasticsearch/renders/esql.py b/uncoder-core/app/translator/platforms/elasticsearch/renders/esql.py index 62e785ee..ebeba491 100644 --- a/uncoder-core/app/translator/platforms/elasticsearch/renders/esql.py +++ b/uncoder-core/app/translator/platforms/elasticsearch/renders/esql.py @@ -28,14 +28,14 @@ from app.translator.platforms.elasticsearch.const import elasticsearch_esql_query_details from app.translator.platforms.elasticsearch.mapping import ElasticESQLMappings, esql_query_mappings from app.translator.platforms.elasticsearch.str_value_manager import ( - ESQLQueryStrValueManager, + ESQLStrValueManager, esql_str_value_manager ) class ESQLFieldValueRender(BaseFieldValueRender): details: PlatformDetails = elasticsearch_esql_query_details - str_value_manager: ESQLQueryStrValueManager = esql_str_value_manager + str_value_manager: ESQLStrValueManager = esql_str_value_manager @staticmethod def _make_case_insensitive(value: str) -> str: diff --git a/uncoder-core/app/translator/platforms/elasticsearch/str_value_manager.py b/uncoder-core/app/translator/platforms/elasticsearch/str_value_manager.py index 05200d2b..1de55c91 100644 --- a/uncoder-core/app/translator/platforms/elasticsearch/str_value_manager.py +++ b/uncoder-core/app/translator/platforms/elasticsearch/str_value_manager.py @@ -16,8 +16,9 @@ limitations under the License. ----------------------------------------------------------------- """ -from typing import ClassVar +from typing import ClassVar, Optional +from app.translator.core.custom_types.values import ValueType from app.translator.core.str_value_manager import ( BaseSpecSymbol, ReDigitalSymbol, @@ -30,7 +31,7 @@ from app.translator.platforms.elasticsearch.escape_manager import ESQLQueryEscapeManager, esql_query_escape_manager -class ESQLQueryStrValueManager(StrValueManager): +class ESQLStrValueManager(StrValueManager): escape_manager: ESQLQueryEscapeManager = esql_query_escape_manager re_str_alpha_num_symbols_map: ClassVar[dict[str, type[BaseSpecSymbol]]] = { "w": ReWordSymbol, @@ -42,10 +43,15 @@ class ESQLQueryStrValueManager(StrValueManager): class EQLStrValueManager(StrValueManager): str_spec_symbols_map: ClassVar[dict[str, type[BaseSpecSymbol]]] = {"*": SingleSymbolWildCard} - def from_str_to_container(self, value: str) -> StrValue: + def from_str_to_container( + self, + value: str, + value_type: str = ValueType.value, # noqa: ARG002 + escape_symbol: Optional[str] = None, # noqa: ARG002 + ) -> StrValue: split = [self.str_spec_symbols_map[char]() if char in self.str_spec_symbols_map else char for char in value] return StrValue(value, self._concat(split)) -esql_str_value_manager = ESQLQueryStrValueManager() +esql_str_value_manager = ESQLStrValueManager() eql_str_value_manager = EQLStrValueManager() diff --git a/uncoder-core/app/translator/platforms/sigma/escape_manager.py b/uncoder-core/app/translator/platforms/sigma/escape_manager.py index c0efb332..26df6163 100644 --- a/uncoder-core/app/translator/platforms/sigma/escape_manager.py +++ b/uncoder-core/app/translator/platforms/sigma/escape_manager.py @@ -7,7 +7,8 @@ class SigmaEscapeManager(EscapeManager): escape_map: ClassVar[dict[str, list[EscapeDetails]]] = { - ValueType.value: [EscapeDetails(pattern=r"([*?\\])", escape_symbols=r"\\\1")] + ValueType.value: [EscapeDetails(pattern=r"([*?\\])", escape_symbols=r"\\\1")], + ValueType.regex_value: [EscapeDetails(pattern=r"([$^*+()\[\]{}|.?\-\\])", escape_symbols=r"\\\1")] } diff --git a/uncoder-core/app/translator/platforms/sigma/renders/sigma.py b/uncoder-core/app/translator/platforms/sigma/renders/sigma.py index 51b1b642..e20b7682 100644 --- a/uncoder-core/app/translator/platforms/sigma/renders/sigma.py +++ b/uncoder-core/app/translator/platforms/sigma/renders/sigma.py @@ -23,6 +23,7 @@ from app.translator.const import DEFAULT_VALUE_TYPE from app.translator.core.custom_types.meta_info import SeverityType from app.translator.core.custom_types.tokens import OperatorType +from app.translator.core.custom_types.values import ValueType from app.translator.core.mapping import DEFAULT_MAPPING_NAME, SourceMapping from app.translator.core.models.query_tokens.field_value import FieldValue from app.translator.core.models.query_tokens.keyword import Keyword @@ -211,18 +212,26 @@ def generate_field(self, data: FieldValue, source_mapping: SourceMapping): ): field_name = f"{field_name}|{data.operator.token_type}" - values = self.__pre_process_values(data.values) + value_type_map = { + OperatorType.REGEX: ValueType.regex_value + } + value_type = value_type_map.get(data.operator.token_type, ValueType.value) + values = self.__pre_process_values(data.values, value_type) if len(values) == 1: return {field_name: values[0]} elif len(values) == 0: return {field_name: ""} return {field_name: values} - def __pre_process_values(self, values: DEFAULT_VALUE_TYPE) -> list[Union[int, str]]: + def __pre_process_values( + self, + values: DEFAULT_VALUE_TYPE, + value_type: str = ValueType.value + ) -> list[Union[int, str]]: processed = [] for v in values: if isinstance(v, StrValue): - processed.append(self.str_value_manager.from_container_to_str(v)) + processed.append(self.str_value_manager.from_container_to_str(v, value_type=value_type)) elif isinstance(v, str): processed.append(v) else: diff --git a/uncoder-core/app/translator/platforms/sigma/str_value_manager.py b/uncoder-core/app/translator/platforms/sigma/str_value_manager.py index 751db716..6d3abe56 100644 --- a/uncoder-core/app/translator/platforms/sigma/str_value_manager.py +++ b/uncoder-core/app/translator/platforms/sigma/str_value_manager.py @@ -16,7 +16,9 @@ limitations under the License. ----------------------------------------------------------------- """ +from typing import Optional +from app.translator.core.custom_types.values import ValueType from app.translator.core.str_value_manager import ( RE_STR_SPEC_SYMBOLS_MAP, ReDigitalSymbol, @@ -42,7 +44,12 @@ class SigmaStrValueManager(StrValueManager): } re_str_spec_symbols_map = RE_STR_SPEC_SYMBOLS_MAP - def from_str_to_container(self, value: str) -> StrValue: + def from_str_to_container( + self, + value: str, + value_type: str = ValueType.value, # noqa: ARG002 + escape_symbol: Optional[str] = None # noqa: ARG002 + ) -> StrValue: split = [] prev_char = None for char in value: pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy