4 İşlemeler 17eeb18feb ... 00afaaed6a

Yazar SHA1 Mesaj Tarih
  yhirose 00afaaed6a Release v0.60.1 1 hafta önce
  yhirose e803f5e413 Let the SSL chain policy alone judge the Windows chain (#2618) 1 hafta önce
  Michael Weitzel 57b8aca6da Avoid name clash with class WebSocketClient by explicit qualification (#2616) 1 hafta önce
  KBS 213029685a Serve the whole body for a suffix range longer than it (#2615) 1 hafta önce
4 değiştirilmiş dosya ile 27 ekleme ve 18 silme
  1. 1 1
      README.md
  2. 1 1
      docs-src/config.toml
  3. 8 10
      httplib.h
  4. 17 6
      test/test.cc

+ 1 - 1
README.md

@@ -230,7 +230,7 @@ cpp-httplib automatically integrates with the OS certificate store on macOS and
 | Platform | Behavior | Disable (compile time) |
 | :------- | :------- | :--------------------- |
 | macOS | Loads system certs from Keychain (link `CoreFoundation` and `Security` with `-framework`). Requires Apple Clang; GCC is not supported for this feature. | `CPPHTTPLIB_DISABLE_MACOSX_AUTOMATIC_ROOT_CERTIFICATES` |
-| Windows | Verifies the certificate chain with CryptoAPI (`CertGetCertificateChain` / `CertVerifyCertificateChainPolicy`) instead of the TLS backend, with revocation checking. Windows fetches missing roots and intermediates on demand. With a custom CA, the TLS backend verifies the chain instead; with `set_server_certificate_verifier()`, both do. | `CPPHTTPLIB_DISABLE_WINDOWS_AUTOMATIC_ROOT_CERTIFICATES_UPDATE` |
+| Windows | Verifies the certificate chain with CryptoAPI (`CertGetCertificateChain` / `CertVerifyCertificateChainPolicy`) instead of the TLS backend. Revocation checking is best-effort: a revoked server certificate is rejected, while one whose revocation status cannot be determined is accepted. Windows fetches missing roots and intermediates on demand. With a custom CA, the TLS backend verifies the chain instead; with `set_server_certificate_verifier()`, both do. | `CPPHTTPLIB_DISABLE_WINDOWS_AUTOMATIC_ROOT_CERTIFICATES_UPDATE` |
 
 On Windows, verification can also be disabled at runtime:
 

+ 1 - 1
docs-src/config.toml

@@ -4,7 +4,7 @@ langs = ["en", "ja"]
 
 [site]
 title = "cpp-httplib"
-version = "0.60.0"
+version = "0.60.1"
 hostname = "https://yhirose.github.io"
 base_path = "/cpp-httplib"
 footer_message = "© 2026 Yuji Hirose. All rights reserved."

+ 8 - 10
httplib.h

@@ -8,8 +8,8 @@
 #ifndef CPPHTTPLIB_HTTPLIB_H
 #define CPPHTTPLIB_HTTPLIB_H
 
-#define CPPHTTPLIB_VERSION "0.60.0"
-#define CPPHTTPLIB_VERSION_NUM "0x003c00"
+#define CPPHTTPLIB_VERSION "0.60.1"
+#define CPPHTTPLIB_VERSION_NUM "0x003c01"
 
 #ifdef _WIN32
 #if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0A00
@@ -4412,6 +4412,8 @@ private:
 
 namespace ws {
 
+class WebSocketClient;
+
 enum class Opcode : uint8_t {
   Continuation = 0x0,
   Text = 0x1,
@@ -4513,7 +4515,7 @@ public:
 
 private:
   friend class httplib::Server;
-  friend class WebSocketClient;
+  friend class httplib::ws::WebSocketClient;
 
   WebSocket(
       Stream &strm, const Request &req, bool is_server,
@@ -9910,8 +9912,10 @@ inline bool range_error(Request &req, Response &res) {
         last_pos = content_len;
       }
 
+      // RFC 9110 14.1.2: a suffix-length longer than the representation
+      // selects the entire representation.
       if (first_pos == -1) {
-        first_pos = content_len - last_pos;
+        first_pos = (std::max)(static_cast<ssize_t>(0), content_len - last_pos);
         last_pos = content_len - 1;
       }
 
@@ -10854,12 +10858,6 @@ inline bool verify_cert_with_windows_schannel(
   auto chain_guard =
       scope_exit([&] { CertFreeCertificateChain(chain_context); });
 
-  // Check if chain has errors
-  if (chain_context->TrustStatus.dwErrorStatus != CERT_TRUST_NO_ERROR) {
-    out_error = chain_context->TrustStatus.dwErrorStatus;
-    return false;
-  }
-
   // Verify SSL policy
   SSL_EXTRA_CERT_CHAIN_POLICY_PARA extra_policy_para = {};
   extra_policy_para.cbSize = sizeof(extra_policy_para);

+ 17 - 6
test/test.cc

@@ -7242,8 +7242,21 @@ TEST_F(ServerTest, GetStreamedWithRangeSuffix1) {
 }
 
 TEST_F(ServerTest, GetStreamedWithRangeSuffix2) {
+  // RFC 9110 14.1.2: a suffix-length longer than the representation selects
+  // the entire representation.
+  for (auto range : {"bytes=-8", "bytes=-9999"}) {
+    auto res = cli_.Get("/streamed-with-range", Headers{{"Range", range}});
+    ASSERT_TRUE(res) << "Error: " << to_string(res.error());
+    EXPECT_EQ(StatusCode::PartialContent_206, res->status) << range;
+    EXPECT_EQ("7", res->get_header_value("Content-Length")) << range;
+    EXPECT_EQ("bytes 0-6/7", res->get_header_value("Content-Range")) << range;
+    EXPECT_EQ(std::string("abcdefg"), res->body) << range;
+  }
+}
+
+TEST_F(ServerTest, GetStreamedWithRangeSuffixZero) {
   auto res =
-      cli_.Get("/streamed-with-range?error", Headers{{"Range", "bytes=-9999"}});
+      cli_.Get("/streamed-with-range?error", Headers{{"Range", "bytes=-0"}});
   ASSERT_TRUE(res) << "Error: " << to_string(res.error());
   EXPECT_EQ(StatusCode::RangeNotSatisfiable_416, res->status);
   EXPECT_EQ("0", res->get_header_value("Content-Length"));
@@ -14176,9 +14189,8 @@ TEST(SSLClientTest, WindowsCertificateVerification_ServerIntermediates_Online) {
                    << " ssl_backend_error=" << res.ssl_backend_error();
 }
 
-// Windows, not the backend, decides on the chain: the error carries a
-// CryptoAPI trust status, which no backend error for a self-signed
-// certificate has.
+// Windows, not the backend, decides on the chain: the error is a CryptoAPI
+// policy status, which no backend reports for a self-signed certificate.
 TEST(SSLClientTest, WindowsCertificateVerification_RejectsUntrustedRoot) {
   SSLServer svr(SERVER_CERT2_FILE, SERVER_PRIVATE_KEY_FILE);
   ASSERT_TRUE(svr.is_valid());
@@ -14198,8 +14210,7 @@ TEST(SSLClientTest, WindowsCertificateVerification_RejectsUntrustedRoot) {
   auto res = cli.Get("/");
   ASSERT_FALSE(res);
   EXPECT_EQ(Error::SSLServerVerification, res.error());
-  EXPECT_NE(0u, res.ssl_backend_error() & CERT_TRUST_IS_UNTRUSTED_ROOT)
-      << "ssl_backend_error=" << res.ssl_backend_error();
+  EXPECT_EQ(static_cast<DWORD>(CERT_E_UNTRUSTEDROOT), res.ssl_backend_error());
 }
 #endif