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.
Passed
Branch dev (231e41)
by Liuta
03:38
created

Xcloner_Restore::update_wp_config()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 3
eloc 15
nc 3
nop 5
dl 0
loc 28
rs 9.7666
c 2
b 1
f 0
1
<?php
2
3
if (!defined('AUTH_KEY'))
4
{
5
	define('AUTH_KEY', '');
6
}
7
8
if (!defined("DS"))
9
{
10
	define("DS", DIRECTORY_SEPARATOR);
11
}
12
13
if (!defined('XCLONER_PLUGIN_ACCESS') || XCLONER_PLUGIN_ACCESS != 1)
14
{	
15
	if (!AUTH_KEY)
16
	{
17
			Xcloner_Restore::send_response("404", "Could not run restore script, AUTH_KEY not set!");
18
			exit;
19
	}
20
	
21
	if (!isset($_REQUEST['hash']))
22
	{
23
			Xcloner_Restore::send_response("404", "Could not run restore script, sent HASH is empty!");
24
			exit;
25
	}
26
	
27
	if ($_REQUEST['hash'] != AUTH_KEY)
28
	{
29
			Xcloner_Restore::send_response("404", "Could not run restore script, AUTH_KEY doesn't match the sent HASH!");
30
			exit;
31
	}
32
}
33
34
//check minimum PHP version
35
if (version_compare(phpversion(), Xcloner_Restore::xcloner_minimum_version, '<'))
36
{
37
	Xcloner_Restore::send_response(500, sprintf(("XCloner requires minimum PHP version %s in order to run correctly. We have detected your version as %s"), Xcloner_Restore::xcloner_minimum_version, phpversion()));
38
	exit;
39
40
}
41
42
$file = dirname(__DIR__).DS.'vendor'.DS.'autoload.php';
43
44
if (file_exists($file))
45
{
46
	
47
	require_once($file);
48
}
49
elseif (file_exists("vendor.phar") and extension_loaded('phar'))
50
{
51
	require_once(__DIR__.DS."vendor.phar");
52
} else {	
53
	
54
	$file = dirname(__FILE__).DS.'vendor'.DS.'autoload.php';
55
	
56
	if (!file_exists($file))
57
	{
58
		Xcloner_Restore::send_response("404", "File $file does not exists, please extract the vendor.tgz archive on the server or enable PHP Phar module!");
59
		exit;
60
	}
61
	
62
	require_once($file);
63
}
64
65
66
use League\Flysystem\Config;
67
use League\Flysystem\Filesystem;
68
use League\Flysystem\Util;
69
use League\Flysystem\Adapter\Local;
70
71
use splitbrain\PHPArchive\Tar;
72
use splitbrain\PHPArchive\Archive;
73
use splitbrain\PHPArchive\FileInfo;
74
75
use Monolog\Logger;
76
use Monolog\Handler\StreamHandler;
77
78
79
//do not modify below
80
$that = "";
81
if (defined('XCLONER_PLUGIN_ACCESS') && XCLONER_PLUGIN_ACCESS)
82
{
83
	$that = $this;
84
}
85
$xcloner_restore = new Xcloner_Restore($that);
86
87
try {
88
	$return = $xcloner_restore->init();
89
	$xcloner_restore->send_response(200, $return);
90
}catch (Exception $e) {
91
	$xcloner_restore->send_response(417, $e->getMessage());
92
}
93
94
class Xcloner_Restore
95
{
96
	
97
	const 	xcloner_minimum_version = "5.4.0";
98
	
99
	private $backup_archive_extensions = array("zip", "tar", "tgz", "tar.gz", "gz", "csv");
100
	private $process_files_limit = 150;
101
	private $process_files_limit_list = 350;
102
	private $process_mysql_records_limit = 250;
103
	private $adapter;
104
	private $filesystem;
105
	private $logger;
106
	private $backup_storage_dir;
107
	private $parent_api;
108
109
	/**
110
	 * Xcloner_Restore constructor.
111
	 * @param string $parent_api
112
	 * @throws Exception
113
	 */
114
	public function __construct($parent_api = "")
115
	{
116
		register_shutdown_function(array($this, 'exception_handler'));
117
118
		if (defined('XCLONER_PLUGIN_ACCESS') && XCLONER_PLUGIN_ACCESS)
119
		{
120
			$dir = $parent_api->get_xcloner_container()->get_xcloner_settings()->get_xcloner_store_path();
121
		}
122
		
123
		if (!isset($dir) || !$dir) {
124
			$dir = dirname(__FILE__);
125
		}
126
		
127
		$this->parent_api = $parent_api;
128
		
129
		$this->backup_storage_dir = $dir;
130
		
131
		$this->adapter = new Local($dir, LOCK_EX, 'SKIP_LINKS');
0 ignored issues
show
Bug introduced by
'SKIP_LINKS' of type string is incompatible with the type integer expected by parameter $linkHandling of League\Flysystem\Adapter\Local::__construct(). ( Ignorable by Annotation )

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

131
		$this->adapter = new Local($dir, LOCK_EX, /** @scrutinizer ignore-type */ 'SKIP_LINKS');
Loading history...
132
		$this->filesystem = new Filesystem($this->adapter, new Config([
133
				'disable_asserts' => true,
134
			]));
135
			
136
		$this->logger = new Logger('xcloner_restore');
137
		
138
		$logger_path = $this->get_logger_filename();
139
		
140
		if (!is_writeable($logger_path) and !touch($logger_path))
141
		{
142
			$logger_path = "php://stderr";
143
		}
144
		
145
		$this->logger->pushHandler(new StreamHandler($logger_path, Logger::DEBUG));
146
		
147
		if (isset($_POST['API_ID'])) {
148
			$this->logger->info("Processing ajax request ID ".substr(filter_input(INPUT_POST, 'API_ID', FILTER_SANITIZE_STRING), 0, 15));
149
		}
150
151
	}
152
153
	/**
154
	 * Exception handler method
155
	 */
156
	public function exception_handler() {
157
		
158
		$error = error_get_last();
159
		
160
		if ($error['type'] and $this->logger)
161
		{
162
			$this->logger->info($this->friendly_error_type($error['type']).": ".var_export($error, true));
163
		}
164
	
165
	}
166
167
	/**
168
	 * @param $type
169
	 * @return mixed|string
170
	 */
171
	private function friendly_error_type($type) {
172
		static $levels = null;
173
		if ($levels === null) {
174
			$levels = [];
175
			foreach (get_defined_constants() as $key=>$value) {
176
				if (strpos($key, 'E_') !== 0) {continue; }
177
					$levels[$value] = $key; //substr($key,2);
178
			}
179
		}
180
		return (isset($levels[$type]) ? $levels[$type] : "Error #{$type}");
181
	}
182
	
183
	public function get_logger_filename()
184
	{
185
		$filename = $this->backup_storage_dir.DS."xcloner_restore.log";
186
		
187
		return $filename;
188
	}
189
190
	/**
191
	 * Init method
192
	 *
193
	 * @return mixed|void
194
	 * @throws Exception
195
	 */
196
	public function init()
197
	{
198
		if (isset($_POST['xcloner_action']) and $_POST['xcloner_action'])
199
		{
200
			$method = filter_input(INPUT_POST, 'xcloner_action', FILTER_SANITIZE_STRING);
201
			
202
			//$method = "list_backup_archives";
203
			
204
			$method .= "_action";
205
			
206
			if (method_exists($this, $method))
207
			{
208
				$this->logger->debug(sprintf('Starting action %s', $method));
209
				return call_user_func(array($this, $method));
210
				
211
			} else {
212
				throw new Exception($method." does not exists");
213
				}
214
		}
215
		
216
		return $this->check_system();
217
	}
218
219
	/**
220
	 * Write file method
221
	 *
222
	 * @return bool|int
223
	 * @throws Exception
224
	 */
225
	public function write_file_action()
226
	{
227
		if (isset($_POST['file']))
228
		{
229
			$target_file = filter_input(INPUT_POST, 'file', FILTER_SANITIZE_STRING);
230
			
231
			if (!$_POST['start'])
232
				$fp = fopen($target_file, "wb+");
233
			else
234
				$fp = fopen($target_file, "ab+");	
235
			
236
			if (!$fp)
0 ignored issues
show
introduced by
$fp is of type false|resource, thus it always evaluated to false.
Loading history...
237
				throw new Exception("Unable to open $target_file file for writing");
238
			
239
			fseek($fp, $_POST['start']);
240
			
241
			if (isset($_FILES['blob']))
242
			{
243
				$this->logger->debug(sprintf('Writing %s bytes to file %s starting position %s using FILES blob', filesize($_FILES['blob']['tmp_name']), $target_file, $_POST['start']));
244
				
245
				$blob = file_get_contents($_FILES['blob']['tmp_name']);
246
				
247
				if (!$bytes_written = fwrite($fp, $blob))
248
					throw new Exception("Unable to write data to file $target_file");
249
250
				try {
251
					unlink($_FILES['blob']['tmp_name']);
252
				}catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
253
254
				}
255
256
			}elseif (isset($_POST['blob'])) {
257
				$this->logger->debug(sprintf('Writing %s bytes to file %s starting position %s using POST blob', strlen($_POST['blob']), $target_file, $_POST['start']));
258
				
259
				$blob = $_POST['blob'];
260
261
				if (!$bytes_written = fwrite($fp, $blob))
262
					throw new Exception("Unable to write data to file $target_file");
263
			} else {
264
				throw new Exception("Upload failed, did not receive any binary data");
265
			}
266
			
267
			fclose($fp);
268
		}
269
		
270
		return $bytes_written;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $bytes_written does not seem to be defined for all execution paths leading up to this point.
Loading history...
271
		
272
	}
