From b8593b1bf2bb23d1946dff96450092b8bde34453 Mon Sep 17 00:00:00 2001 From: El RIDO Date: Thu, 10 Nov 2022 20:36:15 +0100 Subject: [PATCH] use a glob iterator to stream through as many matches as needed --- lib/Data/Filesystem.php | 148 +++++++++------------------------------- 1 file changed, 34 insertions(+), 114 deletions(-) diff --git a/lib/Data/Filesystem.php b/lib/Data/Filesystem.php index 966506fd..1f00b577 100644 --- a/lib/Data/Filesystem.php +++ b/lib/Data/Filesystem.php @@ -340,63 +340,25 @@ class Filesystem extends AbstractData */ protected function _getExpiredPastes($batchsize) { - $pastes = array(); - $firstLevel = array_filter( - scandir($this->_path), - 'PrivateBin\Data\Filesystem::_isFirstLevelDir' - ); - if (count($firstLevel) > 0) { - // try at most 10 times the $batchsize pastes before giving up - for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) { - $firstKey = array_rand($firstLevel); - $secondLevel = array_filter( - scandir($this->_path . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]), - 'PrivateBin\Data\Filesystem::_isSecondLevelDir' - ); - - // skip this folder in the next checks if it is empty - if (count($secondLevel) == 0) { - unset($firstLevel[$firstKey]); - continue; - } - - $secondKey = array_rand($secondLevel); - $path = $this->_path . DIRECTORY_SEPARATOR . - $firstLevel[$firstKey] . DIRECTORY_SEPARATOR . - $secondLevel[$secondKey]; - if (!is_dir($path)) { - continue; - } - $thirdLevel = array_filter( - array_map( - function ($filename) { - return strlen($filename) >= 20 ? - substr($filename, 0, -4) : - $filename; - }, - scandir($path) - ), - 'PrivateBin\\Model\\Paste::isValidId' - ); - if (count($thirdLevel) == 0) { - continue; - } - $thirdKey = array_rand($thirdLevel); - $pasteid = $thirdLevel[$thirdKey]; - if (in_array($pasteid, $pastes)) { - continue; - } - - if ($this->exists($pasteid)) { - $data = $this->read($pasteid); - if ( - array_key_exists('expire_date', $data['meta']) && - $data['meta']['expire_date'] < time() - ) { - $pastes[] = $pasteid; - if (count($pastes) >= $batchsize) { - break; - } + $pastes = array(); + $files = $this->_getPasteIterator(); + $count = 0; + $time = time(); + foreach ($files as $file) { + if ($file->isDir()) { + continue; + } + $pasteid = $file->getBasename('.php'); + if ($this->exists($pasteid)) { + $data = $this->read($pasteid); + if ( + array_key_exists('expire_date', $data['meta']) && + $data['meta']['expire_date'] < $time + ) { + $pastes[] = $pasteid; + ++$count; + if ($count >= $batchsize) { + break; } } } @@ -409,45 +371,11 @@ class Filesystem extends AbstractData */ public function getAllPastes() { - $pastes = array(); - $firstLevel = array_filter( - scandir($this->_path), - 'PrivateBin\Data\Filesystem::_isFirstLevelDir' - ); - if (count($firstLevel) > 0) { - foreach ($firstLevel as $firstKey) { - $secondLevel = array_filter( - scandir($this->_path . DIRECTORY_SEPARATOR . $firstKey), - 'PrivateBin\Data\Filesystem::_isSecondLevelDir' - ); - - // skip this folder - if (count($secondLevel) == 0) { - continue; - } - - foreach ($secondLevel as $secondKey) { - $path = $this->_path . DIRECTORY_SEPARATOR . $firstKey . - DIRECTORY_SEPARATOR . $secondKey; - if (!is_dir($path)) { - continue; - } - $thirdLevel = array_filter( - array_map( - function ($filename) { - return strlen($filename) >= 20 ? - substr($filename, 0, -4) : - $filename; - }, - scandir($path) - ), - 'PrivateBin\\Model\\Paste::isValidId' - ); - if (count($thirdLevel) == 0) { - continue; - } - $pastes += $thirdLevel; - } + $pastes = array(); + $files = $this->_getPasteIterator(); + foreach ($files as $file) { + if ($file->isFile()) { + $pastes[] = $file->getBasename('.php'); } } return $pastes; @@ -490,28 +418,20 @@ class Filesystem extends AbstractData } /** - * Check that the given element is a valid first level directory. + * Get an iterator matching paste files. * * @access private - * @param string $element - * @return bool + * @return \GlobIterator */ - private function _isFirstLevelDir($element) + private function _getPasteIterator() { - return $this->_isSecondLevelDir($element) && - is_dir($this->_path . DIRECTORY_SEPARATOR . $element); - } - - /** - * Check that the given element is a valid second level directory. - * - * @access private - * @param string $element - * @return bool - */ - private function _isSecondLevelDir($element) - { - return (bool) preg_match('/^[a-f0-9]{2}$/', $element); + return new \GlobIterator($this->_path . DIRECTORY_SEPARATOR . + '[a-f0-9][a-f0-9]' . DIRECTORY_SEPARATOR . + '[a-f0-9][a-f0-9]' . DIRECTORY_SEPARATOR . + '[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]' . + '[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]*'); + // need to return both files with and without .php suffix, so they can + // be hardened by _prependRename(), which is hooked into exists() } /**