use a glob iterator to stream through as many matches as needed

This commit is contained in:
El RIDO 2022-11-10 20:36:15 +01:00
parent b3699cae8f
commit b8593b1bf2
No known key found for this signature in database
GPG Key ID: 0F5C940A6BD81F92
1 changed files with 34 additions and 114 deletions

View File

@ -340,63 +340,25 @@ class Filesystem extends AbstractData
*/ */
protected function _getExpiredPastes($batchsize) protected function _getExpiredPastes($batchsize)
{ {
$pastes = array(); $pastes = array();
$firstLevel = array_filter( $files = $this->_getPasteIterator();
scandir($this->_path), $count = 0;
'PrivateBin\Data\Filesystem::_isFirstLevelDir' $time = time();
); foreach ($files as $file) {
if (count($firstLevel) > 0) { if ($file->isDir()) {
// try at most 10 times the $batchsize pastes before giving up continue;
for ($i = 0, $max = $batchsize * 10; $i < $max; ++$i) { }
$firstKey = array_rand($firstLevel); $pasteid = $file->getBasename('.php');
$secondLevel = array_filter( if ($this->exists($pasteid)) {
scandir($this->_path . DIRECTORY_SEPARATOR . $firstLevel[$firstKey]), $data = $this->read($pasteid);
'PrivateBin\Data\Filesystem::_isSecondLevelDir' if (
); array_key_exists('expire_date', $data['meta']) &&
$data['meta']['expire_date'] < $time
// skip this folder in the next checks if it is empty ) {
if (count($secondLevel) == 0) { $pastes[] = $pasteid;
unset($firstLevel[$firstKey]); ++$count;
continue; if ($count >= $batchsize) {
} break;
$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;
}
} }
} }
} }
@ -409,45 +371,11 @@ class Filesystem extends AbstractData
*/ */
public function getAllPastes() public function getAllPastes()
{ {
$pastes = array(); $pastes = array();
$firstLevel = array_filter( $files = $this->_getPasteIterator();
scandir($this->_path), foreach ($files as $file) {
'PrivateBin\Data\Filesystem::_isFirstLevelDir' if ($file->isFile()) {
); $pastes[] = $file->getBasename('.php');
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;
}
} }
} }
return $pastes; 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 * @access private
* @param string $element * @return \GlobIterator
* @return bool
*/ */
private function _isFirstLevelDir($element) private function _getPasteIterator()
{ {
return $this->_isSecondLevelDir($element) && return new \GlobIterator($this->_path . DIRECTORY_SEPARATOR .
is_dir($this->_path . DIRECTORY_SEPARATOR . $element); '[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]*');
* Check that the given element is a valid second level directory. // need to return both files with and without .php suffix, so they can
* // be hardened by _prependRename(), which is hooked into exists()
* @access private
* @param string $element
* @return bool
*/
private function _isSecondLevelDir($element)
{
return (bool) preg_match('/^[a-f0-9]{2}$/', $element);
} }
/** /**