273
274
	/**
275
	 * Connect to mysql server method
276
	 *
277
	 * @param $remote_mysql_host
278
	 * @param $remote_mysql_user
279
	 * @param $remote_mysql_pass
280
	 * @param $remote_mysql_db
281
	 * @return mysqli
282
	 * @throws Exception
283
	 */
284
	public function mysql_connect($remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db)
285
	{
286
		$this->logger->info(sprintf('Connecting to mysql database %s with %s@%s', $remote_mysql_db, $remote_mysql_user, $remote_mysql_host));
287
288
		$mysqli = new mysqli($remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db);
289
290
		if ($mysqli->connect_error) {
291
			throw new Exception('Connect Error ('.$mysqli->connect_errno.') '
292
				. $mysqli->connect_error);
293
		}
294
		
295
		$mysqli->query("SET sql_mode='';");
296
		$mysqli->query("SET foreign_key_checks = 0;");
297
		if (isset($_REQUEST['charset_of_file']) and $_REQUEST['charset_of_file'])
298
			$mysqli->query("SET NAMES ".$_REQUEST['charset_of_file']."");
299
		else
300
			$mysqli->query("SET NAMES utf8;");
301
			
302
		return $mysqli;	
303
	}
304
305
	/**
306
	 * Restore mysql backup file
307
	 *
308
	 * @throws Exception
309
	 */
310
	public function restore_mysql_backup_action()
