File indexing completed on 2024-12-01 08:10:07
0001 /* 0002 SPDX-FileCopyrightText: 2011 Ilia Kats <ilia-kats@gmx.net>, based on work by 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 "simpleipv6addressvalidator.h" 0008 0009 #include <QList> 0010 #include <QStringList> 0011 0012 SimpleIpV6AddressValidator::SimpleIpV6AddressValidator(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-9a-fA-F]{1,4}|:)+"))); 0019 break; 0020 case WithCidr: 0021 m_validator.setRegularExpression(QRegularExpression(QStringLiteral("([0-9a-fA-F]{1,4}|:){2,15}/[0-9]{1,3}"))); 0022 break; 0023 case WithPort: 0024 m_validator.setRegularExpression(QRegularExpression(QStringLiteral("\\[([0-9a-fA-F]{1,4}|:)+\\]:[0-9]{1,5}"))); 0025 } 0026 } 0027 0028 SimpleIpV6AddressValidator::~SimpleIpV6AddressValidator() = default; 0029 0030 QValidator::State SimpleIpV6AddressValidator::validate(QString &address, int &pos) const 0031 { 0032 if (QValidator::Invalid == checkWithInputMask(address, pos)) { 0033 return QValidator::Invalid; 0034 } 0035 0036 return checkTetradsRanges(address); 0037 } 0038 0039 QValidator::State SimpleIpV6AddressValidator::checkWithInputMask(QString &value, int &pos) const 0040 { 0041 return m_validator.validate(value, pos); 0042 } 0043 0044 QValidator::State SimpleIpV6AddressValidator::checkTetradsRanges(QString &value) const 0045 { 0046 QStringList addrParts; 0047 QStringList cidrParts; 0048 QStringList portParts; 0049 bool foundBracket = false; 0050 QValidator::State result = QValidator::Acceptable; 0051 0052 switch (m_addressStyle) { 0053 case Base: 0054 addrParts = value.split(QLatin1Char(':')); 0055 break; 0056 0057 case WithCidr: 0058 cidrParts = value.split(QLatin1Char('/')); 0059 addrParts = cidrParts[0].split(QLatin1Char(':')); 0060 break; 0061 0062 case WithPort: 0063 if (value.isEmpty()) 0064 return QValidator::Intermediate; 0065 if (value[0] != '[') { 0066 return QValidator::Invalid; 0067 } else { 0068 // Input: "[1:2:3:4:5:6:7:8]:123" 0069 // bracketParts: "[1:2:3:4:5:6:7:8" , ":123" 0070 // addrParts: "" , "1:2:3:4:5:6:7:8" 0071 // portParts: "", "123" 0072 QStringList bracketParts = value.split(QLatin1Char(']')); 0073 if (bracketParts.size() < 2) 0074 portParts = QStringList(); 0075 else { 0076 foundBracket = true; 0077 if (!bracketParts[1].isEmpty() && bracketParts[1][0] != ':') 0078 return QValidator::Invalid; 0079 else 0080 portParts = bracketParts[1].split(QLatin1Char(':')); 0081 } 0082 addrParts = bracketParts[0].split(QLatin1Char('['))[1].split(QLatin1Char(':')); 0083 } 0084 } 0085 0086 int number = addrParts.size(); 0087 // There is no case where can be more than 8 colons (9 parts) 0088 // and only one unusual case where there are 8 colons (1:2:3:4:5:6:7::) 0089 if (number > 9) 0090 return QValidator::Invalid; 0091 else if (number == 9 && (!addrParts[7].isEmpty() || !addrParts[8].isEmpty())) 0092 return QValidator::Invalid; 0093 0094 // lets check address parts 0095 bool emptypresent = false; 0096 int i = 1; 0097 for (QString part : std::as_const(addrParts)) { 0098 if (part.isEmpty() && i < number) { 0099 // There is only one case where you can have 3 empty parts 0100 // and that is when you have the string: "::" which is valid 0101 // and useful and of course it can also be extended to ::123 for 0102 // instance. Anywhere other than the beginning though, having 3 empty 0103 // parts indicates either a run of 3 colons ("1:::6")" or two sets of 0104 // 2 colons ("1:2::3:4::") which are always invalid 0105 if (emptypresent && i != 2) { 0106 // qCDebug(PLASMA_NM_EDITOR_LOG) << "part.isEmpty()"; 0107 return QValidator::Invalid; 0108 } else { 0109 // If this is an empty part then set it to zero to not fail 0110 // the next test 0111 part.setNum(0, 16); 0112 emptypresent = true; 0113 } 0114 } 0115 i++; 0116 0117 bool ok; 0118 if (part.toInt(&ok, 16) > 65535) { 0119 return QValidator::Invalid; 0120 } 0121 } 0122 0123 // A special case: a single colon needs to be Intermediate not Acceptable 0124 if (number == 2 && addrParts[0].isEmpty() && addrParts[1].isEmpty()) 0125 result = QValidator::Intermediate; 0126 0127 // Another special case: a single colon followed by something (i.e. ":123" 0128 // is invalid 0129 else if (number > 1 && addrParts[0].isEmpty() && !addrParts[1].isEmpty()) 0130 result = QValidator::Invalid; 0131 0132 // If we don't have 8 parts yet and none of them are empty we aren't done yet 0133 else if (number < 8 && !emptypresent) 0134 result = QValidator::Intermediate; 0135 0136 // If we have 8 parts but the last one is empty we aren't done yet 0137 else if (number == 8 && addrParts[7].isEmpty()) 0138 result = QValidator::Intermediate; 0139 0140 if (m_addressStyle == WithCidr) { 0141 int cidrSize = cidrParts.size(); 0142 0143 // If we have a '/' and the basic address portion is not 0144 // yet complete (i.e. Intermediate) then the whole thing is Invalid 0145 if (cidrSize == 2 && result == QValidator::Intermediate) 0146 return QValidator::Invalid; 0147 0148 if (cidrSize == 1 || (cidrSize == 2 && cidrParts[1].isEmpty())) 0149 return QValidator::Intermediate; 0150 0151 int cidrValue = cidrParts[1].toInt(); 0152 if (cidrValue > 128) 0153 return QValidator::Invalid; 0154 } else if (m_addressStyle == WithPort) { 0155 int portSize = portParts.size(); 0156 0157 // If we have a ']' and the basic address portion is not 0158 // yet complete (i.e. Intermediate) then the whole thing is Invalid 0159 if (foundBracket && result == QValidator::Intermediate) 0160 return QValidator::Invalid; 0161 0162 if (portSize < 2 || (portSize == 2 && portParts[1].isEmpty())) { 0163 return QValidator::Intermediate; 0164 } else { 0165 int portValue = portParts[1].toInt(); 0166 if (portValue > 65535) 0167 return QValidator::Invalid; 0168 } 0169 } 0170 return result; 0171 } 0172 0173 #include "moc_simpleipv6addressvalidator.cpp"