From: Michael R Sweet Date: Thu, 1 May 2025 22:43:53 +0000 (-0400) Subject: Update httpSetCookie to support multiple Set-Cookie values. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b736c8d737666576f1d57c3154e1134d2510bf3;p=thirdparty%2Fcups.git Update httpSetCookie to support multiple Set-Cookie values. --- diff --git a/CHANGES.md b/CHANGES.md index cc21aaa9db..452d84aa57 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -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 diff --git a/cups/http.c b/cups/http.c index 71cb1d97b8..823ac7bec4 100644 --- a/cups/http.c +++ b/cups/http.c @@ -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'; } }