Skip to content

Commit 434b87e

Browse files
committed
Support multiple Set-Cookie values.
1 parent 12a91a1 commit 434b87e

4 files changed

Lines changed: 70 additions & 29 deletions

File tree

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ libcups v3.0.0 (YYYY-MM-DD)
66

77
- Added `cupsOAuthGetJWKS` API.
88
- Added `httpGetCookieValue` and `httpGetSecurity` APIs.
9+
- Updated `httpSetCookie` API to support multiple "Set-Cookie:" header values.
910
- Updated `ippfind` to use `cupsGetClock` API.
1011
- Fixed return values of `ippDateToTime` when the timezone isn't GMT.
1112
- Fixed a potential timing issue with `cupsEnumDests`.

cups/http.c

Lines changed: 57 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -840,11 +840,11 @@ httpGetContentEncoding(http_t *http) // I - HTTP connection
840840

841841

842842
//
843-
// 'httpGetCookie()' - Get "Cookie:" data from the HTTP connection.
843+
// 'httpGetCookie()' - Get cookie data from the HTTP connection.
844844
//
845-
// This function returns any HTTP "Cookie:" header data for the given HTTP
846-
// connection as described in RFC 6265. Use the @link httpGetCookieValue@ to
847-
// get the value of a named cookie.
845+
// This function returns any HTTP "Set-Cookie:" or "Cookie:" header data for the
846+
// given HTTP connection as described in RFC 6265. Use the
847+
// @link httpGetCookieValue@ to get the value of a named "Cookie:" value.
848848
//
849849

850850
const char * // O - Cookie data or `NULL`
@@ -2205,22 +2205,46 @@ httpSetBlocking(http_t *http, // I - HTTP connection
22052205

22062206

22072207
//
2208-
// 'httpSetCookie()' - Set the cookie value(s).
2208+
// 'httpSetCookie()' - Add Set-Cookie value(s).
2209+
//
2210+
// This function adds one or more Set-Cookie header values that will be sent to
2211+
// the client with the @link httpWriteResponse@ function. Each value conforms
2212+
// to the format defined in RFC 6265. Multiple values can be passed in the
2213+
// "cookie" string separated by a newline character.
2214+
//
2215+
// Call the @link httpClearCookies@ function to clear all Set-Cookie values.
22092216
//
22102217

22112218
void
22122219
httpSetCookie(http_t *http, // I - Connection
22132220
const char *cookie) // I - Cookie string
22142221
{
2215-
if (!http)
2222+
// Range check input...
2223+
if (!http || !cookie)
22162224
return;
22172225

2218-
free(http->cookie);
2226+
// Set or append the Set-Cookie value....
2227+
if (http->cookie)
2228+
{
2229+
// Append with a newline between values...
2230+
size_t clen, // Length of cookie string
2231+
ctotal; // Total length of cookies
2232+
char *temp; // Temporary value
22192233

2220-
if (cookie)
2221-
http->cookie = strdup(cookie);
2234+
clen = strlen(http->cookie);
2235+
ctotal = clen + strlen(cookie) + 2;
2236+
2237+
if ((temp = realloc(http->cookie, ctotal)) == NULL)
2238+
return;
2239+
2240+
temp[clen] = '\n';
2241+
cupsCopyString(temp + clen + 1, cookie, ctotal - clen - 1);
2242+
}
22222243
else
2223-
http->cookie = NULL;
2244+
{
2245+
// Just copy/set this cookie...
2246+
http->cookie = strdup(cookie);
2247+
}
22242248
}
22252249

22262250

@@ -3050,26 +3074,35 @@ httpWriteResponse(http_t *http, // I - HTTP connection
30503074

30513075
if (http->cookie)
30523076
{
3053-
if (strchr(http->cookie, ';'))
3077+
char *start, // Start of cookie
3078+
*ptr; // Pointer into cookie
3079+
3080+
for (start = http->cookie; start; start = ptr)
30543081
{
3055-
if (httpPrintf(http, "Set-Cookie: %s\r\n", http->cookie) < 1)
3082+
if ((ptr = strchr(start, '\n')) != NULL)
3083+
*ptr = '\0';
3084+
3085+
if (strchr(start, ';'))
3086+
{
3087+
if (httpPrintf(http, "Set-Cookie: %s\r\n", start) < 1)
3088+
{
3089+
http->status = HTTP_STATUS_ERROR;
3090+
if (ptr)
3091+
*ptr = '\n';
3092+
return (false);
3093+
}
3094+
}
3095+
else if (httpPrintf(http, "Set-Cookie: %s; path=/; httponly;%s\r\n", http->cookie, http->tls ? " secure;" : "") < 1)
30563096
{
30573097
http->status = HTTP_STATUS_ERROR;
3098+
if (ptr)
3099+
*ptr = '\n';
30583100
return (false);
30593101
}
3060-
}
3061-
else if (httpPrintf(http, "Set-Cookie: %s; path=/; httponly;%s\r\n", http->cookie, http->tls ? " secure;" : "") < 1)
3062-
{
3063-
http->status = HTTP_STATUS_ERROR;
3064-
return (false);
3065-
}
3066-
}
30673102

3068-
// "Click-jacking" defense...
3069-
if (httpPrintf(http, "X-Frame-Options: DENY\r\nContent-Security-Policy: frame-ancestors 'none'\r\n") < 1)
3070-
{
3071-
http->status = HTTP_STATUS_ERROR;
3072-
return (false);
3103+
if (ptr)
3104+
*ptr++ = '\n';
3105+
}
30733106
}
30743107
}
30753108

