From 7536ae57996ce7f77109652e4a2877d6d823d5df Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Tue, 7 May 2019 10:37:14 -0700 Subject: [PATCH 01/80] Add switches to make apiscan happy. (#1133) --- Release/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 994111f6d6..c689205590 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -178,8 +178,8 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4264") add_compile_options(/bigobj) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MP") - set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MP") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MP") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MP /profile /OPT:REF /OPT:ICF") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MP /profile /OPT:REF /OPT:ICF") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MP") if (WINDOWS_STORE OR WINDOWS_PHONE) From e037858d627edf175137f3e81c88f2a2ad17f603 Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Tue, 7 May 2019 18:43:33 +0100 Subject: [PATCH 02/80] json: {"meow"} is not a valid object (#1130) * json: {"meow"} is not a valid object * Add to contributors - eighteenth PR seemed like the time! :-) --- CONTRIBUTORS.txt | 3 +++ Release/src/json/json_parsing.cpp | 2 +- Release/tests/functional/json/parsing_tests.cpp | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 845ecd85c0..36348fa544 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -54,3 +54,6 @@ leetal Benjamin Lee (mobileben) René Meusel (reneme) + +Sony Corporation +Gareth Sylvester-Bradley (garethsb-sony) diff --git a/Release/src/json/json_parsing.cpp b/Release/src/json/json_parsing.cpp index 2af0ed1629..30873fd36d 100644 --- a/Release/src/json/json_parsing.cpp +++ b/Release/src/json/json_parsing.cpp @@ -965,7 +965,7 @@ std::unique_ptr JSON_Parser::_ParseObject( if (tkn.m_error) goto error; // State 2: Looking for a colon. - if (tkn.kind != JSON_Parser::Token::TKN_Colon) goto done; + if (tkn.kind != JSON_Parser::Token::TKN_Colon) goto error; GetNextToken(tkn); if (tkn.m_error) goto error; diff --git a/Release/tests/functional/json/parsing_tests.cpp b/Release/tests/functional/json/parsing_tests.cpp index fc7a23779c..cf5a261bf0 100644 --- a/Release/tests/functional/json/parsing_tests.cpp +++ b/Release/tests/functional/json/parsing_tests.cpp @@ -469,6 +469,12 @@ SUITE(parsing_tests) VERIFY_ARE_EQUAL(0u, arr.size()); } + TEST(bug_object_field_key_no_value) + { + VERIFY_PARSING_THROW(json::value::parse(U("{\"meow\"}"))); + VERIFY_PARSING_THROW(json::value::parse(U("{\"meow\": 42, \"purr\": 57, \"hiss\"}"))); + } + TEST(bug_416116) { json::value data2 = json::value::parse(U("\"δοκιμή\"")); From ce50b8cd9d4dc34342a4cd34898e8ea6389e3ac5 Mon Sep 17 00:00:00 2001 From: Bryan Lipinski <46010046+bryan-lipinski@users.noreply.github.com> Date: Mon, 10 Jun 2019 13:45:33 -0700 Subject: [PATCH 03/80] Undefine compress if it is defined by zconf.h (#1150) --- Release/src/http/common/http_compression.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Release/src/http/common/http_compression.cpp b/Release/src/http/common/http_compression.cpp index a9cbc86e1d..691914488a 100644 --- a/Release/src/http/common/http_compression.cpp +++ b/Release/src/http/common/http_compression.cpp @@ -32,6 +32,10 @@ #if defined(CPPREST_HTTP_COMPRESSION) #include +// zconf.h may define compress +#ifdef compress +#undef compress +#endif #if !defined(CPPREST_EXCLUDE_BROTLI) #define CPPREST_BROTLI_COMPRESSION #endif // CPPREST_EXCLUDE_BROTLI From 0e9fef8159c36e8f805c7e10d42d3055ac5899f5 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 12 Jun 2019 18:43:31 -0700 Subject: [PATCH 04/80] Fix broken CI Builds (#1156) * Update vcpkg. * Attempt to fix Ubuntu apt and update MacOS. * Workaround Azure Pipelines forcing an updated copy of boost that doesn't work with default Ubuntu libs. * Add test runs back. * Update boost-for-android and block Boost 1.69 on the image. * Update boost and openssl on iOS. * Use right path to test binaries. * Shut off iOS builds. --- Build_android/configure.sh | 4 ++- Build_iOS/configure.sh | 6 ++-- azure-pipelines.yml | 65 ++++++++++++++++---------------------- vcpkg | 2 +- 4 files changed, 34 insertions(+), 43 deletions(-) diff --git a/Build_android/configure.sh b/Build_android/configure.sh index 0d218a46b4..b4e3e1748d 100755 --- a/Build_android/configure.sh +++ b/Build_android/configure.sh @@ -92,6 +92,8 @@ done # Variables setup +unset BOOST_ROOT + if [ ! -e "${ANDROID_NDK}/ndk-build" ] then echo "ANDROID_NDK does not point to a valid NDK." @@ -153,7 +155,7 @@ if [ "${DO_OPENSSL}" == "1" ]; then ( if [ "${DO_BOOST}" == "1" ]; then ( if [ ! -d 'Boost-for-Android' ]; then git clone https://github.com/moritz-wundke/Boost-for-Android; fi cd Boost-for-Android - git checkout 1356b87fed389b4abf1ff671adec0b899877174b + git checkout b1e2cb397d3ec573f1cfdf4f4d965766204c53f1 PATH="$PATH:$NDK_DIR" \ CXXFLAGS="-std=gnu++11" \ ./build-android.sh \ diff --git a/Build_iOS/configure.sh b/Build_iOS/configure.sh index d4240d8943..722128e3d9 100755 --- a/Build_iOS/configure.sh +++ b/Build_iOS/configure.sh @@ -73,8 +73,8 @@ while (( "$#" )); do done ## Configuration -DEFAULT_BOOST_VERSION=1.67.0 -DEFAULT_OPENSSL_VERSION=1.0.2o +DEFAULT_BOOST_VERSION=1.69.0 +DEFAULT_OPENSSL_VERSION=1.1.0k BOOST_VERSION=${BOOST_VERSION:-${DEFAULT_BOOST_VERSION}} OPENSSL_VERSION=${OPENSSL_VERSION:-${DEFAULT_OPENSSL_VERSION}} CPPRESTSDK_BUILD_TYPE=${CPPRESTSDK_BUILD_TYPE:-Release} @@ -96,7 +96,7 @@ if [ ! -e $ABS_PATH/boost.framework ] && [ ! -d $ABS_PATH/boost ]; then git clone https://github.com/faithfracture/Apple-Boost-BuildScript ${ABS_PATH}/Apple-Boost-BuildScript fi pushd ${ABS_PATH}/Apple-Boost-BuildScript - git checkout 1b94ec2e2b5af1ee036d9559b96e70c113846392 + git checkout 1ebe6e7654d9c9e1792076ee3827a45d5d2f34c5 BOOST_LIBS="thread chrono filesystem regex system random" ./boost.sh -ios -tvos --boost-version $BOOST_VERSION popd mv ${ABS_PATH}/Apple-Boost-BuildScript/build/boost/${BOOST_VERSION}/ios/framework/boost.framework ${ABS_PATH} diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 23cd6f03ff..48d30a1ab8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -153,46 +153,34 @@ jobs: vmImage: 'Ubuntu 16.04' steps: - script: | - sudo apt-get install -y ppa-purge + sudo apt -y remove php* + sudo apt install -y ppa-purge sudo ppa-purge -y ppa:ondrej/php - sudo apt-get install -y libboost-atomic-dev libboost-thread-dev libboost-system-dev libboost-date-time-dev libboost-regex-dev libboost-filesystem-dev libboost-random-dev libboost-chrono-dev libboost-serialization-dev libwebsocketpp-dev openssl libssl-dev ninja-build - displayName: Apt install dependencies - - script: | + unset BOOST_ROOT + sudo apt install -y libboost-atomic-dev libboost-thread-dev libboost-system-dev libboost-date-time-dev libboost-regex-dev libboost-filesystem-dev libboost-random-dev libboost-chrono-dev libboost-serialization-dev libwebsocketpp-dev openssl libssl-dev ninja-build mkdir build.debug - mkdir build.release - displayName: Make Build Directories - - task: CMake@1 - inputs: - workingDirectory: 'build.debug' - cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' - - task: CMake@1 - inputs: - workingDirectory: 'build.release' - cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' - - script: | cd build.debug - ninja - displayName: 'Run ninja, debug' - - script: | + /usr/local/bin/cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug .. + cd .. + mkdir build.release + cd build.release + /usr/local/bin/cmake -G Ninja -DCMAKE_BUILD_TYPE=Release .. + cd .. + ninja -C build.debug + ninja -C build.release cd build.debug/Release/Binaries ./test_runner *test.so - displayName: 'Run tests, debug' - - script: | - cd build.release - ninja - displayName: 'Run ninja, release' - - script: | - cd build.release/Release/Binaries + cd ../../../build.release/Release/Binaries ./test_runner *test.so - displayName: 'Run tests, release' + displayName: Run build - job: Ubuntu_1604_Vcpkg pool: vmImage: 'Ubuntu 16.04' steps: - script: | sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt-get -y update - sudo apt-get install g++-7 ninja-build -y + sudo apt -y update + sudo apt install g++-9 ninja-build -y ./vcpkg/bootstrap-vcpkg.sh ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg displayName: Vcpkg install dependencies @@ -236,7 +224,7 @@ jobs: displayName: 'Build for Android' - job: MacOS_Homebrew pool: - vmImage: 'macOS-10.13' + vmImage: 'macOS-10.14' steps: - script: brew install boost openssl ninja displayName: Brew install dependencies @@ -279,7 +267,7 @@ jobs: displayName: 'Run ninja, release static' - job: MacOS_Vcpkg pool: - vmImage: 'macOS-10.13' + vmImage: 'macOS-10.14' steps: - script: | brew install gcc ninja @@ -314,11 +302,12 @@ jobs: cd build.release/Release/Binaries ./test_runner *test.dylib displayName: 'Run tests, release' - - job: MacOS_iOS - pool: - vmImage: 'macOS-10.13' - steps: - - script: | - cd Build_iOS - ./configure.sh - displayName: 'Build for iOS' + # iOS is disabled for now because the dependency Apple-Boost-BuildScript appears to be broken with the version of XCode in use in Pipelines. + # - job: MacOS_iOS + # pool: + # vmImage: 'macOS-10.14' + # steps: + # - script: | + # cd Build_iOS + # ./configure.sh + # displayName: 'Build for iOS' diff --git a/vcpkg b/vcpkg index c7d4696a88..b7d6160b80 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit c7d4696a8857235ec8e3497e43f0d6fe3d4b5396 +Subproject commit b7d6160b80f417137bc480137b946c91f3272bf5 From be807d42c2d633cd06a91a9011d533061381f6d0 Mon Sep 17 00:00:00 2001 From: Bryan Lipinski <46010046+bryan-lipinski@users.noreply.github.com> Date: Wed, 12 Jun 2019 20:11:30 -0700 Subject: [PATCH 05/80] Use EVP_MAX_MD_SIZE instead of HMAC_MAX_MD_CBLOCK (#1155) --- Release/src/http/oauth/oauth1.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/oauth/oauth1.cpp b/Release/src/http/oauth/oauth1.cpp index 506d9f1faa..0e973aa401 100644 --- a/Release/src/http/oauth/oauth1.cpp +++ b/Release/src/http/oauth/oauth1.cpp @@ -136,7 +136,7 @@ std::vector oauth1_config::_hmac_sha1(const utility::string_t& ke std::vector oauth1_config::_hmac_sha1(const utility::string_t& key, const utility::string_t& data) { - unsigned char digest[HMAC_MAX_MD_CBLOCK]; + unsigned char digest[EVP_MAX_MD_SIZE]; unsigned int digest_len = 0; HMAC(EVP_sha1(), From 36e030a5ed4c15fcfa31aa092bdc4061ad982e5d Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Thu, 13 Jun 2019 13:39:13 -0600 Subject: [PATCH 06/80] Remove the address_configured flag on tcp::resolver::query (#1145) The default behavior for tcp::resolver::query uses the address_configured flag, which only returns addresses if a non-loopback address is available on the system. If this is called before a real network interface is brought up, then resolution will fail and the server won't be functional, even for requests on the loopback interface. Explicitly set the flags to default so that the address_configured flag is not specified. This allows the server to start up normally even when the system has no active network interfaces. --- Release/src/http/listener/http_server_asio.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index e35838a077..96a24f6be6 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -520,7 +520,9 @@ void hostport_listener::start() auto& service = crossplat::threadpool::shared_instance().service(); tcp::resolver resolver(service); // #446: boost resolver does not recognize "+" as a host wildchar - tcp::resolver::query query = ("+" == m_host) ? tcp::resolver::query(m_port) : tcp::resolver::query(m_host, m_port); + tcp::resolver::query query = ("+" == m_host) ? + tcp::resolver::query(m_port, boost::asio::ip::resolver_query_base::flags()) : + tcp::resolver::query(m_host, m_port, boost::asio::ip::resolver_query_base::flags()); tcp::endpoint endpoint = *resolver.resolve(query); From 0f45af151345b330408b53b6410175b7733c0388 Mon Sep 17 00:00:00 2001 From: Kumamon38 Date: Thu, 13 Jun 2019 21:40:00 +0200 Subject: [PATCH 07/80] add ping and pong to message handler (#1143) Add ping and pong to message handler, and optional pong timeout --- Release/include/cpprest/ws_msg.h | 26 ++++++++-- .../src/websockets/client/ws_client_wspp.cpp | 45 +++++++++++++++- .../websockets/client/send_msg_tests.cpp | 51 +++++++++++++++++-- .../utilities/test_websocket_server.cpp | 14 +++++ .../utilities/test_websocket_server.h | 1 + 5 files changed, 127 insertions(+), 10 deletions(-) diff --git a/Release/include/cpprest/ws_msg.h b/Release/include/cpprest/ws_msg.h index 64cee7ae52..73e968a001 100644 --- a/Release/include/cpprest/ws_msg.h +++ b/Release/include/cpprest/ws_msg.h @@ -60,10 +60,23 @@ class websocket_outgoing_message public: #if !defined(__cplusplus_winrt) /// - /// Sets a the outgoing message to be an unsolicited pong message. + /// Sets the outgoing message to be a ping message. /// This is useful when the client side wants to check whether the server is alive. /// - void set_pong_message() { this->set_message_pong(); } + /// UTF-8 String containing the optional ping message. + void set_ping_message(const std::string& data = {}) + { + this->set_message_ping(concurrency::streams::container_buffer(data)); + } + + /// + /// Sets the outgoing message to be an unsolicited pong message. + /// + /// UTF-8 String containing the optional pong message. + void set_pong_message(const std::string& data = {}) + { + this->set_message_pong(concurrency::streams::container_buffer(data)); + } #endif /// @@ -140,9 +153,14 @@ class websocket_outgoing_message const pplx::task_completion_event& body_sent() const { return m_body_sent; } #if !defined(__cplusplus_winrt) - void set_message_pong() + void set_message_ping(const concurrency::streams::container_buffer& buffer) + { + m_msg_type = websocket_message_type::ping; + m_length = static_cast(buffer.size()); + m_body = buffer; + } + void set_message_pong(const concurrency::streams::container_buffer& buffer) { - concurrency::streams::container_buffer buffer(""); m_msg_type = websocket_message_type::pong; m_length = static_cast(buffer.size()); m_body = buffer; diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index 326557fee5..5ef74aaf1e 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -325,6 +325,35 @@ class wspp_callback_client : public websocket_client_callback_impl, } }); + client.set_ping_handler( + [this](websocketpp::connection_hdl, const std::string& msg) { + if (m_external_message_handler) + { + _ASSERTE(m_state >= CONNECTED && m_state < CLOSED); + websocket_incoming_message incoming_msg; + + incoming_msg.m_msg_type = websocket_message_type::ping; + incoming_msg.m_body = concurrency::streams::container_buffer(msg); + + m_external_message_handler(incoming_msg); + } + return true; + }); + + client.set_pong_handler( + [this](websocketpp::connection_hdl, const std::string& msg) { + if (m_external_message_handler) + { + _ASSERTE(m_state >= CONNECTED && m_state < CLOSED); + websocket_incoming_message incoming_msg; + + incoming_msg.m_msg_type = websocket_message_type::pong; + incoming_msg.m_body = concurrency::streams::container_buffer(msg); + + m_external_message_handler(incoming_msg); + } + }); + client.set_close_handler([this](websocketpp::connection_hdl con_hdl) { _ASSERTE(m_state != CLOSED); shutdown_wspp_impl(con_hdl, false); @@ -434,12 +463,13 @@ class wspp_callback_client : public websocket_client_callback_impl, { case websocket_message_type::text_message: case websocket_message_type::binary_message: + case websocket_message_type::ping: case websocket_message_type::pong: break; default: return pplx::task_from_exception(websocket_exception("Message Type not supported.")); } const auto length = msg.m_length; - if (length == 0 && msg.m_msg_type != websocket_message_type::pong) + if (length == 0 && msg.m_msg_type != websocket_message_type::ping && msg.m_msg_type != websocket_message_type::pong) { return pplx::task_from_exception(websocket_exception("Cannot send empty message.")); } @@ -694,7 +724,18 @@ class wspp_callback_client : public websocket_client_callback_impl, case websocket_message_type::binary_message: client.send(this_client->m_con, sp_allocated.get(), length, websocketpp::frame::opcode::binary, ec); break; - case websocket_message_type::pong: client.pong(this_client->m_con, "", ec); break; + case websocket_message_type::ping: + { + std::string s(reinterpret_cast(sp_allocated.get()), length); + client.ping(this_client->m_con, s, ec); + break; + } + case websocket_message_type::pong: + { + std::string s(reinterpret_cast(sp_allocated.get()), length); + client.pong(this_client->m_con, s, ec); + break; + } default: // This case should have already been filtered above. std::abort(); diff --git a/Release/tests/functional/websockets/client/send_msg_tests.cpp b/Release/tests/functional/websockets/client/send_msg_tests.cpp index e99bccd03c..eed1dedf94 100644 --- a/Release/tests/functional/websockets/client/send_msg_tests.cpp +++ b/Release/tests/functional/websockets/client/send_msg_tests.cpp @@ -104,16 +104,32 @@ SUITE(send_msg_tests) } template - pplx::task send_pong_msg_helper(SocketClientClass & client, web::uri uri, test_websocket_server & server) + pplx::task send_ping_msg_helper(SocketClientClass & client, web::uri uri, test_websocket_server & server, + const std::string& body = "") { server.next_message( - [](test_websocket_msg msg) // Handler to verify the message sent by the client. - { websocket_asserts::assert_message_equals(msg, "", test_websocket_message_type::WEB_SOCKET_PONG_TYPE); }); + [body](test_websocket_msg msg) // Handler to verify the message sent by the client. + { websocket_asserts::assert_message_equals(msg, body, test_websocket_message_type::WEB_SOCKET_PING_TYPE); }); client.connect(uri).wait(); websocket_outgoing_message msg; - msg.set_pong_message(); + msg.set_ping_message(body); + return client.send(msg); + } + + template + pplx::task send_pong_msg_helper(SocketClientClass & client, web::uri uri, test_websocket_server & server, + const std::string& body = "") + { + server.next_message( + [body](test_websocket_msg msg) // Handler to verify the message sent by the client. + { websocket_asserts::assert_message_equals(msg, body, test_websocket_message_type::WEB_SOCKET_PONG_TYPE); }); + + client.connect(uri).wait(); + + websocket_outgoing_message msg; + msg.set_pong_message(body); return client.send(msg); } @@ -493,6 +509,24 @@ SUITE(send_msg_tests) } #if !defined(__cplusplus_winrt) + // Send a ping message to the server + TEST_FIXTURE(uri_address, send_ping_msg) + { + test_websocket_server server; + websocket_client client; + send_ping_msg_helper(client, m_uri, server).wait(); + client.close().wait(); + } + + // Send a ping message to the server with a body + TEST_FIXTURE(uri_address, send_ping_msg_body) + { + test_websocket_server server; + websocket_client client; + send_ping_msg_helper(client, m_uri, server, "abcdefghijklmnopqrstuvwxyz").wait(); + client.close().wait(); + } + // Send an unsolicited pong message to the server TEST_FIXTURE(uri_address, send_pong_msg) { @@ -502,6 +536,15 @@ SUITE(send_msg_tests) client.close().wait(); } + // Send an unsolicited pong message to the server with a body + TEST_FIXTURE(uri_address, send_pong_msg_body) + { + test_websocket_server server; + websocket_client client; + send_pong_msg_helper(client, m_uri, server, "abcdefghijklmnopqrstuvwxyz").wait(); + client.close().wait(); + } + // Send an unsolicited pong message to the server with websocket_callback_client TEST_FIXTURE(uri_address, send_pong_msg_callback_client) { diff --git a/Release/tests/functional/websockets/utilities/test_websocket_server.cpp b/Release/tests/functional/websockets/utilities/test_websocket_server.cpp index 151d03bca0..863376f22a 100644 --- a/Release/tests/functional/websockets/utilities/test_websocket_server.cpp +++ b/Release/tests/functional/websockets/utilities/test_websocket_server.cpp @@ -122,6 +122,20 @@ class _test_websocket_server m_server_connected.set_exception(std::runtime_error("Connection attempt failed.")); }); + m_srv.set_ping_handler([this](websocketpp::connection_hdl hdl, std::string input) { + auto fn = m_test_srv->get_next_message_handler(); + assert(fn); + + test_websocket_msg wsmsg; + + wsmsg.set_data(std::vector(input.begin(), input.end())); + + wsmsg.set_msg_type(WEB_SOCKET_PING_TYPE); + fn(wsmsg); + + return true; + }); + m_srv.set_pong_handler([this](websocketpp::connection_hdl hdl, std::string input) { auto fn = m_test_srv->get_next_message_handler(); assert(fn); diff --git a/Release/tests/functional/websockets/utilities/test_websocket_server.h b/Release/tests/functional/websockets/utilities/test_websocket_server.h index 50489e1a9d..23fbea12e2 100644 --- a/Release/tests/functional/websockets/utilities/test_websocket_server.h +++ b/Release/tests/functional/websockets/utilities/test_websocket_server.h @@ -46,6 +46,7 @@ enum test_websocket_message_type WEB_SOCKET_UTF8_MESSAGE_TYPE, WEB_SOCKET_UTF8_FRAGMENT_TYPE, WEB_SOCKET_CLOSE_TYPE, + WEB_SOCKET_PING_TYPE, WEB_SOCKET_PONG_TYPE }; From 5b32e16f5e174cd6ee6041af6e67461212df2a1c Mon Sep 17 00:00:00 2001 From: VZ Date: Thu, 13 Jun 2019 21:41:11 +0200 Subject: [PATCH 08/80] Fix reusing ASIO http_client connecting to HTTPS server via proxy (#539) Calling request() twice on the same client configured to connect to a server via HTTPS didn't work under Unix because we issues CONNECT for every request, meaning that, for the second one, we sent CONNECT via an already established connection to the end server itself which, unsurprisingly, didn't work at all. Fix this by only setting up SSL tunnelling for a new connection but not for the already used one. --- Release/src/http/client/http_client_asio.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 1bcb335e27..96a627abe2 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -905,7 +905,8 @@ class asio_context final : public request_context, public std::enable_shared_fro } }; - if (proxy_type == http_proxy_type::ssl_tunnel) + // Note that we must not try to CONNECT using an already established connection via proxy -- this would send CONNECT to the end server which is definitely not what we want. + if (proxy_type == http_proxy_type::ssl_tunnel && !m_connection->is_reused()) { // The ssl_tunnel_proxy keeps the context alive and then calls back once the ssl tunnel is established via // 'start_http_request_flow' From 06aeb8ea9f60d474ce64bc2004433c17a4ce6b78 Mon Sep 17 00:00:00 2001 From: dejaniv Date: Thu, 11 Jul 2019 18:15:21 -0700 Subject: [PATCH 09/80] Fix issue #1171: Order of object destruction (#1175) - Connection object is now destroyed before client object - Client is destroyed only when wspp_callback_client is destroyed to prevent race condition with the destructor --- Release/src/websockets/client/ws_client_wspp.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index 5ef74aaf1e..26fa547d5d 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -689,9 +689,6 @@ class wspp_callback_client : public websocket_client_callback_impl, } } // unlock - // Delete client to make sure Websocketpp cleans up all Boost.Asio portions. - m_client.reset(); - if (connecting) { websocket_exception exc(ec, build_error_msg(ec, "set_fail_handler")); @@ -801,8 +798,6 @@ class wspp_callback_client : public websocket_client_callback_impl, websocketpp::client m_client; }; - websocketpp::connection_hdl m_con; - pplx::task_completion_event m_connect_tce; pplx::task_completion_event m_close_tce; @@ -810,6 +805,7 @@ class wspp_callback_client : public websocket_client_callback_impl, std::mutex m_wspp_client_lock; State m_state; std::unique_ptr m_client; + websocketpp::connection_hdl m_con; // Queue to track pending sends outgoing_msg_queue m_out_queue; From 47cd408966f33199903a6b1426ce843235873084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Meusel?= Date: Fri, 12 Jul 2019 03:16:57 +0200 Subject: [PATCH 10/80] FIX: SSL proxy tunnel support with basic auth (#1183) --- Release/src/http/client/http_client_asio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 96a627abe2..c5c815eec7 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -570,7 +570,7 @@ class asio_context final : public request_context, public std::enable_shared_fro if (m_context->m_http_client->client_config().proxy().credentials().is_set()) { - request_stream << m_context->generate_basic_proxy_auth_header() << CRLF; + request_stream << m_context->generate_basic_proxy_auth_header(); } request_stream << CRLF; From 951e269923c7b09a45582e37687124db651f3a34 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Thu, 11 Jul 2019 18:59:47 -0700 Subject: [PATCH 11/80] Fix profile being set on the compiler instead of the linker. (#1184) --- Release/CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index c689205590..9a0bbf1a24 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -178,10 +178,13 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4264") add_compile_options(/bigobj) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MP") - set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MP /profile /OPT:REF /OPT:ICF") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MP /profile /OPT:REF /OPT:ICF") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MP") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MP") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MP") + set(CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL} /profile /OPT:REF /OPT:ICF") + set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /profile /OPT:REF /OPT:ICF") + if (WINDOWS_STORE OR WINDOWS_PHONE) add_compile_options(/ZW) endif() From 643dc60703987d15b30124ec7ce90d97997f512b Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Fri, 12 Jul 2019 13:14:55 -0700 Subject: [PATCH 12/80] Update boost-for-android for Android NDK r20 and disable macOS Homebrew. (#1185) * Update boost-for-android for Android NDK r20. * Also disable homebrew. * I mean homebrew I said! * Apparently Android isn't ready for Boost 1.70 yet. --- Build_android/configure.sh | 2 +- azure-pipelines.yml | 87 +++++++++++++++++++------------------- 2 files changed, 45 insertions(+), 44 deletions(-) diff --git a/Build_android/configure.sh b/Build_android/configure.sh index b4e3e1748d..5088f44d8f 100755 --- a/Build_android/configure.sh +++ b/Build_android/configure.sh @@ -155,7 +155,7 @@ if [ "${DO_OPENSSL}" == "1" ]; then ( if [ "${DO_BOOST}" == "1" ]; then ( if [ ! -d 'Boost-for-Android' ]; then git clone https://github.com/moritz-wundke/Boost-for-Android; fi cd Boost-for-Android - git checkout b1e2cb397d3ec573f1cfdf4f4d965766204c53f1 + git checkout aed656a97fb3af7322fd2c3da5995a2d09d87d4b PATH="$PATH:$NDK_DIR" \ CXXFLAGS="-std=gnu++11" \ ./build-android.sh \ diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 48d30a1ab8..8c878f0901 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -222,49 +222,50 @@ jobs: export NCPU=2 ../configure.sh --ndk /usr/local/lib/android/sdk/ndk-bundle displayName: 'Build for Android' - - job: MacOS_Homebrew - pool: - vmImage: 'macOS-10.14' - steps: - - script: brew install boost openssl ninja - displayName: Brew install dependencies - - script: | - mkdir build.debug - mkdir build.release - mkdir build.release.static - displayName: Make Build Directories - - task: CMake@1 - inputs: - workingDirectory: 'build.debug' - cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' - - task: CMake@1 - inputs: - workingDirectory: 'build.release' - cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' - - task: CMake@1 - inputs: - workingDirectory: 'build.release.static' - cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF ..' - - script: | - cd build.debug - ninja - displayName: 'Run ninja, debug' - - script: | - cd build.debug/Release/Binaries - ./test_runner *test.dylib - displayName: 'Run tests, debug' - - script: | - cd build.release - ninja - displayName: 'Run ninja, release' - - script: | - cd build.release/Release/Binaries - ./test_runner *test.dylib - displayName: 'Run tests, release' - - script: | - cd build.release.static - ninja - displayName: 'Run ninja, release static' + # Homebrew is disabled for now because it apparently is deploying a Boost version that the version of xcode deployed in Pipelines cannot build. + # - job: MacOS_Homebrew + # pool: + # vmImage: 'macOS-10.14' + # steps: + # - script: brew install boost openssl ninja + # displayName: Brew install dependencies + # - script: | + # mkdir build.debug + # mkdir build.release + # mkdir build.release.static + # displayName: Make Build Directories + # - task: CMake@1 + # inputs: + # workingDirectory: 'build.debug' + # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' + # - task: CMake@1 + # inputs: + # workingDirectory: 'build.release' + # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' + # - task: CMake@1 + # inputs: + # workingDirectory: 'build.release.static' + # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF ..' + # - script: | + # cd build.debug + # ninja + # displayName: 'Run ninja, debug' + # - script: | + # cd build.debug/Release/Binaries + # ./test_runner *test.dylib + # displayName: 'Run tests, debug' + # - script: | + # cd build.release + # ninja + # displayName: 'Run ninja, release' + # - script: | + # cd build.release/Release/Binaries + # ./test_runner *test.dylib + # displayName: 'Run tests, release' + # - script: | + # cd build.release.static + # ninja + # displayName: 'Run ninja, release static' - job: MacOS_Vcpkg pool: vmImage: 'macOS-10.14' From a718c5bcf471d7589c5779e6746290743cd0f211 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Fri, 12 Jul 2019 16:27:44 -0700 Subject: [PATCH 13/80] Remove invalid nondependent static assert (#1186) * Remove invalid static_assert(false). * Turn on permissive-. * clang-format --- Release/CMakeLists.txt | 4 ++++ Release/include/cpprest/streams.h | 18 ++++++------------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 9a0bbf1a24..b9e6d6d56a 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -188,6 +188,10 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") if (WINDOWS_STORE OR WINDOWS_PHONE) add_compile_options(/ZW) endif() + + if (NOT (MSVC_VERSION LESS 1920)) + add_compile_options(/permissive-) + endif() else() message("-- Unknown compiler, success is doubtful.") message("CMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID}") diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index bfeeee5885..08713226b7 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -528,9 +528,12 @@ class type_parser public: static pplx::task parse(streams::streambuf buffer) { - typename _type_parser_integral_traits::_is_integral ii; - typename _type_parser_integral_traits::_is_unsigned ui; - return _parse(buffer, ii, ui); + typedef typename _type_parser_integral_traits::_is_integral ii; + typedef typename _type_parser_integral_traits::_is_unsigned ui; + + static_assert(ii::value || !ui::value, "type is not supported for extraction from a stream"); + + return _parse(buffer, ii {}, ui {}); } private: @@ -539,15 +542,6 @@ class type_parser _parse_floating_point(buffer); } - static pplx::task _parse(streams::streambuf, std::false_type, std::true_type) - { -#ifdef _WIN32 - static_assert(false, "type is not supported for extraction from a stream"); -#else - throw std::runtime_error("type is not supported for extraction from a stream"); -#endif - } - static pplx::task _parse(streams::streambuf buffer, std::true_type, std::false_type) { return type_parser::parse(buffer).then([](pplx::task op) -> T { From bed8fa538c862a8297cb02c99d8b3dcc29247d5b Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Fri, 12 Jul 2019 18:05:14 -0700 Subject: [PATCH 14/80] Replace CPPREST_TARGET_XP with version checks, remove ""s, and other cleanup (#1187) * Audit for "" and use std::string default ctor instead. * Fix Linux ambiguity. * Exclude common build directories. * Replace CPPREST_TARGET_XP with checks against _WIN32_WINNT to allow more fine grained controls going forward (e.g. assume Win10). Also fix a few typos. * Delete CASABLANCA_UNREFERENCED_PARAMETER and attempt Linux compile fix. * Defend NOMINMAX. * Another _WIN32 guard. * With && this time. * Fix more spelling errors. * Optimize trim_nulls slightly. * And actually make the optimization correct this time. * Fix unit test failure. * clang-format --- .gitignore | 2 + .vscode/settings.json | 16 ++- .../include/cpprest/details/cpprest_compat.h | 3 - .../include/cpprest/details/web_utilities.h | 30 ++-- Release/include/cpprest/http_client.h | 6 +- Release/include/cpprest/streams.h | 21 ++- Release/include/cpprest/ws_client.h | 7 +- Release/include/cpprest/ws_msg.h | 2 +- Release/include/pplx/pplxtasks.h | 4 +- .../BlackJack_Client/BlackJackClient.cpp | 1 - .../BlackJack/BlackJack_Server/messagetypes.h | 4 +- .../BlackJack/BlackJack_Server/stdafx.h | 3 - .../BlackJack_UIClient/Player.xaml.cpp | 16 ++- .../BlackJack_UIClient/Player.xaml.h | 8 +- .../BlackJack_UIClient/PlayingTable.xaml.cpp | 22 +-- .../BlackJack_UIClient/PlayingTable.xaml.h | 2 +- Release/samples/CasaLens/casalens.cpp | 8 +- Release/samples/OAuth2Live/MainPage.xaml.cpp | 6 +- Release/samples/Oauth1Client/Oauth1Client.cpp | 8 +- Release/samples/Oauth2Client/Oauth2Client.cpp | 14 +- .../samples/WindowsLiveAuth/live_connect.h | 4 +- Release/src/http/client/http_client.cpp | 2 +- Release/src/http/client/http_client_asio.cpp | 26 ++-- .../src/http/client/http_client_winhttp.cpp | 130 +++++++++++------- Release/src/http/client/http_client_winrt.cpp | 18 +-- Release/src/http/common/http_compression.cpp | 4 +- Release/src/http/common/http_msg.cpp | 16 +-- .../src/http/listener/http_server_asio.cpp | 16 +-- .../src/http/listener/http_server_httpsys.cpp | 8 +- .../src/http/listener/http_server_httpsys.h | 6 +- Release/src/http/oauth/oauth1.cpp | 4 +- Release/src/json/json.cpp | 11 +- Release/src/pch/stdafx.h | 24 ++-- Release/src/streams/fileio_posix.cpp | 8 +- Release/src/streams/fileio_win32.cpp | 6 +- Release/src/uri/uri.cpp | 2 +- Release/src/utilities/web_utilities.cpp | 16 ++- Release/src/websockets/client/ws_client.cpp | 3 +- .../src/websockets/client/ws_client_winrt.cpp | 2 +- .../src/websockets/client/ws_client_wspp.cpp | 47 ++++--- .../tests/common/TestRunner/test_runner.cpp | 6 +- Release/tests/common/UnitTestpp/src/Checks.h | 2 +- .../UnitTestpp/src/DeferredTestResult.cpp | 6 +- .../common/UnitTestpp/src/MemoryOutStream.cpp | 2 +- Release/tests/common/UnitTestpp/src/stdafx.h | 1 - .../tests/common/utilities/os_utilities.cpp | 1 - .../http/client/compression_tests.cpp | 22 +-- .../functional/http/client/outside_tests.cpp | 2 +- .../tests/functional/http/utilities/stdafx.h | 1 - .../functional/json/json_numbers_tests.cpp | 16 +-- Release/tests/functional/json/stdafx.h | 1 - .../misc/atl_headers/header_test1.cpp | 1 - .../misc/atl_headers/header_test2.cpp | 1 - .../tests/functional/pplx/pplx_test/stdafx.h | 1 - .../functional/streams/istream_tests.cpp | 2 +- .../functional/streams/memstream_tests.cpp | 1 - .../utils/win32_encryption_tests.cpp | 4 +- .../functional/websockets/utilities/stdafx.h | 1 - 58 files changed, 326 insertions(+), 281 deletions(-) diff --git a/.gitignore b/.gitignore index 8fc8285e16..3a3fea4411 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,5 @@ Build_android/build/ Generated Files/ # Ignore iOS temp build directories Build_iOS/Apple-Boost-BuildScript + +/out/ diff --git a/.vscode/settings.json b/.vscode/settings.json index 2fc5e0c5fe..9bad9cb7c7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,18 @@ "**/.git/objects/**": true, "**/.git/subtree-cache/**": true, "**/node_modules/*/**": true, - "**/vcpkg/**": true - } + "**/vcpkg/**": true, + "build.x86.debug": true, + "build.x86.release": true, + "build.x64.debug": true, + "build.x64.release": true, + "out": true, + }, + "cSpell.words": [ + "XPLATSTR", + "blittable", + "pplx", + "rdpos", + "rgpsz" + ] } diff --git a/Release/include/cpprest/details/cpprest_compat.h b/Release/include/cpprest/details/cpprest_compat.h index c671ce2fe5..6dae41d8d9 100644 --- a/Release/include/cpprest/details/cpprest_compat.h +++ b/Release/include/cpprest/details/cpprest_compat.h @@ -24,8 +24,6 @@ #define CPPREST_CONSTEXPR const #endif // _MSC_VER >= 1900 -#define CASABLANCA_UNREFERENCED_PARAMETER(x) (x) - #include #else // ^^^ _WIN32 ^^^ // vvv !_WIN32 vvv @@ -38,7 +36,6 @@ { \ if (!(x)) __builtin_unreachable(); \ } while (false) -#define CASABLANCA_UNREFERENCED_PARAMETER(x) (void)x #define CPPREST_NOEXCEPT noexcept #define CPPREST_CONSTEXPR constexpr diff --git a/Release/include/cpprest/details/web_utilities.h b/Release/include/cpprest/details/web_utilities.h index 8b99d94aa2..aed7419c85 100644 --- a/Release/include/cpprest/details/web_utilities.h +++ b/Release/include/cpprest/details/web_utilities.h @@ -10,6 +10,10 @@ ****/ #pragma once +#ifdef _WIN32 +#include +#endif // _WIN32 + #include "cpprest/asyncrt_utils.h" #include "cpprest/uri.h" @@ -24,23 +28,24 @@ class zero_memory_deleter }; typedef std::unique_ptr<::utility::string_t, zero_memory_deleter> plaintext_string; -#if defined(_WIN32) && !defined(CPPREST_TARGET_XP) -#if defined(__cplusplus_winrt) +#ifdef _WIN32 +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA +#ifdef __cplusplus_winrt class winrt_encryption { public: - winrt_encryption() {} + winrt_encryption() = default; _ASYNCRTIMP winrt_encryption(const std::wstring& data); _ASYNCRTIMP plaintext_string decrypt() const; private: ::pplx::task m_buffer; }; -#else +#else // ^^^ __cplusplus_winrt ^^^ // vvv !__cplusplus_winrt vvv class win32_encryption { public: - win32_encryption() {} + win32_encryption() = default; _ASYNCRTIMP win32_encryption(const std::wstring& data); _ASYNCRTIMP ~win32_encryption(); _ASYNCRTIMP plaintext_string decrypt() const; @@ -49,8 +54,9 @@ class win32_encryption std::vector m_buffer; size_t m_numCharacters; }; -#endif -#endif +#endif // __cplusplus_winrt +#endif // _WIN32_WINNT >= _WIN32_WINNT_VISTA +#endif // _WIN32 } // namespace details /// @@ -89,7 +95,7 @@ class credentials "This API is deprecated for security reasons to avoid unnecessary password copies stored in plaintext.") utility::string_t password() const { -#if defined(_WIN32) && !defined(CPPREST_TARGET_XP) +#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return utility::string_t(*m_password.decrypt()); #else return m_password; @@ -105,7 +111,7 @@ class credentials details::plaintext_string _internal_decrypt() const { // Encryption APIs not supported on XP -#if defined(_WIN32) && !defined(CPPREST_TARGET_XP) +#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA return m_password.decrypt(); #else return details::plaintext_string(new ::utility::string_t(m_password)); @@ -115,7 +121,7 @@ class credentials private: ::utility::string_t m_username; -#if defined(_WIN32) && !defined(CPPREST_TARGET_XP) +#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA #if defined(__cplusplus_winrt) details::winrt_encryption m_password; #else @@ -151,13 +157,13 @@ class web_proxy /// /// Constructs a proxy with the default settings. /// - web_proxy() : m_address(_XPLATSTR("")), m_mode(use_default_) {} + web_proxy() : m_address(), m_mode(use_default_) {} /// /// Creates a proxy with specified mode. /// /// Mode to use. - web_proxy(web_proxy_mode mode) : m_address(_XPLATSTR("")), m_mode(static_cast(mode)) {} + web_proxy(web_proxy_mode mode) : m_address(), m_mode(static_cast(mode)) {} /// /// Creates a proxy explicitly with provided address. diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 743e2b5635..0bedfbd42a 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -54,7 +54,7 @@ typedef void* native_handle; #include #include -#if !defined(CPPREST_TARGET_XP) +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA #include "cpprest/oauth1.h" #endif @@ -110,7 +110,7 @@ class http_client_config { } -#if !defined(CPPREST_TARGET_XP) +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA /// /// Get OAuth 1.0 configuration. /// @@ -363,7 +363,7 @@ class http_client_config #endif private: -#if !defined(CPPREST_TARGET_XP) +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA std::shared_ptr m_oauth1; #endif diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index 08713226b7..c2968b9d49 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -470,7 +470,7 @@ _UINT_TRAIT(unsigned long long, ULLONG_MIN, ULLONG_MAX) { \ typedef std::true_type _is_integral; \ typedef std::false_type _is_unsigned; \ - static const int64_t _min = std::numeric_limits<_t>::min(); \ + static const int64_t _min = (std::numeric_limits<_t>::min)(); \ static const int64_t _max = (std::numeric_limits<_t>::max)(); \ }; #define _UINT_TRAIT(_t) \ @@ -1139,8 +1139,8 @@ pplx::task _type_parser_base::_parse_input(concurrency::st auto update = [=](pplx::task op) -> pplx::task { int_type ch = op.get(); if (ch == traits::eof()) return pplx::task_from_result(false); - bool accptd = accept_character(state, ch); - if (!accptd) return pplx::task_from_result(false); + bool accepted = accept_character(state, ch); + if (!accepted) return pplx::task_from_result(false); // We peeked earlier, so now we must advance the position. concurrency::streams::streambuf buf = buffer; return buf.bumpc().then([](int_type) { return true; }); @@ -1308,9 +1308,18 @@ struct _double_state template static std::string create_exception_message(int_type ch, bool exponent) { - std::ostringstream os; - os << "Invalid character '" << char(ch) << "'" << (exponent ? " in exponent" : ""); - return os.str(); + std::string result; + if (exponent) + { + result.assign("Invalid character 'X' in exponent"); + } + else + { + result.assign("Invalid character 'X'"); + } + + result[19] = static_cast(ch); + return result; } template diff --git a/Release/include/cpprest/ws_client.h b/Release/include/cpprest/ws_client.h index 9c202d7f73..af17bd6060 100644 --- a/Release/include/cpprest/ws_client.h +++ b/Release/include/cpprest/ws_client.h @@ -330,8 +330,7 @@ class websocket_client_callback_impl virtual pplx::task close() = 0; - virtual pplx::task close(websocket_close_status close_status, - const utility::string_t& close_reason = _XPLATSTR("")) = 0; + virtual pplx::task close(websocket_close_status close_status, const utility::string_t& close_reason = {}) = 0; virtual void set_close_handler( const std::function& @@ -478,7 +477,7 @@ class websocket_client /// frame. While closing an established connection, an endpoint may indicate the /// reason for closure. An asynchronous operation that is completed the connection has been /// successfully closed. - pplx::task close(websocket_close_status close_status, const utility::string_t& close_reason = _XPLATSTR("")) + pplx::task close(websocket_close_status close_status, const utility::string_t& close_reason = {}) { return m_client->callback_client()->close(close_status, close_reason); } @@ -566,7 +565,7 @@ class websocket_callback_client /// frame. While closing an established connection, an endpoint may indicate the /// reason for closure. An asynchronous operation that is completed the connection has been /// successfully closed. - pplx::task close(websocket_close_status close_status, const utility::string_t& close_reason = _XPLATSTR("")) + pplx::task close(websocket_close_status close_status, const utility::string_t& close_reason = {}) { return m_client->close(close_status, close_reason); } diff --git a/Release/include/cpprest/ws_msg.h b/Release/include/cpprest/ws_msg.h index 73e968a001..9b13a80849 100644 --- a/Release/include/cpprest/ws_msg.h +++ b/Release/include/cpprest/ws_msg.h @@ -74,7 +74,7 @@ class websocket_outgoing_message /// /// UTF-8 String containing the optional pong message. void set_pong_message(const std::string& data = {}) - { + { this->set_message_pong(concurrency::streams::container_buffer(data)); } #endif diff --git a/Release/include/pplx/pplxtasks.h b/Release/include/pplx/pplxtasks.h index 63cedc4f28..6868fc1619 100644 --- a/Release/include/pplx/pplxtasks.h +++ b/Release/include/pplx/pplxtasks.h @@ -3799,7 +3799,7 @@ class task auto _LogWorkItemAndInvokeUserLambda(_Func&& _func) const -> decltype(_func()) { details::_TaskWorkItemRAIILogger _LogWorkItem(this->_M_pTask->_M_taskEventLogger); - CASABLANCA_UNREFERENCED_PARAMETER(_LogWorkItem); + (void)_LogWorkItem; return _func(); } @@ -3931,7 +3931,7 @@ class task -> decltype(_func(std::forward<_Arg>(_value))) { details::_TaskWorkItemRAIILogger _LogWorkItem(this->_M_pTask->_M_taskEventLogger); - CASABLANCA_UNREFERENCED_PARAMETER(_LogWorkItem); + (void)_LogWorkItem; return _func(std::forward<_Arg>(_value)); } diff --git a/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp b/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp index 5c9b1fc4b1..184ab42937 100644 --- a/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp +++ b/Release/samples/BlackJack/BlackJack_Client/BlackJackClient.cpp @@ -17,7 +17,6 @@ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif -#define NOMINMAX #include #include diff --git a/Release/samples/BlackJack/BlackJack_Server/messagetypes.h b/Release/samples/BlackJack/BlackJack_Server/messagetypes.h index 91c633984e..f38556dde3 100644 --- a/Release/samples/BlackJack/BlackJack_Server/messagetypes.h +++ b/Release/samples/BlackJack/BlackJack_Server/messagetypes.h @@ -179,7 +179,7 @@ struct BJHand { if (iter->value == CV_Ace) hasAces = true; - res.low += std::min((int)iter->value, 10); + res.low += (std::min)((int)iter->value, 10); } res.high = hasAces ? res.low + 10 : res.low; return res; @@ -271,7 +271,7 @@ struct Player static Player FromJSON(const web::json::object& object) { - Player result(U("")); + Player result(utility::string_t{}); auto iName = object.find(NAME); if (iName == object.end()) diff --git a/Release/samples/BlackJack/BlackJack_Server/stdafx.h b/Release/samples/BlackJack/BlackJack_Server/stdafx.h index ae59ac7dbd..d9bef583ff 100644 --- a/Release/samples/BlackJack/BlackJack_Server/stdafx.h +++ b/Release/samples/BlackJack/BlackJack_Server/stdafx.h @@ -26,9 +26,6 @@ #include #ifdef _WIN32 -#ifndef NOMINMAX -#define NOMINMAX -#endif #include #else #include diff --git a/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.cpp b/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.cpp index e32a766883..394165a53c 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.cpp +++ b/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.cpp @@ -54,7 +54,13 @@ void PlayerSpace::Update(Player player) playerName->Text = ref new Platform::String(web::uri::decode(player.Name).c_str()); playerBalance->Text = "$" + player.Balance.ToString(); playerBet->Text = "Bet: $" + player.Hand.bet.ToString(); - playerInsurance->Text = (player.Hand.insurance > 0) ? "Ins: $" + player.Hand.insurance.ToString() : ""; + if (player.Hand.insurance > 0) { + auto& text = playerInsurance->Text; + text.assign("Ins: $"); + text.append(std::to_string(player.Hand.insurance)); + } else { + text.clear(); + } } void PlayerSpace::AddCard(Card card) @@ -87,19 +93,19 @@ void PlayerSpace::ShowResult(BJHandResult result) { case BJHandResult::HR_ComputerWin: playerInsurance->Text = L"Dealer Wins"; - playerBet->Text = L""; + playerBet->Text.clear(); break; case BJHandResult::HR_PlayerWin: playerInsurance->Text = L"Player Wins"; - playerBet->Text = L""; + playerBet->Text.clear(); break; case BJHandResult::HR_Push: playerInsurance->Text = L"Push"; - playerBet->Text = L""; + playerBet->Text.clear(); break; case BJHandResult::HR_PlayerBlackJack: playerInsurance->Text = L"Blackjack!"; - playerBet->Text = L""; + playerBet->Text.clear(); break; default: break; } diff --git a/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.h b/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.h index 429d5e38c3..5b7ee7462b 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.h +++ b/Release/samples/BlackJack/BlackJack_UIClient/Player.xaml.h @@ -25,10 +25,10 @@ ref class PlayerSpace sealed void Clear() { - playerBalance->Text = L""; - playerBet->Text = L""; - playerName->Text = L""; - playerInsurance->Text = L""; + playerBalance->Text.clear(); + playerBet->Text.clear(); + playerName->Text.clear(); + playerInsurance->Text.clear(); m_cards.clear(); playerCardGrid->Children->Clear(); } diff --git a/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp b/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp index 64fd0adae6..5f835e1b3f 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp +++ b/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.cpp @@ -116,7 +116,7 @@ void BlackjackClient::PlayingTable::Refresh() request.then( [this](pplx::task tsk) { - this->resultLabel->Text = L""; + this->resultLabel->Text.clear(); try { @@ -137,7 +137,7 @@ void BlackjackClient::PlayingTable::InterpretResponse(http_response& response) { if (response.headers().content_type() != L"application/json") return; - this->resultLabel->Text = L""; + this->resultLabel->Text.clear(); response.extract_json().then( [this, response](json::value jsonResponse) { @@ -265,7 +265,7 @@ void BlackjackClient::PlayingTable::BetButton_Click(Platform::Object ^ sender, request.then( [this](pplx::task tsk) { - this->resultLabel->Text = L""; + this->resultLabel->Text.clear(); try { @@ -307,7 +307,7 @@ void BlackjackClient::PlayingTable::InsuranceButton_Click(Platform::Object ^ sen request.then( [this](pplx::task tsk) { - this->resultLabel->Text = L""; + this->resultLabel->Text.clear(); try { @@ -343,7 +343,7 @@ void BlackjackClient::PlayingTable::DoubleButton_Click(Platform::Object ^ sender request.then( [this](pplx::task tsk) { - this->resultLabel->Text = L""; + this->resultLabel->Text.clear(); try { @@ -378,7 +378,7 @@ void BlackjackClient::PlayingTable::StayButton_Click(Platform::Object ^ sender, request.then( [this](pplx::task tsk) { - this->resultLabel->Text = L""; + this->resultLabel->Text.clear(); try { @@ -412,7 +412,7 @@ void BlackjackClient::PlayingTable::HitButton_Click(Platform::Object ^ sender, request.then( [this](pplx::task tsk) { - this->resultLabel->Text = L""; + this->resultLabel->Text.clear(); try { @@ -449,7 +449,7 @@ void BlackjackClient::PlayingTable::ExitButton_Click(Platform::Object ^ sender, [this](pplx::task tsk) { EnableExit(); - this->resultLabel->Text = L""; + this->resultLabel->Text.clear(); try { @@ -499,7 +499,7 @@ void BlackjackClient::PlayingTable::JoinButton_Click(Platform::Object ^ sender, [this](pplx::task tsk) { EnableExit(); - this->resultLabel->Text = L""; + this->resultLabel->Text.clear(); try { @@ -516,7 +516,7 @@ void BlackjackClient::PlayingTable::JoinButton_Click(Platform::Object ^ sender, { InterpretError(exc.error_code().value()); EnableConnecting(); - _tableId = L""; + _tableId.clear(); } }, ctx); @@ -551,7 +551,7 @@ void BlackjackClient::PlayingTable::LeaveButton_Click(Platform::Object ^ sender, this->resultLabel->Text = L"Thanks for playing!"; - _tableId = L""; + _tableId.clear(); } catch (const http_exception& exc) { diff --git a/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.h b/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.h index 589c1f9e6c..9f2fbe689a 100644 --- a/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.h +++ b/Release/samples/BlackJack/BlackJack_UIClient/PlayingTable.xaml.h @@ -93,7 +93,7 @@ ref class PlayingTable sealed { ClearDealerCards(); ClearPlayerCards(); - resultLabel->Text = ""; + resultLabel->Text.clear(); } void EnableBetting() diff --git a/Release/samples/CasaLens/casalens.cpp b/Release/samples/CasaLens/casalens.cpp index c98e926abf..5990ef240f 100644 --- a/Release/samples/CasaLens/casalens.cpp +++ b/Release/samples/CasaLens/casalens.cpp @@ -30,13 +30,13 @@ const utility::string_t casalens_creds::weather_url = U("http://api.openweatherm // FILL IN THE API KEYS FOR THE DIFFERENT SERVICES HERE. // Refer Readme.txt for details on how to obtain the key for the services. const utility::string_t casalens_creds::events_keyname = U("app_key"); -const utility::string_t casalens_creds::events_key = U(""); +const utility::string_t casalens_creds::events_key; const utility::string_t casalens_creds::movies_keyname = U("api_key"); -const utility::string_t casalens_creds::movies_key = U(""); +const utility::string_t casalens_creds::movies_key; const utility::string_t casalens_creds::images_keyname = U("username"); -const utility::string_t casalens_creds::images_key = U(""); +const utility::string_t casalens_creds::images_key; const utility::string_t casalens_creds::bmaps_keyname = U("key"); -const utility::string_t casalens_creds::bmaps_key = U(""); +const utility::string_t casalens_creds::bmaps_key; const utility::string_t CasaLens::events_json_key = U("events"); const utility::string_t CasaLens::movies_json_key = U("movies"); diff --git a/Release/samples/OAuth2Live/MainPage.xaml.cpp b/Release/samples/OAuth2Live/MainPage.xaml.cpp index acdc7ba4e3..fef5d2d365 100644 --- a/Release/samples/OAuth2Live/MainPage.xaml.cpp +++ b/Release/samples/OAuth2Live/MainPage.xaml.cpp @@ -29,8 +29,8 @@ using namespace web::http::oauth2::experimental; // // NOTE: You must set this Live key and secret for app to work. // -static const utility::string_t s_live_key(U("")); -static const utility::string_t s_live_secret(U("")); +static const utility::string_t s_live_key; +static const utility::string_t s_live_secret; MainPage::MainPage() : m_live_oauth2_config(s_live_key, @@ -69,7 +69,7 @@ void OAuth2Live::MainPage::_GetToken() // Start over, clear tokens and button state. m_live_oauth2_config.set_token(oauth2_token()); - AccessToken->Text = ""; + AccessToken->Text.clear(); _UpdateButtonState(); String ^ authURI = ref new String(m_live_oauth2_config.build_authorization_uri(true).c_str()); diff --git a/Release/samples/Oauth1Client/Oauth1Client.cpp b/Release/samples/Oauth1Client/Oauth1Client.cpp index da09fda29f..dec9b342b5 100644 --- a/Release/samples/Oauth1Client/Oauth1Client.cpp +++ b/Release/samples/Oauth1Client/Oauth1Client.cpp @@ -49,11 +49,11 @@ using namespace web::http::experimental::listener; // // Set key & secret pair to enable session for that service. // -static const utility::string_t s_linkedin_key(U("")); -static const utility::string_t s_linkedin_secret(U("")); +static const utility::string_t s_linkedin_key; +static const utility::string_t s_linkedin_secret; -static const utility::string_t s_twitter_key(U("")); -static const utility::string_t s_twitter_secret(U("")); +static const utility::string_t s_twitter_key; +static const utility::string_t s_twitter_secret; // // Utility method to open browser on Windows, OS X and Linux systems. diff --git a/Release/samples/Oauth2Client/Oauth2Client.cpp b/Release/samples/Oauth2Client/Oauth2Client.cpp index 2d82a70f18..19072cf6c6 100644 --- a/Release/samples/Oauth2Client/Oauth2Client.cpp +++ b/Release/samples/Oauth2Client/Oauth2Client.cpp @@ -49,14 +49,14 @@ using namespace web::http::experimental::listener; // // Set key & secret pair to enable session for that service. // -static const utility::string_t s_dropbox_key(U("")); -static const utility::string_t s_dropbox_secret(U("")); +static const utility::string_t s_dropbox_key; +static const utility::string_t s_dropbox_secret; -static const utility::string_t s_linkedin_key(U("")); -static const utility::string_t s_linkedin_secret(U("")); +static const utility::string_t s_linkedin_key; +static const utility::string_t s_linkedin_secret; -static const utility::string_t s_live_key(U("")); -static const utility::string_t s_live_secret(U("")); +static const utility::string_t s_live_key; +static const utility::string_t s_live_secret; // // Utility method to open browser on Windows, OS X and Linux systems. @@ -89,7 +89,7 @@ class oauth2_code_listener : m_listener(new http_listener(listen_uri)), m_config(config) { m_listener->support([this](http::http_request request) -> void { - if (request.request_uri().path() == U("/") && request.request_uri().query() != U("")) + if (request.request_uri().path() == U("/") && !request.request_uri().query().empty()) { m_resplock.lock(); diff --git a/Release/samples/WindowsLiveAuth/live_connect.h b/Release/samples/WindowsLiveAuth/live_connect.h index c8381df046..325538c84f 100644 --- a/Release/samples/WindowsLiveAuth/live_connect.h +++ b/Release/samples/WindowsLiveAuth/live_connect.h @@ -338,7 +338,7 @@ class live_client web::http::http_request req(web::http::methods::PUT); req.set_request_uri(bldr.to_string()); - req.set_body(stream, content_length, U("")); + req.set_body(stream, content_length, utility::string_t{}); return _make_request(req).then([](web::http::http_response response) { return _json_extract(response); }); } @@ -368,7 +368,7 @@ class live_client web::http::http_request req(web::http::methods::PUT); req.set_request_uri(bldr.to_string()); - req.set_body(stream, size, U("")); + req.set_body(stream, size, utility::string_t{}); return _make_request(req) .then([](web::http::http_response response) { return response.content_ready(); }) diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index 41230ea517..f3174272bb 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -386,7 +386,7 @@ http_client::http_client(const uri& base_uri, const http_client_config& client_c m_pipeline = std::make_shared(std::move(final_pipeline_stage)); -#if !defined(CPPREST_TARGET_XP) +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA add_handler(std::static_pointer_cast( std::make_shared(client_config.oauth1()))); #endif diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index c5c815eec7..f8401d6e99 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -87,8 +87,7 @@ namespace { const std::string CRLF("\r\n"); -std::string calc_cn_host(const web::http::uri& baseUri, - const web::http::http_headers& requestHeaders) +std::string calc_cn_host(const web::http::uri& baseUri, const web::http::http_headers& requestHeaders) { std::string result; if (baseUri.scheme() == U("https")) @@ -905,7 +904,8 @@ class asio_context final : public request_context, public std::enable_shared_fro } }; - // Note that we must not try to CONNECT using an already established connection via proxy -- this would send CONNECT to the end server which is definitely not what we want. + // Note that we must not try to CONNECT using an already established connection via proxy -- this would send + // CONNECT to the end server which is definitely not what we want. if (proxy_type == http_proxy_type::ssl_tunnel && !m_connection->is_reused()) { // The ssl_tunnel_proxy keeps the context alive and then calls back once the ssl tunnel is established via @@ -1234,8 +1234,8 @@ class asio_context final : public request_context, public std::enable_shared_fro } const auto this_request = shared_from_this(); - const auto readSize = static_cast( - std::min(static_cast(m_http_client->client_config().chunksize()), m_content_length - m_uploaded)); + const auto readSize = static_cast((std::min)( + static_cast(m_http_client->client_config().chunksize()), m_content_length - m_uploaded)); auto readbuf = _get_readbuffer(); readbuf.getn(boost::asio::buffer_cast(m_body_buf.prepare(readSize)), readSize) .then([this_request AND_CAPTURE_MEMBER_FUNCTION_POINTERS](pplx::task op) { @@ -1487,8 +1487,8 @@ class asio_context final : public request_context, public std::enable_shared_fro if (!needChunked) { async_read_until_buffersize( - static_cast( - std::min(m_content_length, static_cast(m_http_client->client_config().chunksize()))), + static_cast((std::min)(m_content_length, + static_cast(m_http_client->client_config().chunksize()))), boost::bind( &asio_context::handle_read_content, shared_from_this(), boost::asio::placeholders::error)); } @@ -1572,7 +1572,7 @@ class asio_context final : public request_context, public std::enable_shared_fro { if (inbytes) { - output.resize(output.size() + std::max(input_size, static_cast(1024))); + output.resize(output.size() + (std::max)(input_size, static_cast(1024))); } got = m_decompressor->decompress(input + inbytes, input_size - inbytes, @@ -1710,7 +1710,7 @@ class asio_context final : public request_context, public std::enable_shared_fro if (ec) { - if (ec == boost::asio::error::eof && m_content_length == std::numeric_limits::max()) + if (ec == boost::asio::error::eof && m_content_length == (std::numeric_limits::max)()) { m_content_length = m_downloaded + m_body_buf.size(); } @@ -1742,7 +1742,7 @@ class asio_context final : public request_context, public std::enable_shared_fro const auto this_request = shared_from_this(); auto read_size = static_cast( - std::min(static_cast(m_body_buf.size()), m_content_length - m_downloaded)); + (std::min)(static_cast(m_body_buf.size()), m_content_length - m_downloaded)); if (m_decompressor) { @@ -1765,7 +1765,7 @@ class asio_context final : public request_context, public std::enable_shared_fro this_request->m_downloaded += static_cast(read_size); this_request->async_read_until_buffersize( - static_cast(std::min( + static_cast((std::min)( static_cast(this_request->m_http_client->client_config().chunksize()), this_request->m_content_length - this_request->m_downloaded)), boost::bind( @@ -1794,7 +1794,7 @@ class asio_context final : public request_context, public std::enable_shared_fro this_request->m_downloaded += static_cast(read_size); this_request->m_body_buf.consume(read_size); this_request->async_read_until_buffersize( - static_cast(std::min( + static_cast((std::min)( static_cast(this_request->m_http_client->client_config().chunksize()), this_request->m_content_length - this_request->m_downloaded)), boost::bind(&asio_context::handle_read_content, @@ -1820,7 +1820,7 @@ class asio_context final : public request_context, public std::enable_shared_fro this_request->m_downloaded += static_cast(writtenSize); this_request->m_body_buf.consume(writtenSize); this_request->async_read_until_buffersize( - static_cast(std::min( + static_cast((std::min)( static_cast(this_request->m_http_client->client_config().chunksize()), this_request->m_content_length - this_request->m_downloaded)), boost::bind(&asio_context::handle_read_content, diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 61a13abfb5..a6e5a226b1 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -20,7 +20,7 @@ #include #include -#ifndef CPPREST_TARGET_XP +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA #include #endif @@ -102,13 +102,46 @@ static http::status_code parse_status_code(HINTERNET request_handle) // Helper function to trim leading and trailing null characters from a string. static void trim_nulls(utility::string_t& str) { - size_t index; - for (index = 0; index < str.size() && str[index] == 0; ++index) - ; - str.erase(0, index); - for (index = str.size(); index > 0 && str[index - 1] == 0; --index) - ; - str.erase(index); + if (str.empty()) + { + return; + } + + auto first = str.begin(); + auto last = str.end(); + + if (*first) + { + --last; + if (*last) + { + // no nulls to remove + return; + } + + // nulls at the back to remove + do + { + --last; + } while (*last == utility::char_t {}); + ++last; + str.erase(last, str.end()); + return; + } + + // nulls at the front, and maybe the back, to remove + first = std::find_if(str.begin(), last, [](const utility::char_t c) { return c != utility::char_t {}; }); + + if (first != last) + { + do + { + --last; + } while (*last == utility::char_t {}); + ++last; + } + + str.assign(first, last); } // Helper function to get the reason phrase from a WinHTTP response. @@ -245,7 +278,7 @@ class winhttp_request_context final : public request_context HINTERNET m_request_handle; std::weak_ptr* - m_request_handle_context; // owned by m_request_handle to be delete'd by WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING + m_request_handle_context; // owned by m_request_handle to be deleted by WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING bool m_proxy_authentication_tried; bool m_server_authentication_tried; @@ -464,7 +497,7 @@ class winhttp_request_context final : public request_context if (m_bytes_remaining) { // We're at the offset of a chunk of consumable data; let the caller process it - l = std::min(m_bytes_remaining, buffer_size - n); + l = (std::min)(m_bytes_remaining, buffer_size - n); m_bytes_remaining -= l; if (!m_bytes_remaining) { @@ -803,12 +836,12 @@ class winhttp_client final : public _http_client_communicator access_type = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; proxy_name = WINHTTP_NO_PROXY_NAME; -#ifdef CPPREST_TARGET_XP +#if _WIN32_WINNT < _WIN32_WINNT_VISTA if (config.proxy().is_auto_discovery()) { m_proxy_auto_config = true; } -#else // ^^^ CPPREST_TARGET_XP ^^^ // vvv !CPPREST_TARGET_XP vvv +#else // ^^^ _WIN32_WINNT < _WIN32_WINNT_VISTA ^^^ // vvv _WIN32_WINNT >= _WIN32_WINNT_VISTA vvv if (IsWindows8Point1OrGreater()) { // Windows 8.1 and newer supports automatic proxy discovery and auto-fallback to IE proxy settings @@ -854,7 +887,7 @@ class winhttp_client final : public _http_client_communicator m_proxy_auto_config = true; } } -#endif // CPPREST_TARGET_XP +#endif // _WIN32_WINNT < _WIN32_WINNT_VISTA } else { @@ -908,7 +941,7 @@ class winhttp_client final : public _http_client_communicator } // Enable TLS 1.1 and 1.2 -#if !defined(CPPREST_TARGET_XP) +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA BOOL win32_result(FALSE); DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | @@ -1074,11 +1107,11 @@ class winhttp_client final : public _http_client_communicator if (client_config().validate_certificates()) { // if we are validating certificates, also turn on revocation checking - DWORD dwEnableSSLRevocOpt = WINHTTP_ENABLE_SSL_REVOCATION; + DWORD dwEnableSSLRevocationOpt = WINHTTP_ENABLE_SSL_REVOCATION; if (!WinHttpSetOption(winhttp_context->m_request_handle, WINHTTP_OPTION_ENABLE_FEATURE, - &dwEnableSSLRevocOpt, - sizeof(dwEnableSSLRevocOpt))) + &dwEnableSSLRevocationOpt, + sizeof(dwEnableSSLRevocationOpt))) { auto errorCode = GetLastError(); request->report_error(errorCode, build_error_msg(errorCode, "Error enabling SSL revocation check")); @@ -1134,7 +1167,7 @@ class winhttp_client final : public _http_client_communicator } // There is a request body that needs to be transferred. - if (content_length == std::numeric_limits::max()) + if (content_length == (std::numeric_limits::max)()) { // The content length is not set and the application set a stream. This is an // indication that we will use transfer encoding chunked. We still want to @@ -1315,11 +1348,11 @@ class winhttp_client final : public _http_client_communicator chunk_size = p_request_context->m_body_data.size() - http::details::chunked_encoding::additional_encoding_space; } - else if (p_request_context->m_remaining_to_write != std::numeric_limits::max()) + else if (p_request_context->m_remaining_to_write != (std::numeric_limits::max)()) { // Choose a semi-intelligent size based on how much total data is left to compress - chunk_size = std::min(static_cast(p_request_context->m_remaining_to_write) + 128, - p_request_context->m_http_client->client_config().chunksize()); + chunk_size = (std::min)(static_cast(p_request_context->m_remaining_to_write) + 128, + p_request_context->m_http_client->client_config().chunksize()); } else { @@ -1331,8 +1364,8 @@ class winhttp_client final : public _http_client_communicator { // We're not compressing; use the smaller of the remaining data (if known) and the configured (or default) // chunk size - chunk_size = std::min(static_cast(p_request_context->m_remaining_to_write), - p_request_context->m_http_client->client_config().chunksize()); + chunk_size = (std::min)(static_cast(p_request_context->m_remaining_to_write), + p_request_context->m_http_client->client_config().chunksize()); } p_request_context->allocate_request_space( nullptr, chunk_size + http::details::chunked_encoding::additional_encoding_space); @@ -1370,7 +1403,7 @@ class winhttp_client final : public _http_client_communicator chunk_size + http::details::chunked_encoding::additional_encoding_space, bytes_read); - if (!compressor && p_request_context->m_remaining_to_write != std::numeric_limits::max()) + if (!compressor && p_request_context->m_remaining_to_write != (std::numeric_limits::max)()) { if (bytes_read == 0 && p_request_context->m_remaining_to_write) { @@ -1465,7 +1498,7 @@ class winhttp_client final : public _http_client_communicator p_request_context->m_compression_state.m_bytes_read) { if (p_request_context->m_remaining_to_write && - p_request_context->m_remaining_to_write != std::numeric_limits::max()) + p_request_context->m_remaining_to_write != (std::numeric_limits::max)()) { // The stream ended earlier than we detected it should return pplx::task_from_exception(http_exception( @@ -1518,7 +1551,7 @@ class winhttp_client final : public _http_client_communicator p_request_context->m_compression_state.m_bytes_processed += r.input_bytes_processed; _ASSERTE(p_request_context->m_compression_state.m_bytes_processed <= p_request_context->m_compression_state.m_bytes_read); - if (p_request_context->m_remaining_to_write != std::numeric_limits::max()) + if (p_request_context->m_remaining_to_write != (std::numeric_limits::max)()) { _ASSERTE(p_request_context->m_remaining_to_write >= r.input_bytes_processed); p_request_context->m_remaining_to_write -= r.input_bytes_processed; @@ -1568,7 +1601,7 @@ class winhttp_client final : public _http_client_communicator return; } else if (p_request_context->m_remaining_to_write && - p_request_context->m_remaining_to_write != std::numeric_limits::max()) + p_request_context->m_remaining_to_write != (std::numeric_limits::max)()) { // Unexpected end-of-stream. p_request_context->report_error(GetLastError(), @@ -1586,8 +1619,8 @@ class winhttp_client final : public _http_client_communicator } else { - length = std::min(static_cast(p_request_context->m_remaining_to_write), - p_request_context->m_http_client->client_config().chunksize()); + length = (std::min)(static_cast(p_request_context->m_remaining_to_write), + p_request_context->m_http_client->client_config().chunksize()); if (p_request_context->m_compression_state.m_buffer.capacity() < length) { p_request_context->m_compression_state.m_buffer.reserve(length); @@ -1842,7 +1875,7 @@ class winhttp_client final : public _http_client_communicator if (content_length > 0) { // There is a request body that needs to be transferred. - if (content_length == std::numeric_limits::max()) + if (content_length == (std::numeric_limits::max)()) { // The content length is unknown and the application set a stream. This is an // indication that we will need to chunk the data. @@ -1873,7 +1906,7 @@ class winhttp_client final : public _http_client_communicator static void CALLBACK completion_callback( HINTERNET hRequestHandle, DWORD_PTR context, DWORD statusCode, _In_ void* statusInfo, DWORD statusInfoLength) { - CASABLANCA_UNREFERENCED_PARAMETER(statusInfoLength); + (void)statusInfoLength; std::weak_ptr* p_weak_request_context = reinterpret_cast*>(context); @@ -2208,8 +2241,8 @@ class winhttp_client final : public _http_client_communicator if (p_request_context->m_decompressor) { - size_t chunk_size = std::max(static_cast(bytesRead), - p_request_context->m_http_client->client_config().chunksize()); + size_t chunk_size = (std::max)(static_cast(bytesRead), + p_request_context->m_http_client->client_config().chunksize()); p_request_context->m_compression_state.m_bytes_read = static_cast(bytesRead); p_request_context->m_compression_state.m_chunk_bytes = 0; @@ -2396,24 +2429,23 @@ class winhttp_client final : public _http_client_communicator return keep_going(p_request_context.get()); }); }); - }) - .then([p_request_context](pplx::task op) { - try - { - bool ignored = op.get(); - } - catch (...) + }).then([p_request_context](pplx::task op) { + try + { + bool ignored = op.get(); + } + catch (...) + { + // We're only here to pick up any exception that may have been thrown, and to clean up + // if needed + if (p_request_context->m_compression_state.m_acquired) { - // We're only here to pick up any exception that may have been thrown, and to clean up - // if needed - if (p_request_context->m_compression_state.m_acquired) - { - p_request_context->_get_writebuffer().commit(0); - p_request_context->m_compression_state.m_acquired = nullptr; - } - p_request_context->report_exception(std::current_exception()); + p_request_context->_get_writebuffer().commit(0); + p_request_context->m_compression_state.m_acquired = nullptr; } - }); + p_request_context->report_exception(std::current_exception()); + } + }); } else { diff --git a/Release/src/http/client/http_client_winrt.cpp b/Release/src/http/client/http_client_winrt.cpp index 294227512d..a95d9b3431 100644 --- a/Release/src/http/client/http_client_winrt.cpp +++ b/Release/src/http/client/http_client_winrt.cpp @@ -188,7 +188,7 @@ class IRequestStream final { public: IRequestStream(const std::weak_ptr& context, - size_t read_length = std::numeric_limits::max()) + size_t read_length = (std::numeric_limits::max)()) : m_context(context), m_read_length(read_length) { // read_length is the initial length of the ISequentialStream that is available for read @@ -253,9 +253,9 @@ class IRequestStream final _In_ ULONG cb, _Out_opt_ ULONG* pcbWritten) { - CASABLANCA_UNREFERENCED_PARAMETER(pv); - CASABLANCA_UNREFERENCED_PARAMETER(cb); - CASABLANCA_UNREFERENCED_PARAMETER(pcbWritten); + (void)pv; + (void)cb; + (void)pcbWritten; return E_NOTIMPL; } @@ -345,9 +345,9 @@ class IResponseStream final _In_ ULONG cb, _Out_ ULONG* pcbRead) { - CASABLANCA_UNREFERENCED_PARAMETER(pv); - CASABLANCA_UNREFERENCED_PARAMETER(cb); - CASABLANCA_UNREFERENCED_PARAMETER(pcbRead); + (void)pv; + (void)cb; + (void)pcbRead; return E_NOTIMPL; } @@ -403,7 +403,7 @@ class winrt_client final : public _http_client_communicator } const size_t content_length = msg._get_impl()->_get_content_length(); - if (content_length == std::numeric_limits::max()) + if (content_length == (std::numeric_limits::max)()) { // IXHR2 does not allow transfer encoding chunked. So the user is expected to set the content length request->report_exception(http_exception(L"Content length is not specified in the http headers")); @@ -478,7 +478,7 @@ class winrt_client final : public _http_client_communicator // Set timeout. ULONGLONG timeout = static_cast(config.timeout().count()); - timeout = std::max(timeout, std::numeric_limits::min() + 1); + timeout = (std::max)(timeout, (std::numeric_limits::min)() + 1); hr = winrt_context->m_hRequest->SetProperty(XHR_PROP_TIMEOUT, timeout); if (FAILED(hr)) { diff --git a/Release/src/http/common/http_compression.cpp b/Release/src/http/common/http_compression.cpp index 691914488a..a65adc2468 100644 --- a/Release/src/http/common/http_compression.cpp +++ b/Release/src/http/common/http_compression.cpp @@ -97,7 +97,7 @@ class zlib_compressor_base : public compress_provider #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wtautological-constant-compare" #endif // __clang__ - if (input_size > std::numeric_limits::max() || output_size > std::numeric_limits::max()) + if (input_size > (std::numeric_limits::max)() || output_size > (std::numeric_limits::max)()) #if defined(__clang__) #pragma clang diagnostic pop #endif // __clang__ @@ -198,7 +198,7 @@ class zlib_decompressor_base : public decompress_provider #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wtautological-constant-compare" #endif // __clang__ - if (input_size > std::numeric_limits::max() || output_size > std::numeric_limits::max()) + if (input_size > (std::numeric_limits::max)() || output_size > (std::numeric_limits::max)()) #if defined(__clang__) #pragma clang diagnostic pop #endif // __clang__ diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index 50332fd1e9..c32dfcfaaa 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -287,11 +287,7 @@ static const utility::char_t* stream_was_set_explicitly = static const utility::char_t* unsupported_charset = _XPLATSTR("Charset must be iso-8859-1, utf-8, utf-16, utf-16le, or utf-16be to be extracted."); -http_msg_base::http_msg_base() - : m_http_version(http::http_version{ 0, 0 }) - , m_headers() - , m_default_outstream(false) -{} +http_msg_base::http_msg_base() : m_http_version(http::http_version {0, 0}), m_headers(), m_default_outstream(false) {} void http_msg_base::_prepare_to_receive_data() { @@ -326,7 +322,7 @@ size_t http_msg_base::_get_stream_length() return static_cast(end - offset); } - return std::numeric_limits::max(); + return (std::numeric_limits::max)(); } size_t http_msg_base::_get_content_length(bool honor_compression) @@ -356,7 +352,7 @@ size_t http_msg_base::_get_content_length(bool honor_compression) } } - return std::numeric_limits::max(); + return (std::numeric_limits::max)(); } if (honor_compression && m_compressor) @@ -365,7 +361,7 @@ size_t http_msg_base::_get_content_length(bool honor_compression) // up front for content encoding. We return the uncompressed length if we can figure it out. headers().add(header_names::transfer_encoding, m_compressor->algorithm()); headers().add(header_names::transfer_encoding, _XPLATSTR("chunked")); - return std::numeric_limits::max(); + return (std::numeric_limits::max)(); } if (headers().match(header_names::content_length, content_length)) @@ -376,7 +372,7 @@ size_t http_msg_base::_get_content_length(bool honor_compression) } content_length = _get_stream_length(); - if (content_length != std::numeric_limits::max()) + if (content_length != (std::numeric_limits::max)()) { // The content length wasn't explicitly set, but we figured it out; // use it, since sending this way is more efficient than chunking @@ -386,7 +382,7 @@ size_t http_msg_base::_get_content_length(bool honor_compression) // We don't know the content length; we'll chunk the stream headers().add(header_names::transfer_encoding, _XPLATSTR("chunked")); - return std::numeric_limits::max(); + return (std::numeric_limits::max)(); } // There is no content diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 96a24f6be6..f1d8c819c5 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -175,7 +175,7 @@ class hostport_listener auto path_segments = uri::split_path(uri::decode(u.path())); for (auto i = static_cast(path_segments.size()); i >= 0; --i) { - std::string path = ""; + std::string path; for (size_t j = 0; j < static_cast(i); ++j) { path += "/" + utility::conversions::to_utf8string(path_segments[j]); @@ -520,9 +520,9 @@ void hostport_listener::start() auto& service = crossplat::threadpool::shared_instance().service(); tcp::resolver resolver(service); // #446: boost resolver does not recognize "+" as a host wildchar - tcp::resolver::query query = ("+" == m_host) ? - tcp::resolver::query(m_port, boost::asio::ip::resolver_query_base::flags()) : - tcp::resolver::query(m_host, m_port, boost::asio::ip::resolver_query_base::flags()); + tcp::resolver::query query = + ("+" == m_host) ? tcp::resolver::query(m_port, boost::asio::ip::resolver_query_base::flags()) + : tcp::resolver::query(m_host, m_port, boost::asio::ip::resolver_query_base::flags()); tcp::endpoint endpoint = *resolver.resolve(query); @@ -828,7 +828,7 @@ will_deref_and_erase_t asio_server_connection::handle_headers() m_read = 0; ++m_refs; async_read_until_buffersize( - std::min(ChunkSize, m_read_size), + (std::min)(ChunkSize, m_read_size), [this](const boost::system::error_code& ec, size_t) { (will_deref_t) this->handle_body(ec); }); } @@ -910,7 +910,7 @@ will_deref_t asio_server_connection::handle_body(const boost::system::error_code auto writebuf = requestImpl->outstream().streambuf(); writebuf .putn_nocopy(boost::asio::buffer_cast(m_request_buf.data()), - std::min(m_request_buf.size(), m_read_size - m_read)) + (std::min)(m_request_buf.size(), m_read_size - m_read)) .then([this](pplx::task writtenSizeTask) -> will_deref_t { size_t writtenSize = 0; try @@ -926,7 +926,7 @@ will_deref_t asio_server_connection::handle_body(const boost::system::error_code m_request_buf.consume(writtenSize); async_read_until_buffersize( - std::min(ChunkSize, m_read_size - m_read), + (std::min)(ChunkSize, m_read_size - m_read), [this](const boost::system::error_code& ec, size_t) { (will_deref_t) this->handle_body(ec); }); return will_deref_t {}; }); @@ -1162,7 +1162,7 @@ will_deref_and_erase_t asio_server_connection::handle_write_large_response(const if (readbuf.is_eof()) return cancel_sending_response_with_error( response, std::make_exception_ptr(http_exception("Response stream close early!"))); - size_t readBytes = std::min(ChunkSize, m_write_size - m_write); + size_t readBytes = (std::min)(ChunkSize, m_write_size - m_write); readbuf.getn(buffer_cast(m_response_buf.prepare(readBytes)), readBytes) .then([=](pplx::task actualSizeTask) -> will_deref_and_erase_t { size_t actualSize = 0; diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 49d83fe874..d4c080a76b 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -155,7 +155,7 @@ void parse_http_headers(const HTTP_REQUEST_HEADERS& headers, http::http_headers& } else { - msgHeaders[unknown_header_name] = U(""); + msgHeaders[unknown_header_name].clear(); } } for (int i = 0; i < HttpHeaderMaximum; ++i) @@ -976,10 +976,10 @@ void windows_request_context::async_process_response() // OK, so we need to chunk it up. _ASSERTE(content_length > 0); - m_sending_in_chunks = (content_length != std::numeric_limits::max()); - m_transfer_encoding = (content_length == std::numeric_limits::max()); + m_sending_in_chunks = (content_length != (std::numeric_limits::max)()); + m_transfer_encoding = (content_length == (std::numeric_limits::max)()); m_remaining_to_write = content_length; - if (content_length == std::numeric_limits::max()) + if (content_length == (std::numeric_limits::max)()) { // Attempt to figure out the remaining length of the input stream m_remaining_to_write = m_response._get_impl()->_get_stream_length(); diff --git a/Release/src/http/listener/http_server_httpsys.h b/Release/src/http/listener/http_server_httpsys.h index d998619bbe..40c2a5e9ab 100644 --- a/Release/src/http/listener/http_server_httpsys.h +++ b/Release/src/http/listener/http_server_httpsys.h @@ -58,9 +58,9 @@ class http_overlapped : public OVERLAPPED ULONG_PTR numberOfBytesTransferred, PTP_IO io) { - CASABLANCA_UNREFERENCED_PARAMETER(io); - CASABLANCA_UNREFERENCED_PARAMETER(context); - CASABLANCA_UNREFERENCED_PARAMETER(instance); + (void)io; + (void)context; + (void)instance; http_overlapped* p_http_overlapped = (http_overlapped*)pOverlapped; p_http_overlapped->m_http_io_completion(result, (DWORD)numberOfBytesTransferred); diff --git a/Release/src/http/oauth/oauth1.cpp b/Release/src/http/oauth/oauth1.cpp index 0e973aa401..b313cfcdb3 100644 --- a/Release/src/http/oauth/oauth1.cpp +++ b/Release/src/http/oauth/oauth1.cpp @@ -15,7 +15,7 @@ #include "cpprest/asyncrt_utils.h" -#if !defined(CPPREST_TARGET_XP) +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA using namespace utility; using web::http::client::http_client; @@ -455,4 +455,4 @@ const oauth1_token& oauth1_config::token() const } // namespace http } // namespace web -#endif +#endif // _WIN32_WINNT >= _WIN32_WINNT_VISTA diff --git a/Release/src/json/json.cpp b/Release/src/json/json.cpp index 7b61a179cc..7614866acc 100644 --- a/Release/src/json/json.cpp +++ b/Release/src/json/json.cpp @@ -286,8 +286,9 @@ bool web::json::number::is_int32() const switch (m_type) { case signed_type: - return m_intval >= std::numeric_limits::min() && m_intval <= std::numeric_limits::max(); - case unsigned_type: return m_uintval <= std::numeric_limits::max(); + return m_intval >= (std::numeric_limits::min)() && + m_intval <= (std::numeric_limits::max)(); + case unsigned_type: return m_uintval <= (std::numeric_limits::max)(); case double_type: default: return false; } @@ -297,8 +298,8 @@ bool web::json::number::is_uint32() const { switch (m_type) { - case signed_type: return m_intval >= 0 && m_intval <= std::numeric_limits::max(); - case unsigned_type: return m_uintval <= std::numeric_limits::max(); + case signed_type: return m_intval >= 0 && m_intval <= (std::numeric_limits::max)(); + case unsigned_type: return m_uintval <= (std::numeric_limits::max)(); case double_type: default: return false; } @@ -309,7 +310,7 @@ bool web::json::number::is_int64() const switch (m_type) { case signed_type: return true; - case unsigned_type: return m_uintval <= static_cast(std::numeric_limits::max()); + case unsigned_type: return m_uintval <= static_cast((std::numeric_limits::max)()); case double_type: default: return false; } diff --git a/Release/src/pch/stdafx.h b/Release/src/pch/stdafx.h index d999befe5b..2061bea7f6 100644 --- a/Release/src/pch/stdafx.h +++ b/Release/src/pch/stdafx.h @@ -20,32 +20,29 @@ #endif #ifdef _WIN32 -#define NOMINMAX -#ifdef CPPREST_TARGET_XP -#include -#ifndef _WIN32_WINNT -#define _WIN32_WINNT _WIN32_WINNT_WS03 // Windows XP with SP2 -#endif -#endif -#include // use the debug version of the CRT if _DEBUG is defined #ifdef _DEBUG #define _CRTDBG_MAP_ALLOC #include -#include -#endif +#endif // _DEBUG +#include #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#if CPPREST_TARGET_XP && _WIN32_WINNT != 0x0501 +#error CPPREST_TARGET_XP implies _WIN32_WINNT == 0x0501 +#endif // CPPREST_TARGET_XP && _WIN32_WINNT != 0x0501 + #include #include // Windows Header Files: -#if !defined(__cplusplus_winrt) +#ifndef __cplusplus_winrt #include +#endif !__cplusplus_winrt -#endif // #if !defined(__cplusplus_winrt) -#else // LINUX or APPLE +#else // LINUX or APPLE #define __STDC_LIMIT_MACROS #include "pthread.h" #include @@ -84,6 +81,7 @@ #include #include #include +#include #include // json diff --git a/Release/src/streams/fileio_posix.cpp b/Release/src/streams/fileio_posix.cpp index 013d910d44..2404196423 100644 --- a/Release/src/streams/fileio_posix.cpp +++ b/Release/src/streams/fileio_posix.cpp @@ -375,7 +375,7 @@ size_t _fill_buffer_fsb(_file_info_impl* fInfo, _filestream_callback* callback, size_t byteCount = count * charSize; if (fInfo->m_buffer == nullptr) { - fInfo->m_bufsize = std::max(PageSize, byteCount); + fInfo->m_bufsize = (std::max)(PageSize, byteCount); fInfo->m_buffer = new char[static_cast(fInfo->m_bufsize)]; fInfo->m_bufoff = fInfo->m_rdpos; @@ -396,7 +396,7 @@ size_t _fill_buffer_fsb(_file_info_impl* fInfo, _filestream_callback* callback, if (bufrem < count) { - fInfo->m_bufsize = std::max(PageSize, byteCount); + fInfo->m_bufsize = (std::max)(PageSize, byteCount); // Then, we allocate a new buffer. @@ -456,7 +456,7 @@ size_t _getn_fsb(Concurrency::streams::details::_file_info* info, if (fInfo->m_buffer_reads) { auto cb = create_callback(fInfo, callback, [=](size_t read) { - auto copy = std::min(read, byteCount); + auto copy = (std::min)(read, byteCount); auto bufoff = fInfo->m_rdpos - fInfo->m_bufoff; memcpy(ptr, fInfo->m_buffer + bufoff * charSize, copy); fInfo->m_atend = copy < byteCount; @@ -467,7 +467,7 @@ size_t _getn_fsb(Concurrency::streams::details::_file_info* info, if (static_cast(read) > 0) { - auto copy = std::min(read, byteCount); + auto copy = (std::min)(read, byteCount); auto bufoff = fInfo->m_rdpos - fInfo->m_bufoff; memcpy(ptr, fInfo->m_buffer + bufoff * charSize, copy); fInfo->m_atend = copy < byteCount; diff --git a/Release/src/streams/fileio_win32.cpp b/Release/src/streams/fileio_win32.cpp index 86b5bd1ddc..97cd6e5e6d 100644 --- a/Release/src/streams/fileio_win32.cpp +++ b/Release/src/streams/fileio_win32.cpp @@ -105,9 +105,9 @@ void CALLBACK IoCompletionCallback(PTP_CALLBACK_INSTANCE instance, ULONG_PTR numberOfBytesTransferred, PTP_IO io) { - CASABLANCA_UNREFERENCED_PARAMETER(io); - CASABLANCA_UNREFERENCED_PARAMETER(ctxt); - CASABLANCA_UNREFERENCED_PARAMETER(instance); + (void)io; + (void)ctxt; + (void)instance; EXTENDED_OVERLAPPED* pExtOverlapped = static_cast(pOverlapped); pExtOverlapped->func(result, static_cast(numberOfBytesTransferred), static_cast(pOverlapped)); diff --git a/Release/src/uri/uri.cpp b/Release/src/uri/uri.cpp index 92781f67a8..3f2414af2c 100644 --- a/Release/src/uri/uri.cpp +++ b/Release/src/uri/uri.cpp @@ -734,7 +734,7 @@ std::map uri::split_query(const utility::s else if (equals_index == 0) { utility::string_t value(key_value_pair.begin() + equals_index + 1, key_value_pair.end()); - results[_XPLATSTR("")] = value; + results[utility::string_t {}] = value; } else { diff --git a/Release/src/utilities/web_utilities.cpp b/Release/src/utilities/web_utilities.cpp index 9316f41f4f..ce00078b79 100644 --- a/Release/src/utilities/web_utilities.cpp +++ b/Release/src/utilities/web_utilities.cpp @@ -27,8 +27,9 @@ namespace web { namespace details { -#if defined(_WIN32) && !defined(CPPREST_TARGET_XP) -#if defined(__cplusplus_winrt) +#ifdef _WIN32 +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA +#ifdef __cplusplus_winrt // Helper function to zero out memory of an IBuffer. void winrt_secure_zero_buffer(Windows::Storage::Streams::IBuffer ^ buffer) @@ -88,7 +89,7 @@ plaintext_string winrt_encryption::decrypt() const return std::move(data); } -#else +#else // ^^^ __cplusplus_winrt ^^^ // vvv !__cplusplus_winrt vvv win32_encryption::win32_encryption(const std::wstring& data) : m_numCharacters(data.size()) { @@ -141,13 +142,14 @@ plaintext_string win32_encryption::decrypt() const return result; } -#endif -#endif +#endif // __cplusplus_winrt +#endif // _WIN32_WINNT >= _WIN32_WINNT_VISTA +#endif // _WIN32 void zero_memory_deleter::operator()(::utility::string_t* data) const { - CASABLANCA_UNREFERENCED_PARAMETER(data); -#if defined(_WIN32) + (void)data; +#ifdef _WIN32 SecureZeroMemory(&(*data)[0], data->size() * sizeof(::utility::string_t::value_type)); delete data; #endif diff --git a/Release/src/websockets/client/ws_client.cpp b/Release/src/websockets/client/ws_client.cpp index f768e968fb..48a40797e6 100644 --- a/Release/src/websockets/client/ws_client.cpp +++ b/Release/src/websockets/client/ws_client.cpp @@ -51,8 +51,7 @@ void websocket_client_task_impl::set_handler() }); m_callback_client->set_close_handler( - [=](websocket_close_status status, const utility::string_t& reason, const std::error_code& error_code) { - CASABLANCA_UNREFERENCED_PARAMETER(status); + [=](websocket_close_status, const utility::string_t& reason, const std::error_code& error_code) { close_pending_tasks_with_error(websocket_exception(error_code, reason)); }); } diff --git a/Release/src/websockets/client/ws_client_winrt.cpp b/Release/src/websockets/client/ws_client_winrt.cpp index 291ba8ce8a..6bb4351cee 100644 --- a/Release/src/websockets/client/ws_client_winrt.cpp +++ b/Release/src/websockets/client/ws_client_winrt.cpp @@ -404,7 +404,7 @@ class winrt_callback_client : public websocket_client_callback_impl, return close(websocket_close_status::normal, _XPLATSTR("Normal")); } - pplx::task close(websocket_close_status status, const utility::string_t& strreason = _XPLATSTR("")) + pplx::task close(websocket_close_status status, const utility::string_t& strreason = {}) { // Send a close frame to the server m_msg_websocket->Close(static_cast(status), Platform::StringReference(strreason.c_str())); diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index 26fa547d5d..ef9c1d0bd3 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -325,34 +325,32 @@ class wspp_callback_client : public websocket_client_callback_impl, } }); - client.set_ping_handler( - [this](websocketpp::connection_hdl, const std::string& msg) { - if (m_external_message_handler) - { - _ASSERTE(m_state >= CONNECTED && m_state < CLOSED); - websocket_incoming_message incoming_msg; + client.set_ping_handler([this](websocketpp::connection_hdl, const std::string& msg) { + if (m_external_message_handler) + { + _ASSERTE(m_state >= CONNECTED && m_state < CLOSED); + websocket_incoming_message incoming_msg; - incoming_msg.m_msg_type = websocket_message_type::ping; - incoming_msg.m_body = concurrency::streams::container_buffer(msg); + incoming_msg.m_msg_type = websocket_message_type::ping; + incoming_msg.m_body = concurrency::streams::container_buffer(msg); - m_external_message_handler(incoming_msg); - } - return true; - }); + m_external_message_handler(incoming_msg); + } + return true; + }); - client.set_pong_handler( - [this](websocketpp::connection_hdl, const std::string& msg) { - if (m_external_message_handler) - { - _ASSERTE(m_state >= CONNECTED && m_state < CLOSED); - websocket_incoming_message incoming_msg; + client.set_pong_handler([this](websocketpp::connection_hdl, const std::string& msg) { + if (m_external_message_handler) + { + _ASSERTE(m_state >= CONNECTED && m_state < CLOSED); + websocket_incoming_message incoming_msg; - incoming_msg.m_msg_type = websocket_message_type::pong; - incoming_msg.m_body = concurrency::streams::container_buffer(msg); + incoming_msg.m_msg_type = websocket_message_type::pong; + incoming_msg.m_body = concurrency::streams::container_buffer(msg); - m_external_message_handler(incoming_msg); - } - }); + m_external_message_handler(incoming_msg); + } + }); client.set_close_handler([this](websocketpp::connection_hdl con_hdl) { _ASSERTE(m_state != CLOSED); @@ -469,7 +467,8 @@ class wspp_callback_client : public websocket_client_callback_impl, } const auto length = msg.m_length; - if (length == 0 && msg.m_msg_type != websocket_message_type::ping && msg.m_msg_type != websocket_message_type::pong) + if (length == 0 && msg.m_msg_type != websocket_message_type::ping && + msg.m_msg_type != websocket_message_type::pong) { return pplx::task_from_exception(websocket_exception("Cannot send empty message.")); } diff --git a/Release/tests/common/TestRunner/test_runner.cpp b/Release/tests/common/TestRunner/test_runner.cpp index 4d1a8d39f9..9a356a9b0f 100644 --- a/Release/tests/common/TestRunner/test_runner.cpp +++ b/Release/tests/common/TestRunner/test_runner.cpp @@ -238,7 +238,7 @@ static int parse_command_line(int argc, char** argv) } else { - UnitTest::GlobalSettings::Add(arg.substr(1), ""); + UnitTest::GlobalSettings::Add(arg.substr(1), std::string{}); } } else if (arg.find("/debug") == 0) @@ -262,9 +262,9 @@ static bool matched_properties(const UnitTest::TestProperties& test_props) // This starts with visual studio versions after VS 2012. #if defined(_MSC_VER) && (_MSC_VER >= 1800) #ifdef WINRT_TEST_RUNNER - UnitTest::GlobalSettings::Add("winrt", ""); + UnitTest::GlobalSettings::Add("winrt", std::string{}); #elif defined DESKTOP_TEST_RUNNER - UnitTest::GlobalSettings::Add("desktop", ""); + UnitTest::GlobalSettings::Add("desktop", std::string{}); #endif #endif diff --git a/Release/tests/common/UnitTestpp/src/Checks.h b/Release/tests/common/UnitTestpp/src/Checks.h index 4425fed100..f4494069b3 100644 --- a/Release/tests/common/UnitTestpp/src/Checks.h +++ b/Release/tests/common/UnitTestpp/src/Checks.h @@ -103,7 +103,7 @@ struct BuildFailureStringImpl std::string BuildString(const char*, const char*, const T1&, const T2&) { // Don't do anything since operator<< isn't supported. - return ""; + return std::string{}; } }; diff --git a/Release/tests/common/UnitTestpp/src/DeferredTestResult.cpp b/Release/tests/common/UnitTestpp/src/DeferredTestResult.cpp index 5800eeb6f1..703031f9fc 100644 --- a/Release/tests/common/UnitTestpp/src/DeferredTestResult.cpp +++ b/Release/tests/common/UnitTestpp/src/DeferredTestResult.cpp @@ -54,12 +54,12 @@ DeferredTestFailure::DeferredTestFailure(int lineNumber_, const char* failureStr } DeferredTestResult::DeferredTestResult() - : suiteName(""), testName(""), failureFile(""), timeElapsed(0.0f), failed(false) + : suiteName(), testName(), failureFile(), timeElapsed(0.0f), failed(false) { } -DeferredTestResult::DeferredTestResult(char const* suite, char const* test) - : suiteName(suite), testName(test), failureFile(""), timeElapsed(0.0f), failed(false) +DeferredTestResult::DeferredTestResult(char const* const suite, char const* const test) + : suiteName(suite), testName(test), failureFile(), timeElapsed(0.0f), failed(false) { } diff --git a/Release/tests/common/UnitTestpp/src/MemoryOutStream.cpp b/Release/tests/common/UnitTestpp/src/MemoryOutStream.cpp index c16845efb8..a0da2e4868 100644 --- a/Release/tests/common/UnitTestpp/src/MemoryOutStream.cpp +++ b/Release/tests/common/UnitTestpp/src/MemoryOutStream.cpp @@ -174,7 +174,7 @@ void MemoryOutStream::GrowBuffer(int const desiredCapacity) if (m_buffer) strcpy(buffer, m_buffer); else - strcpy(buffer, ""); + *buffer = '\0'; delete[] m_buffer; m_buffer = buffer; diff --git a/Release/tests/common/UnitTestpp/src/stdafx.h b/Release/tests/common/UnitTestpp/src/stdafx.h index 14b38623cb..99e91a15ee 100644 --- a/Release/tests/common/UnitTestpp/src/stdafx.h +++ b/Release/tests/common/UnitTestpp/src/stdafx.h @@ -49,6 +49,5 @@ #ifdef WIN32 #define WIN32_LEAN_AND_MEAN -#define NOMINMAX #include #endif \ No newline at end of file diff --git a/Release/tests/common/utilities/os_utilities.cpp b/Release/tests/common/utilities/os_utilities.cpp index de2a06d9fb..12aa4be6ef 100644 --- a/Release/tests/common/utilities/os_utilities.cpp +++ b/Release/tests/common/utilities/os_utilities.cpp @@ -12,7 +12,6 @@ #include "os_utilities.h" #ifdef WIN32 -#define NOMINMAX #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp index 128006431b..1ccb740fab 100644 --- a/Release/tests/functional/http/client/compression_tests.cpp +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -73,7 +73,7 @@ SUITE(compression_tests) << " / " << _size; throw std::runtime_error(std::move(ss.str())); } - bytes = std::min(input_size, output_size); + bytes = (std::min)(input_size, output_size); if (bytes) { memcpy(output, input, bytes); @@ -128,7 +128,7 @@ SUITE(compression_tests) << " / " << _size; throw std::runtime_error(std::move(ss.str())); } - bytes = std::min(input_size, output_size); + bytes = (std::min)(input_size, output_size); if (bytes) { memcpy(output, input, bytes); @@ -218,18 +218,18 @@ SUITE(compression_tests) if (csize == cmpsize) { // extend the output buffer if there may be more compressed bytes to retrieve - cmpsize += std::min(chunk_size, (size_t)200); + cmpsize += (std::min)(chunk_size, (size_t)200); cmp_buffer.resize(cmpsize); } r = compressor ->compress(input_buffer.data() + i, - std::min(chunk_size, buffer_size - i), + (std::min)(chunk_size, buffer_size - i), cmp_buffer.data() + csize, - std::min(chunk_size, cmpsize - csize), + (std::min)(chunk_size, cmpsize - csize), hint) .get(); - VERIFY_IS_TRUE(r.input_bytes_processed == std::min(chunk_size, buffer_size - i) || - r.output_bytes_produced == std::min(chunk_size, cmpsize - csize)); + VERIFY_IS_TRUE(r.input_bytes_processed == (std::min)(chunk_size, buffer_size - i) || + r.output_bytes_produced == (std::min)(chunk_size, cmpsize - csize)); VERIFY_IS_TRUE(hint == operation_hint::is_last || !r.done); chunk_sizes.push_back(r.output_bytes_produced); csize += r.output_bytes_produced; @@ -262,7 +262,7 @@ SUITE(compression_tests) ->decompress(cmp_buffer.data() + nn, *it, dcmp_buffer.data() + dsize, - std::min(chunk_size, buffer_size - dsize), + (std::min)(chunk_size, buffer_size - dsize), hint) .get(); nn += *it; @@ -281,14 +281,14 @@ SUITE(compression_tests) memset(dcmp_buffer.data(), 0, dcmp_buffer.size()); do { - size_t n = std::min(chunk_size, csize - nn); + size_t n = (std::min)(chunk_size, csize - nn); do { r = decompressor ->decompress(cmp_buffer.data() + nn, n, dcmp_buffer.data() + dsize, - std::min(chunk_size, buffer_size - dsize), + (std::min)(chunk_size, buffer_size - dsize), operation_hint::has_more) .get(); dsize += r.output_bytes_produced; @@ -770,7 +770,7 @@ SUITE(compression_tests) } #endif // _WIN32 - auto extra_size = [](size_t bufsz) -> size_t { return std::max(static_cast(128), bufsz / 1000); }; + auto extra_size = [](size_t bufsz) -> size_t { return (std::max)(static_cast(128), bufsz / 1000); }; // Test decompression both explicitly through the test server and implicitly through the listener; // this is the top-level loop in order to avoid thrashing the listeners more than necessary diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index 41709bc3a1..3ff1a809ec 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -352,7 +352,7 @@ SUITE(outside_tests) throw; } #else - CASABLANCA_UNREFERENCED_PARAMETER(e); + (void)e; throw; #endif os_utilities::sleep(1000); diff --git a/Release/tests/functional/http/utilities/stdafx.h b/Release/tests/functional/http/utilities/stdafx.h index 9ce41e4b72..23e69e4535 100644 --- a/Release/tests/functional/http/utilities/stdafx.h +++ b/Release/tests/functional/http/utilities/stdafx.h @@ -13,7 +13,6 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN -#define NOMINMAX #include #include diff --git a/Release/tests/functional/json/json_numbers_tests.cpp b/Release/tests/functional/json/json_numbers_tests.cpp index 4935a6af27..538d44d367 100644 --- a/Release/tests/functional/json/json_numbers_tests.cpp +++ b/Release/tests/functional/json/json_numbers_tests.cpp @@ -258,8 +258,8 @@ SUITE(json_numbers_tests) // unsigned int64 max oracleStream.precision(std::numeric_limits::digits10 + 2); - oracleStream << std::numeric_limits::max(); - json::value iMax(std::numeric_limits::max()); + oracleStream << (std::numeric_limits::max)(); + json::value iMax((std::numeric_limits::max)()); VERIFY_ARE_EQUAL(oracleStream.str(), iMax.serialize()); iMax.serialize(stream); VERIFY_ARE_EQUAL(oracleStream.str(), stream.str()); @@ -268,8 +268,8 @@ SUITE(json_numbers_tests) stream.str(U("")); oracleStream.str(U("")); oracleStream.clear(); - oracleStream << std::numeric_limits::min(); - json::value iMin(std::numeric_limits::min()); + oracleStream << (std::numeric_limits::min)(); + json::value iMin((std::numeric_limits::min)()); VERIFY_ARE_EQUAL(oracleStream.str(), iMin.serialize()); iMin.serialize(stream); VERIFY_ARE_EQUAL(oracleStream.str(), stream.str()); @@ -278,8 +278,8 @@ SUITE(json_numbers_tests) stream.str(U("")); oracleStream.str(U("")); oracleStream.precision(std::numeric_limits::digits10 + 2); - oracleStream << std::numeric_limits::max(); - json::value dMax(std::numeric_limits::max()); + oracleStream << (std::numeric_limits::max)(); + json::value dMax((std::numeric_limits::max)()); VERIFY_ARE_EQUAL(oracleStream.str(), dMax.serialize()); dMax.serialize(stream); VERIFY_ARE_EQUAL(oracleStream.str(), stream.str()); @@ -287,8 +287,8 @@ SUITE(json_numbers_tests) // double min stream.str(U("")); oracleStream.str(U("")); - oracleStream << std::numeric_limits::min(); - json::value dMin(std::numeric_limits::min()); + oracleStream << (std::numeric_limits::min)(); + json::value dMin((std::numeric_limits::min)()); VERIFY_ARE_EQUAL(oracleStream.str(), dMin.serialize()); dMin.serialize(stream); VERIFY_ARE_EQUAL(oracleStream.str(), stream.str()); diff --git a/Release/tests/functional/json/stdafx.h b/Release/tests/functional/json/stdafx.h index bb65303dca..bb43264b61 100644 --- a/Release/tests/functional/json/stdafx.h +++ b/Release/tests/functional/json/stdafx.h @@ -16,5 +16,4 @@ #include "unittestpp.h" #include -#define NOMINMAX #include "json_tests.h" diff --git a/Release/tests/functional/misc/atl_headers/header_test1.cpp b/Release/tests/functional/misc/atl_headers/header_test1.cpp index 46d54ff2e3..95dd22359d 100644 --- a/Release/tests/functional/misc/atl_headers/header_test1.cpp +++ b/Release/tests/functional/misc/atl_headers/header_test1.cpp @@ -11,7 +11,6 @@ // Include ATL headers before casablanca headers #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit #ifndef VC_EXTRALEAN diff --git a/Release/tests/functional/misc/atl_headers/header_test2.cpp b/Release/tests/functional/misc/atl_headers/header_test2.cpp index 91cf63fbc6..73e35711de 100644 --- a/Release/tests/functional/misc/atl_headers/header_test2.cpp +++ b/Release/tests/functional/misc/atl_headers/header_test2.cpp @@ -9,7 +9,6 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX #include "cpprest/http_client.h" // Include ATL headers after casablanca headers diff --git a/Release/tests/functional/pplx/pplx_test/stdafx.h b/Release/tests/functional/pplx/pplx_test/stdafx.h index 7c2d53ab4f..790829ef64 100644 --- a/Release/tests/functional/pplx/pplx_test/stdafx.h +++ b/Release/tests/functional/pplx/pplx_test/stdafx.h @@ -12,7 +12,6 @@ #pragma once #ifdef _WIN32 -#define NOMINMAX #include #endif diff --git a/Release/tests/functional/streams/istream_tests.cpp b/Release/tests/functional/streams/istream_tests.cpp index d1018e3116..32cb545aa2 100644 --- a/Release/tests/functional/streams/istream_tests.cpp +++ b/Release/tests/functional/streams/istream_tests.cpp @@ -1333,7 +1333,7 @@ SUITE(istream_tests) const auto actual = istream_double.extract().get(); compare_double(expected, actual); - if (actual <= std::numeric_limits::max()) + if (actual <= (std::numeric_limits::max)()) compare_float(float(expected), istream_float.extract().get()); else VERIFY_THROWS(istream_float.extract().get(), std::exception); diff --git a/Release/tests/functional/streams/memstream_tests.cpp b/Release/tests/functional/streams/memstream_tests.cpp index 6442883327..3bdbd6812a 100644 --- a/Release/tests/functional/streams/memstream_tests.cpp +++ b/Release/tests/functional/streams/memstream_tests.cpp @@ -13,7 +13,6 @@ #include #endif #ifdef _WIN32 -#define NOMINMAX #include #endif diff --git a/Release/tests/functional/utils/win32_encryption_tests.cpp b/Release/tests/functional/utils/win32_encryption_tests.cpp index 32e6ab2ecb..a2be7cde5a 100644 --- a/Release/tests/functional/utils/win32_encryption_tests.cpp +++ b/Release/tests/functional/utils/win32_encryption_tests.cpp @@ -21,7 +21,7 @@ namespace functional { namespace utils_tests { -#if defined(_WIN32) && !defined(CPPREST_TARGET_XP) && !defined(__cplusplus_winrt) +#if defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt) SUITE(win32_encryption) { TEST(win32_encryption_random_string) @@ -42,7 +42,7 @@ SUITE(win32_encryption) } // SUITE(win32_encryption) -#endif +#endif // defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA && !defined(__cplusplus_winrt) } // namespace utils_tests } // namespace functional diff --git a/Release/tests/functional/websockets/utilities/stdafx.h b/Release/tests/functional/websockets/utilities/stdafx.h index e8adb749c9..0c6e35125a 100644 --- a/Release/tests/functional/websockets/utilities/stdafx.h +++ b/Release/tests/functional/websockets/utilities/stdafx.h @@ -13,7 +13,6 @@ #if defined(_WIN32) // Include first to avoid any issues with Windows.h. -#define NOMINMAX #include #endif From 60e067e71aebebdda5d82955060f5f0821c9df1d Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Tue, 16 Jul 2019 07:55:55 -0700 Subject: [PATCH 15/80] Remove proxy settings detection behavior in "default proxy mode." (#1188) * Remove proxy settings detection behavior in "default proxy mode." This commit partially reverts https://github.com/microsoft/cpprestsdk/commit/eb108ada1ab23a46a09efb87f35c802e57e0832a in order to work around a reliability problem with WinHttpGetProxyForUrl. That function hangs unless there is an available thread pool thread to complete the WPAD request. As a result, if a customer issued ~512 concurrent HTTP requests, or otherwise needed that many thread pool threads, there would not be a thread available for WinHTTP to complete the operation, and the program would deadlock. Moreover this call to WinHttpGetDefaultProxyConfiguration is extremely expensive, taking ~20% of overall CPU for the entire program for some Azure Storage SDK customers. The function WinHttpGetProxyForUrlEx is supposed to help with this problem by being asynchronous, but that function was added in Windows 8, so we can't use it unconditionally. And on Windows 8.1 we already are using WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY instead of trying to do proxy autodetect ourselves. --- .../include/cpprest/details/web_utilities.h | 4 -- .../src/http/client/http_client_winhttp.cpp | 62 ++++++++++--------- 2 files changed, 32 insertions(+), 34 deletions(-) diff --git a/Release/include/cpprest/details/web_utilities.h b/Release/include/cpprest/details/web_utilities.h index aed7419c85..853d7614b1 100644 --- a/Release/include/cpprest/details/web_utilities.h +++ b/Release/include/cpprest/details/web_utilities.h @@ -10,10 +10,6 @@ ****/ #pragma once -#ifdef _WIN32 -#include -#endif // _WIN32 - #include "cpprest/asyncrt_utils.h" #include "cpprest/uri.h" diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index a6e5a226b1..249bfcd52c 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -243,6 +243,24 @@ enum msg_body_type transfer_encoding_chunked }; +static DWORD WinHttpDefaultProxyConstant() CPPREST_NOEXCEPT +{ +#if _WIN32_WINNT >= _WIN32_WINNT_VISTA +#if _WIN32_WINNT < _WIN32_WINNT_WINBLUE + if (!IsWindows8Point1OrGreater()) + { + // Not Windows 8.1 or later, use the default proxy setting + return WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; + } +#endif // _WIN32_WINNT < _WIN32_WINNT_WINBLUE + + // Windows 8.1 or later, use the automatic proxy setting + return WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY; +#else // ^^^ _WIN32_WINNT >= _WIN32_WINNT_VISTA ^^^ // vvv _WIN32_WINNT < _WIN32_WINNT_VISTA vvv + return WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; +#endif // _WIN32_WINNT >= _WIN32_WINNT_VISTA +} + // Additional information necessary to track a WinHTTP request. class winhttp_request_context final : public request_context { @@ -818,38 +836,30 @@ class winhttp_client final : public _http_client_communicator ie_proxy_config proxyIE; DWORD access_type; - LPCWSTR proxy_name; + LPCWSTR proxy_name = WINHTTP_NO_PROXY_NAME; LPCWSTR proxy_bypass = WINHTTP_NO_PROXY_BYPASS; + m_proxy_auto_config = false; utility::string_t proxy_str; http::uri uri; const auto& config = client_config(); - - if (config.proxy().is_disabled()) + const auto& proxy = config.proxy(); + if (proxy.is_default()) + { + access_type = WinHttpDefaultProxyConstant(); + } + else if (proxy.is_disabled()) { access_type = WINHTTP_ACCESS_TYPE_NO_PROXY; - proxy_name = WINHTTP_NO_PROXY_NAME; } - else if (config.proxy().is_default() || config.proxy().is_auto_discovery()) + else if (proxy.is_auto_discovery()) { - // Use the default WinHTTP proxy by default. - access_type = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; - proxy_name = WINHTTP_NO_PROXY_NAME; - -#if _WIN32_WINNT < _WIN32_WINNT_VISTA - if (config.proxy().is_auto_discovery()) + access_type = WinHttpDefaultProxyConstant(); + if (access_type != WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY) { + // Windows 8 or earlier, do proxy autodetection ourselves m_proxy_auto_config = true; - } -#else // ^^^ _WIN32_WINNT < _WIN32_WINNT_VISTA ^^^ // vvv _WIN32_WINNT >= _WIN32_WINNT_VISTA vvv - if (IsWindows8Point1OrGreater()) - { - // Windows 8.1 and newer supports automatic proxy discovery and auto-fallback to IE proxy settings - access_type = WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY; - } - else - { - // However, if it is not configured... + proxy_info proxyDefault; if (!WinHttpGetDefaultProxyConfiguration(&proxyDefault) || proxyDefault.dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY) @@ -881,13 +891,7 @@ class winhttp_client final : public _http_client_communicator } } } - - if (config.proxy().is_auto_discovery()) - { - m_proxy_auto_config = true; - } } -#endif // _WIN32_WINNT < _WIN32_WINNT_VISTA } else { @@ -1007,9 +1011,7 @@ class winhttp_client final : public _http_client_communicator if (m_proxy_auto_config) { - WINHTTP_AUTOPROXY_OPTIONS autoproxy_options; - memset(&autoproxy_options, 0, sizeof(WINHTTP_AUTOPROXY_OPTIONS)); - + WINHTTP_AUTOPROXY_OPTIONS autoproxy_options {}; if (m_proxy_auto_config_url.empty()) { autoproxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT; From 6f602bee67b088a299d7901534af3bce6334ab38 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Tue, 16 Jul 2019 12:07:11 -0700 Subject: [PATCH 16/80] Mint v2.10.14. (#1193) --- Release/CMakeLists.txt | 2 +- Release/include/cpprest/version.h | 2 +- changelog.md | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index b9e6d6d56a..dd5d1daca2 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 13) +set(CPPREST_VERSION_REVISION 14) enable_testing() diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index af1a6c7c1d..a6a55e231b 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -5,6 +5,6 @@ */ #define CPPREST_VERSION_MINOR 10 #define CPPREST_VERSION_MAJOR 2 -#define CPPREST_VERSION_REVISION 13 +#define CPPREST_VERSION_REVISION 14 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR * 100000 + CPPREST_VERSION_MINOR * 100 + CPPREST_VERSION_REVISION) diff --git a/changelog.md b/changelog.md index fd371ec498..3c11c199c6 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,22 @@ +cpprestsdk (2.10.14) +* Potential breaking change warning: This release changes the "default" proxy for the WinHTTP backend to go back to WINHTTP_ACCESS_TYPE_DEFAULT_PROXY. See https://github.com/microsoft/cpprestsdk/commit/60e067e71aebebdda5d82955060f5f0821c9df1d for more details. To get automatic WPAD behavior, set the proxy to auto detect. +* macOS with Brew and iOS builds have been disabled and are no longer being tested because our dependency boost for ios project appears to be broken with current releases of XCode as on the Azure Pipelines machines. We are interested in macOS / iOS folks who know what's going on here in contributing a repair to turn this back on. +* PR##1133 Add switches to make apiscan happy. +* PR##1130 json: {"meow"} is not a valid object +* PR##1150 Undefine compress if it is defined by zconf.h +* PR##1156 Fix broken CI Builds +* PR##1155 Use EVP_MAX_MD_SIZE instead of HMAC_MAX_MD_CBLOCK +* PR##1145 Remove the address_configured flag on tcp::resolver::query +* PR##1143 add ping and pong to message handler +* PR##539 Fix reusing ASIO http_client connecting to HTTPS server via proxy +* PR##1175 Fix issue #1171: Order of object destruction +* PR##1183 FIX: SSL proxy tunnel support with basic auth +* PR##1184 Fix profile being set on the compiler instead of the linker. +* PR##1185 Update boost-for-android for Android NDK r20 and disable macOS Homebrew. +* PR##1187 Replace CPPREST_TARGET_XP with version checks, remove ""s, and other cleanup +* PR##1188 Remove proxy settings detection behavior in "default proxy mode." +-- cpprestsdk team TUE, 16 Jul 2019 09:06:00 +0200 + cpprestsdk (2.10.13) * PR#1120 Fix off by one error in leap years before year 2000, and bad day names * PR#1117 Parse and emit years from 1900 to 9999, and remove environment variable dependence on Android From a40a28610db709ce6abc2bd0bd0f16a2e0af7ebd Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Tue, 23 Jul 2019 18:54:40 +0100 Subject: [PATCH 17/80] Missed one defence against no NOMINMAX in bed8fa538c862a8297cb02c99d8b3dcc29247d5b. (#1202) --- Release/src/http/client/http_client_asio.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index f8401d6e99..a90ca6a7fa 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1444,8 +1444,8 @@ class asio_context final : public request_context, public std::enable_shared_fro } } - m_content_length = std::numeric_limits::max(); // Without Content-Length header, size should be same as - // TCP stream - set it size_t max. + m_content_length = (std::numeric_limits::max)(); // Without Content-Length header, size should be same as + // TCP stream - set it size_t max. m_response.headers().match(header_names::content_length, m_content_length); if (!this->handle_compression()) From 44c491889ddbcfca963aa54e175d81f0eade058d Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Fri, 2 Aug 2019 20:27:46 +0100 Subject: [PATCH 18/80] Workarounds for two GCC 4.7.2 bugs with lambda functions (#1209) * Workarounds for two GCC 4.7.2 bugs with lambda functions using implicit this, surfacing as incorrect const-qualification and an internal compiler error. Resolves immediate issues identified in #1200. * Restore compatibility with modern compilers --- Release/src/websockets/client/ws_client_wspp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Release/src/websockets/client/ws_client_wspp.cpp b/Release/src/websockets/client/ws_client_wspp.cpp index ef9c1d0bd3..d7c31c4095 100644 --- a/Release/src/websockets/client/ws_client_wspp.cpp +++ b/Release/src/websockets/client/ws_client_wspp.cpp @@ -292,7 +292,7 @@ class wspp_callback_client : public websocket_client_callback_impl, client.set_fail_handler([this](websocketpp::connection_hdl con_hdl) { _ASSERTE(m_state == CONNECTING); - shutdown_wspp_impl(con_hdl, true); + this->shutdown_wspp_impl(con_hdl, true); }); client.set_message_handler( @@ -354,7 +354,7 @@ class wspp_callback_client : public websocket_client_callback_impl, client.set_close_handler([this](websocketpp::connection_hdl con_hdl) { _ASSERTE(m_state != CLOSED); - shutdown_wspp_impl(con_hdl, false); + this->shutdown_wspp_impl(con_hdl, false); }); // Set User Agent specified by the user. This needs to happen before any connection is created @@ -679,7 +679,7 @@ class wspp_callback_client : public websocket_client_callback_impl, client.stop_perpetual(); // Can't join thread directly since it is the current thread. - pplx::create_task([this, connecting, ec, closeCode, reason] { + pplx::create_task([] {}).then([this, connecting, ec, closeCode, reason]() mutable { { std::lock_guard lock(m_wspp_client_lock); if (m_thread.joinable()) From 265d681743c78c980383340e786109e41c003bd9 Mon Sep 17 00:00:00 2001 From: Jason Hartman Date: Thu, 22 Aug 2019 19:33:30 -0700 Subject: [PATCH 19/80] fix SxS debug-release builds with Visual Studio (#1220) * On basic_string_view_support: fix SxS debug-release builds with Visual Studio place precompiled header implicitly in Debug/Release path with VS and explicitly in bin dir otherwise standardize pch setup across libraries with helper function * nudge pipeline to rerun --- Release/CMakeLists.txt | 22 +++++++++++++++++++ .../BlackJack/BlackJack_Server/CMakeLists.txt | 11 +--------- Release/src/CMakeLists.txt | 13 +---------- .../functional/http/client/CMakeLists.txt | 13 +---------- .../functional/http/listener/CMakeLists.txt | 11 +--------- Release/tests/functional/json/CMakeLists.txt | 13 +---------- .../functional/pplx/pplx_test/CMakeLists.txt | 13 +---------- .../tests/functional/streams/CMakeLists.txt | 13 +---------- Release/tests/functional/uri/CMakeLists.txt | 13 +---------- Release/tests/functional/utils/CMakeLists.txt | 13 +---------- 10 files changed, 31 insertions(+), 104 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index dd5d1daca2..4b6433a93a 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -202,6 +202,28 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/Binaries) +function(configure_pch target precompile_header precomile_source) # optional additional compile arguments + if(MSVC) + get_target_property(_srcs ${target} SOURCES) + + set(pch_output_filepath_arg) + if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") + set_property(SOURCE ${precomile_source} APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/${target}.pch") + set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${target}.pch") + set(pch_output_filepath_arg "/Fp${CMAKE_CURRENT_BINARY_DIR}/${target}.pch") + else() + # Don't specify output file so that VS may choose a config spefic location. + # Otherwise Debug/Release builds will interfere with one another. + endif() + + set_source_files_properties(${precomile_source} PROPERTIES COMPILE_FLAGS "/Yc${precompile_header}") + target_sources(${target} PRIVATE ${precomile_source}) + # Note: as ${precomile_source} is also a SOURCE for ${target}, the below options will also be applied. + # ${precomile_source} has /Yc option that will cause the shared /Yu to be ignored. + target_compile_options(${target} PRIVATE /Yu${precompile_header} ${pch_output_filepath_arg} ${ARGN}) + endif() +endfunction() + # These settings can be used by the test targets set(Casablanca_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) set(Casablanca_LIBRARY cpprest) diff --git a/Release/samples/BlackJack/BlackJack_Server/CMakeLists.txt b/Release/samples/BlackJack/BlackJack_Server/CMakeLists.txt index cddfdc50a8..25d82598bc 100644 --- a/Release/samples/BlackJack/BlackJack_Server/CMakeLists.txt +++ b/Release/samples/BlackJack/BlackJack_Server/CMakeLists.txt @@ -10,13 +10,4 @@ add_executable(blackjackserver target_link_libraries(blackjackserver cpprest) -if(MSVC) - get_target_property(_srcs blackjackserver SOURCES) - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/blackjack-server-stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/blackjack-server-stdafx.pch") - endif() - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fpblackjack-server-stdafx.pch /Zm120") - target_sources(blackjackserver PRIVATE stdafx.cpp) - target_compile_options(blackjackserver PRIVATE /Yustdafx.h /Fpblackjack-server-stdafx.pch /Zm120) -endif() +configure_pch(blackjackserver stdafx.h stdafx.cpp /Zm120) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 89d2bc55c3..119b07afe2 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -174,18 +174,7 @@ else() message(FATAL_ERROR "Invalid implementation") endif() -if(MSVC) - get_target_property(_srcs cpprest SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE pch/stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/stdafx.pch") - endif() - - set_source_files_properties(pch/stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Zm120") - target_sources(cpprest PRIVATE pch/stdafx.cpp) - target_compile_options(cpprest PRIVATE /Yustdafx.h /Zm120) -endif() +configure_pch(cpprest stdafx.h pch/stdafx.cpp /Zm120) if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU") if(WERROR) diff --git a/Release/tests/functional/http/client/CMakeLists.txt b/Release/tests/functional/http/client/CMakeLists.txt index 45f0d9af02..635e7da843 100644 --- a/Release/tests/functional/http/client/CMakeLists.txt +++ b/Release/tests/functional/http/client/CMakeLists.txt @@ -32,18 +32,7 @@ else() target_link_libraries(httpclient_test PRIVATE httptest_utilities) endif() -if(MSVC) - get_target_property(_srcs httpclient_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/client-tests-stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/client-tests-stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fpclient-tests-stdafx.pch") - target_sources(httpclient_test PRIVATE stdafx.cpp) - target_compile_options(httpclient_test PRIVATE /Yustdafx.h /Fpclient-tests-stdafx.pch) -endif() +configure_pch(httpclient_test stdafx.h stdafx.cpp) if(NOT WIN32) cpprest_find_boost() diff --git a/Release/tests/functional/http/listener/CMakeLists.txt b/Release/tests/functional/http/listener/CMakeLists.txt index aa4245fed8..58cf86a6fd 100644 --- a/Release/tests/functional/http/listener/CMakeLists.txt +++ b/Release/tests/functional/http/listener/CMakeLists.txt @@ -22,14 +22,5 @@ if(NOT WINDOWS_STORE AND NOT WINDOWS_PHONE) target_link_libraries(httplistener_test PRIVATE httptest_utilities) endif() - if(MSVC) - get_target_property(_srcs httplistener_test SOURCES) - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/listener-tests-stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/listener-tests-stdafx.pch") - endif() - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fplistener-tests-stdafx.pch") - target_sources(httplistener_test PRIVATE stdafx.cpp) - target_compile_options(httplistener_test PRIVATE /Yustdafx.h /Fplistener-tests-stdafx.pch) - endif() + configure_pch(httplistener_test stdafx.h stdafx.cpp) endif() diff --git a/Release/tests/functional/json/CMakeLists.txt b/Release/tests/functional/json/CMakeLists.txt index 1d44a99ce6..fb10c885f7 100644 --- a/Release/tests/functional/json/CMakeLists.txt +++ b/Release/tests/functional/json/CMakeLists.txt @@ -16,15 +16,4 @@ if(UNIX AND NOT APPLE) target_link_libraries(json_test PRIVATE cpprestsdk_boost_internal) endif() -if(MSVC) - get_target_property(_srcs json_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/json-tests-stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/json-tests-stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fpjson-tests-stdafx.pch") - target_sources(json_test PRIVATE stdafx.cpp) - target_compile_options(json_test PRIVATE /Yustdafx.h /Fpjson-tests-stdafx.pch) -endif() +configure_pch(json_test stdafx.h stdafx.cpp) diff --git a/Release/tests/functional/pplx/pplx_test/CMakeLists.txt b/Release/tests/functional/pplx/pplx_test/CMakeLists.txt index 0e2672b73e..7007a5829a 100644 --- a/Release/tests/functional/pplx/pplx_test/CMakeLists.txt +++ b/Release/tests/functional/pplx/pplx_test/CMakeLists.txt @@ -6,15 +6,4 @@ set(SOURCES add_casablanca_test(pplx_test SOURCES) -if(MSVC) - get_target_property(_srcs pplx_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/pplx-tests-stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pplx-tests-stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fppplx-tests-stdafx.pch") - target_sources(pplx_test PRIVATE stdafx.cpp) - target_compile_options(pplx_test PRIVATE /Yustdafx.h /Fppplx-tests-stdafx.pch) -endif() +configure_pch(pplx_test stdafx.h stdafx.cpp) diff --git a/Release/tests/functional/streams/CMakeLists.txt b/Release/tests/functional/streams/CMakeLists.txt index 29d09bbac8..92077b0228 100644 --- a/Release/tests/functional/streams/CMakeLists.txt +++ b/Release/tests/functional/streams/CMakeLists.txt @@ -24,15 +24,4 @@ if(NOT WIN32 OR CPPREST_WEBSOCKETS_IMPL STREQUAL "wspp") endif() endif() -if(MSVC) - get_target_property(_srcs streams_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/streams-tests-stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/streams-tests-stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fpstreams-tests-stdafx.pch") - target_sources(streams_test PRIVATE stdafx.cpp) - target_compile_options(streams_test PRIVATE /Yustdafx.h /Fpstreams-tests-stdafx.pch) -endif() +configure_pch(streams_test stdafx.h stdafx.cpp) diff --git a/Release/tests/functional/uri/CMakeLists.txt b/Release/tests/functional/uri/CMakeLists.txt index e3f7de1da2..298ec21b01 100644 --- a/Release/tests/functional/uri/CMakeLists.txt +++ b/Release/tests/functional/uri/CMakeLists.txt @@ -13,15 +13,4 @@ set(SOURCES add_casablanca_test(uri_test SOURCES) -if(MSVC) - get_target_property(_srcs uri_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/uri-tests-stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/uri-tests-stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fpuri-tests-stdafx.pch") - target_sources(uri_test PRIVATE stdafx.cpp) - target_compile_options(uri_test PRIVATE /Yustdafx.h /Fpuri-tests-stdafx.pch) -endif() +configure_pch(uri_test stdafx.h stdafx.cpp) diff --git a/Release/tests/functional/utils/CMakeLists.txt b/Release/tests/functional/utils/CMakeLists.txt index 201af77039..a8f157ecdb 100644 --- a/Release/tests/functional/utils/CMakeLists.txt +++ b/Release/tests/functional/utils/CMakeLists.txt @@ -13,15 +13,4 @@ if(CMAKE_COMPILER_IS_GNUCXX) target_compile_options(utils_test PRIVATE "-Wno-deprecated-declarations") endif() -if(MSVC) - get_target_property(_srcs utils_test SOURCES) - - if(NOT CMAKE_GENERATOR MATCHES "Visual Studio .*") - set_property(SOURCE stdafx.cpp APPEND PROPERTY OBJECT_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/utils-tests-stdafx.pch") - set_property(SOURCE ${_srcs} APPEND PROPERTY OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/utils-tests-stdafx.pch") - endif() - - set_source_files_properties(stdafx.cpp PROPERTIES COMPILE_FLAGS "/Ycstdafx.h /Fputils-tests-stdafx.pch") - target_sources(utils_test PRIVATE stdafx.cpp) - target_compile_options(utils_test PRIVATE /Yustdafx.h /Fputils-tests-stdafx.pch) -endif() +configure_pch(utils_test stdafx.h stdafx.cpp) From f7065f48a3aba547d00b6aaffbdd0de26b182e44 Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Fri, 23 Aug 2019 03:34:39 +0100 Subject: [PATCH 20/80] Fix "Data" to "Date" in the HTTP Server API mapping, and clarify that the indices of these values match the HTTP_HEADER_ID values for HTTP_REQUEST_HEADERS but *not* HTTP_RESPONSE_HEADERS (#1219) --- .../src/http/listener/http_server_httpsys.cpp | 101 ++++++++---------- .../functional/http/listener/header_tests.cpp | 25 +++++ .../http/utilities/test_http_server.cpp | 101 ++++++++---------- 3 files changed, 117 insertions(+), 110 deletions(-) diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index d4c080a76b..318d1404c0 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -43,62 +43,53 @@ namespace experimental namespace details { /// -/// String values for all HTTP Server API known headers. +/// String values for all HTTP Server API HTTP_REQUEST_HEADERS known headers. /// NOTE: the order here is important it is from the _HTTP_HEADER_ID enum. /// -static utility::string_t HttpServerAPIKnownHeaders[] = {U("Cache-Control"), - U("Connection"), - U("Data"), - U("Keep-Alive"), - U("Pragma"), - U("Trailer"), - U("Transfer-Encoding"), - U("Upgrade"), - U("Via"), - U("Warning"), - U("Allow"), - U("Content-Length"), - U("Content-Type"), - U("Content-Encoding"), - U("Content-Language"), - U("Content-Location"), - U("Content-Md5"), - U("Content-Range"), - U("Expires"), - U("Last-Modified"), - U("Accept"), - U("Accept-Charset"), - U("Accept-Encoding"), - U("Accept-Language"), - U("Authorization"), - U("Cookie"), - U("Expect"), - U("From"), - U("Host"), - U("If-Match"), - U("If-Modified-Since"), - U("If-None-Match"), - U("If-Range"), - U("If-Unmodified-Since"), - U("Max-Forwards"), - U("Proxy-Authorization"), - U("Referer"), - U("Range"), - U("TE"), - U("Translate"), - U("User-Agent"), - U("Request-Maximum"), - U("Accept-Ranges"), - U("Age"), - U("Etag"), - U("Location"), - U("Proxy-Authenticate"), - U("Retry-After"), - U("Server"), - U("Set-Cookie"), - U("Vary"), - U("Www-Authenticate"), - U("Response-Maximum")}; +static utility::string_t HttpServerAPIRequestKnownHeaders[] = +{ + U("Cache-Control"), + U("Connection"), + U("Date"), + U("Keep-Alive"), + U("Pragma"), + U("Trailer"), + U("Transfer-Encoding"), + U("Upgrade"), + U("Via"), + U("Warning"), + U("Allow"), + U("Content-Length"), + U("Content-Type"), + U("Content-Encoding"), + U("Content-Language"), + U("Content-Location"), + U("Content-MD5"), + U("Content-Range"), + U("Expires"), + U("Last-Modified"), + U("Accept"), + U("Accept-Charset"), + U("Accept-Encoding"), + U("Accept-Language"), + U("Authorization"), + U("Cookie"), + U("Expect"), + U("From"), + U("Host"), + U("If-Match"), + U("If-Modified-Since"), + U("If-None-Match"), + U("If-Range"), + U("If-Unmodified-Since"), + U("Max-Forwards"), + U("Proxy-Authorization"), + U("Referer"), + U("Range"), + U("TE"), + U("Translate"), + U("User-Agent") +}; static void char_to_wstring(utf16string& dest, const char* src) { @@ -162,7 +153,7 @@ void parse_http_headers(const HTTP_REQUEST_HEADERS& headers, http::http_headers& { if (headers.KnownHeaders[i].RawValueLength > 0) { - msgHeaders.add(HttpServerAPIKnownHeaders[i], + msgHeaders.add(HttpServerAPIRequestKnownHeaders[i], utility::conversions::to_utf16string(headers.KnownHeaders[i].pRawValue)); } } diff --git a/Release/tests/functional/http/listener/header_tests.cpp b/Release/tests/functional/http/listener/header_tests.cpp index a3cff2e2e1..87cf6783fb 100644 --- a/Release/tests/functional/http/listener/header_tests.cpp +++ b/Release/tests/functional/http/listener/header_tests.cpp @@ -112,6 +112,31 @@ SUITE(header_tests) listener.close().wait(); } + TEST_FIXTURE(uri_address, request_known_headers) + { + http_listener listener(m_uri); + listener.open().wait(); + test_http_client::scoped_client client(m_uri); + test_http_client* p_client = client.client(); + const utility::string_t mtd = methods::GET; + std::map headers; + + // "Date" was being incorrectly mapped to "Data" + // see https://github.com/microsoft/cpprestsdk/issues/1208 + headers[U("Date")] = U("Mon, 29 Jul 2019 12:32:57 GMT"); + listener.support([&](http_request request) { + http_asserts::assert_request_equals(request, mtd, U("/"), headers); + request.reply(status_codes::OK).wait(); + }); + VERIFY_ARE_EQUAL(0, p_client->request(mtd, U(""), headers)); + p_client->next_response() + .then([](test_response* p_response) { + http_asserts::assert_test_response_equals(p_response, status_codes::OK); + }) + .wait(); + listener.close().wait(); + } + TEST_FIXTURE(uri_address, response_headers) { http_listener listener(m_uri); diff --git a/Release/tests/functional/http/utilities/test_http_server.cpp b/Release/tests/functional/http/utilities/test_http_server.cpp index e3a96570ab..3abb6915b6 100644 --- a/Release/tests/functional/http/utilities/test_http_server.cpp +++ b/Release/tests/functional/http/utilities/test_http_server.cpp @@ -97,62 +97,53 @@ static utility::string_t parse_verb(const HTTP_REQUEST* p_http_request) } /// -/// String values for all HTTP Server API known headers. +/// String values for all HTTP Server API HTTP_REQUEST_HEADERS known headers. /// NOTE: the order here is important it is from the _HTTP_HEADER_ID enum. /// -static utility::string_t HttpServerAPIKnownHeaders[] = {U("Cache-Control"), - U("Connection"), - U("Data"), - U("Keep-Alive"), - U("Pragma"), - U("Trailer"), - U("Transfer-Encoding"), - U("Upgrade"), - U("Via"), - U("Warning"), - U("Allow"), - U("Content-Length"), - U("Content-Type"), - U("Content-Encoding"), - U("Content-Language"), - U("Content-Location"), - U("Content-Md5"), - U("Content-Range"), - U("Expires"), - U("Last-Modified"), - U("Accept"), - U("Accept-Charset"), - U("Accept-Encoding"), - U("Accept-Language"), - U("Authorization"), - U("Cookie"), - U("Expect"), - U("From"), - U("Host"), - U("If-Match"), - U("If-Modified-Since"), - U("If-None-Match"), - U("If-Range"), - U("If-Unmodified-Since"), - U("Max-Forwards"), - U("Proxy-Authorization"), - U("Referer"), - U("Range"), - U("TE"), - U("Translate"), - U("User-Agent"), - U("Request-Maximum"), - U("Accept-Ranges"), - U("Age"), - U("Etag"), - U("Location"), - U("Proxy-Authenticate"), - U("Retry-After"), - U("Server"), - U("Set-Cookie"), - U("Vary"), - U("Www-Authenticate"), - U("Response-Maximum")}; +static utility::string_t HttpServerAPIRequestKnownHeaders[] = +{ + U("Cache-Control"), + U("Connection"), + U("Date"), + U("Keep-Alive"), + U("Pragma"), + U("Trailer"), + U("Transfer-Encoding"), + U("Upgrade"), + U("Via"), + U("Warning"), + U("Allow"), + U("Content-Length"), + U("Content-Type"), + U("Content-Encoding"), + U("Content-Language"), + U("Content-Location"), + U("Content-MD5"), + U("Content-Range"), + U("Expires"), + U("Last-Modified"), + U("Accept"), + U("Accept-Charset"), + U("Accept-Encoding"), + U("Accept-Language"), + U("Authorization"), + U("Cookie"), + U("Expect"), + U("From"), + U("Host"), + U("If-Match"), + U("If-Modified-Since"), + U("If-None-Match"), + U("If-Range"), + U("If-Unmodified-Since"), + U("Max-Forwards"), + U("Proxy-Authorization"), + U("Referer"), + U("Range"), + U("TE"), + U("Translate"), + U("User-Agent") +}; static utility::string_t char_to_wstring(const char* src) { @@ -176,7 +167,7 @@ static std::map parse_http_headers(const H { if (headers.KnownHeaders[i].RawValueLength != 0) { - headers_map[HttpServerAPIKnownHeaders[i]] = char_to_wstring(headers.KnownHeaders[i].pRawValue); + headers_map[HttpServerAPIRequestKnownHeaders[i]] = char_to_wstring(headers.KnownHeaders[i].pRawValue); } } return headers_map; From 2a8c17e7bb535674c493afca74d49bf66171b082 Mon Sep 17 00:00:00 2001 From: Michael Khlopin Date: Fri, 23 Aug 2019 05:36:07 +0300 Subject: [PATCH 21/80] Fixing of connections_and_errors::cancel_with_error test which sometimes fires false positive error "There are no pending calls to next_request." (#1196) --- Release/tests/functional/http/client/connections_and_errors.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Release/tests/functional/http/client/connections_and_errors.cpp b/Release/tests/functional/http/client/connections_and_errors.cpp index aea69b8c08..847755d80a 100644 --- a/Release/tests/functional/http/client/connections_and_errors.cpp +++ b/Release/tests/functional/http/client/connections_and_errors.cpp @@ -341,7 +341,9 @@ SUITE(connections_and_errors) test_http_server::scoped_server server(m_uri); pplx::cancellation_token_source source; + const auto r = server.server()->next_request(); responseTask = c.request(methods::GET, U("/"), source.get_token()); + r.wait(); source.cancel(); } From ce96a318b14273edba8a122431e588b8733eb9dd Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 28 Aug 2019 12:39:31 -0700 Subject: [PATCH 22/80] Trim whitespace and nulls the same way. (#1233) --- Release/include/cpprest/asyncrt_utils.h | 20 +++++ .../src/http/client/http_client_winhttp.cpp | 48 +----------- .../src/http/common/internal_http_helpers.h | 73 ++++++++++++++++--- 3 files changed, 85 insertions(+), 56 deletions(-) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index a38702f412..4166eb8c48 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -373,6 +373,26 @@ inline bool __cdecl is_alnum(Elem ch) CPPREST_NOEXCEPT return (uch <= static_cast('z') && is_alnum(static_cast(uch))); } +/// +/// Our own implementation of whitespace test instead of std::isspace to avoid +/// taking global lock for performance reasons. +/// The following characters are considered whitespace: +/// 0x09 == Horizontal Tab +/// 0x0A == Line Feed +/// 0x0B == Vertical Tab +/// 0x0C == Form Feed +/// 0x0D == Carrage Return +/// 0x20 == Space +/// +template +inline bool __cdecl is_space(Elem ch) CPPREST_NOEXCEPT +{ + // assumes 'x' == L'x' for the ASCII range + typedef typename std::make_unsigned::type UElem; + const auto uch = static_cast(ch); + return uch == 0x20u || (uch >= 0x09u && uch <= 0x0Du); +} + /// /// Simplistic implementation of make_unique. A better implementation would be based on variadic templates /// and therefore not be compatible with Dev10. diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 249bfcd52c..f4b97f509a 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -15,6 +15,7 @@ #include "stdafx.h" #include "../common/x509_cert_utilities.h" +#include "../common/internal_http_helpers.h" #include "cpprest/http_headers.h" #include "http_client_impl.h" #include @@ -99,51 +100,6 @@ static http::status_code parse_status_code(HINTERNET request_handle) return (unsigned short)_wtoi(buffer.c_str()); } -// Helper function to trim leading and trailing null characters from a string. -static void trim_nulls(utility::string_t& str) -{ - if (str.empty()) - { - return; - } - - auto first = str.begin(); - auto last = str.end(); - - if (*first) - { - --last; - if (*last) - { - // no nulls to remove - return; - } - - // nulls at the back to remove - do - { - --last; - } while (*last == utility::char_t {}); - ++last; - str.erase(last, str.end()); - return; - } - - // nulls at the front, and maybe the back, to remove - first = std::find_if(str.begin(), last, [](const utility::char_t c) { return c != utility::char_t {}; }); - - if (first != last) - { - do - { - --last; - } while (*last == utility::char_t {}); - ++last; - } - - str.assign(first, last); -} - // Helper function to get the reason phrase from a WinHTTP response. static utility::string_t parse_reason_phrase(HINTERNET request_handle) { @@ -159,7 +115,7 @@ static utility::string_t parse_reason_phrase(HINTERNET request_handle) &length, WINHTTP_NO_HEADER_INDEX); // WinHTTP reports back the wrong length, trim any null characters. - trim_nulls(phrase); + ::web::http::details::trim_nulls(phrase); return phrase; } diff --git a/Release/src/http/common/internal_http_helpers.h b/Release/src/http/common/internal_http_helpers.h index 2270f7b955..1fbdfdfa58 100644 --- a/Release/src/http/common/internal_http_helpers.h +++ b/Release/src/http/common/internal_http_helpers.h @@ -5,6 +5,7 @@ #pragma once +#include "cpprest/asyncrt_utils.h" #include "cpprest/details/basic_types.h" #include @@ -19,19 +20,71 @@ namespace details /// utility::string_t get_default_reason_phrase(status_code code); -// simple helper functions to trim whitespace. +template +void trim_if(std::basic_string& str, Fn test) +{ + if (str.empty()) + { + return; + } + + auto first = str.begin(); + auto last = str.end(); + + if (test(*first)) + { + // removals at the front, and maybe the back + for (;;) + { + ++first; + if (first == last) + { + // all removals + str.clear(); + return; + } + + if (!test(*first)) + { + break; + } + } + + do + { + --last; + } while (test(*last)); + ++last; + str.assign(first, last); + return; + } + + // no removals at the front, only maybe the back + --last; + if (!test(*last)) + { + // no removals at all + return; + } + + do + { + --last; + } while (test(*last)); + ++last; + str.erase(last, str.end()); +} + +template +void trim_nulls(std::basic_string& str) +{ + trim_if(str, [](const Char c) { return c == Char {}; }); +} + template void trim_whitespace(std::basic_string& str) { - size_t index; - // trim left whitespace - for (index = 0; index < str.size() && isspace(str[index]); ++index) - ; - str.erase(0, index); - // trim right whitespace - for (index = str.size(); index > 0 && isspace(str[index - 1]); --index) - ; - str.erase(index); + trim_if(str, [](const Char c) { return ::utility::details::is_space(c); }); } bool validate_method(const utility::string_t& method); From c4f37e7a04c9aab49a52a0f85cd815b08ceb2623 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Fri, 27 Sep 2019 14:08:02 -0700 Subject: [PATCH 23/80] Avoid using permissive- with ZW which breaks VS2019 (#1248) * Also add VS2019 configurations to Azure Pipelines. * Also turn on vcpkg caching from @lukka --- .gitmodules | 3 +- Release/CMakeLists.txt | 8 +- azure-devops/build-windows.yml | 50 ++++++++++ azure-devops/vcpkg-windows.txt | 7 ++ azure-pipelines.yml | 162 +++++++-------------------------- vcpkg | 2 +- 6 files changed, 96 insertions(+), 136 deletions(-) create mode 100644 azure-devops/build-windows.yml create mode 100644 azure-devops/vcpkg-windows.txt diff --git a/.gitmodules b/.gitmodules index 5a33829602..54befd07da 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,7 @@ [submodule "vcpkg"] path = vcpkg url = https://github.com/Microsoft/vcpkg -[submodule "websocketspp"] +[submodule "websocketpp"] path = Release/libs/websocketpp url = https://github.com/zaphoyd/websocketpp/ + fetchRecurseSubmodules = false diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 4b6433a93a..6d2521b016 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -187,10 +187,10 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") if (WINDOWS_STORE OR WINDOWS_PHONE) add_compile_options(/ZW) - endif() - - if (NOT (MSVC_VERSION LESS 1920)) - add_compile_options(/permissive-) + else() + if (NOT (MSVC_VERSION LESS 1920)) + add_compile_options(/permissive-) + endif() endif() else() message("-- Unknown compiler, success is doubtful.") diff --git a/azure-devops/build-windows.yml b/azure-devops/build-windows.yml new file mode 100644 index 0000000000..45ea392a82 --- /dev/null +++ b/azure-devops/build-windows.yml @@ -0,0 +1,50 @@ +parameters: + name: 'Windows_VS2019_x86' + targetPlatform: 'x86' + image: 'windows-latest' + +jobs: +- job: ${{ parameters.name }} + pool: + vmImage: ${{ parameters.image }} + variables: + vcpkgLocation: '$(Build.SourcesDirectory)/vcpkg' + vcpkgResponseFile: $(Build.SourcesDirectory)/azure-devops/vcpkg-windows.txt + steps: + - task: CacheBeta@0 + displayName: Cache vcpkg + inputs: + key: $(vcpkgResponseFile) | $(Build.SourcesDirectory)/.git/modules/vcpkg/HEAD | ${{ parameters.targetPlatform }} | ${{ parameters.image }} + path: '$(vcpkgLocation)' + - task: run-vcpkg@0 + displayName: 'Run vcpkg' + inputs: + vcpkgArguments: '@$(vcpkgResponseFile)' + vcpkgDirectory: '$(vcpkgLocation)' + vcpkgTriplet: ${{ parameters.targetPlatform }}-windows + - task: run-cmake@0 + displayName: 'Run CMake with Ninja (Debug)' + enabled: true + inputs: + cmakeListsOrSettingsJson: 'CMakeListsTxtBasic' + cmakeBuildType: 'Debug' + useVcpkgToolchainFile: true + buildDirectory: $(Build.ArtifactStagingDirectory)/${{ parameters.targetPlatform }}_Debug + cmakeAppendedArgs: '-DCPPREST_EXCLUDE_BROTLI=OFF' + - script: | + cd $(Build.ArtifactStagingDirectory)\${{ parameters.targetPlatform }}_Debug\Release\Binaries + .\test_runner.exe *testd.dll + displayName: 'Run tests, debug' + - task: run-cmake@0 + displayName: 'Run CMake with Ninja (Release)' + enabled: true + inputs: + cmakeListsOrSettingsJson: 'CMakeListsTxtBasic' + cmakeBuildType: 'Release' + useVcpkgToolchainFile: true + buildDirectory: $(Build.ArtifactStagingDirectory)/${{ parameters.targetPlatform }}_Release + cmakeAppendedArgs: '-DCPPREST_EXCLUDE_BROTLI=OFF' + - script: | + cd $(Build.ArtifactStagingDirectory)\${{ parameters.targetPlatform }}_Release\Release\Binaries + .\test_runner.exe *test.dll + displayName: 'Run tests, release' diff --git a/azure-devops/vcpkg-windows.txt b/azure-devops/vcpkg-windows.txt new file mode 100644 index 0000000000..582d18dcdb --- /dev/null +++ b/azure-devops/vcpkg-windows.txt @@ -0,0 +1,7 @@ +openssl +boost-system +boost-date-time +boost-regex +boost-interprocess +websocketpp +brotli diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8c878f0901..8fc6f54365 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,73 +1,39 @@ # CppRestSdk Azure Pipelines Configuration jobs: - - job: Windows_VS2017_x86 + - template: azure-devops/build-windows.yml + parameters: + name: 'Windows_VS2019_x86' + targetPlatform: x86 + image: 'windows-latest' + - template: azure-devops/build-windows.yml + parameters: + name: 'Windows_VS2019_x64' + targetPlatform: x64 + image: 'windows-latest' + - template: azure-devops/build-windows.yml + parameters: + name: 'Windows_VS2017_x86' + targetPlatform: x86 + image: 'vs2017-win2016' + - template: azure-devops/build-windows.yml + parameters: + name: 'Windows_VS2017_x64' + targetPlatform: x64 + image: 'vs2017-win2016' + - template: azure-devops/build-windows.yml + parameters: + name: 'Windows_VS2015_x86' + targetPlatform: x86 + image: 'vs2015-win2012r2' + - template: azure-devops/build-windows.yml + parameters: + name: 'Windows_VS2015_x64' + targetPlatform: x64 + image: 'vs2015-win2012r2' + - job: Windows_VS2019_UWP pool: - vmImage: 'vs2017-win2016' - steps: - - script: .\vcpkg\bootstrap-vcpkg.bat - displayName: Bootstrap vcpkg - - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp brotli --vcpkg-root .\vcpkg - displayName: vcpkg install dependencies - - script: mkdir build.common - displayName: Make Build Directory - - task: CMake@1 - inputs: - workingDirectory: 'build.common' - cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DCPPREST_EXCLUDE_BROTLI=OFF ..' - - task: MSBuild@1 - inputs: - solution: 'build.common/ALL_BUILD.vcxproj' - maximumCpuCount: true - - script: | - cd build.common\Release\Binaries\Debug - .\test_runner.exe *testd.dll - displayName: 'Run tests, debug' - - task: MSBuild@1 - inputs: - solution: 'build.common/ALL_BUILD.vcxproj' - maximumCpuCount: true - configuration: 'Release' - - script: | - cd build.common\Release\Binaries\Release - .\test_runner.exe *test.dll - displayName: 'Run tests, release' - - job: Windows_VS2017_x64 - pool: - vmImage: 'vs2017-win2016' - steps: - - script: .\vcpkg\bootstrap-vcpkg.bat - displayName: Bootstrap vcpkg - - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp brotli --triplet x64-windows --vcpkg-root .\vcpkg - displayName: vcpkg install dependencies - - script: mkdir build.common - displayName: Make Build Directory - - task: CMake@1 - inputs: - workingDirectory: 'build.common' - cmakeArgs: '-A x64 -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DCPPREST_EXCLUDE_BROTLI=OFF ..' - - task: MSBuild@1 - inputs: - solution: 'build.common/ALL_BUILD.vcxproj' - maximumCpuCount: true - platform: 'x64' - - script: | - cd build.common\Release\Binaries\Debug - .\test_runner.exe *testd.dll - displayName: 'Run tests, debug' - - task: MSBuild@1 - inputs: - solution: 'build.common/ALL_BUILD.vcxproj' - maximumCpuCount: true - platform: 'x64' - configuration: 'Release' - - script: | - cd build.common\Release\Binaries\Release - .\test_runner.exe *test.dll - displayName: 'Run tests, release' - - job: Windows_VS2017_UWP - pool: - vmImage: 'vs2017-win2016' + vmImage: 'windows-latest' steps: - script: .\vcpkg\bootstrap-vcpkg.bat displayName: Bootstrap vcpkg @@ -84,70 +50,6 @@ jobs: solution: 'build.common/ALL_BUILD.vcxproj' maximumCpuCount: true platform: 'x64' - - job: Windows_VS2015_x86 - pool: - vmImage: 'vs2015-win2012r2' - steps: - - script: .\vcpkg\bootstrap-vcpkg.bat - displayName: Bootstrap vcpkg - - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp brotli --vcpkg-root .\vcpkg - displayName: vcpkg install dependencies - - script: mkdir build.common - displayName: Make Build Directory - - task: CMake@1 - inputs: - workingDirectory: 'build.common' - cmakeArgs: '-DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DCPPREST_EXCLUDE_BROTLI=OFF ..' - - task: MSBuild@1 - inputs: - solution: 'build.common/ALL_BUILD.vcxproj' - maximumCpuCount: true - - script: | - cd build.common\Release\Binaries\Debug - .\test_runner.exe *testd.dll - displayName: 'Run tests, debug' - - task: MSBuild@1 - inputs: - solution: 'build.common/ALL_BUILD.vcxproj' - maximumCpuCount: true - configuration: 'Release' - - script: | - cd build.common\Release\Binaries\Release - .\test_runner.exe *test.dll - displayName: 'Run tests, release' - - job: Windows_VS2015_x64 - pool: - vmImage: 'vs2015-win2012r2' - steps: - - script: .\vcpkg\bootstrap-vcpkg.bat - displayName: Bootstrap vcpkg - - script: .\vcpkg\vcpkg.exe install zlib openssl boost-system boost-date-time boost-regex boost-interprocess websocketpp brotli --triplet x64-windows --vcpkg-root .\vcpkg - displayName: vcpkg install dependencies - - script: mkdir build.common - displayName: Make Build Directory - - task: CMake@1 - inputs: - workingDirectory: 'build.common' - cmakeArgs: '-A x64 -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DCPPREST_EXCLUDE_BROTLI=OFF ..' - - task: MSBuild@1 - inputs: - solution: 'build.common/ALL_BUILD.vcxproj' - maximumCpuCount: true - platform: 'x64' - - script: | - cd build.common\Release\Binaries\Debug - .\test_runner.exe *testd.dll - displayName: 'Run tests, debug' - - task: MSBuild@1 - inputs: - solution: 'build.common/ALL_BUILD.vcxproj' - maximumCpuCount: true - platform: 'x64' - configuration: 'Release' - - script: | - cd build.common\Release\Binaries\Release - .\test_runner.exe *test.dll - displayName: 'Run tests, release' - job: Ubuntu_1604_Apt pool: vmImage: 'Ubuntu 16.04' diff --git a/vcpkg b/vcpkg index b7d6160b80..ee0bfad1cf 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit b7d6160b80f417137bc480137b946c91f3272bf5 +Subproject commit ee0bfad1cfa11e048823e2d02d9f619db7d94a3f From f4c863bcf55b2df25aa087377d7ec1978ae0af29 Mon Sep 17 00:00:00 2001 From: Sinan Kaya <41809318+franksinankaya@users.noreply.github.com> Date: Fri, 27 Sep 2019 19:27:44 -0400 Subject: [PATCH 24/80] Support for WinHTTPAL curl-to-WinHTTP adapter (#1182) --- Release/CMakeLists.txt | 1 + Release/cmake/cpprest_find_winhttppal.cmake | 17 +++++ Release/cmake/cpprestsdk-config.in.cmake | 4 ++ Release/include/cpprest/http_client.h | 8 +-- Release/src/CMakeLists.txt | 12 ++++ Release/src/http/client/http_client.cpp | 4 +- Release/src/http/client/http_client_impl.h | 5 +- .../src/http/client/http_client_winhttp.cpp | 68 ++++++++++++------- Release/src/http/common/http_msg.cpp | 20 +++--- .../http/client/client_construction.cpp | 2 +- .../functional/http/client/outside_tests.cpp | 4 +- .../http/client/request_uri_tests.cpp | 6 +- azure-pipelines.yml | 44 ++++++++++++ 13 files changed, 146 insertions(+), 49 deletions(-) create mode 100644 Release/cmake/cpprest_find_winhttppal.cmake diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 6d2521b016..000516e1be 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -61,6 +61,7 @@ endif() include(cmake/cpprest_find_boost.cmake) include(cmake/cpprest_find_zlib.cmake) +include(cmake/cpprest_find_winhttppal.cmake) include(cmake/cpprest_find_openssl.cmake) include(cmake/cpprest_find_websocketpp.cmake) include(cmake/cpprest_find_brotli.cmake) diff --git a/Release/cmake/cpprest_find_winhttppal.cmake b/Release/cmake/cpprest_find_winhttppal.cmake new file mode 100644 index 0000000000..9a6840fba2 --- /dev/null +++ b/Release/cmake/cpprest_find_winhttppal.cmake @@ -0,0 +1,17 @@ +function(cpprest_find_winhttppal) + if(TARGET cpprestsdk_winhttppal_internal) + return() + endif() + + if(NOT WINHTTPPAL_LIBRARY OR NOT WINHTTPPAL_INCLUDE_DIRS) + find_package(winhttppal REQUIRED) + endif() + + add_library(cpprestsdk_winhttppal_internal INTERFACE) + if(TARGET winhttppal::winhttppal) + target_link_libraries(cpprestsdk_winhttppal_internal INTERFACE winhttppal::winhttppal) + else() + target_link_libraries(cpprestsdk_winhttppal_internal INTERFACE "$") + target_include_directories(cpprestsdk_winhttppal_internal INTERFACE "$") + endif() +endfunction() diff --git a/Release/cmake/cpprestsdk-config.in.cmake b/Release/cmake/cpprestsdk-config.in.cmake index 8b5e8a6ff3..be95abf99a 100644 --- a/Release/cmake/cpprestsdk-config.in.cmake +++ b/Release/cmake/cpprestsdk-config.in.cmake @@ -11,6 +11,10 @@ if(@CPPREST_USES_OPENSSL@) find_dependency(OpenSSL) endif() +if(@CPPREST_USES_WINHTTPPAL@) + find_dependency(WINHTTPPAL) +endif() + if(@CPPREST_USES_BOOST@ AND OFF) if(UNIX) find_dependency(Boost COMPONENTS random system thread filesystem chrono atomic date_time regex) diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 0bedfbd42a..82fa3222b6 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -104,7 +104,7 @@ class http_client_config #if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO) , m_tlsext_sni_enabled(true) #endif -#if defined(_WIN32) && !defined(__cplusplus_winrt) +#if (defined(_WIN32) && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) , m_buffer_request(false) #endif { @@ -262,7 +262,7 @@ class http_client_config void set_validate_certificates(bool validate_certs) { m_validate_certificates = validate_certs; } #endif -#if defined(_WIN32) && !defined(__cplusplus_winrt) +#if (defined(_WIN32) && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) /// /// Checks if request data buffering is turned on, the default is off. /// @@ -389,7 +389,7 @@ class http_client_config std::function m_ssl_context_callback; bool m_tlsext_sni_enabled; #endif -#if defined(_WIN32) && !defined(__cplusplus_winrt) +#if (defined(_WIN32) && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) bool m_buffer_request; #endif }; @@ -716,7 +716,7 @@ class http_client namespace details { -#if defined(_WIN32) +#if defined(_WIN32) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) extern const utility::char_t* get_with_body_err_msg; #endif diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 119b07afe2..c9d0349a87 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -131,6 +131,13 @@ if(CPPREST_HTTP_CLIENT_IMPL STREQUAL "asio") target_compile_definitions(cpprest PUBLIC -DCPPREST_FORCE_HTTP_CLIENT_ASIO) target_sources(cpprest PRIVATE http/client/http_client_asio.cpp http/client/x509_cert_utilities.cpp) target_link_libraries(cpprest PUBLIC cpprestsdk_boost_internal cpprestsdk_openssl_internal) +elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winhttppal") + cpprest_find_boost() + cpprest_find_openssl() + cpprest_find_winhttppal() + target_compile_definitions(cpprest PUBLIC -DCPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) + target_sources(cpprest PRIVATE http/client/http_client_winhttp.cpp http/client/x509_cert_utilities.cpp) + target_link_libraries(cpprest PUBLIC cpprestsdk_boost_internal cpprestsdk_openssl_internal cpprestsdk_winhttppal_internal) elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winhttp") target_link_libraries(cpprest PRIVATE httpapi.lib @@ -237,6 +244,7 @@ if(CPPREST_INSTALL) set(CPPREST_USES_ZLIB OFF) set(CPPREST_USES_BROTLI OFF) set(CPPREST_USES_OPENSSL OFF) + set(CPPREST_USES_WINHTTPPAL OFF) set(CPPREST_TARGETS cpprest) if(TARGET cpprestsdk_boost_internal) @@ -255,6 +263,10 @@ if(CPPREST_INSTALL) list(APPEND CPPREST_TARGETS cpprestsdk_openssl_internal) set(CPPREST_USES_OPENSSL ON) endif() + if(TARGET cpprestsdk_winhttppal_internal) + list(APPEND CPPREST_TARGETS cpprestsdk_winhttppal_internal) + set(CPPREST_USES_WINHTTPPAL ON) + endif() if(TARGET cpprestsdk_websocketpp_internal) list(APPEND CPPREST_TARGETS cpprestsdk_websocketpp_internal) endif() diff --git a/Release/src/http/client/http_client.cpp b/Release/src/http/client/http_client.cpp index f3174272bb..09e3eed15a 100644 --- a/Release/src/http/client/http_client.cpp +++ b/Release/src/http/client/http_client.cpp @@ -41,8 +41,8 @@ static void verify_uri(const uri& uri) namespace details { -#if defined(_WIN32) -extern const utility::char_t* get_with_body_err_msg = +#if defined(_WIN32) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) +const utility::char_t* get_with_body_err_msg = _XPLATSTR("A GET or HEAD request should not have an entity body."); #endif diff --git a/Release/src/http/client/http_client_impl.h b/Release/src/http/client/http_client_impl.h index 384c9b2de6..d9e7d4829e 100644 --- a/Release/src/http/client/http_client_impl.h +++ b/Release/src/http/client/http_client_impl.h @@ -30,13 +30,10 @@ namespace details /// Serialize the http_headers into name:value pairs separated by a carriage return and line feed. /// utility::string_t flatten_http_headers(const http_headers& headers); -#if defined(_WIN32) /// /// Parses a string containing Http headers. /// -void parse_headers_string(_Inout_z_ utf16char* headersStr, http_headers& headers); -#endif - +void parse_headers_string(_Inout_z_ utility::char_t* headersStr, http_headers& headers); } // namespace details } // namespace http } // namespace web diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index f4b97f509a..fc2bfbae8c 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -18,10 +18,15 @@ #include "../common/internal_http_helpers.h" #include "cpprest/http_headers.h" #include "http_client_impl.h" +#ifdef WIN32 #include +#endif +#if defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) +#include "winhttppal.h" +#endif #include -#if _WIN32_WINNT >= _WIN32_WINNT_VISTA +#if _WIN32_WINNT && (_WIN32_WINNT >= _WIN32_WINNT_VISTA) #include #endif @@ -97,7 +102,7 @@ static http::status_code parse_status_code(HINTERNET request_handle) &buffer[0], &length, WINHTTP_NO_HEADER_INDEX); - return (unsigned short)_wtoi(buffer.c_str()); + return (unsigned short)stoi(buffer); } // Helper function to get the reason phrase from a WinHTTP response. @@ -122,7 +127,7 @@ static utility::string_t parse_reason_phrase(HINTERNET request_handle) /// /// Parses a string containing HTTP headers. /// -static void parse_winhttp_headers(HINTERNET request_handle, _In_z_ utf16char* headersStr, http_response& response) +static void parse_winhttp_headers(HINTERNET request_handle, _In_z_ utility::char_t* headersStr, http_response& response) { // Clear the header map for each new response; otherwise, the header values will be combined. response.headers().clear(); @@ -141,7 +146,7 @@ static std::string build_error_msg(unsigned long code, const std::string& locati msg.append(": "); msg.append(std::to_string(code)); msg.append(": "); - msg.append(utility::details::windows_category().message(code)); + msg.append(utility::details::platform_category().message(static_cast(code))); return msg; } @@ -159,6 +164,7 @@ static std::string build_error_msg(_In_ WINHTTP_ASYNC_RESULT* error_result) } } + class memory_holder { uint8_t* m_externalData; @@ -289,7 +295,7 @@ class winhttp_request_context final : public request_context { } -#if defined(_MSC_VER) && _MSC_VER < 1900 +#if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) compression_state(const compression_state&) = delete; compression_state(compression_state&& other) : m_buffer(std::move(other.m_buffer)) @@ -552,6 +558,10 @@ class winhttp_request_context final : public request_context void on_send_request_validate_cn() { +#if defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) + // we do the validation inside curl + return; +#else if (m_customCnCheck.empty()) { // no custom validation selected; either we've delegated that to winhttp or @@ -647,6 +657,7 @@ class winhttp_request_context final : public request_context } m_cachedEncodedCert.assign(encodedFirst, encodedLast); +#endif } protected: @@ -666,13 +677,13 @@ class winhttp_request_context final : public request_context winhttp_request_context(const std::shared_ptr<_http_client_communicator>& client, const http_request& request) : request_context(client, request) , m_request_handle(nullptr) - , m_bodyType(no_body) - , m_startingPosition(std::char_traits::eof()) - , m_body_data() - , m_remaining_to_write(0) , m_proxy_authentication_tried(false) , m_server_authentication_tried(false) + , m_bodyType(no_body) + , m_remaining_to_write(0) + , m_startingPosition(std::char_traits::eof()) , m_readStream(request.body()) + , m_body_data() { } }; @@ -731,10 +742,10 @@ class winhttp_client final : public _http_client_communicator public: winhttp_client(http::uri address, http_client_config client_config) : _http_client_communicator(std::move(address), std::move(client_config)) - , m_secure(m_uri.scheme() == _XPLATSTR("https")) , m_opened(false) , m_hSession(nullptr) , m_hConnection(nullptr) + , m_secure(m_uri.scheme() == _XPLATSTR("https")) { } @@ -752,7 +763,7 @@ class winhttp_client final : public _http_client_communicator if (m_hSession != nullptr) { // Unregister the callback. - WinHttpSetStatusCallback(m_hSession, nullptr, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, NULL); + WinHttpSetStatusCallback(m_hSession, nullptr, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0); WinHttpCloseHandle(m_hSession); } @@ -792,8 +803,8 @@ class winhttp_client final : public _http_client_communicator ie_proxy_config proxyIE; DWORD access_type; - LPCWSTR proxy_name = WINHTTP_NO_PROXY_NAME; - LPCWSTR proxy_bypass = WINHTTP_NO_PROXY_BYPASS; + LPCTSTR proxy_name = WINHTTP_NO_PROXY_NAME; + LPCTSTR proxy_bypass = WINHTTP_NO_PROXY_BYPASS; m_proxy_auto_config = false; utility::string_t proxy_str; http::uri uri; @@ -901,7 +912,7 @@ class winhttp_client final : public _http_client_communicator } // Enable TLS 1.1 and 1.2 -#if _WIN32_WINNT >= _WIN32_WINNT_VISTA +#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) BOOL win32_result(FALSE); DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | @@ -965,6 +976,17 @@ class winhttp_client final : public _http_client_communicator proxy_info info; bool proxy_info_required = false; + const auto& method = msg.method(); + + // stop injection of headers via method + // resource should be ok, since it's been encoded + // and host won't resolve + if (!::web::http::details::validate_method(method)) + { + request->report_exception(http_exception("The method string is invalid.")); + return; + } + if (m_proxy_auto_config) { WINHTTP_AUTOPROXY_OPTIONS autoproxy_options {}; @@ -1416,7 +1438,6 @@ class winhttp_client final : public _http_client_communicator { return pplx::task_from_exception(std::current_exception()); } - _ASSERTE(bytes_read >= 0); uint8_t* buffer = p_request_context->m_compression_state.m_acquired; if (buffer == nullptr) @@ -1689,16 +1710,16 @@ class winhttp_client final : public _http_client_communicator } } - static std::wstring get_request_url(HINTERNET hRequestHandle) + static utility::string_t get_request_url(HINTERNET hRequestHandle) { - std::wstring url; + utility::string_t url; auto urlSize = static_cast(url.capacity()) * 2; // use initial small string optimization capacity for (;;) { - url.resize(urlSize / sizeof(wchar_t)); - if (WinHttpQueryOption(hRequestHandle, WINHTTP_OPTION_URL, &url[0], &urlSize)) + url.resize(urlSize / sizeof(utility::char_t)); + if (WinHttpQueryOption(hRequestHandle, WINHTTP_OPTION_URL, &url[0], (LPDWORD)&urlSize)) { - url.resize(wcslen(url.c_str())); + url.resize(url.length()); return url; } @@ -2014,7 +2035,7 @@ class winhttp_client final : public _http_client_communicator // Now allocate buffer for headers and query for them. std::vector header_raw_buffer; header_raw_buffer.resize(headerBufferLength); - utf16char* header_buffer = reinterpret_cast(&header_raw_buffer[0]); + utility::char_t* header_buffer = reinterpret_cast(&header_raw_buffer[0]); if (!WinHttpQueryHeaders(hRequestHandle, WINHTTP_QUERY_RAW_HEADERS_CRLF, WINHTTP_HEADER_NAME_BY_INDEX, @@ -2052,7 +2073,7 @@ class winhttp_client final : public _http_client_communicator !p_request_context->m_http_client->client_config().request_compressed_response()) { p_request_context->m_compression_state.m_chunk = - std::make_unique(); + ::utility::details::make_unique(); p_request_context->m_compression_state.m_chunked = true; } @@ -2390,7 +2411,7 @@ class winhttp_client final : public _http_client_communicator }).then([p_request_context](pplx::task op) { try { - bool ignored = op.get(); + op.get(); } catch (...) { @@ -2466,6 +2487,7 @@ std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage( return std::make_shared(std::move(base_uri), std::move(client_config)); } + } // namespace details } // namespace client } // namespace http diff --git a/Release/src/http/common/http_msg.cpp b/Release/src/http/common/http_msg.cpp index c32dfcfaaa..a3c51c62a1 100644 --- a/Release/src/http/common/http_msg.cpp +++ b/Release/src/http/common/http_msg.cpp @@ -225,27 +225,27 @@ utility::string_t flatten_http_headers(const http_headers& headers) return flattened_headers; } -#if defined(_WIN32) -void parse_headers_string(_Inout_z_ utf16char* headersStr, http_headers& headers) +void parse_headers_string(_Inout_z_ utility::char_t* headersStr, web::http::http_headers& headers) { - utf16char* context = nullptr; - utf16char* line = wcstok_s(headersStr, CRLF, &context); - while (line != nullptr) + utility::string_t str(headersStr); + std::size_t pos = str.find_first_of(_XPLATSTR("\r\n")); + std::size_t startpos = 0; + while (pos!=std::string::npos) { - const utility::string_t header_line(line); + const utility::string_t header_line(str, startpos, pos - startpos); const size_t colonIndex = header_line.find_first_of(_XPLATSTR(":")); if (colonIndex != utility::string_t::npos) { utility::string_t key = header_line.substr(0, colonIndex); utility::string_t value = header_line.substr(colonIndex + 1, header_line.length() - colonIndex - 1); - http::details::trim_whitespace(key); - http::details::trim_whitespace(value); + web::http::details::trim_whitespace(key); + web::http::details::trim_whitespace(value); headers.add(key, value); } - line = wcstok_s(nullptr, CRLF, &context); + startpos = pos + 1; + pos = str.find_first_of(_XPLATSTR("\r\n"), pos + 1); } } -#endif } // namespace details diff --git a/Release/tests/functional/http/client/client_construction.cpp b/Release/tests/functional/http/client/client_construction.cpp index 1229b2cfd7..f5d20b8379 100644 --- a/Release/tests/functional/http/client/client_construction.cpp +++ b/Release/tests/functional/http/client/client_construction.cpp @@ -173,7 +173,7 @@ SUITE(client_construction) VERIFY_ARE_EQUAL(baseclient2.base_uri(), m_uri); } -#if !defined(_WIN32) && !defined(__cplusplus_winrt) +#if defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) // Verify that the callback of sslcontext is called for HTTPS TEST_FIXTURE(uri_address, ssl_context_callback_https) diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index 3ff1a809ec..05bb306e7a 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -228,7 +228,7 @@ SUITE(outside_tests) TEST(server_hostname_mismatch) { test_failed_ssl_cert(U("https://wrong.host.badssl.com/")); } -#if !defined(__cplusplus_winrt) +#if !defined(__cplusplus_winrt) && !defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) TEST(server_hostname_host_override) { handle_timeout([] { @@ -253,7 +253,7 @@ SUITE(outside_tests) const auto statusCode = response.status_code(); CHECK(statusCode == status_codes::OK || statusCode == status_codes::MovedPermanently); } -#endif // !defined(__cplusplus_winrt) +#endif // !defined(__cplusplus_winrt) && !defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) TEST(server_cert_expired) { test_failed_ssl_cert(U("https://expired.badssl.com/")); } diff --git a/Release/tests/functional/http/client/request_uri_tests.cpp b/Release/tests/functional/http/client/request_uri_tests.cpp index c856b600e3..5d61556991 100644 --- a/Release/tests/functional/http/client/request_uri_tests.cpp +++ b/Release/tests/functional/http/client/request_uri_tests.cpp @@ -88,7 +88,7 @@ SUITE(request_uri_tests) // WinRT implementation percent encodes the '#'. utility::string_t expected_value = U("/heheh?key1=value2#fragment"); -#ifdef __cplusplus_winrt +#if defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) expected_value = percent_encode_pound(expected_value); #endif @@ -137,7 +137,7 @@ SUITE(request_uri_tests) p_server->next_request().then([&](test_request* p_request) { // WinRT implementation percent encodes the '#'. utility::string_t expected_value = U("/path1?key1=value1&key2=value2#frag"); -#ifdef __cplusplus_winrt +#if defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) expected_value = percent_encode_pound(expected_value); #endif http_asserts::assert_test_request_equals(p_request, methods::GET, expected_value); @@ -157,7 +157,7 @@ SUITE(request_uri_tests) p_server->next_request().then([&](test_request* p_request) { // WinRT implementation percent encodes the '#'. utility::string_t expected_value = U("/path1/path2?key2=value2#fragmentfg2"); -#ifdef __cplusplus_winrt +#if defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) expected_value = percent_encode_pound(expected_value); #endif http_asserts::assert_test_request_equals(p_request, methods::GET, expected_value); diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 8fc6f54365..a5e397d0e8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -214,3 +214,47 @@ jobs: # cd Build_iOS # ./configure.sh # displayName: 'Build for iOS' + - job: Ubuntu_1604_Apt_winhttppal + pool: + vmImage: 'Ubuntu 16.04' + steps: + - script: | + set -e + sudo apt -y remove php* + sudo apt install -y ppa-purge + sudo ppa-purge -y ppa:ondrej/php + unset BOOST_ROOT + sudo apt install -y libboost-atomic-dev libboost-thread-dev libboost-system-dev libboost-date-time-dev libboost-regex-dev libboost-filesystem-dev libboost-random-dev libboost-chrono-dev libboost-serialization-dev libwebsocketpp-dev openssl libssl-dev ninja-build wget + wget http://curl.haxx.se/download/curl-7.57.0.tar.gz + sudo apt install -y libtool + sudo apt install -y make + tar -xvf curl-7.57.0.tar.gz + cd curl-7.57.0 + ./buildconf + ./configure --with-ssl --prefix=/usr + make + sudo make install + cd .. + git clone https://github.com/microsoft/WinHttpPAL.git + cd WinHttpPAL + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr .. + make + sudo make install + cd ../.. + mkdir build.debug + cd build.debug + /usr/local/bin/cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCPPREST_HTTP_CLIENT_IMPL=winhttppal .. + cd .. + mkdir build.release + cd build.release + /usr/local/bin/cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCPPREST_HTTP_CLIENT_IMPL=winhttppal .. + cd .. + ninja -C build.debug + ninja -C build.release + cd build.debug/Release/Binaries + #./test_runner *test.so + cd ../../../build.release/Release/Binaries + #./test_runner *test.so + displayName: Run build From 7e50b513398a5ec9cd72e62ade887adeccc73608 Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Tue, 29 Oct 2019 01:40:35 +0000 Subject: [PATCH 25/80] http_server_httpsys.cpp requires linking against httpapi.lib, http_client_winhttp.cpp does not. (#1253) --- Release/src/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index c9d0349a87..1c40257c47 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -140,7 +140,6 @@ elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winhttppal") target_link_libraries(cpprest PUBLIC cpprestsdk_boost_internal cpprestsdk_openssl_internal cpprestsdk_winhttppal_internal) elseif(CPPREST_HTTP_CLIENT_IMPL STREQUAL "winhttp") target_link_libraries(cpprest PRIVATE - httpapi.lib Winhttp.lib ) target_sources(cpprest PRIVATE http/client/http_client_winhttp.cpp) @@ -176,6 +175,9 @@ elseif(CPPREST_HTTP_LISTENER_IMPL STREQUAL "httpsys") http/listener/http_server_httpsys.cpp http/listener/http_server_httpsys.h ) + target_link_libraries(cpprest PRIVATE + httpapi.lib + ) elseif(CPPREST_HTTP_LISTENER_IMPL STREQUAL "none") else() message(FATAL_ERROR "Invalid implementation") From ce443d567f1550a911a1b4e8539615a2f1b67347 Mon Sep 17 00:00:00 2001 From: ASHISH BHARDWAJ Date: Tue, 29 Oct 2019 07:11:03 +0530 Subject: [PATCH 26/80] Update README.md (#1256) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 391027675b..09cf148dcf 100644 --- a/README.md +++ b/README.md @@ -73,3 +73,4 @@ We'd love to get your review score, whether good or bad, but even more than that * Directly contact us: This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + From fd6aa00c18a7fb8dbe957175078f02346775045a Mon Sep 17 00:00:00 2001 From: kevin-- Date: Mon, 28 Oct 2019 18:41:24 -0700 Subject: [PATCH 27/80] remove trailing slash on websocketpp submodule url, which causes checkout failure on CircleCI with git 2.22.0 (#1263) --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 54befd07da..f9d0b58a34 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,5 +3,5 @@ url = https://github.com/Microsoft/vcpkg [submodule "websocketpp"] path = Release/libs/websocketpp - url = https://github.com/zaphoyd/websocketpp/ + url = https://github.com/zaphoyd/websocketpp fetchRecurseSubmodules = false From c9f91156e34af0f6727edbb4cf766ff501735340 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 18 Dec 2019 13:41:42 -0800 Subject: [PATCH 28/80] Update vcpkg and remove tests that look for web servers that no longer exist (#1293) --- Build_android/configure.sh | 2 +- Build_iOS/configure.sh | 4 +- .../client/authentication_tests.cpp | 79 ------------------- azure-pipelines.yml | 79 +++++++++---------- vcpkg | 2 +- 5 files changed, 42 insertions(+), 124 deletions(-) diff --git a/Build_android/configure.sh b/Build_android/configure.sh index 5088f44d8f..ea29c38b29 100755 --- a/Build_android/configure.sh +++ b/Build_android/configure.sh @@ -155,7 +155,7 @@ if [ "${DO_OPENSSL}" == "1" ]; then ( if [ "${DO_BOOST}" == "1" ]; then ( if [ ! -d 'Boost-for-Android' ]; then git clone https://github.com/moritz-wundke/Boost-for-Android; fi cd Boost-for-Android - git checkout aed656a97fb3af7322fd2c3da5995a2d09d87d4b + git checkout 245ea53385a55742a9ab08a8bd32c6a2dc0bbea4 PATH="$PATH:$NDK_DIR" \ CXXFLAGS="-std=gnu++11" \ ./build-android.sh \ diff --git a/Build_iOS/configure.sh b/Build_iOS/configure.sh index 722128e3d9..7045be58fc 100755 --- a/Build_iOS/configure.sh +++ b/Build_iOS/configure.sh @@ -96,7 +96,7 @@ if [ ! -e $ABS_PATH/boost.framework ] && [ ! -d $ABS_PATH/boost ]; then git clone https://github.com/faithfracture/Apple-Boost-BuildScript ${ABS_PATH}/Apple-Boost-BuildScript fi pushd ${ABS_PATH}/Apple-Boost-BuildScript - git checkout 1ebe6e7654d9c9e1792076ee3827a45d5d2f34c5 + git checkout 8c42427b4ebc7865eb99b0a0b9607888af2c6abc BOOST_LIBS="thread chrono filesystem regex system random" ./boost.sh -ios -tvos --boost-version $BOOST_VERSION popd mv ${ABS_PATH}/Apple-Boost-BuildScript/build/boost/${BOOST_VERSION}/ios/framework/boost.framework ${ABS_PATH} @@ -112,7 +112,7 @@ if [ ! -e ${ABS_PATH}/openssl/lib/libcrypto.a ]; then git clone --depth=1 https://github.com/x2on/OpenSSL-for-iPhone.git ${ABS_PATH}/OpenSSL-for-iPhone fi pushd ${ABS_PATH}/OpenSSL-for-iPhone - git checkout 10019638e80e8a8a5fc19642a840d8a69fac7349 + git checkout 6c665e2a15ba7e834875eecaf4eb93c11605dd9a ./build-libssl.sh --version=${OPENSSL_VERSION} popd mkdir -p ${ABS_PATH}/openssl/lib diff --git a/Release/tests/functional/websockets/client/authentication_tests.cpp b/Release/tests/functional/websockets/client/authentication_tests.cpp index 2953686042..a35949c9f3 100644 --- a/Release/tests/functional/websockets/client/authentication_tests.cpp +++ b/Release/tests/functional/websockets/client/authentication_tests.cpp @@ -128,83 +128,6 @@ SUITE(authentication_tests) } } -// These tests are specific to our websocketpp based implementation. -#if !defined(__cplusplus_winrt) - - void sni_test_impl(websocket_client & client) - { - try - { - client.connect(U("wss://swordsoftruth.com")).wait(); - - // Should never be reached. - VERIFY_IS_TRUE(false); - } - catch (const websocket_exception& e) - { - if (is_timeout(e.what())) - { - // Since this test depends on an outside server sometimes it sporadically can fail due to timeouts - // especially on our build machines. - return; - } - - // This test just covers establishing the TLS connection and verifying - // the server certificate, expect it to return an unexpected HTTP status code. - if (e.error_code().value() == 20) - { - return; - } - throw; - } - } - - // Test specifically for server SignalR team hit interesting cases with. - TEST(sni_with_older_server_test) - { - websocket_client client; - sni_test_impl(client); - } - - // WinRT doesn't expose option for disabling. - // No stable server is available to reliably test this. - // The configuration below relies on a timeout in the success case. - TEST(disable_sni, "Ignore", "Manual") - { - websocket_client_config config; - config.set_server_name("expired.badssl.com"); - config.disable_sni(); - websocket_client client(config); - - try - { - client.connect(U("wss://badssl.com")).wait(); - - // Should never be reached. - VERIFY_IS_TRUE(false); - } - catch (const websocket_exception& e) - { - // Should fail for a reason different than invalid HTTP status. - if (e.error_code().value() != 20) - { - return; - } - throw; - } - } - - // Winrt doesn't allow explicitly setting server host for SNI. - TEST(sni_explicit_hostname) - { - websocket_client_config config; - const auto& name = utf8string("swordsoftruth.com"); - config.set_server_name(name); - VERIFY_ARE_EQUAL(name, config.server_name()); - websocket_client client(config); - sni_test_impl(client); - } - void handshake_error_test_impl(const ::utility::string_t& host) { websocket_client client; @@ -231,8 +154,6 @@ SUITE(authentication_tests) TEST(cert_expired) { handshake_error_test_impl(U("wss://expired.badssl.com/")); } -#endif - } // SUITE(authentication_tests) } // namespace client diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a5e397d0e8..55f7683b3a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -124,10 +124,9 @@ jobs: export NCPU=2 ../configure.sh --ndk /usr/local/lib/android/sdk/ndk-bundle displayName: 'Build for Android' - # Homebrew is disabled for now because it apparently is deploying a Boost version that the version of xcode deployed in Pipelines cannot build. # - job: MacOS_Homebrew # pool: - # vmImage: 'macOS-10.14' + # vmImage: 'macOS-latest' # steps: # - script: brew install boost openssl ninja # displayName: Brew install dependencies @@ -168,47 +167,45 @@ jobs: # cd build.release.static # ninja # displayName: 'Run ninja, release static' - - job: MacOS_Vcpkg - pool: - vmImage: 'macOS-10.14' - steps: - - script: | - brew install gcc ninja - ./vcpkg/bootstrap-vcpkg.sh - ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg - displayName: Vcpkg install dependencies - - script: | - mkdir build.debug - mkdir build.release - displayName: Make Build Directories - - task: CMake@1 - inputs: - workingDirectory: 'build.debug' - cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' - - task: CMake@1 - inputs: - workingDirectory: 'build.release' - cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' - - script: | - cd build.debug - ninja - displayName: 'Run ninja debug' - - script: | - cd build.debug/Release/Binaries - ./test_runner *test.dylib - displayName: 'Run Tests debug' - - script: | - cd build.release - ninja - displayName: 'Run ninja, release' - - script: | - cd build.release/Release/Binaries - ./test_runner *test.dylib - displayName: 'Run tests, release' - # iOS is disabled for now because the dependency Apple-Boost-BuildScript appears to be broken with the version of XCode in use in Pipelines. + # - job: MacOS_Vcpkg + # pool: + # vmImage: 'macOS-latest' + # steps: + # - script: | + # ./vcpkg/bootstrap-vcpkg.sh + # ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg + # displayName: Vcpkg install dependencies + # - script: | + # mkdir build.debug + # mkdir build.release + # displayName: Make Build Directories + # - task: CMake@1 + # inputs: + # workingDirectory: 'build.debug' + # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + # - task: CMake@1 + # inputs: + # workingDirectory: 'build.release' + # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + # - script: | + # cd build.debug + # ninja + # displayName: 'Run ninja debug' + # - script: | + # cd build.debug/Release/Binaries + # ./test_runner *test.dylib + # displayName: 'Run Tests debug' + # - script: | + # cd build.release + # ninja + # displayName: 'Run ninja, release' + # - script: | + # cd build.release/Release/Binaries + # ./test_runner *test.dylib + # displayName: 'Run tests, release' # - job: MacOS_iOS # pool: - # vmImage: 'macOS-10.14' + # vmImage: 'macOS-latest' # steps: # - script: | # cd Build_iOS diff --git a/vcpkg b/vcpkg index ee0bfad1cf..43fa3e60cf 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit ee0bfad1cfa11e048823e2d02d9f619db7d94a3f +Subproject commit 43fa3e60cfb96fa42940d234b011514c8be92256 From e7c6b08b88888444bc8ba1e8d32897cb28eba6f2 Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Thu, 19 Dec 2019 00:13:30 +0000 Subject: [PATCH 29/80] Fix test case broken by commit f4c863bcf55b2df25aa087377d7ec1978ae0af29 (#1288) --- Release/tests/functional/http/client/client_construction.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/tests/functional/http/client/client_construction.cpp b/Release/tests/functional/http/client/client_construction.cpp index f5d20b8379..9d5216c202 100644 --- a/Release/tests/functional/http/client/client_construction.cpp +++ b/Release/tests/functional/http/client/client_construction.cpp @@ -183,7 +183,7 @@ SUITE(client_construction) config.set_ssl_context_callback([&called](boost::asio::ssl::context& ctx) { called = true; }); - http_client client("https://www.google.com/", config); + http_client client(U("https://www.google.com/"), config); try { @@ -204,7 +204,7 @@ SUITE(client_construction) config.set_ssl_context_callback([&called](boost::asio::ssl::context& ctx) { called = true; }); - http_client client("http://www.google.com/", config); + http_client client(U("http://www.google.com/"), config); try { From 53dcf8b34f8879ed3bd8f9ed6d489b730b156335 Mon Sep 17 00:00:00 2001 From: Jonathan Saylor Date: Wed, 18 Dec 2019 16:14:04 -0800 Subject: [PATCH 30/80] Added comparison overrides to utility::datetime (#1276) I was trying to compare timestamps and noticed that the code doesn't support this so std::max and std::min don't work with datetime timestamps. I've added less/greater/less-or-equal/greater-or-equal operators. --- Release/include/cpprest/asyncrt_utils.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 4166eb8c48..1b54f1634a 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -628,6 +628,14 @@ class datetime bool operator==(datetime dt) const { return m_interval == dt.m_interval; } bool operator!=(const datetime& dt) const { return !(*this == dt); } + + bool operator>(const datetime& dt) const { return this->m_interval > dt.m_interval; } + + bool operator<(const datetime& dt) const { return this->m_interval < dt.m_interval; } + + bool operator>=(const datetime& dt) const { return this->m_interval >= dt.m_interval; } + + bool operator<=(const datetime& dt) const { return this->m_interval <= dt.m_interval; } static interval_type from_milliseconds(unsigned int milliseconds) { return milliseconds * _msTicks; } From 96e7d20e398b629de2935f9ac32cfa2780cd0b0b Mon Sep 17 00:00:00 2001 From: Gavin Halliday Date: Thu, 19 Dec 2019 21:10:21 +0000 Subject: [PATCH 31/80] Fix various warnings reported by gcc 9.3, and possibly earlier versions (#1289) Signed-off-by: Gavin Halliday --- Release/include/cpprest/details/SafeInt3.hpp | 2 ++ Release/include/cpprest/json.h | 2 +- Release/src/json/json.cpp | 2 +- Release/tests/common/TestRunner/test_runner.cpp | 5 ++--- .../tests/functional/http/client/compression_tests.cpp | 8 ++++---- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Release/include/cpprest/details/SafeInt3.hpp b/Release/include/cpprest/details/SafeInt3.hpp index 0a9dbdd76a..950ac80172 100644 --- a/Release/include/cpprest/details/SafeInt3.hpp +++ b/Release/include/cpprest/details/SafeInt3.hpp @@ -6022,6 +6022,8 @@ class SafeInt m_int = (T)(b ? 1 : 0); } + constexpr SafeInt(const SafeInt& u) SAFEINT_CPP_THROW = default; + template SafeInt(const SafeInt& u) SAFEINT_CPP_THROW { diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index 4095be50ea..4549d1017c 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -918,7 +918,7 @@ class array msl::safeint3::SafeInt nMinSize(index); nMinSize += 1; msl::safeint3::SafeInt nlastSize(m_elements.size()); - if (nlastSize < nMinSize) m_elements.resize(nMinSize); + if (nlastSize < nMinSize) m_elements.resize((size_type)nMinSize); return m_elements[index]; } diff --git a/Release/src/json/json.cpp b/Release/src/json/json.cpp index 7614866acc..f1f0865d87 100644 --- a/Release/src/json/json.cpp +++ b/Release/src/json/json.cpp @@ -288,7 +288,7 @@ bool web::json::number::is_int32() const case signed_type: return m_intval >= (std::numeric_limits::min)() && m_intval <= (std::numeric_limits::max)(); - case unsigned_type: return m_uintval <= (std::numeric_limits::max)(); + case unsigned_type: return m_uintval <= (uint32_t)(std::numeric_limits::max)(); case double_type: default: return false; } diff --git a/Release/tests/common/TestRunner/test_runner.cpp b/Release/tests/common/TestRunner/test_runner.cpp index 9a356a9b0f..4913699d3d 100644 --- a/Release/tests/common/TestRunner/test_runner.cpp +++ b/Release/tests/common/TestRunner/test_runner.cpp @@ -557,8 +557,8 @@ int main(int argc, char* argv[]) breakOnError = true; } - // Determine if list or listProperties. - bool listOption = false, listPropertiesOption = false; + // The list_test_options() function determines if list or listProperties. + bool listOption = false; if (UnitTest::GlobalSettings::Has("list")) { listOption = true; @@ -566,7 +566,6 @@ int main(int argc, char* argv[]) if (UnitTest::GlobalSettings::Has("listproperties")) { listOption = true; - listPropertiesOption = true; } #ifdef _WIN32 if (UnitTest::GlobalSettings::Has("detectleaks")) diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp index 1ccb740fab..dd6e49f3ce 100644 --- a/Release/tests/functional/http/client/compression_tests.cpp +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -206,7 +206,7 @@ SUITE(compression_tests) std::vector cmp_buffer(buffer_size); size_t cmpsize = buffer_size; size_t csize = 0; - operation_result r = {0}; + operation_result r = {}; operation_hint hint = operation_hint::has_more; for (i = 0; i < buffer_size || csize == cmpsize || !r.done; i += r.input_bytes_processed) { @@ -361,9 +361,9 @@ SUITE(compression_tests) if (!cfactory) { auto size = tuples[i][0]; - compress_and_decompress(utility::details::make_unique(tuples[i][0]), - utility::details::make_unique(tuples[i][0]), - tuples[i][0], + compress_and_decompress(utility::details::make_unique(size), + utility::details::make_unique(size), + size, tuples[i][1], !!j); } From 40dad5c67409bd41e7b6a9cd8bbc27c05d4e27c3 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 19 Feb 2020 16:16:23 -0800 Subject: [PATCH 32/80] Update vcpkg and boost on Android (#1334) * websocketpp appears a lost cause, disable websockets for Android Also fixes #1333 as a drive-by :) --- Build_android/configure.sh | 26 +-- .../functional/http/client/outside_tests.cpp | 71 -------- Release/tests/functional/json/CMakeLists.txt | 2 - .../functional/json/construction_tests.cpp | 3 +- Release/tests/functional/json/fuzz_tests.cpp | 4 +- .../tests/functional/json/iterator_tests.cpp | 4 +- .../functional/json/json_numbers_tests.cpp | 4 +- Release/tests/functional/json/json_tests.h | 25 --- .../json/negative_parsing_tests.cpp | 3 +- .../tests/functional/json/parsing_tests.cpp | 172 +++++++++++++++++- Release/tests/functional/json/stdafx.cpp | 14 -- Release/tests/functional/json/stdafx.h | 19 -- .../json/to_as_and_operators_tests.cpp | 3 +- azure-devops/build-windows.yml | 2 + azure-pipelines.yml | 24 ++- vcpkg | 2 +- 16 files changed, 213 insertions(+), 165 deletions(-) delete mode 100644 Release/tests/functional/json/json_tests.h delete mode 100644 Release/tests/functional/json/stdafx.cpp delete mode 100644 Release/tests/functional/json/stdafx.h diff --git a/Build_android/configure.sh b/Build_android/configure.sh index ea29c38b29..59b35659ae 100755 --- a/Build_android/configure.sh +++ b/Build_android/configure.sh @@ -25,7 +25,7 @@ DO_OPENSSL=1 DO_CMAKE=1 DO_CPPRESTSDK=1 -BOOSTVER=1.69.0 +BOOSTVER=1.70.0 OPENSSLVER=1.1.0j CMAKEVER=3.14.0 @@ -54,8 +54,8 @@ do DO_OPENSSL=0 ;; "--skip-cmake") - DO_CMAKE=0 - ;; + DO_CMAKE=0 + ;; "--skip-cpprestsdk") DO_CPPRESTSDK=0 ;; @@ -104,10 +104,10 @@ NDK_DIR=`cd "${ANDROID_NDK}" && pwd` SRC_DIR=`pwd` if [ -z "$NCPU" ]; then - NCPU=4 - if uname -s | grep -i "linux" > /dev/null ; then - NCPU=`cat /proc/cpuinfo | grep -c -i processor` - fi + NCPU=4 + if uname -s | grep -i "linux" > /dev/null ; then + NCPU=`cat /proc/cpuinfo | grep -c -i processor` + fi fi # ----------------------- @@ -151,11 +151,12 @@ if [ "${DO_OPENSSL}" == "1" ]; then ( # ----- # Uses the build script from Moritz Wundke (formerly MysticTreeGames) # https://github.com/moritz-wundke/Boost-for-Android +# (plus the patch https://github.com/o01eg/Boost-for-Android/tree/ndk-bump-21) if [ "${DO_BOOST}" == "1" ]; then ( - if [ ! -d 'Boost-for-Android' ]; then git clone https://github.com/moritz-wundke/Boost-for-Android; fi + if [ ! -d 'Boost-for-Android' ]; then git clone https://github.com/o01eg/Boost-for-Android/; fi cd Boost-for-Android - git checkout 245ea53385a55742a9ab08a8bd32c6a2dc0bbea4 + git checkout 7626dd6f7cab7866dce20e685d4a1b11194366a7 PATH="$PATH:$NDK_DIR" \ CXXFLAGS="-std=gnu++11" \ ./build-android.sh \ @@ -186,16 +187,17 @@ if [ "${DO_CMAKE}" == "1" ]; then ( if [ "${DO_CPPRESTSDK}" == "1" ]; then # Use the builtin CMake toolchain configuration that comes with the NDK function build_cpprestsdk { ( - rm -rf $1 + rm -rf $1 ./cmake-${CMAKEVER}/bin/cmake \ -DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}/build/cmake/android.toolchain.cmake" \ -DANDROID_NDK="${ANDROID_NDK}" \ -DANDROID_TOOLCHAIN=clang \ -DANDROID_ABI=$2 \ -DBOOST_VERSION="${BOOSTVER}" \ + -DCPPREST_EXCLUDE_WEBSOCKETS=ON \ -DCMAKE_BUILD_TYPE=$3 \ - -S "${DIR}/.." \ - -B $1 + -S "${DIR}/.." \ + -B $1 make -j $NCPU -C $1 ) } diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index 05bb306e7a..1b3f64a4ca 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -290,77 +290,6 @@ SUITE(outside_tests) }); } #endif // !defined(__cplusplus_winrt) - - TEST_FIXTURE(uri_address, outside_ssl_json) - { - // Create URI for: - // https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=UUF1hMUVwlrvlVMjUGOZExgg&key=AIzaSyAviHxf_y0SzNoAq3iKqvWVE4KQ0yylsnk - uri_builder playlistUri(U("https://www.googleapis.com/youtube/v3/playlistItems?")); - playlistUri.append_query(U("part"), U("snippet")); - playlistUri.append_query(U("playlistId"), U("UUF1hMUVwlrvlVMjUGOZExgg")); - playlistUri.append_query(U("key"), U("AIzaSyAviHxf_y0SzNoAq3iKqvWVE4KQ0yylsnk")); - - // Send request - web::http::client::http_client playlistClient(playlistUri.to_uri()); - - handle_timeout([&] { - // Retry up to 4 times. - for (int i = 0; i < 4; ++i) - { - try - { - playlistClient.request(methods::GET) - .then([=](http_response playlistResponse) -> pplx::task { - return playlistResponse.extract_json(); - }) - .then([=](json::value v) { - int count = 0; - auto& obj = v.as_object(); - - VERIFY_ARE_NOT_EQUAL(obj.find(U("pageInfo")), obj.end()); - VERIFY_ARE_NOT_EQUAL(obj.find(U("items")), obj.end()); - - auto& items = obj[U("items")]; - - for (auto iter = items.as_array().cbegin(); iter != items.as_array().cend(); ++iter) - { - const auto& item = *iter; - auto iSnippet = item.as_object().find(U("snippet")); - if (iSnippet == item.as_object().end()) - { - throw std::runtime_error("snippet key not found"); - } - auto iTitle = iSnippet->second.as_object().find(U("title")); - if (iTitle == iSnippet->second.as_object().end()) - { - throw std::runtime_error("title key not found"); - } - auto name = iTitle->second.serialize(); - count++; - } - VERIFY_ARE_EQUAL(3, count); // Update this accordingly, if the number of items changes - }) - .wait(); - break; - } - catch (web::http::http_exception const& e) - { -#if defined(_MSC_VER) && !defined(__cplusplus_winrt) - if (e.error_code().value() != API_QUERY_DATA_AVAILABLE || i == 3) - { - // If we didn't get a "connection broken" error (or we are on the last retry), rethrow it - throw; - } -#else - (void)e; - throw; -#endif - os_utilities::sleep(1000); - } - } - }); - } - } // SUITE(outside_tests) } // namespace client diff --git a/Release/tests/functional/json/CMakeLists.txt b/Release/tests/functional/json/CMakeLists.txt index fb10c885f7..25c90f29c1 100644 --- a/Release/tests/functional/json/CMakeLists.txt +++ b/Release/tests/functional/json/CMakeLists.txt @@ -15,5 +15,3 @@ if(UNIX AND NOT APPLE) cpprest_find_boost() target_link_libraries(json_test PRIVATE cpprestsdk_boost_internal) endif() - -configure_pch(json_test stdafx.h stdafx.cpp) diff --git a/Release/tests/functional/json/construction_tests.cpp b/Release/tests/functional/json/construction_tests.cpp index ee5d9cbbce..111b1454e1 100644 --- a/Release/tests/functional/json/construction_tests.cpp +++ b/Release/tests/functional/json/construction_tests.cpp @@ -11,7 +11,8 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ -#include "stdafx.h" +#include "cpprest/json.h" +#include "unittestpp.h" using namespace web; using namespace utility; diff --git a/Release/tests/functional/json/fuzz_tests.cpp b/Release/tests/functional/json/fuzz_tests.cpp index a925bf9dfb..80b9a81b04 100644 --- a/Release/tests/functional/json/fuzz_tests.cpp +++ b/Release/tests/functional/json/fuzz_tests.cpp @@ -10,10 +10,10 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ -#include "stdafx.h" - +#include "cpprest/json.h" #include "cpprest/containerstream.h" #include "cpprest/filestream.h" +#include "unittestpp.h" using namespace web; diff --git a/Release/tests/functional/json/iterator_tests.cpp b/Release/tests/functional/json/iterator_tests.cpp index e6c8e60ec3..0e72709aa3 100644 --- a/Release/tests/functional/json/iterator_tests.cpp +++ b/Release/tests/functional/json/iterator_tests.cpp @@ -11,8 +11,8 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ -#include "stdafx.h" - +#include "cpprest/json.h" +#include "unittestpp.h" #include using namespace web; diff --git a/Release/tests/functional/json/json_numbers_tests.cpp b/Release/tests/functional/json/json_numbers_tests.cpp index 538d44d367..5fa90267ff 100644 --- a/Release/tests/functional/json/json_numbers_tests.cpp +++ b/Release/tests/functional/json/json_numbers_tests.cpp @@ -11,8 +11,8 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ -#include "stdafx.h" - +#include "cpprest/json.h" +#include "unittestpp.h" #include #include diff --git a/Release/tests/functional/json/json_tests.h b/Release/tests/functional/json/json_tests.h deleted file mode 100644 index 2d0bac62d1..0000000000 --- a/Release/tests/functional/json/json_tests.h +++ /dev/null @@ -1,25 +0,0 @@ -/*** - * Copyright (C) Microsoft. All rights reserved. - * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. - * - * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - * - * json_tests.h - * - * Common utilities and helper functions for JSON tests. - * - * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - ****/ - -#include "cpprest/json.h" -#include "unittestpp.h" - -namespace tests -{ -namespace functional -{ -namespace json_tests -{ -} -} // namespace functional -} // namespace tests diff --git a/Release/tests/functional/json/negative_parsing_tests.cpp b/Release/tests/functional/json/negative_parsing_tests.cpp index 33a678ab16..6c2ee9375f 100644 --- a/Release/tests/functional/json/negative_parsing_tests.cpp +++ b/Release/tests/functional/json/negative_parsing_tests.cpp @@ -10,7 +10,8 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ -#include "stdafx.h" +#include "cpprest/json.h" +#include "unittestpp.h" using namespace web; using namespace utility; diff --git a/Release/tests/functional/json/parsing_tests.cpp b/Release/tests/functional/json/parsing_tests.cpp index cf5a261bf0..2a4db09538 100644 --- a/Release/tests/functional/json/parsing_tests.cpp +++ b/Release/tests/functional/json/parsing_tests.cpp @@ -9,8 +9,8 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ -#include "stdafx.h" - +#include "cpprest/json.h" +#include "unittestpp.h" #include #include @@ -26,6 +26,144 @@ using namespace web; using namespace utility; using namespace utility::conversions; +static utility::string_t youtubeJson = _XPLATSTR( +R"delimeter({ + "kind": "youtube#playlistItemListResponse", + "etag": "\"Fznwjl6JEQdo1MGvHOGaz_YanRU/ranGcWzseanYs9xZ0NXAq24qK-w\"", + "pageInfo": { + "totalResults": 3, + "resultsPerPage": 5 + }, + "items": [ + { + "kind": "youtube#playlistItem", + "etag": "\"Fznwjl6JEQdo1MGvHOGaz_YanRU/phfRXORDKFrYjeJGWbI8MbIk08A\"", + "id": "VVVGMWhNVVZ3bHJ2bFZNalVHT1pFeGdnLm12RERIeEJyd1U4", + "snippet": { + "publishedAt": "2013-05-24T22:03:10.000Z", + "channelId": "UCF1hMUVwlrvlVMjUGOZExgg", + "title": "C++ REST SDK (\"Casablanca\")", + "description": "This library is a Microsoft effort to support cloud-based client-server communication in native code using a modern asynchronous C++ API design.", + "thumbnails": { + "default": { + "url": "https://i.ytimg.com/vi/mvDDHxBrwU8/default.jpg", + "width": 120, + "height": 90 + }, + "medium": { + "url": "https://i.ytimg.com/vi/mvDDHxBrwU8/mqdefault.jpg", + "width": 320, + "height": 180 + }, + "high": { + "url": "https://i.ytimg.com/vi/mvDDHxBrwU8/hqdefault.jpg", + "width": 480, + "height": 360 + }, + "standard": { + "url": "https://i.ytimg.com/vi/mvDDHxBrwU8/sddefault.jpg", + "width": 640, + "height": 480 + }, + "maxres": { + "url": "https://i.ytimg.com/vi/mvDDHxBrwU8/maxresdefault.jpg", + "width": 1280, + "height": 720 + } + }, + "channelTitle": "casablancacore", + "playlistId": "UUF1hMUVwlrvlVMjUGOZExgg", + "position": 0, + "resourceId": { + "kind": "youtube#video", + "videoId": "mvDDHxBrwU8" + } + } + }, + { + "kind": "youtube#playlistItem", + "etag": "\"Fznwjl6JEQdo1MGvHOGaz_YanRU/J65jYO0AIlbIqd4JpVigajlhVnE\"", + "id": "VVVGMWhNVVZ3bHJ2bFZNalVHT1pFeGdnLmlFVU9fdDhFYW5r", + "snippet": { + "publishedAt": "2013-05-07T18:47:24.000Z", + "channelId": "UCF1hMUVwlrvlVMjUGOZExgg", + "title": "C++ REST SDK", + "description": "A brief introduction to the C++ REST SDK. This video goes over high level concepts and features of the library. \n\nFor more information visit: http://casablanca.codeplex.com\nFor more information on PPL tasks visit: http://msdn.microsoft.com/en-us/library/dd492418.aspx", + "thumbnails": { + "default": { + "url": "https://i.ytimg.com/vi/iEUO_t8Eank/default.jpg", + "width": 120, + "height": 90 + }, + "medium": { + "url": "https://i.ytimg.com/vi/iEUO_t8Eank/mqdefault.jpg", + "width": 320, + "height": 180 + }, + "high": { + "url": "https://i.ytimg.com/vi/iEUO_t8Eank/hqdefault.jpg", + "width": 480, + "height": 360 + }, + "standard": { + "url": "https://i.ytimg.com/vi/iEUO_t8Eank/sddefault.jpg", + "width": 640, + "height": 480 + } + }, + "channelTitle": "casablancacore", + "playlistId": "UUF1hMUVwlrvlVMjUGOZExgg", + "position": 1, + "resourceId": { + "kind": "youtube#video", + "videoId": "iEUO_t8Eank" + } + } + }, + { + "kind": "youtube#playlistItem", + "etag": "\"Fznwjl6JEQdo1MGvHOGaz_YanRU/XMpuK2N4-LOhDWtgCG8nBw7eNl8\"", + "id": "VVVGMWhNVVZ3bHJ2bFZNalVHT1pFeGdnLk41cnlJN3U5RVFB", + "snippet": { + "publishedAt": "2013-05-02T21:24:56.000Z", + "channelId": "UCF1hMUVwlrvlVMjUGOZExgg", + "title": "bunny", + "description": "", + "thumbnails": { + "default": { + "url": "https://i.ytimg.com/vi/N5ryI7u9EQA/default.jpg", + "width": 120, + "height": 90 + }, + "medium": { + "url": "https://i.ytimg.com/vi/N5ryI7u9EQA/mqdefault.jpg", + "width": 320, + "height": 180 + }, + "high": { + "url": "https://i.ytimg.com/vi/N5ryI7u9EQA/hqdefault.jpg", + "width": 480, + "height": 360 + }, + "standard": { + "url": "https://i.ytimg.com/vi/N5ryI7u9EQA/sddefault.jpg", + "width": 640, + "height": 480 + } + }, + "channelTitle": "casablancacore", + "playlistId": "UUF1hMUVwlrvlVMjUGOZExgg", + "position": 2, + "resourceId": { + "kind": "youtube#video", + "videoId": "N5ryI7u9EQA" + } + } + } + ] +})delimeter" +); + namespace tests { namespace functional @@ -762,6 +900,36 @@ SUITE(parsing_tests) #endif } + TEST(youtube_api) + { + auto v = json::value::parse(youtubeJson); + int count = 0; + auto& obj = v.as_object(); + + VERIFY_ARE_NOT_EQUAL(obj.find(U("pageInfo")), obj.end()); + VERIFY_ARE_NOT_EQUAL(obj.find(U("items")), obj.end()); + + auto& items = obj[U("items")]; + + for (auto iter = items.as_array().cbegin(); iter != items.as_array().cend(); ++iter) + { + const auto& item = *iter; + auto iSnippet = item.as_object().find(U("snippet")); + if (iSnippet == item.as_object().end()) + { + throw std::runtime_error("snippet key not found"); + } + auto iTitle = iSnippet->second.as_object().find(U("title")); + if (iTitle == iSnippet->second.as_object().end()) + { + throw std::runtime_error("title key not found"); + } + auto name = iTitle->second.serialize(); + count++; + } + VERIFY_ARE_EQUAL(3, count); // Update this accordingly, if the number of items changes + } + } // SUITE(parsing_tests) } // namespace json_tests diff --git a/Release/tests/functional/json/stdafx.cpp b/Release/tests/functional/json/stdafx.cpp deleted file mode 100644 index 48b9655134..0000000000 --- a/Release/tests/functional/json/stdafx.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/*** - * Copyright (C) Microsoft. All rights reserved. - * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. - * - * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - **/ -// stdafx.cpp : -// Include the standard header and generate the precompiled header. - -#include "stdafx.h" - -#if WIN32 -__declspec(dllexport) int json_test_generate_lib = 0; -#endif diff --git a/Release/tests/functional/json/stdafx.h b/Release/tests/functional/json/stdafx.h deleted file mode 100644 index bb43264b61..0000000000 --- a/Release/tests/functional/json/stdafx.h +++ /dev/null @@ -1,19 +0,0 @@ -/*** - * Copyright (C) Microsoft. All rights reserved. - * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. - * - * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ - * - * stdafx.h - * - * Pre-compiled headers - * - * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - ****/ - -#pragma once - -#include "unittestpp.h" -#include - -#include "json_tests.h" diff --git a/Release/tests/functional/json/to_as_and_operators_tests.cpp b/Release/tests/functional/json/to_as_and_operators_tests.cpp index 6103adf6a4..cbf2a92e04 100644 --- a/Release/tests/functional/json/to_as_and_operators_tests.cpp +++ b/Release/tests/functional/json/to_as_and_operators_tests.cpp @@ -9,7 +9,8 @@ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ****/ -#include "stdafx.h" +#include "cpprest/json.h" +#include "unittestpp.h" using namespace web; using namespace utility; diff --git a/azure-devops/build-windows.yml b/azure-devops/build-windows.yml index 45ea392a82..2a5de3c509 100644 --- a/azure-devops/build-windows.yml +++ b/azure-devops/build-windows.yml @@ -11,6 +11,8 @@ jobs: vcpkgLocation: '$(Build.SourcesDirectory)/vcpkg' vcpkgResponseFile: $(Build.SourcesDirectory)/azure-devops/vcpkg-windows.txt steps: + - script: git submodule update --init vcpkg + displayName: Checkout vcpkg submodule - task: CacheBeta@0 displayName: Cache vcpkg inputs: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 55f7683b3a..9a03666ec8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -21,20 +21,23 @@ jobs: name: 'Windows_VS2017_x64' targetPlatform: x64 image: 'vs2017-win2016' - - template: azure-devops/build-windows.yml - parameters: - name: 'Windows_VS2015_x86' - targetPlatform: x86 - image: 'vs2015-win2012r2' - - template: azure-devops/build-windows.yml - parameters: - name: 'Windows_VS2015_x64' - targetPlatform: x64 - image: 'vs2015-win2012r2' + # VS2015 is disabled for now pending https://github.com/microsoft/vcpkg/pull/10126 + # - template: azure-devops/build-windows.yml + # parameters: + # name: 'Windows_VS2015_x86' + # targetPlatform: x86 + # image: 'vs2015-win2012r2' + # - template: azure-devops/build-windows.yml + # parameters: + # name: 'Windows_VS2015_x64' + # targetPlatform: x64 + # image: 'vs2015-win2012r2' - job: Windows_VS2019_UWP pool: vmImage: 'windows-latest' steps: + - script: git submodule update --init vcpkg + displayName: Checkout vcpkg submodule - script: .\vcpkg\bootstrap-vcpkg.bat displayName: Bootstrap vcpkg - script: .\vcpkg\vcpkg.exe install zlib --triplet x64-uwp --vcpkg-root .\vcpkg @@ -83,6 +86,7 @@ jobs: sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y sudo apt -y update sudo apt install g++-9 ninja-build -y + git submodule update --init vcpkg ./vcpkg/bootstrap-vcpkg.sh ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg displayName: Vcpkg install dependencies diff --git a/vcpkg b/vcpkg index 43fa3e60cf..1be75a28bf 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit 43fa3e60cfb96fa42940d234b011514c8be92256 +Subproject commit 1be75a28bfce2084bb0b59ec92a6853f13d7be66 From feb0755637d28bbfb7ded52a5bf1eb4f76ec057f Mon Sep 17 00:00:00 2001 From: Gianfranco Costamagna Date: Thu, 20 Feb 2020 01:38:05 +0100 Subject: [PATCH 33/80] Change default installation directory for cmake files to cmake/cpprestsdk (#1306) --- Release/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 000516e1be..953dd29665 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -19,7 +19,7 @@ set(WERROR ON CACHE BOOL "Treat Warnings as Errors.") set(CPPREST_EXCLUDE_WEBSOCKETS OFF CACHE BOOL "Exclude websockets functionality.") set(CPPREST_EXCLUDE_COMPRESSION OFF CACHE BOOL "Exclude compression functionality.") set(CPPREST_EXCLUDE_BROTLI ON CACHE BOOL "Exclude Brotli compression functionality.") -set(CPPREST_EXPORT_DIR cpprestsdk CACHE STRING "Directory to install CMake config files.") +set(CPPREST_EXPORT_DIR cmake/cpprestsdk CACHE STRING "Directory to install CMake config files.") set(CPPREST_INSTALL_HEADERS ON CACHE BOOL "Install header files.") set(CPPREST_INSTALL ON CACHE BOOL "Add install commands.") From a835bfac35339c77e31a5cce25100384d3631134 Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Thu, 20 Feb 2020 01:18:56 +0000 Subject: [PATCH 34/80] Use LC_ALL_MASK rather than LC_ALL when calling newlocale (#1330) Resolves #1329 as @jason-ha suggests --- Release/src/utilities/asyncrt_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index 5263c8d5d5..62cce9e8fb 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -124,7 +124,7 @@ scoped_c_thread_locale::xplat_locale scoped_c_thread_locale::c_locale() delete clocale; }; #else - *clocale = newlocale(LC_ALL, "C", nullptr); + *clocale = newlocale(LC_ALL_MASK, "C", nullptr); if (clocale == nullptr || *clocale == nullptr) { throw std::runtime_error("Unable to create 'C' locale."); From f43bf646dee96702db7ab3d74761a3a68489376a Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Thu, 20 Feb 2020 02:00:34 +0000 Subject: [PATCH 35/80] Add TCP_NODELAY to disable Nagle's algorithm in Boost.ASIO-based http_client (#1310) * Add TCP_NODELAY to disable Nagle's algorithm to avoid waiting for ACK for HTTP request headers before transmitting the request body, in order to significantly improve performance for requests with bodies (see #1201) * Also add TCP_NODELAY on the server-side, to disable Nagle's algorithm to avoid waiting for ACK for HTTP response headers before transmitting the response body (see #1201) --- Release/src/http/client/http_client_asio.cpp | 8 ++++++++ Release/src/http/listener/http_server_asio.cpp | 3 +++ 2 files changed, 11 insertions(+) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index a90ca6a7fa..ad4238afc8 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -330,6 +330,12 @@ class asio_connection void start_reuse() { m_is_reused = true; } + void enable_no_delay() + { + boost::asio::ip::tcp::no_delay option(true); + m_socket.set_option(option); + } + private: // Guards concurrent access to socket/ssl::stream. This is necessary // because timeouts and cancellation can touch the socket at the same time @@ -610,6 +616,7 @@ class asio_context final : public request_context, public std::enable_shared_fro if (!ec) { m_context->m_timer.reset(); + m_context->m_connection->enable_no_delay(); m_context->m_connection->async_write(m_request, boost::bind(&ssl_proxy_tunnel::handle_write_request, shared_from_this(), @@ -1006,6 +1013,7 @@ class asio_context final : public request_context, public std::enable_shared_fro m_timer.reset(); if (!ec) { + m_connection->enable_no_delay(); write_request(); } else if (ec.value() == boost::system::errc::operation_canceled || diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index f1d8c819c5..5b392012df 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -593,6 +593,9 @@ void hostport_listener::on_accept(std::unique_ptr socket, const // Handle successful accept if (!ec) { + boost::asio::ip::tcp::no_delay option(true); + socket->set_option(option); + auto conn = asio_server_connection::create(std::move(socket), m_p_server, this); m_connections.insert(conn.get()); From d29cfa1b7c35f7be40a1f7f91daf1cb88832a12c Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Wed, 19 Feb 2020 18:27:12 -0800 Subject: [PATCH 36/80] Turn VS2015 back on now that vcpkg is fixed. (#1335) --- azure-pipelines.yml | 21 ++++++++++----------- vcpkg | 2 +- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9a03666ec8..63684db53c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -21,17 +21,16 @@ jobs: name: 'Windows_VS2017_x64' targetPlatform: x64 image: 'vs2017-win2016' - # VS2015 is disabled for now pending https://github.com/microsoft/vcpkg/pull/10126 - # - template: azure-devops/build-windows.yml - # parameters: - # name: 'Windows_VS2015_x86' - # targetPlatform: x86 - # image: 'vs2015-win2012r2' - # - template: azure-devops/build-windows.yml - # parameters: - # name: 'Windows_VS2015_x64' - # targetPlatform: x64 - # image: 'vs2015-win2012r2' + - template: azure-devops/build-windows.yml + parameters: + name: 'Windows_VS2015_x86' + targetPlatform: x86 + image: 'vs2015-win2012r2' + - template: azure-devops/build-windows.yml + parameters: + name: 'Windows_VS2015_x64' + targetPlatform: x64 + image: 'vs2015-win2012r2' - job: Windows_VS2019_UWP pool: vmImage: 'windows-latest' diff --git a/vcpkg b/vcpkg index 1be75a28bf..ef60f1d9b9 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit 1be75a28bfce2084bb0b59ec92a6853f13d7be66 +Subproject commit ef60f1d9b97fab6fcc61651936196866bb6553d0 From 1f97f5465232177989bcaac6ea103f970cef0cc8 Mon Sep 17 00:00:00 2001 From: Arkady Shapkin Date: Fri, 21 Feb 2020 22:56:35 +0300 Subject: [PATCH 37/80] Enable HTTP compression support on all platforms (#1322) --- Release/src/http/common/http_compression.cpp | 11 +---------- .../functional/http/client/compression_tests.cpp | 14 +++++++++++++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Release/src/http/common/http_compression.cpp b/Release/src/http/common/http_compression.cpp index a65adc2468..1596ddca86 100644 --- a/Release/src/http/common/http_compression.cpp +++ b/Release/src/http/common/http_compression.cpp @@ -17,18 +17,9 @@ // it. CPPREST_EXCLUDE_BROTLI is set if we want to explicitly disable Brotli compression support. // CPPREST_EXCLUDE_WEBSOCKETS is a flag that now essentially means "no external dependencies". TODO: Rename -#if __APPLE__ -#include "TargetConditionals.h" -#if defined(TARGET_OS_MAC) -#if !defined(CPPREST_EXCLUDE_COMPRESSION) -#define CPPREST_HTTP_COMPRESSION -#endif // !defined(CPPREST_EXCLUDE_COMPRESSION) -#endif // defined(TARGET_OS_MAC) -#elif defined(_WIN32) && (!defined(WINAPI_FAMILY) || WINAPI_PARTITION_DESKTOP) #if !defined(CPPREST_EXCLUDE_WEBSOCKETS) && !defined(CPPREST_EXCLUDE_COMPRESSION) #define CPPREST_HTTP_COMPRESSION #endif // !defined(CPPREST_EXCLUDE_WEBSOCKETS) && !defined(CPPREST_EXCLUDE_COMPRESSION) -#endif #if defined(CPPREST_HTTP_COMPRESSION) #include @@ -277,7 +268,7 @@ class gzip_compressor : public zlib_compressor_base class gzip_decompressor : public zlib_decompressor_base { public: - gzip_decompressor() : zlib_decompressor_base(16) // gzip auto-detect + gzip_decompressor() : zlib_decompressor_base(31) // 15 is MAX_WBITS in zconf.h; add 16 for gzip { } }; diff --git a/Release/tests/functional/http/client/compression_tests.cpp b/Release/tests/functional/http/client/compression_tests.cpp index dd6e49f3ce..46ac3f42ac 100644 --- a/Release/tests/functional/http/client/compression_tests.cpp +++ b/Release/tests/functional/http/client/compression_tests.cpp @@ -376,19 +376,31 @@ SUITE(compression_tests) } } - TEST_FIXTURE(uri_address, compress_and_decompress) + TEST_FIXTURE(uri_address, compress_and_decompress_fake) { compress_test(nullptr, nullptr); // FAKE + } + + TEST_FIXTURE(uri_address, compress_and_decompress_gzip) + { if (builtin::algorithm::supported(builtin::algorithm::GZIP)) { compress_test(builtin::get_compress_factory(builtin::algorithm::GZIP), builtin::get_decompress_factory(builtin::algorithm::GZIP)); } + } + + TEST_FIXTURE(uri_address, compress_and_decompress_deflate) + { if (builtin::algorithm::supported(builtin::algorithm::DEFLATE)) { compress_test(builtin::get_compress_factory(builtin::algorithm::DEFLATE), builtin::get_decompress_factory(builtin::algorithm::DEFLATE)); } + } + + TEST_FIXTURE(uri_address, compress_and_decompress_brotli) + { if (builtin::algorithm::supported(builtin::algorithm::BROTLI)) { compress_test(builtin::get_compress_factory(builtin::algorithm::BROTLI), From 23e4c6197f3e62018baf20f4da7f1788b61fd077 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Sat, 22 Feb 2020 05:11:51 -0800 Subject: [PATCH 38/80] Add Ubuntu 18.04 testing. (#1340) --- azure-devops/build-ubuntu-apt.yml | 30 +++++++++++ azure-devops/build-ubuntu-vcpkg.yml | 45 ++++++++++++++++ azure-pipelines.yml | 81 ++++++----------------------- 3 files changed, 91 insertions(+), 65 deletions(-) create mode 100644 azure-devops/build-ubuntu-apt.yml create mode 100644 azure-devops/build-ubuntu-vcpkg.yml diff --git a/azure-devops/build-ubuntu-apt.yml b/azure-devops/build-ubuntu-apt.yml new file mode 100644 index 0000000000..ae3844edb3 --- /dev/null +++ b/azure-devops/build-ubuntu-apt.yml @@ -0,0 +1,30 @@ +parameters: + name: 'Ubuntu_1604_Apt' + image: 'Ubuntu 16.04' + +jobs: +- job: ${{ parameters.name }} + pool: + vmImage: ${{ parameters.image }} + steps: + - script: | + sudo apt -y remove php* + sudo apt install -y ppa-purge + sudo ppa-purge -y ppa:ondrej/php + unset BOOST_ROOT + sudo apt install -y libboost-atomic-dev libboost-thread-dev libboost-system-dev libboost-date-time-dev libboost-regex-dev libboost-filesystem-dev libboost-random-dev libboost-chrono-dev libboost-serialization-dev libwebsocketpp-dev openssl libssl-dev ninja-build + mkdir build.debug + cd build.debug + /usr/local/bin/cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug .. + cd .. + mkdir build.release + cd build.release + /usr/local/bin/cmake -G Ninja -DCMAKE_BUILD_TYPE=Release .. + cd .. + ninja -C build.debug + ninja -C build.release + cd build.debug/Release/Binaries + ./test_runner *test.so + cd ../../../build.release/Release/Binaries + ./test_runner *test.so + displayName: Run build diff --git a/azure-devops/build-ubuntu-vcpkg.yml b/azure-devops/build-ubuntu-vcpkg.yml new file mode 100644 index 0000000000..bc14ecd87b --- /dev/null +++ b/azure-devops/build-ubuntu-vcpkg.yml @@ -0,0 +1,45 @@ +parameters: + name: 'Ubuntu_1604_Vcpkg' + image: 'Ubuntu 16.04' + +jobs: +- job: ${{ parameters.name }} + pool: + vmImage: ${{ parameters.image }} + steps: + - script: | + sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y + sudo apt -y update + sudo apt install g++-9 ninja-build -y + git submodule update --init vcpkg + ./vcpkg/bootstrap-vcpkg.sh + ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg + displayName: Vcpkg install dependencies + - script: | + mkdir build.debug + mkdir build.release + displayName: Make Build Directories + - task: CMake@1 + inputs: + workingDirectory: 'build.debug' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - task: CMake@1 + inputs: + workingDirectory: 'build.release' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - script: | + cd build.debug + ninja + displayName: 'Run ninja debug' + - script: | + cd build.debug/Release/Binaries + ./test_runner *test.so + displayName: 'Run Tests debug' + - script: | + cd build.release + ninja + displayName: 'Run ninja, release' + - script: | + cd build.release/Release/Binaries + ./test_runner *test.so + displayName: 'Run tests, release' diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 63684db53c..a78d0ac829 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -52,71 +52,22 @@ jobs: solution: 'build.common/ALL_BUILD.vcxproj' maximumCpuCount: true platform: 'x64' - - job: Ubuntu_1604_Apt - pool: - vmImage: 'Ubuntu 16.04' - steps: - - script: | - sudo apt -y remove php* - sudo apt install -y ppa-purge - sudo ppa-purge -y ppa:ondrej/php - unset BOOST_ROOT - sudo apt install -y libboost-atomic-dev libboost-thread-dev libboost-system-dev libboost-date-time-dev libboost-regex-dev libboost-filesystem-dev libboost-random-dev libboost-chrono-dev libboost-serialization-dev libwebsocketpp-dev openssl libssl-dev ninja-build - mkdir build.debug - cd build.debug - /usr/local/bin/cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug .. - cd .. - mkdir build.release - cd build.release - /usr/local/bin/cmake -G Ninja -DCMAKE_BUILD_TYPE=Release .. - cd .. - ninja -C build.debug - ninja -C build.release - cd build.debug/Release/Binaries - ./test_runner *test.so - cd ../../../build.release/Release/Binaries - ./test_runner *test.so - displayName: Run build - - job: Ubuntu_1604_Vcpkg - pool: - vmImage: 'Ubuntu 16.04' - steps: - - script: | - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo apt -y update - sudo apt install g++-9 ninja-build -y - git submodule update --init vcpkg - ./vcpkg/bootstrap-vcpkg.sh - ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg - displayName: Vcpkg install dependencies - - script: | - mkdir build.debug - mkdir build.release - displayName: Make Build Directories - - task: CMake@1 - inputs: - workingDirectory: 'build.debug' - cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' - - task: CMake@1 - inputs: - workingDirectory: 'build.release' - cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' - - script: | - cd build.debug - ninja - displayName: 'Run ninja debug' - - script: | - cd build.debug/Release/Binaries - ./test_runner *test.so - displayName: 'Run Tests debug' - - script: | - cd build.release - ninja - displayName: 'Run ninja, release' - - script: | - cd build.release/Release/Binaries - ./test_runner *test.so - displayName: 'Run tests, release' + - template: azure-devops/build-ubuntu-apt.yml + parameters: + name: 'Ubuntu_1604_Apt' + image: 'Ubuntu 16.04' + - template: azure-devops/build-ubuntu-apt.yml + parameters: + name: 'Ubuntu_1804_Apt' + image: 'Ubuntu 18.04' + - template: azure-devops/build-ubuntu-vcpkg.yml + parameters: + name: 'Ubuntu_1604_Vcpkg' + image: 'Ubuntu 16.04' + - template: azure-devops/build-ubuntu-vcpkg.yml + parameters: + name: 'Ubuntu_1804_Vcpkg' + image: 'Ubuntu 18.04' - job: Android pool: vmImage: 'Ubuntu 16.04' From 43f6f3424fec6c5089340389e994ac193730cf37 Mon Sep 17 00:00:00 2001 From: VZ Date: Sun, 23 Feb 2020 18:38:17 +0100 Subject: [PATCH 39/80] Use C++11 synchronization classes under macOS too (#1342) There doesn't seem to be any reason to prefer using Boost libraries to standard C++ classes under macOS, so use the latter ones unconditionally on this platform too, just as it was already done for the other Unix systems. This notably avoids dependencies on the compiled Boost libraries, which don't have to be compiled before building C++ REST SDK any more. --- Release/include/pplx/pplxlinux.h | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/Release/include/pplx/pplxlinux.h b/Release/include/pplx/pplxlinux.h index 5aca316e45..ab0c5c9908 100644 --- a/Release/include/pplx/pplxlinux.h +++ b/Release/include/pplx/pplxlinux.h @@ -23,25 +23,14 @@ #include "pthread.h" #include -#if defined(__APPLE__) -#include -#include -#include -#else #include #include #include -#endif #include "pplx/pplxinterface.h" namespace pplx { -#if defined(__APPLE__) -namespace cpprest_synchronization = ::boost; -#else -namespace cpprest_synchronization = ::std; -#endif namespace details { namespace platform @@ -68,8 +57,8 @@ __declspec(noinline) inline static size_t CaptureCallstack(void**, size_t, size_ class event_impl { private: - cpprest_synchronization::mutex _lock; - cpprest_synchronization::condition_variable _condition; + std::mutex _lock; + std::condition_variable _condition; bool _signaled; public: @@ -79,20 +68,20 @@ class event_impl void set() { - cpprest_synchronization::lock_guard lock(_lock); + std::lock_guard lock(_lock); _signaled = true; _condition.notify_all(); } void reset() { - cpprest_synchronization::lock_guard lock(_lock); + std::lock_guard lock(_lock); _signaled = false; } unsigned int wait(unsigned int timeout) { - cpprest_synchronization::unique_lock lock(_lock); + std::unique_lock lock(_lock); if (timeout == event_impl::timeout_infinite) { _condition.wait(lock, [this]() -> bool { return _signaled; }); @@ -100,7 +89,7 @@ class event_impl } else { - cpprest_synchronization::chrono::milliseconds period(timeout); + std::chrono::milliseconds period(timeout); auto status = _condition.wait_for(lock, period, [this]() -> bool { return _signaled; }); _ASSERTE(status == _signaled); // Return 0 if the wait completed as a result of signaling the event. Otherwise, return timeout_infinite @@ -195,7 +184,7 @@ class recursive_lock_impl } private: - cpprest_synchronization::mutex _M_cs; + std::mutex _M_cs; std::atomic _M_owner; long _M_recursionCount; }; @@ -219,7 +208,7 @@ class linux_scheduler : public pplx::scheduler_interface /// /// A generic RAII wrapper for locks that implements the critical_section interface -/// cpprest_synchronization::lock_guard +/// std::lock_guard /// template class scoped_lock @@ -244,7 +233,7 @@ namespace extensibility { typedef ::pplx::details::event_impl event_t; -typedef cpprest_synchronization::mutex critical_section_t; +typedef std::mutex critical_section_t; typedef scoped_lock scoped_critical_section_t; typedef ::pplx::details::reader_writer_lock_impl reader_writer_lock_t; From 0886fcc138038152d7c9f54365b7976038364ab7 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Sun, 23 Feb 2020 10:51:19 -0800 Subject: [PATCH 40/80] Fix tcp::resolver data race in the asio backend and be defensive against empty results (#1339) * Move TCP resolver to asio_context rather than asio_client, as that type is not safe to touch from multiple threads. * Defend against empty responses from async_resolve. Co-authored-by: Jinming Hu jinming.hu@microsoft.com --- Release/src/http/client/http_client_asio.cpp | 34 +++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index ad4238afc8..215b03e58a 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -474,7 +474,6 @@ class asio_client final : public _http_client_communicator public: asio_client(http::uri&& address, http_client_config&& client_config) : _http_client_communicator(std::move(address), std::move(client_config)) - , m_resolver(crossplat::threadpool::shared_instance().service()) , m_pool(std::make_shared()) { } @@ -502,8 +501,6 @@ class asio_client final : public _http_client_communicator virtual pplx::task propagate(http_request request) override; - tcp::resolver m_resolver; - private: const std::shared_ptr m_pool; }; @@ -520,6 +517,7 @@ class asio_context final : public request_context, public std::enable_shared_fro , m_content_length(0) , m_needChunked(false) , m_timer(client->client_config().timeout()) + , m_resolver(crossplat::threadpool::shared_instance().service()) , m_connection(connection) #ifdef CPPREST_PLATFORM_ASIO_CERT_VERIFICATION_AVAILABLE , m_openssl_failed(false) @@ -585,11 +583,11 @@ class asio_context final : public request_context, public std::enable_shared_fro tcp::resolver::query query(utility::conversions::to_utf8string(proxy_host), to_string(proxy_port)); auto client = std::static_pointer_cast(m_context->m_http_client); - client->m_resolver.async_resolve(query, - boost::bind(&ssl_proxy_tunnel::handle_resolve, - shared_from_this(), - boost::asio::placeholders::error, - boost::asio::placeholders::iterator)); + m_context->m_resolver.async_resolve(query, + boost::bind(&ssl_proxy_tunnel::handle_resolve, + shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::iterator)); } private: @@ -887,12 +885,11 @@ class asio_context final : public request_context, public std::enable_shared_fro auto tcp_port = proxy_type == http_proxy_type::http ? proxy_port : port; tcp::resolver::query query(tcp_host, to_string(tcp_port)); - auto client = std::static_pointer_cast(ctx->m_http_client); - client->m_resolver.async_resolve(query, - boost::bind(&asio_context::handle_resolve, - ctx, - boost::asio::placeholders::error, - boost::asio::placeholders::iterator)); + ctx->m_resolver.async_resolve(query, + boost::bind(&asio_context::handle_resolve, + ctx, + boost::asio::placeholders::error, + boost::asio::placeholders::iterator)); } // Register for notification on cancellation to abort this request. @@ -1053,6 +1050,10 @@ class asio_context final : public request_context, public std::enable_shared_fro { report_error("Error resolving address", ec, httpclient_errorcode_context::connect); } + else if (endpoints == tcp::resolver::iterator()) + { + report_error("Failed to resolve address", ec, httpclient_errorcode_context::connect); + } else { m_timer.reset(); @@ -1452,8 +1453,8 @@ class asio_context final : public request_context, public std::enable_shared_fro } } - m_content_length = (std::numeric_limits::max)(); // Without Content-Length header, size should be same as - // TCP stream - set it size_t max. + m_content_length = (std::numeric_limits::max)(); // Without Content-Length header, size should be same + // as TCP stream - set it size_t max. m_response.headers().match(header_names::content_length, m_content_length); if (!this->handle_compression()) @@ -1936,6 +1937,7 @@ class asio_context final : public request_context, public std::enable_shared_fro uint64_t m_content_length; bool m_needChunked; timeout_timer m_timer; + tcp::resolver m_resolver; boost::asio::streambuf m_body_buf; std::shared_ptr m_connection; From b94bc32ff84e815ba44c567f6fe4af5f5f6b3048 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Sun, 23 Feb 2020 20:33:51 -0800 Subject: [PATCH 41/80] Mint v2.10.15. (#1336) --- Release/CMakeLists.txt | 2 +- Release/include/cpprest/version.h | 2 +- changelog.md | 54 +++++++++++++++++++++++-------- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 953dd29665..18b0cb3f48 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 14) +set(CPPREST_VERSION_REVISION 15) enable_testing() diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index a6a55e231b..b505f1b9e3 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -5,6 +5,6 @@ */ #define CPPREST_VERSION_MINOR 10 #define CPPREST_VERSION_MAJOR 2 -#define CPPREST_VERSION_REVISION 14 +#define CPPREST_VERSION_REVISION 15 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR * 100000 + CPPREST_VERSION_MINOR * 100 + CPPREST_VERSION_REVISION) diff --git a/changelog.md b/changelog.md index 3c11c199c6..d5a44eb6b9 100644 --- a/changelog.md +++ b/changelog.md @@ -1,20 +1,46 @@ +cpprestsdk (2.10.15) +* Extremely special thanks to @garethsb-sony for a large number of contributions in this release +* PR#1209 Workarounds for two GCC 4.7.2 bugs with lambda functions +* PR#1220 Fix SxS debug-release builds with Visual Studio +* PR#1219 Fix "Data" to "Date" in the HTTP Server API mapping, and clarify that the indices of these values match the HTTP_HEADER_ID values for HTTP_REQUEST_HEADERS but *not* HTTP_RESPONSE_HEADERS +* PR#1196 Fixing of connections_and_errors::cancel_with_error test which sometimes fires false positive error "There are no pending calls to next_request." +* PR#1233 Trim whitespace and nulls the same way. +* PR#1248 Avoid using permissive- with ZW which breaks VS2019 +* PR#1182 Support for WinHTTPAL curl-to-WinHTTP adapter +* PR#1253 http_server_httpsys.cpp requires linking against httpapi.lib, http_client_winhttp.cpp does not. +* PR#1263 Remove trailing slash on websocketpp submodule url, which causes checkout failure on CircleCI with git 2.22.0 +* PR#1293 Update vcpkg and remove tests that look for web servers that no longer exist +* PR#1288 Fix test case broken by commit f4c863b +* PR#1276 Added comparison overrides to utility::datetime +* PR#1289 Fix various warnings reported by gcc 9.3, and possibly earlier versions +* PR#1334 Update vcpkg and boost on Android +* PR#1306 Change default installation directory for cmake files to cmake/cpprestsdk +* PR#1330 Use LC_ALL_MASK rather than LC_ALL when calling newlocale +* PR#1310 Add TCP_NODELAY to disable Nagle's algorithm in Boost.ASIO-based http_client +* PR#1335 Turn VS2015 back on now that vcpkg is fixed. +* PR#1322 Enable HTTP compression support on all platforms +* PR#1340 Add Ubuntu 18.04 testing. +* PR#1342 Use C++11 synchronization classes under macOS too +* PR#1339 Fix tcp::resolver data race in the asio backend and be defensive against empty results +-- cpprestsdk team THR, 22 Feb 2020 08:31:00 -0800 + cpprestsdk (2.10.14) * Potential breaking change warning: This release changes the "default" proxy for the WinHTTP backend to go back to WINHTTP_ACCESS_TYPE_DEFAULT_PROXY. See https://github.com/microsoft/cpprestsdk/commit/60e067e71aebebdda5d82955060f5f0821c9df1d for more details. To get automatic WPAD behavior, set the proxy to auto detect. * macOS with Brew and iOS builds have been disabled and are no longer being tested because our dependency boost for ios project appears to be broken with current releases of XCode as on the Azure Pipelines machines. We are interested in macOS / iOS folks who know what's going on here in contributing a repair to turn this back on. -* PR##1133 Add switches to make apiscan happy. -* PR##1130 json: {"meow"} is not a valid object -* PR##1150 Undefine compress if it is defined by zconf.h -* PR##1156 Fix broken CI Builds -* PR##1155 Use EVP_MAX_MD_SIZE instead of HMAC_MAX_MD_CBLOCK -* PR##1145 Remove the address_configured flag on tcp::resolver::query -* PR##1143 add ping and pong to message handler -* PR##539 Fix reusing ASIO http_client connecting to HTTPS server via proxy -* PR##1175 Fix issue #1171: Order of object destruction -* PR##1183 FIX: SSL proxy tunnel support with basic auth -* PR##1184 Fix profile being set on the compiler instead of the linker. -* PR##1185 Update boost-for-android for Android NDK r20 and disable macOS Homebrew. -* PR##1187 Replace CPPREST_TARGET_XP with version checks, remove ""s, and other cleanup -* PR##1188 Remove proxy settings detection behavior in "default proxy mode." +* PR#1133 Add switches to make apiscan happy. +* PR#1130 json: {"meow"} is not a valid object +* PR#1150 Undefine compress if it is defined by zconf.h +* PR#1156 Fix broken CI Builds +* PR#1155 Use EVP_MAX_MD_SIZE instead of HMAC_MAX_MD_CBLOCK +* PR#1145 Remove the address_configured flag on tcp::resolver::query +* PR#1143 add ping and pong to message handler +* PR#539 Fix reusing ASIO http_client connecting to HTTPS server via proxy +* PR#1175 Fix issue #1171: Order of object destruction +* PR#1183 FIX: SSL proxy tunnel support with basic auth +* PR#1184 Fix profile being set on the compiler instead of the linker. +* PR#1185 Update boost-for-android for Android NDK r20 and disable macOS Homebrew. +* PR#1187 Replace CPPREST_TARGET_XP with version checks, remove ""s, and other cleanup +* PR#1188 Remove proxy settings detection behavior in "default proxy mode." -- cpprestsdk team TUE, 16 Jul 2019 09:06:00 +0200 cpprestsdk (2.10.13) From cb7ca74e5f3bdbde363ed4ddb5655e76931397bd Mon Sep 17 00:00:00 2001 From: Fabrice Fontaine Date: Mon, 2 Mar 2020 23:51:12 +0100 Subject: [PATCH 42/80] libcpprestsdk: fix building as a static library (#1344) On Unix, try to use pkg-config to find OpenSSL. This will automatically find any dependent libraries and put them in the correct order for linking. If pkg-config is not available or system is not UNIX, fallback on current mechanism Signed-off-by: Adam Duskett [Retrieved (and slightly updated) from: https://git.buildroot.net/buildroot/tree/package/libcpprestsdk/0001-libcpprestsdk-fix-building-as-a-static-library.patch] Signed-off-by: Fabrice Fontaine --- Release/cmake/cpprest_find_openssl.cmake | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Release/cmake/cpprest_find_openssl.cmake b/Release/cmake/cpprest_find_openssl.cmake index 0b49a7e55c..57e43a2fb7 100644 --- a/Release/cmake/cpprest_find_openssl.cmake +++ b/Release/cmake/cpprest_find_openssl.cmake @@ -41,7 +41,15 @@ function(cpprest_find_openssl) # This should prevent linking against the system provided 0.9.8y set(_OPENSSL_VERSION "") endif() - find_package(OpenSSL 1.0.0 REQUIRED) + if(UNIX) + find_package(PkgConfig) + pkg_search_module(OPENSSL openssl) + endif() + if(OPENSSL_FOUND) + target_link_libraries(cpprest PRIVATE ${OPENSSL_LDFLAGS}) + else() + find_package(OpenSSL 1.0.0 REQUIRED) + endif() INCLUDE(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_INCLUDES "${OPENSSL_INCLUDE_DIR}") @@ -67,4 +75,4 @@ function(cpprest_find_openssl) # libressl doesn't ship with the cleanup method being used in ws_client_wspp target_compile_definitions(cpprestsdk_openssl_internal INTERFACE -DCPPREST_NO_SSL_LEAK_SUPPRESS) endif() -endfunction() \ No newline at end of file +endfunction() From cdae258bfb22f948c7b768b4dc56f5f4a2d9b2ce Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Mon, 2 Mar 2020 23:00:16 +0000 Subject: [PATCH 43/80] [#1349] Expose json::value::parse for UTF8 string on Windows (#1350) --- Release/include/cpprest/json.h | 24 ++++- Release/src/json/json_parsing.cpp | 93 +++++++------------ .../tests/functional/json/parsing_tests.cpp | 26 ++++-- 3 files changed, 69 insertions(+), 74 deletions(-) diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index 4549d1017c..8fbbf947f2 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -390,17 +390,37 @@ class value /// /// Parses a string and construct a JSON value. /// - /// The C++ value to create a JSON value from, a C++ STL double-byte string + /// The C++ value to create a JSON value from, a C++ STL string of the + /// platform-native character width _ASYNCRTIMP static value __cdecl parse(const utility::string_t& value); /// /// Attempts to parse a string and construct a JSON value. /// - /// The C++ value to create a JSON value from, a C++ STL double-byte string + /// The C++ value to create a JSON value from, a C++ STL string of the + /// platform-native character width /// If parsing fails, the error code is greater than 0 /// The parsed object. Returns web::json::value::null if failed _ASYNCRTIMP static value __cdecl parse(const utility::string_t& value, std::error_code& errorCode); +#ifdef _WIN32 + /// + /// Parses a string and construct a JSON value. + /// + /// The C++ value to create a JSON value from, a C++ STL string in + /// UTF8 format + _ASYNCRTIMP static value __cdecl parse(const std::string& value); + + /// + /// Attempts to parse a string and construct a JSON value. + /// + /// The C++ value to create a JSON value from, a C++ STL string in + /// UTF8 format + /// If parsing fails, the error code is greater than 0 + /// The parsed object. Returns web::json::value::null if failed + _ASYNCRTIMP static value __cdecl parse(const std::string& value, std::error_code& errorCode); +#endif + /// /// Serializes the current JSON value to a C++ string. /// diff --git a/Release/src/json/json_parsing.cpp b/Release/src/json/json_parsing.cpp index 30873fd36d..01f0d0b160 100644 --- a/Release/src/json/json_parsing.cpp +++ b/Release/src/json/json_parsing.cpp @@ -1120,10 +1120,11 @@ std::unique_ptr JSON_Parser::_ParseValue( } // namespace json } // namespace web -static web::json::value _parse_stream(utility::istream_t& stream) +template +static web::json::value _parse_stream(std::basic_istream& stream) { - web::json::details::JSON_StreamParser parser(stream); - web::json::details::JSON_Parser::Token tkn; + web::json::details::JSON_StreamParser parser(stream); + typename web::json::details::JSON_Parser::Token tkn; parser.GetNextToken(tkn); if (tkn.m_error) @@ -1136,7 +1137,7 @@ static web::json::value _parse_stream(utility::istream_t& stream) { web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message())); } - else if (tkn.kind != web::json::details::JSON_Parser::Token::TKN_EOF) + else if (tkn.kind != web::json::details::JSON_Parser::Token::TKN_EOF) { web::json::details::CreateException(tkn, _XPLATSTR("Left-over characters in stream after parsing a JSON value")); @@ -1144,10 +1145,11 @@ static web::json::value _parse_stream(utility::istream_t& stream) return value; } -static web::json::value _parse_stream(utility::istream_t& stream, std::error_code& error) +template +static web::json::value _parse_stream(std::basic_istream& stream, std::error_code& error) { - web::json::details::JSON_StreamParser parser(stream); - web::json::details::JSON_Parser::Token tkn; + web::json::details::JSON_StreamParser parser(stream); + typename web::json::details::JSON_Parser::Token tkn; parser.GetNextToken(tkn); if (tkn.m_error) @@ -1157,7 +1159,7 @@ static web::json::value _parse_stream(utility::istream_t& stream, std::error_cod } auto returnObject = parser.ParseValue(tkn); - if (tkn.kind != web::json::details::JSON_Parser::Token::TKN_EOF) + if (tkn.kind != web::json::details::JSON_Parser::Token::TKN_EOF) { web::json::details::SetErrorCode(tkn, web::json::details::json_error::left_over_character_in_stream); } @@ -1166,11 +1168,11 @@ static web::json::value _parse_stream(utility::istream_t& stream, std::error_cod return returnObject; } -#ifdef _WIN32 -static web::json::value _parse_narrow_stream(std::istream& stream) +template +static web::json::value _parse_string(const std::basic_string& str) { - web::json::details::JSON_StreamParser parser(stream); - web::json::details::JSON_StreamParser::Token tkn; + web::json::details::JSON_StringParser parser(str); + typename web::json::details::JSON_Parser::Token tkn; parser.GetNextToken(tkn); if (tkn.m_error) @@ -1183,7 +1185,7 @@ static web::json::value _parse_narrow_stream(std::istream& stream) { web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message())); } - else if (tkn.kind != web::json::details::JSON_Parser::Token::TKN_EOF) + else if (tkn.kind != web::json::details::JSON_Parser::Token::TKN_EOF) { web::json::details::CreateException(tkn, _XPLATSTR("Left-over characters in stream after parsing a JSON value")); @@ -1191,10 +1193,11 @@ static web::json::value _parse_narrow_stream(std::istream& stream) return value; } -static web::json::value _parse_narrow_stream(std::istream& stream, std::error_code& error) +template +static web::json::value _parse_string(const std::basic_string& str, std::error_code& error) { - web::json::details::JSON_StreamParser parser(stream); - web::json::details::JSON_StreamParser::Token tkn; + web::json::details::JSON_StringParser parser(str); + typename web::json::details::JSON_Parser::Token tkn; parser.GetNextToken(tkn); if (tkn.m_error) @@ -1204,7 +1207,7 @@ static web::json::value _parse_narrow_stream(std::istream& stream, std::error_co } auto returnObject = parser.ParseValue(tkn); - if (tkn.kind != web::json::details::JSON_Parser::Token::TKN_EOF) + if (tkn.kind != web::json::details::JSON_Parser::Token::TKN_EOF) { returnObject = web::json::value(); web::json::details::SetErrorCode(tkn, web::json::details::json_error::left_over_character_in_stream); @@ -1213,53 +1216,12 @@ static web::json::value _parse_narrow_stream(std::istream& stream, std::error_co error = std::move(tkn.m_error); return returnObject; } -#endif -web::json::value web::json::value::parse(const utility::string_t& str) -{ - web::json::details::JSON_StringParser parser(str); - web::json::details::JSON_Parser::Token tkn; - - parser.GetNextToken(tkn); - if (tkn.m_error) - { - web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message())); - } - - auto value = parser.ParseValue(tkn); - if (tkn.m_error) - { - web::json::details::CreateException(tkn, utility::conversions::to_string_t(tkn.m_error.message())); - } - else if (tkn.kind != web::json::details::JSON_Parser::Token::TKN_EOF) - { - web::json::details::CreateException(tkn, - _XPLATSTR("Left-over characters in stream after parsing a JSON value")); - } - return value; -} +web::json::value web::json::value::parse(const utility::string_t& str) { return _parse_string(str); } web::json::value web::json::value::parse(const utility::string_t& str, std::error_code& error) { - web::json::details::JSON_StringParser parser(str); - web::json::details::JSON_Parser::Token tkn; - - parser.GetNextToken(tkn); - if (tkn.m_error) - { - error = std::move(tkn.m_error); - return web::json::value(); - } - - auto returnObject = parser.ParseValue(tkn); - if (tkn.kind != web::json::details::JSON_Parser::Token::TKN_EOF) - { - returnObject = web::json::value(); - web::json::details::SetErrorCode(tkn, web::json::details::json_error::left_over_character_in_stream); - } - - error = std::move(tkn.m_error); - return returnObject; + return _parse_string(str, error); } web::json::value web::json::value::parse(utility::istream_t& stream) { return _parse_stream(stream); } @@ -1270,10 +1232,17 @@ web::json::value web::json::value::parse(utility::istream_t& stream, std::error_ } #ifdef _WIN32 -web::json::value web::json::value::parse(std::istream& stream) { return _parse_narrow_stream(stream); } +web::json::value web::json::value::parse(const std::string& str) { return _parse_string(str); } + +web::json::value web::json::value::parse(const std::string& str, std::error_code& error) +{ + return _parse_string(str, error); +} + +web::json::value web::json::value::parse(std::istream& stream) { return _parse_stream(stream); } web::json::value web::json::value::parse(std::istream& stream, std::error_code& error) { - return _parse_narrow_stream(stream, error); + return _parse_stream(stream, error); } #endif diff --git a/Release/tests/functional/json/parsing_tests.cpp b/Release/tests/functional/json/parsing_tests.cpp index 2a4db09538..bd43ee253c 100644 --- a/Release/tests/functional/json/parsing_tests.cpp +++ b/Release/tests/functional/json/parsing_tests.cpp @@ -347,7 +347,7 @@ SUITE(parsing_tests) VERIFY_ARE_EQUAL(U("K"), str.as_string()); str = json::value::parse(U("\"\\u20AC\"")); - // Euro sign as a hexidecmial UTF-8 + // Euro sign as a hexadecimal UTF-8 const auto euro = to_string_t("\xE2\x82\xAC"); VERIFY_ARE_EQUAL(euro, str.as_string()); @@ -631,30 +631,34 @@ SUITE(parsing_tests) TEST(byte_ptr_parsing_array) { char s[] = "[ \"test1\",true]"; + json::value v = json::value::parse(s); std::stringstream ss; ss << s; - json::value v = json::value::parse(ss); - auto s2 = v.serialize(); + json::value vv = json::value::parse(ss); + VERIFY_ARE_EQUAL(v, vv); + auto s2 = v.serialize(); VERIFY_ARE_EQUAL(s2, U("[\"test1\",true]")); std::stringstream os; - v.serialize(os); + vv.serialize(os); VERIFY_ARE_EQUAL(s2, to_string_t(os.str())); } TEST(byte_ptr_parsing_object) { char s[] = "{\"test1\":true }"; + json::value v = json::value::parse(s); std::stringstream ss; ss << s; - json::value v = json::value::parse(ss); - auto s2 = v.serialize(); + json::value vv = json::value::parse(ss); + VERIFY_ARE_EQUAL(v, vv); + auto s2 = v.serialize(); VERIFY_ARE_EQUAL(s2, U("{\"test1\":true}")); std::stringstream os; - v.serialize(os); + vv.serialize(os); VERIFY_ARE_EQUAL(s2, to_string_t(os.str())); } @@ -662,16 +666,18 @@ SUITE(parsing_tests) { utility::string_t ws = U("\"こんにちは\""); std::string s = to_utf8string(ws); + json::value v = json::value::parse(s); std::stringstream ss; ss << s; - json::value v = json::value::parse(ss); - auto s2 = v.serialize(); + json::value vv = json::value::parse(ss); + VERIFY_ARE_EQUAL(v, vv); + auto s2 = v.serialize(); VERIFY_ARE_EQUAL(s2, ws); std::stringstream os; - v.serialize(os); + vv.serialize(os); VERIFY_ARE_EQUAL(s2, to_string_t(os.str())); } From 927afad9093ba56f4b39d0a5285171a8fa59d835 Mon Sep 17 00:00:00 2001 From: Dmitry Tsarevich Date: Wed, 1 Apr 2020 02:02:07 +0300 Subject: [PATCH 44/80] Static analyzer (PVS Studio) fixes (#1372) * [init] Initialize stream mode to in by default * [leak] Fix memory leak of server api ptr Should call delete on pointer instead of releasing it to the caller. * [macro] Ensure priority of macro computation Enclose macro args in round brackets to ensure operators priority. * [prep] Fix comment after preprocessor macro * [ub] Use typed pointer in delete operation * Delete of void pointer is UB. See section 5.3.5/3. SO question: https://stackoverflow.com/questions/941832/is-it-safe-to-delete-a-void-pointer * Windows APIs used here return FALSE in case of failure, and non-FALSE on success. There is no info in spec that only TRUE value indicates success. Correct way to implement check for success call is to compare with false like result != FALSE. * [fmt] Fix military RFC1123 time format parsing Ensure + or - sign is used for time zone offset in RFC1123 military time format. * Remove redundant != FALSE. Co-authored-by: Billy Robert O'Neal III --- Release/include/cpprest/producerconsumerstream.h | 1 + Release/src/http/listener/http_server_api.cpp | 2 +- Release/src/http/listener/http_server_httpsys.cpp | 2 +- Release/src/pch/stdafx.h | 2 +- Release/src/streams/fileio_win32.cpp | 10 +++++----- Release/src/utilities/asyncrt_utils.cpp | 2 +- Release/tests/functional/utils/datetime.cpp | 3 ++- 7 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Release/include/cpprest/producerconsumerstream.h b/Release/include/cpprest/producerconsumerstream.h index bbdb2c1c85..28463372e4 100644 --- a/Release/include/cpprest/producerconsumerstream.h +++ b/Release/include/cpprest/producerconsumerstream.h @@ -47,6 +47,7 @@ class basic_producer_consumer_buffer : public streams::details::streambuf_state_ /// basic_producer_consumer_buffer(size_t alloc_size) : streambuf_state_manager<_CharType>(std::ios_base::out | std::ios_base::in) + , m_mode(std::ios_base::in) , m_alloc_size(alloc_size) , m_allocBlock(nullptr) , m_total(0) diff --git a/Release/src/http/listener/http_server_api.cpp b/Release/src/http/listener/http_server_api.cpp index 8c50353783..ea985f4a0a 100644 --- a/Release/src/http/listener/http_server_api.cpp +++ b/Release/src/http/listener/http_server_api.cpp @@ -50,7 +50,7 @@ void http_server_api::unregister_server_api() throw http_exception(_XPLATSTR("Server API was cleared while listeners were still attached")); } - s_server_api.release(); + s_server_api.reset(); } void http_server_api::unsafe_register_server_api(std::unique_ptr server_api) diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index 318d1404c0..2eac0baf11 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -32,7 +32,7 @@ using namespace http::details; using namespace http::experimental::listener; using namespace http::experimental::details; -#define CHUNK_SIZE 64 * 1024 +#define CHUNK_SIZE (64 * 1024) namespace web { diff --git a/Release/src/pch/stdafx.h b/Release/src/pch/stdafx.h index 2061bea7f6..5c398e14c4 100644 --- a/Release/src/pch/stdafx.h +++ b/Release/src/pch/stdafx.h @@ -40,7 +40,7 @@ // Windows Header Files: #ifndef __cplusplus_winrt #include -#endif !__cplusplus_winrt +#endif // !__cplusplus_winrt #else // LINUX or APPLE #define __STDC_LIMIT_MACROS diff --git a/Release/src/streams/fileio_win32.cpp b/Release/src/streams/fileio_win32.cpp index 97cd6e5e6d..057dd9b670 100644 --- a/Release/src/streams/fileio_win32.cpp +++ b/Release/src/streams/fileio_win32.cpp @@ -111,7 +111,7 @@ void CALLBACK IoCompletionCallback(PTP_CALLBACK_INSTANCE instance, EXTENDED_OVERLAPPED* pExtOverlapped = static_cast(pOverlapped); pExtOverlapped->func(result, static_cast(numberOfBytesTransferred), static_cast(pOverlapped)); - delete pOverlapped; + delete pExtOverlapped; } #endif @@ -399,10 +399,10 @@ size_t _write_file_async(_In_ streams::details::_file_info_impl* fInfo, size_t result = static_cast(-1); - if (wrResult == TRUE) + if (wrResult) { // If WriteFile returned true, it must be because the operation completed immediately. - // However, we didn't pass in an address for the number of bytes written, so + // However, we didn't pass in an address for the number of bytes written, so // we have to retrieve it using 'GetOverlappedResult,' which may, in turn, fail. DWORD written = 0; result = GetOverlappedResult(fInfo->m_handle, pOverlapped.get(), &written, FALSE) ? static_cast(written) @@ -496,7 +496,7 @@ size_t _read_file_async(_In_ streams::details::_file_info_impl* fInfo, size_t result = static_cast(-1); - if (wrResult == TRUE) + if (wrResult) { // If ReadFile returned true, it must be because the operation completed immediately. // However, we didn't pass in an address for the number of bytes written, so @@ -941,7 +941,7 @@ utility::size64_t __cdecl _get_size(_In_ concurrency::streams::details::_file_in LARGE_INTEGER size; - if (GetFileSizeEx(fInfo->m_handle, &size) == TRUE) + if (GetFileSizeEx(fInfo->m_handle, &size)) return utility::size64_t(size.QuadPart / char_size); else return 0; diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index 62cce9e8fb..16d7e687b9 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -1148,7 +1148,7 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date { tzHours = 8; } - else if ((tzCh == _XPLATSTR('+') || tzCh == _XPLATSTR('-')) && ascii_isdigit2(str[1]) && + else if ((str[0] == _XPLATSTR('+') || str[0] == _XPLATSTR('-')) && ascii_isdigit2(str[1]) && ascii_isdigit(str[2]) && ascii_isdigit5(str[3]) && ascii_isdigit(str[4])) { tzCh = str[0]; diff --git a/Release/tests/functional/utils/datetime.cpp b/Release/tests/functional/utils/datetime.cpp index 33d532a098..aac5b16714 100644 --- a/Release/tests/functional/utils/datetime.cpp +++ b/Release/tests/functional/utils/datetime.cpp @@ -304,7 +304,8 @@ SUITE(datetime) _XPLATSTR("01 Jan 1971 00:00:61 GMT"), _XPLATSTR("01 Jan 1899 00:00:00 GMT"), // underflow _XPLATSTR("01 Jan 1969 00:00:00 CEST"), // bad tz - _XPLATSTR("01 Jan 1970 00:00:00 +2400"), // bad tzoffsets + _XPLATSTR("14 Jan 2019 23:16:21 G0100"), // bad tzoffsets + _XPLATSTR("01 Jan 1970 00:00:00 +2400"), _XPLATSTR("01 Jan 1970 00:00:00 -3000"), _XPLATSTR("01 Jan 1970 00:00:00 +2160"), _XPLATSTR("01 Jan 1970 00:00:00 -2400"), From 6d0e2b73af5b684d4d3fd9338130701c2f43aef3 Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Wed, 1 Apr 2020 00:21:51 +0100 Subject: [PATCH 45/80] Remove redundant std::move noted by gcc 9.2 (-Wredundant-move) (#1370) --- Release/src/json/json_parsing.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Release/src/json/json_parsing.cpp b/Release/src/json/json_parsing.cpp index 01f0d0b160..a026ecaba2 100644 --- a/Release/src/json/json_parsing.cpp +++ b/Release/src/json/json_parsing.cpp @@ -1040,7 +1040,7 @@ std::unique_ptr JSON_Parser::_ParseArray( case JSON_Parser::Token::TKN_CloseBracket: GetNextToken(tkn); if (tkn.m_error) return utility::details::make_unique(); - return std::move(result); + return result; default: SetErrorCode(tkn, json_error::malformed_array_literal); return utility::details::make_unique(); @@ -1074,7 +1074,7 @@ std::unique_ptr JSON_Parser::_ParseValue( tkn.has_unescape_symbol); GetNextToken(tkn); if (tkn.m_error) return utility::details::make_unique(); - return std::move(value); + return value; } case JSON_Parser::Token::TKN_IntegerLiteral: { @@ -1086,21 +1086,21 @@ std::unique_ptr JSON_Parser::_ParseValue( GetNextToken(tkn); if (tkn.m_error) return utility::details::make_unique(); - return std::move(value); + return value; } case JSON_Parser::Token::TKN_NumberLiteral: { auto value = utility::details::make_unique(tkn.double_val); GetNextToken(tkn); if (tkn.m_error) return utility::details::make_unique(); - return std::move(value); + return value; } case JSON_Parser::Token::TKN_BooleanLiteral: { auto value = utility::details::make_unique(tkn.boolean_val); GetNextToken(tkn); if (tkn.m_error) return utility::details::make_unique(); - return std::move(value); + return value; } case JSON_Parser::Token::TKN_NullLiteral: { From 1d7550f5d4f8d644e22989e04230a41560f87293 Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Wed, 1 Apr 2020 00:22:47 +0100 Subject: [PATCH 46/80] Fix more http test build fails in certain configurations (#1332) --- .../tests/functional/http/client/client_construction.cpp | 2 +- .../http/listener/listener_construction_tests.cpp | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Release/tests/functional/http/client/client_construction.cpp b/Release/tests/functional/http/client/client_construction.cpp index 9d5216c202..acad00eb61 100644 --- a/Release/tests/functional/http/client/client_construction.cpp +++ b/Release/tests/functional/http/client/client_construction.cpp @@ -173,7 +173,7 @@ SUITE(client_construction) VERIFY_ARE_EQUAL(baseclient2.base_uri(), m_uri); } -#if defined(CPPREST_FORCE_HTTP_LISTENER_ASIO) +#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO) // Verify that the callback of sslcontext is called for HTTPS TEST_FIXTURE(uri_address, ssl_context_callback_https) diff --git a/Release/tests/functional/http/listener/listener_construction_tests.cpp b/Release/tests/functional/http/listener/listener_construction_tests.cpp index 1e93ef56ae..c6d95876ce 100644 --- a/Release/tests/functional/http/listener/listener_construction_tests.cpp +++ b/Release/tests/functional/http/listener/listener_construction_tests.cpp @@ -549,9 +549,13 @@ XzJTD4slrGSJrcpLt/g/Jqqdjg== listener.open().wait(); client::http_client_config client_config; +#if !defined(_WIN32) && !defined(__cplusplus_winrt) || defined(CPPREST_FORCE_HTTP_CLIENT_ASIO) client_config.set_ssl_context_callback( [&](boost::asio::ssl::context& ctx) { ctx.add_certificate_authority(cert); }); - +#else + // in this build configuration, with WinHTTP-based http_client, this test will fail unless the self-signed + // cert is added to the Windows certificate store (or certificate validation is disabled in client_config) +#endif client::http_client client(m_secure_uri, client_config); http_request msg(methods::GET); msg.set_request_uri(U("/")); From f4124a9ee10042582c795578d69022368877282e Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Wed, 1 Apr 2020 05:57:39 +0100 Subject: [PATCH 47/80] Add support for HTTP redirection in ASIO and WinHTTP-based http_clients (#1328) --- Release/include/cpprest/http_client.h | 37 ++ Release/src/http/client/http_client_asio.cpp | 160 +++++++- .../src/http/client/http_client_winhttp.cpp | 148 +++++++- .../tests/common/TestRunner/CMakeLists.txt | 3 + .../common/TestRunner/test_runner.manifest | 17 + .../functional/http/client/CMakeLists.txt | 1 + .../functional/http/client/outside_tests.cpp | 11 +- .../functional/http/client/redirect_tests.cpp | 342 ++++++++++++++++++ 8 files changed, 691 insertions(+), 28 deletions(-) create mode 100644 Release/tests/common/TestRunner/test_runner.manifest create mode 100644 Release/tests/functional/http/client/redirect_tests.cpp diff --git a/Release/include/cpprest/http_client.h b/Release/include/cpprest/http_client.h index 82fa3222b6..fb7c6067ab 100644 --- a/Release/include/cpprest/http_client.h +++ b/Release/include/cpprest/http_client.h @@ -107,6 +107,8 @@ class http_client_config #if (defined(_WIN32) && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) , m_buffer_request(false) #endif + , m_max_redirects(10) + , m_https_to_http_redirects(false) { } @@ -279,6 +281,38 @@ class http_client_config void set_buffer_request(bool buffer_request) { m_buffer_request = buffer_request; } #endif + /// + /// Get the maximum number of redirects to follow automatically. + /// A value of 0 indicates that no automatic redirection is performed. + /// + /// The maximum number of redirects to follow automatically. + /// This is a hint -- an implementation may enforce a lower value. + size_t max_redirects() const { return m_max_redirects; } + + /// + /// Set the maximum number of redirects to follow automatically. + /// A value of 0 indicates that no automatic redirection is performed. + /// + /// The maximum number of redirects to follow automatically. + /// This is a hint -- an implementation may enforce a lower value. + void set_max_redirects(size_t max_redirects) { m_max_redirects = max_redirects; } + + /// + /// Checks if HTTPS to HTTP redirects are automatically followed. + /// + /// True if HTTPS to HTTP redirects are automatically followed, false otherwise. + bool https_to_http_redirects() const { return m_https_to_http_redirects; } + + /// + /// Sets if HTTPS to HTTP redirects are automatically followed. + /// + /// True if HTTPS to HTTP redirects are to be automatically + /// followed, false otherwise. + void set_https_to_http_redirects(bool https_to_http_redirects) + { + m_https_to_http_redirects = https_to_http_redirects; + } + /// /// Sets a callback to enable custom setting of platform specific options. /// @@ -392,6 +426,9 @@ class http_client_config #if (defined(_WIN32) && !defined(__cplusplus_winrt)) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) bool m_buffer_request; #endif + + size_t m_max_redirects; + bool m_https_to_http_redirects; }; class http_pipeline; diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 215b03e58a..7ae7e9921f 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -1976,6 +1976,162 @@ void asio_client::send_request(const std::shared_ptr& request_c ctx->start_request(); } +static bool is_retrieval_redirection(status_code code) +{ + // See https://tools.ietf.org/html/rfc7231#section-6.4 + + switch (code) + { + case status_codes::MovedPermanently: + // "For historical reasons, a user agent MAY change the request method + // from POST to GET for the subsequent request." + return true; + case status_codes::Found: + // "For historical reasons, a user agent MAY change the request method + // from POST to GET for the subsequent request." + return true; + case status_codes::SeeOther: + // "A user agent can perform a [GET or HEAD] request. It is primarily + // used to allow the output of a POST action to redirect the user agent + // to a selected resource." + return true; + default: + return false; + } +} + +static bool is_unchanged_redirection(status_code code) +{ + // See https://tools.ietf.org/html/rfc7231#section-6.4 + // and https://tools.ietf.org/html/rfc7538#section-3 + + switch (code) + { + case status_codes::TemporaryRedirect: + // "The user agent MUST NOT change the request method if it performs an + // automatic redirection to that URI." + return true; + case status_codes::PermanentRedirect: + // This status code "does not allow changing the request method from POST + // to GET." + return true; + default: + return false; + } +} + +static bool is_recognized_redirection(status_code code) +{ + // other 3xx status codes, e.g. 300 Multiple Choices, are not handled + // and should be handled externally + return is_retrieval_redirection(code) || is_unchanged_redirection(code); +} + +static bool is_retrieval_request(method method) +{ + return methods::GET == method || methods::HEAD == method; +} + +static const std::vector request_body_header_names = +{ + header_names::content_encoding, + header_names::content_language, + header_names::content_length, + header_names::content_location, + header_names::content_type +}; + +// A request continuation that follows redirects according to the specified configuration. +// This implementation only supports retrieval redirects, as it cannot redirect e.g. a POST request +// using the same method since the request body may have been consumed. +struct http_redirect_follower +{ + http_client_config config; + std::vector followed_urls; + http_request redirect; + + http_redirect_follower(http_client_config config, const http_request& request); + + uri url_to_follow(const http_response& response) const; + + pplx::task operator()(http_response response); +}; + +http_redirect_follower::http_redirect_follower(http_client_config config, const http_request& request) + : config(std::move(config)) + , followed_urls(1, request.absolute_uri()) + , redirect(request.method()) +{ + // Stash the original request URL, etc. to be prepared for an automatic redirect + + // Basically, it makes sense to send the redirects with the same headers as the original request + redirect.headers() = request.headers(); + // However, this implementation only supports retrieval redirects, with no body, so Content-* headers + // should be removed + for (const auto& content_header : request_body_header_names) + { + redirect.headers().remove(content_header); + } + + redirect._set_cancellation_token(request._cancellation_token()); +} + +uri http_redirect_follower::url_to_follow(const http_response& response) const +{ + // Return immediately if the response is not a supported redirection + if (!is_recognized_redirection(response.status_code())) + return{}; + + // Although not required by RFC 7231, config may limit the number of automatic redirects + // (followed_urls includes the initial request URL, hence '<' here) + if (config.max_redirects() < followed_urls.size()) + return{}; + + // Can't very well automatically redirect if the server hasn't provided a Location + const auto location = response.headers().find(header_names::location); + if (response.headers().end() == location) + return{}; + + uri to_follow(followed_urls.back().resolve_uri(location->second)); + + // Config may prohibit automatic redirects from HTTPS to HTTP + if (!config.https_to_http_redirects() && followed_urls.back().scheme() == _XPLATSTR("https") + && to_follow.scheme() != _XPLATSTR("https")) + return{}; + + // "A client SHOULD detect and intervene in cyclical redirections." + if (followed_urls.end() != std::find(followed_urls.begin(), followed_urls.end(), to_follow)) + return{}; + + return to_follow; +} + +pplx::task http_redirect_follower::operator()(http_response response) +{ + // Return immediately if the response doesn't indicate a valid automatic redirect + uri to_follow = url_to_follow(response); + if (to_follow.is_empty()) + return pplx::task_from_result(response); + + // This implementation only supports retrieval redirects, as it cannot redirect e.g. a POST request + // using the same method since the request body may have been consumed. + if (!is_retrieval_request(redirect.method()) && !is_retrieval_redirection(response.status_code())) + return pplx::task_from_result(response); + + if (!is_retrieval_request(redirect.method())) + redirect.set_method(methods::GET); + + // If the reply to this request is also a redirect, we want visibility of that + auto config_no_redirects = config; + config_no_redirects.set_max_redirects(0); + http_client client(to_follow, config_no_redirects); + + // Stash the redirect request URL and make the request with the same continuation + auto request_task = client.request(redirect, redirect._cancellation_token()); + followed_urls.push_back(std::move(to_follow)); + return request_task.then(std::move(*this)); +} + pplx::task asio_client::propagate(http_request request) { auto self = std::static_pointer_cast<_http_client_communicator>(shared_from_this()); @@ -1995,7 +2151,9 @@ pplx::task asio_client::propagate(http_request request) // Asynchronously send the response with the HTTP client implementation. this->async_send_request(context); - return result_task; + return client_config().max_redirects() > 0 + ? result_task.then(http_redirect_follower(client_config(), request)) + : result_task; } } // namespace details } // namespace client diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index fc2bfbae8c..d6cdb5384a 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -263,6 +263,8 @@ class winhttp_request_context final : public request_context bool m_proxy_authentication_tried; bool m_server_authentication_tried; + size_t m_remaining_redirects; + msg_body_type m_bodyType; utility::size64_t m_remaining_to_write; @@ -679,6 +681,7 @@ class winhttp_request_context final : public request_context , m_request_handle(nullptr) , m_proxy_authentication_tried(false) , m_server_authentication_tried(false) + , m_remaining_redirects(0) , m_bodyType(no_body) , m_remaining_to_write(0) , m_startingPosition(std::char_traits::eof()) @@ -892,12 +895,14 @@ class winhttp_client final : public _http_client_communicator return GetLastError(); } - // Set timeouts. - int milliseconds = static_cast(config.timeout().count()); - milliseconds = std::max(milliseconds, 1); - if (!WinHttpSetTimeouts(m_hSession, milliseconds, milliseconds, milliseconds, milliseconds)) { - return GetLastError(); + // Set timeouts. + const int milliseconds = + (std::max)(static_cast(config.timeout().count()), 1); + if (!WinHttpSetTimeouts(m_hSession, milliseconds, milliseconds, milliseconds, milliseconds)) + { + return GetLastError(); + } } if (config.guarantee_order()) @@ -911,19 +916,18 @@ class winhttp_client final : public _http_client_communicator } } - // Enable TLS 1.1 and 1.2 -#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) - BOOL win32_result(FALSE); - - DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | - WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2); - win32_result = ::WinHttpSetOption( - m_hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols)); - if (FALSE == win32_result) { - return GetLastError(); - } + // Enable TLS 1.1 and 1.2 +#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) || defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) + DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 | + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2); + if (!WinHttpSetOption( + m_hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols))) + { + return GetLastError(); + } #endif + } config._invoke_nativesessionhandle_options(m_hSession); @@ -932,7 +936,8 @@ class winhttp_client final : public _http_client_communicator WinHttpSetStatusCallback(m_hSession, &winhttp_client::completion_callback, WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS | WINHTTP_CALLBACK_FLAG_HANDLES | - WINHTTP_CALLBACK_FLAG_SECURE_FAILURE | WINHTTP_CALLBACK_FLAG_SEND_REQUEST, + WINHTTP_CALLBACK_FLAG_SECURE_FAILURE | WINHTTP_CALLBACK_FLAG_SEND_REQUEST | + WINHTTP_CALLBACK_STATUS_REDIRECT, 0)) { return GetLastError(); @@ -1128,6 +1133,63 @@ class winhttp_client final : public _http_client_communicator return; } +// WinHttpPAL does not currently provide these options +// See https://github.com/microsoft/WinHttpPAL/issues/1 +#if !defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) + if (client_config().max_redirects() == 0) + { + // Disable auto redirects. + DWORD redirectPolicy = WINHTTP_OPTION_REDIRECT_POLICY_NEVER; + if (!WinHttpSetOption(winhttp_context->m_request_handle, + WINHTTP_OPTION_REDIRECT_POLICY, + &redirectPolicy, + sizeof(redirectPolicy))) + { + auto errorCode = GetLastError(); + request->report_error(errorCode, build_error_msg(errorCode, "Setting redirect policy")); + return; + } + // Note, using WINHTTP_OPTION_DISABLE_FEATURE with WINHTTP_DISABLE_REDIRECTS here doesn't seem to work. + } + else + { + // Set max auto redirects. + + // Add 1 to config value because WinHttp option counts the original request. + // And another 1 to enable the response (headers) of the rejected automatic redirect to be returned + // rather than reporting an error "WinHttpReceiveResponse: 12156: The HTTP redirect request failed". + DWORD maxRedirects = client_config().max_redirects() < MAXDWORD - 2 + ? static_cast(client_config().max_redirects() + 2) + : MAXDWORD; + // Therefore, effective max redirects + winhttp_context->m_remaining_redirects = maxRedirects - 2; + + if (!WinHttpSetOption(winhttp_context->m_request_handle, + WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS, + &maxRedirects, + sizeof(maxRedirects))) + { + auto errorCode = GetLastError(); + request->report_error(errorCode, build_error_msg(errorCode, "Setting max automatic redirects")); + return; + } + + // (Dis)allow HTTPS to HTTP redirects. + DWORD redirectPolicy = client_config().https_to_http_redirects() + ? WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS + : WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP; + if (!WinHttpSetOption(winhttp_context->m_request_handle, + WINHTTP_OPTION_REDIRECT_POLICY, + &redirectPolicy, + sizeof(redirectPolicy))) + { + auto errorCode = GetLastError(); + request->report_error(errorCode, build_error_msg(errorCode, "Setting redirect policy")); + return; + } + } +#endif + size_t content_length; try { @@ -1974,11 +2036,17 @@ class winhttp_client final : public _http_client_communicator } return; } - case WINHTTP_CALLBACK_STATUS_SENDING_REQUEST: p_request_context->on_send_request_validate_cn(); return; + case WINHTTP_CALLBACK_STATUS_SENDING_REQUEST: + { + p_request_context->on_send_request_validate_cn(); + return; + } case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE: + { p_request_context->report_exception(web::http::http_exception( generate_security_failure_message(*reinterpret_cast(statusInfo)))); return; + } case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE: { DWORD bytesWritten = *((DWORD*)statusInfo); @@ -2026,6 +2094,49 @@ class winhttp_client final : public _http_client_communicator } return; } + case WINHTTP_CALLBACK_STATUS_REDIRECT: + { + // Return and continue unless that's too many automatic redirects. + if (p_request_context->m_remaining_redirects > 0) + { + --p_request_context->m_remaining_redirects; + return; + } + + // First need to query to see what the headers size is. + DWORD headerBufferLength = 0; + query_header_length(hRequestHandle, WINHTTP_QUERY_RAW_HEADERS_CRLF, headerBufferLength); + + // Now allocate buffer for headers and query for them. + std::vector header_raw_buffer; + header_raw_buffer.resize(headerBufferLength); + utility::char_t* header_buffer = reinterpret_cast(&header_raw_buffer[0]); + if (!WinHttpQueryHeaders(hRequestHandle, + WINHTTP_QUERY_RAW_HEADERS_CRLF, + WINHTTP_HEADER_NAME_BY_INDEX, + header_buffer, + &headerBufferLength, + WINHTTP_NO_HEADER_INDEX)) + { + auto errorCode = GetLastError(); + p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpQueryHeaders")); + return; + } + + http_response& response = p_request_context->m_response; + parse_winhttp_headers(hRequestHandle, header_buffer, response); + + // Signal that the headers are available. + p_request_context->complete_headers(); + + // The body of the message is unavailable in WINHTTP_CALLBACK_STATUS_REDIRECT. + p_request_context->allocate_request_space(nullptr, 0); + p_request_context->complete_request(0); + + // Cancel the WinHTTP operation by closing the handle. + p_request_context->cleanup(); + return; + } case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE: { // First need to query to see what the headers size is. @@ -2045,7 +2156,6 @@ class winhttp_client final : public _http_client_communicator { auto errorCode = GetLastError(); p_request_context->report_error(errorCode, build_error_msg(errorCode, "WinHttpQueryHeaders")); - ; return; } diff --git a/Release/tests/common/TestRunner/CMakeLists.txt b/Release/tests/common/TestRunner/CMakeLists.txt index 59b720d24c..48540d579a 100644 --- a/Release/tests/common/TestRunner/CMakeLists.txt +++ b/Release/tests/common/TestRunner/CMakeLists.txt @@ -8,6 +8,9 @@ endif() add_executable(test_runner test_runner.cpp test_module_loader.cpp) target_link_libraries(test_runner PRIVATE unittestpp ${CMAKE_DL_LIBS}) +if (WIN32) + target_sources(test_runner PRIVATE test_runner.manifest) +endif() if(BUILD_SHARED_LIBS AND NOT TEST_LIBRARY_TARGET_TYPE STREQUAL "OBJECT") elseif(APPLE) diff --git a/Release/tests/common/TestRunner/test_runner.manifest b/Release/tests/common/TestRunner/test_runner.manifest new file mode 100644 index 0000000000..5621c557d6 --- /dev/null +++ b/Release/tests/common/TestRunner/test_runner.manifest @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/Release/tests/functional/http/client/CMakeLists.txt b/Release/tests/functional/http/client/CMakeLists.txt index 635e7da843..3e1a93635a 100644 --- a/Release/tests/functional/http/client/CMakeLists.txt +++ b/Release/tests/functional/http/client/CMakeLists.txt @@ -16,6 +16,7 @@ set(SOURCES pipeline_stage_tests.cpp progress_handler_tests.cpp proxy_tests.cpp + redirect_tests.cpp request_helper_tests.cpp request_stream_tests.cpp request_uri_tests.cpp diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index 1b3f64a4ca..439772c72d 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -50,14 +50,12 @@ SUITE(outside_tests) // CNN's main page doesn't use chunked transfer encoding. http_response response = client.request(methods::GET).get(); - auto code = response.status_code(); - VERIFY_IS_TRUE(code == status_codes::OK || code == status_codes::MovedPermanently); + VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); response.content_ready().wait(); // CNN's other pages do use chunked transfer encoding. response = client.request(methods::GET, U("us")).get(); - code = response.status_code(); - VERIFY_IS_TRUE(code == status_codes::OK || code == status_codes::MovedPermanently); + VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); response.content_ready().wait(); }); } @@ -248,10 +246,7 @@ SUITE(outside_tests) http_request req(methods::GET); req.headers().add(U("Host"), U("en.wikipedia.org")); auto response = client.request(req).get(); - // WinHTTP will transparently follow the HTTP 301 upgrade request redirect, - // ASIO does not and will return the 301 directly. - const auto statusCode = response.status_code(); - CHECK(statusCode == status_codes::OK || statusCode == status_codes::MovedPermanently); + VERIFY_ARE_EQUAL(status_codes::OK, response.status_code()); } #endif // !defined(__cplusplus_winrt) && !defined(CPPREST_FORCE_HTTP_CLIENT_WINHTTPPAL) diff --git a/Release/tests/functional/http/client/redirect_tests.cpp b/Release/tests/functional/http/client/redirect_tests.cpp new file mode 100644 index 0000000000..a9d4179450 --- /dev/null +++ b/Release/tests/functional/http/client/redirect_tests.cpp @@ -0,0 +1,342 @@ +/*** + * Copyright (C) Microsoft. All rights reserved. + * Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. + * + * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ + * + * Tests cases for multiple requests and responses from an http_client. + * + * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + ****/ + +#include "stdafx.h" +#ifdef _WIN32 +#include +#include +#endif // _WIN32 + +using namespace web::http; +using namespace web::http::client; + +using namespace tests::functional::http::utilities; + +#if defined(_WIN32) && !defined(CPPREST_FORCE_HTTP_CLIENT_ASIO) +#define USING_WINHTTP 1 +#else +#define USING_WINHTTP 0 +#endif + +namespace tests +{ +namespace functional +{ +namespace http +{ +namespace client +{ +pplx::task next_reply_assert( + test_http_server* p_server, + const method& method, + const utility::string_t& path, + status_code code = status_codes::OK, + const utility::string_t& location = U("")) +{ + return p_server->next_request().then([=](test_request* p_request) { + http_asserts::assert_test_request_equals(p_request, method, path); + size_t content_length; + VERIFY_ARE_EQUAL(methods::POST == method, + p_request->match_header(header_names::content_length, content_length)); + + std::map headers; + if (!location.empty()) + { + headers[header_names::location] = location; + } + + // web::http::details::get_default_reason_phrase is internal :-/ + p_request->reply(code, {}, headers); + }); +} + +pplx::task next_reply_assert( + test_http_server* p_server, + const utility::string_t& path, + status_code code = status_codes::OK, + const utility::string_t& location = U("")) +{ + return next_reply_assert(p_server, methods::GET, path, code, location); +} + +SUITE(redirect_tests) +{ + TEST_FIXTURE(uri_address, follows_multiple_redirects_by_default) + { + test_http_server::scoped_server scoped(m_uri); + auto p_server = scoped.server(); + + std::vector> replies; + replies.push_back(next_reply_assert(p_server, U("/"), status_codes::MovedPermanently, U("/moved-here"))); + replies.push_back(next_reply_assert(p_server, U("/moved-here"), status_codes::TemporaryRedirect, U("/moved-there"))); + replies.push_back(next_reply_assert(p_server, U("/moved-there"), status_codes::Found, U("/found-elsewhere"))); + replies.push_back(next_reply_assert(p_server, U("/found-elsewhere"))); + + http_client_config config; + http_client client(m_uri, config); + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::OK) + ); + p_server->close(); + for (auto& reply : replies) + { + VERIFY_NO_THROWS(reply.get()); + } + } + + TEST_FIXTURE(uri_address, follows_retrieval_redirect) + { + test_http_server::scoped_server scoped(m_uri); + auto p_server = scoped.server(); + + std::vector> replies; + replies.push_back(next_reply_assert(p_server, methods::POST, U("/"), status_codes::SeeOther, U("/see-here"))); + replies.push_back(next_reply_assert(p_server, methods::GET, U("/see-here"))); + + http_client_config config; + http_client client(m_uri, config); + + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::POST, U(""), U("body")).get(), status_codes::OK); + ); + p_server->close(); + for (auto& reply : replies) + { + VERIFY_NO_THROWS(reply.get()); + } + } + + TEST_FIXTURE(uri_address, obeys_max_redirects) + { + test_http_server::scoped_server scoped(m_uri); + auto p_server = scoped.server(); + + std::vector> replies; + replies.push_back(next_reply_assert(p_server, U("/"), status_codes::MovedPermanently, U("/moved-here"))); + replies.push_back(next_reply_assert(p_server, U("/moved-here"), status_codes::TemporaryRedirect, U("/moved-there"))); + replies.push_back(next_reply_assert(p_server, U("/moved-there"), status_codes::Found, U("/found-elsewhere"))); + + http_client_config config; + config.set_max_redirects(2); + http_client client(m_uri, config); + + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::Found) + ); + p_server->close(); + for (auto& reply : replies) + { + VERIFY_NO_THROWS(reply.get()); + } + } + + TEST_FIXTURE(uri_address, can_disable_redirects) + { + test_http_server::scoped_server scoped(m_uri); + auto p_server = scoped.server(); + + std::vector> replies; + replies.push_back(next_reply_assert(p_server, U("/"), status_codes::MovedPermanently, U("/moved-here"))); + + http_client_config config; + config.set_max_redirects(0); + http_client client(m_uri, config); + + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::MovedPermanently) + ); + p_server->close(); + for (auto& reply : replies) + { + VERIFY_NO_THROWS(reply.get()); + } + } + + TEST(does_not_follow_https_to_http_by_default) + { + handle_timeout([] { + http_client_config config; + http_client client(U("https://http.badssl.com/"), config); + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::MovedPermanently) + ); + }); + } + + TEST(can_follow_https_to_http) + { + handle_timeout([] { + http_client_config config; + config.set_https_to_http_redirects(true); + http_client client(U("https://http.badssl.com/"), config); + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::OK) + ); + }); + } + + TEST_FIXTURE(uri_address, follows_permanent_redirect) + { +#if USING_WINHTTP + // note that 308 Permanent Redirect is only supported by WinHTTP from Windows 10 + if (!IsWindows10OrGreater()) { + return; + } +#endif // USING_WINHTTP + test_http_server::scoped_server scoped(m_uri); + auto p_server = scoped.server(); + + std::vector> replies; + replies.push_back(next_reply_assert(p_server, U("/"), status_codes::PermanentRedirect, U("/moved-here"))); + replies.push_back(next_reply_assert(p_server, U("/moved-here"))); + + http_client_config config; + http_client client(m_uri, config); + + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::OK) + ); + p_server->close(); + for (auto& reply : replies) + { + VERIFY_NO_THROWS(reply.get()); + } + } + + TEST_FIXTURE(uri_address, may_throw_if_no_location) + { + test_http_server::scoped_server scoped(m_uri); + auto p_server = scoped.server(); + + std::vector> replies; + replies.push_back(next_reply_assert(p_server, U("/"), status_codes::MovedPermanently)); + + http_client_config config; + http_client client(m_uri, config); + + // implementation-specific behaviour +#if USING_WINHTTP + VERIFY_THROWS( + client.request(methods::GET).get(), + http_exception + ); +#else + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::MovedPermanently) + ); +#endif + p_server->close(); + for (auto& reply : replies) + { + VERIFY_NO_THROWS(reply.get()); + } + } + + TEST_FIXTURE(uri_address, should_not_follow_cyclic_redirect) + { + test_http_server::scoped_server scoped(m_uri); + auto p_server = scoped.server(); + + std::vector> replies; + replies.push_back(next_reply_assert(p_server, U("/"), status_codes::TemporaryRedirect, U("/briefly-here"))); + replies.push_back(next_reply_assert(p_server, U("/briefly-here"), status_codes::MovedPermanently, U("/"))); +#if USING_WINHTTP + replies.push_back(next_reply_assert(p_server, U("/"), status_codes::NotFound)); +#endif + + http_client_config config; + http_client client(m_uri, config); + + // implementation-specific behaviour +#if USING_WINHTTP + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::NotFound) + ); +#else // ^^^ USING_WINHTTP / !USING_WINHTTP vvv + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::MovedPermanently) + ); +#endif // USING_WINHTTP + p_server->close(); + for (auto& reply : replies) + { + VERIFY_NO_THROWS(reply.get()); + } + } + + TEST_FIXTURE(uri_address, may_follow_unchanged_redirect) + { + test_http_server::scoped_server scoped(m_uri); + auto p_server = scoped.server(); + + std::vector> replies; + replies.push_back(next_reply_assert(p_server, methods::POST, U("/"), status_codes::TemporaryRedirect, U("/retry-here"))); +#if USING_WINHTTP + replies.push_back(next_reply_assert(p_server, methods::POST, U("/retry-here"))); +#endif + + http_client_config config; + http_client client(m_uri, config); + + // implementation-specific behaviour +#if USING_WINHTTP + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::POST, U(""), U("body")).get(), status_codes::OK) + ); +#else // ^^^ USING_WINHTTP / !USING_WINHTTP vvv + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::POST, U(""), U("body")).get(), status_codes::TemporaryRedirect) + ); +#endif // USING_WINHTTP + p_server->close(); + for (auto& reply : replies) + { + VERIFY_NO_THROWS(reply.get()); + } + } + + TEST_FIXTURE(uri_address, may_not_follow_manual_redirect) + { + test_http_server::scoped_server scoped(m_uri); + auto p_server = scoped.server(); + + std::vector> replies; + replies.push_back(next_reply_assert(p_server, U("/"), status_codes::MultipleChoices, U("/prefer-here"))); +#if USING_WINHTTP + replies.push_back(next_reply_assert(p_server, U("/prefer-here"))); +#endif + + http_client_config config; + http_client client(m_uri, config); + + // implementation-specific behaviour +#if USING_WINHTTP + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::OK) + ); +#else // ^^^ USING_WINHTTP / !USING_WINHTTP vvv + VERIFY_NO_THROWS( + http_asserts::assert_response_equals(client.request(methods::GET).get(), status_codes::MultipleChoices) + ); +#endif // USING_WINHTTP + p_server->close(); + for (auto& reply : replies) + { + VERIFY_NO_THROWS(reply.get()); + } + } + +} // SUITE(redirect_tests) + +} // namespace client +} // namespace http +} // namespace functional +} // namespace tests From e18f6f2f90f34d3315c76310ee286986dc1ce55f Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Fri, 24 Apr 2020 00:50:54 +0100 Subject: [PATCH 48/80] Fix compilation with GCC 4.8/4.9, which was broken by commit 53fab3aa124eb712c0d5c4861438ecdbc5b5c2d5. (#1379) --- Release/src/json/json_parsing.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Release/src/json/json_parsing.cpp b/Release/src/json/json_parsing.cpp index a026ecaba2..cdef44287f 100644 --- a/Release/src/json/json_parsing.cpp +++ b/Release/src/json/json_parsing.cpp @@ -1040,7 +1040,7 @@ std::unique_ptr JSON_Parser::_ParseArray( case JSON_Parser::Token::TKN_CloseBracket: GetNextToken(tkn); if (tkn.m_error) return utility::details::make_unique(); - return result; + return std::unique_ptr(result.release()); default: SetErrorCode(tkn, json_error::malformed_array_literal); return utility::details::make_unique(); @@ -1058,6 +1058,7 @@ template std::unique_ptr JSON_Parser::_ParseValue( typename JSON_Parser::Token& tkn) { + typedef std::unique_ptr Vptr; switch (tkn.kind) { case JSON_Parser::Token::TKN_OpenBrace: @@ -1070,7 +1071,7 @@ std::unique_ptr JSON_Parser::_ParseValue( } case JSON_Parser::Token::TKN_StringLiteral: { - auto value = utility::details::make_unique(std::move(tkn.string_val), + Vptr value = utility::details::make_unique(std::move(tkn.string_val), tkn.has_unescape_symbol); GetNextToken(tkn); if (tkn.m_error) return utility::details::make_unique(); @@ -1078,7 +1079,7 @@ std::unique_ptr JSON_Parser::_ParseValue( } case JSON_Parser::Token::TKN_IntegerLiteral: { - std::unique_ptr value; + Vptr value; if (tkn.signed_number) value = utility::details::make_unique(tkn.int64_val); else @@ -1090,14 +1091,14 @@ std::unique_ptr JSON_Parser::_ParseValue( } case JSON_Parser::Token::TKN_NumberLiteral: { - auto value = utility::details::make_unique(tkn.double_val); + Vptr value = utility::details::make_unique(tkn.double_val); GetNextToken(tkn); if (tkn.m_error) return utility::details::make_unique(); return value; } case JSON_Parser::Token::TKN_BooleanLiteral: { - auto value = utility::details::make_unique(tkn.boolean_val); + Vptr value = utility::details::make_unique(tkn.boolean_val); GetNextToken(tkn); if (tkn.m_error) return utility::details::make_unique(); return value; From 538dd497bcf86a6ab56d40c94694b56aa19320ad Mon Sep 17 00:00:00 2001 From: Gareth Sylvester-Bradley <31761158+garethsb-sony@users.noreply.github.com> Date: Fri, 24 Apr 2020 00:51:31 +0100 Subject: [PATCH 49/80] Do not report errors (such as EBADF and EINVAL) from setsockopt here, since this is a performance optimization only, and hard errors will be picked up by the following operation (#1393) --- Release/src/http/client/http_client_asio.cpp | 3 ++- Release/src/http/listener/http_server_asio.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 7ae7e9921f..07bb4885bf 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -333,7 +333,8 @@ class asio_connection void enable_no_delay() { boost::asio::ip::tcp::no_delay option(true); - m_socket.set_option(option); + boost::system::error_code error_ignored; + m_socket.set_option(option, error_ignored); } private: diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index 5b392012df..e83b9ff525 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -594,7 +594,8 @@ void hostport_listener::on_accept(std::unique_ptr socket, const if (!ec) { boost::asio::ip::tcp::no_delay option(true); - socket->set_option(option); + boost::system::error_code error_ignored; + socket->set_option(option, error_ignored); auto conn = asio_server_connection::create(std::move(socket), m_p_server, this); From b07011d3ab391ab6f22d1f5a9f10113943c3e218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20St=C3=B6ggl?= Date: Fri, 24 Apr 2020 04:13:27 +0200 Subject: [PATCH 50/80] Update submodule websocketpp to 0.8.2 (#1392) * Update submodule websocketpp to 0.8.2 - Update to WebSocket++/0.8.2 commit 56123c87598f8b1dd471be83ca841ceae07f95ba - Fixes build issues with boost 1.70 and newer * Update vcpkg. * Remove defunct VS2015 configurations. Co-authored-by: Billy Robert O'Neal III --- Release/libs/websocketpp | 2 +- azure-pipelines.yml | 10 ---------- vcpkg | 2 +- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/Release/libs/websocketpp b/Release/libs/websocketpp index c6d7e295bf..56123c8759 160000 --- a/Release/libs/websocketpp +++ b/Release/libs/websocketpp @@ -1 +1 @@ -Subproject commit c6d7e295bf5a0ab9b5f896720cc1a0e0fdc397a7 +Subproject commit 56123c87598f8b1dd471be83ca841ceae07f95ba diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a78d0ac829..05f20d6f80 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -21,16 +21,6 @@ jobs: name: 'Windows_VS2017_x64' targetPlatform: x64 image: 'vs2017-win2016' - - template: azure-devops/build-windows.yml - parameters: - name: 'Windows_VS2015_x86' - targetPlatform: x86 - image: 'vs2015-win2012r2' - - template: azure-devops/build-windows.yml - parameters: - name: 'Windows_VS2015_x64' - targetPlatform: x64 - image: 'vs2015-win2012r2' - job: Windows_VS2019_UWP pool: vmImage: 'windows-latest' diff --git a/vcpkg b/vcpkg index ef60f1d9b9..6709d3d7d0 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit ef60f1d9b97fab6fcc61651936196866bb6553d0 +Subproject commit 6709d3d7d0cba96508ba3606f810ab562ea32556 From 319dd31f7ba8752683aaab2679a1c8fefcf48ef3 Mon Sep 17 00:00:00 2001 From: Clovis Durand Date: Sat, 25 Apr 2020 01:53:50 +0200 Subject: [PATCH 51/80] CMake fixes + CMake search for OpenSSL (macOS) (#1383) Signed-off-by: Clovis Durand Co-authored-by: Billy Robert O'Neal III --- Build_iOS/CMakeLists.txt | 2 +- CMakeLists.txt | 2 +- README.md | 2 +- Release/CMakeLists.txt | 2 +- Release/cmake/cpprest_find_openssl.cmake | 4 +- .../cmake/cpprestsdk-config-version.in.cmake | 10 ++ Release/cmake/cpprestsdk-config.in.cmake | 2 +- Release/src/CMakeLists.txt | 9 +- azure-devops/build-windows.yml | 5 - azure-pipelines.yml | 162 +++++++++--------- 10 files changed, 106 insertions(+), 94 deletions(-) create mode 100644 Release/cmake/cpprestsdk-config-version.in.cmake diff --git a/Build_iOS/CMakeLists.txt b/Build_iOS/CMakeLists.txt index 0cf1b62467..f5c5bae75a 100644 --- a/Build_iOS/CMakeLists.txt +++ b/Build_iOS/CMakeLists.txt @@ -1,5 +1,5 @@ project(casablanca-ios NONE) -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.9) enable_testing() diff --git a/CMakeLists.txt b/CMakeLists.txt index d010e21fcd..4e0377ef27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.9) project(cpprestsdk-root NONE) enable_testing() add_subdirectory(Release) diff --git a/README.md b/README.md index 09cf148dcf..a1f46ab4fb 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Once you have the library, look at our [tutorial](https://github.com/Microsoft/c To use from CMake: ```cmake -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.9) project(main) find_package(cpprestsdk REQUIRED) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 18b0cb3f48..e495bd391b 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -1,5 +1,5 @@ set(CMAKE_LEGACY_CYGWIN_WIN32 0) -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.9) if(POLICY CMP0042) cmake_policy(SET CMP0042 NEW) # use MACOSX_RPATH endif() diff --git a/Release/cmake/cpprest_find_openssl.cmake b/Release/cmake/cpprest_find_openssl.cmake index 57e43a2fb7..9333663607 100644 --- a/Release/cmake/cpprest_find_openssl.cmake +++ b/Release/cmake/cpprest_find_openssl.cmake @@ -34,11 +34,13 @@ function(cpprest_find_openssl) if(APPLE) if(NOT DEFINED OPENSSL_ROOT_DIR) # Prefer a homebrew version of OpenSSL over the one in /usr/lib - file(GLOB OPENSSL_ROOT_DIR /usr/local/Cellar/openssl/*) + file(GLOB OPENSSL_ROOT_DIR /usr/local/Cellar/openssl*/*) # Prefer the latest (make the latest one first) list(REVERSE OPENSSL_ROOT_DIR) + list(GET OPENSSL_ROOT_DIR 0 OPENSSL_ROOT_DIR) endif() # This should prevent linking against the system provided 0.9.8y + message(STATUS "OPENSSL_ROOT_DIR = ${OPENSSL_ROOT_DIR}") set(_OPENSSL_VERSION "") endif() if(UNIX) diff --git a/Release/cmake/cpprestsdk-config-version.in.cmake b/Release/cmake/cpprestsdk-config-version.in.cmake new file mode 100644 index 0000000000..017879c58f --- /dev/null +++ b/Release/cmake/cpprestsdk-config-version.in.cmake @@ -0,0 +1,10 @@ +set(PACKAGE_VERSION @CPPREST_VERSION_MAJOR@.@CPPREST_VERSION_MINOR@.@CPPREST_VERSION_REVISION@) + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) +endif(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) diff --git a/Release/cmake/cpprestsdk-config.in.cmake b/Release/cmake/cpprestsdk-config.in.cmake index be95abf99a..72476b062d 100644 --- a/Release/cmake/cpprestsdk-config.in.cmake +++ b/Release/cmake/cpprestsdk-config.in.cmake @@ -15,7 +15,7 @@ if(@CPPREST_USES_WINHTTPPAL@) find_dependency(WINHTTPPAL) endif() -if(@CPPREST_USES_BOOST@ AND OFF) +if(@CPPREST_USES_BOOST@) if(UNIX) find_dependency(Boost COMPONENTS random system thread filesystem chrono atomic date_time regex) else() diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index 1c40257c47..a2d4d30b64 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -236,9 +236,9 @@ else() endif() if(CPPREST_INSTALL_HEADERS) - install(FILES ${HEADERS_CPPREST} DESTINATION include/cpprest) - install(FILES ${HEADERS_PPLX} DESTINATION include/pplx) - install(FILES ${HEADERS_DETAILS} DESTINATION include/cpprest/details) + install(FILES ${HEADERS_CPPREST} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpprest) + install(FILES ${HEADERS_PPLX} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pplx) + install(FILES ${HEADERS_DETAILS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpprest/details) endif() if(CPPREST_INSTALL) @@ -281,9 +281,10 @@ if(CPPREST_INSTALL) ) configure_file(../cmake/cpprestsdk-config.in.cmake "${CMAKE_CURRENT_BINARY_DIR}/cpprestsdk-config.cmake" @ONLY) + configure_file(../cmake/cpprestsdk-config-version.in.cmake "${CMAKE_CURRENT_BINARY_DIR}/cpprestsdk-config-version.cmake" @ONLY) install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/cpprestsdk-config.cmake" + FILES "${CMAKE_CURRENT_BINARY_DIR}/cpprestsdk-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/cpprestsdk-config-version.cmake" DESTINATION ${CMAKE_INSTALL_LIBDIR}/${CPPREST_EXPORT_DIR} ) install( diff --git a/azure-devops/build-windows.yml b/azure-devops/build-windows.yml index 2a5de3c509..45045ee907 100644 --- a/azure-devops/build-windows.yml +++ b/azure-devops/build-windows.yml @@ -13,11 +13,6 @@ jobs: steps: - script: git submodule update --init vcpkg displayName: Checkout vcpkg submodule - - task: CacheBeta@0 - displayName: Cache vcpkg - inputs: - key: $(vcpkgResponseFile) | $(Build.SourcesDirectory)/.git/modules/vcpkg/HEAD | ${{ parameters.targetPlatform }} | ${{ parameters.image }} - path: '$(vcpkgLocation)' - task: run-vcpkg@0 displayName: 'Run vcpkg' inputs: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 05f20d6f80..7df61d453a 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -68,85 +68,89 @@ jobs: export NCPU=2 ../configure.sh --ndk /usr/local/lib/android/sdk/ndk-bundle displayName: 'Build for Android' - # - job: MacOS_Homebrew - # pool: - # vmImage: 'macOS-latest' - # steps: - # - script: brew install boost openssl ninja - # displayName: Brew install dependencies - # - script: | - # mkdir build.debug - # mkdir build.release - # mkdir build.release.static - # displayName: Make Build Directories - # - task: CMake@1 - # inputs: - # workingDirectory: 'build.debug' - # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' - # - task: CMake@1 - # inputs: - # workingDirectory: 'build.release' - # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' - # - task: CMake@1 - # inputs: - # workingDirectory: 'build.release.static' - # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF ..' - # - script: | - # cd build.debug - # ninja - # displayName: 'Run ninja, debug' - # - script: | - # cd build.debug/Release/Binaries - # ./test_runner *test.dylib - # displayName: 'Run tests, debug' - # - script: | - # cd build.release - # ninja - # displayName: 'Run ninja, release' - # - script: | - # cd build.release/Release/Binaries - # ./test_runner *test.dylib - # displayName: 'Run tests, release' - # - script: | - # cd build.release.static - # ninja - # displayName: 'Run ninja, release static' - # - job: MacOS_Vcpkg - # pool: - # vmImage: 'macOS-latest' - # steps: - # - script: | - # ./vcpkg/bootstrap-vcpkg.sh - # ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg - # displayName: Vcpkg install dependencies - # - script: | - # mkdir build.debug - # mkdir build.release - # displayName: Make Build Directories - # - task: CMake@1 - # inputs: - # workingDirectory: 'build.debug' - # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' - # - task: CMake@1 - # inputs: - # workingDirectory: 'build.release' - # cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' - # - script: | - # cd build.debug - # ninja - # displayName: 'Run ninja debug' - # - script: | - # cd build.debug/Release/Binaries - # ./test_runner *test.dylib - # displayName: 'Run Tests debug' - # - script: | - # cd build.release - # ninja - # displayName: 'Run ninja, release' - # - script: | - # cd build.release/Release/Binaries - # ./test_runner *test.dylib - # displayName: 'Run tests, release' + - job: MacOS_Homebrew + pool: + vmImage: 'macOS-latest' + steps: + - script: brew install boost openssl ninja + displayName: Brew install dependencies + - script: git submodule update --init Release/libs/websocketpp + displayName: Checkout websocketpp submodule + - script: | + mkdir build.debug + mkdir build.release + mkdir build.release.static + displayName: Make Build Directories + - task: CMake@1 + inputs: + workingDirectory: 'build.debug' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Debug ..' + - task: CMake@1 + inputs: + workingDirectory: 'build.release' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release ..' + - task: CMake@1 + inputs: + workingDirectory: 'build.release.static' + cmakeArgs: '-G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF ..' + - script: | + cd build.debug + ninja + displayName: 'Run ninja, debug' + - script: | + cd build.debug/Release/Binaries + ./test_runner *test.dylib + displayName: 'Run tests, debug' + - script: | + cd build.release + ninja + displayName: 'Run ninja, release' + - script: | + cd build.release/Release/Binaries + ./test_runner *test.dylib + displayName: 'Run tests, release' + - script: | + cd build.release.static + ninja + displayName: 'Run ninja, release static' + - job: MacOS_Vcpkg + pool: + vmImage: 'macOS-latest' + steps: + - script: git submodule update --init vcpkg + displayName: Checkout vcpkg submodule + - script: | + ./vcpkg/bootstrap-vcpkg.sh + ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg + displayName: Vcpkg install dependencies + - script: | + mkdir build.debug + mkdir build.release + displayName: Make Build Directories + - task: CMake@1 + inputs: + workingDirectory: 'build.debug' + cmakeArgs: '-G Ninja -DCMAKE_MAKE_PROGRAM=$(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.0-osx/ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - task: CMake@1 + inputs: + workingDirectory: 'build.release' + cmakeArgs: '-G Ninja -DCMAKE_MAKE_PROGRAM=$(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.0-osx/ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + - script: | + cd build.debug + $(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.0-osx/ninja + displayName: 'Run ninja debug' + - script: | + cd build.debug/Release/Binaries + ./test_runner *test.dylib + displayName: 'Run Tests debug' + - script: | + cd build.release + $(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.0-osx/ninja + displayName: 'Run ninja, release' + - script: | + cd build.release/Release/Binaries + ./test_runner *test.dylib + displayName: 'Run tests, release' # - job: MacOS_iOS # pool: # vmImage: 'macOS-latest' From 18212a2a7967e12d740bfb957e500892b3463c88 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Fri, 24 Apr 2020 17:44:16 -0700 Subject: [PATCH 52/80] Mint v2.10.16. (#1395) --- Release/CMakeLists.txt | 2 +- Release/include/cpprest/version.h | 2 +- changelog.md | 13 +++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index e495bd391b..13a3f01db8 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 15) +set(CPPREST_VERSION_REVISION 16) enable_testing() diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index b505f1b9e3..0bffcc2a6b 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -5,6 +5,6 @@ */ #define CPPREST_VERSION_MINOR 10 #define CPPREST_VERSION_MAJOR 2 -#define CPPREST_VERSION_REVISION 15 +#define CPPREST_VERSION_REVISION 16 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR * 100000 + CPPREST_VERSION_MINOR * 100 + CPPREST_VERSION_REVISION) diff --git a/changelog.md b/changelog.md index d5a44eb6b9..4c9bb6f123 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,16 @@ +cpprestsdk (2.10.16) +* PR#1383 CMake fixes + CMake search for OpenSSL (macOS) +* PR#1392 Update submodule websocketpp to 0.8.2 +* PR#1393 Do not report errors (such as EBADF and EINVAL) from setsockopt here, since this is a performance optimization only, and hard errors will be picked up by the following operation +* PR#1379 Fix compilation with GCC 4.8/4.9, which was broken by commit 53fab3a. +* PR#1328 Add support for HTTP redirection in ASIO and WinHTTP-based http_clients +* PR#1332 Fix more http test build fails in certain configurations +* PR#1370 Remove redundant std::move noted by gcc 9.2 (-Wredundant-move) +* PR#1372 Static analyzer (PVS Studio) fixes +* PR#1350 Expose json::value::parse for UTF8 string on Windows +* PR#1344 libcpprestsdk: fix building as a static library +-- cpprestsdk team FRI, 24 Apr 2020 16:56:00 -0700 + cpprestsdk (2.10.15) * Extremely special thanks to @garethsb-sony for a large number of contributions in this release * PR#1209 Workarounds for two GCC 4.7.2 bugs with lambda functions From 7fbb08c491f9c8888cc0f3d86962acb3af672772 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Sun, 10 May 2020 16:29:07 -0700 Subject: [PATCH 53/80] Delete apparently broken .vcxprojs and .pfxes. (#1415) --- .../BlackJack_UIClient140.vcxproj | 181 ----------------- .../BlackJack_UIClient141.vcxproj | 191 ------------------ .../BlackJack_UIClient_TemporaryKey.pfx | Bin 2541 -> 0 bytes .../CasaLens/CasaLens140/CasaLens140.vcxproj | 168 --------------- .../CasaLens/CasaLens141/CasaLens141.vcxproj | 169 ---------------- .../FacebookDemo/FacebookDemo140.vcxproj | 182 ----------------- .../FacebookDemo/FacebookDemo141.vcxproj | 184 ----------------- .../FacebookDemo_TemporaryKey.pfx | Bin 2549 -> 0 bytes .../samples/OAuth2Live/OAuth2Live140.vcxproj | 188 ----------------- .../samples/OAuth2Live/OAuth2Live141.vcxproj | 190 ----------------- .../OAuth2Live/OAuth2Live_TemporaryKey.pfx | Bin 2549 -> 0 bytes Release/samples/Regenerate-Certificates.ps1 | 34 ---- .../WindowsLiveAuth140.vcxproj | 189 ----------------- .../WindowsLiveAuth141.vcxproj | 191 ------------------ .../WindowsLiveAuth_TemporaryKey.pfx | Bin 2549 -> 0 bytes 15 files changed, 1867 deletions(-) delete mode 100644 Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient140.vcxproj delete mode 100644 Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient141.vcxproj delete mode 100644 Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient_TemporaryKey.pfx delete mode 100644 Release/samples/CasaLens/CasaLens140/CasaLens140.vcxproj delete mode 100644 Release/samples/CasaLens/CasaLens141/CasaLens141.vcxproj delete mode 100644 Release/samples/FacebookDemo/FacebookDemo140.vcxproj delete mode 100644 Release/samples/FacebookDemo/FacebookDemo141.vcxproj delete mode 100644 Release/samples/FacebookDemo/FacebookDemo_TemporaryKey.pfx delete mode 100644 Release/samples/OAuth2Live/OAuth2Live140.vcxproj delete mode 100644 Release/samples/OAuth2Live/OAuth2Live141.vcxproj delete mode 100644 Release/samples/OAuth2Live/OAuth2Live_TemporaryKey.pfx delete mode 100644 Release/samples/Regenerate-Certificates.ps1 delete mode 100644 Release/samples/WindowsLiveAuth/WindowsLiveAuth140.vcxproj delete mode 100644 Release/samples/WindowsLiveAuth/WindowsLiveAuth141.vcxproj delete mode 100644 Release/samples/WindowsLiveAuth/WindowsLiveAuth_TemporaryKey.pfx diff --git a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient140.vcxproj b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient140.vcxproj deleted file mode 100644 index 2a0c920c4b..0000000000 --- a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient140.vcxproj +++ /dev/null @@ -1,181 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {b8d3f85b-da71-4aca-87ba-10fed681dc79} - BlackJack_UIClient - en-US - 12.0 - true - SAK - SAK - SAK - SAK - Windows Store - 8.1 - - - - Application - true - v140 - - - Application - true - v140 - - - Application - true - v140 - - - Application - false - true - v140 - - - Application - false - true - v140 - - - Application - false - true - v140 - - - - - - - - - - - - - - - - - - - - - - - - - - BlackJack_UIClient_TemporaryKey.pfx - - - - pch.h - WIN32;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);%(AdditionalIncludeDirectories) - 4100;4267;4450;4453;4702;%(DisableSpecificWarnings) - - - - $(OutDir)\$(MSBuildProjectName)\ - 5C945ED108BF1723994A90F9BAA4B7D93FBE0E47 - - - - CardShape.xaml - - - - App.xaml - - - Player.xaml - - - PlayingTable.xaml - - - - - Designer - - - - Designer - - - - - - - Designer - - - - - - - - - - - - - App.xaml - - - CardShape.xaml - - - Create - Create - Create - Create - Create - Create - - - Player.xaml - - - PlayingTable.xaml - - - - - {198ED804-2655-4D92-8104-C220E3EA9452} - - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient141.vcxproj b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient141.vcxproj deleted file mode 100644 index 9fd3069aa1..0000000000 --- a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient141.vcxproj +++ /dev/null @@ -1,191 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {b8d3f85b-da71-4aca-87ba-10fed681dc79} - BlackJack_UIClient - en-US - 14.0 - true - SAK - SAK - SAK - SAK - Windows Store - 10.0 - 10.0.16299.0 - 10.0.16299.0 - - - - Application - true - v141 - - - Application - true - v141 - - - Application - true - v141 - - - Application - false - true - v141 - - - Application - false - true - v141 - - - Application - false - true - v141 - - - - - - - - - - - - - - - - - - - - - - - - - - BlackJack_UIClient_TemporaryKey.pfx - - - - pch.h - WIN32;%(PreprocessorDefinitions) - $(CasablancaIncludeDir);%(AdditionalIncludeDirectories) - 4100;4267;4450;4453;4702;%(DisableSpecificWarnings) - /Zm150 %(AdditionalOptions) - /Zm150 %(AdditionalOptions) - /Zm150 %(AdditionalOptions) - /Zm150 %(AdditionalOptions) - /Zm150 %(AdditionalOptions) - /Zm150 %(AdditionalOptions) - - - - $(OutDir)\$(MSBuildProjectName)\ - 5C945ED108BF1723994A90F9BAA4B7D93FBE0E47 - - - - CardShape.xaml - - - - App.xaml - - - Player.xaml - - - PlayingTable.xaml - - - - - Designer - - - - Designer - - - - - - - - - - - - - - - - - App.xaml - - - CardShape.xaml - - - Create - Create - Create - Create - Create - Create - - - Player.xaml - - - PlayingTable.xaml - - - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - Designer - - - - \ No newline at end of file diff --git a/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient_TemporaryKey.pfx b/Release/samples/BlackJack/BlackJack_UIClient/BlackJack_UIClient_TemporaryKey.pfx deleted file mode 100644 index 53921885f20a243ad8dbdf408108392de342babd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2541 zcmai02{e>#8-8bJFf%a{vKM8jcWgr?WC<;X@Rgzwk}PB26K|HH5(a~^Dk)tlzhy)|qF*&qda91L9b(`BGUkA%qlVvwg;86}9^jYlJLvhRd8su|sF+ zv$v|*j0;k_d)(Xg9Wg)Hah;h3`YQ&ky2Dmcs-~ds6aJh@henIQ-gToe=VOP8B81*6 z6OE>$!sONoBo_kLY@BueCqt;bfPSvv(>`Kg8*+&|R$?{Js(fDLPL1@jbTQ9~A5IRj@=OyB0=00pZ`X#^jrHG_fXNN7{manMhO*m(_adXx_7)%}i zFtxW!->iZBlv2W16-9iP7|Sv~*z#&`>(3S~neyEzw`IKx28@f?)gKyczm$iDhr@((H zH+L$9by*}y;?jieKqX;l%i8_!33Yb2agW zS&ZH^i$x)~&o`M0rZP=VkDbK)r0+lQ@oaBY%Ts#5e<^&^?VXye;k2tRLwzd>hree`(1ONb_EtZ#pMW7K7Z4-h@mplp_0bBqFz#Cu! zKCqnyd;w|T82sHpJOF1n(ue&Zz!S!paO@4(!~VIyRMG(bFP=XfIRZ|AH|X@=nq=y6 zNo$zk54ZxBfIBSO15?z1Gk^-5LJcme4k!Z}fEMhl!k!vjTm@drfF|r|!fOKqVg4DI z1p-vqXt2@|a0DS#^sho2;{g?bhEP5*%!JMLpECdjZ|cLK&aVl;yLm&f8x~MtTmgiT z#B3B2fkcw78O;Q}No}}p(pp7HqbtsU0>6qN1TX+7NF{*;EXoRv62kfTI@|j?`GArl z0#pqul?s9&RYRR>1BbL_p%l(kxy80rY_4vxS-EUFdv3Bg3=O&mSrG?@8x7@Cg2~3LDe5TDLCdKaaa-+8-e+#w}H^e0eU_JbB zUEAJusHn-66Pff1`CUK3E;HCy^tsbfXE9113)7DwqsJ}r#p!b1$!b#`t^j2!L4yL&! zwO6~(B;Cm&|E?X-|LZ&490Xu*FY8f1dGi&&l>A9^U5%b%dDjEub>FH>1;tryJN%kP z30d;RYw0g~qF1y}zqi*7Xd5z2eua*0!~o*mh0SOB@(7DZ*6F#4!M@=Knccf$nk-@r zzh$X$cDme5&RshMs@9&enpcIJ1VkiU@QVdN_HBc?=^?9iJvgzZc=LuzFDMr3k dXtJzj5$T|lbib(TO%F3OlAb>PJALEf^(TEKCr|(Y diff --git a/Release/samples/CasaLens/CasaLens140/CasaLens140.vcxproj b/Release/samples/CasaLens/CasaLens140/CasaLens140.vcxproj deleted file mode 100644 index 5034ead2da..0000000000 --- a/Release/samples/CasaLens/CasaLens140/CasaLens140.vcxproj +++ /dev/null @@ -1,168 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - - - - Application - true - NotSet - v140 - - - Application - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - Application - false - true - NotSet - v140 - - - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/samples/CasaLens/CasaLens141/CasaLens141.vcxproj b/Release/samples/CasaLens/CasaLens141/CasaLens141.vcxproj deleted file mode 100644 index e43ab1b904..0000000000 --- a/Release/samples/CasaLens/CasaLens141/CasaLens141.vcxproj +++ /dev/null @@ -1,169 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {FFBFD6C1-B525-4D35-AB64-A2FE9460B147} - SAK - SAK - SAK - SAK - Win32Proj - $(VCTargetsPath12) - 10.0.16299.0 - - - - Application - true - NotSet - v141 - - - Application - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - Application - false - true - NotSet - v141 - - - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - Disabled - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - /bigobj -Zm140 %(AdditionalOptions) - Use - MaxSpeed - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - $(CasablancaIncludeDir) - Async - - - Console - true - true - true - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - {1014c621-bc2d-4813-b8c1-6d83ad6f9249} - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Release/samples/FacebookDemo/FacebookDemo140.vcxproj b/Release/samples/FacebookDemo/FacebookDemo140.vcxproj deleted file mode 100644 index bd249ff292..0000000000 --- a/Release/samples/FacebookDemo/FacebookDemo140.vcxproj +++ /dev/null @@ -1,182 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658} - FacebookDemo - en-US - 14.0 - true - Windows Store - 8.2 - - - - Application - true - v140 - - - Application - true - v140 - - - Application - true - v140 - - - Application - false - true - v140 - - - Application - false - true - v140 - - - Application - false - true - v140 - - - - - - - FacebookDemo_TemporaryKey.pfx - - - $(OutDir)\$(MSBuildProjectName)\ - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj /Zm137 %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - - - App.xaml - - - MainPage.xaml - - - - - Designer - - - Designer - - - Designer - - - - - Designer - - - - - - - - - - - - App.xaml - - - - MainPage.xaml - - - Create - Create - Create - Create - Create - Create - - - - - {198ed804-2655-4d92-8104-c220e3ea9452} - - - - - - \ No newline at end of file diff --git a/Release/samples/FacebookDemo/FacebookDemo141.vcxproj b/Release/samples/FacebookDemo/FacebookDemo141.vcxproj deleted file mode 100644 index fb8baf2f63..0000000000 --- a/Release/samples/FacebookDemo/FacebookDemo141.vcxproj +++ /dev/null @@ -1,184 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {43DE4DF3-ACAA-429E-B260-CC6D4FE82658} - FacebookDemo - en-US - 14.0 - true - Windows Store - 10.0.16299.0 - 10.0.16299.0 - 10.0 - - - - Application - true - v141 - - - Application - true - v141 - - - Application - true - v141 - - - Application - false - true - v141 - - - Application - false - true - v141 - - - Application - false - true - v141 - - - - - - - FacebookDemo_TemporaryKey.pfx - - - $(OutDir)\$(MSBuildProjectName)\ - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj /Zm137 %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - /bigobj %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - - - - App.xaml - - - MainPage.xaml - - - - - Designer - - - Designer - - - Designer - - - - - Designer - - - - - - - - - - - - App.xaml - - - - MainPage.xaml - - - Create - Create - Create - Create - Create - Create - - - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - \ No newline at end of file diff --git a/Release/samples/FacebookDemo/FacebookDemo_TemporaryKey.pfx b/Release/samples/FacebookDemo/FacebookDemo_TemporaryKey.pfx deleted file mode 100644 index c02d448da88c71f109ce7daf8c5d6aac8a8a98c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2549 zcmai0c{o&U8$V~}%vfj843)AkO^ck7r5V}R5~1u=vXga+EMbmJwnRlGWEoN+z20e& zkSu+)nCw~0nvxL8TYN{?`}Muwb#-0eANO;9_wTuX_kCUGey-uME$( zjb+MOB7i(#9>SLkA$(aVoe3j&-v8OceS;9(0*v5hQJcmK{H+q?2QhgFv;rg0GQ1hj z{~sDnPK0#r~WUYIaNDVj3Fc3WGTy?0` z`|x$`{rd3ZxFH+nymeC1i|@scs&mtTvU%Ojn5pcvx$CdDRgA6PIax{w^pqW{D_4z@ z`UBC^uQh%X-ZS3JHVb_Z!vO($CGVmp_Md)fuyg$g?_B(1v<)RocF0P?%jx5E!qKC) zvsN)#XX}!n;2Sy#i=5GY*?Un^PEV&MBgW70 z>5`(deem5Kq0yHIcD@=LEjzg}@>CY9oV7F4fua>hJ6j|gY!ZJ$H?YDdv@edJSLw89 zrfqxcOK6kus?d{%<7_79t<9eGmGC#RPtVti0qIjp_dFuC7-n)8^g>wY77lxe+j*@- z)aUuf=*OKTIMvvlghjk09Qa*)q0;i(7(4x3iX>7Q1Rn1|SL5n{X9c7jGQ!ew@TJeQs8_ zK!C}+WzIL!-luHDRB>p7E|YR-{|lKT)QJ5hmdZ;VNcO(E61CJ+`M)=-bivDw9@WaZ#y} z7aC|<#3NA#hg>YzIcT`a!JP(oKBrdKPfUj^VRLJlrX}4zbX?)qPU__g7ygX9M8~PH zDemtCokkE#PHzXZ8P9jUq=T0=v))tAPA65~)~+z!p@IpNU6o&&rC>MzOA%H82y??5t0n49p zp{VB$cmN@=$A4>*srHh#Xh1072OI+YQ4t+Y?+&N|8mQ6GRTWS|zcf^+jv`f*aR+vz z$Q3w-qBYJFWz~RP0QG0QI-r7LS3nI$u&iH&*2V-j3_`FBlnzAA@1L^(i*6dAq|UEN zz$dmQP(}sYQGN@IV1)9p7!ZRIzKIjxYrybGGucHdXL_F38 z!jgCxC%jxwcrake^#rOql}d$Sn5wR(;)uE$zg(*0Z#4)g`_I%M4!|Oy5C9_}KL!Co zpk<{=DEZNab-py?0=iS$X=}D5fJuG9Njs&;&#Fo%*`0mW)#IP}rJ8Ex4zSf~Ie>Dt}KBf{YuaL#} z^_h3whm;)#;q@YYn(y0cmraQ|>58F|CP{nlA0aEJtX>MgXS``gv}5Ut;%H}EJ_ZW{ zU|~2M1`DBoTY?0Fs}K%Gdj!BzYlH%{0T#paqURWg=pfySb&L{t_9mxOdJK7u&$aA*J%!#$R&1F0e=p#+Ghb?7D9^^em z9?%R;;a~TF`}96d+D?C$Wj>A>3$nfYS5quPZIWk>)|}o*kC>(J9SpIId>u0o;6+ z>$OSt!-1jtWzlA7ux{iI+nGsogvCP}LNLKXe}eWD3V!8~}}b|Mxd4v`aHS?z8=pSGJ* o|3R{4qaio&QV9%^pPS%>TNWAz$|EFSh5M5^`ho%CYY(u01DuB!g8%>k diff --git a/Release/samples/OAuth2Live/OAuth2Live140.vcxproj b/Release/samples/OAuth2Live/OAuth2Live140.vcxproj deleted file mode 100644 index 6671f9c227..0000000000 --- a/Release/samples/OAuth2Live/OAuth2Live140.vcxproj +++ /dev/null @@ -1,188 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {2887A786-B818-4B3D-94EF-21EFD6AFDC22} - OAuth2Live - en-US - 14.0 - true - Windows Store - 8.2 - - - - Application - true - v140 - - - Application - true - v140 - - - Application - true - v140 - - - Application - false - true - v140 - - - Application - false - true - v140 - - - Application - false - true - v140 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /bigobj /Zm200 %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - $(OutDir)\$(MSBuildProjectName)\ - - - OAuth2Live_TemporaryKey.pfx - - - - - App.xaml - - - MainPage.xaml - - - - - Designer - - - Designer - - - Designer - - - - - Designer - - - - - - - - - - - - App.xaml - - - MainPage.xaml - - - Create - Create - Create - Create - Create - Create - - - - - {198ed804-2655-4d92-8104-c220e3ea9452} - - - - - - \ No newline at end of file diff --git a/Release/samples/OAuth2Live/OAuth2Live141.vcxproj b/Release/samples/OAuth2Live/OAuth2Live141.vcxproj deleted file mode 100644 index 07d4d46897..0000000000 --- a/Release/samples/OAuth2Live/OAuth2Live141.vcxproj +++ /dev/null @@ -1,190 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {2887A786-B818-4B3D-94EF-21EFD6AFDC22} - OAuth2Live - en-US - 14.0 - true - Windows Store - 10.0.16299.0 - 10.0.16299.0 - 10.0 - - - - Application - true - v141 - - - Application - true - v141 - - - Application - true - v141 - - - Application - false - true - v141 - - - Application - false - true - v141 - - - Application - false - true - v141 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /bigobj /Zm200 %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - $(OutDir)\$(MSBuildProjectName)\ - - - OAuth2Live_TemporaryKey.pfx - - - - - App.xaml - - - MainPage.xaml - - - - - Designer - - - Designer - - - Designer - - - - - Designer - - - - - - - - - - - - App.xaml - - - MainPage.xaml - - - Create - Create - Create - Create - Create - Create - - - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - \ No newline at end of file diff --git a/Release/samples/OAuth2Live/OAuth2Live_TemporaryKey.pfx b/Release/samples/OAuth2Live/OAuth2Live_TemporaryKey.pfx deleted file mode 100644 index c6d6c59f23b5f58d2a4af662c1d14653ca23e389..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2549 zcmai02T)U47k)35Wa)$=0@9J7@Ir(L3K4-tr7K102!_xE2^tizL=B=yQA(67MY@KL zx*~=mAnq>R0;muZ!9s8sP_Q8EV`qQ={bzROpEu{d^L^)h_sqO==bj6(aI**y39)e1 z7#xwkgS{vPV!iC zfz&Yg|IqN_(kKaU^h(JhzGN)|fgM1xP$S;@4k3eP*ZZ^Lc3U!auk1Z4OdQ_1<$Qnd zCAr5hlBL;FBY;YCMJBSdYgj90jA6UT3UyyM{o9Eq9MQ}c;!)5^rlGa;<^#?p+I6(f z!x>MKw!aj#vYR%JSPYn`edPXJc=xMsU&Zw`4iN|2y9ONy{;9Wy9`b~n)Osvpo$tg* zdS)K74P*QNA(lA(_{NV~y2|eFKDG8sq51J4<9w?*QK^>Nn`c7c7Ldv_XAtGJf{(|Y z?|4*uhRJ=>y)kF%SZ8miR`3Q+N8j$a@nNBguDMYMH(F(CBrs~3i1o@e-h7?B%u9HA z^A+IwRy;g8veeLv-FEkyPQODQbJoMQ?f3Xd5=$+ z4GD=H<4lcx@A&d_Qnv1NU*)|X#%^8jL`>4rysBdt?|a~G7m4#}RaON#XEl@G=C+AA zNO{rdh;4lXms4#Mzo%~9qoVmiU9B)zg<{Xzm*iQkYc{j7ph}4bf<{5l)k^{vj zIR;kdEk2i)Dl0y#mU9dXw@V7I9PMsy1Q&M3Z=Ppz(0CJkw6e{8p?=l)V0jutt19nT zXH%W%N6o(6TKb;-F^AH%$7Sw%-CRF6%@->`kH0N(ovpT|JJ1?-QP&=Qd&iX1WtW;U zfQxFxzN6;ymD(>?r1#AXrH{FLCIt&n#}ZDVx`}DzqJ%{$nJ9eB9-Oq7BC>U&5s4&4jY>lU-TO>8+C;(_?q- zC--|!R1Alj20d>R2~vVegQgf=;gI%_xY^1ehrFPWIbx|<(rQGUbG&9Oevp!r?BnOE z8}j}M;nE)qgkl@pqmCt`weerHbEP{nCTZ#=p2aU_@Ze`uoYsqz& zc$MnX{cx?>hu`SEKCgUiC@+^zTnSnjqFnlEKQTU}jM$0e)e`&8B+yL^NuxdcGz=^b zs=vJ&+iWkI!P{m}vq_r%OLOKIV|6~&sOv}+@8NowDN!q1wugSJ>)hh!r~N}g59LgA zQQoy*&aQxDw^ne?*PerASsw8g@6Ws^oq7f-d_OL6iX;pQ1p)v7`D1WK7!U=rC~_dl zO~VCn2Eu_5AP$HD7_iZRct8`_1HV_9gFqOJY+?T>5DRlLFpdL)VW0k&N)vGVEAI%5 zLV*K79CYBnH3_7>8eVY15g-!q0HR@$B|rhp0Sf?v%TVB=WMCugn*y7GO|Z8K#-@LH z!En?9&Rpea@RtN8U}EKml3SRfw30zsfP zqHSzBTfI8zb&R%-Z!ep0W8j&(*I>MgmEpG*!2;93qm>$=S&CI&jYUbjIdU zWt2SWnBE;053KEMGI|O%^TS0M*UgI2_jGQ=32$eH`-{0$j$BlZlkpQ?|AqGU>*bfo z8t=0DS9)R#m?w|a1SRT~#*>}A)ZV(w7WWfOgYnb$6<QfAyDMJD&+TewkPI;20spW}6`{y+e<=VnqRIa21TI$j zuT0PE_nuF60xnuOZkF13EFhOl>L{?35xO#Ug!8?}+n!#EAd6?}H`riPEhKg6?5i6k zj6E#gEIRF3v diff --git a/Release/samples/Regenerate-Certificates.ps1 b/Release/samples/Regenerate-Certificates.ps1 deleted file mode 100644 index 96918fa99e..0000000000 --- a/Release/samples/Regenerate-Certificates.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -[CmdletBinding(SupportsShouldProcess=$true)] -param( - [Parameter(Mandatory=$true)] - [String]$PublisherName -) - -$ErrorActionPreference = "Stop" - -$Paths = @( - "$PSScriptRoot\BlackJack\BlackJack_UIClient\BlackJack_UIClient_TemporaryKey.pfx", - "$PSScriptRoot\FacebookDemo\FacebookDemo_TemporaryKey.pfx", - "$PSScriptRoot\OAuth2Live\OAuth2Live_TemporaryKey.pfx", - "$PSScriptRoot\WindowsLiveAuth\WindowsLiveAuth_TemporaryKey.pfx" -) - -$MakeCert = "C:\Program Files (x86)\Windows Kits\10\bin\x86\makecert.exe" -$Pvk2Pfx = "C:\Program Files (x86)\Windows Kits\10\bin\x86\pvk2pfx.exe" - -pushd $PSScriptRoot - -foreach($Path in $Paths) -{ - Remove-Item $Path -ErrorAction SilentlyContinue - if ($PSCmdlet.ShouldProcess($PSScriptRoot, "MakeCert")) - { - & $MakeCert -n "CN=$PublisherName" -a sha512 -m 12 -r -h 0 -eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" /sv "Temp.pvk" "Temp.cer" - } - if ($PSCmdlet.ShouldProcess($Path, "Pvk2Pfx")) - { - & $Pvk2Pfx -pvk "Temp.pvk" -spc "Temp.cer" -pfx $Path - Remove-Item "$PSScriptRoot\Temp.pvk" - Remove-Item "$PSScriptRoot\Temp.cer" - } -} diff --git a/Release/samples/WindowsLiveAuth/WindowsLiveAuth140.vcxproj b/Release/samples/WindowsLiveAuth/WindowsLiveAuth140.vcxproj deleted file mode 100644 index 7be6b6dda1..0000000000 --- a/Release/samples/WindowsLiveAuth/WindowsLiveAuth140.vcxproj +++ /dev/null @@ -1,189 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {1c20f771-3131-46e8-805f-aa1fe44165c0} - WindowsLiveAuth - en-US - 14.0 - true - Windows Store - 8.2 - - - - Application - true - v140 - - - Application - true - v140 - - - Application - true - v140 - - - Application - false - true - v140 - - - Application - false - true - v140 - - - Application - false - true - v140 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /bigobj /Zm200 %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - $(OutDir)\$(MSBuildProjectName)\ - - - WindowsLiveAuth_TemporaryKey.pfx - - - - - - App.xaml - - - MainPage.xaml - - - - - Designer - - - Designer - - - Designer - - - - - Designer - - - - - - - - - - - - App.xaml - - - MainPage.xaml - - - Create - Create - Create - Create - Create - Create - - - - - {198ed804-2655-4d92-8104-c220e3ea9452} - - - - - - \ No newline at end of file diff --git a/Release/samples/WindowsLiveAuth/WindowsLiveAuth141.vcxproj b/Release/samples/WindowsLiveAuth/WindowsLiveAuth141.vcxproj deleted file mode 100644 index 7fec114667..0000000000 --- a/Release/samples/WindowsLiveAuth/WindowsLiveAuth141.vcxproj +++ /dev/null @@ -1,191 +0,0 @@ - - - - - Debug - ARM - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - Win32 - - - Release - x64 - - - - {1c20f771-3131-46e8-805f-aa1fe44165c0} - WindowsLiveAuth - en-US - 14.0 - true - Windows Store - 10.0.10240.0 - 10.0.10240.0 - 10.0 - - - - Application - true - v140 - - - Application - true - v140 - - - Application - true - v140 - - - Application - false - true - v140 - - - Application - false - true - v140 - - - Application - false - true - v140 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /bigobj /Zm200 %(AdditionalOptions) - 4453 - $(MSBuildProjectDirectory);$(CasablancaIncludeDir);$(MSBuildProjectDirectory)\Generated Files;%(AdditionalIncludeDirectories) - - - - $(OutDir)\$(MSBuildProjectName)\ - - - WindowsLiveAuth_TemporaryKey.pfx - - - - - - App.xaml - - - MainPage.xaml - - - - - Designer - - - Designer - - - Designer - - - - - Designer - - - - - - - - - - - - App.xaml - - - MainPage.xaml - - - Create - Create - Create - Create - Create - Create - - - - - {36d79e79-7e9e-4b3a-88a3-9f9b295c80b9} - - - - - - \ No newline at end of file diff --git a/Release/samples/WindowsLiveAuth/WindowsLiveAuth_TemporaryKey.pfx b/Release/samples/WindowsLiveAuth/WindowsLiveAuth_TemporaryKey.pfx deleted file mode 100644 index 8cb613e1d53742a6fe51d5f45b4ddfdfe1de0fb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2549 zcmai0c{EjP8{hkkj^UW6GLsVr?PEG8!!gAvai|oD3~_LkOd;{b7KsKVQ^`=~P}~R$ z73ti_m`L=IWacOeb-7#Xetq{_tF^vAo_9aL-}C(5XRZCb>wR7bCM=;qGz1gMaRk-4 zy>VapKs=ZW6K-Q*LKZ@&K`@T%e?r(b42)fYVC)iN^EjTrRlM9FDi_9VKrm(g666nto&c67b06_H zEVEx^$Ze1FGOib0>6jNf@BHQCA2xamS=%f&Vu2_?}RKZtj^PYqhu4ykvLFo{gIh`LE^@&2|pPZV#n5A3RTB6*{quUPPfYgy3s zY?v=KW|Ag!FO8o)@QC4I&IvU%&YNB69F4t$zp?E-Wj#ffIj7TUCA9V>y2?AWVdXHL zGiFl5bO^;9;UX~}pp*{H;5jEIpo8!z>e8gzUzo-HLe92c3wlO|E_eP^}XXh6o> zw$543 zour*BTQG9-_$oqlQV)lE-N%bJip}W}kIi|%>Pn52bI$C3=X^3n%qimbw=*Vg)X{NT z(Ooq`YNBDvO38Dj^!KJd`7tJ=nYdX(5yr|_I64JFUR0!#lVeARw<^F+ElYl z8)e>q<%|bpCzWYcz#)yZ;m|sD!(ac6qKRuANL~yIb0vMC=&dicaY~GP7C)CAeK5ih z2@7SmWA=A&>7iB*6+siynmuuT&yKdI!C-#v^oT|A+lVjyt6iV%JFMIyNc%fx+lMsd zzXmkkj>nRV#&W#4!Z4jY%{k|*1G5uMt#uyc4h@uxJ!Z%{D9o@0mOqIdaLl@Xzj-|D6ua&WZGsdi0gOH?IldQ`&s2M%~V4Y7}@%iPDt{xlTOO8pazs$I)rGM>-) zlFjotv3FUQO0r_e4v#-IsIUm&qi<8I_LaJ>iR?|+{P_n&>z;YHMHIH*%Z2gw6aCcj zfogo*^011L`YCmaZv;>s*py~*t(&A)*mhZjbE4q*1;I4=1S_d}f&Oazdv@KclS0Dx zdz)Tu@HyBWR@WBDgDX~zl90CTLZ8Ed;wYwpMwbCAF14zOxY;wO`FYjUXl~Ys z9`F9dD6Ap(Np7_EPI8~{z2S^N*}5{!v^?Wzi;hS|FKPO1e7nUeD}-Y=AA7K2q^>z8 zdCew|5QSp<9p7l=TvZWP+sm$ZzRS#XQp_p6g}dll&ZsHqEE-)c(|raEd7`?EbhPTP zn+KfyD3bkjjOCPGeb9u)C38mx33hEuJJ<_um}3#gHKND2h~+@X?D2nOVUL&&tb3 zAmsVqnj#bjnIlL-2;d9Y0jCg=9zX>kKo?15A>ZAIL>-_ZD+R&ofHo4h{1bpX1f%1A7TOvU=uixd4npYDi243=7NC)!8A2NUoCE~1Ex|5C zKt^~H1f%$K(I^mw5)i!ySr$EfRA|{Cy5=q&3P5~6i-3Gs01~1IKtvq+Fa|A*4+{2j z3-%0xWW@O>x)cfpf*^{nj*cS&sXw8%<1aNZsPNCNK`elVL4E*&L2eWbf1>aP9Yoy!yQA7t-XbjhGg;k^gbNqVwmu1 z%C6ZpAmv*AoK=Wxf4bdos@ODNV3g11h1^eMytFR!daq9)-L)t#8Vw zrE=VQZuO})yz3H!)+y4Dp!og8xQJvr@IWzCuq|Lm(bAdfsY2q~-O86JGzfrq&O)IO zKk~Pwg+Xu=gN2YD0g&t#u>&IkiQ%}AbBx8}(P$j^-zS0DL;`~cTCl*QJ(A8$9tp}IW)fRh}Phj z=P+*9PZ7Oq6ZA`9)rAqR-7%KO9dlILE!Vrt{Jd;ve?-Syo3ilSTDI~{f|}68xSvo= zuVOk7)#MVGWT`*fN9lX7eMEK1=gVMo&vo%xD+hXvFLlzeEl2!yr(uguuWpNdaom-u z4>9Z3O~Y5jt{x3yEe`iE$QN`)Y0qzHca+w;Y=U*I2YKB2UB7$Dy-~_`vP_>*cb3K< z%eBoLUg;RvUUD|de&*OcYgmIh81e9x<16mDaslPvMg#~s%L8GzP-2b4+?%bbZ97(L zYTO2&yXc=$(lJ!k`oO7$R{aHRD5Af>(iD=X|j0jfIhmJC4-pXEXI4f@N j?@6MtsxTrh#nbtv&%HZ71eTdfwsf Date: Sat, 23 May 2020 16:40:58 +0300 Subject: [PATCH 54/80] Add constructor from all integer types. Fixes #1428 --- Release/include/cpprest/json.h | 62 ++++++++++++++----- Release/src/json/json.cpp | 37 ++++++++--- .../functional/json/construction_tests.cpp | 55 ++++++++++++++++ 3 files changed, 130 insertions(+), 24 deletions(-) diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index 8fbbf947f2..84bf2b89d6 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -100,25 +100,37 @@ class value /// Constructor creating a JSON number value /// /// The C++ value to create a JSON value from - _ASYNCRTIMP value(int32_t value); + _ASYNCRTIMP value(int value); /// /// Constructor creating a JSON number value /// /// The C++ value to create a JSON value from - _ASYNCRTIMP value(uint32_t value); + _ASYNCRTIMP value(unsigned value); /// /// Constructor creating a JSON number value /// /// The C++ value to create a JSON value from - _ASYNCRTIMP value(int64_t value); + _ASYNCRTIMP value(long value); /// /// Constructor creating a JSON number value /// /// The C++ value to create a JSON value from - _ASYNCRTIMP value(uint64_t value); + _ASYNCRTIMP value(unsigned long value); + + /// + /// Constructor creating a JSON number value + /// + /// The C++ value to create a JSON value from + _ASYNCRTIMP value(long long value); + + /// + /// Constructor creating a JSON number value + /// + /// The C++ value to create a JSON value from + _ASYNCRTIMP value(unsigned long long value); /// /// Constructor creating a JSON number value @@ -222,28 +234,42 @@ class value /// /// The C++ value to create a JSON value from /// A JSON number value - static _ASYNCRTIMP value __cdecl number(int32_t value); + static _ASYNCRTIMP value __cdecl number(int value); + + /// + /// Creates a number value + /// + /// The C++ value to create a JSON value from + /// A JSON number value + static _ASYNCRTIMP value __cdecl number(unsigned value); + + /// + /// Creates a number value + /// + /// The C++ value to create a JSON value from + /// A JSON number value + static _ASYNCRTIMP value __cdecl number(long value); /// /// Creates a number value /// /// The C++ value to create a JSON value from /// A JSON number value - static _ASYNCRTIMP value __cdecl number(uint32_t value); + static _ASYNCRTIMP value __cdecl number(unsigned long value); /// /// Creates a number value /// /// The C++ value to create a JSON value from /// A JSON number value - static _ASYNCRTIMP value __cdecl number(int64_t value); + static _ASYNCRTIMP value __cdecl number(long long value); /// /// Creates a number value /// /// The C++ value to create a JSON value from /// A JSON number value - static _ASYNCRTIMP value __cdecl number(uint64_t value); + static _ASYNCRTIMP value __cdecl number(unsigned long long value); /// /// Creates a Boolean value @@ -1218,10 +1244,12 @@ class number // convert to unsigned int64). This helps handling number objects e.g. comparing two numbers. number(double value) : m_value(value), m_type(double_type) {} - number(int32_t value) : m_intval(value), m_type(value < 0 ? signed_type : unsigned_type) {} - number(uint32_t value) : m_intval(value), m_type(unsigned_type) {} - number(int64_t value) : m_intval(value), m_type(value < 0 ? signed_type : unsigned_type) {} - number(uint64_t value) : m_uintval(value), m_type(unsigned_type) {} + number(int value) : m_intval(value), m_type(value < 0 ? signed_type : unsigned_type) {} + number(unsigned value) : m_intval(value), m_type(unsigned_type) {} + number(long value) : m_intval(value), m_type(value < 0 ? signed_type : unsigned_type) {} + number(unsigned long value) : m_uintval(value), m_type(unsigned_type) {} + number(long long value) : m_intval(value), m_type(value < 0 ? signed_type : unsigned_type) { } + number(unsigned long long value) : m_uintval(value), m_type(unsigned_type) { } public: /// @@ -1438,10 +1466,12 @@ class _Number : public _Value { public: _Number(double value) : m_number(value) {} - _Number(int32_t value) : m_number(value) {} - _Number(uint32_t value) : m_number(value) {} - _Number(int64_t value) : m_number(value) {} - _Number(uint64_t value) : m_number(value) {} + _Number(int value) : m_number(value) {} + _Number(unsigned value) : m_number(value) {} + _Number(long value) : m_number(value) {} + _Number(unsigned long value) : m_number(value) {} + _Number(long long value) : m_number(value) { } + _Number(unsigned long long value) : m_number(value) { } virtual std::unique_ptr<_Value> _copy_value() { return utility::details::make_unique<_Number>(*this); } diff --git a/Release/src/json/json.cpp b/Release/src/json/json.cpp index f1f0865d87..079ccae473 100644 --- a/Release/src/json/json.cpp +++ b/Release/src/json/json.cpp @@ -38,7 +38,7 @@ web::json::value::value() { } -web::json::value::value(int32_t value) +web::json::value::value(int value) : m_value(utility::details::make_unique(value)) #ifdef ENABLE_JSON_VALUE_VISUALIZER , m_kind(value::Number) @@ -46,7 +46,7 @@ web::json::value::value(int32_t value) { } -web::json::value::value(uint32_t value) +web::json::value::value(unsigned value) : m_value(utility::details::make_unique(value)) #ifdef ENABLE_JSON_VALUE_VISUALIZER , m_kind(value::Number) @@ -54,7 +54,8 @@ web::json::value::value(uint32_t value) { } -web::json::value::value(int64_t value) + +web::json::value::value(long value) : m_value(utility::details::make_unique(value)) #ifdef ENABLE_JSON_VALUE_VISUALIZER , m_kind(value::Number) @@ -62,7 +63,23 @@ web::json::value::value(int64_t value) { } -web::json::value::value(uint64_t value) +web::json::value::value(unsigned long value) + : m_value(utility::details::make_unique(value)) +#ifdef ENABLE_JSON_VALUE_VISUALIZER + , m_kind(value::Number) +#endif +{ +} + +web::json::value::value(long long value) + : m_value(utility::details::make_unique(value)) +#ifdef ENABLE_JSON_VALUE_VISUALIZER + , m_kind(value::Number) +#endif +{ +} + +web::json::value::value(unsigned long long value) : m_value(utility::details::make_unique(value)) #ifdef ENABLE_JSON_VALUE_VISUALIZER , m_kind(value::Number) @@ -162,13 +179,17 @@ web::json::value web::json::value::null() { return web::json::value(); } web::json::value web::json::value::number(double value) { return web::json::value(value); } -web::json::value web::json::value::number(int32_t value) { return web::json::value(value); } +web::json::value web::json::value::number(int value) { return web::json::value(value); } + +web::json::value web::json::value::number(unsigned value) { return web::json::value(value); } + +web::json::value web::json::value::number(long value) { return web::json::value(value); } -web::json::value web::json::value::number(uint32_t value) { return web::json::value(value); } +web::json::value web::json::value::number(unsigned long value) { return web::json::value(value); } -web::json::value web::json::value::number(int64_t value) { return web::json::value(value); } +web::json::value web::json::value::number(long long value) { return web::json::value(value); } -web::json::value web::json::value::number(uint64_t value) { return web::json::value(value); } +web::json::value web::json::value::number(unsigned long long value) { return web::json::value(value); } web::json::value web::json::value::boolean(bool value) { return web::json::value(value); } diff --git a/Release/tests/functional/json/construction_tests.cpp b/Release/tests/functional/json/construction_tests.cpp index 111b1454e1..7a9275b301 100644 --- a/Release/tests/functional/json/construction_tests.cpp +++ b/Release/tests/functional/json/construction_tests.cpp @@ -50,6 +50,61 @@ SUITE(construction_tests) VERIFY_ARE_EQUAL(U("null"), arr[1].serialize()); } + TEST(int_assignment_op) + { + json::value v; + v = static_cast(1); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + + v = static_cast(1); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + + v = static_cast(1); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + + v = static_cast(1); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + + v = static_cast(1); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + + v = static_cast(1); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + } + + TEST(int_ctor) + { + { + json::value v(static_cast(1)); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + } + + { + json::value v(static_cast(1)); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + } + + { + json::value v(static_cast(1)); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + } + + { + json::value v(static_cast(1)); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + } + + { + json::value v(static_cast(1)); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + } + + { + json::value v(static_cast(1)); + VERIFY_ARE_EQUAL(U("1"), v.serialize()); + } + } + TEST(copy_ctor_array) { json::value arr = json::value::array(); From 708a5df2bb328705622c42f84b4167ea2c7c98c9 Mon Sep 17 00:00:00 2001 From: Ivan Cherniukh Date: Wed, 9 Sep 2020 09:09:04 -0700 Subject: [PATCH 55/80] Add support for oauth2 using only client credentials --- .../cpprest/details/http_constants.dat | 1 + Release/include/cpprest/oauth2.h | 15 ++++ .../functional/http/client/oauth2_tests.cpp | 68 +++++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/Release/include/cpprest/details/http_constants.dat b/Release/include/cpprest/details/http_constants.dat index c3b1a53cb6..3deb24a146 100644 --- a/Release/include/cpprest/details/http_constants.dat +++ b/Release/include/cpprest/details/http_constants.dat @@ -190,6 +190,7 @@ DAT(expires_in, "expires_in") DAT(grant_type, "grant_type") DAT(redirect_uri, "redirect_uri") DAT(refresh_token, "refresh_token") +DAT(client_credentials, "client_credentials") DAT(response_type, "response_type") DAT(scope, "scope") DAT(state, "state") diff --git a/Release/include/cpprest/oauth2.h b/Release/include/cpprest/oauth2.h index 693ebbe34c..68a7c7b9ab 100644 --- a/Release/include/cpprest/oauth2.h +++ b/Release/include/cpprest/oauth2.h @@ -284,6 +284,21 @@ class oauth2_config return _request_token(ub); } + /// + /// Fetches an access token from the token endpoint using client credentials grant type. + /// The task creates an HTTP request to the token_endpoint() using + /// client authentication as the authorization grant. + /// See: http://tools.ietf.org/html/rfc6749#section-4.4 + /// + /// Task that fetches token(s) using client credentials. + pplx::task token_from_client_credentials() + { + uri_builder ub; + ub.append_query( + details::oauth2_strings::grant_type, details::oauth2_strings::client_credentials, false); + return _request_token(ub); + } + /// /// Returns enabled state of the configuration. /// The oauth2_handler will perform OAuth 2.0 authentication only if diff --git a/Release/tests/functional/http/client/oauth2_tests.cpp b/Release/tests/functional/http/client/oauth2_tests.cpp index e1f5408588..08bb12a652 100644 --- a/Release/tests/functional/http/client/oauth2_tests.cpp +++ b/Release/tests/functional/http/client/oauth2_tests.cpp @@ -291,6 +291,74 @@ SUITE(oauth2_tests) VERIFY_ARE_EQUAL(U("done"), m_oauth2_config.token().access_token()); } + TEST_FIXTURE(oauth2_test_setup, oauth2_token_from_client_credentials) + { + VERIFY_IS_FALSE(m_oauth2_config.is_enabled()); + + m_oauth2_config.set_user_agent(U("test_user_agent")); + + // Fetch using HTTP Basic authentication. + { + m_scoped.server()->next_request().then([](test_request* request) { + VERIFY_ARE_EQUAL(request->m_method, methods::POST); + + VERIFY_IS_TRUE(is_application_x_www_form_urlencoded(request)); + + VERIFY_ARE_EQUAL( + U("Basic MTIzQUJDOjQ1NkRFRg=="), + request->m_headers[header_names::authorization]); + + VERIFY_ARE_EQUAL( + to_body_data(U("grant_type=client_credentials")), + request->m_body); + + VERIFY_ARE_EQUAL( + U("test_user_agent"), + get_request_user_agent(request)); + + std::map headers; + headers[header_names::content_type] = mime_types::application_json; + request->reply( + status_codes::OK, U(""), headers, "{\"access_token\":\"xyzzy123\",\"token_type\":\"bearer\"}"); + }); + + m_oauth2_config.token_from_client_credentials().wait(); + VERIFY_ARE_EQUAL(U("xyzzy123"), m_oauth2_config.token().access_token()); + VERIFY_IS_TRUE(m_oauth2_config.is_enabled()); + } + + // Fetch using client key & secret in request body (x-www-form-urlencoded). + { + m_scoped.server()->next_request().then([](test_request* request) { + VERIFY_IS_TRUE(is_application_x_www_form_urlencoded(request)); + + VERIFY_ARE_EQUAL(U(""), request->m_headers[header_names::authorization]); + + VERIFY_ARE_EQUAL( + to_body_data(U("grant_type=client_credentials&client_id=123ABC&client_secret=456DEF")), + request->m_body); + + VERIFY_ARE_EQUAL(U("test_user_agent"), get_request_user_agent(request)); + + std::map headers; + headers[header_names::content_type] = mime_types::application_json; + request->reply( + status_codes::OK, U(""), headers, "{\"access_token\":\"xyzzy123\",\"token_type\":\"bearer\"}"); + }); + + m_oauth2_config.set_token(oauth2_token()); // Clear token. + VERIFY_IS_FALSE(m_oauth2_config.is_enabled()); + + m_oauth2_config.set_http_basic_auth(false); + m_oauth2_config.token_from_client_credentials().wait(); + + VERIFY_ARE_EQUAL( + U("xyzzy123"), + m_oauth2_config.token().access_token()); + VERIFY_IS_TRUE(m_oauth2_config.is_enabled()); + } + } + TEST_FIXTURE(oauth2_test_setup, oauth2_bearer_token) { m_oauth2_config.set_token(oauth2_token(U("12345678"))); From 6ed6d67c80d6efb90dd4b756be8ca9f31ea96371 Mon Sep 17 00:00:00 2001 From: Tao He Date: Thu, 22 Oct 2020 16:06:55 +0800 Subject: [PATCH 56/80] Define __STDC_FORMAT_MACROS when it hasn't been defined to avoid duplicate define error. Signed-off-by: Tao He --- Release/src/json/json_serialization.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Release/src/json/json_serialization.cpp b/Release/src/json/json_serialization.cpp index 3aa0c50ceb..0191b34ff1 100644 --- a/Release/src/json/json_serialization.cpp +++ b/Release/src/json/json_serialization.cpp @@ -16,7 +16,9 @@ #include #ifndef _WIN32 +#ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS +#endif #include #endif From dbb55638b2d7ecf248eb35db6148747a0f762677 Mon Sep 17 00:00:00 2001 From: Sztergbaum Roman Date: Mon, 26 Oct 2020 13:27:33 +0100 Subject: [PATCH 57/80] [MacOS]: fix wrong linking of Apple Frameworks see #1522 --- Release/src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/src/CMakeLists.txt b/Release/src/CMakeLists.txt index a2d4d30b64..e15aeb7fc3 100644 --- a/Release/src/CMakeLists.txt +++ b/Release/src/CMakeLists.txt @@ -94,7 +94,7 @@ endif() if(CPPREST_PPLX_IMPL STREQUAL "apple") find_library(COREFOUNDATION CoreFoundation "/") find_library(SECURITY Security "/") - target_link_libraries(cpprest PUBLIC ${COREFOUNDATION} ${SECURITY}) + target_link_libraries(cpprest PRIVATE ${COREFOUNDATION} ${SECURITY}) target_sources(cpprest PRIVATE pplx/pplxapple.cpp pplx/pplx.cpp pplx/threadpool.cpp ../include/pplx/threadpool.h) if(CPPREST_INSTALL_HEADERS) install(FILES ../include/pplx/threadpool.h DESTINATION include/pplx) From eb6801fa65083197ea88e5c4f2d97d5b8a98262a Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Thu, 10 Dec 2020 16:12:55 -0800 Subject: [PATCH 58/80] Update README.md Remove the direct contact link, since it goes to a very old email list that we're shutting down in favor of monitoring issues more consistently --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index a1f46ab4fb..5d9cd4c0a6 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,6 @@ We'd love to get your review score, whether good or bad, but even more than that * [FAQ](https://github.com/Microsoft/cpprestsdk/wiki/FAQ) * [Documentation](https://github.com/Microsoft/cpprestsdk/wiki) * [Issue Tracker](https://github.com/Microsoft/cpprestsdk/issues) -* Directly contact us: This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. From 8ae5da616dca0beb0c3ac9910c8db64153b33b0d Mon Sep 17 00:00:00 2001 From: Ivan Cherniukh Date: Tue, 15 Dec 2020 13:57:00 -0800 Subject: [PATCH 59/80] Update oauth2.h indentation correction --- Release/include/cpprest/oauth2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/oauth2.h b/Release/include/cpprest/oauth2.h index 68a7c7b9ab..b1ec324996 100644 --- a/Release/include/cpprest/oauth2.h +++ b/Release/include/cpprest/oauth2.h @@ -295,7 +295,7 @@ class oauth2_config { uri_builder ub; ub.append_query( - details::oauth2_strings::grant_type, details::oauth2_strings::client_credentials, false); + details::oauth2_strings::grant_type, details::oauth2_strings::client_credentials, false); return _request_token(ub); } From 198b034679cf7f962e242977b99ea5c63ad9eb03 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Wed, 30 Dec 2020 19:46:21 -0800 Subject: [PATCH 60/80] Fix year calculation for the last day of a leap year. --- Release/src/utilities/asyncrt_utils.cpp | 6 ++++++ Release/tests/functional/utils/datetime.cpp | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index 16d7e687b9..579fedc25f 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -736,6 +736,12 @@ static compute_year_result compute_year(int64_t secondsSince1900) int secondsInt = static_cast(secondsLeft - year4 * SecondsIn4Years); int year1 = secondsInt / SecondsInYear; + if (year1 == 4) + { + // this is the last day in a leap year + year1 = 3; + } + secondsInt -= year1 * SecondsInYear; // shift back to 1900 base from 1601: diff --git a/Release/tests/functional/utils/datetime.cpp b/Release/tests/functional/utils/datetime.cpp index aac5b16714..a584b1e3c2 100644 --- a/Release/tests/functional/utils/datetime.cpp +++ b/Release/tests/functional/utils/datetime.cpp @@ -133,6 +133,21 @@ SUITE(datetime) TestDateTimeRoundtrip(_XPLATSTR("9999-12-31T23:59:59Z")); } + TEST(parsing_time_roundtrip_year_2016) + { + TestDateTimeRoundtrip(_XPLATSTR("2016-12-31T20:59:59Z")); + } + + TEST(parsing_time_roundtrip_year_2020) + { + TestDateTimeRoundtrip(_XPLATSTR("2020-12-31T20:59:59Z")); + } + + TEST(parsing_time_roundtrip_year_2021) + { + TestDateTimeRoundtrip(_XPLATSTR("2021-01-01T20:59:59Z")); + } + TEST(emitting_time_correct_day) { const auto test = utility::datetime() + UINT64_C(132004507640000000); // 2019-04-22T23:52:44 is a Monday const auto actual = test.to_string(utility::datetime::RFC_1123); From 5fda55ae2d8cbcc391e3241b5c0194a61a436171 Mon Sep 17 00:00:00 2001 From: Charlie Date: Wed, 30 Dec 2020 20:10:44 -0800 Subject: [PATCH 61/80] mint 2.10.17 --- Release/CMakeLists.txt | 2 +- Release/include/cpprest/version.h | 2 +- changelog.md | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 13a3f01db8..441cdf8c28 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 16) +set(CPPREST_VERSION_REVISION 17) enable_testing() diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index 0bffcc2a6b..2787e276c7 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -5,6 +5,6 @@ */ #define CPPREST_VERSION_MINOR 10 #define CPPREST_VERSION_MAJOR 2 -#define CPPREST_VERSION_REVISION 16 +#define CPPREST_VERSION_REVISION 17 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR * 100000 + CPPREST_VERSION_MINOR * 100 + CPPREST_VERSION_REVISION) diff --git a/changelog.md b/changelog.md index 4c9bb6f123..6e912c80e1 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,11 @@ +cpprestsdk (2.10.17) +* PR#1550 Fix year calculation for the last day of a leap year +* PR#1523 Fix wrong linking of Apple Frameworks on MacOS +* PR#1520 Define __STDC_FORMAT_MACROS when it hasn't been defined to avoid duplicate define error. +* PR#1415 Delete apparently broken .vcxprojs and .pfxes. +* Removed defunct email contact information from the readme +-- cpprestsdk team WED, 30 Dec 2020 20:08:00 -0700 + cpprestsdk (2.10.16) * PR#1383 CMake fixes + CMake search for OpenSSL (macOS) * PR#1392 Update submodule websocketpp to 0.8.2 From 3eb3c412113bb2ee1797980becbf2887383184da Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 25 Jan 2021 18:48:55 -0800 Subject: [PATCH 62/80] Update vcpkg. --- vcpkg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcpkg b/vcpkg index 6709d3d7d0..b759049a36 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit 6709d3d7d0cba96508ba3606f810ab562ea32556 +Subproject commit b759049a36728d18260963799a56e6b19cb4a2ef From 880e535ccbbe6500cdbc0d2fc2d5eff0af255ef7 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 25 Jan 2021 18:57:34 -0800 Subject: [PATCH 63/80] Fix VS2019 build warning caused by mixing floating point types. --- Release/include/cpprest/streams.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Release/include/cpprest/streams.h b/Release/include/cpprest/streams.h index c2968b9d49..b6c3864028 100644 --- a/Release/include/cpprest/streams.h +++ b/Release/include/cpprest/streams.h @@ -17,6 +17,7 @@ #include "cpprest/astreambuf.h" #include +#include namespace Concurrency { @@ -1434,7 +1435,8 @@ static pplx::task _extract_result(std::shared_ptr<_double_stateexponent_number >= 0) { - result *= pow(FloatingPoint(10.0), state->exponent_number); + result *= static_cast( + std::pow(static_cast(10.0), static_cast(state->exponent_number))); #pragma push_macro("max") #undef max @@ -1447,7 +1449,8 @@ static pplx::task _extract_result(std::shared_ptr<_double_stateexponent_number); + result /= static_cast( + std::pow(static_cast(10.0), static_cast(-state->exponent_number))); if (!is_zero && result > -std::numeric_limits::denorm_min() && result < std::numeric_limits::denorm_min()) From 7046d3a996f0ce55aa9dc041b020012302d80bc4 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 25 Jan 2021 19:51:05 -0800 Subject: [PATCH 64/80] Add ability to emit the NT epoch. --- Release/src/utilities/asyncrt_utils.cpp | 84 ++++++++++++--------- Release/tests/functional/utils/datetime.cpp | 14 ++++ 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index 579fedc25f..7548bc5ea0 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -177,8 +177,8 @@ scoped_c_thread_locale::~scoped_c_thread_locale() } } #elif (defined(ANDROID) || defined(__ANDROID__)) -scoped_c_thread_locale::scoped_c_thread_locale() {} -scoped_c_thread_locale::~scoped_c_thread_locale() {} +scoped_c_thread_locale::scoped_c_thread_locale() { } +scoped_c_thread_locale::~scoped_c_thread_locale() { } #else scoped_c_thread_locale::scoped_c_thread_locale() : m_prevLocale(nullptr) { @@ -620,7 +620,13 @@ utf16string __cdecl conversions::to_utf16string(const std::string& value) { retu static const int64_t NtToUnixOffsetSeconds = 11644473600; // diff between windows and unix epochs (seconds) -static bool year_is_leap_year(int year) { return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); } +static bool year_is_leap_year_1601(int year) +{ + int decimal_year = year + 1601; + return (decimal_year % 4 == 0 && (decimal_year % 100 != 0 || decimal_year % 400 == 0)); +} + +static bool year_is_leap_year(int year) { return year_is_leap_year_1601(year + 299); } static const int SecondsInMinute = 60; static const int SecondsInHour = SecondsInMinute * 60; @@ -639,26 +645,27 @@ static const int64_t SecondsFrom1900To2001 = INT64_C(3187296000); static const int64_t NtTo1900OffsetInterval = INT64_C(0x014F373BFDE04000); -static int count_leap_years(const int yearsSince1900) +static int count_leap_years_1601(int yearsSince1601) { - int tmpYears = yearsSince1900 + 299; // shift into 1601, the first 400 year cycle including 1900 - - int year400 = tmpYears / 400; - tmpYears -= year400 * 400; + int year400 = yearsSince1601 / 400; + yearsSince1601 -= year400 * 400; int result = year400 * 97; - int year100 = tmpYears / 100; - tmpYears -= year100 * 100; + int year100 = yearsSince1601 / 100; + yearsSince1601 -= year100 * 100; result += year100 * 24; - result += tmpYears / 4; - - // subtract off leap years from 1601 - result -= 72; + result += yearsSince1601 / 4; return result; } +static int count_leap_years(const int yearsSince1900) +{ + // shift into 1601, the first 400 year cycle including 1900, then subtract leap years from 1601->1900 + return count_leap_years_1601(yearsSince1900 + 299) - 72; +} + // The following table assumes no leap year; leap year is added separately static const unsigned short cumulative_days_to_month[12] = { 0, // Jan @@ -720,20 +727,16 @@ struct compute_year_result int secondsLeftThisYear; }; -static const int64_t secondsFrom1601To1900 = INT64_C(9435484800); - -static compute_year_result compute_year(int64_t secondsSince1900) +static compute_year_result compute_year_1601(int64_t secondsSince1601) { - int64_t secondsLeft = secondsSince1900 + secondsFrom1601To1900; // shift to start of this 400 year cycle - - int year400 = static_cast(secondsLeft / SecondsIn400Years); - secondsLeft -= year400 * SecondsIn400Years; + int year400 = static_cast(secondsSince1601 / SecondsIn400Years); + secondsSince1601 -= year400 * SecondsIn400Years; - int year100 = static_cast(secondsLeft / SecondsIn100Years); - secondsLeft -= year100 * SecondsIn100Years; + int year100 = static_cast(secondsSince1601 / SecondsIn100Years); + secondsSince1601 -= year100 * SecondsIn100Years; - int year4 = static_cast(secondsLeft / SecondsIn4Years); - int secondsInt = static_cast(secondsLeft - year4 * SecondsIn4Years); + int year4 = static_cast(secondsSince1601 / SecondsIn4Years); + int secondsInt = static_cast(secondsSince1601 - year4 * SecondsIn4Years); int year1 = secondsInt / SecondsInYear; if (year1 == 4) @@ -743,9 +746,16 @@ static compute_year_result compute_year(int64_t secondsSince1900) } secondsInt -= year1 * SecondsInYear; + return {year400 * 400 + year100 * 100 + year4 * 4 + year1, secondsInt}; +} - // shift back to 1900 base from 1601: - return {year400 * 400 + year100 * 100 + year4 * 4 + year1 - 299, secondsInt}; +static const int64_t secondsFrom1601To1900 = INT64_C(9435484800); +static compute_year_result compute_year(int64_t secondsSince1900) +{ + // shift to start of this 400 year cycle + auto partialResult = compute_year_1601(secondsSince1900 + secondsFrom1601To1900); + // shift back to 1900 + return {partialResult.year - 299, partialResult.secondsLeftThisYear}; } utility::string_t datetime::to_string(date_format format) const @@ -755,11 +765,11 @@ utility::string_t datetime::to_string(date_format format) const throw std::out_of_range("The requested year exceeds the year 9999."); } - const int64_t epochAdjusted = static_cast(m_interval) - NtTo1900OffsetInterval; - const int64_t secondsSince1900 = epochAdjusted / _secondTicks; // convert to seconds - const int fracSec = static_cast(epochAdjusted % _secondTicks); + const int64_t interval = static_cast(m_interval); + const int64_t secondsSince1601 = interval / _secondTicks; // convert to seconds + const int fracSec = static_cast(interval % _secondTicks); - const auto yearData = compute_year(secondsSince1900); + const auto yearData = compute_year_1601(secondsSince1601); const int year = yearData.year; const int yearDay = yearData.secondsLeftThisYear / SecondsInDay; int leftover = yearData.secondsLeftThisYear % SecondsInDay; @@ -768,7 +778,7 @@ utility::string_t datetime::to_string(date_format format) const const int minute = leftover / SecondsInMinute; leftover = leftover % SecondsInMinute; - const auto& monthTable = year_is_leap_year(year) ? cumulative_days_to_month_leap : cumulative_days_to_month; + const auto& monthTable = year_is_leap_year_1601(year) ? cumulative_days_to_month_leap : cumulative_days_to_month; int month = 0; while (month < 11 && monthTable[month + 1] <= yearDay) { @@ -776,7 +786,7 @@ utility::string_t datetime::to_string(date_format format) const } const auto monthDay = yearDay - monthTable[month] + 1; - const auto weekday = static_cast((secondsSince1900 / SecondsInDay + 1) % 7); + const auto weekday = static_cast((secondsSince1601 / SecondsInDay + 1) % 7); char outBuffer[38]; // Thu, 01 Jan 1970 00:00:00 GMT\0 // 1970-01-01T00:00:00.1234567Z\0 @@ -791,7 +801,7 @@ utility::string_t datetime::to_string(date_format format) const dayNames + 4 * weekday, monthDay, monthNames + 4 * month, - year + 1900, + year + 1601, hour, minute, leftover); @@ -801,7 +811,7 @@ utility::string_t datetime::to_string(date_format format) const dayNames + 4 * weekday, monthDay, monthNames + 4 * month, - year + 1900, + year + 1601, hour, minute, leftover); @@ -815,7 +825,7 @@ utility::string_t datetime::to_string(date_format format) const sprintf_s(outCursor, 20, "%04d-%02d-%02dT%02d:%02d:%02d", - year + 1900, + year + 1601, month + 1, monthDay, hour, @@ -823,7 +833,7 @@ utility::string_t datetime::to_string(date_format format) const leftover); #else // ^^^ _MSC_VER // !_MSC_VER vvv sprintf( - outCursor, "%04d-%02d-%02dT%02d:%02d:%02d", year + 1900, month + 1, monthDay, hour, minute, leftover); + outCursor, "%04d-%02d-%02dT%02d:%02d:%02d", year + 1601, month + 1, monthDay, hour, minute, leftover); #endif // _MSC_VER outCursor += 19; if (fracSec != 0) diff --git a/Release/tests/functional/utils/datetime.cpp b/Release/tests/functional/utils/datetime.cpp index a584b1e3c2..3949b000bf 100644 --- a/Release/tests/functional/utils/datetime.cpp +++ b/Release/tests/functional/utils/datetime.cpp @@ -502,6 +502,20 @@ SUITE(datetime) } } + TEST(can_emit_nt_epoch_zero) + { + // ISO 8601 + { + auto result = utility::datetime{}.to_string(utility::datetime::RFC_1123); + VERIFY_ARE_EQUAL(_XPLATSTR("Mon, 01 Jan 1601 00:00:00 GMT"), result); + } + // ISO 8601 + { + auto result = utility::datetime{}.to_string(utility::datetime::ISO_8601); + VERIFY_ARE_EQUAL(_XPLATSTR("1601-01-01T00:00:00Z"), result); + } + } + } // SUITE(datetime) } // namespace utils_tests From faa72d6847e329c97c540a34018790fceb68baf8 Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 25 Jan 2021 20:15:04 -0800 Subject: [PATCH 65/80] Introduce new API from_string_maximum_error so that legitimate 1601 can be distinguished from parse failure. --- Release/include/cpprest/asyncrt_utils.h | 23 +++++-- Release/src/utilities/asyncrt_utils.cpp | 14 +++- Release/tests/functional/utils/datetime.cpp | 76 +++++++++------------ 3 files changed, 62 insertions(+), 51 deletions(-) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 1b54f1634a..cadc6c715e 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -603,14 +603,21 @@ class datetime } } - datetime() : m_interval(0) {} + datetime() : m_interval(0) { } /// - /// Creates datetime from a string representing time in UTC in RFC 1123 format. + /// Creates datetime from a string representing time in UTC in RFC 1123 or ISO 8601 format. /// /// Returns a datetime of zero if not successful. static _ASYNCRTIMP datetime __cdecl from_string(const utility::string_t& timestring, date_format format = RFC_1123); + /// + /// Creates datetime from a string representing time in UTC in RFC 1123 or ISO 8601 format. + /// + /// Returns datetime::maximum() if not successful. + static _ASYNCRTIMP datetime __cdecl from_string_maximum_error(const utility::string_t& timestring, + date_format format = RFC_1123); + /// /// Returns a string representation of the datetime. /// @@ -628,13 +635,13 @@ class datetime bool operator==(datetime dt) const { return m_interval == dt.m_interval; } bool operator!=(const datetime& dt) const { return !(*this == dt); } - + bool operator>(const datetime& dt) const { return this->m_interval > dt.m_interval; } - + bool operator<(const datetime& dt) const { return this->m_interval < dt.m_interval; } - + bool operator>=(const datetime& dt) const { return this->m_interval >= dt.m_interval; } - + bool operator<=(const datetime& dt) const { return this->m_interval <= dt.m_interval; } static interval_type from_milliseconds(unsigned int milliseconds) { return milliseconds * _msTicks; } @@ -649,6 +656,8 @@ class datetime bool is_initialized() const { return m_interval != 0; } + static datetime maximum() { return datetime(static_cast(-1)); } + private: friend int operator-(datetime t1, datetime t2); @@ -659,7 +668,7 @@ class datetime static const interval_type _dayTicks = 24 * 60 * 60 * _secondTicks; // Private constructor. Use static methods to create an instance. - datetime(interval_type interval) : m_interval(interval) {} + datetime(interval_type interval) : m_interval(interval) { } // Storing as hundreds of nanoseconds 10e-7, i.e. 1 here equals 100ns. interval_type m_interval; diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index 7548bc5ea0..e392fc15ff 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -995,10 +995,20 @@ zone = "UT" / "GMT" ; Universal Time ; hours+min. (HHMM) */ - datetime __cdecl datetime::from_string(const utility::string_t& dateString, date_format format) { - datetime result; + auto result = from_string_maximum_error(dateString, format); + if (result == datetime::maximum()) + { + return datetime(); + } + + return result; +} + +datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& dateString, date_format format) +{ + datetime result = datetime::maximum(); int64_t secondsSince1900; uint64_t fracSec = 0; auto str = dateString.c_str(); diff --git a/Release/tests/functional/utils/datetime.cpp b/Release/tests/functional/utils/datetime.cpp index 3949b000bf..ab349beee3 100644 --- a/Release/tests/functional/utils/datetime.cpp +++ b/Release/tests/functional/utils/datetime.cpp @@ -10,6 +10,7 @@ ****/ #include "stdafx.h" + #include #include @@ -81,6 +82,10 @@ SUITE(datetime) auto dt = utility::datetime::from_string(str, utility::datetime::ISO_8601); utility::string_t str2 = dt.to_string(utility::datetime::ISO_8601); VERIFY_ARE_EQUAL(str2, strExpected); + + auto dt_me = utility::datetime::from_string_maximum_error(str, utility::datetime::ISO_8601); + utility::string_t str3 = dt_me.to_string(utility::datetime::ISO_8601); + VERIFY_ARE_EQUAL(str3, strExpected); } void TestDateTimeRoundtrip(utility::string_t str) { TestDateTimeRoundtrip(str, str); } @@ -123,32 +128,18 @@ SUITE(datetime) TestDateTimeRoundtrip(_XPLATSTR("2013-11-19T14:30:59.5Z")); } - TEST(parsing_time_roundtrip_year_1900) - { - TestDateTimeRoundtrip(_XPLATSTR("1900-01-01T00:00:00Z")); - } + TEST(parsing_time_roundtrip_year_1900) { TestDateTimeRoundtrip(_XPLATSTR("1900-01-01T00:00:00Z")); } - TEST(parsing_time_roundtrip_year_9999) - { - TestDateTimeRoundtrip(_XPLATSTR("9999-12-31T23:59:59Z")); - } + TEST(parsing_time_roundtrip_year_9999) { TestDateTimeRoundtrip(_XPLATSTR("9999-12-31T23:59:59Z")); } - TEST(parsing_time_roundtrip_year_2016) - { - TestDateTimeRoundtrip(_XPLATSTR("2016-12-31T20:59:59Z")); - } + TEST(parsing_time_roundtrip_year_2016) { TestDateTimeRoundtrip(_XPLATSTR("2016-12-31T20:59:59Z")); } - TEST(parsing_time_roundtrip_year_2020) - { - TestDateTimeRoundtrip(_XPLATSTR("2020-12-31T20:59:59Z")); - } + TEST(parsing_time_roundtrip_year_2020) { TestDateTimeRoundtrip(_XPLATSTR("2020-12-31T20:59:59Z")); } - TEST(parsing_time_roundtrip_year_2021) - { - TestDateTimeRoundtrip(_XPLATSTR("2021-01-01T20:59:59Z")); - } + TEST(parsing_time_roundtrip_year_2021) { TestDateTimeRoundtrip(_XPLATSTR("2021-01-01T20:59:59Z")); } - TEST(emitting_time_correct_day) { + TEST(emitting_time_correct_day) + { const auto test = utility::datetime() + UINT64_C(132004507640000000); // 2019-04-22T23:52:44 is a Monday const auto actual = test.to_string(utility::datetime::RFC_1123); const utility::string_t expected(_XPLATSTR("Mon")); @@ -296,13 +287,13 @@ SUITE(datetime) _XPLATSTR("Thu, 01 Jan 1970 00:00:00 G"), _XPLATSTR("Thu, 01 Jan 1970 00:00:00 GM"), _XPLATSTR("Fri, 01 Jan 1970 00:00:00 GMT"), // wrong day - _XPLATSTR("01 Jan 1899 00:00:00 GMT"), // year too small - _XPLATSTR("01 Xxx 1971 00:00:00 GMT"), // month bad - _XPLATSTR("00 Jan 1971 00:00:00 GMT"), // day too small - _XPLATSTR("32 Jan 1971 00:00:00 GMT"), // day too big - _XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb - _XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb (non-leap year) - _XPLATSTR("32 Mar 1971 00:00:00 GMT"), // other months + _XPLATSTR("01 Jan 1899 00:00:00 GMT"), // year too small + _XPLATSTR("01 Xxx 1971 00:00:00 GMT"), // month bad + _XPLATSTR("00 Jan 1971 00:00:00 GMT"), // day too small + _XPLATSTR("32 Jan 1971 00:00:00 GMT"), // day too big + _XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb + _XPLATSTR("30 Feb 1971 00:00:00 GMT"), // day too big for feb (non-leap year) + _XPLATSTR("32 Mar 1971 00:00:00 GMT"), // other months _XPLATSTR("31 Apr 1971 00:00:00 GMT"), _XPLATSTR("32 May 1971 00:00:00 GMT"), _XPLATSTR("31 Jun 1971 00:00:00 GMT"), @@ -317,8 +308,8 @@ SUITE(datetime) _XPLATSTR("01 Jan 1971 00:60:00 GMT"), // minute too big _XPLATSTR("01 Jan 1971 00:00:70 GMT"), // second too big _XPLATSTR("01 Jan 1971 00:00:61 GMT"), - _XPLATSTR("01 Jan 1899 00:00:00 GMT"), // underflow - _XPLATSTR("01 Jan 1969 00:00:00 CEST"), // bad tz + _XPLATSTR("01 Jan 1899 00:00:00 GMT"), // underflow + _XPLATSTR("01 Jan 1969 00:00:00 CEST"), // bad tz _XPLATSTR("14 Jan 2019 23:16:21 G0100"), // bad tzoffsets _XPLATSTR("01 Jan 1970 00:00:00 +2400"), _XPLATSTR("01 Jan 1970 00:00:00 -3000"), @@ -332,6 +323,8 @@ SUITE(datetime) { auto dt = utility::datetime::from_string(str, utility::datetime::RFC_1123); VERIFY_ARE_EQUAL(0, dt.to_interval()); + auto dt_me = utility::datetime::from_string_maximum_error(str, utility::datetime::RFC_1123); + VERIFY_ARE_EQUAL(utility::datetime::maximum(), dt_me); } } @@ -484,7 +477,7 @@ SUITE(datetime) _XPLATSTR("1971-01-01T00:60:00Z"), // minute too big _XPLATSTR("1971-01-01T00:00:70Z"), // second too big _XPLATSTR("1971-01-01T00:00:61Z"), - _XPLATSTR("1899-01-01T00:00:00Z"), // underflow + _XPLATSTR("1899-01-01T00:00:00Z"), // underflow _XPLATSTR("1900-01-01T00:00:00+00:01"), // time zone underflow // _XPLATSTR("1970-01-01T00:00:00.Z"), // accepted as invalid timezone above _XPLATSTR("1970-01-01T00:00:00+24:00"), // bad tzoffsets @@ -499,23 +492,22 @@ SUITE(datetime) { auto dt = utility::datetime::from_string(str, utility::datetime::ISO_8601); VERIFY_ARE_EQUAL(dt.to_interval(), 0); + auto dt_me = utility::datetime::from_string_maximum_error(str, utility::datetime::ISO_8601); + VERIFY_ARE_EQUAL(dt_me, utility::datetime::maximum()); } } - TEST(can_emit_nt_epoch_zero) + TEST(can_emit_nt_epoch_zero_rfc_1123) { - // ISO 8601 - { - auto result = utility::datetime{}.to_string(utility::datetime::RFC_1123); - VERIFY_ARE_EQUAL(_XPLATSTR("Mon, 01 Jan 1601 00:00:00 GMT"), result); - } - // ISO 8601 - { - auto result = utility::datetime{}.to_string(utility::datetime::ISO_8601); - VERIFY_ARE_EQUAL(_XPLATSTR("1601-01-01T00:00:00Z"), result); - } + auto result = utility::datetime {}.to_string(utility::datetime::RFC_1123); + VERIFY_ARE_EQUAL(_XPLATSTR("Mon, 01 Jan 1601 00:00:00 GMT"), result); } + TEST(can_emit_nt_epoch_zero_iso_8601) + { + auto result = utility::datetime {}.to_string(utility::datetime::ISO_8601); + VERIFY_ARE_EQUAL(_XPLATSTR("1601-01-01T00:00:00Z"), result); + } } // SUITE(datetime) } // namespace utils_tests From a3da3e9fe3868d81848dd3946b1aa97699d8d62f Mon Sep 17 00:00:00 2001 From: Billy Robert O'Neal III Date: Mon, 25 Jan 2021 20:51:18 -0800 Subject: [PATCH 66/80] Added the ability to parse years back to 1601 to support the NT epoch. --- Release/include/cpprest/asyncrt_utils.h | 2 + Release/src/utilities/asyncrt_utils.cpp | 108 ++++++++++---------- Release/tests/functional/utils/datetime.cpp | 51 ++++++++- 3 files changed, 104 insertions(+), 57 deletions(-) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index cadc6c715e..3e4bfdd5c4 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -628,6 +628,8 @@ class datetime /// interval_type to_interval() const { return m_interval; } + static datetime from_interval(interval_type interval) { return datetime(interval); } + datetime operator-(interval_type value) const { return datetime(m_interval - value); } datetime operator+(interval_type value) const { return datetime(m_interval + value); } diff --git a/Release/src/utilities/asyncrt_utils.cpp b/Release/src/utilities/asyncrt_utils.cpp index e392fc15ff..cf747c666c 100644 --- a/Release/src/utilities/asyncrt_utils.cpp +++ b/Release/src/utilities/asyncrt_utils.cpp @@ -620,14 +620,12 @@ utf16string __cdecl conversions::to_utf16string(const std::string& value) { retu static const int64_t NtToUnixOffsetSeconds = 11644473600; // diff between windows and unix epochs (seconds) -static bool year_is_leap_year_1601(int year) +static bool year_is_leap_year_1601(int yearsSince1601) { - int decimal_year = year + 1601; - return (decimal_year % 4 == 0 && (decimal_year % 100 != 0 || decimal_year % 400 == 0)); + int decimalYear = yearsSince1601 + 1601; + return (decimalYear % 4 == 0 && (decimalYear % 100 != 0 || decimalYear % 400 == 0)); } -static bool year_is_leap_year(int year) { return year_is_leap_year_1601(year + 299); } - static const int SecondsInMinute = 60; static const int SecondsInHour = SecondsInMinute * 60; static const int SecondsInDay = SecondsInHour * 24; @@ -641,9 +639,6 @@ static const int SecondsInYear = SecondsInDay * DaysInYear; static const int SecondsIn4Years = SecondsInDay * DaysIn4Years; static const int64_t SecondsIn100Years = static_cast(SecondsInDay) * DaysIn100Years; static const int64_t SecondsIn400Years = static_cast(SecondsInDay) * DaysIn400Years; -static const int64_t SecondsFrom1900To2001 = INT64_C(3187296000); - -static const int64_t NtTo1900OffsetInterval = INT64_C(0x014F373BFDE04000); static int count_leap_years_1601(int yearsSince1601) { @@ -660,12 +655,6 @@ static int count_leap_years_1601(int yearsSince1601) return result; } -static int count_leap_years(const int yearsSince1900) -{ - // shift into 1601, the first 400 year cycle including 1900, then subtract leap years from 1601->1900 - return count_leap_years_1601(yearsSince1900 + 299) - 72; -} - // The following table assumes no leap year; leap year is added separately static const unsigned short cumulative_days_to_month[12] = { 0, // Jan @@ -749,23 +738,37 @@ static compute_year_result compute_year_1601(int64_t secondsSince1601) return {year400 * 400 + year100 * 100 + year4 * 4 + year1, secondsInt}; } -static const int64_t secondsFrom1601To1900 = INT64_C(9435484800); -static compute_year_result compute_year(int64_t secondsSince1900) -{ - // shift to start of this 400 year cycle - auto partialResult = compute_year_1601(secondsSince1900 + secondsFrom1601To1900); - // shift back to 1900 - return {partialResult.year - 299, partialResult.secondsLeftThisYear}; -} +// The constant below was calculated by running the following test program on a Windows machine: +// #include +// #include + +// int main() { +// SYSTEMTIME st; +// st.wYear = 9999; +// st.wMonth = 12; +// st.wDayOfWeek = 5; +// st.wDay = 31; +// st.wHour = 23; +// st.wMinute = 59; +// st.wSecond = 59; +// st.wMilliseconds = 999; + +// unsigned long long ft; +// if (SystemTimeToFileTime(&st, reinterpret_cast(&ft))) { +// printf("0x%016llX\n", ft); +// } else { +// puts("failed!"); +// } +// } utility::string_t datetime::to_string(date_format format) const { - if (m_interval > INT64_C(2650467743990000000)) + const int64_t interval = static_cast(m_interval); + if (interval > INT64_C(0x24C85A5ED1C018F0)) { throw std::out_of_range("The requested year exceeds the year 9999."); } - const int64_t interval = static_cast(m_interval); const int64_t secondsSince1601 = interval / _secondTicks; // convert to seconds const int fracSec = static_cast(interval % _secondTicks); @@ -899,12 +902,12 @@ static const unsigned char max_days_in_month[12] = { 31 // Dec }; -static bool validate_day_month(int day, int month, int year) +static bool validate_day_month_1601(int day, int month, int year) { int maxDaysThisMonth; if (month == 1) { // Feb needs leap year testing - maxDaysThisMonth = 28 + year_is_leap_year(year); + maxDaysThisMonth = 28 + year_is_leap_year_1601(year); } else { @@ -914,9 +917,9 @@ static bool validate_day_month(int day, int month, int year) return day >= 1 && day <= maxDaysThisMonth; } -static int get_year_day(int month, int monthDay, int year) +static int get_year_day_1601(int month, int monthDay, int year) { - return cumulative_days_to_month[month] + monthDay + (year_is_leap_year(year) && month > 1) - 1; + return cumulative_days_to_month[month] + monthDay + (year_is_leap_year_1601(year) && month > 1) - 1; } template @@ -1009,7 +1012,7 @@ datetime __cdecl datetime::from_string(const utility::string_t& dateString, date datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& dateString, date_format format) { datetime result = datetime::maximum(); - int64_t secondsSince1900; + int64_t secondsSince1601; uint64_t fracSec = 0; auto str = dateString.c_str(); if (format == RFC_1123) @@ -1076,19 +1079,21 @@ datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& da int year = (str[0] - _XPLATSTR('0')) * 1000 + (str[1] - _XPLATSTR('0')) * 100 + (str[2] - _XPLATSTR('0')) * 10 + (str[3] - _XPLATSTR('0')); - if (year < 1900) + if (year < 1601) { return result; } + year -= 1601; + // days in month validity check - if (!validate_day_month(monthDay, month, year)) + if (!validate_day_month_1601(monthDay, month, year)) { return result; } str += 5; // parsed year - const int yearDay = get_year_day(month, monthDay, year); + const int yearDay = get_year_day_1601(month, monthDay, year); if (!ascii_isdigit2(str[0]) || !ascii_isdigit(str[1]) || str[2] != _XPLATSTR(':') || !ascii_isdigit5(str[3]) || !ascii_isdigit(str[4])) @@ -1132,12 +1137,11 @@ datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& da return result; } - year -= 1900; - int daysSince1900 = year * DaysInYear + count_leap_years(year) + yearDay; + int daysSince1601 = year * DaysInYear + count_leap_years_1601(year) + yearDay; if (parsedWeekday != 7) { - const int actualWeekday = (daysSince1900 + 1) % 7; + const int actualWeekday = (daysSince1601 + 1) % 7; if (parsedWeekday != actualWeekday) { @@ -1145,8 +1149,8 @@ datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& da } } - secondsSince1900 = - static_cast(daysSince1900) * SecondsInDay + hour * SecondsInHour + minute * SecondsInMinute + sec; + secondsSince1601 = + static_cast(daysSince1601) * SecondsInDay + hour * SecondsInHour + minute * SecondsInMinute + sec; if (!string_starts_with(str, "GMT") && !string_starts_with(str, "UT")) { @@ -1186,8 +1190,8 @@ datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& da return result; } - secondsSince1900 = timezone_adjust(secondsSince1900, static_cast(tzCh), tzHours, tzMinutes); - if (secondsSince1900 < 0) + secondsSince1601 = timezone_adjust(secondsSince1601, static_cast(tzCh), tzHours, tzMinutes); + if (secondsSince1601 < 0) { return result; } @@ -1203,11 +1207,13 @@ datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& da int year = (str[0] - _XPLATSTR('0')) * 1000 + (str[1] - _XPLATSTR('0')) * 100 + (str[2] - _XPLATSTR('0')) * 10 + (str[3] - _XPLATSTR('0')); - if (year < 1900) + if (year < 1601) { return result; } + year -= 1601; + str += 4; if (*str == _XPLATSTR('-')) { @@ -1241,24 +1247,22 @@ datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& da } int monthDay = atoi2(str); - if (!validate_day_month(monthDay, month, year)) + if (!validate_day_month_1601(monthDay, month, year)) { return result; } - const int yearDay = get_year_day(month, monthDay, year); + const int yearDay = get_year_day_1601(month, monthDay, year); str += 2; - year -= 1900; - int daysSince1900 = year * DaysInYear + count_leap_years(year) + yearDay; + int daysSince1601 = year * DaysInYear + count_leap_years_1601(year) + yearDay; if (str[0] != _XPLATSTR('T') && str[0] != _XPLATSTR('t')) { // No time - secondsSince1900 = static_cast(daysSince1900) * SecondsInDay; + secondsSince1601 = static_cast(daysSince1601) * SecondsInDay; - result.m_interval = - static_cast(secondsSince1900 * _secondTicks + fracSec + NtTo1900OffsetInterval); + result.m_interval = static_cast(secondsSince1601 * _secondTicks + fracSec); return result; } @@ -1347,8 +1351,8 @@ datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& da } } - secondsSince1900 = - static_cast(daysSince1900) * SecondsInDay + hour * SecondsInHour + minute * SecondsInMinute + sec; + secondsSince1601 = + static_cast(daysSince1601) * SecondsInDay + hour * SecondsInHour + minute * SecondsInMinute + sec; if (str[0] == _XPLATSTR('Z') || str[0] == _XPLATSTR('z')) { @@ -1363,8 +1367,8 @@ datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& da return result; } - secondsSince1900 = timezone_adjust(secondsSince1900, offsetDirection, atoi2(str + 1), atoi2(str + 4)); - if (secondsSince1900 < 0) + secondsSince1601 = timezone_adjust(secondsSince1601, offsetDirection, atoi2(str + 1), atoi2(str + 4)); + if (secondsSince1601 < 0) { return result; } @@ -1379,7 +1383,7 @@ datetime __cdecl datetime::from_string_maximum_error(const utility::string_t& da throw std::invalid_argument("unrecognized date format"); } - result.m_interval = static_cast(secondsSince1900 * _secondTicks + fracSec + NtTo1900OffsetInterval); + result.m_interval = static_cast(secondsSince1601 * _secondTicks + fracSec); return result; } diff --git a/Release/tests/functional/utils/datetime.cpp b/Release/tests/functional/utils/datetime.cpp index ab349beee3..22954ca942 100644 --- a/Release/tests/functional/utils/datetime.cpp +++ b/Release/tests/functional/utils/datetime.cpp @@ -138,6 +138,14 @@ SUITE(datetime) TEST(parsing_time_roundtrip_year_2021) { TestDateTimeRoundtrip(_XPLATSTR("2021-01-01T20:59:59Z")); } + TEST(parsing_time_roundtrip_year_1601) { TestDateTimeRoundtrip(_XPLATSTR("1601-01-01T00:00:00Z")); } + + TEST(parsing_time_roundtrip_year_1602) { TestDateTimeRoundtrip(_XPLATSTR("1602-01-01T00:00:00Z")); } + + TEST(parsing_time_roundtrip_year_1603) { TestDateTimeRoundtrip(_XPLATSTR("1603-01-01T00:00:00Z")); } + + TEST(parsing_time_roundtrip_year_1604) { TestDateTimeRoundtrip(_XPLATSTR("1604-01-01T00:00:00Z")); } + TEST(emitting_time_correct_day) { const auto test = utility::datetime() + UINT64_C(132004507640000000); // 2019-04-22T23:52:44 is a Monday @@ -287,7 +295,7 @@ SUITE(datetime) _XPLATSTR("Thu, 01 Jan 1970 00:00:00 G"), _XPLATSTR("Thu, 01 Jan 1970 00:00:00 GM"), _XPLATSTR("Fri, 01 Jan 1970 00:00:00 GMT"), // wrong day - _XPLATSTR("01 Jan 1899 00:00:00 GMT"), // year too small + _XPLATSTR("01 Jan 1600 00:00:00 GMT"), // year too small _XPLATSTR("01 Xxx 1971 00:00:00 GMT"), // month bad _XPLATSTR("00 Jan 1971 00:00:00 GMT"), // day too small _XPLATSTR("32 Jan 1971 00:00:00 GMT"), // day too big @@ -308,7 +316,7 @@ SUITE(datetime) _XPLATSTR("01 Jan 1971 00:60:00 GMT"), // minute too big _XPLATSTR("01 Jan 1971 00:00:70 GMT"), // second too big _XPLATSTR("01 Jan 1971 00:00:61 GMT"), - _XPLATSTR("01 Jan 1899 00:00:00 GMT"), // underflow + _XPLATSTR("01 Jan 1600 00:00:00 GMT"), // underflow _XPLATSTR("01 Jan 1969 00:00:00 CEST"), // bad tz _XPLATSTR("14 Jan 2019 23:16:21 G0100"), // bad tzoffsets _XPLATSTR("01 Jan 1970 00:00:00 +2400"), @@ -454,7 +462,7 @@ SUITE(datetime) _XPLATSTR("1970-01-01T00:00:"), _XPLATSTR("1970-01-01T00:00:0"), // _XPLATSTR("1970-01-01T00:00:00"), // accepted as invalid timezone above - _XPLATSTR("1899-01-01T00:00:00Z"), // year too small + _XPLATSTR("1600-01-01T00:00:00Z"), // year too small _XPLATSTR("1971-00-01T00:00:00Z"), // month too small _XPLATSTR("1971-20-01T00:00:00Z"), // month too big _XPLATSTR("1971-13-01T00:00:00Z"), @@ -477,8 +485,8 @@ SUITE(datetime) _XPLATSTR("1971-01-01T00:60:00Z"), // minute too big _XPLATSTR("1971-01-01T00:00:70Z"), // second too big _XPLATSTR("1971-01-01T00:00:61Z"), - _XPLATSTR("1899-01-01T00:00:00Z"), // underflow - _XPLATSTR("1900-01-01T00:00:00+00:01"), // time zone underflow + _XPLATSTR("1600-01-01T00:00:00Z"), // underflow + _XPLATSTR("1601-01-01T00:00:00+00:01"), // time zone underflow // _XPLATSTR("1970-01-01T00:00:00.Z"), // accepted as invalid timezone above _XPLATSTR("1970-01-01T00:00:00+24:00"), // bad tzoffsets _XPLATSTR("1970-01-01T00:00:00-30:00"), @@ -508,6 +516,39 @@ SUITE(datetime) auto result = utility::datetime {}.to_string(utility::datetime::ISO_8601); VERIFY_ARE_EQUAL(_XPLATSTR("1601-01-01T00:00:00Z"), result); } + + TEST(can_emit_year_9999_rfc_1123) + { + auto result = + utility::datetime::from_interval(INT64_C(0x24C85A5ED1C018F0)).to_string(utility::datetime::RFC_1123); + VERIFY_ARE_EQUAL(_XPLATSTR("Fri, 31 Dec 9999 23:59:59 GMT"), result); + } + + TEST(can_emit_year_9999_iso_8601) + { + auto result = + utility::datetime::from_interval(INT64_C(0x24C85A5ED1C018F0)).to_string(utility::datetime::ISO_8601); + VERIFY_ARE_EQUAL(_XPLATSTR("9999-12-31T23:59:59.999Z"), result); + } + + TEST(can_parse_nt_epoch_zero_rfc_1123) + { + auto dt = + utility::datetime::from_string(_XPLATSTR("Mon, 01 Jan 1601 00:00:00 GMT"), utility::datetime::RFC_1123); + VERIFY_ARE_EQUAL(0U, dt.to_interval()); + auto dt_me = utility::datetime::from_string_maximum_error(_XPLATSTR("Mon, 01 Jan 1601 00:00:00 GMT"), + utility::datetime::RFC_1123); + VERIFY_ARE_EQUAL(0U, dt_me.to_interval()); + } + + TEST(can_parse_nt_epoch_zero_iso_8601) + { + auto dt = utility::datetime::from_string(_XPLATSTR("1601-01-01T00:00:00Z"), utility::datetime::ISO_8601); + VERIFY_ARE_EQUAL(0U, dt.to_interval()); + auto dt_me = utility::datetime::from_string_maximum_error(_XPLATSTR("1601-01-01T00:00:00Z"), + utility::datetime::ISO_8601); + VERIFY_ARE_EQUAL(0U, dt_me.to_interval()); + } } // SUITE(datetime) } // namespace utils_tests From 42dbc767f03a24bc7f96b484c1d8cee512c9a19e Mon Sep 17 00:00:00 2001 From: Charlie Date: Mon, 1 Feb 2021 11:13:23 -0800 Subject: [PATCH 67/80] add boost locale vcpkg to CI builds. --- azure-devops/build-ubuntu-vcpkg.yml | 2 +- azure-pipelines.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-devops/build-ubuntu-vcpkg.yml b/azure-devops/build-ubuntu-vcpkg.yml index bc14ecd87b..aeae2b7ea5 100644 --- a/azure-devops/build-ubuntu-vcpkg.yml +++ b/azure-devops/build-ubuntu-vcpkg.yml @@ -13,7 +13,7 @@ jobs: sudo apt install g++-9 ninja-build -y git submodule update --init vcpkg ./vcpkg/bootstrap-vcpkg.sh - ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg + ./vcpkg/vcpkg install zlib openssl boost-locale boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg displayName: Vcpkg install dependencies - script: | mkdir build.debug diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7df61d453a..96a6c9c066 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -121,7 +121,7 @@ jobs: displayName: Checkout vcpkg submodule - script: | ./vcpkg/bootstrap-vcpkg.sh - ./vcpkg/vcpkg install zlib openssl boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg + ./vcpkg/vcpkg install zlib openssl boost-locale boost-system boost-date-time boost-regex websocketpp boost-thread boost-filesystem boost-random boost-chrono boost-interprocess brotli --vcpkg-root ./vcpkg displayName: Vcpkg install dependencies - script: | mkdir build.debug From 977769e8f3799eabd5ab94aa63020bfa28bca0a1 Mon Sep 17 00:00:00 2001 From: Charlie Date: Mon, 1 Feb 2021 19:50:19 -0800 Subject: [PATCH 68/80] fix macos-vcpkg pipelines --- azure-pipelines.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 96a6c9c066..b83222df04 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -130,14 +130,14 @@ jobs: - task: CMake@1 inputs: workingDirectory: 'build.debug' - cmakeArgs: '-G Ninja -DCMAKE_MAKE_PROGRAM=$(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.0-osx/ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + cmakeArgs: '-G Ninja -DCMAKE_MAKE_PROGRAM=$(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.1-osx/ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' - task: CMake@1 inputs: workingDirectory: 'build.release' - cmakeArgs: '-G Ninja -DCMAKE_MAKE_PROGRAM=$(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.0-osx/ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' + cmakeArgs: '-G Ninja -DCMAKE_MAKE_PROGRAM=$(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.1-osx/ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake ..' - script: | cd build.debug - $(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.0-osx/ninja + $(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.1-osx/ninja displayName: 'Run ninja debug' - script: | cd build.debug/Release/Binaries @@ -145,7 +145,7 @@ jobs: displayName: 'Run Tests debug' - script: | cd build.release - $(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.0-osx/ninja + $(Build.SourcesDirectory)/vcpkg/downloads/tools/ninja-1.10.1-osx/ninja displayName: 'Run ninja, release' - script: | cd build.release/Release/Binaries From 122d09549201da5383321d870bed45ecb9e168c5 Mon Sep 17 00:00:00 2001 From: Charlie Date: Mon, 1 Feb 2021 20:03:00 -0800 Subject: [PATCH 69/80] mint 2.10.18 --- Release/CMakeLists.txt | 2 +- Release/include/cpprest/version.h | 2 +- changelog.md | 6 ++++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 441cdf8c28..b8f3809dbc 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 17) +set(CPPREST_VERSION_REVISION 18) enable_testing() diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index 2787e276c7..d8771581ad 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -5,6 +5,6 @@ */ #define CPPREST_VERSION_MINOR 10 #define CPPREST_VERSION_MAJOR 2 -#define CPPREST_VERSION_REVISION 17 +#define CPPREST_VERSION_REVISION 18 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR * 100000 + CPPREST_VERSION_MINOR * 100 + CPPREST_VERSION_REVISION) diff --git a/changelog.md b/changelog.md index 6e912c80e1..c547665912 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,9 @@ +cpprestsdk (2.10.18) +* PR#1571 Add ability to parse and emit the NT Epoch 1601-01-01T00:00:00Z +* PR#1571 Update vcpkg submodule +* Update CI configuration +-- cpprestsdk team MON, 1 Feb 2021 20:02:00 -0700 + cpprestsdk (2.10.17) * PR#1550 Fix year calculation for the last day of a leap year * PR#1523 Fix wrong linking of Apple Frameworks on MacOS From 80444805898842f7e5c62b256337c0897eb254bb Mon Sep 17 00:00:00 2001 From: Jeffrey van de Glind Date: Wed, 17 Feb 2021 08:42:14 +0100 Subject: [PATCH 70/80] export http_exception for non Windows builds If a project compiled with clang for macos links to CppRest, and the -fvisibility=hidden compiler option is used, the http_exception is used as std::exception. The clang compiler requires it to be exported in order to know about the symbols. Since the Visual Studio compiler throws warnings regarding the export of a class that inherits from a non-exported class, std::exception in this case, this export is only defined for clang. --- Release/include/cpprest/details/cpprest_compat.h | 8 ++++++++ Release/include/cpprest/http_msg.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Release/include/cpprest/details/cpprest_compat.h b/Release/include/cpprest/details/cpprest_compat.h index 6dae41d8d9..bf10747987 100644 --- a/Release/include/cpprest/details/cpprest_compat.h +++ b/Release/include/cpprest/details/cpprest_compat.h @@ -71,12 +71,20 @@ #ifdef _NO_ASYNCRTIMP #define _ASYNCRTIMP +#define _ASYNCRTIMP_TYPEINFO #else // ^^^ _NO_ASYNCRTIMP ^^^ // vvv !_NO_ASYNCRTIMP vvv #ifdef _ASYNCRT_EXPORT #define _ASYNCRTIMP __declspec(dllexport) #else // ^^^ _ASYNCRT_EXPORT ^^^ // vvv !_ASYNCRT_EXPORT vvv #define _ASYNCRTIMP __declspec(dllimport) #endif // _ASYNCRT_EXPORT + +#if defined(_WIN32) +#define _ASYNCRTIMP_TYPEINFO +#else // ^^^ _WIN32 ^^^ // vvv !_WIN32 vvv +#define _ASYNCRTIMP_TYPEINFO __attribute__((visibility("default"))) +#endif // _WIN32 + #endif // _NO_ASYNCRTIMP #ifdef CASABLANCA_DEPRECATION_NO_WARNINGS diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 50f05ef213..55c0433c94 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -187,7 +187,7 @@ class header_names /// /// Represents an HTTP error. This class holds an error message and an optional error code. /// -class http_exception : public std::exception +class _ASYNCRTIMP_TYPEINFO http_exception : public std::exception { public: /// From 0ddc6182943f43a71453c97640ae7987d1868ea8 Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Mon, 8 Mar 2021 11:37:25 -0800 Subject: [PATCH 71/80] Clarify cpprestsdk level of support --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5d9cd4c0a6..e7d91abeaa 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +**cpprestsdk is in maintenance mode and we do not recommend its use in new projects. We will continue to fix critical bugs and address security issues.** + ## Welcome! The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services. From 06363bc78325e9541dd9fa2a6eab291d3f3c8596 Mon Sep 17 00:00:00 2001 From: NN <580536+NN---@users.noreply.github.com> Date: Thu, 10 Mar 2022 22:38:13 +0200 Subject: [PATCH 72/80] Update Release/include/cpprest/json.h Co-authored-by: Charlie Barto --- Release/include/cpprest/json.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index 84bf2b89d6..78e20c4d9e 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -1248,8 +1248,8 @@ class number number(unsigned value) : m_intval(value), m_type(unsigned_type) {} number(long value) : m_intval(value), m_type(value < 0 ? signed_type : unsigned_type) {} number(unsigned long value) : m_uintval(value), m_type(unsigned_type) {} - number(long long value) : m_intval(value), m_type(value < 0 ? signed_type : unsigned_type) { } - number(unsigned long long value) : m_uintval(value), m_type(unsigned_type) { } + number(long long value) : m_intval(value), m_type(value < 0 ? signed_type : unsigned_type) {} + number(unsigned long long value) : m_uintval(value), m_type(unsigned_type) {} public: /// From 3eac925ada68dc2df6a5b688fdfb79865e04a6f3 Mon Sep 17 00:00:00 2001 From: NN <580536+NN---@users.noreply.github.com> Date: Thu, 10 Mar 2022 22:38:30 +0200 Subject: [PATCH 73/80] Update Release/include/cpprest/json.h Co-authored-by: Charlie Barto --- Release/include/cpprest/json.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index 78e20c4d9e..9549f9b8d5 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -1470,8 +1470,8 @@ class _Number : public _Value _Number(unsigned value) : m_number(value) {} _Number(long value) : m_number(value) {} _Number(unsigned long value) : m_number(value) {} - _Number(long long value) : m_number(value) { } - _Number(unsigned long long value) : m_number(value) { } + _Number(long long value) : m_number(value) {} + _Number(unsigned long long value) : m_number(value) {} virtual std::unique_ptr<_Value> _copy_value() { return utility::details::make_unique<_Number>(*this); } From 3308d97280a076327d3f2abe31253323274a7692 Mon Sep 17 00:00:00 2001 From: Fighter19 <1475802+Fighter19@users.noreply.github.com> Date: Fri, 1 Jul 2022 14:19:04 +0200 Subject: [PATCH 74/80] Fix likely typo in SafeInt3.hpp, that results in error with clang 15 --- Release/include/cpprest/details/SafeInt3.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/details/SafeInt3.hpp b/Release/include/cpprest/details/SafeInt3.hpp index 950ac80172..e6276f949b 100644 --- a/Release/include/cpprest/details/SafeInt3.hpp +++ b/Release/include/cpprest/details/SafeInt3.hpp @@ -1574,7 +1574,7 @@ class SafeCastHelper } template - static void CastThrow(bool b, T& t) SAFEINT_CPP_THROW + static void CastThrow(T t, bool& b) SAFEINT_CPP_THROW { b = !!t; } From a57f4591876a4565ce21ee1bac1904cb49adc424 Mon Sep 17 00:00:00 2001 From: "microsoft-github-policy-service[bot]" <77245923+microsoft-github-policy-service[bot]@users.noreply.github.com> Date: Wed, 31 Aug 2022 15:23:18 +0000 Subject: [PATCH 75/80] Microsoft mandatory file --- SECURITY.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..869fdfe2b2 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + From 98ee36dacd1844a5a6861d4a8cc20ec3aad5c9e9 Mon Sep 17 00:00:00 2001 From: Ye Cao Date: Mon, 19 Sep 2022 22:50:48 +0800 Subject: [PATCH 76/80] Fix typo --- Release/include/cpprest/producerconsumerstream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Release/include/cpprest/producerconsumerstream.h b/Release/include/cpprest/producerconsumerstream.h index 28463372e4..3487c4606f 100644 --- a/Release/include/cpprest/producerconsumerstream.h +++ b/Release/include/cpprest/producerconsumerstream.h @@ -584,7 +584,7 @@ class basic_producer_consumer_buffer : public streams::details::streambuf_state_ // If front block is not empty - we are done if (m_blocks.front()->rd_chars_left() > 0) break; - // The block has no more data to be read. Relase the block + // The block has no more data to be read. Release the block m_blocks.pop_front(); } } From 9c654889efb6f5bda69fe8f52b3f7d3d3fb56cd8 Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Wed, 16 Nov 2022 13:07:45 -0800 Subject: [PATCH 77/80] Remove email list from the readme It's better to use issues, so everyone can see the responses. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e7d91abeaa..c2e8f3cbdb 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ target_link_libraries(main PRIVATE cpprestsdk::cpprest) Is there a feature missing that you'd like to see, or found a bug that you have a fix for? Or do you have an idea or just interest in helping out in building the library? Let us know and we'd love to work with you. For a good starting point on where we are headed and feature ideas, take a look at our [requested features and bugs](https://github.com/Microsoft/cpprestsdk/issues). -Big or small we'd like to take your [contributions](https://github.com/Microsoft/cpprestsdk/wiki/Make-a-contribution-and-report-issues) back to help improve the C++ Rest SDK for everyone. If interested contact us askcasablanca at Microsoft dot com. +Big or small we'd like to take your [contributions](https://github.com/Microsoft/cpprestsdk/wiki/Make-a-contribution-and-report-issues) back to help improve the C++ Rest SDK for everyone. ## Having Trouble? From 006271f6a782141a7c9cef17e6d76f080c022add Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Mon, 4 Dec 2023 19:58:39 -0800 Subject: [PATCH 78/80] make Uri.is_host_loopback() only return true for localhost and 127.0.0.1 exactly --- Release/include/cpprest/base_uri.h | 5 +++-- Release/tests/functional/uri/constructor_tests.cpp | 5 +++++ Release/tests/functional/uri/diagnostic_tests.cpp | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Release/include/cpprest/base_uri.h b/Release/include/cpprest/base_uri.h index 7c6943119c..7e96b6c016 100644 --- a/Release/include/cpprest/base_uri.h +++ b/Release/include/cpprest/base_uri.h @@ -296,13 +296,14 @@ class uri /// A loopback URI is one which refers to a hostname or ip address with meaning only on the local machine. /// /// - /// Examples include "localhost", or ip addresses in the loopback range (127.0.0.0/24). + /// Examples include "localhost", or "127.0.0.1". The only URIs for which this method returns true are "127.0.0.1", and "localhost", + /// all other URIs return false /// /// true if this URI references the local host, false otherwise. bool is_host_loopback() const { return !is_empty() && - ((host() == _XPLATSTR("localhost")) || (host().size() > 4 && host().substr(0, 4) == _XPLATSTR("127."))); + ((host() == _XPLATSTR("localhost")) || (host() == _XPLATSTR("127.0.0.1"))); } /// diff --git a/Release/tests/functional/uri/constructor_tests.cpp b/Release/tests/functional/uri/constructor_tests.cpp index ea6041c26a..ffcf5ada27 100644 --- a/Release/tests/functional/uri/constructor_tests.cpp +++ b/Release/tests/functional/uri/constructor_tests.cpp @@ -24,6 +24,11 @@ namespace uri_tests { SUITE(constructor_tests) { + TEST(not_really_a_loopback_uri) + { + uri u(uri::encode_uri(U("https://127.evil.com"))); + VERIFY_IS_FALSE(u.is_host_loopback()); + } TEST(parsing_constructor_char) { uri u(uri::encode_uri(U("net.tcp://steve:@testname.com:81/bleh%?qstring#goo"))); diff --git a/Release/tests/functional/uri/diagnostic_tests.cpp b/Release/tests/functional/uri/diagnostic_tests.cpp index d8fb45d91c..3271898f60 100644 --- a/Release/tests/functional/uri/diagnostic_tests.cpp +++ b/Release/tests/functional/uri/diagnostic_tests.cpp @@ -82,7 +82,7 @@ SUITE(diagnostic_tests) VERIFY_IS_FALSE(uri(U("http://bleh/?qstring")).is_host_loopback()); VERIFY_IS_FALSE(uri(U("http://+*/?qstring")).is_host_loopback()); VERIFY_IS_TRUE(uri(U("http://127.0.0.1/")).is_host_loopback()); - VERIFY_IS_TRUE(uri(U("http://127.155.0.1/")).is_host_loopback()); + VERIFY_IS_FALSE(uri(U("http://127.155.0.1/")).is_host_loopback()); VERIFY_IS_FALSE(uri(U("http://128.0.0.1/")).is_host_loopback()); } From 411a109150b270f23c8c97fa4ec9a0a4a98cdecf Mon Sep 17 00:00:00 2001 From: Charlie Barto Date: Mon, 4 Dec 2023 20:23:31 -0800 Subject: [PATCH 79/80] mint 2.10.19 --- Release/CMakeLists.txt | 2 +- Release/include/cpprest/version.h | 2 +- changelog.md | 9 +++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index b8f3809dbc..14e43cedcd 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -11,7 +11,7 @@ endif() set(CPPREST_VERSION_MAJOR 2) set(CPPREST_VERSION_MINOR 10) -set(CPPREST_VERSION_REVISION 18) +set(CPPREST_VERSION_REVISION 19) enable_testing() diff --git a/Release/include/cpprest/version.h b/Release/include/cpprest/version.h index d8771581ad..3f86f141fb 100644 --- a/Release/include/cpprest/version.h +++ b/Release/include/cpprest/version.h @@ -5,6 +5,6 @@ */ #define CPPREST_VERSION_MINOR 10 #define CPPREST_VERSION_MAJOR 2 -#define CPPREST_VERSION_REVISION 18 +#define CPPREST_VERSION_REVISION 19 #define CPPREST_VERSION (CPPREST_VERSION_MAJOR * 100000 + CPPREST_VERSION_MINOR * 100 + CPPREST_VERSION_REVISION) diff --git a/changelog.md b/changelog.md index c547665912..7a9b6dfe04 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,12 @@ +cpprestsdk (2.10.19) +* PR#1982 make Uri.is_host_loopback() only return true for localhost and 127.0.0.1 exactly. + The old behavior could potentially return "true" for URLs that were not, in fact, local, + and this could cause security issues if is_host_loopback was used in certain ways. +* PR#1711 Fix likely typo in SafeInt3.hpp, that results in error with clang 15 +* PR#1496 Support for oauth2 with "client_credentials" grant type. +* PR#1429 Add constructor from all integer types for json value. +* PR#1577 export http_exception for non Windows builds using visibility macros. + cpprestsdk (2.10.18) * PR#1571 Add ability to parse and emit the NT Epoch 1601-01-01T00:00:00Z * PR#1571 Update vcpkg submodule From 0b1ce318a757bbfb89bdb0fffb61ca4e38dc3b33 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 22 Nov 2024 17:52:57 -0800 Subject: [PATCH 80/80] Include `` for `system_clock` (#1811) --- Release/tests/common/UnitTestpp/src/TestRunner.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Release/tests/common/UnitTestpp/src/TestRunner.cpp b/Release/tests/common/UnitTestpp/src/TestRunner.cpp index 807a0e3b10..69551f3e2e 100644 --- a/Release/tests/common/UnitTestpp/src/TestRunner.cpp +++ b/Release/tests/common/UnitTestpp/src/TestRunner.cpp @@ -39,6 +39,7 @@ #include #include #else +#include #include #endif