File: //proc/self/cwd/wp-content/plugins/backup/src/JetBackup/Ajax/Ajax.php
<?php
namespace JetBackup\Ajax;
use Exception;
use JetBackup\Cron\Cron;
use JetBackup\Data\ArrayData;
use JetBackup\Entities\Util;
use JetBackup\Exception\AjaxException;
use JetBackup\Exception\JBException;
use JetBackup\JetBackup;
use JetBackup\MFA\GoogleAuthenticator;
use JetBackup\Wordpress\UI;
use JetBackup\Wordpress\Wordpress;
if (!defined( '__JETBACKUP__')) die('Direct access is not allowed');
class Ajax extends ArrayData {
const MFA_ALLOWED_FUNCTIONS = ['panelPreload', 'getQRCode', 'validateMFA'];
private function __construct() {
$this->setData(self::_getRequestData());
}
/**
* @return array
*/
private static function _getRequestData():array {
$input = file_get_contents("php://input");
$params = $input ? json_decode($input,true) : [];
if(!$params) $params = [];
if($_GET && is_array($_GET)) $params = array_merge($_GET, $params);
if($_POST && is_array($_POST)) $params = array_merge($_POST, $params);
if($_REQUEST && is_array($_REQUEST)) $params = array_merge($_REQUEST, $params);
return $params;
}
/**
* @return string
*/
private static function _getNonce():string {
$params = self::_getRequestData();
return $params['nonce'] ?? '';
}
/**
* @return void
* @throws AjaxException
*/
private static function _init():void {
if (!function_exists('current_user_can')) throw new AjaxException('Error %s - WordPress Core function missing', [102]);
if (!function_exists('is_user_logged_in')) throw new AjaxException('Error %s - WordPress Core function missing', [103]);
if (!is_user_logged_in()) throw new AjaxException('Error %s - You are not logged in', [104]);
if (!current_user_can('manage_options')) throw new AjaxException('Error %s - Insufficient user permissions', [105]);
if (!Wordpress::verifyNonce(self::_getNonce())) throw new AjaxException('Error %s - Session Expired (Refresh Page Needed?)', [108]);
}
/**
* @return void
*/
public static function main():void {
header('Content-Type: application/json');
register_shutdown_function([self::class, 'handleFatalError']);
(new Ajax())->execute();
}
/**
* Shutdown handler to catch fatal errors and output proper JSON response
*/
public static function handleFatalError(): void {
$error = error_get_last();
if ($error === null || !in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE])) {
return;
}
// Clear any output that may have been sent
if (ob_get_level()) ob_end_clean();
$message = sprintf("Fatal error: %s in %s:%d", $error['message'], $error['file'], $error['line']);
die(json_encode([
'message' => $message,
'success' => 0,
'data' => [],
'system' => ['version' => JetBackup::VERSION],
]));
}
/**
* @return void
*/
public function execute():void {
if (Wordpress::isDebugModeEnabled()) {
error_reporting(E_ALL);
ini_set('log_errors', 1);
ini_set('display_errors', 0);
}
$data = $this->getData();
try {
self::_init();
if(!isset($data['actionType']) || !$data['actionType']) throw new AjaxException("No action type provided");
$method = "\JetBackup\Ajax\Calls\\" . ucfirst($data['actionType']);
if(!class_exists($method)) throw new AjaxException("Invalid action type provided (action: %s)", [$data['actionType']]);
if (GoogleAuthenticator::isSetupCompleted() &&
!UI::validateMFA() &&
!in_array($data['actionType'], self::MFA_ALLOWED_FUNCTIONS)) throw new AjaxException('MFA is not validated');
/** @var iAjax $call */
$call = new $method();
$call->setData($data);
$call->execute();
self::_output($call->getResponseMessage(), $call->getResponseData());
} catch(AjaxException $e) {
$msg = $e->getMessage();
self::_exit($msg, $e->getData());
} catch(JBException $e) {
self::_exit($e->getMessage());
} catch(\Throwable $e) {
self::_exit("Unexpected error: " . $e->getMessage() . " in " . $e->getFile() . ":" . $e->getLine());
}
}
/**
* @return void
*/
public static function heartbeat():void {
header('Content-Type: application/json');
register_shutdown_function([self::class, 'handleFatalError']);
try {
self::_init();
Cron::main();
} catch(\Throwable $e) {
self::_exit($e->getMessage() . " in " . $e->getFile() . ":" . $e->getLine());
return;
}
self::_output('Heartbeat Done');
}
/**
* @param string $message
* @param array $data
* @param int $success
*
* @return void
*/
private static function _output(string $message, array $data=[], int $success=1):void {
$response = [
'message' => $message,
'success' => $success,
'data' => $data,
'system' => [
'version' => JetBackup::VERSION,
'nonce' => Wordpress::createNonce(),
],
];
$json = json_encode($response, JSON_INVALID_UTF8_SUBSTITUTE);
if ($json === false) {
// Fallback if encoding fails - try without data
$json = json_encode([
'message' => 'JSON encoding failed: ' . json_last_error_msg(),
'success' => 0,
'data' => [],
'system' => ['version' => JetBackup::VERSION],
]);
}
while (ob_get_level() > 0 && @ob_end_clean());
die($json);
}
/**
* @param string $message
* @param array $data
*
* @return void
*/
private static function _exit(string $message, array $data=[]):void {
self::_output($message, $data, 0);
}
/**
* @param int $time
*
* @return string
* @throws Exception
*/
public static function date(int $time):string {
return Util::date("Y-m-d H:i:s", $time);
}
}