GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Xcloner_Api::delete_backup_by_name()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 6
c 1
b 1
f 0
nc 1
nop 0
dl 0
loc 12
rs 10
1
<?php
2
/**
3
 * XCloner - Backup and Restore backup plugin for Wordpress
4
 *
5
 * class-xcloner-api.php
6
 * @author Liuta Ovidiu <[email protected]>
7
 *
8
 *        This program is free software; you can redistribute it and/or modify
9
 *        it under the terms of the GNU General Public License as published by
10
 *        the Free Software Foundation; either version 2 of the License, or
11
 *        (at your option) any later version.
12
 *
13
 *        This program is distributed in the hope that it will be useful,
14
 *        but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 *        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 *        GNU General Public License for more details.
17
 *
18
 *        You should have received a copy of the GNU General Public License
19
 *        along with this program; if not, write to the Free Software
20
 *        Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21
 *        MA 02110-1301, USA.
22
 *
23
 * @link https://github.com/ovidiul/XCloner-Wordpress
24
 *
25
 * @modified 7/31/18 3:00 PM
26
 *
27
 */
28
29
use League\Flysystem\Config;
30
use League\Flysystem\Filesystem;
31
use League\Flysystem\Util;
32
use League\Flysystem\Adapter\Local;
33
34
use splitbrain\PHPArchive\Tar;
35
use splitbrain\PHPArchive\Zip;
36
use splitbrain\PHPArchive\Archive;
37
use splitbrain\PHPArchive\FileInfo;
38
39
40
/**
41
 * XCloner Api Class
42
 */
