File indexing completed on 2024-12-01 08:10:07

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 <QList>
0010 #include <QStringList>
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     QList<QStringView> addrParts;
0060     QStringList cidrParts;
0061     QStringList portParts;
0062 
0063     switch (m_addressStyle) {
0064     case Base:
0065         addrParts = QStringView(value).split(QLatin1Char('.'));
0066         break;
0067 
0068     case WithCidr:
0069         cidrParts = value.split(QLatin1Char('/'));
0070         addrParts = QStringView(cidrParts[0]).split(QLatin1Char('.'));
0071         break;
0072 
0073     case WithPort:
0074         portParts = value.split(QLatin1Char(':'));
0075         addrParts = QStringView(portParts[0]).split(QLatin1Char('.'));
0076         break;
0077     }
0078 
0079     int i = 0;
0080     // fill in the list with invalid values
0081     tetrads << -1 << -1 << -1 << -1;
0082 
0083     // lets check address parts
0084     for (const QStringView &part : std::as_const(addrParts)) {
0085         if (part.isEmpty()) {
0086             if (i != (addrParts.size() - 1)) {
0087                 // qCDebug(PLASMA_NM_EDITOR_LOG) << "part.isEmpty()";
0088                 return QValidator::Invalid;
0089             }
0090             // the last tetrad can be empty, continue...
0091             return QValidator::Intermediate;
0092         }
0093 
0094         tetrads[i] = part.toInt();
0095 
0096         if (tetrads[i] > 255) {
0097             // qCDebug(PLASMA_NM_EDITOR_LOG) << "tetrads[i] > 255";
0098             return QValidator::Invalid;
0099         }
0100 
0101         // correct tetrad value: for example, 001 -> 1
0102         temp.append(QString::number(tetrads[i]));
0103 
0104         i++;
0105     }
0106 
0107     // replace input string with the corrected version
0108     value = temp.join(QLatin1String("."));
0109 
0110     if (i < 4) {
0111         // not all tetrads are filled... continue
0112         // qCDebug(PLASMA_NM_EDITOR_LOG) << "QValidator::Intermediate";
0113         return QValidator::Intermediate;
0114     } else {
0115         if (m_addressStyle == WithCidr) {
0116             if (cidrParts.size() > 1) {
0117                 value += QLatin1String("/");
0118                 if (!cidrParts[1].isEmpty()) {
0119                     int cidrValue = cidrParts[1].toInt();
0120                     if (cidrValue > 32) {
0121                         return QValidator::Invalid;
0122                     } else {
0123                         value += cidrParts[1];
0124                         return QValidator::Acceptable;
0125                     }
0126                 } else {
0127                     return QValidator::Intermediate;
0128                 }
0129             }
0130         } else if (m_addressStyle == WithPort) {
0131             if (portParts.size() > 1) {
0132                 value += QLatin1String(":");
0133                 if (!portParts[1].isEmpty()) {
0134                     int portValue = portParts[1].toInt();
0135                     if (portValue > 65535) {
0136                         return QValidator::Invalid;
0137                     } else {
0138                         value += portParts[1];
0139                         return QValidator::Acceptable;
0140                     }
0141                 } else {
0142                     return QValidator::Intermediate;
0143                 }
0144             }
0145         }
0146 
0147         // qCDebug(PLASMA_NM_EDITOR_LOG) << "QValidator::Acceptable";
0148         return QValidator::Acceptable;
0149     }
0150 }
0151 
0152 #include "moc_simpleipv4addressvalidator.cpp"