From 7731f47cc4e0f7924ca6cd2bcb9deddc120a83f5 Mon Sep 17 00:00:00 2001 From: Nodir Temirkhodjaev Date: Wed, 6 Nov 2024 15:25:20 +0500 Subject: [PATCH] Tests: tst_ruletextparser.h: Add "lineIpPort" test --- src/tests/UtilTest/tst_ruletextparser.h | 38 ++++++++++++ src/ui/util/conf/ruletextparser.cpp | 77 ++++++++++++++++++------- src/ui/util/conf/ruletextparser.h | 14 +++-- 3 files changed, 103 insertions(+), 26 deletions(-) diff --git a/src/tests/UtilTest/tst_ruletextparser.h b/src/tests/UtilTest/tst_ruletextparser.h index 91f820ac..5f714666 100644 --- a/src/tests/UtilTest/tst_ruletextparser.h +++ b/src/tests/UtilTest/tst_ruletextparser.h @@ -6,6 +6,23 @@ #include +namespace { + +bool compareStringList(const StringViewList &l1, const QStringList &l2) +{ + if (l1.size() != l2.size()) + return false; + + for (int i = 0; i < l1.size(); ++i) { + if (l1[i] != l2[i]) + return false; + } + + return true; +} + +} + class RuleTextParserTest : public Test { // Test interface @@ -26,3 +43,24 @@ TEST_F(RuleTextParserTest, emptyList) ASSERT_EQ(p.ruleFilters().size(), 0); } + +TEST_F(RuleTextParserTest, lineIpPort) +{ + RuleTextParser p("1.1.1.1:53"); + + ASSERT_TRUE(p.parse()); + + ASSERT_EQ(p.ruleFilters().size(), 4); + + // Check IP + { + const RuleFilter &rf = p.ruleFilters()[2]; + ASSERT_TRUE(compareStringList(rf.values, { "1.1.1.1" })); + } + + // Check Port + { + const RuleFilter &rf = p.ruleFilters()[3]; + ASSERT_TRUE(compareStringList(rf.values, { "53" })); + } +} diff --git a/src/ui/util/conf/ruletextparser.cpp b/src/ui/util/conf/ruletextparser.cpp index 4ee44d29..ee2c1d9e 100644 --- a/src/ui/util/conf/ruletextparser.cpp +++ b/src/ui/util/conf/ruletextparser.cpp @@ -7,7 +7,8 @@ namespace { const char *const extraNameChars = "_"; -const char *const extraValueChars = ".:-/"; +const char *const extraValueChars = ".-/"; +const char *const extraValueEndChars = ".-/:"; int getCharIndex(const char *chars, const char c) { @@ -89,7 +90,7 @@ void RuleTextParser::parseLines() const int nodeIndex = beginList(FORT_RULE_FILTER_TYPE_LIST_OR); for (;;) { - if (!skipComments(CharAnyBegin)) + if (!skipComments(CharLineBegin)) break; if (!parseLine()) @@ -103,20 +104,31 @@ bool RuleTextParser::parseLine() { const int nodeIndex = beginList(FORT_RULE_FILTER_TYPE_LIST_AND); - m_ruleFilter.type = FORT_RULE_FILTER_TYPE_ADDRESS; // default type + RuleCharTypes expectedSeparator = CharNone; + + m_ruleFilter.type = FORT_RULE_FILTER_TYPE_ADDRESS; // Default type for (;;) { - if (!parseLineSection()) + if (!parseLineSection(expectedSeparator)) break; + if (m_ruleFilter.isLineEnd || m_ruleFilter.isListEnd) + break; + + const bool isSectionEnd = m_ruleFilter.isSectionEnd; + if (!checkAddFilter()) return false; - if (!m_ruleFilter.hasFilterName) { - // next default type, if applicable + resetFilter(); + + // Next default type, if applicable + if (!isSectionEnd && !m_ruleFilter.hasFilterName) { m_ruleFilter.type = m_ruleFilter.isTypeAddress() ? FORT_RULE_FILTER_TYPE_PORT : FORT_RULE_FILTER_TYPE_INVALID; } + + expectedSeparator = CharColon | CharNewLine; } endList(nodeIndex); @@ -124,10 +136,10 @@ bool RuleTextParser::parseLine() return true; } -bool RuleTextParser::parseLineSection() +bool RuleTextParser::parseLineSection(RuleCharTypes expectedSeparator) { for (;;) { - if (!nextCharType(CharAnyBegin, CharSpace)) + if (!nextCharType(CharLineBegin | expectedSeparator, CharSpace)) return false; if (!processSection()) @@ -157,7 +169,9 @@ bool RuleTextParser::processSectionBlock() } break; case CharDigit: case CharValueBegin: { - parseValue(); + const bool expectValueEnd = (m_charType == CharValueBegin); + + parseValue(expectValueEnd); } break; } @@ -174,10 +188,12 @@ bool RuleTextParser::processSectionChar() m_ruleFilter.isNot = !m_ruleFilter.isNot; return true; } break; - case CharColon: - case CharNewLine: { + case CharColon: { m_ruleFilter.isSectionEnd = true; } break; + case CharNewLine: { + m_ruleFilter.isLineEnd = true; + } break; case CharListEnd: { m_ruleFilter.isListEnd = true; checkListEnd(); @@ -278,27 +294,36 @@ bool RuleTextParser::parseBracketValue(RuleCharTypes expectedSeparator) resetParsedCharTypes(); if (!parseChars(CharValueBegin | CharValue, - CharSpaceComment | CharBracketEnd | expectedSeparator, extraValueChars)) + CharSpaceComment | CharBracketEnd | expectedSeparator, extraValueEndChars)) return false; - if ((m_parsedCharTypes & CharBracketEnd) != 0) + if (hasParsedCharTypes(CharBracketEnd)) return false; - if ((m_parsedCharTypes & expectedSeparator) == 0) { + if (!hasParsedCharTypes(expectedSeparator)) { setErrorMessage(tr("Unexpected end of values list")); return false; } - return parseValue(); + const bool expectValueEnd = hasParsedCharTypes(CharValueBegin); + + return parseValue(expectValueEnd); } -bool RuleTextParser::parseValue() +bool RuleTextParser::parseValue(bool expectValueEnd) { const QChar *value = parsedCharPtr(); - if (!parseChars(CharLetter | CharValue | CharValueEnd, extraValueChars)) + const char *extraChars = expectValueEnd ? extraValueEndChars : extraValueChars; + + if (!parseChars(CharLetter | CharValue, extraChars)) return false; + if (expectValueEnd && m_charType != CharValueEnd) { + setErrorMessage(tr("Unexpected end of value")); + return false; + } + const QStringView valueView(value, currentCharPtr() - value); m_ruleFilter.addValue(valueView); @@ -309,7 +334,7 @@ bool RuleTextParser::parseValue() bool RuleTextParser::checkAddFilter() { if (!m_ruleFilter.hasValues()) { - if (m_ruleFilter.isSectionEnd) { + if (!m_ruleFilter.isSectionEnd) { setErrorMessage(tr("Unexpected end of line section")); return false; } @@ -332,6 +357,7 @@ void RuleTextParser::resetFilter() m_ruleFilter.isNot = false; m_ruleFilter.hasFilterName = false; m_ruleFilter.isListEnd = false; + m_ruleFilter.isLineEnd = false; m_ruleFilter.isSectionEnd = false; // m_ruleFilter.type is not reset @@ -342,8 +368,6 @@ void RuleTextParser::resetFilter() void RuleTextParser::addFilter() { m_ruleFilters.append(m_ruleFilter); - - resetFilter(); } int RuleTextParser::beginList(qint8 listType) @@ -354,6 +378,8 @@ int RuleTextParser::beginList(qint8 listType) addFilter(); + resetFilter(); + return nodeIndex; } @@ -392,11 +418,18 @@ bool RuleTextParser::parseChars( return false; } - ungetChar(); + ungetParsedChar(); return true; } +void RuleTextParser::ungetParsedChar() +{ + if (!isEmpty()) { + ungetChar(); + } +} + bool RuleTextParser::nextCharType( RuleCharTypes expectedCharTypes, RuleCharTypes skipCharTypes, const char *extraChars) { @@ -406,7 +439,7 @@ bool RuleTextParser::nextCharType( m_charType = CharNone; - while (m_p < m_end) { + while (!isEmpty()) { const QChar c = *m_p++; m_charType = getCharType(m_charType, c, extraChars); diff --git a/src/ui/util/conf/ruletextparser.h b/src/ui/util/conf/ruletextparser.h index f7e4e172..3bcaa4da 100644 --- a/src/ui/util/conf/ruletextparser.h +++ b/src/ui/util/conf/ruletextparser.h @@ -26,10 +26,10 @@ enum RuleCharType : RuleCharTypes { CharNot = (1 << 13), // ! CharExtra = (1 << 14), // Name | Value // Complex types - CharAnyBegin = (CharListBegin | CharListEnd | CharBracketBegin | CharLetter | CharDigit + CharLineBegin = (CharListBegin | CharListEnd | CharBracketBegin | CharLetter | CharDigit | CharValueBegin | CharNot), CharName = (CharLetter | CharExtra), // a-zA-Z_ - CharValue = (CharDigit | CharExtra), // 0-9.:-/ + CharValue = (CharDigit | CharExtra), // 0-9.-/: CharSpaceComment = (CharSpace | CharComment), }; @@ -43,6 +43,7 @@ struct RuleFilter bool isNot : 1 = false; bool hasFilterName : 1 = false; bool isListEnd : 1 = false; + bool isLineEnd : 1 = false; bool isSectionEnd : 1 = false; qint8 type = 0; @@ -74,7 +75,7 @@ private: void parseLines(); bool parseLine(); - bool parseLineSection(); + bool parseLineSection(RuleCharTypes expectedSeparator); bool processSection(); bool processSectionBlock(); bool processSectionChar(); @@ -86,7 +87,7 @@ private: void parseBracketValues(); bool parseBracketValue(RuleCharTypes expectedSeparator); - bool parseValue(); + bool parseValue(bool expectValueEnd); bool checkAddFilter(); @@ -97,12 +98,15 @@ private: void endList(int nodeIndex); void resetParsedCharTypes() { m_parsedCharTypes = CharNone; } + bool hasParsedCharTypes(RuleCharTypes v) { return v != 0 && (m_parsedCharTypes & v) != 0; } void ungetChar() { --m_p; } const QChar *currentCharPtr() const { return m_p; } const QChar *parsedCharPtr() const { return m_p - 1; } + bool isEmpty() const { return m_p >= m_end; } + RuleFilter &listNode(int listIndex) { return m_ruleFilters[listIndex]; } bool skipComments(RuleCharTypes expectedCharTypes); @@ -115,6 +119,8 @@ private: bool parseChars(RuleCharTypes expectedCharTypes, RuleCharTypes skipCharTypes, const char *extraChars = nullptr); + void ungetParsedChar(); + bool nextCharType(RuleCharTypes expectedCharTypes, RuleCharTypes skipCharTypes, const char *extraChars = nullptr);