[cpp-sp] branch main updated: Implement chunking methods.

Codeberg noreply at shibboleth.net
Mon Oct 5 14:19:42 UTC 2026


This is an automated email from the git hooks/post-receive script.

codeberg pushed a commit to branch main
in repository cpp-sp.

View the commit online:
https://codeberg.org/Shibboleth/cpp-sp/commit/5ec61a444e0ab784acc897f1e0fd1d3f5c45cc4d

The following commit(s) were added to refs/heads/main by this push:
     new 5ec61a44 Implement chunking methods.
5ec61a44 is described below

commit 5ec61a444e0ab784acc897f1e0fd1d3f5c45cc4d
Author: Scott Cantor <scott at restingparrotsoftware.com>
AuthorDate: Mon Oct 5 10:19:29 2026 -0400

    Implement chunking methods.
---
 shibsp/io/CookieManager.h        |   2 +-
 shibsp/io/impl/CookieManager.cpp | 148 ++++++++++++++++++++++++++++++++-------
 2 files changed, 125 insertions(+), 25 deletions(-)

diff --git a/shibsp/io/CookieManager.h b/shibsp/io/CookieManager.h
index 916ffeac..eb44c72a 100644
--- a/shibsp/io/CookieManager.h
+++ b/shibsp/io/CookieManager.h
@@ -231,7 +231,7 @@ namespace shibsp {
 
     private:
         std::string computeCookieName(const SPRequest& request) const;
-        void outputHeader(SPRequest& request, const char* value, int maxAge) const;
+        void outputHeader(SPRequest& request, const char* name, const char* value, int maxAge) const;
 
         std::string m_defaultName;
         std::string m_overrideProperty;
diff --git a/shibsp/io/impl/CookieManager.cpp b/shibsp/io/impl/CookieManager.cpp
index b9391ddd..9978df3a 100644
--- a/shibsp/io/impl/CookieManager.cpp
+++ b/shibsp/io/impl/CookieManager.cpp
@@ -28,7 +28,6 @@
 #include "util/PropertySet.h"
 
 #include <boost/lexical_cast.hpp>
-#include <string.h>
 
 using namespace shibsp;
 using namespace std;
@@ -130,6 +129,128 @@ void CookieManager::setChunkSize(unsigned int chunkSize)
     m_chunkSize = chunkSize;
 }
 
