diff options
author | Richard Walters <rwalters@digitalstirling.com> | 2018-07-04 19:58:11 -0700 |
---|---|---|
committer | Richard Walters <rwalters@digitalstirling.com> | 2018-07-04 19:58:11 -0700 |
commit | af8ff1ec7bc115f714bc332263c379bf9d6c650e (patch) | |
tree | 95f379b56e41d87dd3bb7a50d4438763fbdc1976 /src/Uri.cpp | |
parent | 69d6838899bf3fe86a81960c574202acfb5f0f77 (diff) |
Percent-encode if necessary any elements when generating strings
Diffstat (limited to 'src/Uri.cpp')
-rw-r--r-- | src/Uri.cpp | 62 |
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(); } |