311
	{
312
		$mysqldump_file = filter_input(INPUT_POST, 'mysqldump_file', FILTER_SANITIZE_STRING);
313
		$remote_path = filter_input(INPUT_POST, 'remote_path', FILTER_SANITIZE_STRING);
314
		$remote_mysql_user 	= filter_input(INPUT_POST, 'remote_mysql_user', FILTER_SANITIZE_STRING);
315
		$remote_mysql_pass 	= filter_input(INPUT_POST, 'remote_mysql_pass', FILTER_SANITIZE_STRING);
316
		$remote_mysql_db = filter_input(INPUT_POST, 'remote_mysql_db', FILTER_SANITIZE_STRING);
317
		$remote_mysql_host 	= filter_input(INPUT_POST, 'remote_mysql_host', FILTER_SANITIZE_STRING);
318
		$execute_query = trim(stripslashes($_POST['query']));
319
		$error_line = filter_input(INPUT_POST, 'error_line', FILTER_SANITIZE_NUMBER_INT);
0 ignored issues
show
Unused Code introduced by
The assignment to $error_line is dead and can be removed.
Loading history...
320
		$start = filter_input(INPUT_POST, 'start', FILTER_SANITIZE_NUMBER_INT);
321
		
322
		$wp_home_url 		= filter_input(INPUT_POST, 'wp_home_url', FILTER_SANITIZE_STRING);
323
		$remote_restore_url = filter_input(INPUT_POST, 'remote_restore_url', FILTER_SANITIZE_STRING);
324
		
325
		$wp_site_url 		= filter_input(INPUT_POST, 'wp_site_url', FILTER_SANITIZE_STRING);
326
		$restore_site_url 	= filter_input(INPUT_POST, 'restore_site_url', FILTER_SANITIZE_STRING);
327
		
328
		$mysql_backup_file = $remote_path.DS.$mysqldump_file;
329
		
330
		if (!file_exists($mysql_backup_file))
331
			throw new Exception(sprintf("Mysql backup file %s does not exists", $mysql_backup_file));
332
		
333
		
334
		/*if(defined('XCLONER_PLUGIN_ACCESS') && XCLONER_PLUGIN_ACCESS)
335
		{
336
			global $wpdb;
337
			//$mysqli = $this->parent_api->get_xcloner_container()->get_xcloner_database();
338
			$remote_mysql_host 	= $wpdb->dbhost;
339
			$remote_mysql_user 	= $wpdb->dbuser;
340
			$remote_mysql_pass 	= $wpdb->dbpassword;
341
			$remote_mysql_db 	= $wpdb->dbname;
342
		}*/
343
		
344
		{
345
			$mysqli = $this->mysql_connect($remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db);
346
		}
347
		
348
		$line_count = 0;
349
		$query = "";
350
		$return['finished'] = 1;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.
Loading history...
351
		$return['backup_file']	= $mysqldump_file;
352
		$return['backup_size']	= filesize($mysql_backup_file);
353
		
354
		$fp = fopen($mysql_backup_file, "r");
355
		if ($fp)
0 ignored issues
show
introduced by
$fp is of type false|resource, thus it always evaluated to false.
Loading history...
356
		{
357
			$this->logger->info(sprintf("Opening mysql dump file %s at position %s.", $mysql_backup_file, $start));
358
			fseek($fp, $start);
359
			while ($line_count <= $this->process_mysql_records_limit and ($line = fgets($fp)) !== false) {
360
			// process the line read.
361
									
362
				//check if line is comment
363
				if (substr($line, 0, 1) == "#")
364
					continue;
365
				
366
				//check if line is empty	
367
				if ($line == "\n" or trim($line) == "")
368
					continue;
369
					
370
				if (substr($line, strlen($line) - 2, strlen($line)) == ";\n")
371
					$query .= $line;
372
				else {
373
					$query .= $line;
374
					continue;
375
				}
376
				
377
				if ($execute_query)
378
				{
379
					$query = (($execute_query));
380
					$execute_query = "";
381
				}	
382
				
383
				//Doing serialized url replace here
384
				
385
				if ($wp_site_url and $wp_home_url and strlen($wp_home_url) < strlen($wp_site_url))
386
				{
387
					list($wp_home_url, $wp_site_url) = array($wp_site_url, $wp_home_url);
388
					list($remote_restore_url, $restore_site_url) = array($restore_site_url, $remote_restore_url);
389
					
390
				}
391
				
392
				if ($wp_home_url and $remote_restore_url and strpos($query, $wp_home_url) !== false)
393
				{
394
					$query = $this->url_replace($wp_home_url, $remote_restore_url, $query);
395
				}
396
				
397
				if ($wp_site_url and $restore_site_url and strpos($query, $wp_site_url) !== false)
398
				{
399
					$query = $this->url_replace($wp_site_url, $restore_site_url, $query);
400
				}
401
				
402
				if (!$mysqli->query($query) && !stristr($mysqli->error, "Duplicate entry"))
403
				{
404
					//$return['error_line'] = $line_count;
405
					$return['start'] = ftell($fp) - strlen($line);
406
					$return['query_error'] = true;
407
					$return['query'] = $query;
408
					$return['message'] = sprintf("Mysql Error: %s\n", $mysqli->error);
409
					
410
					$this->logger->error($return['message']);
411
					
412
					$this->send_response(418, $return);
413
					//throw new Exception(sprintf("Mysql Error: %s\n Mysql Query: %s", $mysqli->error, $query));
414
				}
415
				//else echo $line;
416
					
417
				$query = "";
418
419
				$line_count++;
420
				
421
			}
422
		}
423
		
424
		$return['start'] = ftell($fp);
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of ftell() does only seem to accept resource, 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

424
		$return['start'] = ftell(/** @scrutinizer ignore-type */ $fp);
Loading history...
425
		
426
		$this->logger->info(sprintf("Executed %s queries of size %s bytes", $line_count, ($return['start'] - $start)));
427
		
428
		if (!feof($fp))
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of feof() does only seem to accept resource, 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

428
		if (!feof(/** @scrutinizer ignore-type */ $fp))
Loading history...
429
		{
430
			$return['finished'] = 0;
431
		} else {
432
			$this->logger->info(sprintf("Mysql Import Done."));
433
		}
434
		
435
		fclose($fp);
0 ignored issues
show
Bug introduced by
It seems like $fp can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, 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

435
		fclose(/** @scrutinizer ignore-type */ $fp);
Loading history...
436
		
437
		$this->send_response(200, $return);
438
	}
439
440
	/**
441
	 * Url replace method inside database backup file
442
	 *
443
	 * @param $search
444
	 * @param $replace
445
	 * @param $query
446
	 * @return mixed|string|string[]|null
447
	 */
448
	private function url_replace($search, $replace, $query)
449
	{
450
		$this->logger->info(sprintf("Doing url replace on query with length %s", strlen($query)), array("QUERY_REPLACE"));
451
		$query = str_replace($search, $replace, $query);
452
		$original_query = $query;
453
		
454
		if ($this->has_serialized($query))
455
		{
456
			$this->logger->info(sprintf("Query contains serialized data, doing serialized size fix"), array("QUERY_REPLACE"));
457
			$query = $this->do_serialized_fix($query);
458
			
459
			if (!$query)
460
			{
461
				$this->logger->info(sprintf("Serialization probably failed here..."), array("QUERY_REPLACE"));
462
				$query = $original_query;
463
			}
464
		}
465
		$this->logger->info(sprintf("New query length is %s", strlen($query)), array("QUERY_REPLACE"));
466
		
467
		return $query;
468
	}