+const char* CookieManager::getCookieValue(const SPRequest& request) const
+{
+    const auto& cookies = request.getCookies();
+    const auto& entry = cookies.find(computeCookieName(request));
+    return entry == cookies.end() ? nullptr : entry->second.c_str();
+}
+
+string CookieManager::getChunkedCookieValue(const SPRequest& request) const
+{
+    string buffer;
+    string baseName = computeCookieName(request);
+
+    const auto& cookies = request.getCookies();
+
+    // In a loop, read the cookies in until we don't find a value.
+    unsigned int i = 1;
+    while (true) {
+        try {
+            string chunkedName = baseName + '.' + boost::lexical_cast<string>(i++);
+            const auto& entry = cookies.find(chunkedName);
+            if (entry == cookies.end()) {
+                break;
+            }
+            buffer += entry->second;
+        }
+        catch (const boost::bad_lexical_cast& e) {
+            request.error("caught exception casting chunked cookie index into string: %s", e.what());
+            return string();
+        }
+    }
+
+    return buffer;
+}
+
+void CookieManager::setCookie(SPRequest& request, const char* value, bool chunked) const
+{
+    unsigned int maxAge = request.getRequestSettings().first->getInt(RequestMapper::COOKIE_MAXAGE_PROP_NAME, m_maxAge);
+    string baseName = computeCookieName(request);
+
+    if (chunked) {
+        // Subtly, we need to both set our own cookies, but also continue processing
+        // by checking for "additional" chunked cookies we don't need and clear those.
+
+        unsigned int i = 1;
+        const char* ch = value;
+        unique_ptr<char[]> buffer(new char[m_chunkSize + 1]);
+
+        while (*ch) {
+            size_t count = 0;
+            char* bufptr = &buffer[0];
+
+            // Copy up to chunk size into buffer, stopping if the source exhausts.
+            while (*ch && count < m_chunkSize) {
+                *bufptr++ = *ch++;
+                count++;
+            }
+
+            // Terminate with null.
+            *bufptr = 0;
+
+            // Output the latest chunk.
+            try {
+                string chunkedName = baseName + '.' + boost::lexical_cast<string>(i++);
+                outputHeader(request, chunkedName.c_str(), buffer.get(), maxAge);
+            }
+            catch (const boost::bad_lexical_cast& e) {
+                request.error("caught exception casting chunked cookie index into string: %s", e.what());
+                return;
+            }
+        }
+
+        // Now we unset anything we find that's beyond our counter.
+        const auto& cookies = request.getCookies();
+        while (true) {
+            try {
+                string chunkedName = baseName + '.' + boost::lexical_cast<string>(i++);
+                const auto& entry = cookies.find(chunkedName);
+                if (entry == cookies.end()) {
+                    break;
+                }
+                outputHeader(request, chunkedName.c_str(), nullptr, 0);
+            }
+            catch (const boost::bad_lexical_cast& e) {
+                request.error("caught exception casting chunked cookie index into string: %s", e.what());
+                return;
+            }
+        }
+    }
+    else {
+        outputHeader(request, baseName.c_str(), value, maxAge);
+    }
+}
+
+void CookieManager::unsetCookie(SPRequest& request, bool chunked) const
+{
+    string baseName = computeCookieName(request);
+
+    if (chunked) {
+        const auto& cookies = request.getCookies();
+
+        // In loop, clear any cookies that exist on the request side.
+        unsigned int i = 1;
+        while (true) {
+            try {
+                string chunkedName = baseName + '.' + boost::lexical_cast<string>(i++);
+                const auto& entry = cookies.find(chunkedName);
+                if (entry == cookies.end()) {
+                    break;
+                }
+                outputHeader(request, chunkedName.c_str(), nullptr, 0);
+            }
+            catch (const boost::bad_lexical_cast& e) {
+                request.error("caught exception casting chunked cookie index into string: %s", e.what());
+                return;
+            }
+        }
+    }
+    else {
+        outputHeader(request, baseName.c_str(), nullptr, 0);
+    }
+}
+
 string CookieManager::computeCookieName(const SPRequest& request) const
 {
     // If not app-specific, return the overridden or default name unadorned.
@@ -151,9 +272,9 @@ string CookieManager::computeCookieName(const SPRequest& request) const
     return cookieName + '_' + hex_encode(decoration);
 }
 
-void CookieManager::outputHeader(SPRequest& request, const char* value, int maxAge) const
+void CookieManager::outputHeader(SPRequest& request, const char* name, const char* value, int maxAge) const
 {
-    string header(computeCookieName(request));
+    string header(name);
     header += '=';
     if (value) {
         header += value;
@@ -199,24 +320,3 @@ void CookieManager::outputHeader(SPRequest& request, const char* value, int maxA
     request.setResponseHeader("Set-Cookie", header.c_str());
 }
 
-const char* CookieManager::getCookieValue(const SPRequest& request) const
-{
-    const auto& cookies = request.getCookies();
-    const auto& entry = cookies.find(computeCookieName(request));
-    return entry == cookies.end() ? nullptr : entry->second.c_str();
-}
-
-string CookieManager::getChunkedCookieValue(const SPRequest& request) const
-{
-    return string();
-}
-
-void CookieManager::setCookie(SPRequest& request, const char* value, bool chunked) const
-{
-    outputHeader(request, value, request.getRequestSettings().first->getInt(RequestMapper::COOKIE_MAXAGE_PROP_NAME, m_maxAge));
-}
-
-void CookieManager::unsetCookie(SPRequest& request, bool chunked) const
-{
-    outputHeader(request, nullptr, 0);
-}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list