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.
Completed
Push — master ( e65d67...dc9fa8 )
by Liuta
03:08
created

Xcloner_Restore::__construct()   C

Complexity

Conditions 8
Paths 16

Size

Total Lines 38
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 18
nc 16
nop 1
dl 0
loc 38
rs 5.3846
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 5 and the first side effect is on line 17.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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'))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
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
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
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
	public function __construct($parent_api = "")
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
111
	{
112
		register_shutdown_function(array($this, 'exception_handler'));
113
114
		if(defined('XCLONER_PLUGIN_ACCESS') && XCLONER_PLUGIN_ACCESS)
115
		{
116
			$dir = get_option("xcloner_store_path");
117
		}
118
		
119
		if(!isset($dir) || !$dir){
120
			$dir = dirname(__FILE__);
121
		}
122
		
123
		$this->parent_api = $parent_api;
124
		
125
		$this->backup_storage_dir = $dir;
126
		
127
		$this->adapter = new Local($dir ,LOCK_EX, 'SKIP_LINKS');
128
		$this->filesystem = new Filesystem($this->adapter, new Config([
129
				'disable_asserts' => true,
130
			]));
131
			
132
		$this->logger = new Logger('xcloner_restore');
133
		
134
		$logger_path = $this->get_logger_filename();
135
		
136
		if(!is_writeable($logger_path) and !touch($logger_path))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
137
		{
138
			$logger_path = "php://stderr";
139
		}
140
		
141
		$this->logger->pushHandler(new StreamHandler($logger_path, Logger::DEBUG));
142
		
143
		if(isset($_POST['API_ID'])){
144
			$this->logger->info("Processing ajax request ID ".substr(filter_input(INPUT_POST, 'API_ID', FILTER_SANITIZE_STRING), 0 , 15));
145
		}
146
147
	}
148
	
149
	public function exception_handler() {
150
		
151
		$error = error_get_last();
152
		
153
		if($error['type'] and $this->logger)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
154
		{
155
			$this->logger->info($this->friendly_error_type ($error['type']).": ".var_export($error, true));
156
		}
157
	
158
	}
159
	
160 View Code Duplication
	private function friendly_error_type($type) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
161
	    static $levels=null;
162
	    if ($levels===null) {
163
	        $levels=[];
164
	        foreach (get_defined_constants() as $key=>$value) {
165
	            if (strpos($key,'E_')!==0) {continue;}
166
					$levels[$value]= $key; //substr($key,2);
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
167
	        }
168
	    }
169
	    return (isset($levels[$type]) ? $levels[$type] : "Error #{$type}");
170
	}
171
	
172
	public function get_logger_filename()
173
	{
174
		$filename = $this->backup_storage_dir .DS. "xcloner_restore.log";
175
		
176
		return $filename;
177
	}
178
	
179
	public function init()
0 ignored issues
show
Coding Style introduced by
init uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
180
	{
181
		if(isset($_POST['xcloner_action']) and $_POST['xcloner_action'])
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
182
		{
183
			$method = filter_input(INPUT_POST, 'xcloner_action', FILTER_SANITIZE_STRING);
184
			
185
			//$method = "list_backup_archives";
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
186
			
187
			$method .= "_action";
188
			
189
			if(method_exists($this, $method))
190
			{
191
				$this->logger->debug(sprintf('Starting action %s', $method));
192
				return call_user_func(array($this, $method));
193
				
194
			}else{
195
				throw new Exception($method ." does not exists");
196
				}
197
		}
198
		
199
		return $this->check_system();
200
	}
201
	
202
	public function write_file_action()
