diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Files/FileStorage.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Files/FileStorage.php index e9781414b..f73cc3bce 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Files/FileStorage.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Files/FileStorage.php @@ -55,16 +55,6 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles $bCreate = !!\preg_match('/[wac]/', $sOpenMode); $sFileName = $this->generateFullFileName($oAccount, $sKey, $bCreate); - if (!\file_exists($sFileName)) { - $sOldFileName = $this->generateFullFileNameOld($oAccount, $sKey); - if (\file_exists($sOldFileName) - && ( - (!\is_dir(\dirname($sOldFileName)) && !\mkdir(\dirname($sOldFileName), 0700, true)) - || !\rename($sOldFileName, $sFileName) - )) { - $sFileName = $sOldFileName; - } - } if ($bCreate || \file_exists($sFileName)) { $mResult = \fopen($sFileName, $sOpenMode); @@ -81,18 +71,12 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles public function GetFileName(\RainLoop\Model\Account $oAccount, string $sKey) /*: string|false*/ { $sFileName = $this->generateFullFileName($oAccount, $sKey); - if (!\file_exists($sFileName)) { - $sFileName = $this->generateFullFileNameOld($oAccount, $sKey); - } return \file_exists($sFileName) ? $sFileName : false; } public function Clear(\RainLoop\Model\Account $oAccount, string $sKey) : bool { $sFileName = $this->generateFullFileName($oAccount, $sKey); - if (!\file_exists($sFileName)) { - $sFileName = $this->generateFullFileNameOld($oAccount, $sKey); - } if (\file_exists($sFileName)) { if (isset($this->aResources[$sFileName]) && \is_resource($this->aResources[$sFileName])) { \fclose($this->aResources[$sFileName]); @@ -105,16 +89,12 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles public function FileSize(\RainLoop\Model\Account $oAccount, string $sKey) /*: int|false*/ { $sFileName = $this->generateFullFileName($oAccount, $sKey); - if (!\file_exists($sFileName)) { - $sFileName = $this->generateFullFileNameOld($oAccount, $sKey); - } return \file_exists($sFileName) ? \filesize($sFileName) : false; } public function FileExists(\RainLoop\Model\Account $oAccount, string $sKey) : bool { - return \file_exists($this->generateFullFileName($oAccount, $sKey)) - || \file_exists($this->generateFullFileNameOld($oAccount, $sKey)); + return \file_exists($this->generateFullFileName($oAccount, $sKey)); } public function GC(int $iTimeToClearInHours = 24) : bool @@ -180,39 +160,4 @@ class FileStorage implements \RainLoop\Providers\Files\IFiles return $sFilePath; } - private function generateFullFileNameOld(\RainLoop\Model\Account $oAccount, string $sKey, bool $bMkDir = false) : string - { - $sEmail = $sSubEmail = ''; - if ($oAccount instanceof \RainLoop\Model\Account) - { - $sEmail = \preg_replace('/[^a-z0-9\-\.@]+/', '_', $oAccount->ParentEmailHelper()); - if ($oAccount->IsAdditionalAccount()) - { - $sSubEmail = \preg_replace('/[^a-z0-9\-\.@]+/', '_', $oAccount->Email()); - } - } - - if (empty($sEmail)) - { - $sEmail = '__unknown__'; - } - - $sKeyPath = \sha1($sKey); - $sKeyPath = \substr($sKeyPath, 0, 2).'/'.\substr($sKeyPath, 2, 2).'/'.$sKeyPath; - - $sFilePath = $this->sDataPath.'/'. - \str_pad(\rtrim(\substr($sEmail, 0, 2), '@'), 2, '_').'/'.$sEmail.'/'. - (0 < \strlen($sSubEmail) ? $sSubEmail.'/' : ''). - $sKeyPath; - - if ($bMkDir && !empty($sFilePath) && !\is_dir(\dirname($sFilePath))) - { - if (!\mkdir(\dirname($sFilePath), 0700, true)) - { - throw new \RainLoop\Exceptions\Exception('Can\'t make storage directory "'.$sFilePath.'"'); - } - } - - return $sFilePath; - } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php index 9496f7842..2a08367d3 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FileStorage.php @@ -49,13 +49,6 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); if ($sFileName && \file_exists($sFileName)) { $mValue = \file_get_contents($sFileName); - } else { - $sFileName = $this->generateFileNameOld($oAccount, $iStorageType, $sKey); - if ($sFileName && \file_exists($sFileName)) { - $mValue = \file_get_contents($sFileName); - $this->Put($oAccount, $iStorageType, $sKey, $mValue); - \unlink($sFileName); - } } return false === $mValue ? $mDefault : $mValue; @@ -70,11 +63,6 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage $sFileName = $this->generateFileName($oAccount, $iStorageType, $sKey); if ($sFileName && \file_exists($sFileName)) { $mResult = \unlink($sFileName); - } else { - $sFileName = $this->generateFileNameOld($oAccount, $iStorageType, $sKey); - if ($sFileName && \file_exists($sFileName)) { - $mResult = \unlink($sFileName); - } } return $mResult; @@ -89,17 +77,6 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage if ($sPath && \is_dir($sPath)) { \MailSo\Base\Utils::RecRmDir($sPath); } - - $sPath = $this->generateFileNameOld($oAccount, StorageType::USER, '', false, true); - if ($sPath && \is_dir($sPath)) { - \MailSo\Base\Utils::RecRmDir($sPath); - } - - $sPath = $this->generateFileNameOld($oAccount, StorageType::CONFIG, '', false, true); - if ($sPath && \is_dir($sPath)) { - \MailSo\Base\Utils::RecRmDir($sPath); - } - return true; } @@ -147,6 +124,9 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage if (empty($sEmail)) { return ''; } + if (\is_dir("{$this->sDataPath}/cfg")) { + FixFileStorage::FixIt($this->sDataPath); + } $aEmail = \explode('@', $sEmail ?: 'nobody@unknown.tld'); $sDomain = \trim(1 < \count($aEmail) ? \array_pop($aEmail) : ''); $sFilePath = $this->sDataPath @@ -175,74 +155,6 @@ class FileStorage implements \RainLoop\Providers\Storage\IStorage return $sFilePath; } - /** - * Old RainLoop structure - */ - private function generateFileNameOld($mAccount, int $iStorageType, string $sKey, bool $bMkDir = false, bool $bForDeleteAction = false) : string - { - if (null === $mAccount) - { - $iStorageType = StorageType::NOBODY; - } - - $sEmail = $sSubEmail = ''; - if ($mAccount instanceof \RainLoop\Model\Account) - { - $sEmail = $mAccount->ParentEmailHelper(); - if ($this->bLocal && $mAccount->IsAdditionalAccount() && !$bForDeleteAction) - { - $sSubEmail = $mAccount->Email(); - } - } - - if (\is_string($mAccount) && empty($sEmail)) - { - $sEmail = $mAccount; - } - - $sEmail = \preg_replace('/[^a-z0-9\-\.@]+/i', '_', $sEmail); - $sSubEmail = \preg_replace('/[^a-z0-9\-\.@]+/i', '_', $sSubEmail); - - $sTypePath = $sKeyPath = ''; - switch ($iStorageType) - { - default: - case StorageType::USER: - case StorageType::NOBODY: - $sTypePath = 'data'; - $sKeyPath = \md5($sKey); - $sKeyPath = \substr($sKeyPath, 0, 2).'/'.$sKeyPath; - break; - case StorageType::CONFIG: - $sTypePath = 'cfg'; - $sKeyPath = \preg_replace('/[_]+/', '_', \preg_replace('/[^a-zA-Z0-9\/]/', '_', $sKey)); - break; - } - - $sFilePath = ''; - if (StorageType::NOBODY === $iStorageType) - { - $sFilePath = $this->sDataPath.'/'.$sTypePath.'/__nobody__/'.$sKeyPath; - } - else if (!empty($sEmail)) - { - $sFilePath = $this->sDataPath.'/'.$sTypePath.'/'. - \str_pad(\rtrim(\substr($sEmail, 0, 2), '@'), 2, '_').'/'.$sEmail.'/'. - (\strlen($sSubEmail) ? $sSubEmail.'/' : ''). - ($bForDeleteAction ? '' : $sKeyPath); - } - - if ($bMkDir && !$bForDeleteAction && !empty($sFilePath) && !\is_dir(\dirname($sFilePath))) - { - if (!\mkdir(\dirname($sFilePath), 0700, true)) - { - throw new \RainLoop\Exceptions\Exception('Can\'t make storage directory "'.$sFilePath.'"'); - } - } - - return $sFilePath; - } - public function SetLogger(?\MailSo\Log\Logger $oLogger) { $this->oLogger = $oLogger; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FixFileStorage.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FixFileStorage.php new file mode 100644 index 000000000..9edf15120 --- /dev/null +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Providers/Storage/FixFileStorage.php @@ -0,0 +1,47 @@ ++\\[\\]/&\\s\\pC]#su', '-', $filename); + } + + public static function FixIt(string $sDataPath) + { + // /cfg/ex/example@example.com + foreach (\glob("{$sDataPath}/cfg/*", GLOB_ONLYDIR) as $sOldDir) { + foreach (\glob("{$sOldDir}/*", GLOB_ONLYDIR) as $sDomainDir) { + $aEmail = \explode('@', \basename($sDomainDir)); + $sDomain = \trim(1 < \count($aEmail) ? \array_pop($aEmail) : ''); + $sNewDir = $sDataPath + .'/'.static::fixName($sDomain ?: 'unknown.tld') + .'/'.static::fixName(\implode('@', $aEmail) ?: '.unknown'); + if (\is_dir($sNewDir) || \mkdir($sNewDir, 0700, true)) { + foreach (\glob("{$sDomainDir}/*") as $sItem) { + $sName = \basename($sItem); + if ('sign_me' === $sName) { + // Security issue + // https://github.com/RainLoop/rainloop-webmail/issues/2133 + \unlink($sItem); + } else { + \rename($sItem, "{$sNewDir}/{$sName}"); + } + } + \MailSo\Base\Utils::RecRmDir($sDomainDir); + } + } + } + \MailSo\Base\Utils::RecRmDir("{$sDataPath}/cfg"); + \MailSo\Base\Utils::RecRmDir("{$sDataPath}/data"); + \MailSo\Base\Utils::RecRmDir("{$sDataPath}/files"); + } + +}