PluginProbe ʕ •ᴥ•ʔ
JetBackup – Backup, Restore & Migrate / trunk
JetBackup – Backup, Restore & Migrate vtrunk
3.1.22.3 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.8.1 1.4.9 1.5.0 1.5.1 1.5.1.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 1.6.10 1.6.11 1.6.12 1.6.13 1.6.15 1.6.5.1 1.6.8.8 1.6.9 1.6.9.1 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7.5 2.0.8.7 2.0.9.11 2.0.9.14 2.0.9.15 2.0.9.6 2.0.9.7 2.0.9.9 3.1.10.7 3.1.11.1 3.1.12.3 3.1.13.4 3.1.14.17 3.1.15.4 3.1.16.1 3.1.17.5 3.1.18.10 3.1.18.8 3.1.18.9 3.1.19.8 3.1.20.3 3.1.21.3 3.1.7.9 3.1.9.2 trunk 1.1.90 1.1.91 1.2.0 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2
backup / src / JetBackup / Ajax / Ajax.php
backup / src / JetBackup / Ajax Last commit date
Calls 5 days ago .htaccess 1 year ago Ajax.php 5 days ago ListRecord.php 1 year ago aAjax.php 1 year ago iAjax.php 1 year ago index.html 1 year ago web.config 1 year ago
Ajax.php
199 lines
1 <?php
2
3 namespace JetBackup\Ajax;
4
5 use Exception;
6 use JetBackup\Cron\Cron;
7 use JetBackup\Data\ArrayData;
8 use JetBackup\Entities\Util;
9 use JetBackup\Exception\AjaxException;
10 use JetBackup\Exception\JBException;
11 use JetBackup\JetBackup;
12 use JetBackup\MFA\GoogleAuthenticator;
13 use JetBackup\Wordpress\UI;
14 use JetBackup\Wordpress\Wordpress;
15
16 if (!defined( '__JETBACKUP__')) die('Direct access is not allowed');
17
18 class Ajax extends ArrayData {
19
20 const MFA_ALLOWED_FUNCTIONS = ['panelPreload', 'getQRCode', 'validateMFA'];
21
22 private function __construct() {
23 $this->setData(self::_getRequestData());
24 }
25
26 /**
27 * @return array
28 */
29 private static function _getRequestData():array {
30 $input = file_get_contents("php://input");
31 $params = $input ? json_decode($input,true) : [];
32 if(!$params) $params = [];
33 if($_GET && is_array($_GET)) $params = array_merge($_GET, $params);
34 if($_POST && is_array($_POST)) $params = array_merge($_POST, $params);
35 if($_REQUEST && is_array($_REQUEST)) $params = array_merge($_REQUEST, $params);
36 return $params;
37 }
38
39 /**
40 * @return string
41 */
42 private static function _getNonce():string {
43 $params = self::_getRequestData();
44 return $params['nonce'] ?? '';
45 }
46
47 /**
48 * @return void
49 * @throws AjaxException
50 */
51 private static function _init():void {
52 if (!function_exists('current_user_can')) throw new AjaxException('Error %s - WordPress Core function missing', [102]);
53 if (!function_exists('is_user_logged_in')) throw new AjaxException('Error %s - WordPress Core function missing', [103]);
54 if (!is_user_logged_in()) throw new AjaxException('Error %s - You are not logged in', [104]);
55 if (!current_user_can('manage_options')) throw new AjaxException('Error %s - Insufficient user permissions', [105]);
56 if (!Wordpress::verifyNonce(self::_getNonce())) throw new AjaxException('Error %s - Session Expired (Refresh Page Needed?)', [108]);
57 }
58
59 /**
60 * @return void
61 */
62 public static function main():void {
63 header('Content-Type: application/json');
64 register_shutdown_function([self::class, 'handleFatalError']);
65 (new Ajax())->execute();
66 }
67
68 /**
69 * Shutdown handler to catch fatal errors and output proper JSON response
70 */
71 public static function handleFatalError(): void {
72 $error = error_get_last();
73 if ($error === null || !in_array($error['type'], [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE])) {
74 return;
75 }
76 // Clear any output that may have been sent
77 if (ob_get_level()) ob_end_clean();
78
79 $message = sprintf("Fatal error: %s in %s:%d", $error['message'], $error['file'], $error['line']);
80 die(json_encode([
81 'message' => $message,
82 'success' => 0,
83 'data' => [],
84 'system' => ['version' => JetBackup::VERSION],
85 ]));
86 }
87
88 /**
89 * @return void
90 */
91 public function execute():void {
92
93 if (Wordpress::isDebugModeEnabled()) {
94 error_reporting(E_ALL);
95 ini_set('log_errors', 1);
96 ini_set('display_errors', 0);
97 }
98
99 $data = $this->getData();
100
101 try {
102 self::_init();
103 if(!isset($data['actionType']) || !$data['actionType']) throw new AjaxException("No action type provided");
104
105 $method = "\JetBackup\Ajax\Calls\\" . ucfirst($data['actionType']);
106 if(!class_exists($method)) throw new AjaxException("Invalid action type provided (action: %s)", [$data['actionType']]);
107
108 if (GoogleAuthenticator::isSetupCompleted() &&
109 !UI::validateMFA() &&
110 !in_array($data['actionType'], self::MFA_ALLOWED_FUNCTIONS)) throw new AjaxException('MFA is not validated');
111
112 /** @var iAjax $call */
113 $call = new $method();
114 $call->setData($data);
115
116 $call->execute();
117 self::_output($call->getResponseMessage(), $call->getResponseData());
118 } catch(AjaxException $e) {
119 $msg = $e->getMessage();
120 self::_exit($msg, $e->getData());
121 } catch(JBException $e) {
122 self::_exit($e->getMessage());
123 } catch(\Throwable $e) {
124 self::_exit("Unexpected error: " . $e->getMessage() . " in " . $e->getFile() . ":" . $e->getLine());
125 }
126 }
127
128 /**
129 * @return void
130 */
131 public static function heartbeat():void {
132 header('Content-Type: application/json');
133 register_shutdown_function([self::class, 'handleFatalError']);
134
135 try {
136 self::_init();
137 Cron::main();
138 } catch(\Throwable $e) {
139 self::_exit($e->getMessage() . " in " . $e->getFile() . ":" . $e->getLine());
140 return;
141 }
142
143 self::_output('Heartbeat Done');
144 }
145
146
147 /**
148 * @param string $message
149 * @param array $data
150 * @param int $success
151 *
152 * @return void
153 */
154 private static function _output(string $message, array $data=[], int $success=1):void {
155 $response = [
156 'message' => $message,
157 'success' => $success,
158 'data' => $data,
159 'system' => [
160 'version' => JetBackup::VERSION,
161 'nonce' => Wordpress::createNonce(),
162 ],
163 ];
164
165 $json = json_encode($response, JSON_INVALID_UTF8_SUBSTITUTE);
166 if ($json === false) {
167 // Fallback if encoding fails - try without data
168 $json = json_encode([
169 'message' => 'JSON encoding failed: ' . json_last_error_msg(),
170 'success' => 0,
171 'data' => [],
172 'system' => ['version' => JetBackup::VERSION],
173 ]);
174 }
175
176 while (ob_get_level() > 0 && @ob_end_clean());
177 die($json);
178 }
179
180 /**
181 * @param string $message
182 * @param array $data
183 *
184 * @return void
185 */
186 private static function _exit(string $message, array $data=[]):void {
187 self::_output($message, $data, 0);
188 }
189
190 /**
191 * @param int $time
192 *
193 * @return string
194 * @throws Exception
195 */
196 public static function date(int $time):string {
197 return Util::date("Y-m-d H:i:s", $time);
198 }
199 }