diff --git a/libs/editor/CMakeLists.txt b/libs/editor/CMakeLists.txt --- a/libs/editor/CMakeLists.txt +++ b/libs/editor/CMakeLists.txt @@ -40,6 +40,7 @@ listvalidator.cpp simpleipv4addressvalidator.cpp simpleipv6addressvalidator.cpp + simpleiplistvalidator.cpp vpnuiplugin.cpp ../configuration.cpp diff --git a/libs/editor/simpleiplistvalidator.h b/libs/editor/simpleiplistvalidator.h new file mode 100644 --- /dev/null +++ b/libs/editor/simpleiplistvalidator.h @@ -0,0 +1,46 @@ +/* +Copyright 2018 Bruce Anderson + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of +the License or (at your option) version 3 or any later version +accepted by the membership of KDE e.V. (or its successor approved +by the membership of KDE e.V.), which shall act as a proxy +defined in Section 14 of version 3 of the license. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifndef SIMPLEIPLISTVALIDATOR_H +#define SIMPLEIPLISTVALIDATOR_H + +#include +#include "simpleipv4addressvalidator.h" +#include "simpleipv6addressvalidator.h" + +class Q_DECL_EXPORT SimpleIpListValidator : public QValidator +{ +public: + enum AddressType {Ipv4, Ipv6, Both}; + enum AddressStyle {Base, WithCidr, WithPort}; + + explicit SimpleIpListValidator(QObject *parent, + AddressStyle style = AddressStyle::Base, + AddressType allow = AddressType::Both); + ~SimpleIpListValidator() override; + + State validate(QString &, int &) const override; + +private: + SimpleIpV6AddressValidator *m_ipv6Validator; + SimpleIpV4AddressValidator *m_ipv4Validator; +}; + +#endif // SIMPLEIPV4ADDRESSVALIDATOR_H diff --git a/libs/editor/simpleiplistvalidator.cpp b/libs/editor/simpleiplistvalidator.cpp new file mode 100644 --- /dev/null +++ b/libs/editor/simpleiplistvalidator.cpp @@ -0,0 +1,107 @@ +/* +Copyright 2018 Bruce Anderson + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of +the License or (at your option) version 3 or any later version +accepted by the membership of KDE e.V. (or its successor approved +by the membership of KDE e.V.), which shall act as a proxy +defined in Section 14 of version 3 of the license. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "simpleiplistvalidator.h" + +#include +#include + +SimpleIpListValidator::SimpleIpListValidator(QObject *parent, + AddressStyle style, + AddressType type) + : QValidator(parent) +{ + if (type == Ipv4 || type == Both) { + SimpleIpV4AddressValidator::AddressStyle ipv4Style; + if (style == Base) + ipv4Style = SimpleIpV4AddressValidator::AddressStyle::Base; + else if (style == WithCidr) + ipv4Style = SimpleIpV4AddressValidator::AddressStyle::WithCidr; + else + ipv4Style = SimpleIpV4AddressValidator::AddressStyle::WithPort; + m_ipv4Validator = new SimpleIpV4AddressValidator(this, ipv4Style); + } + if (type == Ipv6 || type == Both) { + SimpleIpV6AddressValidator::AddressStyle ipv6Style; + if (style == Base) + ipv6Style = SimpleIpV6AddressValidator::AddressStyle::Base; + else if (style == WithCidr) + ipv6Style = SimpleIpV6AddressValidator::AddressStyle::WithCidr; + else + ipv6Style = SimpleIpV6AddressValidator::AddressStyle::WithPort; + m_ipv6Validator = new SimpleIpV6AddressValidator(this, ipv6Style); + } +} + +SimpleIpListValidator::~SimpleIpListValidator() +{ +} + +QValidator::State SimpleIpListValidator::validate(QString &address, int &pos) const +{ + Q_UNUSED(pos) + + // Split the incoming address on commas possibly with spaces on either side + QStringList addressList = address.split(QRegularExpression("\\s*,\\s*")); + + // Use a local variable for position in the validators so it doesn't screw + // up the position of the cursor when we return + int localPos = 0; + int i = 0; + QValidator::State result = QValidator::Acceptable; + + for (QString &addr : addressList) { + QValidator::State ipv4Result = QValidator::Acceptable; + QValidator::State ipv6Result = QValidator::Acceptable; + + // If we are starting a new address and all the previous addressess + // ar not Acceptable then the previous addresses need to be completed + // before a new one is started + if (result != QValidator::Acceptable) + return QValidator::Invalid; + + // See if it is an IPv4 address. If we are not testing for IPv4 + // then by definition IPv4 is Invalid + if (m_ipv4Validator != nullptr) + ipv4Result = m_ipv4Validator->validate(addr, localPos); + else + ipv4Result = QValidator::Invalid; + + // See if it is an IPv6 address. If we are not testing for IPv6 + // then by definition IPv6 is Invalid + if (m_ipv6Validator != nullptr) + ipv6Result = m_ipv6Validator->validate(addr, localPos); + else + ipv6Result = QValidator::Invalid; + + // If this address is not at least an Intermediate then get out because the list is Invalid + if (ipv6Result == QValidator::Invalid && ipv4Result == QValidator::Invalid) + return QValidator::Invalid; + + // If either validator judged this address to be Intermediate then that's the best the + // final result can be for the whole list. No need to test for Acceptable because + // that's the default set on entry and we only downgrade it from there. + if (result != QValidator::Invalid + && (ipv4Result == QValidator::Intermediate || ipv6Result == QValidator::Intermediate)) + result = QValidator::Intermediate; + i++; + } + return result; +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,51 @@ +set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} ) + +include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +########### next target ############### + +include(ECMAddTests) + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -ggdb") + +set(simpleipv6test_SRCS simpleipv6test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../libs/editor/simpleipv6addressvalidator.cpp ) + +add_executable(simpleipv6test ${simpleipv6test_SRCS}) +add_test(simpleipv6 simpleipv6test) +ecm_mark_as_test(simpleipv6test) + +target_link_libraries(simpleipv6test + Qt5::Test + Qt5::Widgets + KF5::ConfigCore + KF5::CoreAddons) +add_library(simpleipv6test_SRCS) + +set(simpleipv4test_SRCS simpleipv4test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/../libs/editor/simpleipv4addressvalidator.cpp ) + +add_executable(simpleipv4test ${simpleipv4test_SRCS}) +add_test(simpleipv4 simpleipv4test) +ecm_mark_as_test(simpleipv4test) + +target_link_libraries(simpleipv4test + Qt5::Test + Qt5::Widgets + KF5::ConfigCore + KF5::CoreAddons) +add_library(simpleipv4test_SRCS) + +set(simpleiplisttest_SRCS simpleiplisttest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../libs/editor/simpleipv4addressvalidator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../libs/editor/simpleipv6addressvalidator.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/../libs/editor/simpleiplistvalidator.cpp ) + +add_executable(simpleiplisttest ${simpleiplisttest_SRCS}) +add_test(simpleiplist simpleiplisttest) +ecm_mark_as_test(simpleiplisttest) + +target_link_libraries(simpleiplisttest + Qt5::Test + Qt5::Widgets + KF5::ConfigCore + KF5::CoreAddons) +add_library(simpleiplisttest_SRCS) diff --git a/tests/simpleiplisttest.cpp b/tests/simpleiplisttest.cpp new file mode 100644 --- /dev/null +++ b/tests/simpleiplisttest.cpp @@ -0,0 +1,152 @@ +/* +Copyright 2018 Bruce Anderson + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of +the License or (at your option) version 3 or any later version +accepted by the membership of KDE e.V. (or its successor approved +by the membership of KDE e.V.), which shall act as a proxy +defined in Section 14 of version 3 of the license. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "simpleiplistvalidator.h" +#include +#include + +class SimpleipListTest : public QObject +{ + Q_OBJECT + +private slots: + void initTestCase(); + void baseTest(); + void cidrTest(); + void portTest(); + +private: + SimpleIpListValidator* vb; + SimpleIpListValidator* vc; + SimpleIpListValidator* vp; +}; + +void SimpleipListTest::initTestCase() +{ + vb = new SimpleIpListValidator(nullptr, SimpleIpListValidator::AddressStyle::Base); + vc = new SimpleIpListValidator(nullptr, SimpleIpListValidator::AddressStyle::WithCidr); + vp = new SimpleIpListValidator(nullptr, SimpleIpListValidator::AddressStyle::WithPort); +} + +void SimpleipListTest::baseTest() +{ + int pos = 0; + // Null string is intermediate because it's waiting for input + QString tstr(""); + QVERIFY(vb->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "123.12.2"; + QVERIFY(vb->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "123.12.2,"; + QVERIFY(vb->validate(tstr, pos) == QValidator::Invalid); + + tstr = "123.45.22.9"; + QVERIFY(vb->validate(tstr, pos) == QValidator::Acceptable); + + tstr = "123.45.22.9,"; + QVERIFY(vb->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "123.45.22.9, "; + QVERIFY(vb->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "123.45.22,"; + QVERIFY(vb->validate(tstr, pos) == QValidator::Invalid); + + tstr = "123.45.22.9, BBEf:0112"; + QVERIFY(vb->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "123.45.22.9, BBEf:0112::1"; + QVERIFY(vb->validate(tstr, pos) == QValidator::Acceptable); + + tstr = "123.45.22.9, BBEf:0112:,"; + QVERIFY(vb->validate(tstr, pos) == QValidator::Invalid); + + tstr = "123.45.22.9, BBEf:0112::1,"; + QVERIFY(vb->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "123.45.22.9, BBEf:0112::1/123,"; + QVERIFY(vb->validate(tstr, pos) == QValidator::Invalid); + + tstr = "123.45.22.9, BBEf:0112::1,1.2.3.4"; + QVERIFY(vb->validate(tstr, pos) == QValidator::Acceptable); +} + +void SimpleipListTest::cidrTest() +{ + int pos = 0; + + QString tstr("10.77.18.4/32"); + QVERIFY(vc->validate(tstr, pos) == QValidator::Acceptable); + + tstr = "10.77.18.4/32,"; + QVERIFY(vc->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "10.77.18.4/32,Be00:e00:0:"; + QVERIFY(vc->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "10.77.18.4/32,Be00:e00:0:21/3"; + QVERIFY(vc->validate(tstr, pos) == QValidator::Invalid); + + tstr = "10.77.18.4/32,Be00:e00::0:21/128"; + QVERIFY(vc->validate(tstr, pos) == QValidator::Acceptable); + + tstr = "10.77.18.4/32,Be00:e00::0:21/129"; + QVERIFY(vc->validate(tstr, pos) == QValidator::Invalid); +} + +void SimpleipListTest::portTest() +{ + int pos = 0; + + QString tstr("10.77.18.4:32"); + QVERIFY(vp->validate(tstr, pos) == QValidator::Acceptable); + + tstr = "10.77.18.4:,"; + QVERIFY(vp->validate(tstr, pos) == QValidator::Invalid); + + tstr = "10.77.18.4:234, 1"; + QVERIFY(vp->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "10.77.18.4:234, 1b"; + QVERIFY(vp->validate(tstr, pos) == QValidator::Invalid); + + tstr = "10.77.18.4:234, [1b"; + QVERIFY(vp->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "10.77.18.4:234, [10:33:22::1"; + QVERIFY(vp->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "10.77.18.4:234, [10:33:22::1]"; + QVERIFY(vp->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "10.77.18.4:234, [10:33:22::1]:"; + QVERIFY(vp->validate(tstr, pos) == QValidator::Intermediate); + + tstr = "10.77.18.4:234, [10:33:22::1]:22"; + QVERIFY(vp->validate(tstr, pos) == QValidator::Acceptable); + + tstr = "10.77.18.4:234, [10:33:22::1]:22,12.23.34.45:65535"; + QVERIFY(vp->validate(tstr, pos) == QValidator::Acceptable); +} + +QTEST_GUILESS_MAIN(SimpleipListTest) + +#include "simpleiplisttest.moc"