]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Update httpSetCookie to support multiple Set-Cookie values.
authorMichael R Sweet <msweet@msweet.org>
Thu, 1 May 2025 22:43:53 +0000 (18:43 -0400)
committerMichael R Sweet <msweet@msweet.org>
Thu, 1 May 2025 22:43:53 +0000 (18:43 -0400)
CHANGES.md
cups/http.c

index cc21aaa9db12c1fc40dffa233a53380eef054805..452d84aa573d28fe3b42f82c73073efe53695b2b 100644 (file)
@@ -76,6 +76,8 @@ Changes in CUPS v2.5b1 (YYYY-MM-DD)
   filtering options in client.conf (Issue #1180)
 - Updated the CUPS web interface to make administrative tasks more discoverable
   (Issue #1207)
+- Updated the `httpSetCookie` API to support multiple "Set-Cookie:" header
+  values.
 - Deprecated the "page-border" Job Template attribute (Issue #1020)
 - Removed the `cups-config` utility (use `pkg-config` instead)
 - Fixed use-after-free in `cupsdAcceptClient()` when we log warning during error
index 71cb1d97b81017641da1a3137f78576bf47336ca..823ac7bec4c98801a15b230d9bdc163b1e986a95 100644 (file)
@@ -1030,11 +1030,11 @@ httpGetContentEncoding(http_t *http)    // I - HTTP connection
 
 
 //
-// 'httpGetCookie()' - Get "Cookie:" data from the HTTP connection.
+// 'httpGetCookie()' - Get cookie data from the HTTP connection.
 //
-// This function returns any HTTP "Cookie:" header data for the given HTTP
-// connection as described in RFC 6265.  Use the @link httpGetCookieValue@ to
-// get the value of a named cookie.
+// This function returns any HTTP "Set-Cookie:" or "Cookie:" header data for the
+// given HTTP connection as described in RFC 6265.  Use the
+// @link httpGetCookieValue@ to get the value of a named "Cookie:" value.
 //
 // @since CUPS 1.1.19@
 //
@@ -2632,25 +2632,48 @@ httpSetCredentials(http_t       *http,          // I - HTTP connection
 
 
 //
-// 'httpSetCookie()' - Set the cookie value(s).
+// 'httpSetCookie()' - Add Set-Cookie value(s).
+//
+// This function adds one or more Set-Cookie header values that will be sent to
+// the client with the @link httpWriteResponse@ function.  Each value conforms
+// to the format defined in RFC 6265.  Multiple values can be passed in the
+// "cookie" string separated by a newline character.
+//
+// Call the @link httpClearCookies@ function to clear all Set-Cookie values.
 //
 // @since CUPS 1.1.19@
 //
 
 void
-httpSetCookie(http_t     *http,                // I - Connection
+httpSetCookie(http_t     *http,                // I - HTTP cnnection
               const char *cookie)      // I - Cookie string
 {
-  if (!http)
+  // Range check input...
+  if (!http || !cookie)
     return;
 
+  // Set or append the Set-Cookie value....
   if (http->cookie)
-    free(http->cookie);
+  {
+    // Append with a newline between values...
+    size_t     clen,                   // Length of cookie string
+               ctotal;                 // Total length of cookies
+    char       *temp;                  // Temporary value
 
-  if (cookie)
-    http->cookie = strdup(cookie);
+    clen   = strlen(http->cookie);
+    ctotal = clen + strlen(cookie) + 2;
+
+    if ((temp = realloc(http->cookie, ctotal)) == NULL)
+      return;
+
+    temp[clen] = '\n';
+    cupsCopyString(temp + clen + 1, cookie, ctotal - clen - 1);
+  }
   else
-    http->cookie = NULL;
+  {
+    // Just copy/set this cookie...
+    http->cookie = strdup(cookie);
+  }
 }
 
 
@@ -3470,18 +3493,34 @@ httpWriteResponse(http_t        *http,  // I - HTTP connection
 
     if (http->cookie)
     {
-      if (strchr(http->cookie, ';'))
+      char     *start,                 // Start of cookie
+               *ptr;                   // Pointer into cookie
+
+      for (start = http->cookie; start; start = ptr)
       {
-        if (httpPrintf(http, "Set-Cookie: %s\r\n", http->cookie) < 1)
+        if ((ptr = strchr(start, '\n')) != NULL)
+          *ptr = '\0';
+
+       if (strchr(start, ';'))
+       {
+         if (httpPrintf(http, "Set-Cookie: %s\r\n", start) < 1)
+         {
+           http->status = HTTP_STATUS_ERROR;
+           if (ptr)
+             *ptr = '\n';
+           return (-1);
+         }
+       }
+       else if (httpPrintf(http, "Set-Cookie: %s; path=/; httponly;%s\r\n", http->cookie, http->tls ? " secure;" : "") < 1)
        {
          http->status = HTTP_STATUS_ERROR;
+         if (ptr)
+           *ptr = '\n';
          return (-1);
        }
-      }
-      else if (httpPrintf(http, "Set-Cookie: %s; path=/; httponly;%s\r\n", http->cookie, http->tls ? " secure;" : "") < 1)
-      {
-       http->status = HTTP_STATUS_ERROR;
-       return (-1);
+
+       if (ptr)
+         *ptr++ = '\n';
       }
     }