Skip to content

Commit eca8ff7

Browse files
committed
Fixing bug in uri_builder::append_query when using the key value version a few characters were missed being encoded.
1 parent ba8e9b2 commit eca8ff7

File tree

3 files changed

+27
-6
lines changed

3 files changed

+27
-6
lines changed

Release/include/cpprest/base_uri.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ namespace web {
441441
friend class uri_builder;
442442

443443
// Encodes all characters not in given set determined by given function.
444-
static utility::string_t encode_impl(const utility::string_t &raw, const std::function<bool(int)>& should_encode);
444+
_ASYNCRTIMP static utility::string_t __cdecl encode_impl(const utility::string_t &raw, const std::function<bool __cdecl(int)>& should_encode);
445445

446446
utility::string_t m_uri;
447447
details::uri_components m_components;

Release/include/cpprest/uri_builder.h

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <vector>
3131

3232
#include "cpprest/base_uri.h"
33+
#include "cpprest/details/uri_parser.h"
3334

3435
namespace web
3536
{
@@ -234,12 +235,29 @@ namespace web
234235
/// <param name="value">The value portion of the query string</param>
235236
/// <returns>A reference to this uri_builder to support chaining.</returns>
236237
template<typename T>
237-
uri_builder &append_query(utility::string_t name, const T &value, bool do_encoding = true)
238+
uri_builder &append_query(const utility::string_t &name, const T &value, bool do_encoding = true)
238239
{
239-
utility::ostringstream_t ss;
240-
ss.imbue(std::locale::classic());
241-
ss << name << _XPLATSTR("=") << value;
242-
return append_query(ss.str(), do_encoding);
240+
auto encodedName = name;
241+
auto encodedValue = ::utility::conversions::print_string(value, std::locale::classic());
242+
243+
if (do_encoding)
244+
{
245+
auto encodingCheck = [](int ch)
246+
{
247+
// Encode '&', ';', and '=' since they are used
248+
// as delimiters in query component.
249+
return ch == '&' || ch == ';' || ch == '=' || !::web::details::uri_parser::is_query_character(ch)
250+
|| ch == '%' || ch == '+';
251+
};
252+
encodedName = uri::encode_impl(encodedName, encodingCheck);
253+
encodedValue = uri::encode_impl(encodedValue, encodingCheck);
254+
}
255+
256+
auto encodedQuery = encodedName;
257+
encodedQuery.append(_XPLATSTR("="));
258+
encodedQuery.append(encodedValue);
259+
// The query key value pair was already encoded by us or the user separately.
260+
return append_query(encodedQuery, false);
243261
}
244262

245263
/// <summary>

Release/tests/functional/uri/uri_builder_tests.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,9 @@ TEST(append_query_string)
316316
builder.append_query(U("key6"), U("val6"));
317317
VERIFY_ARE_EQUAL(U("key1=value1&key2=value2&key3=value3&key4=value4&key5=1&key6=val6"), builder.query());
318318

319+
// key and value separate with '=', '&', and ';'
320+
builder.append_query(U("key=&;"), U("=&;value"));
321+
VERIFY_ARE_EQUAL(U("key1=value1&key2=value2&key3=value3&key4=value4&key5=1&key6=val6&key%3D%26%3B=%3D%26%3Bvalue"), builder.query());
319322
}
320323

321324
TEST(append_string)

0 commit comments

Comments
 (0)