From 5005a09f06a29afb9c55b8dd8f2c13c410b09de2 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Tue, 24 Oct 2023 22:37:21 +0900 Subject: [PATCH] Add Rhymix\Framework\Cookie class with sane defaults --- classes/context/Context.class.php | 2 +- classes/mobile/Mobile.class.php | 3 +- common/framework/Cookie.php | 124 ++++++++++++++++++++++++++++++ common/framework/UA.php | 6 +- 4 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 common/framework/Cookie.php diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index 0576b55f1..a185d5da2 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -321,7 +321,7 @@ class Context $lang_type = preg_replace('/[^a-zA-Z0-9_-]/', '', $lang_type ?? ''); if ($set_lang_cookie) { - setcookie('lang_type', $lang_type, time() + 86400 * 365, \RX_BASEURL, '', !!config('session.use_ssl_cookies')); + Rhymix\Framework\Cookie::set('lang_type', $lang_type, ['expires' => 365]); } if(!$lang_type || !isset($enabled_langs[$lang_type])) diff --git a/classes/mobile/Mobile.class.php b/classes/mobile/Mobile.class.php index 9e227bb4b..49e5b91e0 100644 --- a/classes/mobile/Mobile.class.php +++ b/classes/mobile/Mobile.class.php @@ -72,8 +72,7 @@ class Mobile $uatype = $uahash . ':' . (self::$_ismobile ? '1' : '0'); if ($cookie !== $uatype) { - setcookie('rx_uatype', $uatype, 0, \RX_BASEURL, '', !!config('session.use_ssl_cookies')); - $_COOKIE['rx_uatype'] = $uatype; + Rhymix\Framework\Cookie::set('rx_uatype', $uatype, ['expires' => 0]); } return self::$_ismobile; diff --git a/common/framework/Cookie.php b/common/framework/Cookie.php new file mode 100644 index 000000000..2c98f4d60 --- /dev/null +++ b/common/framework/Cookie.php @@ -0,0 +1,124 @@ + 0 && $options['expires'] < 36500) + { + $options['expires'] = time() + ($options['expires'] * 86400); + } + else + { + // Session cookie or Unix timestamp, no change + } + + // Set defaults. + if (!isset($options['path'])) + { + $options['path'] = \RX_BASEURL; + } + if (!isset($options['secure'])) + { + $options['secure'] = \RX_SSL && !!config('session.use_ssl_cookies'); + } + if (!isset($options['samesite'])) + { + $options['samesite'] = 'Lax'; + } + + // PHP 7.3+ supports the samesite attribute natively. PHP 7.2 requires a hack. + if (\PHP_VERSION_ID >= 70300) + { + $result = setcookie($name, $value, $options); + } + else + { + $expires = $options['expires']; + $path = $options['path'] ?? \RX_BASEURL; + $domain = $options['domain'] ?? null; + $secure = $options['secure'] ?? false; + $httponly = $options['httponly'] ?? false; + if (!empty($options['samesite'])) + { + $path = ($path ?: '/') . '; SameSite=' . $options['samesite']; + } + $result = setcookie($name, $value, $expires, $path, $domain, $secure, $httponly); + } + + // Make the cookie immediately available server-side. + if ($result && $options['expires'] >= 0) + { + $_COOKIE[$name] = $value; + } + return $result; + } + + /** + * Delete a cookie. + * + * You must pass an options array with the same values that were used to + * create the cookie, except 'expires' which doesn't apply here. + * + * @param string $name + * @param array $options + * @return bool + */ + public static function remove(string $name, array $options = []): bool + { + // Setting the expiry date to a negative number will take care of it. + $options['expires'] = -1; + $result = self::set($name, '', $options); + + // Make the cookie immediately unavailable server-side. + if ($result) + { + unset($_COOKIE[$name]); + } + return $result; + } +} diff --git a/common/framework/UA.php b/common/framework/UA.php index 82b9a4741..573af9d51 100644 --- a/common/framework/UA.php +++ b/common/framework/UA.php @@ -470,13 +470,11 @@ class UA { if (in_array($color_scheme, ['light', 'dark'])) { - $_COOKIE['rx_color_scheme'] = $color_scheme; - setcookie('rx_color_scheme', $color_scheme, time() + 86400 * 365, \RX_BASEURL, '', !!config('session.use_ssl_cookies')); + Cookie::set('rx_color_scheme', $color_scheme, ['expires' => 365]); } else { - unset($_COOKIE['rx_color_scheme']); - setcookie('rx_color_scheme', 'deleted', time() - 86400, \RX_BASEURL); + Cookie::remove('rx_color_scheme'); } } }