File: /home/dmstechonline/giaconieditore.com/wp-content/plugins/backup/src/JetBackup/Wordpress/Init.php
<?php
namespace JetBackup\Wordpress;
use JetBackup\BackupJob\BackupJob;
use JetBackup\CLI\CLI;
use JetBackup\Destination\Destination;
use JetBackup\Download\Download;
use JetBackup\Downloader\Downloader;
use JetBackup\Entities\Util;
use JetBackup\Exception\JBException;
use JetBackup\Factory;
use JetBackup\JetBackup;
use JetBackup\Queue\QueueItem;
use JetBackup\Schedule\Schedule;
use JetBackup\SGB\Migration;
use JetBackup\UserInput\UserInput;
if (!defined( '__JETBACKUP__')) die('Direct access is not allowed');
class Init {
private static bool $_initialized = false;
private function __construct() { } // only static method
public static function isInitialized(): bool {
return self::$_initialized;
}
/**
* Detect whether the site is likely running on WP Cloud / Atomic (e.g., Porkbun WP Cloud).
*
* Logic:
* 1) IS_ATOMIC must exist and evaluate to true
* 2) AND at least one of ATOMIC_CLIENT_ID / ATOMIC_SITE_ID must exist (to reduce false positives)
*/
public static function isWpCloudAtomic(): bool
{
// Fast fail: constant not present at all
if (!\defined('IS_ATOMIC')) {
return false;
}
// Some platforms may define it as bool/int/string; normalize safely
$isAtomic = \constant('IS_ATOMIC');
// Treat 1 / "1" / true / "true" as true
$isAtomic = ($isAtomic === true)
|| ($isAtomic === 1)
|| ($isAtomic === '1')
|| (\is_string($isAtomic) && \strcasecmp($isAtomic, 'true') === 0);
if (!$isAtomic) {
return false;
}
// Extra signals to avoid collisions with other platforms that might define IS_ATOMIC
$hasClientId = \defined('ATOMIC_CLIENT_ID') && \constant('ATOMIC_CLIENT_ID') !== null && \constant('ATOMIC_CLIENT_ID') !== '';
$hasSiteId = \defined('ATOMIC_SITE_ID') && \constant('ATOMIC_SITE_ID') !== null && \constant('ATOMIC_SITE_ID') !== '';
return ($hasClientId || $hasSiteId);
}
/**
* Run a callable only if JetBackup init completed successfully.
* Never throws (logs and returns default).
*
* @param callable $callable
* @param array $args
* @param mixed $default
* @return mixed
*/
public static function guard(callable $callable, array $args = [], $default = null) {
try {
if (!self::isInitialized()) return $default;
return \call_user_func_array($callable, $args);
} catch (\Throwable $e) {
error_log('[JetBackup] guarded hook failed: ' . $e->getMessage());
return $default;
}
}
/**
* @return void
*/
public static function actionInit() {
if (!function_exists('current_user_can') || !current_user_can('manage_options')) return;
try {
load_plugin_textdomain('jetbackup', false, JetBackup::PLUGIN_NAME . DIRECTORY_SEPARATOR . 'languages');
// Cookie Env (safe)
add_action('wp_loaded', ['\JetBackup\Wordpress\Wordpress', 'setNonceCookie']);
add_action('wp_loaded', ['\JetBackup\Wordpress\Wordpress', 'setUserLanguageCookie']);
self::_createWorkingSpace();
self::_validateWorkingSpace();
(new Migration())->migrate();
Destination::createDefaultDestination();
Schedule::createDefaultSchedule();
BackupJob::getDefaultJob();
BackupJob::getDefaultConfigJob();
self::_download();
//Only register UI/AJAX/heartbeat after we know init succeeded.
$hookNetworkMenu = false;
if (Helper::isMultisite()) {
if (!Helper::isMainSite() || !Helper::isNetworkAdminUser()) return;
$hookNetworkMenu = Helper::isNetworkAdminInterface();
}
if ($hookNetworkMenu) add_action('network_admin_menu', ['\JetBackup\Wordpress\UI', 'main']);
self::$_initialized = true;
add_action('admin_menu', ['\JetBackup\Wordpress\UI', 'main']);
add_action('wp_ajax_jetbackup_api', ['\JetBackup\Ajax\Ajax', 'main']);
if (Factory::getSettingsAutomation()->isHeartbeatEnabled()) {
add_action('admin_footer', ['\JetBackup\Wordpress\UI', 'heartbeat']);
add_action('wp_ajax_jetbackup_heartbeat', ['\JetBackup\Ajax\Ajax', 'heartbeat']);
}
if (self::isWpCloudAtomic()) {
$restore = Factory::getSettingsRestore();
$changed = false;
if (!$restore->isRestoreWpContentOnlyEnabled()) {
$restore->setRestoreWpContentOnly(true);
$changed = true;
}
if (!$restore->isRestoreAlternatePathEnabled()) {
$restore->setRestoreAlternatePath(true);
$changed = true;
}
if ($changed) $restore->save();
}
} catch (\Throwable $e) {
error_log('[JetBackup] actionInit failed: ' . $e->getMessage() . "\n" . $e->getTraceAsString());
// if any hooks were added earlier, remove them
remove_action('admin_menu', ['\JetBackup\Wordpress\UI', 'main']);
remove_action('network_admin_menu', ['\JetBackup\Wordpress\UI', 'main']);
remove_action('admin_footer', ['\JetBackup\Wordpress\UI', 'heartbeat']);
remove_action('wp_ajax_jetbackup_api', ['\JetBackup\Ajax\Ajax', 'main']);
remove_action('wp_ajax_jetbackup_heartbeat', ['\JetBackup\Ajax\Ajax', 'heartbeat']);
if (function_exists('is_admin') && is_admin()) {
add_action('admin_notices', function () use ($e) {
if (!current_user_can('manage_options')) return;
echo '<div class="notice notice-error"><p><strong>JetBackup:</strong> '
. esc_html('JetBackup failed to initialize and was disabled for this request. Reason: ' . $e->getMessage())
. '</p></div>';
});
}
return;
}
}
private static function _download():void {
try {
$userInput = new UserInput();
$userInput->setData($_REQUEST);
if($download_id = $userInput->getValidated('download_id', 0, UserInput::UINT)) {
$download = new Download($download_id);
if(!$download->getId()) throw new JBException('The provided download id not found');
$download->download();
}
if($queue_item_id = $userInput->getValidated('queue_item_id', 0, UserInput::UINT)) {
$queue_item = new QueueItem($queue_item_id);
if(!$queue_item->getId()) throw new JBException('The provided queue item id not found');
$downloader = new Downloader($queue_item->getLogFile());
$downloader->download();
}
} catch(JBException $e) {
wp_die(esc_html('JetBackup: ' . $e->getMessage()));
}
}
private static function _getWorkingSpaceLockFile(): string
{
return Factory::getLocations()->getDataDir()
. JetBackup::SEP
. Factory::getConfig()->getUniqueID()
. '.lock';
}
private static function _getWorkingSpaceLockFileValue(): string
{
$lockFile = self::_getWorkingSpaceLockFile();
if (!file_exists($lockFile)) return '';
$content = @file_get_contents($lockFile);
if ($content === false) return ''; // Treat as corrupted; let validator handle it
return trim($content);
}
private static function _getInstallFingerprint(): string
{
global $wpdb;
$dbName = $wpdb->dbname ?? '';
$prefix = $wpdb->prefix ?? '';
$secret = defined('AUTH_KEY')
? AUTH_KEY
: Factory::getConfig()->getEncryptionKey();
return sha1($dbName . '|' . $prefix . '|' . $secret);
}
private static function _updateWorkingSpaceLockFile(): void
{
$lockFile = self::_getWorkingSpaceLockFile();
$fingerprint = self::_getInstallFingerprint();
if (file_put_contents($lockFile, $fingerprint, LOCK_EX) !== false) {
@chmod($lockFile, 0400);
}
}
private static function _validateWorkingSpace(): void
{
// Only lock the folder if we are using an alternate datadir
// Regular setup is inside wp-content which is per-install
if (empty(Factory::getConfig()->getAlternateDataFolder())) return;
$lockFile = self::_getWorkingSpaceLockFile();
// First run: create lock file and exit
if (!file_exists($lockFile)) {
self::_updateWorkingSpaceLockFile();
return;
}
$storedFingerprint = self::_getWorkingSpaceLockFileValue();
$currentFingerprint = self::_getInstallFingerprint();
if (!hash_equals($storedFingerprint, $currentFingerprint)) {
error_log('JetBackup: Alternate data folder reset due to mismatched installation fingerprint.');
Factory::getConfig()->setAlternateDataFolder('');
Factory::getConfig()->save();
}
}
private static function _createWorkingSpace() {
$folders = [
Factory::getLocations()->getDataDir(),
Factory::getLocations()->getTempDir(),
Factory::getLocations()->getDatabaseDir(),
Factory::getLocations()->getDownloadsDir(),
Factory::getLocations()->getBackupsDir(),
Factory::getLocations()->getLogsDir(),
];
foreach ($folders as $folder) Util::secureFolder($folder);
}
public static function filterAdminBodyClass($classes) {
$screen = Helper::getCurrentScreen();
if ($screen && strpos($screen, 'jetbackup') !== false) $classes .= ' jetbackup';
return $classes;
}
public static function actionCLI() {
if (defined('WP_CLI') && WP_CLI) CLI::init();
}
}