0 ignored issues
show
Coding Style introduced by
write_file_action uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
write_file_action uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
203
	{
204
		if(isset($_POST['file']))
205
		{
206
			$target_file = filter_input(INPUT_POST, 'file', FILTER_SANITIZE_STRING);
207
			
208
			if(!$_POST['start'])
209
				$fp = fopen($target_file, "wb+");
210
			else
211
				$fp = fopen($target_file, "ab+");	
212
			
213
			if(!$fp)
214
				throw new Exception("Unable to open $target_file file for writing");
215
			
216
			fseek($fp, $_POST['start']);
217
			
218
			if(isset($_FILES['blob']))
219
			{
220
				$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']));
221
				
222
				$blob = file_get_contents($_FILES['blob']['tmp_name']);
223
				
224
				if(!$bytes_written = fwrite($fp, $blob))
225
					throw new Exception("Unable to write data to file $target_file");
226
				
227
				@unlink($_FILES['blob']['tmp_name']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
228
			}elseif(isset($_POST['blob'])){
229
				$this->logger->debug(sprintf('Writing %s bytes to file %s starting position %s using POST blob', strlen($_POST['blob']), $target_file, $_POST['start']));
230
				
231
				$blob = $_POST['blob'];
232
233
				if(!$bytes_written = fwrite($fp, $blob))
234
					throw new Exception("Unable to write data to file $target_file");
235
			}else{
236
				throw new Exception("Upload failed, did not receive any binary data");
237
			}
238
			
239
			fclose($fp);
240
		}
241
		
242
		return $bytes_written;
0 ignored issues
show
Bug introduced by
The variable $bytes_written does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
243
		
244
	}
245
	
246
	public function mysql_connect($remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db )
0 ignored issues
show
Coding Style introduced by
mysql_connect uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
247
	{
248
		$this->logger->info(sprintf('Connecting to mysql database %s with %s@%s', $remote_mysql_db, $remote_mysql_user, $remote_mysql_host));
249
250
		$mysqli = new mysqli($remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db);
251
252
		if ($mysqli->connect_error) {
253
			throw new Exception('Connect Error (' . $mysqli->connect_errno . ') '
254
				. $mysqli->connect_error);
255
		}
256
		
257
		$mysqli->query("SET sql_mode='';");
258
		$mysqli->query("SET foreign_key_checks = 0;");
259
		if(isset($_REQUEST['charset_of_file']) and $_REQUEST['charset_of_file'])
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
260
			$mysqli->query("SET NAMES ".$_REQUEST['charset_of_file']."");
261
		else
262
			$mysqli->query("SET NAMES utf8;");
263
			
264
		return $mysqli;	
265
	}
266
	
267
	public function restore_mysql_backup_action()
0 ignored issues
show
Coding Style introduced by
restore_mysql_backup_action uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
268
	{
269
		$mysqldump_file 	= filter_input(INPUT_POST, 'mysqldump_file', FILTER_SANITIZE_STRING);
270
		$remote_path 		= filter_input(INPUT_POST, 'remote_path', FILTER_SANITIZE_STRING);
271
		$remote_mysql_user 	= filter_input(INPUT_POST, 'remote_mysql_user', FILTER_SANITIZE_STRING);
272
		$remote_mysql_pass 	= filter_input(INPUT_POST, 'remote_mysql_pass', FILTER_SANITIZE_STRING);
273
		$remote_mysql_db 	= filter_input(INPUT_POST, 'remote_mysql_db', FILTER_SANITIZE_STRING);
274
		$remote_mysql_host 	= filter_input(INPUT_POST, 'remote_mysql_host', FILTER_SANITIZE_STRING);
275
		$execute_query 		= trim(stripslashes($_POST['query']));
276
		$error_line			= filter_input(INPUT_POST, 'error_line', FILTER_SANITIZE_NUMBER_INT);
0 ignored issues
show
Unused Code introduced by
$error_line is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
277
		$start			 	= filter_input(INPUT_POST, 'start', FILTER_SANITIZE_NUMBER_INT);
278
		
279
		$wp_home_url 		= filter_input(INPUT_POST, 'wp_home_url', FILTER_SANITIZE_STRING);
280
		$remote_restore_url = filter_input(INPUT_POST, 'remote_restore_url', FILTER_SANITIZE_STRING);
281
		
282
		$wp_site_url 		= filter_input(INPUT_POST, 'wp_site_url', FILTER_SANITIZE_STRING);
283
		$restore_site_url 	= filter_input(INPUT_POST, 'restore_site_url', FILTER_SANITIZE_STRING);
284
		
285
		$mysql_backup_file = $remote_path.DS.$mysqldump_file;
286
		
287
		if(!file_exists($mysql_backup_file))
288
			throw new Exception(sprintf("Mysql backup file %s does not exists",$mysql_backup_file));
289
		
290
		
291
		/*if(defined('XCLONER_PLUGIN_ACCESS') && XCLONER_PLUGIN_ACCESS)
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
292
		{
293
			global $wpdb;
294
			//$mysqli = $this->parent_api->get_xcloner_container()->get_xcloner_database();
295
			$remote_mysql_host 	= $wpdb->dbhost;
296
			$remote_mysql_user 	= $wpdb->dbuser;
297
			$remote_mysql_pass 	= $wpdb->dbpassword;
298
			$remote_mysql_db 	= $wpdb->dbname;
299
		}*/
300
		
301
		{
302
			$mysqli = $this->mysql_connect($remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db );
303
		}
304
		
305
		$line_count = 0;
306
		$query = "";
307
		$return['finished'] = 1;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
308
		$return['backup_file']	= $mysqldump_file;
309
		$return['backup_size']	= filesize($mysql_backup_file);
310
		
311
		$fp = fopen($mysql_backup_file, "r");
312
		if($fp)
313
		{
314
			$this->logger->info(sprintf("Opening mysql dump file %s at position %s.", $mysql_backup_file, $start));
315
			fseek($fp, $start);
316
			while ($line_count <= $this->process_mysql_records_limit and ($line = fgets($fp)) !== false) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
317
			// process the line read.
318
									
319
				//check if line is comment
320
				if(substr($line, 0, 1) == "#")
321
					continue;
322
				
323
				//check if line is empty	
324
				if($line == "\n" or trim($line) == "")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
325
					continue;
326
					
327
				if(substr($line, strlen($line)-2, strlen($line)) == ";\n")
328
					$query .= $line;
329
				else{
330
					$query .= $line;
331
					continue;
332
				}
333
				
334
				if($execute_query)
335
				{
336
					$query  = (($execute_query));
337
					$execute_query = "";
338
				}	
339
				
340
				//Doing serialized url replace here
341
				
342
				if($wp_site_url and $wp_home_url and strlen($wp_home_url) < strlen($wp_site_url))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
343
				{
344
					list($wp_home_url,$wp_site_url) 			= array($wp_site_url,$wp_home_url);
345
					list($remote_restore_url,$restore_site_url) = array($restore_site_url,$remote_restore_url);
346
					
347
				}
348
				
349
				if($wp_home_url and $remote_restore_url and strpos($query, $wp_home_url) !== false)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
350
				{
351
					$query = $this->url_replace($wp_home_url, $remote_restore_url, $query);
352
				}
353
				
354
				if($wp_site_url and $restore_site_url and strpos($query, $wp_site_url) !== false)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
355
				{
356
					$query = $this->url_replace($wp_site_url, $restore_site_url, $query);
357
				}
358
				
359
				if(!$mysqli->query($query) && !stristr($mysqli->error,"Duplicate entry"))
360
				{
361
					//$return['error_line'] = $line_count;
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
362
					$return['start'] = ftell($fp)-strlen($line);
363
					$return['query_error'] = true;
364
					$return['query'] = $query;
365
					$return['message'] = sprintf("Mysql Error: %s\n", $mysqli->error);
366
					
367
					$this->logger->error($return['message']);
368
					
369
					$this->send_response(418, $return);
370
					//throw new Exception(sprintf("Mysql Error: %s\n Mysql Query: %s", $mysqli->error, $query));
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
371
				}
372
				//else echo $line;
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
373
					
374
				$query = "";
375
376
				$line_count++;
377
				
378
			}
379
		}
380
		
381
		$return['start'] = ftell($fp);
382
		
383
		$this->logger->info(sprintf("Executed %s queries of size %s bytes", $line_count, ($return['start']-$start)));
384
		
385
		if(!feof($fp))
386
		{
387
			$return['finished'] = 0;
388
		}else{
389
			$this->logger->info(sprintf("Mysql Import Done."));
390
		}
391
		
392
		fclose($fp);
393
		
394
		$this->send_response(200, $return);
395
	}
