diff --git a/NuGet.Config b/NuGet.Config new file mode 100644 index 0000000000..abc5b1378c --- /dev/null +++ b/NuGet.Config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Release/CMakeLists.txt b/Release/CMakeLists.txt index 33f0c37fde..a06623bf20 100644 --- a/Release/CMakeLists.txt +++ b/Release/CMakeLists.txt @@ -136,6 +136,11 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR IOS) if(ANDROID) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pedantic") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-attributes -Wno-pointer-arith") + elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") + set(WARNINGS -Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls) + set(LINUX_SUPPRESSIONS -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder -Wno-unused-local-typedefs) + set(WARNINGS ${WARNINGS} ${LINUX_SUPPRESSIONS}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type-c-linkage -Wno-unneeded-internal-declaration") else() set(WARNINGS -Wall -Wextra -Wcast-qual -Wconversion -Wformat=2 -Winit-self -Winvalid-pch -Wmissing-format-attribute -Wmissing-include-dirs -Wpacked -Wredundant-decls) set(OSX_SUPPRESSIONS -Wno-overloaded-virtual -Wno-sign-conversion -Wno-deprecated -Wno-unknown-pragmas -Wno-reorder -Wno-char-subscripts -Wno-switch -Wno-unused-parameter -Wno-unused-variable -Wno-deprecated -Wno-unused-value -Wno-unknown-warning-option -Wno-return-type-c-linkage -Wno-unused-function -Wno-sign-compare -Wno-shorten-64-to-32 -Wno-reorder -Wno-unused-local-typedefs) diff --git a/Release/include/cpprest/asyncrt_utils.h b/Release/include/cpprest/asyncrt_utils.h index 169ec3a203..fac70a91a9 100644 --- a/Release/include/cpprest/asyncrt_utils.h +++ b/Release/include/cpprest/asyncrt_utils.h @@ -29,7 +29,10 @@ #ifndef _WIN32 #include -#if !defined(ANDROID) && !defined(__ANDROID__) // CodePlex 269 +#if !defined(ANDROID) && !defined(__ANDROID__) && !defined(__GLIBC__) // CodePlex 269 +/* Systems using glibc: xlocale.h has been removed from glibc 2.26 + The above include of locale.h is sufficient + Further details: https://sourceware.org/git/?p=glibc.git;a=commit;h=f0be25b6336db7492e47d2e8e72eb8af53b5506d */ #include #endif #endif diff --git a/Release/include/cpprest/details/http_constants.dat b/Release/include/cpprest/details/http_constants.dat index c408556b19..c867b4d07a 100644 --- a/Release/include/cpprest/details/http_constants.dat +++ b/Release/include/cpprest/details/http_constants.dat @@ -28,6 +28,7 @@ DAT(SeeOther, 303, _XPLATSTR("See Other")) DAT(NotModified, 304, _XPLATSTR("Not Modified")) DAT(UseProxy, 305, _XPLATSTR("Use Proxy")) DAT(TemporaryRedirect, 307, _XPLATSTR("Temporary Redirect")) +DAT(PermanentRedirect, 308, _XPLATSTR("Permanent Redirect")) DAT(BadRequest, 400, _XPLATSTR("Bad Request")) DAT(Unauthorized, 401, _XPLATSTR("Unauthorized")) DAT(PaymentRequired, 402, _XPLATSTR("Payment Required")) diff --git a/Release/include/cpprest/http_msg.h b/Release/include/cpprest/http_msg.h index 72a07fdd62..8ca25edc69 100644 --- a/Release/include/cpprest/http_msg.h +++ b/Release/include/cpprest/http_msg.h @@ -715,6 +715,8 @@ class _http_request final : public http::details::http_msg_base, public std::ena _ASYNCRTIMP void set_request_uri(const uri&); + const utility::string_t& remote_address() const { return m_remote_address; } + const pplx::cancellation_token &cancellation_token() const { return m_cancellationToken; } void set_cancellation_token(const pplx::cancellation_token &token) @@ -755,6 +757,8 @@ class _http_request final : public http::details::http_msg_base, public std::ena void _set_base_uri(const http::uri &base_uri) { m_base_uri = base_uri; } + void _set_remote_address(const utility::string_t &remote_address) { m_remote_address = remote_address; } + private: // Actual initiates sending the response, without checking if a response has already been sent. @@ -778,6 +782,8 @@ class _http_request final : public http::details::http_msg_base, public std::ena std::shared_ptr m_progress_handler; pplx::task_completion_event m_response; + + utility::string_t m_remote_address; }; @@ -869,6 +875,12 @@ class http_request /// const http_headers &headers() const { return _m_impl->headers(); } + /// + /// Returns a string representation of the remote IP address. + /// + /// The remote IP address. + const utility::string_t& get_remote_address() const { return _m_impl->remote_address(); } + /// /// Extract the body of the request message as a string value, checking that the content type is a MIME text type. /// A body can only be extracted once because in some cases an optimization is made where the data is 'moved' out. diff --git a/Release/include/cpprest/json.h b/Release/include/cpprest/json.h index c833529850..5f2572ca01 100644 --- a/Release/include/cpprest/json.h +++ b/Release/include/cpprest/json.h @@ -1383,7 +1383,12 @@ namespace json return m_value == other.m_value; } __assume(0); + // Absence of this return statement provokes a warning from Intel + // compiler, but its presence results in a warning from MSVC, so + // we have to resort to conditional compilation to keep both happy. +#ifdef __INTEL_COMPILER return false; +#endif } private: diff --git a/Release/include/cpprest/uri_builder.h b/Release/include/cpprest/uri_builder.h index 8464d1e0af..4827534249 100644 --- a/Release/include/cpprest/uri_builder.h +++ b/Release/include/cpprest/uri_builder.h @@ -261,13 +261,13 @@ namespace web /// Combine and validate the URI components into a encoded string. An exception will be thrown if the URI is invalid. /// /// The created URI as a string. - _ASYNCRTIMP utility::string_t to_string(); + _ASYNCRTIMP utility::string_t to_string() const; /// /// Combine and validate the URI components into a URI class instance. An exception will be thrown if the URI is invalid. /// /// The create URI as a URI class instance. - _ASYNCRTIMP uri to_uri(); + _ASYNCRTIMP uri to_uri() const; /// /// Validate the generated URI from all existing components of this uri_builder. diff --git a/Release/libs/websocketpp/CMakeLists.txt b/Release/libs/websocketpp/CMakeLists.txt index b30a0ed464..f8df9de08a 100644 --- a/Release/libs/websocketpp/CMakeLists.txt +++ b/Release/libs/websocketpp/CMakeLists.txt @@ -135,7 +135,11 @@ if (BUILD_TESTS OR BUILD_EXAMPLES) endif() set (WEBSOCKETPP_PLATFORM_TSL_LIBS ssl crypto) set (WEBSOCKETPP_BOOST_LIBS system thread) - set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++0x -stdlib=libc++") # todo: is libc++ really needed here? + if(CMAKE_SYSTEM_NAME MATCHES "Linux") + set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++0x") + else() + set (CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "-std=c++0x -stdlib=libc++") # todo: is libc++ really needed here? + endif() if (NOT APPLE) add_definitions (-DNDEBUG -Wall -Wno-padded) # todo: should we use CMAKE_C_FLAGS for these? endif () @@ -241,4 +245,3 @@ install (FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-config.cmake" "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/websocketpp-configVersion.cmake" DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev) - diff --git a/Release/libs/websocketpp/websocketpp/transport/asio/security/tls.hpp b/Release/libs/websocketpp/websocketpp/transport/asio/security/tls.hpp index 8434a5c3d9..8932655803 100644 --- a/Release/libs/websocketpp/websocketpp/transport/asio/security/tls.hpp +++ b/Release/libs/websocketpp/websocketpp/transport/asio/security/tls.hpp @@ -307,8 +307,13 @@ class connection : public lib::enable_shared_from_this { */ lib::error_code translate_ec(boost::system::error_code ec) { if (ec.category() == boost::asio::error::get_ssl_category()) { +#if defined SSL_R_SHORT_READ if (ERR_GET_REASON(ec.value()) == SSL_R_SHORT_READ) { return make_error_code(transport::error::tls_short_read); +#else + if (ERR_GET_REASON(ec.value()) == boost::asio::ssl::error::stream_truncated) { + return make_error_code(boost::asio::ssl::error::stream_truncated); +#endif } else { // We know it is a TLS related error, but otherwise don't know // more. Pass through as TLS generic. diff --git a/Release/src/http/client/http_client_asio.cpp b/Release/src/http/client/http_client_asio.cpp index 6a6786dcf5..19e09b2427 100644 --- a/Release/src/http/client/http_client_asio.cpp +++ b/Release/src/http/client/http_client_asio.cpp @@ -809,7 +809,7 @@ class asio_context : public request_context, public std::enable_shared_from_this { std::string header; header.append("Proxy-Authorization: Basic "); - header.append(generate_base64_userpass(m_http_client->client_config().credentials())); + header.append(generate_base64_userpass(m_http_client->client_config().proxy().credentials())); header.append(CRLF); return header; } @@ -1229,9 +1229,17 @@ class asio_context : public request_context, public std::enable_shared_from_this } } + // Check for HEAD requests and status codes which cannot contain a + // message body in HTTP/1.1 (see 3.3.3/1 of the RFC 7230). + // // note: need to check for 'chunked' here as well, azure storage sends both // transfer-encoding:chunked and content-length:0 (although HTTP says not to) - if (m_request.method() == U("HEAD") || (!needChunked && m_content_length == 0)) + const auto status = m_response.status_code(); + if (m_request.method() == U("HEAD") + || (status >= 100 && status < 200) + || status == status_codes::NoContent + || status == status_codes::NotModified + || (!needChunked && m_content_length == 0)) { // we can stop early - no body const auto &progress = m_request._get_impl()->_progress_handler(); diff --git a/Release/src/http/client/http_client_winhttp.cpp b/Release/src/http/client/http_client_winhttp.cpp index 3eee959aff..333cb39545 100644 --- a/Release/src/http/client/http_client_winhttp.cpp +++ b/Release/src/http/client/http_client_winhttp.cpp @@ -17,6 +17,10 @@ #include "cpprest/http_headers.h" #include "http_client_impl.h" +#ifndef CPPREST_TARGET_XP +#include +#endif + namespace web { namespace http @@ -297,6 +301,42 @@ static DWORD ChooseAuthScheme( DWORD dwSupportedSchemes ) return 0; } +// Small RAII helper to ensure that the fields of this struct are always +// properly freed. +struct proxy_info : WINHTTP_PROXY_INFO +{ + proxy_info() + { + memset( this, 0, sizeof(WINHTTP_PROXY_INFO) ); + } + + ~proxy_info() + { + if ( lpszProxy ) + ::GlobalFree(lpszProxy); + if ( lpszProxyBypass ) + ::GlobalFree(lpszProxyBypass); + } +}; + +struct ie_proxy_config : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG +{ + ie_proxy_config() + { + memset( this, 0, sizeof(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG) ); + } + + ~ie_proxy_config() + { + if ( lpszAutoConfigUrl ) + ::GlobalFree(lpszAutoConfigUrl); + if ( lpszProxy ) + ::GlobalFree(lpszProxy); + if ( lpszProxyBypass ) + ::GlobalFree(lpszProxyBypass); + } +}; + // WinHTTP client. class winhttp_client : public _http_client_communicator { @@ -358,9 +398,13 @@ class winhttp_client : public _http_client_communicator // Open session and connection with the server. virtual unsigned long open() override { + // This object have lifetime greater than proxy_name and proxy_bypass + // which may point to its elements. + ie_proxy_config proxyIE; + DWORD access_type; LPCWSTR proxy_name; - utility::string_t proxy_str; + LPCWSTR proxy_bypass = WINHTTP_NO_PROXY_BYPASS; http::uri uri; const auto& config = client_config(); @@ -372,8 +416,54 @@ class winhttp_client : public _http_client_communicator } else if(config.proxy().is_default() || config.proxy().is_auto_discovery()) { + // Use the default WinHTTP proxy by default. access_type = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; proxy_name = WINHTTP_NO_PROXY_NAME; + +#ifndef CPPREST_TARGET_XP + if (IsWindows8Point1OrGreater()) + { + access_type = WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY; + } + + // However, if it is not configured... + proxy_info proxyDefault; + if(!WinHttpGetDefaultProxyConfiguration(&proxyDefault) || + proxyDefault.dwAccessType == WINHTTP_ACCESS_TYPE_NO_PROXY) + { + // ... then try to fall back on the default WinINET proxy, as + // recommended for the desktop applications (if we're not + // running under a user account, the function below will just + // fail, so there is no real need to check for this explicitly) + if(WinHttpGetIEProxyConfigForCurrentUser(&proxyIE)) + { + if(proxyIE.fAutoDetect) + { + m_proxy_auto_config = true; + } + else if(proxyIE.lpszAutoConfigUrl) + { + m_proxy_auto_config = true; + m_proxy_auto_config_url = proxyIE.lpszAutoConfigUrl; + } + else if(proxyIE.lpszProxy) + { + access_type = WINHTTP_ACCESS_TYPE_NAMED_PROXY; + proxy_name = proxyIE.lpszProxy; + + if(proxyIE.lpszProxyBypass) + { + proxy_bypass = proxyIE.lpszProxyBypass; + } + } + } + } +#endif + + if (config.proxy().is_auto_discovery()) + { + m_proxy_auto_config = true; + } } else { @@ -388,6 +478,7 @@ class winhttp_client : public _http_client_communicator } else { + utility::string_t proxy_str; if (uri.port() > 0) { utility::ostringstream_t ss; @@ -408,7 +499,7 @@ class winhttp_client : public _http_client_communicator NULL, access_type, proxy_name, - WINHTTP_NO_PROXY_BYPASS, + proxy_bypass, WINHTTP_FLAG_ASYNC); if(!m_hSession) { @@ -437,18 +528,8 @@ class winhttp_client : public _http_client_communicator } } -#if 0 // Work in progress. Enable this to support server certificate revocation check - if( m_secure ) - { - DWORD dwEnableSSLRevocOpt = WINHTTP_ENABLE_SSL_REVOCATION; - if(!WinHttpSetOption(m_hSession, WINHTTP_OPTION_ENABLE_FEATURE, &dwEnableSSLRevocOpt, sizeof(dwEnableSSLRevocOpt))) - { - DWORD dwError = GetLastError(); dwError; - return report_failure(U("Error enabling SSL revocation check")); - } - } -#endif //Enable TLS 1.1 and 1.2 +#if !defined(CPPREST_TARGET_XP) 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); @@ -457,6 +538,7 @@ class winhttp_client : public _http_client_communicator { return report_failure(_XPLATSTR("Error setting session options")); } +#endif config._invoke_nativesessionhandle_options(m_hSession); @@ -492,17 +574,25 @@ class winhttp_client : public _http_client_communicator http_request &msg = request->m_request; winhttp_request_context * winhttp_context = static_cast(request.get()); - WINHTTP_PROXY_INFO info; + proxy_info info; bool proxy_info_required = false; - if( client_config().proxy().is_auto_discovery() ) + if(m_proxy_auto_config) { WINHTTP_AUTOPROXY_OPTIONS autoproxy_options; memset( &autoproxy_options, 0, sizeof(WINHTTP_AUTOPROXY_OPTIONS) ); - memset( &info, 0, sizeof(WINHTTP_PROXY_INFO) ); - autoproxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT; - autoproxy_options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A; + if(m_proxy_auto_config_url.empty()) + { + autoproxy_options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT; + autoproxy_options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A; + } + else + { + autoproxy_options.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL; + autoproxy_options.lpszAutoConfigUrl = m_proxy_auto_config_url.c_str(); + } + autoproxy_options.fAutoLogonIfChallenged = TRUE; auto result = WinHttpGetProxyForUrl( @@ -540,6 +630,18 @@ class winhttp_client : public _http_client_communicator return; } + // Enable the certificate revocation check + if (m_secure) + { + DWORD dwEnableSSLRevocOpt = WINHTTP_ENABLE_SSL_REVOCATION; + if (!WinHttpSetOption(winhttp_context->m_request_handle, WINHTTP_OPTION_ENABLE_FEATURE, &dwEnableSSLRevocOpt, sizeof(dwEnableSSLRevocOpt))) + { + auto errorCode = GetLastError(); + request->report_error(errorCode, build_error_msg(errorCode, "Error enabling SSL revocation check")); + return; + } + } + if(proxy_info_required) { auto result = WinHttpSetOption( @@ -1353,6 +1455,12 @@ class winhttp_client : public _http_client_communicator HINTERNET m_hSession; HINTERNET m_hConnection; bool m_secure; + + // If auto config is true, dynamically find the proxy for each URL using + // the proxy configuration script at the given URL if it's not empty or + // using WPAD otherwise. + bool m_proxy_auto_config{false}; + utility::string_t m_proxy_auto_config_url; }; std::shared_ptr<_http_client_communicator> create_platform_final_pipeline_stage(uri&& base_uri, http_client_config&& client_config) diff --git a/Release/src/http/listener/http_server_asio.cpp b/Release/src/http/listener/http_server_asio.cpp index ee026cede1..99351c13a0 100644 --- a/Release/src/http/listener/http_server_asio.cpp +++ b/Release/src/http/listener/http_server_asio.cpp @@ -475,7 +475,11 @@ void hostport_listener::start() // resolve the endpoint address auto& service = crossplat::threadpool::shared_instance().service(); tcp::resolver resolver(service); - tcp::resolver::query query(m_host, m_port); + // #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::endpoint endpoint = *resolver.resolve(query); m_acceptor.reset(new tcp::acceptor(service, endpoint)); @@ -650,6 +654,9 @@ will_deref_and_erase_t asio_server_connection::handle_http_line(const boost::sys m_close = true; } + // Get the remote IP address + m_request._get_impl()->_set_remote_address(utility::conversions::to_string_t(m_socket->remote_endpoint().address().to_string())); + return handle_headers(); } } @@ -1320,4 +1327,4 @@ std::unique_ptr make_http_asio_server() return make_unique(); } -}}}} \ No newline at end of file +}}}} diff --git a/Release/src/http/listener/http_server_httpsys.cpp b/Release/src/http/listener/http_server_httpsys.cpp index ce1717ea3d..9b58d20ef1 100644 --- a/Release/src/http/listener/http_server_httpsys.cpp +++ b/Release/src/http/listener/http_server_httpsys.cpp @@ -17,6 +17,8 @@ #if _WIN32_WINNT >= _WIN32_WINNT_VISTA +#pragma comment(lib, "Ws2_32") + #include "http_server_httpsys.h" #include "http_server_impl.h" @@ -555,6 +557,26 @@ void windows_request_context::read_headers_io_completion(DWORD error_code, DWORD m_msg.set_method(parse_request_method(m_request)); parse_http_headers(m_request->Headers, m_msg.headers()); + // Retrieve the remote IP address + std::vector remoteAddressBuffer(50); + + if (m_request->Address.pRemoteAddress->sa_family == AF_INET6) + { + auto inAddr = &reinterpret_cast(m_request->Address.pRemoteAddress)->sin6_addr; + InetNtopW(AF_INET6, inAddr, &remoteAddressBuffer[0], remoteAddressBuffer.size()); + } + else if (m_request->Address.pRemoteAddress->sa_family == AF_INET) + { + auto inAddr = &reinterpret_cast(m_request->Address.pRemoteAddress)->sin_addr; + InetNtopW(AF_INET, inAddr, &remoteAddressBuffer[0], remoteAddressBuffer.size()); + } + else + { + remoteAddressBuffer[0] = L'\0'; + } + + m_msg._get_impl()->_set_remote_address(&remoteAddressBuffer[0]); + // Start reading in body from the network. m_msg._get_impl()->_prepare_to_receive_data(); read_request_body_chunk(); diff --git a/Release/src/uri/uri.cpp b/Release/src/uri/uri.cpp index fb395edf5d..3157b96a6d 100644 --- a/Release/src/uri/uri.cpp +++ b/Release/src/uri/uri.cpp @@ -22,12 +22,12 @@ utility::string_t uri_components::join() // canonicalize components first // convert scheme to lowercase - std::transform(m_scheme.begin(), m_scheme.end(), m_scheme.begin(), [this](utility::char_t c) { + std::transform(m_scheme.begin(), m_scheme.end(), m_scheme.begin(), [](utility::char_t c) { return (utility::char_t)tolower(c); }); // convert host to lowercase - std::transform(m_host.begin(), m_host.end(), m_host.begin(), [this](utility::char_t c) { + std::transform(m_host.begin(), m_host.end(), m_host.begin(), [](utility::char_t c) { return (utility::char_t)tolower(c); }); diff --git a/Release/src/uri/uri_builder.cpp b/Release/src/uri/uri_builder.cpp index 46f599bbcc..b7d08b6380 100644 --- a/Release/src/uri/uri_builder.cpp +++ b/Release/src/uri/uri_builder.cpp @@ -91,12 +91,12 @@ uri_builder &uri_builder::append(const http::uri &relative_uri) return *this; } -utility::string_t uri_builder::to_string() +utility::string_t uri_builder::to_string() const { return to_uri().to_string(); } -uri uri_builder::to_uri() +uri uri_builder::to_uri() const { return uri(m_uri); } diff --git a/Release/src/utilities/web_utilities.cpp b/Release/src/utilities/web_utilities.cpp index 367c95c2f4..f17b5ab099 100644 --- a/Release/src/utilities/web_utilities.cpp +++ b/Release/src/utilities/web_utilities.cpp @@ -92,6 +92,12 @@ plaintext_string winrt_encryption::decrypt() const win32_encryption::win32_encryption(const std::wstring &data) : m_numCharacters(data.size()) { + // Early return because CryptProtectMemory crashs with empty string + if (m_numCharacters == 0) + { + return; + } + const auto dataNumBytes = data.size() * sizeof(std::wstring::value_type); m_buffer.resize(dataNumBytes); memcpy_s(m_buffer.data(), m_buffer.size(), data.c_str(), dataNumBytes); diff --git a/Release/tests/functional/http/client/outside_tests.cpp b/Release/tests/functional/http/client/outside_tests.cpp index b1da9c23e7..4ac5a23632 100644 --- a/Release/tests/functional/http/client/outside_tests.cpp +++ b/Release/tests/functional/http/client/outside_tests.cpp @@ -39,7 +39,8 @@ TEST_FIXTURE(uri_address, outside_cnn_dot_com) { handle_timeout([] { - http_client client(U("http://www.cnn.com")); + // http://www.cnn.com redirects users from countries outside of the US to the "http://edition.cnn.com/" drop location + http_client client(U("http://edition.cnn.com")); // CNN's main page doesn't use chunked transfer encoding. http_response response = client.request(methods::GET).get(); @@ -83,7 +84,8 @@ TEST_FIXTURE(uri_address, outside_wikipedia_compressed_http_response) TEST_FIXTURE(uri_address, outside_google_dot_com) { - http_client client(U("http://www.google.com")); + // Use code.google.com instead of www.google.com, which redirects + http_client client(U("http://code.google.com")); http_request request(methods::GET); for (int i = 0; i < 2; ++i) { @@ -96,7 +98,8 @@ TEST_FIXTURE(uri_address, multiple_https_requests) { handle_timeout([&] { - http_client client(U("https://www.google.com")); + // Use code.google.com instead of www.google.com, which redirects + http_client client(U("https://code.google.com")); http_response response; for(int i = 0; i < 5; ++i) @@ -112,7 +115,8 @@ TEST_FIXTURE(uri_address, reading_google_stream) { handle_timeout([&] { - http_client simpleclient(U("http://www.google.com")); + // Use code.google.com instead of www.google.com, which redirects + http_client simpleclient(U("http://code.google.com")); utility::string_t path = m_uri.query(); http_response response = simpleclient.request(::http::methods::GET).get(); @@ -122,7 +126,9 @@ TEST_FIXTURE(uri_address, reading_google_stream) streams::rawptr_buffer temp(chars, sizeof(chars)); VERIFY_ARE_EQUAL(response.body().read(temp, 70).get(), 70); - VERIFY_ARE_EQUAL(strcmp((const char *) chars, "\n \n request(methods::GET, U("/path1"))); + + p_client->next_response().then([](test_response *p_response) + { + http_asserts::assert_test_response_equals(p_response, status_codes::NoContent); + }).wait(); + + VERIFY_IS_TRUE(requestCount >= 1); + listener.close().wait(); +} + } }}}} diff --git a/Release/tests/functional/utils/CMakeLists.txt b/Release/tests/functional/utils/CMakeLists.txt index e2d0e6bca3..5c6577b24e 100644 --- a/Release/tests/functional/utils/CMakeLists.txt +++ b/Release/tests/functional/utils/CMakeLists.txt @@ -4,6 +4,7 @@ set(SOURCES strings.cpp macro_test.cpp nonce_generator_tests.cpp + win32_encryption_tests.cpp stdafx.cpp ) diff --git a/Release/tests/functional/utils/stdafx.h b/Release/tests/functional/utils/stdafx.h index 32455df0e1..8188bec2e5 100644 --- a/Release/tests/functional/utils/stdafx.h +++ b/Release/tests/functional/utils/stdafx.h @@ -16,6 +16,7 @@ #include "cpprest/uri.h" #include "cpprest/asyncrt_utils.h" +#include "cpprest/details/web_utilities.h" #include "unittestpp.h" -#include "utils_tests.h" \ No newline at end of file +#include "utils_tests.h" diff --git a/Release/tests/functional/utils/win32_encryption_tests.cpp b/Release/tests/functional/utils/win32_encryption_tests.cpp new file mode 100644 index 0000000000..2ec4b21a68 --- /dev/null +++ b/Release/tests/functional/utils/win32_encryption_tests.cpp @@ -0,0 +1,44 @@ +/*** +* Copyright (C) Microsoft. All rights reserved. +* Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +* +* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ +* +* win32_encryption_tests.cpp +* +* Tests for win32_encryption class. +* +* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +****/ + +#include "stdafx.h" + +using namespace utility; + +namespace tests { namespace functional { namespace utils_tests { + +#if defined(_WIN32) && !defined(CPPREST_TARGET_XP) && !defined(__cplusplus_winrt) +SUITE(win32_encryption) +{ + +TEST(win32_encryption_random_string) +{ + utility::string_t rndStr = utility::conversions::to_string_t("random string"); + web::details::win32_encryption enc(rndStr); + + VERIFY_ARE_EQUAL(*enc.decrypt(), rndStr); +} + +TEST(win32_encryption_empty_string) +{ + utility::string_t emptyStr = utility::conversions::to_string_t(""); + web::details::win32_encryption enc(emptyStr); + + VERIFY_ARE_EQUAL(*enc.decrypt(), emptyStr); +} + +} // SUITE(win32_encryption) + +#endif + +}}}