Skip to content

Commit e609e44

Browse files
committed
Implement proof-of-concept partitioned option for setcookie
1 parent fc66f37 commit e609e44

File tree

4 files changed

+34
-14
lines changed

4 files changed

+34
-14
lines changed

ext/standard/head.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ PHPAPI int php_header(void)
7979
#define ILLEGAL_COOKIE_CHARACTER "\",\", \";\", \" \", \"\\t\", \"\\r\", \"\\n\", \"\\013\", or \"\\014\""
8080
PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t expires,
8181
zend_string *path, zend_string *domain, bool secure, bool httponly,
82-
zend_string *samesite, bool url_encode)
82+
zend_string *samesite, bool partitioned, bool url_encode)
8383
{
8484
zend_string *dt;
8585
sapi_header_line ctr = {0};
@@ -117,6 +117,11 @@ PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t e
117117
return FAILURE;
118118
}
119119
#endif
120+
if (partitioned && !secure) {
121+
zend_value_error("%s(): \"partitioned\" option cannot be used without \"secure\" option",
122+
get_active_function_name());
123+
return FAILURE;
124+
}
120125

121126
/* Should check value of SameSite? */
122127

@@ -182,6 +187,9 @@ PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t e
182187
smart_str_appends(&buf, COOKIE_SAMESITE);
183188
smart_str_append(&buf, samesite);
184189
}
190+
if (partitioned) {
191+
smart_str_appends(&buf, COOKIE_PARTITIONED);
192+
}
185193

186194
ctr.line = ZSTR_VAL(buf.s);
187195
ctr.line_len = (uint32_t) ZSTR_LEN(buf.s);
@@ -192,7 +200,7 @@ PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t e
192200
}
193201

194202
static zend_result php_head_parse_cookie_options_array(HashTable *options, zend_long *expires, zend_string **path,
195-
zend_string **domain, bool *secure, bool *httponly, zend_string **samesite)
203+
zend_string **domain, bool *secure, bool *httponly, zend_string **samesite, bool *partitioned)
196204
{
197205
zend_string *key;
198206
zval *value;
@@ -214,6 +222,8 @@ static zend_result php_head_parse_cookie_options_array(HashTable *options, zend_
214222
*httponly = zval_is_true(value);
215223
} else if (zend_string_equals_literal_ci(key, "samesite")) {
216224
*samesite = zval_get_string(value);
225+
} else if (zend_string_equals_literal_ci(key, "partitioned")) {
226+
*partitioned = zval_is_true(value);
217227
} else {
218228
zend_value_error("%s(): option \"%s\" is invalid", get_active_function_name(), ZSTR_VAL(key));
219229
return FAILURE;
@@ -227,7 +237,7 @@ static void php_setcookie_common(INTERNAL_FUNCTION_PARAMETERS, bool is_raw)
227237
HashTable *options = NULL;
228238
zend_long expires = 0;
229239
zend_string *name, *value = NULL, *path = NULL, *domain = NULL, *samesite = NULL;
230-
bool secure = 0, httponly = 0;
240+
bool secure = 0, httponly = 0, partitioned = false;
231241

232242
ZEND_PARSE_PARAMETERS_START(1, 7)
233243
Z_PARAM_STR(name)
@@ -248,13 +258,13 @@ static void php_setcookie_common(INTERNAL_FUNCTION_PARAMETERS, bool is_raw)
248258
}
249259

250260
if (FAILURE == php_head_parse_cookie_options_array(options, &expires, &path,
251-
&domain, &secure, &httponly, &samesite)
261+
&domain, &secure, &httponly, &samesite, &partitioned)
252262
) {
253263
goto cleanup;
254264
}
255265
}
256266

