aboutsummaryrefslogtreecommitdiff
path: root/src/Uri.cpp
diff options
context:
space:
mode:
authorRichard Walters <rwalters@digitalstirling.com>2018-07-04 19:58:11 -0700
committerRichard Walters <rwalters@digitalstirling.com>2018-07-04 19:58:11 -0700
commitaf8ff1ec7bc115f714bc332263c379bf9d6c650e (patch)
tree95f379b56e41d87dd3bb7a50d4438763fbdc1976 /src/Uri.cpp
parent69d6838899bf3fe86a81960c574202acfb5f0f77 (diff)
Percent-encode if necessary any elements when generating strings
Diffstat (limited to 'src/Uri.cpp')
-rw-r--r--src/Uri.cpp62
1 files changed, 57 insertions, 5 deletions
diff --git a/src/Uri.cpp b/src/Uri.cpp
index 4e3cba0..3091b89 100644
--- a/src/Uri.cpp
+++ b/src/Uri.cpp
@@ -483,6 +483,58 @@ namespace {
}
/**
+ * This function returns the hex digit that corresponds
+ * to the given value.
+ *
+ * @param[in] value
+ * This is the value to convert to a hex digit.
+ *
+ * @return
+ * The hex digit corresponding to the given value is returned.
+ */
+ char MakeHexDigit(unsigned int value) {
+ if (value < 10) {
+ return (char)(value + '0');
+ } else {
+ return (char)(value - 10 + 'A');
+ }
+ }
+
+ /**
+ * This method encodes the given URI element.
+ * What we are calling a "URI element" is any part of the URI
+ * which is a sequence of characters that:
+ * - may be percent-encoded
+ * - if not percent-encoded, are in a restricted set of characters
+ *
+ * @param[in] element
+ * This is the element to encode.
+ *
+ * @param[in] allowedCharacters
+ * This is the set of characters that do not need to
+ * be percent-encoded.
+ *
+ * @return
+ * The encoded element is returned.
+ */
+ std::string EncodeElement(
+ const std::string& element,
+ const Uri::CharacterSet& allowedCharacters
+ ) {
+ std::string encodedElement;
+ for (auto c: element) {
+ if (allowedCharacters.Contains(c)) {
+ encodedElement.push_back(c);
+ } else {
+ encodedElement.push_back('%');
+ encodedElement.push_back(MakeHexDigit((unsigned int)c >> 4));
+ encodedElement.push_back(MakeHexDigit((unsigned int)c & 0x0F));
+ }
+ }
+ return encodedElement;
+ }
+
+ /**
* This method checks and decodes the given query or fragment.
*
* @param[in,out] queryOrFragment
@@ -1337,13 +1389,13 @@ namespace Uri {
if (impl_->HasAuthority()) {
buffer << "//";
if (!impl_->userInfo.empty()) {
- buffer << impl_->userInfo << '@';
+ buffer << EncodeElement(impl_->userInfo, USER_INFO_NOT_PCT_ENCODED) << '@';
}
if (!impl_->host.empty()) {
if (ValidateIpv6Address(impl_->host)) {
buffer << '[' << impl_->host << ']';
} else {
- buffer << impl_->host;
+ buffer << EncodeElement(impl_->host, REG_NAME_NOT_PCT_ENCODED);
}
}
if (impl_->hasPort) {
@@ -1359,17 +1411,17 @@ namespace Uri {
}
size_t i = 0;
for (const auto& segment: impl_->path) {
- buffer << segment;
+ buffer << EncodeElement(segment, PCHAR_NOT_PCT_ENCODED);
if (i + 1 < impl_->path.size()) {
buffer << '/';
}
++i;
}
if (impl_->hasQuery) {
- buffer << '?' << impl_->query;
+ buffer << '?' << EncodeElement(impl_->query, QUERY_OR_FRAGMENT_NOT_PCT_ENCODED);
}
if (impl_->hasFragment) {
- buffer << '#' << impl_->fragment;
+ buffer << '#' << EncodeElement(impl_->fragment, QUERY_OR_FRAGMENT_NOT_PCT_ENCODED);
}
return buffer.str();
}