204 lines
5.1 KiB
PHP
204 lines
5.1 KiB
PHP
<?php
|
|
|
|
/**
|
|
* archive path file list object
|
|
*
|
|
* Standard: PSR-2
|
|
*
|
|
* @link http://www.php-fig.org/psr/psr-2
|
|
*
|
|
* @package name
|
|
* @copyright (c) 2019, Snapcreek LLC
|
|
* @license https://opensource.org/licenses/GPL-3.0 GNU Public License
|
|
*/
|
|
|
|
defined('ABSPATH') || defined('DUPXABSPATH') || exit;
|
|
|
|
use Duplicator\Libs\Snap\SnapIO;
|
|
use Duplicator\Libs\Snap\SnapJson;
|
|
|
|
class DUP_Archive_File_List
|
|
{
|
|
protected $path = null;
|
|
protected $handle = null;
|
|
protected $cache = null;
|
|
|
|
public function __construct($path)
|
|
{
|
|
if (empty($path)) {
|
|
throw new Exception('path can\'t be empty');
|
|
}
|
|
|
|
$this->path = SnapIO::safePath($path);
|
|
}
|
|
|
|
public function __destruct()
|
|
{
|
|
$this->close();
|
|
}
|
|
|
|
public function getPath()
|
|
{
|
|
return $this->path;
|
|
}
|
|
|
|
public function open($truncate = false)
|
|
{
|
|
if (is_null($this->handle)) {
|
|
if (($this->handle = fopen($this->path, 'a+')) === false) {
|
|
DUP_Log::trace('Can\'t open ' . $this->path);
|
|
$this->handle = null;
|
|
return false;
|
|
}
|
|
}
|
|
if ($truncate) {
|
|
$this->emptyFile();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function emptyFile()
|
|
{
|
|
if (!$this->open(false)) {
|
|
return false;
|
|
}
|
|
if (($res = ftruncate($this->handle, 0)) === false) {
|
|
DUP_Log::trace('Can\'t truncate file ' . $this->path);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function close()
|
|
{
|
|
if (!is_null($this->handle)) {
|
|
if (($res = @fclose($this->handle)) === false) {
|
|
DUP_Log::trace('Can\'t close ' . $this->path);
|
|
return false;
|
|
}
|
|
$this->handle = null;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function addEntry($path, $size, $nodes)
|
|
{
|
|
|
|
if (is_null($this->handle)) { // check to generate less overhead
|
|
if (!$this->open()) {
|
|
return false;
|
|
}
|
|
}
|
|
$entry = array('p' => $path, 's' => $size, 'n' => $nodes);
|
|
fwrite($this->handle, SnapJson::jsonEncode($entry) . "\n");
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param bool $pathOnly if true return only payth
|
|
*
|
|
* @return boolean|array|string return false if is end of filer.
|
|
*/
|
|
public function getEntry($pathOnly = false)
|
|
{
|
|
if (is_null($this->handle)) { // check to generate less overhead
|
|
if (!$this->open()) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (($json = fgets($this->handle, 4196)) === false) {
|
|
// end of file return false
|
|
return false;
|
|
}
|
|
|
|
$result = json_decode($json, true);
|
|
if ($pathOnly) {
|
|
return $result['p'];
|
|
} else {
|
|
return $result;
|
|
}
|
|
}
|
|
|
|
protected function cleanCache()
|
|
{
|
|
$this->cache = null;
|
|
return true;
|
|
}
|
|
|
|
protected function loadCache($refreshCache = false)
|
|
{
|
|
if ($refreshCache || is_null($this->cache)) {
|
|
if (!$this->open()) {
|
|
return false;
|
|
}
|
|
$this->cache = array();
|
|
if (@fseek($this->handle, 0) === -1) {
|
|
DUP_Log::trace('Can\'t seek at 0 pos for file ' . $this->path);
|
|
$this->cleanCache();
|
|
return false;
|
|
}
|
|
while (($entry = $this->getEntry()) !== false) {
|
|
$this->cache[$entry['p']] = $entry;
|
|
}
|
|
if (!feof($this->handle)) {
|
|
DUP_Log::trace('Error: unexpected fgets() fail', '', false);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function getEntryFromPath($path, $refreshCache = false)
|
|
{
|
|
if (!$this->loadCache($refreshCache)) {
|
|
return false;
|
|
}
|
|
|
|
if (array_key_exists($path, $this->cache)) {
|
|
return $this->cache[$path];
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function getEntriesFormPath($path, $refreshCache = false)
|
|
{
|
|
if (!$this->loadCache($refreshCache)) {
|
|
return false;
|
|
}
|
|
|
|
if (array_key_exists($path, $this->cache)) {
|
|
$result = array();
|
|
foreach ($this->cache as $current => $entry) {
|
|
if (preg_match('/^' . preg_quote($path, '/') . '\/[^\/]+$/', $current)) {
|
|
$result[] = $entry;
|
|
}
|
|
}
|
|
return $result;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function getArrayPaths($pathPrefix = '')
|
|
{
|
|
if (!$this->open()) {
|
|
return false;
|
|
}
|
|
|
|
$result = array();
|
|
if (@fseek($this->handle, 0) === -1) {
|
|
DUP_Log::trace('Can\'t seek at 0 pos for file ' . $this->path);
|
|
return false;
|
|
}
|
|
$safePrefix = SnapIO::safePathUntrailingslashit($pathPrefix);
|
|
while (($path = $this->getEntry(true)) !== false) {
|
|
$result[] = $safePrefix . '/' . $path;
|
|
}
|
|
if (!feof($this->handle)) {
|
|
DUP_Log::trace('Error: unexpected fgets() fail', '', false);
|
|
}
|
|
return $result;
|
|
}
|
|
}
|