Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions zonefile_parser/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
def remove_comments(line:str):
for index,character in enumerate(line):
if character == ";" and not is_in_quote(line,index):
if index > 0 and line[index - 1] == '\\':
continue
line = line[:index]
break
return line
Expand Down
10 changes: 10 additions & 0 deletions zonefile_parser/helper_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ def test_doesnt_change_string_without_comment(self):
result = helper.remove_comments(input)
assert result == input

def test_doesnt_remove_escaped_semicolon(self):
input = r"v=DMARC1\;"
result = helper.remove_comments(input)
assert result == input

def test_doesnt_treat_text_after_escaped_semicolon_as_comment(self):
input = r"v=DMARC1\; comment"
result = helper.remove_comments(input)
assert result == input

class TestIsInQuote:
def test_returns_whether_index_in_quote(self):
input = '"A"'
Expand Down
31 changes: 31 additions & 0 deletions zonefile_parser/main_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,37 @@ def test_origin_not_appended_to_txt_rdata_when_name_matches(self):
assert record.rtype == "TXT"
assert record.rdata == {"value": "v=spf1 include:mail.otherdomain.com ~all"}

def test_issue_49_escaped_semicolon_in_txt(self):
# TXT record with a trailing escaped semicolon (\;) should not raise ValueError
text = """
$TTL 3600
$ORIGIN example.com.
_dmarc 3600 IN TXT v=DMARC1\\;
"""
result = zonefile_parser.main.parse(text)

record = result[0]

assert record.name == "_dmarc.example.com."
assert record.rtype == "TXT"
assert record.rdata == {"value": "v=DMARC1;"}

def test_issue_49_dmarc_record_with_comment(self):
# DMARC TXT record with an escaped semicolon followed by a real comment
# the real comment (unescaped ;) should be stripped, \; should survive as ;
text = """
$TTL 3600
$ORIGIN example.com.
_dmarc 3600 IN TXT v=DMARC1\\; ; this is a comment
"""
result = zonefile_parser.main.parse(text)

record = result[0]

assert record.name == "_dmarc.example.com."
assert record.rtype == "TXT"
assert record.rdata == {"value": "v=DMARC1;"}

def test_multiple_cnames_with_name_in_target(self):
# multiple records in the same zone, each with name appearing in their CNAME target
text = """
Expand Down
Loading