doc/cupspm.epub

144 Bytes
Binary file not shown.

doc/cupspm.html

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7782,7 +7782,7 @@ <h4 class="discussion">Discussion</h4>
77827782
client. The value returned can be use in subsequent requests (for clients)
77837783
or in the response (for servers) in order to compress the content stream.</p>
77847784
<h3 class="function"><a id="httpGetCookie">httpGetCookie</a></h3>
7785-
<p class="description">Get &quot;Cookie:&quot; data from the HTTP connection.</p>
7785+
<p class="description">Get cookie data from the HTTP connection.</p>
77867786
<p class="code">
77877787
<span class="reserved">const</span> <span class="reserved">char</span> *httpGetCookie(<a href="#http_t">http_t</a> *http);</p>
77887788
<h4 class="parameters">Parameters</h4>
@@ -7793,9 +7793,9 @@ <h4 class="parameters">Parameters</h4>
77937793
<h4 class="returnvalue">Return Value</h4>
77947794
<p class="description">Cookie data or <code>NULL</code></p>
77957795
<h4 class="discussion">Discussion</h4>
7796-
<p class="discussion">This function returns any HTTP &quot;Cookie:&quot; header data for the given HTTP
7797-
connection as described in RFC 6265. Use the <a href="#httpGetCookieValue"><code>httpGetCookieValue</code></a> to
7798-
get the value of a named cookie.</p>
7796+
<p class="discussion">This function returns any HTTP &quot;Set-Cookie:&quot; or &quot;Cookie:&quot; header data for the
7797+
given HTTP connection as described in RFC 6265. Use the
7798+
<a href="#httpGetCookieValue"><code>httpGetCookieValue</code></a> to get the value of a named &quot;Cookie:&quot; value.</p>
77997799
<h3 class="function"><a id="httpGetCookieValue">httpGetCookieValue</a></h3>
78007800
<p class="description">Get the value of a named cookie from the HTTP connection.</p>
78017801
<p class="code">
@@ -8295,7 +8295,7 @@ <h4 class="discussion">Discussion</h4>
82958295
or writing data. The &quot;http&quot; argument specifies the HTTP connection and the
82968296
&quot;blocking&quot; argument specifies whether to use blocking behavior.</p>
82978297
<h3 class="function"><a id="httpSetCookie">httpSetCookie</a></h3>
8298-
<p class="description">Set the cookie value(s).</p>
8298+
<p class="description">Add Set-Cookie value(s).</p>
82998299
<p class="code">
83008300
<span class="reserved">void</span> httpSetCookie(<a href="#http_t">http_t</a> *http, <span class="reserved">const</span> <span class="reserved">char</span> *cookie);</p>
83018301
<h4 class="parameters">Parameters</h4>
@@ -8305,6 +8305,13 @@ <h4 class="parameters">Parameters</h4>
83058305
<tr><th>cookie</th>
83068306
<td class="description">Cookie string</td></tr>
83078307
</tbody></table>
8308+
<h4 class="discussion">Discussion</h4>
8309+
<p class="discussion">This function adds one or more Set-Cookie header values that will be sent to
8310+
the client with the <a href="#httpWriteResponse"><code>httpWriteResponse</code></a> function. Each value conforms
8311+
to the format defined in RFC 6265. Multiple values can be passed in the
8312+
&quot;cookie&quot; string separated by a newline character.<br>
8313+
<br>
8314+
Call the <a href="#httpClearCookies"><code>httpClearCookies</code></a> function to clear all Set-Cookie values.</p>
83088315
<h3 class="function"><a id="httpSetDefaultField">httpSetDefaultField</a></h3>
83098316
<p class="description">Set the default value of a HTTP header.</p>
83108317
<p class="code">

0 commit comments

Comments
 (0)