File: /home/acnbijigo78q/public_html/wp-content/plugins/duplicator-pro/src/Ajax/ServicesStorage.php
<?php
/**
* @package Duplicator
* @copyright (c) 2022, Snap Creek LLC
*/
namespace Duplicator\Ajax;
use DUP_PRO_Log;
use DUP_PRO_Package;
use Duplicator\Controllers\SchedulePageController;
use Duplicator\Core\CapMng;
use Duplicator\Libs\Snap\SnapLog;
use Duplicator\Libs\Snap\SnapUtil;
use Duplicator\Models\Storages\AbstractStorageEntity;
use Duplicator\Models\Storages\StorageAuthInterface;
use Duplicator\Models\Storages\UnknownStorage;
use Duplicator\Package\AbstractPackage;
use Duplicator\Utils\Logging\ErrorHandler;
use Exception;
use Duplicator\Models\ScheduleEntity;
class ServicesStorage extends AbstractAjaxService
{
const STORAGE_BULK_DELETE = 1;
const STORAGE_GET_SCHEDULES = 5;
/**
* Init ajax calls
*
* @return void
*/
public function init(): void
{
$this->addAjaxCall("wp_ajax_duplicator_pro_storage_bulk_actions", "bulkActions");
$this->addAjaxCall('wp_ajax_duplicator_pro_get_storage_details', 'packageStoragesDetails');
$this->addAjaxCall("wp_ajax_duplicator_pro_storage_test", "testStorage");
$this->addAjaxCall("wp_ajax_duplicator_pro_auth_storage", "authorizeStorage");
$this->addAjaxCall("wp_ajax_duplicator_pro_revoke_storage", "revokeStorage");
}
/**
* Storage bulk actions handler
*
* @return void
* @throws \Exception
*/
public function bulkActions(): void
{
ErrorHandler::init();
check_ajax_referer('duplicator_pro_storage_bulk_actions', 'nonce');
$json = [
'success' => false,
'message' => '',
'schedules' => [],
];
$isValid = true;
$inputData = filter_input_array(INPUT_POST, [
'storage_ids' => [
'filter' => FILTER_VALIDATE_INT,
'flags' => FILTER_REQUIRE_ARRAY,
'options' => ['default' => false],
],
'perform' => [
'filter' => FILTER_VALIDATE_INT,
'flags' => FILTER_REQUIRE_SCALAR,
'options' => ['default' => false],
],
]);
$storageIDs = $inputData['storage_ids'];
$action = $inputData['perform'];
if (empty($storageIDs) || in_array(false, $storageIDs) || $action === false) {
$isValid = false;
}
try {
CapMng::can(CapMng::CAP_STORAGE);
if (!$isValid) {
throw new \Exception(__("Invalid Request.", 'duplicator-pro'));
}
foreach ($storageIDs as $id) {
switch ($action) {
case self::STORAGE_BULK_DELETE:
AbstractStorageEntity::deleteById($id);
break;
case self::STORAGE_GET_SCHEDULES:
foreach (ScheduleEntity::getSchedulesByStorageId($id) as $schedule) {
$json["schedules"][] = [
"id" => $schedule->getId(),
"name" => $schedule->name,
"hasOneStorage" => count($schedule->storage_ids) <= 1,
"editURL" => SchedulePageController::getInstance()->getEditUrl($schedule->getId()),
];
}
break;
default:
throw new \Exception("Invalid action.");
}
}
//SORT_REGULAR allows to do array_unique on multidimensional arrays
$json["schedules"] = array_unique($json["schedules"], SORT_REGULAR);
$json["success"] = true;
} catch (\Exception $ex) {
$json['message'] = $ex->getMessage();
}
die(json_encode($json));
}
/**
* Test storage connection
*
* @return void
*/
public function packageStoragesDetails(): void
{
AjaxWrapper::json(
[
self::class,
'packageStoragesDetailsCallback',
],
'duplicator_pro_get_storage_details',
SnapUtil::sanitizeTextInput(INPUT_POST, 'nonce'),
CapMng::CAP_CREATE
);
}
/**
* Hook ajax wp_ajax_duplicator_pro_get_storage_details
*
* @return array<string,mixed>
*/
public static function packageStoragesDetailsCallback(): array
{
$result = [
'success' => false,
'message' => '',
'logURL' => '',
'storage_providers' => [],
];
try {
if (($package_id = SnapUtil::sanitizeIntInput(INPUT_POST, 'package_id', -1)) < 0) {
throw new Exception(__("Invalid Request.", 'duplicator-pro'));
}
$package = DUP_PRO_Package::getById($package_id);
if ($package == false) {
throw new Exception(sprintf(__('Unknown Backup %1$d', 'duplicator-pro'), $package_id));
}
$providers = [];
foreach ($package->upload_infos as $upload_info) {
if ($upload_info->isDownloadFromRemote()) {
continue;
}
if (($storage = AbstractStorageEntity::getById($upload_info->getStorageId())) === false) {
continue;
}
$storageInfo = [];
$storageInfo["failed"] = $upload_info->isFailed();
$storageInfo["cancelled"] = $upload_info->isCancelled();
$storageInfo["infoHTML"] = $storage->renderRemoteLocationInfo(
$upload_info->isFailed(),
$upload_info->isCancelled(),
$upload_info->packageExists(),
false
);
// Newest storage upload infos will supercede earlier attempts to the same storage
$providers[$upload_info->getStorageId()] = $storageInfo;
}
$result['success'] = true;
$result['message'] = __('Retrieved storage information', 'duplicator-pro');
$result['logURL'] = $package->getLocalPackageFileURL(AbstractPackage::FILE_TYPE_LOG);
$result['storage_providers'] = $providers;
} catch (Exception $ex) {
$result['success'] = false;
$result['message'] = $ex->getMessage();
DUP_PRO_Log::traceError($ex->getMessage());
}
return $result;
}
/**
* Test storage connection
*
* @return void
*/
public function testStorage(): void
{
AjaxWrapper::json(
[
self::class,
'testStorageCallback',
],
'duplicator_pro_storage_test',
SnapUtil::sanitizeTextInput(INPUT_POST, 'nonce'),
CapMng::CAP_STORAGE
);
}
/**
* Test storage callback
*
* @return array<string,mixed>
*/
public static function testStorageCallback(): array
{
$result = [
'success' => false,
'message' => '',
'status_msgs' => '',
];
$storageId = SnapUtil::sanitizeIntInput(SnapUtil::INPUT_REQUEST, 'storage_id', -1);
if ($storageId < 0 || ($storage = AbstractStorageEntity::getById($storageId)) === false) {
$result['message'] = __('Invalid storage', 'duplicator-pro');
$result['status_msgs'] = __('Invalid storage', 'duplicator-pro');
} else {
$result['success'] = $storage->test($result['message']);
$result['status_msgs'] = $storage->getTestLog();
}
return $result;
}
/**
* Authorize storage
*
* @return void
*/
public function authorizeStorage(): void
{
AjaxWrapper::json(
[
self::class,
'authorizeStorageCallback',
],
'duplicator_pro_auth_storage',
SnapUtil::sanitizeTextInput(INPUT_POST, 'nonce'),
CapMng::CAP_STORAGE
);
}
/**
* Authorize storage callback
*
* @return mixed[]
*/
public static function authorizeStorageCallback(): array
{
$result = [
'success' => false,
'storage_id' => -1,
'message' => '',
];
$storageId = SnapUtil::sanitizeIntInput(SnapUtil::INPUT_REQUEST, 'storage_id', -1);
if ($storageId < 0) {
// New storage
$intMin = (PHP_INT_MAX * -1 - 1); // On php 5.6 PHP_INT_MIN don't exists
$storageType = SnapUtil::sanitizeIntInput(SnapUtil::INPUT_REQUEST, 'storage_type', $intMin);
$storage = AbstractStorageEntity::getNewStorageByType($storageType);
if ($storage instanceof UnknownStorage) {
$result['message'] = __('Invalid storage type', 'duplicator-pro');
return $result;
}
} elseif (($storage = AbstractStorageEntity::getById($storageId)) === false) {
$result['message'] = __('Invalid storage', 'duplicator-pro');
return $result;
} else {
$result['storage_id'] = $storage->getId();
}
DUP_PRO_Log::trace("Auth storage: " . $storage->getName() . "[ID:" . $storage->getId() . "] type: " . $storage->getStypeName());
if (!$storage instanceof StorageAuthInterface) {
$result['message'] = __('Storage does not support authorization', 'duplicator-pro');
return $result;
}
if ($storage->authorizeFromRequest($result['message'])) {
if (($result['success'] = $storage->save()) == false) {
$result['message'] = __('Failed to update storage', 'duplicator-pro');
}
}
// Make suge storage id is set for new storage
$result['storage_id'] = $storage->getId();
DUP_PRO_Log::trace('Auth result: ' . SnapLog::v2str($result['success']) . ' msg: ' . $result['message']);
return $result;
}
/**
* Revoke storage
*
* @return void
*/
public function revokeStorage(): void
{
AjaxWrapper::json(
[
self::class,
'revokeStorageCallback',
],
'duplicator_pro_revoke_storage',
SnapUtil::sanitizeTextInput(INPUT_POST, 'nonce'),
CapMng::CAP_STORAGE
);
}
/**
* Revoke storage callback
*
* @return mixed[]
*/
public static function revokeStorageCallback(): array
{
$result = [
'success' => false,
'message' => '',
];
$storageId = SnapUtil::sanitizeIntInput(SnapUtil::INPUT_REQUEST, 'storage_id', -1);
if ($storageId < 0 || ($storage = AbstractStorageEntity::getById($storageId)) === false) {
$result['message'] = __('Invalid storage', 'duplicator-pro');
return $result;
}
DUP_PRO_Log::trace("Revoke storage: " . $storage->getName() . "[ID:" . $storage->getId() . "] type: " . $storage->getStypeName());
if (!$storage instanceof StorageAuthInterface) {
$result['message'] = __('Storage does not support authorization', 'duplicator-pro');
DUP_PRO_Log::trace($result['message']);
return $result;
}
if ($storage->revokeAuthorization($result['message'])) {
if (($result['success'] = $storage->save()) == false) {
$result['message'] = __('Failed to update storage', 'duplicator-pro');
}
}
DUP_PRO_Log::trace('Revoke result: ' . SnapLog::v2str($result['success']) . ' msg: ' . $result['message']);
return $result;
}
}