File: /home/infowars/askalexjones.com/wp-content/plugins/backup/src/JetBackup/Destination/Tree.php
<?php
namespace JetBackup\Destination;
use JetBackup\Exception\DestinationException;
use JetBackup\Exception\IOVanishedException;
use JetBackup\Factory;
use JetBackup\JetBackup;
use JetBackup\Queue\QueueItem;
use SleekDB\Exceptions\InvalidArgumentException;
use SleekDB\Exceptions\IOException;
if (!defined( '__JETBACKUP__')) die('Direct access is not allowed');
class Tree {
const TREE_FILE = '%s' . JetBackup::SEP . '%d_tree.ini';
private Destination $_destination;
private QueueItem $_queue_item;
private string $_source;
private string $_tree_file;
/**
* @param Destination $destination
* @param QueueItem $item
* @param string $source
*/
public function __construct(Destination $destination, QueueItem $item, string $source) {
$this->_destination = $destination;
$this->_queue_item = $item;
$this->_source = $source;
$this->_tree_file = sprintf(self::TREE_FILE, $source, $destination->getId());
}
/**
* @return void
* @throws DestinationException
* @throws IOVanishedException
* @throws IOException
* @throws InvalidArgumentException
*/
private function _build():void {
if(file_exists($this->_tree_file)) return;
$excludes = [
'*' . JetBackup::SEP . '.htaccess',
'*' . JetBackup::SEP . 'web.config',
'*' . JetBackup::SEP . 'index.html',
JetBackup::SEP . 'tree.php_done',
JetBackup::SEP . '*_tree.ini',
JetBackup::SEP . 'tmp',
JetBackup::SEP . 'tmp' . JetBackup::SEP . '*',
JetBackup::SEP . 'logs',
JetBackup::SEP . 'logs' . JetBackup::SEP . '*',
JetBackup::SEP . basename($this->_tree_file),
];
$fd = fopen($this->_tree_file, 'w');
if(!$fd) throw new DestinationException("Cannot open tree file: $this->_tree_file");
// We must build the tree with directories first, we must create the directory before uploading files to that directory
$scan = new ScanDirIterator($this->_source);
$total_size = 0;
while($entry = $scan->next()) {
$filename = substr($entry->getFullPath(), strlen($this->_source));
foreach($excludes as $exclude) if(fnmatch($exclude, $filename)) continue 2;
fwrite($fd, $filename . PHP_EOL);
if(!$entry->isDir()) $total_size += $entry->getSize();
}
fclose($fd);
$progress = $this->_queue_item->getProgress();
$progress->setTotalSubItems($total_size);
$progress->setCurrentSubItem(0);
$this->_queue_item->save();
}
/**
* @param callable $callback
*
* @return void
* @throws DestinationException
* @throws IOVanishedException
*/
public function process(callable $callback) {
$this->_build();
$fp = fopen($this->_tree_file, 'r+');
if (!$fp) throw new DestinationException("Cannot open tree file: $this->_tree_file");
fseek($fp, 0, SEEK_END);
$fileSize = ftell($fp); // Get the initial size of the file
$position = $fileSize;
$buffer = '';
$_chunk_size = $this->_destination->getChunkSizeBytes() ?: Factory::getSettingsPerformance()->getReadChunkSizeBytes();
while ($position > 0) {
$readSize = min($position, $_chunk_size);
$position -= $readSize; // Adjust position for the next read
fseek($fp, $position);
$chunk = fread($fp, $readSize) . $buffer; // Prepend previously buffered data
while (($eolPos = strrpos($chunk, PHP_EOL)) !== false) {
$lineStartPos = $eolPos + strlen(PHP_EOL);
$line = substr($chunk, $lineStartPos);
$chunk = substr($chunk, 0, $eolPos);
if (!empty($line)/* && basename($line) != basename(self::TREE_FILE)*/) call_user_func($callback, $line);
// Update the position for truncating the file
$newSize = $position + $eolPos + strlen(PHP_EOL);
ftruncate($fp, $newSize);
fflush($fp); // Ensure changes are written
fseek($fp, $newSize); // Set the pointer for the next operation
}
$buffer = $chunk; // Save any remaining data not followed by PHP_EOL
if ($position === 0 && !empty($buffer)) {
// If there's buffered data left when we reach the start of the file, process it
call_user_func($callback, $buffer);
ftruncate($fp, 0); // Truncate the file if the entire content has been processed
}
}
fclose($fp);
// At this point, if tree file is empty we know we finished with the current destination
// tree upload, we need this if using multiple uploads to multiple destinations.
// Do not delete tree file here
//unlink($_tree_file);
}
}