43
class Xcloner_Api
44
{
45
46
	private $xcloner_database;
47
	private $xcloner_settings;
48
	private $xcloner_file_system;
49
	private $xcloner_scheduler;
50
	private $xcloner_requirements;
51
	private $xcloner_sanitization;
52
	private $xcloner_encryption;
53
	private $xcloner_remote_storage;
54
	private $archive_system;
55
	private $form_params;
56
	private $logger;
57
	private $xcloner_container;
58
59
	/**
60
	 * XCloner_Api construct class
61
	 *
62
	 * @param Xcloner $xcloner_container [description]
63
	 */
64
	public function __construct(Xcloner $xcloner_container)
65
	{
66
		global $wpdb;
67
68
		if (WP_DEBUG) {
69
			error_reporting(0);
70
		}
71
72
		if (ob_get_length()) {
73
			ob_end_clean();
74
		}
75
		ob_start();
76
77
		$wpdb->show_errors = false;
78
79
		$this->xcloner_container = $xcloner_container;
80
81
		$this->xcloner_settings         = $xcloner_container->get_xcloner_settings();
82
		$this->logger                   = $xcloner_container->get_xcloner_logger()->withName("xcloner_api");
83
		$this->xcloner_file_system      = $xcloner_container->get_xcloner_filesystem();
84
		$this->xcloner_sanitization     = $xcloner_container->get_xcloner_sanitization();
85
		$this->xcloner_requirements     = $xcloner_container->get_xcloner_requirements();
86
		$this->archive_system           = $xcloner_container->get_archive_system();
87
		$this->xcloner_database         = $xcloner_container->get_xcloner_database();
88
		$this->xcloner_scheduler        = $xcloner_container->get_xcloner_scheduler();
89
		$this->xcloner_encryption       = $xcloner_container->get_xcloner_encryption();
90
		$this->xcloner_remote_storage   = $xcloner_container->get_xcloner_remote_storage();
91
92
		if (isset($_POST['API_ID'])) {
93
			$this->logger->info("Processing ajax request ID ".substr($this->xcloner_sanitization->sanitize_input_as_string($_POST['API_ID']),
0 ignored issues
show
Bug introduced by
The method sanitize_input_as_string() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

93
			$this->logger->info("Processing ajax request ID ".substr($this->xcloner_sanitization->/** @scrutinizer ignore-call */ sanitize_input_as_string($_POST['API_ID']),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
94
					0, 15));
95
		}
96
97
	}
98
99
	/**
100
	 * Get XCloner Container
101
	 * @return XCloner return the XCloner container
102
	 */
103
	public function get_xcloner_container()
104
	{
105
		return $this->xcloner_container;
106
	}
107
108
109
	/**
110
	 * Checks API access
111
	 */
112
	private function check_access()
113
	{
114
		if (function_exists('current_user_can') && !current_user_can('manage_options')) {
115
			$this->send_response(json_encode("Not allowed access here!"));
116
		}
117
	}
118
119
	/**
120
	 * Initialize the database connection
121
	 */
122
	public function init_db()
123
	{
124
		return;
125
126
127
		$data['dbHostname'] = $this->xcloner_settings->get_db_hostname();
0 ignored issues
show
Unused Code introduced by
$data['dbHostname'] = $t...ings->get_db_hostname() is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
128
		$data['dbUsername'] = $this->xcloner_settings->get_db_username();
129
		$data['dbPassword'] = $this->xcloner_settings->get_db_password();
130
		$data['dbDatabase'] = $this->xcloner_settings->get_db_database();
131
132
133
		$data['recordsPerSession'] = $this->xcloner_settings->get_xcloner_option('xcloner_database_records_per_request');
134
		$data['TEMP_DBPROCESS_FILE'] = $this->xcloner_settings->get_xcloner_tmp_path().DS.".database";
135
		$data['TEMP_DUMP_FILE'] = $this->xcloner_settings->get_xcloner_tmp_path().DS."database-sql.sql";
136
137
		try {
138
			$this->xcloner_database->init($data);
139
140
		}catch (Exception $e) {
141
142
			$this->send_response($e->getMessage());
143
			$this->logger->error($e->getMessage());
144
145
		}
146
147
		return $this->xcloner_database;
148
149
150
	}
151
152
	/*
153
     * Save Schedule API
154
     */
155
	public function save_schedule()
156
	{
157
		global $wpdb;
158
159
		$this->check_access();
160
161
		$scheduler = $this->xcloner_scheduler;
162
		$params = array();
163
		$schedule = array();
164
		$response = array();
165
166
		if (isset($_POST['data'])) {
167
			$params = json_decode(stripslashes($_POST['data']));
168
		}
169
170
		$this->process_params($params);
171
172
		if (isset($_POST['id'])) {
173
174
			$this->form_params['backup_params']['backup_name'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['backup_name']);
175
			$this->form_params['backup_params']['email_notification'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['email_notification']);
176
			if ($_POST['diff_start_date']) {
177
				$this->form_params['backup_params']['diff_start_date'] = strtotime($this->xcloner_sanitization->sanitize_input_as_string($_POST['diff_start_date']));
178
			} else {
179
				$this->form_params['backup_params']['diff_start_date'] = "";
180
			}
181
			$this->form_params['backup_params']['schedule_name'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['schedule_name']);
182
			$this->form_params['backup_params']['backup_encrypt'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['backup_encrypt']);
183
			$this->form_params['backup_params']['start_at'] = strtotime($_POST['schedule_start_date']);
184
			$this->form_params['backup_params']['schedule_frequency'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['schedule_frequency']);
185
			$this->form_params['backup_params']['schedule_storage'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['schedule_storage']);
186
			$this->form_params['database'] = (stripslashes($this->xcloner_sanitization->sanitize_input_as_raw($_POST['table_params'])));
187
			$this->form_params['excluded_files'] = (stripslashes($this->xcloner_sanitization->sanitize_input_as_raw($_POST['excluded_files'])));
188
189
			//$this->form_params['backup_params']['backup_type'] = $this->xcloner_sanitization->sanitize_input_as_string($_POST['backup_type']);
190
191
			$tables = explode(PHP_EOL, $this->form_params['database']);
192
			$return = array();
193
194
			foreach ($tables as $table) {
195
				$table = str_replace("\r", "", $table);
196
				$data = explode(".", $table);
197
				if (isset($data[1])) {
198
					$return[$data[0]][] = $data[1];
199
				}
200
			}
201
202
			$this->form_params['database'] = ($return);
203
204
			$excluded_files = explode(PHP_EOL, $this->form_params['excluded_files']);
205
			$return = array();
206
207
			foreach ($excluded_files as $file) {
208
				$file = str_replace("\r", "", $file);
209
				if ($file) {
210
					$return[] = $file;
211
				}
212
			}
213
214
			$this->form_params['excluded_files'] = ($return);
215
216
			$schedule['start_at'] = $this->form_params['backup_params']['start_at'];
217
218
			if (!isset($_POST['status'])) {
219
				$schedule['status'] = 0;
220
			} else {
221
				$schedule['status'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['status']);
222
			}
223
		} else {
224
225
			$schedule['status'] = 1;
226
			$schedule['start_at'] = strtotime($this->form_params['backup_params']['schedule_start_date'].
227
				" ".$this->form_params['backup_params']['schedule_start_time']);
228
229
			if ($schedule['start_at'] <= time()) {
230
				$schedule['start_at'] = "";
231
			}
232
		}
233
234
		if (!$schedule['start_at']) {
235
			$schedule['start_at'] = date('Y-m-d H:i:s', time());
236
		} else {
237
			$schedule['start_at'] = date('Y-m-d H:i:s',
238
				$schedule['start_at'] - (get_option('gmt_offset') * HOUR_IN_SECONDS));
239
		}
240
241
		$schedule['name'] = $this->form_params['backup_params']['schedule_name'];
242
		$schedule['recurrence'] = $this->form_params['backup_params']['schedule_frequency'];
243
		if (!isset($this->form_params['backup_params']['schedule_storage'])) {
244
			$this->form_params['backup_params']['schedule_storage'] = "";
245
		}
246
		$schedule['remote_storage'] = $this->form_params['backup_params']['schedule_storage'];
247
		//$schedule['backup_type'] = $this->form_params['backup_params']['backup_type'];
248
		$schedule['params'] = json_encode($this->form_params);
249
250
		if (!isset($_POST['id'])) {
251
			$wpdb->insert(
252
				$wpdb->prefix.'xcloner_scheduler',
253
				$schedule,
254
				array(
255
					'%s',
256
					'%s'
257
				)
258
			);
259
		} else {
260
			$wpdb->update(
261
				$wpdb->prefix.'xcloner_scheduler',
262
				$schedule,
263
				array('id' => $_POST['id']),
264
				array(
265
					'%s',
266
					'%s'
267
				)
268
			);
269
		}
270
		if (isset($_POST['id'])) {
271
			$scheduler->update_cron_hook($_POST['id']);
0 ignored issues
show
Bug introduced by
The method update_cron_hook() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

271
			$scheduler->/** @scrutinizer ignore-call */ 
272
               update_cron_hook($_POST['id']);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
272
		}
273
274
		if ($wpdb->last_error) {
275
			$response['error'] = 1;
276
			$response['error_message'] = $wpdb->last_error/*."--".$wpdb->last_query*/
277
			;
278
279
		}
280
281
		$scheduler->update_wp_cron_hooks();
282
		$response['finished'] = 1;
283
284
		$this->send_response($response);
285
	}
286
287
	/*
288
     *
289
     * Backup Files API
290
     *
291
     */
292
	public function backup_files()
293
	{
294
		$return = array();
295
		$additional = array();
296
297
		$this->check_access();
298
299
		$params = json_decode(stripslashes($_POST['data']));
300
301
		$init = (int)$_POST['init'];
302
303
		if ($params === null) {
304
			return $this->send_response('{"status":false,"msg":"The post_data parameter must be valid JSON"}');
305
		}
306
307
		$this->process_params($params);
308
309
		$return['finished'] = 1;
310
311
		//$return = $this->archive_system->start_incremental_backup($this->form_params['backup_params'], $this->form_params['extra'], $init);
312
		try {
313
			$return = $this->archive_system->start_incremental_backup($this->form_params['backup_params'],
0 ignored issues
show
Bug introduced by
The method start_incremental_backup() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

313
			/** @scrutinizer ignore-call */ 
314
   $return = $this->archive_system->start_incremental_backup($this->form_params['backup_params'],

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
314
				$this->form_params['extra'], $init);
315
		}catch (Exception $e) {
316
			$return = array();
317
			$return['error'] = true;
318
			$return['status'] = 500;
319
			$return['error_message'] = $e->getMessage();
320
321
			return $this->send_response($return, $hash = 1);
322
		}
323
324
		if ($return['finished']) {
325
			$return['extra']['backup_parent'] = $this->archive_system->get_archive_name_with_extension();
326
			if ($this->xcloner_file_system->is_part($this->archive_system->get_archive_name_with_extension())) {
0 ignored issues
show
Bug introduced by
The method is_part() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

326
			if ($this->xcloner_file_system->/** @scrutinizer ignore-call */ is_part($this->archive_system->get_archive_name_with_extension())) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
327
				$return['extra']['backup_parent'] = $this->archive_system->get_archive_name_multipart();
328
			}
329
		}
330
331
		$data = $return;
332
333
		//check if backup is finished
334
		if ($return['finished']) {
335
			if (isset($this->form_params['backup_params']['email_notification']) and $to = $this->form_params['backup_params']['email_notification']) {
336
				try {
337
					$from = "";
338
					$subject = "";
339
					$additional['lines_total'] = $return['extra']['lines_total'];
340
					$this->archive_system->send_notification($to, $from, $subject, $return['extra']['backup_parent'],
341
						$this->form_params, "", $additional);
342
				}catch (Exception $e) {
343
					$this->logger->error($e->getMessage());
344
				}
345
			}
346
			$this->xcloner_file_system->remove_tmp_filesystem();
347
		}
348
349
		return $this->send_response($data, $hash = 1);
350
	}
351
352
	/*
353
     *
354
     * Backup Database API
355
     *
356
     */
357
	public function backup_database()
358
	{
359
		$data = array();
360
361
		$this->check_access();
362
363
		$params = json_decode(stripslashes($_POST['data']));
364
365
		$init = (int)$_POST['init'];
366
367
		if ($params === null) {
368
			return $this->send_response('{"status":false,"msg":"The post_data parameter must be valid JSON"}');
369
		}
370
371
		$this->process_params($params);
372
373
		//$xcloner_database = $this->init_db();
374
		$return = $this->xcloner_database->start_database_recursion($this->form_params['database'],
0 ignored issues
show
Bug introduced by
The method start_database_recursion() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

374
		/** @scrutinizer ignore-call */ 
375
  $return = $this->xcloner_database->start_database_recursion($this->form_params['database'],

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
375
			$this->form_params['extra'], $init);
376
377
		if (isset($return['error']) and $return['error']) {
378
			$data['finished'] = 1;
379
		} else {
380
			$data['finished'] = $return['finished'];
381
		}
382
383
		$data['extra'] = $return;
384
385
		return $this->send_response($data, $hash = 1);
386
	}
387
388
	/*
389
     *
390
     * Scan Filesystem API
391
     *
392
     */
393
	public function scan_filesystem()
394
	{
395
		$data = array();
396
397
		$this->check_access();
398
399
		$params = json_decode(stripslashes($_POST['data']));
400
		$init = (int)$_POST['init'];
401
402
		if ($params === null) {
403
			$this->send_response('{"status":false,"msg":"The post_data parameter must be valid JSON"}');
404
		}
405
406
		$this->process_params($params);
407
408
		$this->xcloner_file_system->set_excluded_files($this->form_params['excluded_files']);
409
410
		$return = $this->xcloner_file_system->start_file_recursion($init);
411
412
		$data["finished"] = !$return;
413
		$data["total_files_num"] = $this->xcloner_file_system->get_scanned_files_num();
414
		$data["last_logged_file"] = $this->xcloner_file_system->last_logged_file();
415
		$data["total_files_size"] = sprintf("%.2f",
416
			$this->xcloner_file_system->get_scanned_files_total_size() / (1024 * 1024));
417
418
		return $this->send_response($data, $hash = 1);
419
	}
420
421
	/*
422
     *
423
     * Process params sent by the user
424
     *
425
     */
426
	private function process_params($params)
427
	{
428
		if (isset($params->hash)) {
429
			$this->xcloner_settings->set_hash($params->hash);
0 ignored issues
show
Bug introduced by
The method set_hash() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

429
			$this->xcloner_settings->/** @scrutinizer ignore-call */ 
430
                            set_hash($params->hash);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
430
		}
431
432
		$this->form_params['extra'] = array();
433
		$this->form_params['backup_params'] = array();
434
435
		$this->form_params['database'] = array();
436
437
		if (isset($params->backup_params)) {
438
			foreach ($params->backup_params as $param) {
439
				$this->form_params['backup_params'][$param->name] = $this->xcloner_sanitization->sanitize_input_as_string($param->value);
440
				$this->logger->debug("Adding form parameter ".$param->name.".".$param->value."\n", array(
441
					'POST',
442
					'fields filter'
443
				));
444
			}
445
		}
446
447
		$this->form_params['database'] = array();
448
449
		if (isset($params->table_params)) {
450
			foreach ($params->table_params as $param) {
451
				$this->form_params['database'][$param->parent][] = $this->xcloner_sanitization->sanitize_input_as_raw($param->id);
452
				$this->logger->debug("Adding database filter ".$param->parent.".".$param->id."\n", array(
453
					'POST',
454
					'database filter'
455
				));
456
			}
457
		}
458
459
		$this->form_params['excluded_files'] = array();
460
		if (isset($params->files_params)) {
461
			foreach ($params->files_params as $param) {
462
				$this->form_params['excluded_files'][] = $this->xcloner_sanitization->sanitize_input_as_relative_path($param->id);
463
			}
464
465
			$unique_exclude_files = array();
466
467
			foreach ($params->files_params as $key => $param) {
468
				if (!in_array($param->parent, $this->form_params['excluded_files'])) {
469
					//$this->form_params['excluded_files'][] = $this->xcloner_sanitization->sanitize_input_as_relative_path($param->id);
470
					$unique_exclude_files[] = $param->id;
471
					$this->logger->debug("Adding file filter ".$param->id."\n", array(
472
						'POST',
473
						'exclude files filter'
474
					));
475
				}
476
			}
477
			$this->form_params['excluded_files'] = (array)$unique_exclude_files;
478
479
		}
480
481
		//$this->form_params['excluded_files'] =  array_merge($this->form_params['excluded_files'], $this->exclude_files_by_default);
482
483
		if (isset($params->extra)) {
484
			foreach ($params->extra as $key => $value) {
485
				$this->form_params['extra'][$key] = $this->xcloner_sanitization->sanitize_input_as_raw($value);
486
			}
487
		}
488
489
		if (isset($this->form_params['backup_params']['diff_start_date']) and $this->form_params['backup_params']['diff_start_date']) {
490
			$this->form_params['backup_params']['diff_start_date'] = strtotime($this->form_params['backup_params']['diff_start_date']);
491
			$this->xcloner_file_system->set_diff_timestamp_start($this->form_params['backup_params']['diff_start_date']);
492
		}
493
494
		return $this->xcloner_settings->get_hash();
495
	}
496
497
	/*
498
     *
499
     * Get file list for tree view API
500
     *
501
     */
502
	public function get_file_system_action()
503
	{
504
		$this->check_access();
505
506
		$folder = $this->xcloner_sanitization->sanitize_input_as_relative_path($_POST['id']);
507
508
		$data = array();
509
510
		if ($folder == "#") {
511
512
			$folder = "/";
513
			$data[] = array(
514
				'id' => $folder,
515
				'parent' => '#',
516
				'text' => $this->xcloner_settings->get_xcloner_start_path(),
517
				//'children' => true,
518
				'state' => array('selected' => false, 'opened' => true),
519
				'icon' => plugin_dir_url(dirname(__FILE__))."/admin/assets/file-icon-root.png"
520
			);
521
		}
522
523
		try {
524
			$files = $this->xcloner_file_system->list_directory($folder);
525
		}catch (Exception $e) {
526
527
			print $e->getMessage();
528
			$this->logger->error($e->getMessage());
529
530
			return;
531
		}
532
533
		$type = array();
534
		foreach ($files as $key => $row) {
535
			$type[$key] = $row['type'];
536
		}
537
		array_multisort($type, SORT_ASC, $files);
538
539
		foreach ($files as $file) {
540
			$children = false;
541
			$text = $file['basename'];
542
543
			if ($file['type'] == "dir") {
544
				$children = true;
545
			} else {
546
				$text .= " (".$this->xcloner_requirements->file_format_size($file['size']).")";
0 ignored issues
show
Bug introduced by
The method file_format_size() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

546
				$text .= " (".$this->xcloner_requirements->/** @scrutinizer ignore-call */ file_format_size($file['size']).")";

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
547
			}
548
549
			if ($this->xcloner_file_system->is_excluded($file)) {
550
				$selected = true;
551
			} else {
552
				$selected = false;
553
			}
554
555
			$data[] = array(
556
				'id' => $file['path'],
557
				'parent' => $folder,
558
				'text' => $text,
559
				//'title' => "test",
560
				'children' => $children,
561
				'state' => array('selected' => $selected, 'opened' => false, "checkbox_disabled" => $selected),
562
				'icon' => plugin_dir_url(dirname(__FILE__))."/admin/assets/file-icon-".strtolower(substr($file['type'],
563
						0, 1)).".png"
564
			);
565
		}
566
567
568
		return $this->send_response($data, 0);
569
	}
570
571
	/*
572
     *
573
     * Get databases/tables list for frontend tree display API
574
     *
575
     */
576
	public function get_database_tables_action()
577
	{
578
		$this->check_access();
579
580
		$database = $this->xcloner_sanitization->sanitize_input_as_raw($_POST['id']);
581
582
		$data = array();
583
584
		$xcloner_backup_only_wp_tables = $this->xcloner_settings->get_xcloner_option('xcloner_backup_only_wp_tables');
585
586
		if ($database == "#") {
587
			try {
588
				$return = $this->xcloner_database->get_all_databases();
589
			}catch (Exception $e) {
590
				$this->logger->error($e->getMessage());
591
			}
592
593
			foreach ($return as $database) {
594
				if ($xcloner_backup_only_wp_tables and $database['name'] != $this->xcloner_settings->get_db_database()) {
595
					continue;
596
				}
597
598
				$state = array();
599
600
				if ($database['name'] == $this->xcloner_settings->get_db_database()) {
601
					$state['selected'] = true;
602
					if ($database['num_tables'] < 25) {
603
						$state['opened'] = false;
604
					}
605
				}
606
607
				$data[] = array(
608
					'id' => $database['name'],
609
					'parent' => '#',
610
					'text' => $database['name']." (".(int)$database['num_tables'].")",
611
					'children' => true,
612
					'state' => $state,
613
					'icon' => plugin_dir_url(dirname(__FILE__))."/admin/assets/database-icon.png"
614
				);
615
			}
616
617
		} else {
618
619
			try {
620
				$return = $this->xcloner_database->list_tables($database, "", 1);
621
			}catch (Exception $e) {
622
				$this->logger->error($e->getMessage());
623
			}
624
625
			foreach ($return as $table) {
626
				$state = array();
627
628
				if ($xcloner_backup_only_wp_tables and !stristr($table['name'],
629
						$this->xcloner_settings->get_table_prefix())) {
630
					continue;
631
				}
632
633
				if (isset($database['name']) and $database['name'] == $this->xcloner_settings->get_db_database()) {
634
					$state = array('selected' => true);
635
				}
636
637
				$data[] = array(
638
					'id' => $database.".".$table['name'],
639
					'parent' => $database,
640
					'text' => $table['name']." (".(int)$table['records'].")",
641
					'children' => false,
642
					'state' => $state,
643
					'icon' => plugin_dir_url(dirname(__FILE__))."/admin/assets/table-icon.png"
644
				);
645
			}
646
		}
647
648
		return $this->send_response($data, 0);
649
	}
650
651
	/*
652
     *
653
     * Get schedule by id API
654
     *
655
     */
656
	public function get_schedule_by_id()
657
	{
658
		$this->check_access();
659
660
		$schedule_id = $this->xcloner_sanitization->sanitize_input_as_int($_GET['id']);
661
		$scheduler = $this->xcloner_scheduler;
662
		$data = $scheduler->get_schedule_by_id($schedule_id);
663
664
		$data['start_at'] = date("Y-m-d H:i",
665
			strtotime($data['start_at']) + (get_option('gmt_offset') * HOUR_IN_SECONDS));
666
		if (isset($data['backup_params']->diff_start_date) && $data['backup_params']->diff_start_date != "") {
667
			$data['backup_params']->diff_start_date = date("Y-m-d", ($data['backup_params']->diff_start_date));
668
		}
669
670
		return $this->send_response($data);
671
	}
672
673
	/*
674
     *
675
     * Get Schedule list API
676
     *
677
     */
678
	public function get_scheduler_list()
679
	{
680
		$return = array();
681
682
		$this->check_access();
683
684
		$scheduler = $this->xcloner_scheduler;
685
		$data = $scheduler->get_scheduler_list();
686
		$return['data'] = array();
687
688
		foreach ($data as $res) {
689
			$action = "<a href=\"#".$res->id."\" class=\"edit\" title='Edit'> <i class=\"material-icons \">edit</i></a>
690
					<a href=\"#" . $res->id."\" class=\"delete\" title='Delete'><i class=\"material-icons  \">delete</i></a>";
691
			if ($res->status) {
692
				$status = '<i class="material-icons active status">timer</i>';
693
			} else {
694
				$status = '<i class="material-icons status inactive">timer_off</i>';
695
			}
696
697
			$next_run_time = wp_next_scheduled('xcloner_scheduler_'.$res->id, array($res->id));
698
699
			$next_run = date(get_option('date_format')." ".get_option('time_format'), $next_run_time);
0 ignored issues
show
Bug introduced by
Are you sure get_option('date_format') of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

699
			$next_run = date(/** @scrutinizer ignore-type */ get_option('date_format')." ".get_option('time_format'), $next_run_time);
Loading history...
Bug introduced by
Are you sure get_option('time_format') of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

699
			$next_run = date(get_option('date_format')." "./** @scrutinizer ignore-type */ get_option('time_format'), $next_run_time);
Loading history...
Bug introduced by
It seems like $next_run_time can also be of type false; however, parameter $timestamp of date() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

699
			$next_run = date(get_option('date_format')." ".get_option('time_format'), /** @scrutinizer ignore-type */ $next_run_time);
Loading history...
700
701
			$remote_storage = $res->remote_storage;
702
703
			if (!$next_run_time >= time()) {
704
				$next_run = " ";
705
			}
706
707
			if (trim($next_run)) {
708
				$date_text = date(get_option('date_format')." ".get_option('time_format'),
709
					$next_run_time + (get_option('gmt_offset') * HOUR_IN_SECONDS));
710
711
				if ($next_run_time >= time()) {
712
					$next_run = "in ".human_time_diff($next_run_time, time());
0 ignored issues
show
Bug introduced by
It seems like $next_run_time can also be of type false; however, parameter $from of human_time_diff() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

712
					$next_run = "in ".human_time_diff(/** @scrutinizer ignore-type */ $next_run_time, time());
Loading history...
713
				} else {
714
					$next_run = __("executed", 'xcloner-backup-and-restore');
715
				}
716
717
				$next_run = "<a href='#' title='".$date_text."'>".$next_run."</a>";
718
				//$next_run .=" ($date_text)";
719
			}
720
721
			$backup_text = "";
722
			$backup_size = "";
723
			$backup_time = "";
724
725
			if ($res->last_backup) {
726
				if ($this->xcloner_file_system->get_storage_filesystem()->has($res->last_backup)) {
727
					$metadata = $this->xcloner_file_system->get_storage_filesystem()->getMetadata($res->last_backup);
728
					$backup_size = size_format($this->xcloner_file_system->get_backup_size($res->last_backup));
729
					$backup_time = date(get_option('date_format')." ".get_option('time_format'),
730
						$metadata['timestamp'] + (get_option('gmt_offset') * HOUR_IN_SECONDS));
731
				}
732
733
				$backup_text = "<span title='".$backup_time."' class='shorten_string'>".$res->last_backup." (".$backup_size.")</span>";
0 ignored issues
show
Bug introduced by
Are you sure $backup_size of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

733
				$backup_text = "<span title='".$backup_time."' class='shorten_string'>".$res->last_backup." ("./** @scrutinizer ignore-type */ $backup_size.")</span>";
Loading history...
734
			}
735
736
			$schedules = wp_get_schedules();
737
738
			if (isset($schedules[$res->recurrence])) {
739
				$res->recurrence = $schedules[$res->recurrence]['display'];
740
			}
741
742
			$return['data'][] = array(
743
				$res->id,
744
				$res->name,
745
				$res->recurrence, /*$res->start_at,*/
746
				$next_run,
747
				$remote_storage,
748
				$backup_text,
749
				$status,
750
				$action
751
			);
752
		}
753
754
		return $this->send_response($return, 0);
755
	}
756
757
	/*
758
     *
759
     * Delete Schedule by ID API
760
     *
761
     */
762
	public function delete_schedule_by_id()
763
	{
764
		$data = array();
765
766
		$this->check_access();
767
768
		$schedule_id = $this->xcloner_sanitization->sanitize_input_as_int($_GET['id']);
769
		$scheduler = $this->xcloner_scheduler;
770
		$data['finished'] = $scheduler->delete_schedule_by_id($schedule_id);
771
772
		return $this->send_response($data);
773
	}
774
775
	/*
776
     *
777
     * Delete backup by name from the storage path
778
     *
779
     */
780
	public function delete_backup_by_name()
781
	{
782
		$data = array();
783
784
		$this->check_access();
785
786
		$backup_name = $this->xcloner_sanitization->sanitize_input_as_string($_POST['name']);
787
		$storage_selection = $this->xcloner_sanitization->sanitize_input_as_string($_POST['storage_selection']);
788
789
		$data['finished'] = $this->xcloner_file_system->delete_backup_by_name($backup_name, $storage_selection);
790
791
		return $this->send_response($data);
792
	}
793
794
	/**
795
	 *  API Incremental Backup Encryption Method
796
	 */
797
	public function backup_encryption()
798
	{
799
		$this->check_access();
800
801
		$backup_parts = array();
802
		$return = array();
803
804
805
		if (isset($_POST['data'])) {
806
			$params = json_decode(stripslashes($_POST['data']));
807
808
			$this->process_params($params);
809
			$source_backup_file = $this->xcloner_sanitization->sanitize_input_as_string($this->form_params['extra']['backup_parent']);
810
811
			if (isset($this->form_params['extra']['start'])) {
812
				$start = $this->xcloner_sanitization->sanitize_input_as_int($this->form_params['extra']['start']);
813
			} else {
814
				$start = 0;
815
			}
816
817
			if (isset($this->form_params['extra']['iv'])) {
818
				$iv = $this->xcloner_sanitization->sanitize_input_as_raw($this->form_params['extra']['iv']);
819
			} else {
820
				$iv = "";
821
			}
822
823
			if (isset($this->form_params['extra']['part'])) {
824
				$return['part'] = (int)$this->xcloner_sanitization->sanitize_input_as_int($this->form_params['extra']['part']);
825
			} else {
826
				$return['part'] = 0;
827
			}
828
829
		} else {
830
			$source_backup_file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
831
			$start = $this->xcloner_sanitization->sanitize_input_as_int($_POST['start']);
832
			$iv = $this->xcloner_sanitization->sanitize_input_as_raw($_POST['iv']);
833
			$return['part'] = (int)$this->xcloner_sanitization->sanitize_input_as_int($_POST['part']);
834
		}
835
836
		$backup_file = $source_backup_file;
837
838
		if ($this->xcloner_file_system->is_multipart($backup_file)) {
839
			$backup_parts = $this->xcloner_file_system->get_multipart_files($backup_file);
840
			$backup_file = $backup_parts[$return['part']];
841
		}
842
843
		$return['processing_file'] = $backup_file;
844
		$return['total_size'] = filesize($this->xcloner_settings->get_xcloner_store_path().DS.$backup_file);
845
846
		try {
847
			$this->logger->info(json_encode($_POST));
848
			$this->logger->info($iv);
849
			$return = array_merge($return,
850
				$this->xcloner_encryption->encrypt_file($backup_file, "", "", $start, base64_decode($iv)));
0 ignored issues
show
Bug introduced by
The method encrypt_file() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

850
				$this->xcloner_encryption->/** @scrutinizer ignore-call */ 
851
                               encrypt_file($backup_file, "", "", $start, base64_decode($iv)));

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
851
		}catch (\Exception $e) {
852
			$return['error'] = true;
853
			$return['message'] = $e->getMessage();
854
			$return['error_message'] = $e->getMessage();
855
		}
856
857
		//echo strlen($return['iv']);exit;
858
859
		if (isset($return['finished']) && $return['finished']) {
860
			if ($this->xcloner_file_system->is_multipart($source_backup_file)) {
861
				$return['start'] = 0;
862
863
				++$return['part'];
864
865
				if ($return['part'] < sizeof($backup_parts)) {
866
					$return['finished'] = 0;
867
				}
868
869
			}
870
		}
871
872
		if (isset($_POST['data'])) {
873
			$return['extra'] = array_merge($this->form_params['extra'], $return);
874
		}
875
876
		$this->send_response($return, 0);
877
	}
878
879
	/**
880
	 *  API Incremental Backup Decryption Method
881
	 */
882
	public function backup_decryption()
883
	{
884
		$this->check_access();
885
886
		$backup_parts = array();
887
		$return = array();
888
889
		$source_backup_file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
890
		$start = $this->xcloner_sanitization->sanitize_input_as_int($_POST['start']);
891
		$iv = $this->xcloner_sanitization->sanitize_input_as_raw($_POST['iv']);
892
		$decryption_key = $this->xcloner_sanitization->sanitize_input_as_raw($_POST['decryption_key']); ;
893
		$return['part'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['part']);
894
895
		$backup_file = $source_backup_file;
896
897
		if ($this->xcloner_file_system->is_multipart($backup_file)) {
898
			$backup_parts = $this->xcloner_file_system->get_multipart_files($backup_file);
899
			$backup_file = $backup_parts[$return['part']];
900
		}
901
902
		$return['processing_file'] = $backup_file;
903
		$return['total_size'] = filesize($this->xcloner_settings->get_xcloner_store_path().DS.$backup_file);
904
905
		try {
906
			$return = array_merge($return,
907
				$this->xcloner_encryption->decrypt_file($backup_file, "", $decryption_key, $start, base64_decode($iv)));
908
		}catch (\Exception $e) {
909
			$return['error'] = true;
910
			$return['message'] = $e->getMessage();
911
		}
912
913
		if ($return['finished']) {
914
			if ($this->xcloner_file_system->is_multipart($source_backup_file)) {
915
				$return['start'] = 0;
916
917
				++$return['part'];
918
919
				if ($return['part'] < sizeof($backup_parts)) {
920
					$return['finished'] = 0;
921
				}
922
923
			}
924
		}
925
926
		$this->send_response($return, 0);
927
	}
928
929
	public function get_manage_backups_list() {
930
931
		$this->check_access();
932
933
		$return = array();
934
		$storage_selection = "";
935
936
		if (isset($_GET['storage_selection']) and $_GET['storage_selection']) {
937
			$storage_selection = $this->xcloner_sanitization->sanitize_input_as_string($_GET['storage_selection']);
938
		}
939
		$available_storages = $this->xcloner_remote_storage->get_available_storages();
0 ignored issues
show
Bug introduced by
The method get_available_storages() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

939
		/** @scrutinizer ignore-call */ 
940
  $available_storages = $this->xcloner_remote_storage->get_available_storages();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
940
941
		$backup_list = $this->xcloner_file_system->get_backup_archives_list($storage_selection);
942
943
		$i = -1;
944
		foreach ($backup_list as $file_info):?>
945
            <?php
946
			if ($storage_selection == "gdrive") {
947
				$file_info['path'] = $file_info['filename'].".".$file_info['extension'];
948
			}
949
			$file_exists_on_local_storage = true;
950
951
			if ($storage_selection) {
952
				if (!$this->xcloner_file_system->get_storage_filesystem()->has($file_info['path'])) {
953
					$file_exists_on_local_storage = false;
954
				}
955
			}
956
957
			?>
958
            <?php if (!isset($file_info['parent'])): ?>
959
960
                <?php ob_start(); ?>
961
                        <p>
962
                            <input name="backup[]" value="<?php echo $file_info['basename'] ?>" type="checkbox"
963
                                   id="checkbox_<?php echo ++$i ?>">
964
                            <label for="checkbox_<?php echo $i ?>">&nbsp;</label>
965
                        </p>
966
                <?php
967
				$return['data'][$i][] = ob_get_contents();
968
				ob_end_clean();
969
				?>
970
971
                <?php ob_start(); ?>
972
                        <span class=""><?php echo $file_info['path'] ?></span>
973
                        <?php if (!$file_exists_on_local_storage): ?>
974
                            <a href="#"
975
                               title="<?php echo __("File does not exists on local storage",
976
								   "xcloner-backup-and-restore") ?>"><i
977
                                        class="material-icons backup_warning">warning</i></a>
978
                        <?php endif ?>
979
                        <?php
980
						if (isset($file_info['childs']) and is_array($file_info['childs'])):
981
							?>
982
                            <a href="#" title="expand" class="expand-multipart add"><i
983
                                        class="material-icons">add</i></a>
984
                            <a href="#" title="collapse" class="expand-multipart remove"><i class="material-icons">remove</i></a>
985
                            <ul class="multipart">
986
                                <?php foreach ($file_info['childs'] as $child): ?>
987
                                    <li>
988
                                        <?php echo $child[0] ?> (<?php echo esc_html(size_format($child[2])) ?>)
0 ignored issues
show
Bug introduced by
It seems like size_format($child[2]) can also be of type false; however, parameter $text of esc_html() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

988
                                        <?php echo $child[0] ?> (<?php echo esc_html(/** @scrutinizer ignore-type */ size_format($child[2])) ?>)
Loading history...
989
                                        <?php
990
										$child_exists_on_local_storage = true;
991
										if ($storage_selection) {
992
											if (!$this->xcloner_file_system->get_storage_filesystem()->has($child[0])) {
993
												$child_exists_on_local_storage = false;
994
											}
995
										}
996
										?>
997
                                        <?php if (!$child_exists_on_local_storage): ?>
998
                                            <a href="#"
999
                                               title="<?php echo __("File does not exists on local storage",
1000
												   "xcloner-backup-and-restore") ?>"><i
1001
                                                        class="material-icons backup_warning">warning</i></a>
1002
                                        <?php endif ?>
1003
                                        <?php if (!$storage_selection) : ?>
1004
                                            <a href="#<?php echo $child[0]; ?>" class="download"
1005
                                               title="Download Backup"><i class="material-icons">file_download</i></a>
1006
1007
                                            <?php if ($this->xcloner_encryption->is_encrypted_file($child[0])) :?>
1008
                                                <a href="#<?php echo $child[0] ?>" class="backup-decryption"
1009
                                                   title="<?php echo __('Backup Decryption', 'xcloner-backup-and-restore') ?>">
1010
                                                    <i class="material-icons">enhanced_encryption</i>
1011
                                                </a>
1012
                                            <?php else: ?>
1013
                                                <a href="#<?php echo $child[0] ?>" class="list-backup-content"
1014
                                                   title="<?php echo __('List Backup Content',
1015
													   'xcloner-backup-and-restore') ?>"><i
1016
                                                            class="material-icons">folder_open</i></a>
1017
1018
                                                <a href="#<?php echo $child[0] ?>" class="backup-encryption"
1019
                                                   title="<?php echo __('Backup Encryption', 'xcloner-backup-and-restore') ?>">
1020
                                                    <i class="material-icons">no_encryption</i>
1021
                                                </a>
1022
                                            <?php endif?>
1023
1024
                                        <?php elseif ($storage_selection != "gdrive" && !$this->xcloner_file_system->get_storage_filesystem()->has($child[0])): ?>
1025
                                            <a href="#<?php echo $child[0] ?>" class="copy-remote-to-local"
1026
                                               title="<?php echo __('Push Backup To Local Storage',
1027
												   'xcloner-backup-and-restore') ?>"><i
1028
                                                        class="material-icons">file_upload</i></a>
1029
                                        <?php endif ?>
1030
                                    </li>
1031
                                <?php endforeach; ?>
1032
                            </ul>
1033
                        <?php endif; ?>
1034
                <?php
1035
				$return['data'][$i][] = ob_get_contents();
1036
				ob_end_clean();
1037
				?>
1038
                    <?php ob_start(); ?>
1039
                        <?php if (isset($file_info['timestamp']))
1040
							echo date("Y-m-d H:i", $file_info['timestamp'])
1041
						?>
1042
                    <?php
1043
						$return['data'][$i][] = ob_get_contents();
1044
						ob_end_clean();
1045
						?>
1046
1047
                    <?php ob_start(); ?>
1048
                        <?php echo esc_html(size_format($file_info['size'])) ?>
1049
                    <?php
1050
						$return['data'][$i][] = ob_get_contents();
1051
						ob_end_clean();
1052
					?>
1053
1054
                    <?php ob_start(); ?>
1055
                        <?php if (!$storage_selection): ?>
1056
                            <a href="#<?php echo $file_info['basename']; ?>" class="download"
1057
                               title="<?php echo __('Download Backup', 'xcloner-backup-and-restore') ?>"><i
1058
                                        class="material-icons">file_download</i></a>
1059
1060
                            <?php if (sizeof($available_storages)): ?>
1061
                                <a href="#<?php echo $file_info['basename'] ?>" class="cloud-upload"
1062
                                   title="<?php echo __('Send Backup To Remote Storage',
1063
									   'xcloner-backup-and-restore') ?>"><i