469
470
	/**
471
	 * List backup files method
472
	 *
473
	 * @throws \League\Flysystem\FileNotFoundException
474
	 */
475
	public function list_backup_files_action()
476
	{
477
		$backup_parts = array();
478
		
479
		$source_backup_file = filter_input(INPUT_POST, 'file', FILTER_SANITIZE_STRING);
480
		$start = (int)filter_input(INPUT_POST, 'start', FILTER_SANITIZE_STRING);
481
		$return['part'] = (int)filter_input(INPUT_POST, 'part', FILTER_SANITIZE_STRING);
0 ignored issues
show
Comprehensibility Best Practice introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.
Loading history...
482
		
483
		$backup_file = $source_backup_file;
484
		
485
		if ($this->is_multipart($backup_file))
486
		{
487
			$backup_parts = $this->get_multipart_files($backup_file);
488
			$backup_file = $backup_parts[$return['part']];
489
		}
490
		
491
		try {
492
			$tar = new Tar();
493
			$tar->open($this->backup_storage_dir.DS.$backup_file, $start);
494
		
495
			$data = $tar->contents($this->process_files_limit_list);
496
		}catch (Exception $e)
497
		{
498
			$return['error'] = true;
499
			$return['message'] = $e->getMessage();
500
			$this->send_response(200, $return);
501
		}
502
		
503
		$return['files'] = array();
504
		$return['finished'] = 1;
505
		$return['total_size'] = filesize($this->backup_storage_dir.DS.$backup_file);
506
		$i = 0;
507
		
508
		if (isset($data['extracted_files']) and is_array($data['extracted_files']))
509
		{
510
			foreach ($data['extracted_files'] as $file)
511
			{
512
				$return['files'][$i]['path'] = $file->getPath();
513
				$return['files'][$i]['size'] = $file->getSize();
514
				$return['files'][$i]['mtime'] = date("d M,Y H:i", $file->getMtime());
515
				
516
				$i++;
517
			}
518
		}
519
		
520
		if (isset($data['start']))
521
		{
522
			$return['start'] = $data['start'];
523
			$return['finished'] = 0;	
524
		} else {
525
			if ($this->is_multipart($source_backup_file))
526
			{
527
				$return['start'] = 0;
528
				
529
				++$return['part'];
530
			
531
				if ($return['part'] < sizeof($backup_parts))	
532
					$return['finished'] = 0;
533
				
534
			}
535
		}	
536
		
537
		$this->send_response(200, $return);
538
	}
539
540
	/**
541
	 * Finish backup restore method
542
	 *
543
	 * @throws \League\Flysystem\FileNotFoundException
544
	 */
545
	public function restore_finish_action()
546
	{
547
		$remote_path 		= filter_input(INPUT_POST, 'remote_path', FILTER_SANITIZE_STRING);
548
		
549
		$wp_home_url 		= filter_input(INPUT_POST, 'wp_home_url', FILTER_SANITIZE_STRING);
0 ignored issues
show
Unused Code introduced by
The assignment to $wp_home_url is dead and can be removed.
Loading history...
550
		$remote_restore_url = filter_input(INPUT_POST, 'remote_restore_url', FILTER_SANITIZE_STRING);
551
		
552
		$remote_mysql_user 	= filter_input(INPUT_POST, 'remote_mysql_user', FILTER_SANITIZE_STRING);
553
		$remote_mysql_pass 	= filter_input(INPUT_POST, 'remote_mysql_pass', FILTER_SANITIZE_STRING);
554
		$remote_mysql_db = filter_input(INPUT_POST, 'remote_mysql_db', FILTER_SANITIZE_STRING);
555
		$remote_mysql_host 	= filter_input(INPUT_POST, 'remote_mysql_host', FILTER_SANITIZE_STRING);
556
		
557
		$update_remote_site_url = filter_input(INPUT_POST, 'update_remote_site_url', FILTER_SANITIZE_NUMBER_INT);
558
		$delete_restore_script = filter_input(INPUT_POST, 'delete_restore_script', FILTER_SANITIZE_NUMBER_INT);
559
		$delete_backup_temporary_folder = filter_input(INPUT_POST, 'delete_backup_temporary_folder', FILTER_SANITIZE_NUMBER_INT);
560
				
561
		if ($update_remote_site_url)
562
		{
563
			$mysqli = $this->mysql_connect($remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db);
564
			$this->update_wp_config($remote_path, $remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db);
565
			$this->update_wp_url($remote_path, $remote_restore_url, $mysqli);
566
		}
567
		
568
		if ($delete_backup_temporary_folder)
569
		{
570
			$this->delete_backup_temporary_folder($remote_path);
571
		}
572
		
573
		if (!defined('XCLONER_PLUGIN_ACCESS') || XCLONER_PLUGIN_ACCESS != 1)
574
		{
575
			if ($delete_restore_script)
576
			{
577
				$this->delete_self();
578
			}
579
		}
580
		
581
		$return = "Restore Process Finished.";
582
		$this->send_response(200, $return);
583
	}
584
585
	/**
586
	 * Delete backup temporary folder
587
	 *
588
	 * @param $remote_path
589
	 * @return bool
590
	 */
591
	private function delete_backup_temporary_folder($remote_path)
592
	{
593
		$this->target_adapter = new Local($remote_path, LOCK_EX, 'SKIP_LINKS');
0 ignored issues
show
Bug introduced by
'SKIP_LINKS' of type string is incompatible with the type integer expected by parameter $linkHandling of League\Flysystem\Adapter\Local::__construct(). ( Ignorable by Annotation )

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

593
		$this->target_adapter = new Local($remote_path, LOCK_EX, /** @scrutinizer ignore-type */ 'SKIP_LINKS');
Loading history...
Bug Best Practice introduced by
The property target_adapter does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
594
		$this->target_filesystem = new Filesystem($this->target_adapter, new Config([
0 ignored issues
show
Bug Best Practice introduced by
The property target_filesystem does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
595
				'disable_asserts' => true,
596
			]));
597
			
598
		$mysqldump_list = array();
0 ignored issues
show
Unused Code introduced by
The assignment to $mysqldump_list is dead and can be removed.
Loading history...
599
		$list = $this->target_filesystem->listContents();
600
		
601
		foreach ($list as $file)
602
		{
603
			$matches = array();
604
			
605
			if ($file['type'] == "dir")
606
			{
607
				if (preg_match("/xcloner-(\w*)/", $file['basename'], $matches)) {
608
					$this->logger->info(sprintf('Deleting temporary folder %s', $file['path']));
609
					$this->target_filesystem->deleteDir($file['path']);
610
				}
611
			}
612
		}
613
		
614
		return true;
615
	
616
	}
