diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vmime/parserHelpers.hpp | 6 | ||||
-rw-r--r-- | src/vmime/utility/url.cpp | 62 | ||||
-rw-r--r-- | src/vmime/utility/urlUtils.cpp | 16 | ||||
-rw-r--r-- | src/vmime/utility/urlUtils.hpp | 4 |
4 files changed, 75 insertions, 13 deletions
diff --git a/src/vmime/parserHelpers.hpp b/src/vmime/parserHelpers.hpp index cba43c6c..f150a355 100644 --- a/src/vmime/parserHelpers.hpp +++ b/src/vmime/parserHelpers.hpp @@ -54,6 +54,12 @@ public: return c >= '0' && c <= '9'; } + static bool isXDigit(const char_t c) { + + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F'); + } + static bool isAlpha(const char_t c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); diff --git a/src/vmime/utility/url.cpp b/src/vmime/utility/url.cpp index 59cb1f51..334e78fc 100644 --- a/src/vmime/utility/url.cpp +++ b/src/vmime/utility/url.cpp @@ -126,7 +126,7 @@ const string url::build() const { oss << "@"; } - oss << urlUtils::encode(m_host); + oss << urlUtils::encodeHost(m_host); if (m_port != UNSPECIFIED_PORT) { @@ -166,6 +166,53 @@ const string url::build() const { } +static bool extractHostIPv6(string& hostPart, string& host, string& port) { + + if (hostPart[0] != '[') { + return false; + } + + const auto len = hostPart.find(']'); + + if (len == string::npos) { + return false; + } + + host.assign(&hostPart[1], len - 1); + + if (hostPart[len] == '\0') { + return true; + } + if (hostPart[len + 1] != ':') { + return false; + } + + port = hostPart.substr(len + 2); + + return true; +} + + +static void extractHost(string& hostPart, string& host, string& port) { + + if (extractHostIPv6(hostPart, host, port)) { + return; + } + + const size_t colonPos = hostPart.find(':'); + + if (colonPos == string::npos) { + + host = utility::stringUtils::trim(hostPart); + + } else { + + host = utility::stringUtils::trim(string(hostPart.begin(), hostPart.begin() + colonPos)); + port = utility::stringUtils::trim(string(hostPart.begin() + colonPos + 1, hostPart.end())); + } +} + + void url::parse(const string& str) { // Protocol @@ -222,20 +269,9 @@ void url::parse(const string& str) { } // Host/port - const size_t colonPos = hostPart.find(':'); - string host; string port; - - if (colonPos == string::npos) { - - host = utility::stringUtils::trim(hostPart); - - } else { - - host = utility::stringUtils::trim(string(hostPart.begin(), hostPart.begin() + colonPos)); - port = utility::stringUtils::trim(string(hostPart.begin() + colonPos + 1, hostPart.end())); - } + extractHost(hostPart, host, port); // Path string path = utility::stringUtils::trim(string(str.begin() + slashPos, str.end())); diff --git a/src/vmime/utility/urlUtils.cpp b/src/vmime/utility/urlUtils.cpp index cf51a506..ca0f9c6b 100644 --- a/src/vmime/utility/urlUtils.cpp +++ b/src/vmime/utility/urlUtils.cpp @@ -66,6 +66,22 @@ const string urlUtils::encode(const string& s) { } +const string urlUtils::encodeHost(const string& s) { + + if (s.size() == 0) { + return encode(s); + } + + for (auto it = s.begin() + 1 ; it != s.end() - 1 ; ++it) { + if (!parserHelpers::isXDigit(*it) && *it != ':') { + return encode(s); + } + } + + return "[" + s + "]"; +} + + const string urlUtils::decode(const string& s) { string result; diff --git a/src/vmime/utility/urlUtils.hpp b/src/vmime/utility/urlUtils.hpp index 54ffa2ac..63689816 100644 --- a/src/vmime/utility/urlUtils.hpp +++ b/src/vmime/utility/urlUtils.hpp @@ -44,6 +44,10 @@ public: */ static const string encode(const string& s); + /** Encode the host portion of a URL string. + */ + static const string encodeHost(const string& s); + /** Decode an hex-encoded URL (see encode()). */ static const string decode(const string& s); |