Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid applying filtering inside of quoted strings. #178

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 40 additions & 10 deletions mreg_cli/outputmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,28 +78,58 @@ def add_formatted_line_with_source(
formatted_line = "{1:<{0}} {2:<{0}} {3}".format(padding, key, value, source)
self.add_line(formatted_line)

def _find_split_index(self, command: str) -> int:
"""Find the index to split the command for filtering.

It handles both single and double quotes, ensuring that the split
occurs outside of any quoted sections.

:param command: The command string to be processed.
:return: The index at which to split the command, or -1 if not found.
"""
in_quotes = False
current_quote = None

for i, char in enumerate(command):
if char in ["'", '"']:
if in_quotes and char == current_quote:
in_quotes = False
current_quote = None
elif not in_quotes:
in_quotes = True
current_quote = char
elif char == "|" and not in_quotes:
return i

return -1

# We want to use re.Pattern as the type here, but python 3.6 and older re-modules
# don't have that type. So we use Any instead.
def get_filter(self, command: str) -> Tuple[str, Any, bool]:
"""Returns the filter for the output.

:param command: The command to parse for the filter.
Parses the command string and extracts a filter if present, taking into
account both single and double quoted strings to avoid incorrect
splitting.

:return: The filter and whether it is a negated filter.
:param command: The command to parse for the filter.
:return: The command, the filter, and whether it is a negated filter.
"""
self.command = command
negate = False
filter_re = None

if command and "|" in command:
command, filter_str = command.split("|", 1)
filter_str = filter_str.strip()
if command:
split_index = self._find_split_index(command)

if split_index != -1:
filter_str = command[split_index + 1 :].strip()
command = command[:split_index].strip()

if filter_str.startswith("!"):
negate = True
filter_str = filter_str[1:].strip()
if filter_str.startswith("!"):
negate = True
filter_str = filter_str[1:].strip()

filter_re = re.compile(filter_str)
filter_re = re.compile(filter_str)

return (command, filter_re, negate)

Expand Down