1064
                                            class="material-icons">cloud_upload</i></a>
1065
                            <?php endif ?>
1066
                            <?php
1067
							$basename = $file_info['basename'];
1068
							if (isset($file_info['childs']) and sizeof($file_info['childs']))
1069
								$basename = $file_info['childs'][0][0];
1070
							?>
1071
                            <?php if ($this->xcloner_encryption->is_encrypted_file($basename)) :?>
1072
                                <a href="#<?php echo $file_info['basename'] ?>" class="backup-decryption"
1073
                                   title="<?php echo __('Backup Decryption', 'xcloner-backup-and-restore') ?>">
1074
                                    <i class="material-icons">enhanced_encryption</i>
1075
                                </a>
1076
                            <?php else: ?>
1077
                                <a href="#<?php echo $file_info['basename'] ?>" class="list-backup-content"
1078
                                    title="<?php echo __('List Backup Content', 'xcloner-backup-and-restore') ?>"><i
1079
                                    class="material-icons">folder_open</i></a>
1080
1081
                                <a href="#<?php echo $file_info['basename'] ?>" class="backup-encryption"
1082
                                   title="<?php echo __('Backup Encryption', 'xcloner-backup-and-restore') ?>">
1083
                                    <i class="material-icons">no_encryption</i>
1084
                                </a>
