1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
if(!defined('AUTH_KEY')) |
4
|
|
|
{ |
5
|
|
|
define('AUTH_KEY', ''); |
6
|
|
|
} |
7
|
|
|
|
8
|
|
|
if(!defined("DS")) |
9
|
|
|
{ |
10
|
|
|
define("DS", DIRECTORY_SEPARATOR); |
11
|
|
|
} |
12
|
|
|
|
13
|
|
|
if(!defined('XCLONER_PLUGIN_ACCESS') || XCLONER_PLUGIN_ACCESS != 1) |
14
|
|
|
{ |
15
|
|
|
if(!AUTH_KEY) |
16
|
|
|
{ |
17
|
|
|
Xcloner_Restore::send_response("404", "Could not run restore script, AUTH_KEY not set!"); |
18
|
|
|
exit; |
19
|
|
|
} |
20
|
|
|
|
21
|
|
|
if(!isset($_REQUEST['hash'])) |
22
|
|
|
{ |
23
|
|
|
Xcloner_Restore::send_response("404", "Could not run restore script, sent HASH is empty!"); |
24
|
|
|
exit; |
25
|
|
|
} |
26
|
|
|
|
27
|
|
|
if($_REQUEST['hash'] != AUTH_KEY) |
28
|
|
|
{ |
29
|
|
|
Xcloner_Restore::send_response("404", "Could not run restore script, AUTH_KEY doesn't match the sent HASH!"); |
30
|
|
|
exit; |
31
|
|
|
} |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
//check minimum PHP version |
35
|
|
|
if(version_compare(phpversion(), Xcloner_Restore::xcloner_minimum_version, '<')) |
36
|
|
|
{ |
37
|
|
|
Xcloner_Restore::send_response(500, sprintf(("XCloner requires minimum PHP version %s in order to run correctly. We have detected your version as %s"),Xcloner_Restore::xcloner_minimum_version, phpversion()) ); |
38
|
|
|
exit; |
39
|
|
|
|
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
$file = dirname( __DIR__ ) . DS.'vendor'.DS.'autoload.php'; |
43
|
|
|
|
44
|
|
|
if(file_exists($file)) |
45
|
|
|
{ |
46
|
|
|
|
47
|
|
|
require_once($file); |
48
|
|
|
} |
49
|
|
|
elseif(file_exists("vendor.phar") and extension_loaded('phar')) |
|
|
|
|
50
|
|
|
{ |
51
|
|
|
require_once(__DIR__.DS."vendor.phar"); |
52
|
|
|
}else{ |
53
|
|
|
|
54
|
|
|
$file = dirname( __FILE__ ) . DS.'vendor'.DS.'autoload.php'; |
55
|
|
|
|
56
|
|
|
if(!file_exists($file)) |
57
|
|
|
{ |
58
|
|
|
Xcloner_Restore::send_response("404", "File $file does not exists, please extract the vendor.tgz archive on the server or enable PHP Phar module!"); |
59
|
|
|
exit; |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
require_once($file); |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
|
66
|
|
|
use League\Flysystem\Config; |
67
|
|
|
use League\Flysystem\Filesystem; |
68
|
|
|
use League\Flysystem\Util; |
69
|
|
|
use League\Flysystem\Adapter\Local; |
70
|
|
|
|
71
|
|
|
use splitbrain\PHPArchive\Tar; |
72
|
|
|
use splitbrain\PHPArchive\Archive; |
73
|
|
|
use splitbrain\PHPArchive\FileInfo; |
74
|
|
|
|
75
|
|
|
use Monolog\Logger; |
76
|
|
|
use Monolog\Handler\StreamHandler; |
77
|
|
|
|
78
|
|
|
|
79
|
|
|
//do not modify below |
80
|
|
|
$that = ""; |
81
|
|
|
if(defined('XCLONER_PLUGIN_ACCESS') && XCLONER_PLUGIN_ACCESS) |
82
|
|
|
{ |
83
|
|
|
$that = $this; |
84
|
|
|
} |
85
|
|
|
$xcloner_restore = new Xcloner_Restore($that); |
86
|
|
|
|
87
|
|
|
try{ |
88
|
|
|
$return = $xcloner_restore->init(); |
89
|
|
|
$xcloner_restore->send_response(200, $return); |
90
|
|
|
}catch(Exception $e){ |
91
|
|
|
$xcloner_restore->send_response(417, $e->getMessage()); |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
class Xcloner_Restore |
|
|
|
|
95
|
|
|
{ |
96
|
|
|
|
97
|
|
|
const xcloner_minimum_version = "5.4.0"; |
98
|
|
|
|
99
|
|
|
private $backup_archive_extensions = array("zip", "tar", "tgz", "tar.gz", "gz", "csv"); |
100
|
|
|
private $process_files_limit = 150; |
101
|
|
|
private $process_files_limit_list = 350; |
102
|
|
|
private $process_mysql_records_limit = 250; |
103
|
|
|
private $adapter; |
104
|
|
|
private $filesystem; |
105
|
|
|
private $logger; |
106
|
|
|
private $backup_storage_dir; |
107
|
|
|
private $parent_api; |
108
|
|
|
|
109
|
|
|
|
110
|
|
|
public function __construct($parent_api = "") |
|
|
|
|
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)) |
|
|
|
|
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) |
|
|
|
|
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) { |
|
|
|
|
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); |
|
|
|
|
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() |
|
|
|
|
180
|
|
|
{ |
181
|
|
|
if(isset($_POST['xcloner_action']) and $_POST['xcloner_action']) |
|
|
|
|
182
|
|
|
{ |
183
|
|
|
$method = filter_input(INPUT_POST, 'xcloner_action', FILTER_SANITIZE_STRING); |
184
|
|
|
|
185
|
|
|
//$method = "list_backup_archives"; |
|
|
|
|
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() |
|
|
|
|
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']); |
|
|
|
|
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; |
|
|
|
|
243
|
|
|
|
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
public function mysql_connect($remote_mysql_host, $remote_mysql_user, $remote_mysql_pass, $remote_mysql_db ) |
|
|
|
|
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']) |
|
|
|
|
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() |
|
|
|
|
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); |
|
|
|
|
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) |
|
|
|
|
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; |
|
|
|
|
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) { |
|
|
|
|
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) == "") |
|
|
|
|
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)) |
|
|
|
|
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) |
|
|
|
|
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) |
|
|
|
|
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; |
|
|
|
|
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)); |
|
|
|
|
371
|
|
|
} |
372
|
|
|
//else echo $line; |
|
|
|
|
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); |
|
|
|
|
426
|
|
|
|
427
|
|
|
$backup_file = $source_backup_file; |
428
|
|
|
|
429
|
|
View Code Duplication |
if($this->is_multipart($backup_file)) |
|
|
|
|
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); |
|
|
|
|
438
|
|
|
|
439
|
|
|
$data = $tar->contents($this->process_files_limit_list); |
|
|
|
|
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'])) |
|
|
|
|
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'])) |
|
|
|
|
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); |
|
|
|
|
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'); |
|
|
|
|
527
|
|
|
$this->target_filesystem = new Filesystem($this->target_adapter, new Config([ |
|
|
|
|
528
|
|
|
'disable_asserts' => true, |
529
|
|
|
])); |
530
|
|
|
|
531
|
|
|
$mysqldump_list = array(); |
|
|
|
|
532
|
|
|
$list = $this->target_filesystem->listContents(); |
|
|
|
|
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)){ |
|
|
|
|
541
|
|
|
$this->logger->info(sprintf('Deleting temporary folder %s', $file['path'])); |
542
|
|
|
$this->target_filesystem->deleteDir($file['path']); |
|
|
|
|
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'")) |
|
|
|
|
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'")) |
|
|
|
|
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'); |
|
|
|
|
649
|
|
|
$this->target_filesystem = new Filesystem($this->target_adapter, new Config([ |
|
|
|
|
650
|
|
|
'disable_asserts' => true, |
651
|
|
|
])); |
652
|
|
|
|
653
|
|
|
$mysqldump_list = array(); |
654
|
|
|
$list = $this->target_filesystem->listContents(); |
|
|
|
|
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']); |
|
|
|
|
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]) |
|
|
|
|
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; |
|
|
|
|
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])) |
|
|
|
|
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) |
|
|
|
|
712
|
|
|
{ |
713
|
|
|
$data = array(); |
|
|
|
|
714
|
|
|
|
715
|
|
|
if(isset($file_info['extension']) and $file_info['extension'] == "csv") |
|
|
|
|
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)) |
|
|
|
|
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)) |
|
|
|
|
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; |
|
|
|
|
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); |
|
|
|
|
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'); |
|
|
|
|
772
|
|
|
$this->target_filesystem = new Filesystem($this->target_adapter, new Config([ |
|
|
|
|
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); |
|
|
|
|
794
|
|
|
|
795
|
|
|
$data = $backup_archive->extract($remote_path, '',$exclude_filter_files,$include_filter_files, $this->process_files_limit); |
|
|
|
|
796
|
|
|
|
797
|
|
|
if(isset($data['extracted_files'])) |
798
|
|
|
{ |
799
|
|
|
foreach($data['extracted_files'] as $spl_fileinfo) |
|
|
|
|
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'])) |
|
|
|
|
807
|
|
|
//if(isset($data['start']) and $data['start'] <= $this->filesystem->getSize($backup_file)) |
|
|
|
|
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)) |
|
|
|
|
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; |
|
|
|
|
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"; |
|
|
|
|
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 |
|
|
|
|
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': |
|
|
|
|
895
|
|
|
$val *= 1024; |
896
|
|
|
case 'm': |
|
|
|
|
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) |
|
|
|
|
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) |
|
|
|
|
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', ' |
|
|
|
|
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; |
|
|
|
|
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) |
|
|
|
|
978
|
|
|
{ |
979
|
|
|
$return['error'] = true; |
980
|
|
|
$return['message'] = $response; |
981
|
|
|
} |
982
|
|
|
|
983
|
|
|
echo json_encode($return); |
984
|
|
|
exit; |
|
|
|
|
985
|
|
|
} |
986
|
|
|
|
987
|
|
|
/* |
988
|
|
|
* Serialize fix methods below for mysql query lines |
989
|
|
|
*/ |
990
|
|
|
|
991
|
|
|
function do_serialized_fix($query) |
|
|
|
|
992
|
|
|
{ |
993
|
|
|
//return preg_replace('!s:(\d+):([\\\\]?"[\\\\]?"|[\\\\]?"((.*?)[^\\\\])[\\\\]?");!e', "'s:'.strlen(unescape_mysql('$3')).':\"'.unescape_quotes('$3').'\";'", $query); |
|
|
|
|
994
|
|
|
|
995
|
|
|
return preg_replace_callback('!s:(\d+):([\\\\]?"[\\\\]?"|[\\\\]?"((.*?)[^\\\\])[\\\\]?");!', function ($m) { |
996
|
|
|
$data = ""; |
|
|
|
|
997
|
|
|
|
998
|
|
|
if(!isset($m[3])) |
999
|
|
|
$m[3] = ""; |
1000
|
|
|
|
1001
|
|
|
$data = 's:'.strlen(($m[3])).':\"'.($m[3]).'\";'; |
1002
|
|
|
//return $this->unescape_quotes($data); |
|
|
|
|
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 && |
|
|
|
|
1023
|
|
|
stristr($s, '}' ) != false && |
|
|
|
|
1024
|
|
|
stristr($s, ';' ) != false && |
|
|
|
|
1025
|
|
|
stristr($s, ':' ) != false |
|
|
|
|
1026
|
|
|
){ |
1027
|
|
|
return true; |
1028
|
|
|
}else{ |
1029
|
|
|
return false; |
1030
|
|
|
} |
1031
|
|
|
|
1032
|
|
|
} |
1033
|
|
|
} |
1034
|
|
|
|
1035
|
|
|
|
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.