File indexing completed on 2025-04-20 11:02:16
0001 /* 0002 SPDX-FileCopyrightText: 2009 Paul Marchouk <pmarchouk@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "simpleipv4addressvalidator.h" 0008 0009 #include <QStringList> 0010 #include <QVector> 0011 0012 SimpleIpV4AddressValidator::SimpleIpV4AddressValidator(AddressStyle style, QObject *parent) 0013 : QValidator(parent) 0014 , m_addressStyle(style) 0015 { 0016 switch (style) { 0017 case Base: 0018 m_validator.setRegularExpression(QRegularExpression(QStringLiteral("[0-9, ]{1,3}\\.[0-9, ]{1,3}\\.[0-9, ]{1,3}\\.[0-9, ]{1,3}"))); 0019 break; 0020 case WithCidr: 0021 m_validator.setRegularExpression(QRegularExpression(QStringLiteral("([0-9]{1,3}\\.){3,3}[0-9]{1,3}/[0-9]{1,2}"))); 0022 break; 0023 case WithPort: 0024 m_validator.setRegularExpression(QRegularExpression(QStringLiteral("([0-9]{1,3}\\.){3,3}[0-9]{1,3}:[0-9]{1,5}"))); 0025 break; 0026 } 0027 } 0028 0029 SimpleIpV4AddressValidator::~SimpleIpV4AddressValidator() = default; 0030 0031 QValidator::State SimpleIpV4AddressValidator::validate(QString &address, int &pos) const 0032 { 0033 QValidator::State maskResult = checkWithInputMask(address, pos); 0034 if (QValidator::Invalid == maskResult) { 0035 return QValidator::Invalid; 0036 } 0037 0038 // this list will be filled with tetrad values. It can be used to make 0039 // some additional correctness checks on the last validation step. 0040 QList<int> tetrads; 0041 0042 QValidator::State tetradResult = checkTetradsRanges(address, tetrads); 0043 if (QValidator::Invalid == tetradResult) 0044 return QValidator::Invalid; 0045 else if (QValidator::Intermediate == tetradResult || QValidator::Intermediate == maskResult) 0046 return QValidator::Intermediate; 0047 else 0048 return QValidator::Acceptable; 0049 } 0050 0051 QValidator::State SimpleIpV4AddressValidator::checkWithInputMask(QString &value, int &pos) const 0052 { 0053 return m_validator.validate(value, pos); 0054 } 0055 0056 QValidator::State SimpleIpV4AddressValidator::checkTetradsRanges(QString &value, QList<int> &tetrads) const 0057 { 0058 QStringList temp; 0059 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0060 QVector<QStringRef> addrParts; 0061 #else 0062 QVector<QStringView> addrParts; 0063 #endif 0064 QStringList cidrParts; 0065 QStringList portParts; 0066 0067 switch (m_addressStyle) { 0068 case Base: 0069 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0070 addrParts = value.splitRef(QLatin1Char('.')); 0071 #else 0072 addrParts = QStringView(value).split(QLatin1Char('.')); 0073 #endif 0074 break; 0075 0076 case WithCidr: 0077 cidrParts = value.split(QLatin1Char('/')); 0078 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0079 addrParts = cidrParts[0].splitRef(QLatin1Char('.')); 0080 #else 0081 addrParts = QStringView(cidrParts[0]).split(QLatin1Char('.')); 0082 #endif 0083 break; 0084 0085 case WithPort: 0086 portParts = value.split(QLatin1Char(':')); 0087 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0088 addrParts = portParts[0].splitRef(QLatin1Char('.')); 0089 #else 0090 addrParts = QStringView(portParts[0]).split(QLatin1Char('.')); 0091 #endif 0092 break; 0093 } 0094 0095 int i = 0; 0096 // fill in the list with invalid values 0097 tetrads << -1 << -1 << -1 << -1; 0098 0099 // lets check address parts 0100 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0101 for (const QStringRef &part : std::as_const(addrParts)) { 0102 #else 0103 for (const QStringView &part : std::as_const(addrParts)) { 0104 #endif 0105 if (part.isEmpty()) { 0106 if (i != (addrParts.size() - 1)) { 0107 // qCDebug(PLASMA_NM_EDITOR_LOG) << "part.isEmpty()"; 0108 return QValidator::Invalid; 0109 } 0110 // the last tetrad can be empty, continue... 0111 return QValidator::Intermediate; 0112 } 0113 0114 tetrads[i] = part.toInt(); 0115 0116 if (tetrads[i] > 255) { 0117 // qCDebug(PLASMA_NM_EDITOR_LOG) << "tetrads[i] > 255"; 0118 return QValidator::Invalid; 0119 } 0120 0121 // correct tetrad value: for example, 001 -> 1 0122 temp.append(QString::number(tetrads[i])); 0123 0124 i++; 0125 } 0126 0127 // replace input string with the corrected version 0128 value = temp.join(QLatin1String(".")); 0129 0130 if (i < 4) { 0131 // not all tetrads are filled... continue 0132 // qCDebug(PLASMA_NM_EDITOR_LOG) << "QValidator::Intermediate"; 0133 return QValidator::Intermediate; 0134 } else { 0135 if (m_addressStyle == WithCidr) { 0136 if (cidrParts.size() > 1) { 0137 value += QLatin1String("/"); 0138 if (!cidrParts[1].isEmpty()) { 0139 int cidrValue = cidrParts[1].toInt(); 0140 if (cidrValue > 32) { 0141 return QValidator::Invalid; 0142 } else { 0143 value += cidrParts[1]; 0144 return QValidator::Acceptable; 0145 } 0146 } else { 0147 return QValidator::Intermediate; 0148 } 0149 } 0150 } else if (m_addressStyle == WithPort) { 0151 if (portParts.size() > 1) { 0152 value += QLatin1String(":"); 0153 if (!portParts[1].isEmpty()) { 0154 int portValue = portParts[1].toInt(); 0155 if (portValue > 65535) { 0156 return QValidator::Invalid; 0157 } else { 0158 value += portParts[1]; 0159 return QValidator::Acceptable; 0160 } 0161 } else { 0162 return QValidator::Intermediate; 0163 } 0164 } 0165 } 0166 0167 // qCDebug(PLASMA_NM_EDITOR_LOG) << "QValidator::Acceptable"; 0168 return QValidator::Acceptable; 0169 } 0170 }