diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index b6b9739a4..64c398008 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -748,9 +748,9 @@ class Actions $aResult['ContactsSync'] = $aData; } - $sToken = Utils::GetCookie(self::AUTH_MAILTO_TOKEN_KEY); + $sToken = \SnappyMail\Cookies::get(self::AUTH_MAILTO_TOKEN_KEY); if (null !== $sToken) { - Utils::ClearCookie(self::AUTH_MAILTO_TOKEN_KEY); + \SnappyMail\Cookies::clear(self::AUTH_MAILTO_TOKEN_KEY); $mMailToData = Utils::DecodeKeyValuesQ($sToken); if (!empty($mMailToData['MailTo']) && 'MailTo' === $mMailToData['MailTo'] && !empty($mMailToData['To'])) { diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php index 2e5d8e639..826eb81e6 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Accounts.php @@ -181,7 +181,7 @@ trait Accounts $bReload = false; $oAccount = $this->getAccountFromToken(); if ($oAccount instanceof AdditionalAccount && $oAccount->Email() === $sEmailToDelete) { - Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY); + \SnappyMail\Cookies::clear(self::AUTH_ADDITIONAL_TOKEN_KEY); $bReload = true; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php index 5cbdaa6f5..7e31d78b1 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php @@ -29,13 +29,13 @@ trait Admin protected function getAdminAuthKey() : string { - $cookie = Utils::GetCookie(static::$AUTH_ADMIN_TOKEN_KEY); + $cookie = \SnappyMail\Cookies::get(static::$AUTH_ADMIN_TOKEN_KEY); if ($cookie) { $aAdminHash = Utils::DecodeKeyValuesQ($cookie); if (!empty($aAdminHash[1]) && 'token' === $aAdminHash[0]) { return $aAdminHash[1]; } - Utils::ClearCookie(static::$AUTH_ADMIN_TOKEN_KEY); + \SnappyMail\Cookies::clear(static::$AUTH_ADMIN_TOKEN_KEY); } return ''; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php index fb5b13efd..a65ed8ab7 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/UserAuth.php @@ -9,6 +9,7 @@ use RainLoop\Model\MainAccount; use RainLoop\Model\AdditionalAccount; use RainLoop\Providers\Storage\Enumerations\StorageType; use RainLoop\Exceptions\ClientException; +use SnappyMail\Cookies; trait UserAuth { @@ -156,12 +157,12 @@ trait UserAuth private static function SetAccountCookie(string $sName, ?Account $oAccount) { if ($oAccount) { - Utils::SetCookie( + Cookies::set( $sName, \MailSo\Base\Utils::UrlSafeBase64Encode(\SnappyMail\Crypt::EncryptToJSON($oAccount)) ); } else { - Utils::ClearCookie($sName); + Cookies::clear($sName); } } @@ -209,7 +210,7 @@ trait UserAuth $this->getMainAccountFromToken($bThrowExceptionOnFalse); if (false === $this->oAdditionalAuthAccount && isset($_COOKIE[self::AUTH_ADDITIONAL_TOKEN_KEY])) { - $aData = Utils::GetSecureCookie(self::AUTH_ADDITIONAL_TOKEN_KEY); + $aData = Cookies::getSecure(self::AUTH_ADDITIONAL_TOKEN_KEY); if ($aData) { $this->oAdditionalAuthAccount = AdditionalAccount::NewInstanceFromTokenArray( $this, @@ -219,7 +220,7 @@ trait UserAuth } if (!$this->oAdditionalAuthAccount) { $this->oAdditionalAuthAccount = null; - Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY); + Cookies::clear(self::AUTH_ADDITIONAL_TOKEN_KEY); } } @@ -234,14 +235,14 @@ trait UserAuth if (false === $this->oMainAuthAccount) try { $this->oMainAuthAccount = null; if (isset($_COOKIE[self::AUTH_SPEC_LOGOUT_TOKEN_KEY])) { - Utils::ClearCookie(self::AUTH_SPEC_LOGOUT_TOKEN_KEY); - Utils::ClearCookie(self::AUTH_SIGN_ME_TOKEN_KEY); -// Utils::ClearCookie(self::AUTH_SPEC_TOKEN_KEY); -// Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY); - Utils::ClearCookie(Utils::SESSION_TOKEN); + Cookies::clear(self::AUTH_SPEC_LOGOUT_TOKEN_KEY); + Cookies::clear(self::AUTH_SIGN_ME_TOKEN_KEY); +// Cookies::clear(self::AUTH_SPEC_TOKEN_KEY); +// Cookies::clear(self::AUTH_ADDITIONAL_TOKEN_KEY); + Cookies::clear(Utils::SESSION_TOKEN); } - $aData = Utils::GetSecureCookie(self::AUTH_SPEC_TOKEN_KEY); + $aData = Cookies::getSecure(self::AUTH_SPEC_TOKEN_KEY); if ($aData) { /** * Server side control/kickout of logged in sessions @@ -274,7 +275,7 @@ trait UserAuth } } if (!$this->oMainAuthAccount) { - Utils::ClearCookie(Utils::SESSION_TOKEN); + Cookies::clear(Utils::SESSION_TOKEN); // \MailSo\Base\Http::StatusHeader(401); $this->Logout(true); // $sAdditionalMessage = $this->StaticI18N('SESSION_GONE'); @@ -310,7 +311,7 @@ trait UserAuth $this->oAdditionalAuthAccount = false; $this->oMainAuthAccount = $oAccount; if (!isset($_COOKIE['smctoken'])) { - \RainLoop\Utils::SetCookie('smctoken', \base64_encode(\random_bytes(16)), 0, false); + Cookies::set('smctoken', \base64_encode(\random_bytes(16)), 0, false); } static::SetAccountCookie(self::AUTH_SPEC_TOKEN_KEY, $oAccount); } @@ -327,7 +328,7 @@ trait UserAuth private static function GetSignMeToken(): ?array { - $sSignMeToken = Utils::GetCookie(self::AUTH_SIGN_ME_TOKEN_KEY); + $sSignMeToken = Cookies::get(self::AUTH_SIGN_ME_TOKEN_KEY); if ($sSignMeToken) { \SnappyMail\Log::notice(self::AUTH_SIGN_ME_TOKEN_KEY, 'decrypt'); $aResult = \SnappyMail\Crypt::DecryptUrlSafe($sSignMeToken); @@ -336,7 +337,7 @@ trait UserAuth } \SnappyMail\Log::notice(self::AUTH_SIGN_ME_TOKEN_KEY, 'invalid'); // Don't clear due to smctoken cookie missing at initialization and login checkbox -// Utils::ClearCookie(self::AUTH_SIGN_ME_TOKEN_KEY); +// Cookies::clear(self::AUTH_SIGN_ME_TOKEN_KEY); } return null; } @@ -346,7 +347,7 @@ trait UserAuth $this->ClearSignMeData(); $uuid = \SnappyMail\UUID::generate(); $data = \SnappyMail\Crypt::Encrypt($oAccount); - Utils::SetCookie( + Cookies::set( self::AUTH_SIGN_ME_TOKEN_KEY, \SnappyMail\Crypt::EncryptUrlSafe([ 'e' => $oAccount->Email(), @@ -405,7 +406,7 @@ trait UserAuth if ($aTokenData) { $this->StorageProvider()->Clear($aTokenData['e'], StorageType::SIGN_ME, $aTokenData['u']); } - Utils::ClearCookie(self::AUTH_SIGN_ME_TOKEN_KEY); + Cookies::clear(self::AUTH_SIGN_ME_TOKEN_KEY); } /** @@ -415,14 +416,14 @@ trait UserAuth public function SetAuthLogoutToken(): void { \header('X-RainLoop-Action: Logout'); - Utils::SetCookie(self::AUTH_SPEC_LOGOUT_TOKEN_KEY, \md5($_SERVER['REQUEST_TIME_FLOAT'])); + Cookies::set(self::AUTH_SPEC_LOGOUT_TOKEN_KEY, \md5($_SERVER['REQUEST_TIME_FLOAT'])); } public function GetSpecLogoutCustomMgsWithDeletion(): string { - $sResult = Utils::GetCookie(self::AUTH_SPEC_LOGOUT_CUSTOM_MSG_KEY) ?: ''; + $sResult = Cookies::get(self::AUTH_SPEC_LOGOUT_CUSTOM_MSG_KEY) ?: ''; if (\strlen($sResult)) { - Utils::ClearCookie(self::AUTH_SPEC_LOGOUT_CUSTOM_MSG_KEY); + Cookies::clear(self::AUTH_SPEC_LOGOUT_CUSTOM_MSG_KEY); } return $sResult; @@ -430,14 +431,14 @@ trait UserAuth public function SetSpecLogoutCustomMgsWithDeletion(string $sMessage): void { - Utils::SetCookie(self::AUTH_SPEC_LOGOUT_CUSTOM_MSG_KEY, $sMessage); + Cookies::set(self::AUTH_SPEC_LOGOUT_CUSTOM_MSG_KEY, $sMessage); } public function Logout(bool $bMain) : void { -// Utils::ClearCookie(Utils::SESSION_TOKEN); - Utils::ClearCookie(self::AUTH_ADDITIONAL_TOKEN_KEY); - $bMain && Utils::ClearCookie(self::AUTH_SPEC_TOKEN_KEY); +// Cookies::clear(Utils::SESSION_TOKEN); + Cookies::clear(self::AUTH_ADDITIONAL_TOKEN_KEY); + $bMain && Cookies::clear(self::AUTH_SPEC_TOKEN_KEY); // TODO: kill SignMe data to prevent automatic login? } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php index 3888db991..ac3d3f1a0 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ActionsAdmin.php @@ -133,7 +133,7 @@ class ActionsAdmin extends Actions if ($sAdminKey) { $this->Cacher(null, true)->Delete(KeyPathHelper::SessionAdminKey($sAdminKey)); } - Utils::ClearCookie(static::$AUTH_ADMIN_TOKEN_KEY); + \SnappyMail\Cookies::clear(static::$AUTH_ADMIN_TOKEN_KEY); return $this->TrueResponse(); } @@ -331,7 +331,7 @@ class ActionsAdmin extends Actions if (!$sToken) { throw new \RuntimeException('Failed to encode admin token'); } - Utils::SetCookie(static::$AUTH_ADMIN_TOKEN_KEY, $sToken); + \SnappyMail\Cookies::set(static::$AUTH_ADMIN_TOKEN_KEY, $sToken); return $sToken; } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Api.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Api.php index 19f46597b..783465e8d 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Api.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Api.php @@ -5,16 +5,6 @@ namespace RainLoop; abstract class Api { - public static function Handle() : bool - { - static $bOne = false; - if (!$bOne) { - static::SetupDefaultConfig(); - $bOne = true; - } - return $bOne; - } - public static function Actions() : Actions { static $oActions = null; @@ -40,6 +30,7 @@ abstract class Api // \ini_set('display_errors', '1'); \ini_set('log_errors', '1'); } + \MailSo\Config::$BoundaryPrefix = \trim($oConfig->Get('labs', 'boundary_prefix', '')); } return $oConfig; } @@ -82,17 +73,6 @@ abstract class Api return $oLogger; } - protected static function SetupDefaultConfig() : void - { - \MailSo\Config::$BoundaryPrefix = \trim(static::Config()->Get('labs', 'boundary_prefix', '')); - - Utils::$CookieDefaultPath = static::Config()->Get('labs', 'cookie_default_path', ''); - Utils::$CookieSameSite = static::Config()->Get('security', 'cookie_samesite', 'Strict'); - Utils::$CookieSecure = isset($_SERVER['HTTPS']) - || 'None' == Utils::$CookieSameSite - || !!static::Config()->Get('labs', 'cookie_default_secure', false); - } - public static function Version() : string { return APP_VERSION; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php index 7efe3db55..fb7b2b5f7 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php @@ -545,7 +545,7 @@ class ServiceActions $this->oHttp->ServerNoCache(); $sTo = \trim($_GET['to'] ?? ''); if (!empty($sTo) && \preg_match('/^mailto:/i', $sTo)) { - Utils::SetCookie( + \SnappyMail\Cookies::set( Actions::AUTH_MAILTO_TOKEN_KEY, Utils::EncodeKeyValuesQ(array( 'Time' => \microtime(true), diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Utils.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Utils.php index a756ad9d1..c484a6ef7 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Utils.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Utils.php @@ -4,12 +4,6 @@ namespace RainLoop; class Utils { - static $CookieDefaultPath = ''; - - static $CookieSecure = null; - - static $CookieSameSite = 'Strict'; - const /** * 30 days cookie @@ -60,14 +54,14 @@ class Utils public static function GetSessionToken(bool $generate = true) : ?string { - $sToken = static::GetCookie(self::SESSION_TOKEN); + $sToken = \SnappyMail\Cookies::get(self::SESSION_TOKEN); if (!$sToken) { if (!$generate) { return null; } \SnappyMail\Log::debug('TOKENS', 'New SESSION_TOKEN'); $sToken = \MailSo\Base\Utils::Sha1Rand(APP_SALT); - static::SetCookie(self::SESSION_TOKEN, $sToken); + \SnappyMail\Cookies::set(self::SESSION_TOKEN, $sToken); } return \sha1('Session'.APP_SALT.$sToken.'Token'.APP_SALT); } @@ -79,10 +73,10 @@ class Utils if ($oAccount) { return $oAccount->Hash(); } - $sToken = static::GetCookie(self::CONNECTION_TOKEN); + $sToken = \SnappyMail\Cookies::get(self::CONNECTION_TOKEN); if (!$sToken) { $sToken = \MailSo\Base\Utils::Sha1Rand(APP_SALT); - static::SetCookie(self::CONNECTION_TOKEN, $sToken, \time() + 3600 * 24 * 30); + \SnappyMail\Cookies::set(self::CONNECTION_TOKEN, $sToken, \time() + 3600 * 24 * 30); } return \sha1('Connection'.APP_SALT.$sToken.'Token'.APP_SALT); } @@ -94,9 +88,9 @@ class Utils public static function UpdateConnectionToken() : void { - $sToken = static::GetCookie(self::CONNECTION_TOKEN); + $sToken = \SnappyMail\Cookies::get(self::CONNECTION_TOKEN); if ($sToken) { - static::SetCookie(self::CONNECTION_TOKEN, $sToken, \time() + 3600 * 24 * 30); + \SnappyMail\Cookies::set(self::CONNECTION_TOKEN, $sToken, \time() + 3600 * 24 * 30); } } @@ -110,118 +104,6 @@ class Utils )); } - /** - * @param mixed $mDefault = null - */ - public static function GetCookie(string $sName) : ?string - { - if (isset($_COOKIE[$sName])) { - $aParts = []; - foreach (\array_keys($_COOKIE) as $sCookieName) { - if (\strtok($sCookieName, '~') === $sName) { - $aParts[$sCookieName] = $_COOKIE[$sCookieName]; - } - } - \ksort($aParts); - return \implode('', $aParts); - } - return null; - } - - public static function GetSecureCookie(string $sName) - { - return isset($_COOKIE[$sName]) - ? \SnappyMail\Crypt::DecryptFromJSON(\MailSo\Base\Utils::UrlSafeBase64Decode(static::GetCookie($sName))) - : null; - } - - private static function _SetCookie(string $sName, string $sValue, int $iExpire, bool $httponly = true) - { - $sPath = static::$CookieDefaultPath; - $sPath = $sPath && \strlen($sPath) ? $sPath : '/'; -/* - if (\strlen($sValue) > 4000 - \strlen($sPath . $sName)) { - throw new \Exception("Cookie '{$sName}' value too long"); - } -*/ - if (\strlen($sValue)) { - $_COOKIE[$sName] = $sValue; - } else { - if (!isset($_COOKIE[$sName])) { - return; - } - unset($_COOKIE[$sName]); - $iExpire = \time() - 3600 * 24 * 30; - } - - // Cookie "$sName" has been rejected because it is already expired. - // Happens when \setcookie() sends multiple with the same name (and one is deleted) - // So when previously set, we must delete all 'Set-Cookie' headers and start over - $cookies = []; - $cookie_remove = false; - foreach (\headers_list() as $header) { - if (\preg_match("/Set-Cookie:([^=]+)=/i", $header, $match)) { - if (\trim($match[1]) == $sName) { - $cookie_remove = true; - } else { - $cookies[] = $header; - } - } - } - if ($cookie_remove) { - \header_remove('Set-Cookie'); - foreach ($cookies as $cookie) { - \header($cookie); - } - } - - \setcookie($sName, $sValue, array( - 'expires' => $iExpire, - 'path' => $sPath, -// 'domain' => null, - 'secure' => static::$CookieSecure, - 'httponly' => $httponly, - 'samesite' => static::$CookieSameSite - )); - } - - /** - * Firefox: Cookie "$sName" has been rejected because it is already expired. - * \header_remove("set-cookie: {$sName}"); - */ - public static function SetCookie(string $sName, string $sValue, int $iExpire = 0, bool $httponly = true) - { - $sPath = static::$CookieDefaultPath; - $sPath = $sPath && \strlen($sPath) ? $sPath : '/'; - // https://github.com/the-djmaze/snappymail/issues/451 - // The 4K browser limit is for the entire cookie, including name, value, expiry date etc. - $iMaxSize = 4000 - \strlen($sPath . $sName); -/* - if ($iMaxSize < \strlen($sValue)) { - throw new \Exception("Cookie '{$sName}' value too long"); - } -*/ - // Set the new 4K split cookie - foreach (\str_split($sValue, $iMaxSize) as $i => $sPart) { - $sCookieName = $i ? "{$sName}~{$i}" : $sName; - \SnappyMail\Log::debug('COOKIE', "set {$sCookieName}"); - static::_SetCookie($sCookieName, $sPart, $iExpire); - } - // Delete unused old 4K split cookie parts - foreach (\array_keys($_COOKIE) as $sCookieName) { - $aSplit = \explode('~', $sCookieName); - if (isset($aSplit[1]) && $aSplit[0] == $sName && $aSplit[1] > $i) { - \SnappyMail\Log::debug('COOKIE', "unset {$sCookieName}"); - static::_SetCookie($sCookieName, '', 0); - } - } - } - - public static function ClearCookie(string $sName) - { - static::_SetCookie($sName, '', 0); - } - public static function UrlEncode(string $sV, bool $bEncode = false) : string { return $bEncode ? \urlencode($sV) : $sV; diff --git a/snappymail/v/0.0.0/app/libraries/snappymail/cookies.php b/snappymail/v/0.0.0/app/libraries/snappymail/cookies.php new file mode 100644 index 000000000..9c670239e --- /dev/null +++ b/snappymail/v/0.0.0/app/libraries/snappymail/cookies.php @@ -0,0 +1,138 @@ +Get('labs', 'cookie_default_path', ''); + static::$SameSite = $oConfig->Get('security', 'cookie_samesite', 'Strict'); + static::$Secure = isset($_SERVER['HTTPS']) + || 'None' == static::$SameSite + || !!$oConfig->Get('labs', 'cookie_default_secure', false); + $bOne = true; + } + return $bOne; + } + + public static function get(string $sName) : ?string + { + if (isset($_COOKIE[$sName])) { + $aParts = []; + foreach (\array_keys($_COOKIE) as $sCookieName) { + if (\strtok($sCookieName, '~') === $sName) { + $aParts[$sCookieName] = $_COOKIE[$sCookieName]; + } + } + \ksort($aParts); + return \implode('', $aParts); + } + return null; + } + + public static function getSecure(string $sName) + { + return isset($_COOKIE[$sName]) + ? Crypt::DecryptFromJSON(\MailSo\Base\Utils::UrlSafeBase64Decode(static::get($sName))) + : null; + } + + private static function _set(string $sName, string $sValue, int $iExpire, bool $httponly = true) : bool + { + $sPath = static::$DefaultPath; + $sPath = $sPath && \strlen($sPath) ? $sPath : '/'; +/* + if (\strlen($sValue) > 4000 - \strlen($sPath . $sName)) { + throw new \Exception("Cookie '{$sName}' value too long"); + } +*/ + if (\strlen($sValue)) { + $_COOKIE[$sName] = $sValue; + } else { + if (!isset($_COOKIE[$sName])) { + return true; + } + unset($_COOKIE[$sName]); + $iExpire = \time() - 3600 * 24 * 30; + } + + // Cookie "$sName" has been rejected because it is already expired. + // Happens when \setcookie() sends multiple with the same name (and one is deleted) + // So when previously set, we must delete all 'Set-Cookie' headers and start over + $cookies = []; + $cookie_remove = false; + foreach (\headers_list() as $header) { + if (\preg_match("/Set-Cookie:([^=]+)=/i", $header, $match)) { + if (\trim($match[1]) == $sName) { + $cookie_remove = true; + } else { + $cookies[] = $header; + } + } + } + if ($cookie_remove) { + \header_remove('Set-Cookie'); + foreach ($cookies as $cookie) { + \header($cookie); + } + } + + return \setcookie($sName, $sValue, array( + 'expires' => $iExpire, + 'path' => $sPath, +// 'domain' => null, + 'secure' => static::$Secure, + 'httponly' => $httponly, + 'samesite' => static::$SameSite + )); + } + + /** + * Firefox: Cookie "$sName" has been rejected because it is already expired. + * \header_remove("set-cookie: {$sName}"); + */ + public static function set(string $sName, string $sValue, int $iExpire = 0, bool $httponly = true) : void + { + static::init(); + $sPath = static::$DefaultPath; + $sPath = $sPath && \strlen($sPath) ? $sPath : '/'; + // https://github.com/the-djmaze/snappymail/issues/451 + // The 4K browser limit is for the entire cookie, including name, value, expiry date etc. + $iMaxSize = 4000 - \strlen($sPath . $sName); +/* + if ($iMaxSize < \strlen($sValue)) { + throw new \Exception("Cookie '{$sName}' value too long"); + } +*/ + // Set the new 4K split cookie + foreach (\str_split($sValue, $iMaxSize) as $i => $sPart) { + $sCookieName = $i ? "{$sName}~{$i}" : $sName; + Log::debug('COOKIE', "set {$sCookieName}"); + static::_set($sCookieName, $sPart, $iExpire); + } + // Delete unused old 4K split cookie parts + foreach (\array_keys($_COOKIE) as $sCookieName) { + $aSplit = \explode('~', $sCookieName); + if (isset($aSplit[1]) && $aSplit[0] == $sName && $aSplit[1] > $i) { + Log::debug('COOKIE', "unset {$sCookieName}"); + static::_set($sCookieName, '', 0); + } + } + } + + public static function clear(string $sName) : void + { + static::init(); + static::_set($sName, '', 0); + } +} diff --git a/snappymail/v/0.0.0/include.php b/snappymail/v/0.0.0/include.php index 50b03cce2..4b89e6ec7 100644 --- a/snappymail/v/0.0.0/include.php +++ b/snappymail/v/0.0.0/include.php @@ -165,11 +165,7 @@ if (!empty($_ENV['CPANEL']) && !is_dir(APP_PLUGINS_PATH.'login-remote')) { require __DIR__ . '/cpanel.php'; } -if (class_exists('RainLoop\\Api')) { - RainLoop\Api::Handle(); - // NextCloud/OwnCloud? - if (empty($_ENV['SNAPPYMAIL_INCLUDE_AS_API'])) { - RainLoop\Service::Handle(); - exit(0); - } +if (class_exists('RainLoop\\Api') && empty($_ENV['SNAPPYMAIL_INCLUDE_AS_API'])) { + RainLoop\Service::Handle(); + exit; }