-
-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathCookie.php
More file actions
166 lines (139 loc) · 4.06 KB
/
Copy pathCookie.php
File metadata and controls
166 lines (139 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<?php
declare(strict_types=1);
namespace Bow\Session;
use Bow\Security\Crypto;
class Cookie
{
/**
* The decrypted data collection
*
* @var array
*/
private static array $is_decrypt = [];
/**
* Check if a collection is empty.
*
* @return bool
*/
public static function isEmpty(): bool
{
return empty($_COOKIE);
}
/**
* Allows you to retrieve a value or collection of cookie value.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public static function get(string $key, mixed $default = null): mixed
{
if (static::has($key)) {
$value = Crypto::decrypt($_COOKIE[$key]);
// Cookie::set() json-encodes the payload before encrypting, so decode
// here to mirror it (and Cookie::all()). Fall back to the raw value
// when it is not the JSON we wrote — e.g. a tampered cookie decrypts
// to false, or a cookie was set outside the framework.
if (is_string($value)) {
$decoded = json_decode($value, true);
if (json_last_error() === JSON_ERROR_NONE) {
return $decoded;
}
}
return $value;
}
if (is_callable($default)) {
return $default();
}
return $default;
}
/**
* Check for existence of a key in the session collection
*
* @param string $key
* @param bool $strict
* @return bool
*/
public static function has(string $key, bool $strict = false): bool
{
$isset = isset($_COOKIE[$key]);
if (!$strict) {
return $isset;
}
if ($isset) {
$isset = !empty($_COOKIE[$key]);
}
return $isset;
}
/**
* Return all values of COOKIE
*
* @return array
*/
public static function all(): array
{
foreach ($_COOKIE as $key => $value) {
$_COOKIE[$key] = json_decode(Crypto::decrypt($value));
}
return $_COOKIE;
}
/**
* Delete an entry in the table
*
* @param string $key
* @return string|bool|null
*/
public static function remove(string $key): string|bool|null
{
$old = null;
if (!static::has($key)) {
return null;
}
if (!(static::$is_decrypt[$key] ?? false)) {
$old = Crypto::decrypt($_COOKIE[$key]);
unset(static::$is_decrypt[$key]);
}
static::set($key, '', -1000);
unset($_COOKIE[$key]);
return $old;
}
/**
* Add a value to the cookie table.
*
* @param int|string $key
* @param mixed $data
* @param int $expiration
* @return bool
*/
public static function set(
int|string $key,
mixed $data,
int $expiration = 3600,
): bool {
$data = Crypto::encrypt(json_encode($data));
return setcookie($key, $data, static::options($expiration));
}
/**
* Build the setcookie() options array from the session config.
*
* Every value is coerced to its declared type. config('session.domain') is
* null when SESSION_DOMAIN is unset; passing null straight to setcookie()
* is deprecated on PHP 8.x and a fatal TypeError on PHP 9, so cast here.
*
* @param int $expiration
* @return array
*/
private static function options(int $expiration): array
{
// config() with a second argument is a setter, not a getter-with-default,
// so read each value first and apply the fallback in PHP.
return [
'expires' => time() + $expiration,
'path' => (string) (config('session.path') ?? '/'),
'domain' => (string) (config('session.domain') ?? ''),
'secure' => (bool) config('session.secure'),
'httponly' => (bool) (config('session.httponly') ?? true),
'samesite' => (string) (config('session.samesite') ?? 'Lax'),
];
}
}