257-
if (php_setcookie(name, value, expires, path, domain, secure, httponly, samesite, !is_raw) == SUCCESS) {
267+
if (php_setcookie(name, value, expires, path, domain, secure, httponly, samesite, partitioned, !is_raw) == SUCCESS) {
258268
RETVAL_TRUE;
259269
} else {
260270
RETVAL_FALSE;

ext/standard/head.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,20 @@
1717
#ifndef HEAD_H
1818
#define HEAD_H
1919

20-
#define COOKIE_EXPIRES "; expires="
21-
#define COOKIE_MAX_AGE "; Max-Age="
22-
#define COOKIE_DOMAIN "; domain="
23-
#define COOKIE_PATH "; path="
24-
#define COOKIE_SECURE "; secure"
25-
#define COOKIE_HTTPONLY "; HttpOnly"
26-
#define COOKIE_SAMESITE "; SameSite="
20+
#define COOKIE_EXPIRES "; expires="
21+
#define COOKIE_MAX_AGE "; Max-Age="
22+
#define COOKIE_DOMAIN "; domain="
23+
#define COOKIE_PATH "; path="
24+
#define COOKIE_SECURE "; secure"
25+
#define COOKIE_HTTPONLY "; HttpOnly"
26+
#define COOKIE_SAMESITE "; SameSite="
27+
#define COOKIE_PARTITIONED "; Partitioned"
2728

2829
extern PHP_RINIT_FUNCTION(head);
2930

3031
PHPAPI int php_header(void);
3132
PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t expires,
3233
zend_string *path, zend_string *domain, bool secure, bool httponly,
33-
zend_string *samesite, bool url_encode);
34+
zend_string *samesite, bool partitioned, bool url_encode);
3435

3536
#endif

ext/standard/tests/network/setcookie.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ setcookie('name', 'value', 0, '', '', FALSE, TRUE);
1919

2020
setcookie('name', 'value', ['expires' => $tsp]);
2121
setcookie('name', 'value', ['expires' => $tsn, 'path' => '/path/', 'domain' => 'domain.tld', 'secure' => true, 'httponly' => true, 'samesite' => 'Strict']);
22+
setcookie('name', 'value', ['secure' => true, 'partitioned' => true]);
2223

2324
$expected = array(
2425
'Set-Cookie: name=deleted; expires='.date('D, d M Y H:i:s', 1).' GMT; Max-Age=0',
@@ -34,7 +35,8 @@ $expected = array(
3435
'Set-Cookie: name=value; secure',
3536
'Set-Cookie: name=value; HttpOnly',
3637
'Set-Cookie: name=value; expires='.date('D, d M Y H:i:s', $tsp).' GMT; Max-Age=5',
37-
'Set-Cookie: name=value; expires='.date('D, d M Y H:i:s', $tsn).' GMT; Max-Age=0; path=/path/; domain=domain.tld; secure; HttpOnly; SameSite=Strict'
38+
'Set-Cookie: name=value; expires='.date('D, d M Y H:i:s', $tsn).' GMT; Max-Age=0; path=/path/; domain=domain.tld; secure; HttpOnly; SameSite=Strict',
39+
'Set-Cookie: name=value; secure; Partitioned'
3840
);
3941

4042
$headers = headers_list();

ext/standard/tests/network/setcookie_array_option_error.phpt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ try {
3737
} catch (\ValueError $e) {
3838
echo $e->getMessage() . "\n";
3939
}
40+
// Partitioned without secure
41+
try {
42+
setcookie('name', 'value', ['partitioned' => true]);
43+
} catch (\ValueError $e) {
44+
echo $e->getMessage() . "\n";
45+
}
4046

4147
// Arguments after options array (will not be set)
4248
try {
@@ -66,6 +72,7 @@ setcookie(): option array cannot have numeric keys
6672
setcookie(): option "foo" is invalid
6773
setcookie(): "path" option cannot contain ",", ";", " ", "\t", "\r", "\n", "\013", or "\014"
6874
setcookie(): "domain" option cannot contain ",", ";", " ", "\t", "\r", "\n", "\013", or "\014"
75+
setcookie(): "partitioned" option cannot be used without "secure" option
6976
setcookie(): Expects exactly 3 arguments when argument #3 ($expires_or_options) is an array
7077
bool(true)
7178
array(1) {

0 commit comments

Comments
 (0)