aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vmime/parserHelpers.hpp6
-rw-r--r--src/vmime/utility/url.cpp62
-rw-r--r--src/vmime/utility/urlUtils.cpp16
-rw-r--r--src/vmime/utility/urlUtils.hpp4
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);