617
618
	/**
619
	 * Delete restore script method
620
	 *
621
	 * @throws \League\Flysystem\FileNotFoundException
622
	 */
623
	private function delete_self()
624
	{
625
		if ($this->filesystem->has("vendor.phar"))
626
		{
627
			$this->logger->info(sprintf('Deleting vendor.phar'));
628
			$this->filesystem->delete("vendor.phar");
629
		}
630
		if ($this->filesystem->has("vendor"))
631
		{
632
			$this->logger->info(sprintf('Deleting vendor folder'));
633
			$this->filesystem->deleteDir("vendor");
634
		}
635
		if ($this->filesystem->has("xcloner_restore.php"))
636
		{
637
			$this->logger->info(sprintf('Deleting xcloner_restore.php'));
638
			$this->filesystem->delete("xcloner_restore.php");
639
		}
640
		
641
		if ($this->filesystem->has("xcloner_restore.log"))
642
		{
643
			$this->logger->info(sprintf('Deleting xcloner_restore.log'));
644
			$this->filesystem->delete("xcloner_restore.log");
645
		}
646
		
647
		if ($this->filesystem->has($this->get_logger_filename()))
648
		{
649
			$this->logger->info(sprintf('Deleting logger file %s', $this->get_logger_filename()));
650
			$this->filesystem->delete($this->get_logger_filename());
651
		}
652
		
653
	}
654
655
	/**
656
	 * Update Wordpress url in wp-config.php method
657
	 * @param $wp_path
658
	 * @param $url
659
	 * @param mysqli $mysqli
660
	 * @return bool
661
	 * @throws Exception
662
	 */
663
	private function update_wp_url($wp_path, $url, $mysqli)
664
	{
665
		$wp_config = $wp_path.DS."wp-config.php";
666
		
667
		$this->logger->info(sprintf('Updating site url to %s', $url));
668
		
669
		if (file_exists($wp_config))
670
		{
671
			$config = file_get_contents($wp_config);
672
			preg_match("/.*table_prefix.*=.*'(.*)'/i", $config, $matches);
673
			if (isset($matches[1]))
674
				$table_prefix = $matches[1];
675
			else
676
				throw new Exception("Could not load wordpress table prefix from wp-config.php file.");
677
		}
678
		else
679
			throw new Exception("Could not update the SITEURL and HOME, wp-config.php file not found");
680
			
681
		if (!$mysqli->query("update ".$table_prefix."options set option_value='".($url)."' where option_name='home'"))
682
			throw new Exception(sprintf("Could not update the HOME option, error: %s\n", $mysqli->error));
683
		
684
		if (!$mysqli->query("update ".$table_prefix."options set option_value='".($url)."' where option_name='siteurl'"))
685
			throw new Exception(sprintf("Could not update the SITEURL option, error: %s\n", $mysqli->error));
686
		
687
		return true;
688
	}
689
690
	/**
691
	 * Update local wp-config.php file method
692
	 *
693
	 * @param $remote_path
694
	 * @param $remote_mysql_host
695
	 * @param $remote_mysql_user
696
	 * @param $remote_mysql_pass
697
	 * @param $remote_mysql_db
698
	 * @return string
699
	 * @throws Exception
700
	 */
701
	private function update_wp_config($remote_path, $remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db)
702
	{
703
		$wp_config = $remote_path.DS."wp-config.php";
704
		
705
		if (!file_exists($wp_config))
706
		{
707
			throw new Exception("Could not find the wp-config.php in ".$remote_path);
708
		}
709
		
710
		$content = file_get_contents($wp_config);
711
		
712
		$content = preg_replace("/(?<=DB_NAME', ')(.*?)(?='\);)/", $remote_mysql_db, $content);
713
		$content = preg_replace("/(?<=DB_USER', ')(.*?)(?='\);)/", $remote_mysql_user, $content);
714
		$content = preg_replace("/(?<=DB_PASSWORD', ')(.*?)(?='\);)/", $remote_mysql_pass, $content);
715
		$content = preg_replace("/(?<=DB_HOST', ')(.*?)(?='\);)/", $remote_mysql_host, $content);
716
		
717
		$file_perms = fileperms($wp_config);
718
		
719
		chmod($wp_config, 0777);
720
		
721
		$this->logger->info(sprintf('Updating wp-config.php file with the new mysql details'));
722
		
723
		if (!file_put_contents($wp_config, $content))
724
			throw new Exception("Could not write updated config data to ".$wp_config);
725
		
726
		chmod($wp_config, $file_perms);
727
		
728
		return $wp_config;
729
		
730
	}
731
732
	/**
733
	 * List mysqldump database backup files
734
	 *
735
	 */
736
	public function list_mysqldump_backups_action()
