import difflib
import re
from lib.utils.common import lstrip_once
class DynamicContentParser:
def __init__(self, content1, content2):
self._static_patterns = None
self._differ = difflib.Differ()
self._is_static = content1 == content2
self._base_content = content1
if not self._is_static:
self._static_patterns = self.get_static_patterns(
self._differ.compare(content1.split(), content2.split())
)
def compare_to(self, content):
"""
DynamicContentParser.compare_to() workflow
1. Check if the wildcard response is static or not, if yes, compare two responses.
2. If it's not static, get static patterns (split by space) and check if the response
has all of them.
3. In some cases, checking static patterns isn't reliable enough, so we check the similarity
ratio of the two responses.
"""
if self._is_static:
return content == self._base_content
i = -1
splitted_content = content.split()
misses = 0
for pattern in self._static_patterns:
try:
i = splitted_content.index(pattern, i + 1)
except ValueError:
if misses or len(self._static_patterns) < 20:
return False
misses += 1
if len(content.split()) > len(self._base_content.split()) and len(self._static_patterns) < 20:
return difflib.SequenceMatcher(None, self._base_content, content).ratio() > 0.75
return True
@staticmethod
def get_static_patterns(patterns):
return [lstrip_once(pattern, " ") for pattern in patterns if pattern.startswith(" ")]
def generate_matching_regex(string1: str, string2: str) -> str:
start = "^"
end = "$"
for char1, char2 in zip(string1, string2):
if char1 != char2:
start += ".*"
break
start += re.escape(char1)
if start.endswith(".*"):
for char1, char2 in zip(string1[::-1], string2[::-1]):
if char1 != char2:
break
end = re.escape(char1) + end
return start + end