1085
                            <?php endif?>
1086
                        <?php endif; ?>
1087
1088
                        <a href="#<?php echo $file_info['basename'] ?>" class="delete"
1089
                           title="<?php echo __('Delete Backup', 'xcloner-backup-and-restore') ?>">
1090
                            <i class="material-icons">delete</i>
1091
                        </a>
1092
                        <?php if ($storage_selection and !$file_exists_on_local_storage): ?>
1093
                            <a href="#<?php echo $file_info['basename']; ?>" class="copy-remote-to-local"
1094
                               title="<?php echo __('Push Backup To Local Storage', 'xcloner-backup-and-restore') ?>"><i
1095
                                        class="material-icons">file_upload</i></a>
1096
                        <?php endif ?>
1097
1098
                    <?php
1099
						$return['data'][$i][] = ob_get_contents();
1100
						ob_end_clean(); ?>
1101
1102
            <?php endif ?>
1103
        <?php endforeach ?>
1104
    <?php
1105
		$this->send_response($return, 0);
1106
	}
1107
1108
	/**
1109
	 * API method to list internal backup files
1110
	 */
1111
	public function list_backup_files()
1112
	{
1113
		$this->check_access();
1114
1115
		$backup_parts = array();
1116
		$return = array();
1117
1118
		$source_backup_file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
1119
		$start = $this->xcloner_sanitization->sanitize_input_as_int($_POST['start']);
1120
		$return['part'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['part']);
1121
1122
		$backup_file = $source_backup_file;
1123
1124
		if ($this->xcloner_file_system->is_multipart($backup_file)) {
1125
			$backup_parts = $this->xcloner_file_system->get_multipart_files($backup_file);
1126
			$backup_file = $backup_parts[$return['part']];
1127
		}
1128
1129
		if ($this->xcloner_encryption->is_encrypted_file($backup_file)) {
1130
			$return['error'] = true;
1131
			$return['message'] = __("Backup archive is encrypted, please decrypt it first before you can list it's content.", "xcloner-backup-and-restore");
1132
			$this->send_response($return, 0);
1133
		}
1134
1135
		try {
1136
			$tar = new Tar();
1137
			$tar->open($this->xcloner_settings->get_xcloner_store_path().DS.$backup_file, $start);
1138
1139
			$data = $tar->contents(get_option('xcloner_files_to_process_per_request'));
1140
		}catch (Exception $e) {
1141
			$return['error'] = true;
1142
			$return['message'] = $e->getMessage();
1143
			$this->send_response($return, 0);
1144
		}
1145
1146
		$return['files'] = array();
1147
		$return['finished'] = 1;
1148
		$return['total_size'] = filesize($this->xcloner_settings->get_xcloner_store_path().DS.$backup_file);
1149
		$i = 0;
1150
1151
		if (isset($data['extracted_files']) and is_array($data['extracted_files'])) {
1152
			foreach ($data['extracted_files'] as $file) {
1153
				$return['files'][$i]['path'] = $file->getPath();
1154
				$return['files'][$i]['size'] = $file->getSize();
1155
				$return['files'][$i]['mtime'] = date(get_option('date_format')." ".get_option('time_format'),
0 ignored issues
show
Bug introduced by
Are you sure get_option('date_format') of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1155
				$return['files'][$i]['mtime'] = date(/** @scrutinizer ignore-type */ get_option('date_format')." ".get_option('time_format'),
Loading history...
Bug introduced by
Are you sure get_option('time_format') of type false|mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1155
				$return['files'][$i]['mtime'] = date(get_option('date_format')." "./** @scrutinizer ignore-type */ get_option('time_format'),
Loading history...
1156
					$file->getMtime());
1157
1158
				$i++;
1159
			}
1160
		}
1161
1162
		if (isset($data['start'])) {
1163
			$return['start'] = $data['start'];
1164
			$return['finished'] = 0;
1165
		} else {
1166
			if ($this->xcloner_file_system->is_multipart($source_backup_file)) {
1167
				$return['start'] = 0;
1168
1169
				++$return['part'];
1170
1171
				if ($return['part'] < sizeof($backup_parts)) {
1172
					$return['finished'] = 0;
1173
				}
1174
1175
			}
1176
		}
1177
1178
		$this->send_response($return, 0);
1179
	}
1180
1181
	/*
1182
     * Copy remote backup to local storage
1183
     */
1184
	public function copy_backup_remote_to_local()
1185
	{
1186
1187
		$this->check_access();
1188
1189
		$backup_file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
1190
		$storage_type = $this->xcloner_sanitization->sanitize_input_as_string($_POST['storage_type']);
1191
1192
		$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
1193
1194
		$return = array();
1195
1196
		try {
1197
			if (method_exists($xcloner_remote_storage, "copy_backup_remote_to_local")) {
1198
				$return = call_user_func_array(array(
1199
					$xcloner_remote_storage,
1200
					"copy_backup_remote_to_local"
1201
				), array($backup_file, $storage_type));
1202
			}
1203
		}catch (Exception $e) {
1204
1205
			$return['error'] = 1;
1206
			$return['message'] = $e->getMessage();
1207
		}
1208
1209
		if (!$return) {
1210
			$return['error'] = 1;
1211
			$return['message'] = "Upload failed, please check the error log for more information!";
1212
		}
1213
1214
1215
		$this->send_response($return, 0);
1216
1217
	}
1218
1219
	/*
1220
     *
1221
     * Upload backup to remote API
1222
     *
1223
     */
1224
	public function upload_backup_to_remote()
1225
	{
1226
		$this->check_access();
1227
1228
		$return = array();
1229
1230
		$backup_file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
1231
		$storage_type = $this->xcloner_sanitization->sanitize_input_as_string($_POST['storage_type']);
1232
1233
		$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
1234
1235
		try {
1236
			if (method_exists($xcloner_remote_storage, "upload_backup_to_storage")) {
1237
				$return = call_user_func_array(array(
1238
					$xcloner_remote_storage,
1239
					"upload_backup_to_storage"
1240
				), array($backup_file, $storage_type));
1241
			}
1242
		}catch (Exception $e) {
1243
1244
			$return['error'] = 1;
1245
			$return['message'] = $e->getMessage();
1246
		}
1247
1248
		if (!$return) {
1249
			$return['error'] = 1;
1250
			$return['message'] = "Upload failed, please check the error log for more information!";
1251
		}
1252
1253
1254
		$this->send_response($return, 0);
1255
1256
	}
1257
1258
	/*
1259
     *
1260
     * Remote Storage Status Save
1261
     *
1262
     */
1263
	public function remote_storage_save_status()
1264
	{
1265
		$this->check_access();
1266
1267
		$return = array();
1268
1269
		$xcloner_remote_storage = $this->get_xcloner_container()->get_xcloner_remote_storage();
1270
1271
		$return['finished'] = $xcloner_remote_storage->change_storage_status($_POST['id'], $_POST['value']);
1272
1273
		$this->send_response($return, 0);
1274
	}
1275
1276
1277
	public function download_restore_script()
1278
	{
1279
		$this->check_access();
1280
1281
		ob_end_clean();
1282
1283
		$adapter = new Local(dirname(__DIR__), LOCK_EX, '0001');
1284
		$xcloner_plugin_filesystem = new Filesystem($adapter, new Config([
1285
			'disable_asserts' => true,
1286
		]));
1287
1288
		/* Generate PHAR FILE
1289
        $file = 'restore/vendor.built';
1290
1291
        if(file_exists($file))
1292
            unlink($file);
1293
        $phar2 = new Phar($file, 0, 'vendor.phar');
1294
1295
        // add all files in the project, only include php files
1296
        $phar2->buildFromIterator(
1297
            new RecursiveIteratorIterator(
1298
             new RecursiveDirectoryIterator(__DIR__.'/vendor/')),
1299
            __DIR__);
1300
1301
        $phar2->setStub($phar2->createDefaultStub('vendor/autoload.php', 'vendor/autoload.php'));
1302
         * */
1303
1304
		$tmp_file = $this->xcloner_settings->get_xcloner_tmp_path().DS."xcloner-restore.tgz";
1305
1306
		$tar = new Tar();
1307
		$tar->create($tmp_file);
1308
1309
		$tar->addFile(dirname(__DIR__)."/restore/vendor.build.txt", "vendor.phar");
1310
		//$tar->addFile(dirname(__DIR__)."/restore/vendor.tgz", "vendor.tgz");
1311
1312
		$files = $xcloner_plugin_filesystem->listContents("vendor/", true);
1313
		foreach ($files as $file) {
1314
			$tar->addFile(dirname(__DIR__).DS.$file['path'], $file['path']);
1315
		}
1316
1317
		$content = file_get_contents(dirname(__DIR__)."/restore/xcloner_restore.php");
1318
		$content = str_replace("define('AUTH_KEY', '');", "define('AUTH_KEY', '".md5(AUTH_KEY)."');", $content);
1319
1320
		$tar->addData("xcloner_restore.php", $content);
1321
1322
		$tar->close();
1323
1324
		if (file_exists($tmp_file)) {
1325
			header('Content-Description: File Transfer');
1326
			header('Content-Type: application/octet-stream');
1327
			header('Content-Disposition: attachment; filename="'.basename($tmp_file).'"');
1328
			header('Expires: 0');
1329
			header('Cache-Control: must-revalidate');
1330
			header('Pragma: public');
1331
			header('Content-Length: '.filesize($tmp_file));
1332
			readfile($tmp_file);
1333
1334
		}
1335
1336
		try {
1337
			unlink($tmp_file);
1338
		}catch (Exception $e) {
1339
			//We are not interested in the error here
1340
		}
1341
1342
		die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1343
	}
1344
1345
	/*
1346
     *
1347
     * Download backup by Name from the Storage Path
1348
     *
1349
     */
1350
	public function download_backup_by_name()
1351
	{
1352
		$this->check_access();
1353
1354
		ob_end_clean();
1355
1356
		$backup_name = $this->xcloner_sanitization->sanitize_input_as_string($_GET['name']);
1357
1358
1359
		$metadata = $this->xcloner_file_system->get_storage_filesystem()->getMetadata($backup_name);
1360
		$read_stream = $this->xcloner_file_system->get_storage_filesystem()->readStream($backup_name);
1361
1362
1363
		header('Pragma: public');
1364
		header('Expires: 0');
1365
		header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1366
		header('Cache-Control: private', false);
1367
		header('Content-Transfer-Encoding: binary');
1368
		header('Content-Disposition: attachment; filename="'.$metadata['path'].'";');
1369
		header('Content-Type: application/octet-stream');
1370
		header('Content-Length: '.$metadata['size']);
1371
1372
		ob_end_clean();
1373
1374
		$chunkSize = 1024 * 1024;
1375
		while (!feof($read_stream)) {
1376
			$buffer = fread($read_stream, $chunkSize);
1377
			echo $buffer;
1378
		}
1379
		fclose($read_stream);
1380
1381
		wp_die();
1382
1383
	}
1384
1385
	/*
1386
     * Restore upload backup
1387
     */
1388
	public function restore_upload_backup()
1389
	{
1390
		$this->check_access();
1391
1392
		$return = array();
1393
1394
		$return['part'] = 0;
1395
		$return['total_parts'] = 0;
1396
		$return['uploaded_size'] = 0;
1397
		$is_multipart = 0;
1398
1399
		$file = $this->xcloner_sanitization->sanitize_input_as_string($_POST['file']);
1400
		$hash = $this->xcloner_sanitization->sanitize_input_as_string($_POST['hash']);
1401
1402
		if (isset($_POST['part'])) {
1403
			$return['part'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['part']);
1404
		}
1405
1406
		if (isset($_POST['uploaded_size'])) {
1407
			$return['uploaded_size'] = $this->xcloner_sanitization->sanitize_input_as_int($_POST['uploaded_size']);
1408
		}
1409
1410
		$start = $this->xcloner_sanitization->sanitize_input_as_string($_POST['start']);
1411
		$target_url = $this->xcloner_sanitization->sanitize_input_as_string($_POST['target_url']);
1412
1413
		$return['total_size'] = $this->xcloner_file_system->get_backup_size($file);
1414
1415
		if ($this->xcloner_file_system->is_multipart($file)) {
1416
			$backup_parts = $this->xcloner_file_system->get_multipart_files($file);
1417
1418
			$return['total_parts'] = sizeof($backup_parts) + 1;
1419
1420
			if ($return['part'] and isset($backup_parts[$return['part'] - 1])) {
1421
				$file = $backup_parts[$return['part'] - 1];
1422
			}
1423
1424
			$is_multipart = 1;
1425
		}
1426
1427
		try {
1428
1429
			$xcloner_file_transfer = $this->get_xcloner_container()->get_xcloner_file_transfer();
1430
			$xcloner_file_transfer->set_target($target_url);
1431
			$return['start'] = $xcloner_file_transfer->transfer_file($file, $start, $hash);
1432
1433
		}catch (Exception $e) {
1434
1435
			$return = array();
1436
			$return['error'] = true;
1437
			$return['status'] = 500;
1438
			$return['message'] = "CURL communication error with the restore host. ".$e->getMessage();
1439
			$this->send_response($return, 0);
1440
1441
		}
1442
1443
		$return['status'] = 200;
1444
1445
		//we have finished the upload
1446
		if (!$return['start'] and $is_multipart) {
1447
			$return['part']++;
1448
			$return['uploaded_size'] += $this->xcloner_file_system->get_storage_filesystem()->getSize($file);
1449
		}
1450
1451
		$this->send_response($return, 0);
1452
	}
1453
1454
	/*
1455
     * Restore backup
1456
     */
1457
	public function restore_backup()
1458
	{
1459
		$this->check_access();
1460
1461
		define("XCLONER_PLUGIN_ACCESS", 1);
1462
		include_once(dirname(__DIR__).DS."restore".DS."xcloner_restore.php");
1463
1464
		return;
1465
	}
1466
1467
	/*
1468
     *
1469
     * Send the json response back
1470
     *
1471
     */
1472
	private function send_response($data, $attach_hash = 1)
1473
	{
1474
1475
		if ($attach_hash and null !== $this->xcloner_settings->get_hash()) {
1476
			$data['hash'] = $this->xcloner_settings->get_hash();
1477
		}
1478
1479
		if (ob_get_length()) {
1480
			ob_clean();
1481
		}
1482
		wp_send_json($data);
1483
1484
	}
1485
}
1486