737
	{
738
		$source_backup_file = filter_input(INPUT_POST, 'backup_file', FILTER_SANITIZE_STRING);
739
		$remote_path = filter_input(INPUT_POST, 'remote_path', FILTER_SANITIZE_STRING);
740
	
741
		$hash = $this->get_hash_from_backup($source_backup_file);	
742
		
743
		$this->target_adapter = new Local($remote_path, LOCK_EX, 'SKIP_LINKS');
0 ignored issues
show
Bug Best Practice introduced by
The property target_adapter does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Bug introduced by
'SKIP_LINKS' of type string is incompatible with the type integer expected by parameter $linkHandling of League\Flysystem\Adapter\Local::__construct(). ( Ignorable by Annotation )

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

743
		$this->target_adapter = new Local($remote_path, LOCK_EX, /** @scrutinizer ignore-type */ 'SKIP_LINKS');
Loading history...
744
		$this->target_filesystem = new Filesystem($this->target_adapter, new Config([
0 ignored issues
show
Bug Best Practice introduced by
The property target_filesystem does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
745
				'disable_asserts' => true,
746
			]));
747
			
748
		$mysqldump_list = array();
749
		$list = $this->target_filesystem->listContents();
750
		
751
		foreach ($list as $file)
752
		{
753
			$matches = array();
754
			
755
			if ($file['type'] == "dir")
756
			{
757
				if (preg_match("/xcloner-(\w*)/", $file['basename'], $matches))
758
				{
759
					$files = $this->target_filesystem->listContents($file['basename']);
760
					foreach ($files as $file)
0 ignored issues
show
Comprehensibility Bug introduced by
$file is overwriting a variable from outer foreach loop.
Loading history...
761
					{
762
						if ($file['extension'] == "sql")
763
						{
764
							$this->logger->info(sprintf('Found %s mysql backup file', $file['path']));
765
							$mysqldump_list[$file['path']]['path'] = $file['path'];
766
							$mysqldump_list[$file['path']]['size'] = $file['size'];
767
							$mysqldump_list[$file['path']]['timestamp'] = date("d M,Y H:i", $file['timestamp']);
768
							
769
							if ($hash and $hash == $matches[1])
770
								$mysqldump_list[$file['path']]['selected'] = "selected";
771
							else
772
								$mysqldump_list[$file['path']]['selected'] = "";	
773
						}
774
					}
775
				}
776
			}	
777
		}
778
		
779
		$this->sort_by($mysqldump_list, 'timestamp', 'desc');
780
		$return['files'] = $mysqldump_list;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.
Loading history...
781
		
782
		$this->send_response(200, $return);
783
	}
784
785
	/**
786
	 * Get backup hash method
787
	 *
788
	 * @param $backup_file
789
	 * @return false|string
790
	 */
791
	private function get_hash_from_backup($backup_file)
792
	{
793
		if (!$backup_file)
794
			return false;
795
			
796
		$result = preg_match("/-(\w*)./", substr($backup_file, strlen($backup_file) - 10, strlen($backup_file)), $matches);
797
		
798
		if ($result and isset($matches[1]))
799
			return ($matches[1]);
800
		
801
		return false;
802
	}
803
804
	/**
805
	 * List backup archives found on local system
806
	 *
807
	 * @throws \League\Flysystem\FileNotFoundException
808
	 */
809
	public function list_backup_archives_action()
810
	{
811
		$local_backup_file = filter_input(INPUT_POST, 'local_backup_file', FILTER_SANITIZE_STRING);
812
		$list = $this->filesystem->listContents();
813
		
814
		$backup_files = array();
815
		$parents = array();
816
		
817
		foreach ($list as $file_info)
818
		{
819
			$data = array();
820
			
821
			if (isset($file_info['extension']) and $file_info['extension'] == "csv")
822
			{
823
				$lines = explode(PHP_EOL, $this->filesystem->read($file_info['path']));
0 ignored issues
show
Bug introduced by
It seems like $this->filesystem->read($file_info['path']) can also be of type false; however, parameter $string of explode() 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

823
				$lines = explode(PHP_EOL, /** @scrutinizer ignore-type */ $this->filesystem->read($file_info['path']));
Loading history...
824
				foreach ($lines as $line)
825
					if ($line)
826
					{
827
						$data = str_getcsv($line);
828
						if (is_array($data)) {
829
							$parents[$data[0]] = $file_info['path'];
830
							$file_info['childs'][] = $data;
831
							$file_info['size'] += $data[2];
832
						}
833
					}
834
						
835
			}
836
			
837
			if ($file_info['type'] == 'file' and isset($file_info['extension']) and in_array($file_info['extension'], $this->backup_archive_extensions))
838
				$backup_files[$file_info['path']] = $file_info;
839
		}
840
		
841
		$new_list = array();
842
		
843
		foreach ($backup_files as $key=>$file_info)
844
		{
845
			if (isset($parents[$file_info['path']]))
846
				$backup_files[$key]['parent'] = $parents[$file_info['path']];
847
			else {
848
				
849
				if ($local_backup_file and ($file_info['basename'] == $local_backup_file))
850
					$file_info['selected'] = 'selected';
851
				
852
				$this->logger->info(sprintf('Found %s backup file', $file_info['path']));
853
					
854
				$new_list[$key] = $file_info;
855
			}
856
				
857
		}
858
		
859
		$this->sort_by($new_list, "timestamp", "desc");
860
		
861
		$return['files'] = $new_list;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.
Loading history...
862
		
863
		$this->send_response(200, $return);
864
		
865
	}
866
867
	/**
868
	 * Restore backup archive to local path
869
	 *
870
	 * @throws \League\Flysystem\FileNotFoundException
871
	 * @throws \splitbrain\PHPArchive\ArchiveIOException
872
	 */
873
	public function restore_backup_to_path_action()