396
	
397
	private function url_replace($search, $replace, $query)
398
	{
399
		$this->logger->info(sprintf("Doing url replace on query with length %s", strlen($query)), array("QUERY_REPLACE"));
400
		$query = str_replace($search, $replace, $query);
401
		$original_query = $query;
402
		
403
		if($this->has_serialized($query))
404
		{
405
			$this->logger->info(sprintf("Query contains serialized data, doing serialized size fix"), array("QUERY_REPLACE"));
406
			$query = $this->do_serialized_fix($query);
407
			
408
			if(!$query)
409
			{
410
				$this->logger->info(sprintf("Serialization probably failed here..."), array("QUERY_REPLACE"));
411
				$query = $original_query;
412
			}
413
		}
414
		$this->logger->info(sprintf("New query length is %s", strlen($query)), array("QUERY_REPLACE"));
415
		
416
		return $query;
417
	}
418
	
419
	public function list_backup_files_action()
420
	{
421
		$backup_parts = array();
422
		
423
		$source_backup_file = filter_input(INPUT_POST, 'file', FILTER_SANITIZE_STRING);
424
		$start 				= (int)filter_input(INPUT_POST, 'start', FILTER_SANITIZE_STRING);
425
		$return['part'] 	= (int)filter_input(INPUT_POST, 'part', FILTER_SANITIZE_STRING);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
426
		
427
		$backup_file = $source_backup_file;
428
		
429 View Code Duplication
		if($this->is_multipart($backup_file))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
430
		{
431
			$backup_parts = $this->get_multipart_files($backup_file);
432
			$backup_file = $backup_parts[$return['part']];
433
		}
434
		
435
		try{
436
			$tar = new Tar();
437
			$tar->open($this->backup_storage_dir.DS.$backup_file, $start);
0 ignored issues
show
Unused Code introduced by
The call to Tar::open() has too many arguments starting with $start.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
438
		
439
			$data = $tar->contents($this->process_files_limit_list);
0 ignored issues
show
Unused Code introduced by
The call to Tar::contents() has too many arguments starting with $this->process_files_limit_list.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
440
		}catch(Exception $e)
441
		{
442
			$return['error'] = true;
443
			$return['message'] = $e->getMessage();
444
			$this->send_response(200, $return);
445
		}
446
		
447
		$return['files'] 		= array();
448
		$return['finished'] 	= 1;
449
		$return['total_size'] 	= filesize($this->backup_storage_dir.DS.$backup_file);
450
		$i = 0;
451
		
452
		if(isset($data['extracted_files']) and is_array($data['extracted_files']))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
453
		{
454
			foreach($data['extracted_files'] as $file)
455
			{
456
				$return['files'][$i]['path'] = $file->getPath();
457
				$return['files'][$i]['size'] = $file->getSize();
458
				$return['files'][$i]['mtime'] = date("d M,Y H:i", $file->getMtime());
459
				
460
				$i++;
461
			}
462
		}
463
		
464 View Code Duplication
		if(isset($data['start']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
465
		{
466
			$return['start'] = $data['start'];
467
			$return['finished'] = 0;	
468
		}else{
469
			if($this->is_multipart($source_backup_file))
470
			{
471
				$return['start'] = 0;
472
				
473
				++$return['part'];
474
			
475
				if($return['part'] < sizeof($backup_parts))	
476
					$return['finished'] = 0;
477
				
478
			}
479
		}	
480
		
481
		$this->send_response(200, $return);
482
	}
483
	
484
	public function restore_finish_action()
485
	{
486
		$remote_path 		= filter_input(INPUT_POST, 'remote_path', FILTER_SANITIZE_STRING);
487
		
488
		$wp_home_url 		= filter_input(INPUT_POST, 'wp_home_url', FILTER_SANITIZE_STRING);
0 ignored issues
show
Unused Code introduced by
$wp_home_url is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
489
		$remote_restore_url = filter_input(INPUT_POST, 'remote_restore_url', FILTER_SANITIZE_STRING);
490
		
491
		$remote_mysql_user 	= filter_input(INPUT_POST, 'remote_mysql_user', FILTER_SANITIZE_STRING);
492
		$remote_mysql_pass 	= filter_input(INPUT_POST, 'remote_mysql_pass', FILTER_SANITIZE_STRING);
493
		$remote_mysql_db 	= filter_input(INPUT_POST, 'remote_mysql_db', FILTER_SANITIZE_STRING);
494
		$remote_mysql_host 	= filter_input(INPUT_POST, 'remote_mysql_host', FILTER_SANITIZE_STRING);
495
		
496
		$update_remote_site_url			 	= filter_input(INPUT_POST, 'update_remote_site_url', FILTER_SANITIZE_NUMBER_INT);
497
		$delete_restore_script			 	= filter_input(INPUT_POST, 'delete_restore_script', FILTER_SANITIZE_NUMBER_INT);
498
		$delete_backup_temporary_folder		= filter_input(INPUT_POST, 'delete_backup_temporary_folder', FILTER_SANITIZE_NUMBER_INT);
499
				
500
		if($update_remote_site_url)
501
		{
502
			$mysqli = $this->mysql_connect($remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db );
503
			$this->update_wp_config($remote_path, $remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db);
504
			$this->update_wp_url($remote_path, $remote_restore_url, $mysqli);
505
		}
506
		
507
		if($delete_backup_temporary_folder)
508
		{
509
			$this->delete_backup_temporary_folder($remote_path);
510
		}
511
		
512
		if(!defined('XCLONER_PLUGIN_ACCESS') || XCLONER_PLUGIN_ACCESS != 1)
513
		{
514
			if($delete_restore_script)
515
			{
516
				$this->delete_self();
517
			}
518
		}
519
		
520
		$return = "Restore Process Finished.";
521
		$this->send_response(200, $return);
522
	}
523
	
524
	private function delete_backup_temporary_folder($remote_path)
525
	{
526
		$this->target_adapter = new Local($remote_path ,LOCK_EX, 'SKIP_LINKS');
0 ignored issues
show
Bug introduced by
The property target_adapter does not seem to exist. Did you mean adapter?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
527
		$this->target_filesystem = new Filesystem($this->target_adapter, new Config([
0 ignored issues
show
Bug introduced by
The property target_filesystem does not seem to exist. Did you mean filesystem?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Bug introduced by
The property target_adapter does not seem to exist. Did you mean adapter?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
528
				'disable_asserts' => true,
529
			]));
530
			
531
		$mysqldump_list = array();
0 ignored issues
show
Unused Code introduced by
$mysqldump_list is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
532
		$list = $this->target_filesystem->listContents();
0 ignored issues
show
Bug introduced by
The property target_filesystem does not seem to exist. Did you mean filesystem?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
533
		
534
		foreach($list as $file)
535
		{
536
			$matches = array();
537
			
538
			if($file['type'] == "dir")
539
			{
540 View Code Duplication
				if(preg_match("/xcloner-(\w*)/", $file['basename'], $matches)){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
541
					$this->logger->info(sprintf('Deleting temporary folder %s', $file['path']));
542
					$this->target_filesystem->deleteDir($file['path']);
0 ignored issues
show
Bug introduced by
The property target_filesystem does not seem to exist. Did you mean filesystem?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
543
				}
544
			}
545
		}
546
		
547
		return true;
548
	
549
	}
550
	
551
	private function delete_self()
552
	{
553
		if($this->filesystem->has("vendor.phar"))
554
		{
555
			$this->logger->info(sprintf('Deleting vendor.phar'));
556
			$this->filesystem->delete("vendor.phar");
557
		}
558
		if($this->filesystem->has("vendor"))
559
		{
560
			$this->logger->info(sprintf('Deleting vendor folder'));
561
			$this->filesystem->deleteDir("vendor");
562
		}
563
		if($this->filesystem->has("xcloner_restore.php"))
564
		{
565
			$this->logger->info(sprintf('Deleting xcloner_restore.php'));
566
			$this->filesystem->delete("xcloner_restore.php");
567
		}
568
		
569
		if($this->filesystem->has("xcloner_restore.log"))
570
		{
571
			$this->logger->info(sprintf('Deleting xcloner_restore.log'));
572
			$this->filesystem->delete("xcloner_restore.log");
573
		}
574
		
575
		if($this->filesystem->has($this->get_logger_filename()))
576
		{
577
			$this->logger->info(sprintf('Deleting logger file %s', $this->get_logger_filename()));
578
			$this->filesystem->delete($this->get_logger_filename());
579
		}
580
		
581
	}
582
	
583
	private function update_wp_url($wp_path, $url, $mysqli)
584
	{
585
		$wp_config = $wp_path.DS."wp-config.php";
586
		
587
		$this->logger->info(sprintf('Updating site url to %s', $url));
588
		
589
		if(file_exists($wp_config))
590
		{
591
			$config = file_get_contents($wp_config);
592
			preg_match("/.*table_prefix.*=.*'(.*)'/i", $config, $matches);
593
			if(isset($matches[1]))
594
				$table_prefix = $matches[1];
595
			else
596
				throw new Exception("Could not load wordpress table prefix from wp-config.php file.");
597
		}
598
		else
599
			throw new Exception("Could not update the SITEURL and HOME, wp-config.php file not found");
600
			
601 View Code Duplication
		if(!$mysqli->query("update ".$table_prefix."options set option_value='".($url)."' where option_name='home'"))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
602
			throw new Exception(sprintf("Could not update the HOME option, error: %s\n", $mysqli->error));
603
		
604 View Code Duplication
		if(!$mysqli->query("update ".$table_prefix."options set option_value='".($url)."' where option_name='siteurl'"))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
605
			throw new Exception(sprintf("Could not update the SITEURL option, error: %s\n", $mysqli->error));
606
		
607
		return true;
608
	}
609
	
610
	private function update_wp_config($remote_path, $remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db)
611
	{
612
		$wp_config = $remote_path.DS."wp-config.php";
613
		
614
		if(!file_exists($wp_config))
615
		{
616
			throw new Exception("Could not find the wp-config.php in ".$remote_path);
617
		}
618
		
619
		$content = file_get_contents($wp_config);
620
		
621
		$content = preg_replace("/(?<=DB_NAME', ')(.*?)(?='\);)/", $remote_mysql_db, $content);
622
		$content = preg_replace("/(?<=DB_USER', ')(.*?)(?='\);)/", $remote_mysql_user, $content);
623
		$content = preg_replace("/(?<=DB_PASSWORD', ')(.*?)(?='\);)/", $remote_mysql_pass, $content);
624
		$content = preg_replace("/(?<=DB_HOST', ')(.*?)(?='\);)/", $remote_mysql_host, $content);
625
		
626
		$file_perms = fileperms($wp_config);
627
		
628
		chmod($wp_config, 0777);
629
		
630
		$this->logger->info(sprintf('Updating wp-config.php file with the new mysql details'));
631
		
632
		if(!file_put_contents($wp_config, $content))
633
			throw new Exception("Could not write updated config data to ".$wp_config);
634
		
635
		chmod($wp_config, $file_perms);
636
		
637
		return $wp_config;
638
		
639
	}
640
	
641
	public function list_mysqldump_backups_action()
642
	{
643
		$source_backup_file = filter_input(INPUT_POST, 'backup_file', FILTER_SANITIZE_STRING);
644
		$remote_path = filter_input(INPUT_POST, 'remote_path', FILTER_SANITIZE_STRING);
645
	
646
		$hash = $this->get_hash_from_backup($source_backup_file);	
647
		
648
		$this->target_adapter = new Local($remote_path ,LOCK_EX, 'SKIP_LINKS');
0 ignored issues
show
Bug introduced by
The property target_adapter does not seem to exist. Did you mean adapter?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
649
		$this->target_filesystem = new Filesystem($this->target_adapter, new Config([
0 ignored issues
show
Bug introduced by
The property target_filesystem does not seem to exist. Did you mean filesystem?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Bug introduced by
The property target_adapter does not seem to exist. Did you mean adapter?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
650
				'disable_asserts' => true,
651
			]));
652
			
653
		$mysqldump_list = array();
654
		$list = $this->target_filesystem->listContents();
0 ignored issues
show
Bug introduced by
The property target_filesystem does not seem to exist. Did you mean filesystem?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
655
		
656
		foreach($list as $file)
657
		{
658
			$matches = array();
659
			
660
			if($file['type'] == "dir")
661
			{
662
				if(preg_match("/xcloner-(\w*)/", $file['basename'], $matches))
663
				{
664
					$files = $this->target_filesystem->listContents($file['basename']);
0 ignored issues
show
Bug introduced by
The property target_filesystem does not seem to exist. Did you mean filesystem?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
665
					foreach($files as $file)
666
					{
667
						if($file['extension'] == "sql")
668
						{
669
							$this->logger->info(sprintf('Found %s mysql backup file', $file['path']));
670
							$mysqldump_list[$file['path']]['path'] = $file['path'];
671
							$mysqldump_list[$file['path']]['size'] = $file['size'];
672
							$mysqldump_list[$file['path']]['timestamp'] = date("d M,Y H:i",$file['timestamp']);
673
							
674
							if($hash and $hash == $matches[1])
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
675
								$mysqldump_list[$file['path']]['selected'] = "selected";
676
							else
677
								$mysqldump_list[$file['path']]['selected'] = "";	
678
						}
679
					}
680
				}
681
			}	
682
		}
683
		
684
		$this->sort_by($mysqldump_list, 'timestamp','desc');
685
		$return['files'] = $mysqldump_list;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
686
		
687
		$this->send_response(200, $return);
688
	}
689
	
690
	private function get_hash_from_backup($backup_file)
691
	{
692
		if(!$backup_file)
693
			return false;
694
			
695
		$result = preg_match("/-(\w*)./", substr($backup_file, strlen($backup_file)-10, strlen($backup_file)), $matches)	;
696
		
697
		if($result and isset($matches[1]))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
698
			return ($matches[1]);
699
		
700
		return false;
701
	}
702
	
703
	public function list_backup_archives_action()
704
	{
705
		$local_backup_file = filter_input(INPUT_POST, 'local_backup_file', FILTER_SANITIZE_STRING);
706
		$list = $this->filesystem->listContents();
707
		
708
		$backup_files = array();
709
		$parents = array();
710
		
711 View Code Duplication
		foreach($list as $file_info)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
712
		{
713
			$data = array();
0 ignored issues
show
Unused Code introduced by
$data is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
714
			
715
			if(isset($file_info['extension']) and $file_info['extension'] == "csv")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
716
			{
717
				$lines = explode(PHP_EOL, $this->filesystem->read($file_info['path']));
718
				foreach($lines as $line)
719
					if($line)
720
					{
721
						$data = str_getcsv($line);
722
						if(is_array($data)){
723
							$parents[$data[0]] = $file_info['path'];
724
							$file_info['childs'][] = $data;
725
							$file_info['size'] += $data[2];
726
						}
727
					}
728
						
729
			}
730
			
731
			if($file_info['type'] == 'file' and isset($file_info['extension']) and in_array($file_info['extension'], $this->backup_archive_extensions))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
732
				$backup_files[$file_info['path']] = $file_info;
733
		}
734
		
735
		$new_list = array();
736
		
737
		foreach($backup_files as $key=>$file_info)
738
		{
739
			if(isset($parents[$file_info['path']]))
740
				$backup_files[$key]['parent'] = $parents[$file_info['path']];
741
			else{
742
				
743
				if($local_backup_file and ($file_info['basename'] == $local_backup_file))
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
744
					$file_info['selected'] = 'selected';
745
				
746
				$this->logger->info(sprintf('Found %s backup file', $file_info['path']));
747
					
748
				$new_list[$key] = $file_info;
749
			}
750
				
751
		}
752
		
753
		$this->sort_by($new_list, "timestamp","desc");
754
		
755
		$return['files'] = $new_list;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
756
		
757
		$this->send_response(200, $return);
758
		
759
	}
760
	
761
	public function restore_backup_to_path_action()
762
	{
763
		$source_backup_file 	= filter_input(INPUT_POST, 'backup_file', FILTER_SANITIZE_STRING);
764
		$remote_path 			= filter_input(INPUT_POST, 'remote_path', FILTER_SANITIZE_STRING);
765
		$include_filter_files 	= filter_input(INPUT_POST, 'filter_files', FILTER_SANITIZE_STRING);
766
		$exclude_filter_files 	= "";
767
		$start 					= filter_input(INPUT_POST, 'start', FILTER_SANITIZE_NUMBER_INT);
768
		$return['part'] 		= (int)filter_input(INPUT_POST, 'part', FILTER_SANITIZE_NUMBER_INT);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
769
		$return['processed'] 	= (int)filter_input(INPUT_POST, 'processed', FILTER_SANITIZE_NUMBER_INT);
770
				
771
		$this->target_adapter = new Local($remote_path ,LOCK_EX, 'SKIP_LINKS');
0 ignored issues
show
Bug introduced by
The property target_adapter does not seem to exist. Did you mean adapter?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
772
		$this->target_filesystem = new Filesystem($this->target_adapter, new Config([
0 ignored issues
show
Bug introduced by
The property target_filesystem does not seem to exist. Did you mean filesystem?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Bug introduced by
The property target_adapter does not seem to exist. Did you mean adapter?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
773
				'disable_asserts' => true,
774
			]));
775
		
776
		$backup_file = $source_backup_file;
777
		
778
		$return['finished'] = 1;
779
		$return['extracted_files'] = array();
780
		$return['total_size'] = $this->get_backup_size($backup_file);
781
		
782
		$backup_archive = new Tar();
783
		if($this->is_multipart($backup_file))
784
		{
785
			if(!$return['part'])
786
				$return['processed'] += $this->filesystem->getSize($backup_file);
787
				
788
			$backup_parts = $this->get_multipart_files($backup_file);
789
			$backup_file = $backup_parts[$return['part']];	
790
		}	
791
		
792
		$this->logger->info(sprintf('Opening backup archive %s at position %s', $backup_file, $start));
793
		$backup_archive->open($this->backup_storage_dir .DS. $backup_file, $start);
0 ignored issues
show
Unused Code introduced by
The call to Tar::open() has too many arguments starting with $start.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
794
795
		$data = $backup_archive->extract($remote_path, '',$exclude_filter_files,$include_filter_files, $this->process_files_limit);
0 ignored issues
show
Unused Code introduced by
The call to Tar::extract() has too many arguments starting with $this->process_files_limit.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
796
		
797
		if(isset($data['extracted_files']))
798
		{
799
			foreach($data['extracted_files'] as $spl_fileinfo)
0 ignored issues
show
Bug introduced by
The expression $data['extracted_files'] of type object<splitbrain\PHPArchive\FileInfo> is not traversable.
Loading history...
800
			{
801
				$this->logger->info(sprintf('Extracted %s file', $spl_fileinfo->getPath()));
802
				$return['extracted_files'][] = $spl_fileinfo->getPath()." (".$spl_fileinfo->getSize()." bytes)";
803
			}
804
		}
805
		
806 View Code Duplication
		if(isset($data['start']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
807
		//if(isset($data['start']) and $data['start'] <= $this->filesystem->getSize($backup_file))
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
808
		{
809
			$return['finished'] = 0;
810
			$return['start'] = $data['start'];
811
		}else{
812
			
813
			$return['processed'] += $start;
814
			
815
			if($this->is_multipart($source_backup_file))
816
			{
817
				$return['start'] = 0;
818
				
819
				++$return['part'];
820
			
821
				if($return['part'] < sizeof($backup_parts))	
0 ignored issues
show
Bug introduced by
The variable $backup_parts does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
822
					$return['finished'] = 0;
823
				
824
			}
825
		}
826
		
827
		if($return['finished'])
828
			$this->logger->info(sprintf('Done extracting %s', $source_backup_file));
829
		
830
		$return['backup_file'] = $backup_file;
831
		
832
		$this->send_response(200, $return);
833
	}
834
	
835
	public function get_current_directory_action()
836
	{	
837
		global $wpdb;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
838
		
839
		$restore_script_url = filter_input(INPUT_POST, 'restore_script_url', FILTER_SANITIZE_STRING);
840
		
841
		$pathinfo = pathinfo( __FILE__);
842
		
843
		$suffix = "";
844
		$return['remote_mysql_host'] 	= "localhost";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
845
		$return['remote_mysql_user'] 	= "";
846
		$return['remote_mysql_pass'] 	= "";
847
		$return['remote_mysql_db'] 		= "";
848
		
849
		if(defined('XCLONER_PLUGIN_ACCESS') && XCLONER_PLUGIN_ACCESS)
850
		{
851
			$return['dir'] = realpath(get_home_path().DS.$suffix);
852
			$return['restore_script_url']  	= get_site_url();
853
			$return['remote_mysql_host'] 	= $wpdb->dbhost;
854
			$return['remote_mysql_user'] 	= $wpdb->dbuser;
855
			$return['remote_mysql_pass'] 	= $wpdb->dbpassword;
856
			$return['remote_mysql_db'] 		= $wpdb->dbname;
857
		}
858
		else{
859
			$return['dir'] = ($pathinfo['dirname']).DS.$suffix;
860
			$return['restore_script_url'] = str_replace($pathinfo['basename'], "", $restore_script_url).$suffix;
861
		}	
862
		
863
		$this->logger->info(sprintf('Determining current url as %s and path as %s', $return['dir'], $return['restore_script_url']));
864
		
865
		$this->send_response(200, $return);
866
	}
867
	
868
	public function check_system()
869
	{
870
		//check if i can write
871
		$tmp_file = md5(time());
872
		if(!file_put_contents($tmp_file, "++"))
873
			throw new Exception("Could not write to new host");
874
		
875
		if(!unlink($tmp_file))
876
			throw new Exception("Could not delete temporary file from new host");
877
		
878
		$max_upload      = $this->return_bytes((ini_get('upload_max_filesize')));
879
		$max_post        = $this->return_bytes((ini_get('post_max_size')));
880
881
		$return['max_upload_size'] = min($max_upload, $max_post); // bytes
0 ignored issues
show
Coding Style Comprehensibility introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
882
		$return['status']		= true;
883
		
884
		$this->logger->info(sprintf('Current filesystem max upload size is %s bytes', $return['max_upload_size']));
885
		
886
		$this->send_response(200, $return);
887
	}
888
	
889
	private function return_bytes($val) {
890
	    $val = trim($val);
891
	    $last = strtolower($val[strlen($val)-1]);
892
	    switch($last) {
893
	        // The 'G' modifier is available since PHP 5.1.0
894
	        case 'g':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
895
	            $val *= 1024;
896
	        case 'm':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
897
	            $val *= 1024;
898
	        case 'k':
899
	            $val *= 1024;
900
	    }
901
	
902
	    return $val;
903
	}
904
	
905
	public function is_multipart($backup_name)
906
	{
907
		if(stristr($backup_name, "-multipart"))
908
			return true;
909
		
910
		return false;	
911
	}
912
	
913 View Code Duplication
	public function get_backup_size($backup_name)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
914
	{
915
		$backup_size = $this->filesystem->getSize($backup_name);
916
		if($this->is_multipart($backup_name))
917
		{
918
			$backup_parts = $this->get_multipart_files($backup_name);
919
			foreach($backup_parts as $part_file)
920
				$backup_size += $this->filesystem->getSize($part_file);
921
		}
922
		
923
		return $backup_size;
924
	}
925
	
926 View Code Duplication
	public function get_multipart_files($backup_name)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
927
	{
928
		$files = array();
929
		
930
		if($this->is_multipart($backup_name))
931
		{
932
			$lines = explode(PHP_EOL, $this->filesystem->read($backup_name));
933
			foreach($lines as $line)
934
			{
935
				if($line)
936
				{
937
					$data = str_getcsv($line);
938
					$files[] = $data[0];
939
				}
940
			}
941
		}
942
		
943
		return $files;
944
	}
945
	
946
	private function sort_by( &$array, $field, $direction = 'asc')
947
	{
948
		$direction = strtolower($direction);
949
		
950
	    usort($array, create_function('$a, $b', '
0 ignored issues
show
Security Best Practice introduced by
The use of create_function is highly discouraged, better use a closure.

create_function can pose a great security vulnerability as it is similar to eval, and could be used for arbitrary code execution. We highly recommend to use a closure instead.

// Instead of
$function = create_function('$a, $b', 'return $a + $b');

// Better use
$function = function($a, $b) { return $a + $b; }
Loading history...
951
	        $a = $a["' . $field . '"];
952
	        $b = $b["' . $field . '"];
953
	
954
	        if ($a == $b)
955
	        {
956
	            return 0;
957
	        }
958
	
959
	        return ($a ' . ($direction == 'desc' ? '>' : '<') .' $b) ? -1 : 1;
960
	    '));
961
	
962
	    return true;
963
	}
964
		
965
	public static function send_response($status = 200, $response)
966
	{
967
		header("Access-Control-Allow-Origin: *");
968
		header("HTTP/1.1 200");
969
		header('Content-Type: application/json');
970
		$return['status'] = $status;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$return was never initialized. Although not strictly required by PHP, it is generally a good practice to add $return = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
971
		$return['statusText'] = $response;
972
		
973
		if(isset($response['error']) && $response['error'])
974
		{
975
			$return['statusText'] = $response['message'];
976
			$return['error'] = true;
977
		}elseif($status != 200 and $status != 418)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
978
		{
979
			$return['error'] = true;
980
			$return['message'] = $response;
981
		}
982
		
983
		echo json_encode($return);
984
		exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method send_response() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
985
	}
986
	
987
	/*
988
	 * Serialize fix methods below for mysql query lines
989
	 */ 
990
	 
991
	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...
992
	{
993
		//return preg_replace('!s:(\d+):([\\\\]?"[\\\\]?"|[\\\\]?"((.*?)[^\\\\])[\\\\]?");!e', "'s:'.strlen(unescape_mysql('$3')).':\"'.unescape_quotes('$3').'\";'", $query);
0 ignored issues
show
Unused Code Comprehensibility introduced by
74% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
994
		
995
		return preg_replace_callback('!s:(\d+):([\\\\]?"[\\\\]?"|[\\\\]?"((.*?)[^\\\\])[\\\\]?");!', function ($m) {
996
				  $data = "";
0 ignored issues
show
Unused Code introduced by
$data is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
997
				  	
998
				  if(!isset($m[3]))
999
					$m[3] = "";
1000
					
1001
					$data = 's:'.strlen(($m[3])).':\"'.($m[3]).'\";';
1002
	              //return $this->unescape_quotes($data);
0 ignored issues
show
Unused Code Comprehensibility introduced by
78% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1003
	              
1004
	              return $data;
1005
	            }, $query);
1006
	}
1007
	
1008
	private function unescape_quotes($value) {
1009
		return str_replace('\"', '"', $value);
1010
	}
1011
	
1012
	private function unescape_mysql($value) {
1013
		return str_replace(array("\\\\", "\\0", "\\n", "\\r", "\Z",  "\'", '\"'),
1014
						   array("\\",   "\0",  "\n",  "\r",  "\x1a", "'", '"'), 
1015
						   $value);
1016
	}	
1017
	
1018
	
1019
	private function has_serialized($s)
1020
	{
1021
		if(
1022
		    stristr($s, '{' ) != false &&
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stristr($s, '{') of type string to the boolean false. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
1023
		    stristr($s, '}' ) != false &&
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stristr($s, '}') of type string to the boolean false. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
1024
		    stristr($s, ';' ) != false &&
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stristr($s, ';') of type string to the boolean false. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
1025
		    stristr($s, ':' ) != false
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing stristr($s, ':') of type string to the boolean false. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
1026
		    ){
1027
		    return true;
1028
		}else{
1029
		    return false;
1030
		}
1031
1032
	}
1033
}
1034
1035