Added Poco::Util::AbstractConfiguration::getHost method

This commit is contained in:
m4xxx1m 2024-08-31 18:22:03 +03:00
parent a7d0a5991e
commit 6fd7656aeb
2 changed files with 193 additions and 0 deletions

View File

@ -241,6 +241,20 @@ namespace Util
/// If the value contains references to other properties (${<property>}), these
/// are expanded.
std::string getHost(const std::string & key) const;
/// Returns the string value of the host property with the given name.
/// Throws a NotFoundException if the key does not exist.
/// Throws a SyntaxException if the property is not a valid host (IP address or domain).
/// If the value contains references to other properties (${<property>}), these
/// are expanded.
std::string getHost(const std::string & key, const std::string & defaultValue) const;
/// If a property with the given key exists, returns the host property's string value,
/// otherwise returns the given default value.
/// Throws a SyntaxException if the property is not a valid host (IP address or domain).
/// If the value contains references to other properties (${<property>}), these
/// are expanded.
virtual void setString(const std::string & key, const std::string & value);
/// Sets the property with the given key to the given value.
/// An already existing value for the key is overwritten.
@ -339,12 +353,38 @@ namespace Util
static bool parseBool(const std::string & value);
void setRawWithEvent(const std::string & key, std::string value);
static void checkHostValidity(const std::string & value);
/// Throws a SyntaxException if the value is not a valid host (IP address or domain).
virtual ~AbstractConfiguration();
private:
std::string internalExpand(const std::string & value) const;
std::string uncheckedExpand(const std::string & value) const;
static bool isValidIPv4Address(const std::string & value);
/// A string value is considered to be a valid IPv4 address if it matches
/// "x1.x2.x3.x4", where xi - integer in range 0..255 and may have leading zeroes
static bool isValidIPv6Address(const std::string & value);
/// A string value is considered to be a valid IPv6 address if it matches
/// "x1:x2:x3:x4:x5:x6:x7:x8", where xi is hexadecimal integer and consist of 4
/// characters or less (but at least 1), xi may have leading zeroes.
/// Letters in hexadecimal representation can be in upper case or lower case.
/// One or more consecutive hextets of zeroes can be replaced with "::", but
/// "::" can appear only once in a valid IPv6 address.
static bool isValidDomainName(const std::string & value);
/// <domain> ::= <subdomain> [ "." ]
/// <subdomain> ::= <label> | <subdomain> "." <label>
/// <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
/// <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
/// <let-dig-hyp> ::= <let-dig> | "-"
/// <let-dig> ::= <letter> | <digit>
/// <letter> ::= any one of the 52 alphabetic characters A through Z in
/// upper case and a through z in lower case
/// <digit> ::= any one of the ten digits 0 through 9
AbstractConfiguration(const AbstractConfiguration &);
AbstractConfiguration & operator=(const AbstractConfiguration &);

View File

@ -263,6 +263,41 @@ bool AbstractConfiguration::getBool(const std::string& key, bool defaultValue) c
}
std::string AbstractConfiguration::getHost(const std::string& key) const
{
Mutex::ScopedLock lock(_mutex);
std::string value;
if (getRaw(key, value))
{
std::string expandedValue = internalExpand(value);
checkHostValidity(expandedValue);
return expandedValue;
}
else
throw NotFoundException(key);
}
std::string AbstractConfiguration::getHost(const std::string& key, const std::string& defaultValue) const
{
Mutex::ScopedLock lock(_mutex);
std::string value;
if (getRaw(key, value))
{
std::string expandedValue = internalExpand(value);
checkHostValidity(expandedValue);
return expandedValue;
}
else
{
checkHostValidity(defaultValue);
return defaultValue;
}
}
void AbstractConfiguration::setString(const std::string& key, const std::string& value)
{
setRawWithEvent(key, value);
@ -529,4 +564,122 @@ void AbstractConfiguration::setRawWithEvent(const std::string& key, std::string
}
void AbstractConfiguration::checkHostValidity(const std::string& value)
{
if (!isValidIPv4Address(value) && !isValidIPv6Address(value) && !isValidDomainName(value))
{
throw SyntaxException("Property is not a valid host name", value);
}
}
bool AbstractConfiguration::isValidIPv4Address(const std::string& value)
{
int octet = 0;
int periodsCount = 0;
int octetLength = 0;
for (char ch : value)
{
if (ch == '.')
{
if (octetLength == 0 || octet > 255 || octet < 0)
return false;
++periodsCount;
octet = 0;
octetLength = 0;
}
else if (isdigit(ch))
{
octet = octet * 10 + (ch - '0');
if (octet > 255)
return false;
++octetLength;
}
else
{
return false;
}
}
return periodsCount == 3 && octetLength > 0 && octet >= 0 && octet <= 255;
}
bool AbstractConfiguration::isValidIPv6Address(const std::string& value)
{
char oldChar = 0;
char oldChar2 = 0;
int hextetLength = 0;
int colonsCount = 0;
bool doubleColon = false;
if (value.length() > 1 && value[0] == ':' && value[1] != ':')
return false;
for (char ch : value)
{
if (ch == ':')
{
if (oldChar == ':')
{
if (doubleColon)
return false;
doubleColon = true;
}
else
{
++colonsCount;
hextetLength = 0;
}
}
else if (isdigit(ch) || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))
{
++hextetLength;
if (hextetLength > 4)
return false;
}
else
{
return false;
}
oldChar2 = oldChar;
oldChar = ch;
}
if (oldChar == ':' && oldChar2 == ':')
return colonsCount <= 7;
else
return hextetLength > 0 && ((doubleColon && colonsCount <= 7) || colonsCount == 7);
}
bool AbstractConfiguration::isValidDomainName(const std::string& value)
{
if (value.empty() || value == "." || value.length() > 253)
return false;
int labelLength = 0;
char oldChar = 0;
for (char ch : value)
{
if (ch == '.')
{
if (labelLength == 0 || labelLength > 63 || oldChar == '-')
return false;
labelLength = 0;
}
else if (isalnum(ch) || ch == '-')
{
if (labelLength == 0 && (ch == '-' || isdigit(ch)))
return false;
++labelLength;
}
else
{
return false;
}
oldChar = ch;
}
return oldChar == '.' || (labelLength > 0 && labelLength <= 63 && oldChar != '-');
}
} } // namespace Poco::Util