874
	{
875
		$source_backup_file = filter_input(INPUT_POST, 'backup_file', FILTER_SANITIZE_STRING);
876
		$remote_path = filter_input(INPUT_POST, 'remote_path', FILTER_SANITIZE_STRING);
877
		$include_filter_files 	= filter_input(INPUT_POST, 'filter_files', FILTER_SANITIZE_STRING);
878
		$exclude_filter_files 	= "";
879
		$start = filter_input(INPUT_POST, 'start', FILTER_SANITIZE_NUMBER_INT);
880
		$return['part'] = (int)filter_input(INPUT_POST, 'part', FILTER_SANITIZE_NUMBER_INT);
0 ignored issues
show
Comprehensibility Best Practice introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.
Loading history...
881
		$return['processed'] 	= (int)filter_input(INPUT_POST, 'processed', FILTER_SANITIZE_NUMBER_INT);
882
				
883
		$this->target_adapter = new Local($remote_path, LOCK_EX, 'SKIP_LINKS');
0 ignored issues
show
Bug Best Practice introduced by
The property target_adapter does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Bug introduced by
'SKIP_LINKS' of type string is incompatible with the type integer expected by parameter $linkHandling of League\Flysystem\Adapter\Local::__construct(). ( Ignorable by Annotation )

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

883
		$this->target_adapter = new Local($remote_path, LOCK_EX, /** @scrutinizer ignore-type */ 'SKIP_LINKS');
Loading history...
884
		$this->target_filesystem = new Filesystem($this->target_adapter, new Config([
0 ignored issues
show
Bug Best Practice introduced by
The property target_filesystem does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
885
				'disable_asserts' => true,
886
			]));
887
		
888
		$backup_file = $source_backup_file;
889
		
890
		$return['finished'] = 1;
891
		$return['extracted_files'] = array();
892
		$return['total_size'] = $this->get_backup_size($backup_file);
893
		
894
		$backup_archive = new Tar();
895
		if ($this->is_multipart($backup_file))
896
		{
897
			if (!$return['part'])
898
				$return['processed'] += $this->filesystem->getSize($backup_file);
899
				
900
			$backup_parts = $this->get_multipart_files($backup_file);
901
			$backup_file = $backup_parts[$return['part']];	
902
		}	
903
		
904
		$this->logger->info(sprintf('Opening backup archive %s at position %s', $backup_file, $start));
905
		$backup_archive->open($this->backup_storage_dir.DS.$backup_file, $start);
906
907
		$data = $backup_archive->extract($remote_path, '', $exclude_filter_files, $include_filter_files, $this->process_files_limit);
908
		
909
		if (isset($data['extracted_files']))
910
		{
911
			foreach ($data['extracted_files'] as $spl_fileinfo)
912
			{
913
				$this->logger->info(sprintf('Extracted %s file', $spl_fileinfo->getPath()));
914
				$return['extracted_files'][] = $spl_fileinfo->getPath()." (".$spl_fileinfo->getSize()." bytes)";
915
			}
916
		}
917
		
918
		if (isset($data['start']))
919
		//if(isset($data['start']) and $data['start'] <= $this->filesystem->getSize($backup_file))
920
		{
921
			$return['finished'] = 0;
922
			$return['start'] = $data['start'];
923
		} else {
924
			
925
			$return['processed'] += $start;
926
			
927
			if ($this->is_multipart($source_backup_file))
928
			{
929
				$return['start'] = 0;
930
				
931
				++$return['part'];
932
			
933
				if ($return['part'] < sizeof($backup_parts))	
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $backup_parts does not seem to be defined for all execution paths leading up to this point.
Loading history...
934
					$return['finished'] = 0;
935
				
936
			}
937
		}
938
		
939
		if ($return['finished'])
940
			$this->logger->info(sprintf('Done extracting %s', $source_backup_file));
941
		
942
		$return['backup_file'] = $backup_file;
943
		
944
		$this->send_response(200, $return);
945
	}
946
947
	/**
948
	 * Get current directory method
949
	 */
950
	public function get_current_directory_action()
951
	{	
952
		global $wpdb;
953
		
954
		$restore_script_url = filter_input(INPUT_POST, 'restore_script_url', FILTER_SANITIZE_STRING);
955
		
956
		$pathinfo = pathinfo(__FILE__);
957
		
958
		$suffix = "";
959
		$return['remote_mysql_host'] 	= "localhost";
0 ignored issues
show
Comprehensibility Best Practice introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.
Loading history...
960
		$return['remote_mysql_user'] 	= "";
961
		$return['remote_mysql_pass'] 	= "";
962
		$return['remote_mysql_db'] = "";
963
		
964
		if (defined('XCLONER_PLUGIN_ACCESS') && XCLONER_PLUGIN_ACCESS)
965
		{
966
			$return['dir'] = realpath(get_home_path().DS.$suffix);
0 ignored issues
show
Bug introduced by
The function get_home_path was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

966
			$return['dir'] = realpath(/** @scrutinizer ignore-call */ get_home_path().DS.$suffix);
Loading history...
967
			$return['restore_script_url'] = get_site_url();
0 ignored issues
show
Bug introduced by
The function get_site_url was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

967
			$return['restore_script_url'] = /** @scrutinizer ignore-call */ get_site_url();
Loading history...
968
			$return['remote_mysql_host'] 	= $wpdb->dbhost;
969
			$return['remote_mysql_user'] 	= $wpdb->dbuser;
970
			$return['remote_mysql_pass'] 	= $wpdb->dbpassword;
971
			$return['remote_mysql_db'] = $wpdb->dbname;
972
		}
973
		else {
974
			$return['dir'] = ($pathinfo['dirname']).DS.$suffix;
975
			$return['restore_script_url'] = str_replace($pathinfo['basename'], "", $restore_script_url).$suffix;
976
		}	
977
		
978
		$this->logger->info(sprintf('Determining current url as %s and path as %s', $return['dir'], $return['restore_script_url']));
979
		
980
		$this->send_response(200, $return);
981
	}
982
983
	/**
984
	 * Check current filesystem
985
	 *
986
	 * @throws Exception
987
	 */
988
	public function check_system()
989
	{
990
		//check if i can write
991
		$tmp_file = md5(time());
992
		if (!file_put_contents($tmp_file, "++"))
993
			throw new Exception("Could not write to new host");
994
		
995
		if (!unlink($tmp_file))
996
			throw new Exception("Could not delete temporary file from new host");
997
		
998
		$max_upload      = $this->return_bytes((ini_get('upload_max_filesize')));
999
		$max_post        = $this->return_bytes((ini_get('post_max_size')));
1000
1001
		$return['max_upload_size'] = min($max_upload, $max_post); // bytes
0 ignored issues
show
Comprehensibility Best Practice introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.
Loading history...
1002
		$return['status'] = true;
1003
		
1004
		$this->logger->info(sprintf('Current filesystem max upload size is %s bytes', $return['max_upload_size']));
1005
		
1006
		$this->send_response(200, $return);
1007
	}
1008
1009
	/**
1010
	 * Return bytes from human readable value
1011
	 *
1012
	 * @param string $val
1013
	 * @return int
1014
	 *
1015
	 */
1016
	private function return_bytes($val) {
1017
		$numeric_val = (int)trim($val);
1018
		$last = strtolower($val[strlen($val) - 1]);
1019
		switch ($last) {
1020
			// The 'G' modifier is available since PHP 5.1.0
1021
			case 'g':
1022
				$numeric_val *= 1024;
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment if this fall-through is intended.
Loading history...
1023
			case 'm':
1024
				$numeric_val *= 1024;
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment if this fall-through is intended.
Loading history...
1025
			case 'k':
1026
				$numeric_val *= 1024;
1027
		}
1028
1029
		return $numeric_val;
1030
	}
1031
1032
	/**
1033
	 * Check if backup archive os multipart
1034
	 *
1035
	 * @param $backup_name
1036
	 * @return bool
1037
	 */
1038
	public function is_multipart($backup_name)
1039
	{
1040
		if (stristr($backup_name, "-multipart"))
1041
			return true;
1042
		
1043
		return false;	
1044
	}
1045
1046
	/**
1047
	 * Get backup archive size
1048
	 *
1049
	 * @param $backup_name
1050
	 * @return bool|false|int
1051
	 * @throws \League\Flysystem\FileNotFoundException
1052
	 */
1053
	public function get_backup_size($backup_name)
1054
	{
1055
		$backup_size = $this->filesystem->getSize($backup_name);
1056
		if ($this->is_multipart($backup_name))
1057
		{
1058
			$backup_parts = $this->get_multipart_files($backup_name);
1059
			foreach ($backup_parts as $part_file)
1060
				$backup_size += $this->filesystem->getSize($part_file);
1061
		}
1062
		
1063
		return $backup_size;
1064
	}
1065
1066
	/**
1067
	 * Get multipart backup files list
1068
	 * @param $backup_name
1069
	 * @return array
1070
	 * @throws \League\Flysystem\FileNotFoundException
1071
	 */
1072
	public function get_multipart_files($backup_name)
1073
	{
1074
		$files = array();
1075
		
1076
		if ($this->is_multipart($backup_name))
1077
		{
1078
			$lines = explode(PHP_EOL, $this->filesystem->read($backup_name));
0 ignored issues
show
Bug introduced by
It seems like $this->filesystem->read($backup_name) can also be of type false; however, parameter $string of explode() 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

1078
			$lines = explode(PHP_EOL, /** @scrutinizer ignore-type */ $this->filesystem->read($backup_name));
Loading history...
1079
			foreach ($lines as $line)
1080
			{
1081
				if ($line)
1082
				{
1083
					$data = str_getcsv($line);
1084
					$files[] = $data[0];
1085
				}
1086
			}
1087
		}
1088
		
1089
		return $files;
1090
	}
1091
1092
	/**
1093
	 * Sort_by method
1094
	 *
1095
	 * @param $array
1096
	 * @param string $field
1097
	 * @param string $direction
1098
	 * @return bool
1099
	 */
1100
	private function sort_by(&$array, $field, $direction = 'asc')
1101
	{
1102
		$direction = strtolower($direction);
1103
1104
		usort($array,
1105
1106
			/**
1107
			 * @param string $b
1108
			 */
1109
			function($a, $b) use($field, $direction){
1110
1111
				$a = $a[$field];
1112
				$b = $b[$field];
1113
1114
				if ($a == $b)
1115
				{
1116
					return 0;
1117
				}
1118
1119
				if ($direction == 'desc') {
1120
					if ($a > $b) {
1121
						return -1;
1122
					}
1123
					else {
1124
						return 1;
1125
					}
1126
				} else {
1127
					if ($a < $b) {
1128
						return -1;
1129
					}
1130
					else {
1131
						return 1;
1132
					}
1133
				}
1134
1135
				//return ($a.($direction == 'desc' ? '>' : '<').$b) ? -1 : 1;
1136
			}
1137
		);
1138
1139
		return true;
1140
	}
1141
1142
	/**
1143
	 * Send response method
1144
	 *
1145
	 * @param int $status
1146
	 * @param $response
1147
	 */
1148
	public static function send_response($status = 200, $response)
1149
	{
1150
		header("Access-Control-Allow-Origin: *");
1151
		header("HTTP/1.1 200");
1152
		header('Content-Type: application/json');
1153
		$return['status'] = $status;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.
Loading history...
1154
		$return['statusText'] = $response;
1155
		
1156
		if (isset($response['error']) && $response['error'])
1157
		{
1158
			$return['statusText'] = $response['message'];
1159
			$return['error'] = true;
1160
		}elseif ($status != 200 and $status != 418)
1161
		{
1162
			$return['error'] = true;
1163
			$return['message'] = $response;
1164
		}
1165
		
1166
		echo json_encode($return);
1167
		exit;
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...
1168
	}
1169
1170
	/**
1171
	 * Serialize fix methods below for mysql query lines
1172
	 *
1173
	 * @param $query
1174
	 * @return string
1175
	 */
1176
	 
1177
	function do_serialized_fix($query)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1178
	{
1179
		$query = str_replace(array("\\n", "\\r", "\\'"), array("", "", "\""), ($query));
1180
		
1181
		return preg_replace_callback('!s:(\d+):([\\\\]?"[\\\\]?"|[\\\\]?"((.*?)[^\\\\])[\\\\]?");!', function($m) {
1182
				  $data = "";
0 ignored issues
show
Unused Code introduced by
The assignment to $data is dead and can be removed.
Loading history...
1183
				  	
1184
				  if (!isset($m[3]))
1185
					$m[3] = "";
1186
					
1187
					$data = 's:'.strlen(($m[3])).':\"'.($m[3]).'\";';
1188
				  //return $this->unescape_quotes($data);
1189
	              
1190
				  return $data;
1191
				}, $query);
1192
	}
1193
1194
	/**
1195
	 * Unescape quotes method
1196
	 *
1197
	 * @param $value
1198
	 * @return mixed
1199
	 */
1200
	private function unescape_quotes($value) {
1201
		return str_replace('\"', '"', $value);
1202
	}
1203
1204
	/**
1205
	 * Unescape mysql method
1206
	 *
1207
	 * @param $value
1208
	 * @return mixed
1209
	 */
1210
	private function unescape_mysql($value) {
1211
		return str_replace(array("\\\\", "\\0", "\\n", "\\r", "\Z", "\'", '\"'),
1212
						   array("\\", "\0", "\n", "\r", "\x1a", "'", '"'), 
1213
						   $value);
1214
	}
1215
1216
	/**
1217
	 * Check if string is in serialized format
1218
	 *
1219
	 * @param $s
1220
	 * @return bool
1221
	 */
1222
	private function has_serialized($s)
1223
	{
1224
		if (
1225
			stristr($s, '{') !== false &&
1226
			stristr($s, '}') !== false &&
1227
			stristr($s, ';') !== false &&
1228
			stristr($s, ':') !== false
1229
			) {
1230
			return true;
1231
		} else {
1232
			return false;
1233
		}
1234
1235
	}
1236
}
1237
1238