PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.1.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.1.2
6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 5.2.2 5.3 All 153 releases
mainwp / class / class-mainwp-backup-handler.php

class-mainwp-backup-handler.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.1.2, at class/class-mainwp-backup-handler.php

1,244 lines 54.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Backup Handler.
4 *
5 * @package MainWP/Dashboard
6 */
7
8 namespace MainWP\Dashboard;
9
10 // Exit if accessed directly.
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 /**
16 * Class MainWP_Backup_Handler
17 *
18 * @package MainWP\Dashboard
19 */
20 class MainWP_Backup_Handler { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
21
22 /**
23 * Method get_class_name()
24 *
25 * Get Class Name.
26 *
27 * @return string __CLASS__
28 */
29 public static function get_class_name() {
30 return __CLASS__;
31 }
32
33 /**
34 * Method backup_site()
35 *
36 * Backup Child Site.
37 *
38 * @param mixed $siteid Child Site ID.
39 * @param mixed $pTask Task to perform.
40 * @param mixed $subfolder Sub folder to place backup.
41 *
42 * @gobal object $wp_filesystem WordPress filesystem instance.
43 *
44 * @return mixed $backup_result
45 * @throws MainWP_Exception Error message.
46 *
47 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
48 * @uses \MainWP\Dashboard\MainWP_Connect::download_to_file()
49 * @uses \MainWP\Dashboard\MainWP_Connect::get_get_data_authed()
50 * @uses \MainWP\Dashboard\MainWP_DB_Backup::get_backup_task_progress()
51 * @uses \MainWP\Dashboard\MainWP_DB_Backup::add_backup_task_progress()
52 * @uses \MainWP\Dashboard\MainWP_DB_Backup::update_backup_task_progress()
53 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
54 * @uses \MainWP\Dashboard\MainWP_Exception
55 * @uses \MainWP\Dashboard\MainWP_Logger::debug_for_website()
56 * @uses \MainWP\Dashboard\MainWP_Logger::warning_for_website()
57 * @uses \MainWP\Dashboard\MainWP_System::is_single_user()
58 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_wp_file_system()
59 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_mainwp_specific_dir()
60 * @uses \MainWP\Dashboard\MainWP_Utility::sanitize()
61 * @uses \MainWP\Dashboard\MainWP_Utility::date()
62 * @uses \MainWP\Dashboard\MainWP_Utility::remove_preslash_spaces()
63 * @uses \MainWP\Dashboard\static::normalize_filename()
64 * @uses \MainWP\Dashboard\MainWP_Utility::value_to_string()
65 * @uses \MainWP\Dashboard\static::get_real_extension()
66 */
67 public static function backup_site( $siteid, $pTask, $subfolder ) {
68 // phpcs: ignore -- Current complexity is the only way to achieve desired results, pull request solutions appreciated.
69 if ( ! get_option( 'mainwp_enableLegacyBackupFeature' ) ) {
70 return false;
71 }
72
73 $userid = $pTask->userid;
74 $type = $pTask->type;
75 $exclude = $pTask->exclude;
76 $taskId = $pTask->id;
77 $excludebackup = $pTask->excludebackup;
78 $excludecache = $pTask->excludecache;
79 $excludenonwp = $pTask->excludenonwp;
80 $excludezip = $pTask->excludezip;
81 $pFilename = $pTask->filename;
82
83 if ( '' === trim( $pFilename ) ) {
84 $pFilename = null;
85 }
86
87 $backup_result = array();
88
89 // Creating a backup.
90 $website = MainWP_DB::instance()->get_website_by_id( $siteid );
91 $subfolder = str_replace( '%sitename%', MainWP_Utility::sanitize( $website->name ), $subfolder );
92 $subfolder = str_replace( '%url%', MainWP_Utility::sanitize( MainWP_Utility::get_nice_url( $website->url ) ), $subfolder );
93 $subfolder = str_replace( '%type%', $type, $subfolder );
94 $subfolder = str_replace( '%date%', MainWP_Utility::date( 'Ymd' ), $subfolder );
95 $subfolder = str_replace( '%task%', '', $subfolder );
96 $subfolder = str_replace( '%', '', $subfolder );
97 $subfolder = MainWP_Utility::remove_preslash_spaces( $subfolder );
98 $subfolder = static::normalize_filename( $subfolder );
99
100 if ( ! MainWP_System::instance()->is_single_user() && ( $userid !== $website->userid ) ) {
101 throw new MainWP_Exception( 'Undefined error.' );
102 }
103
104 $websiteCleanUrl = $website->url;
105 if ( '/' === substr( $websiteCleanUrl, - 1 ) ) {
106 $websiteCleanUrl = substr( $websiteCleanUrl, 0, - 1 );
107 }
108 $websiteCleanUrl = str_replace(
109 array( 'http://', 'https://', '/' ),
110 array( '', '', '-' ),
111 $websiteCleanUrl
112 );
113
114 if ( 'db' === $type ) {
115 $ext = '.sql.' . static::get_current_archive_extension( $website, $pTask );
116 } else {
117 $ext = '.' . static::get_current_archive_extension( $website, $pTask );
118 }
119
120 $file = str_replace(
121 array(
122 '%sitename%',
123 '%url%',
124 '%date%',
125 '%time%',
126 '%type%',
127 ),
128 array(
129 MainWP_Utility::sanitize( $website->name ),
130 $websiteCleanUrl,
131 MainWP_Utility::date( 'm-d-Y' ),
132 MainWP_Utility::date( 'G\hi\ms\s' ),
133 $type,
134 ),
135 $pFilename
136 );
137 $file = str_replace( '%', '', $file );
138 $file = static::normalize_filename( $file );
139
140 if ( ! empty( $file ) ) {
141 $file .= $ext;
142 }
143
144 if ( 'zip' === $pTask->archiveFormat ) {
145 $loadFilesBeforeZip = (int) $pTask->loadFilesBeforeZip;
146 } elseif ( '' === $pTask->archiveFormat || 'site' === $pTask->archiveFormat ) {
147 $loadFilesBeforeZip = (int) $website->loadFilesBeforeZip;
148 } else {
149 $loadFilesBeforeZip = 1;
150 }
151
152 if ( 1 === $loadFilesBeforeZip ) {
153 $loadFilesBeforeZip = get_option( 'mainwp_options_loadFilesBeforeZip' );
154 $loadFilesBeforeZip = ( 1 === (int) $loadFilesBeforeZip || false === $loadFilesBeforeZip );
155 } else {
156 $loadFilesBeforeZip = ( 2 === $loadFilesBeforeZip );
157 }
158
159 if ( ( 'zip' === $pTask->archiveFormat ) && ( 1 === (int) $pTask->maximumFileDescriptorsOverride ) ) {
160 $maximumFileDescriptorsAuto = ( 1 === (int) $pTask->maximumFileDescriptorsAuto );
161 $maximumFileDescriptors = $pTask->maximumFileDescriptors;
162 } elseif ( ( '' === $pTask->archiveFormat || 'site' === $pTask->archiveFormat ) && ( 1 === (int) $website->maximumFileDescriptorsOverride ) ) {
163 $maximumFileDescriptorsAuto = ( 1 === (int) $website->maximumFileDescriptorsAuto );
164 $maximumFileDescriptors = $website->maximumFileDescriptors;
165 } else {
166 $maximumFileDescriptorsAuto = get_option( 'mainwp_maximumFileDescriptorsAuto' );
167 $maximumFileDescriptors = get_option( 'mainwp_maximumFileDescriptors' );
168 $maximumFileDescriptors = ( false === $maximumFileDescriptors ? 150 : $maximumFileDescriptors );
169 }
170
171 $information = false;
172 $backupTaskProgress = MainWP_DB_Backup::instance()->get_backup_task_progress( $taskId, $website->id );
173 if ( empty( $backupTaskProgress ) || ( $backupTaskProgress->dtsFetched < $pTask->last_run ) ) {
174 $start = microtime( true );
175 try {
176 $pid = time();
177
178 if ( empty( $backupTaskProgress ) ) {
179 MainWP_DB_Backup::instance()->add_backup_task_progress( $taskId, $website->id, array() );
180 }
181
182 MainWP_DB_Backup::instance()->update_backup_task_progress(
183 $taskId,
184 $website->id,
185 array(
186 'dtsFetched' => time(),
187 'fetchResult' => wp_json_encode( array() ),
188 'downloadedDB' => '',
189 'downloadedDBComplete' => 0,
190 'downloadedFULL' => '',
191 'downloadedFULLComplete' => 0,
192 'removedFiles' => 0,
193 'attempts' => 0,
194 'last_error' => '',
195 'pid' => $pid,
196 )
197 );
198
199 $params = array(
200 'type' => $type,
201 'exclude' => $exclude,
202 'excludebackup' => $excludebackup,
203 'excludecache' => $excludecache,
204 'excludenonwp' => $excludenonwp,
205 'excludezip' => $excludezip,
206 'ext' => static::get_current_archive_extension( $website, $pTask ),
207 'file_descriptors_auto' => $maximumFileDescriptorsAuto,
208 'file_descriptors' => $maximumFileDescriptors,
209 'loadFilesBeforeZip' => $loadFilesBeforeZip,
210 'pid' => $pid,
211 'f' => $file,
212 );
213
214 MainWP_Logger::instance()->debug_for_website( $website, 'backup', 'Requesting backup: ' . MainWP_Utility::value_to_string( $params, 1 ) );
215
216 $information = MainWP_Connect::fetch_url_authed( $website, 'backup', $params, false, false, false );
217 } catch ( MainWP_Exception $e ) {
218 MainWP_Logger::instance()->warning_for_website( $website, 'backup', 'ERROR: ' . $e->getMessage() . ' (' . $e->get_message_extra() . ')' );
219 $stop = microtime( true );
220 // Bigger then 30 seconds means a timeout.
221 if ( 30 < ( $stop - $start ) ) {
222 MainWP_DB_Backup::instance()->update_backup_task_progress(
223 $taskId,
224 $website->id,
225 array(
226 'last_error' => wp_json_encode(
227 array(
228 'message' => $e->getMessage(),
229 'extra' => $e->get_message_extra(),
230 )
231 ),
232 )
233 );
234
235 return false;
236 }
237
238 throw $e;
239 }
240
241 if ( isset( $information['error'] ) && stristr( $information['error'], 'Another backup process is running' ) ) {
242 return false;
243 }
244
245 $backupTaskProgress = MainWP_DB_Backup::instance()->update_backup_task_progress( $taskId, $website->id, array( 'fetchResult' => wp_json_encode( $information ) ) );
246 } elseif ( empty( $backupTaskProgress->fetchResult ) ) {
247 try {
248 $temp = MainWP_Connect::fetch_url_authed( $website, 'backup_checkpid', array( 'pid' => $backupTaskProgress->pid ) );
249 } catch ( \Exception $e ) {
250 // ok!
251 }
252
253 if ( ! empty( $temp ) ) {
254 if ( 'stalled' === $temp['status'] ) {
255 if ( 5 > $backupTaskProgress->attempts ) {
256 $backupTaskProgress = MainWP_DB_Backup::instance()->update_backup_task_progress( $taskId, $website->id, array( 'attempts' => $backupTaskProgress->attempts++ ) );
257
258 try {
259 $information = MainWP_Connect::fetch_url_authed(
260 $website,
261 'backup',
262 array(
263 'type' => $type,
264 'exclude' => $exclude,
265 'excludebackup' => $excludebackup,
266 'excludecache' => $excludecache,
267 'excludenonwp' => $excludenonwp,
268 'excludezip' => $excludezip,
269 'ext' => static::get_current_archive_extension( $website, $pTask ),
270 'file_descriptors_auto' => $maximumFileDescriptorsAuto,
271 'file_descriptors' => $maximumFileDescriptors,
272 'loadFilesBeforeZip' => $loadFilesBeforeZip,
273 'pid' => $backupTaskProgress->pid,
274 'append' => '1',
275 'f' => $temp['file'],
276 ),
277 false,
278 false,
279 false
280 );
281
282 if ( isset( $information['error'] ) && stristr( $information['error'], 'Another backup process is running' ) ) {
283 MainWP_DB_Backup::instance()->update_backup_task_progress( $taskId, $website->id, array( 'attempts' => ( $backupTaskProgress->attempts - 1 ) ) );
284
285 return false;
286 }
287 } catch ( MainWP_Exception $e ) {
288 return false;
289 }
290
291 $backupTaskProgress = MainWP_DB_Backup::instance()->update_backup_task_progress( $taskId, $website->id, array( 'fetchResult' => wp_json_encode( $information ) ) );
292 } else {
293 throw new MainWP_Exception( 'Backup failed after 5 retries.' );
294 }
295 } elseif ( 'invalid' === $temp['status'] ) {
296 $error = json_decode( $backupTaskProgress->last_error );
297
298 if ( ! is_array( $error ) ) {
299 throw new MainWP_Exception( 'Backup failed.' );
300 } else {
301 throw new MainWP_Exception( $error['message'], $error['extra'] ); //phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
302 }
303 } elseif ( 'busy' === $temp['status'] ) {
304 return false;
305 } elseif ( 'done' === $temp['status'] ) {
306 if ( 'full' === $type ) {
307 $information['full'] = $temp['file'];
308 $information['db'] = false;
309 } else {
310 $information['full'] = false;
311 $information['db'] = $temp['file'];
312 }
313
314 $information['size'] = $temp['size'];
315
316 $backupTaskProgress = MainWP_DB_Backup::instance()->update_backup_task_progress( $taskId, $website->id, array( 'fetchResult' => wp_json_encode( $information ) ) );
317 }
318 } elseif ( 5 > $backupTaskProgress->attempts ) {
319 $backupTaskProgress = MainWP_DB_Backup::instance()->update_backup_task_progress( $taskId, $website->id, array( 'attempts' => $backupTaskProgress->attempts++ ) );
320 } else {
321 throw new MainWP_Exception( 'Backup failed after 5 retries.' );
322 }
323 }
324
325 if ( false === $information ) {
326 $information = $backupTaskProgress->fetchResult;
327 }
328
329 if ( isset( $information['error'] ) ) {
330 throw new MainWP_Exception( esc_html( $information['error'] ) );
331 } elseif ( 'db' === $type && ! $information['db'] ) {
332 throw new MainWP_Exception( 'Database backup failed.' );
333 } elseif ( 'full' === $type && ! $information['full'] ) {
334 throw new MainWP_Exception( 'Full backup failed.' );
335 } elseif ( isset( $information['db'] ) ) {
336 $hasWPFileSystem = MainWP_System_Utility::get_wp_file_system();
337
338 /**
339 * WordPress filesystem instance.
340 *
341 * @global object
342 */
343 global $wp_filesystem;
344
345 $dir = MainWP_System_Utility::get_mainwp_specific_dir( $website->id );
346
347 $wp_filesystem->mkdir( $dir, 0750 ); // MWP-1558: tightened from 0777; per-site backup dumps.
348
349 if ( ! $wp_filesystem->exists( $dir . 'index.php' ) ) {
350 $wp_filesystem->touch( $dir . 'index.php' );
351 }
352
353 // Clean old backups from our system.
354 $maxBackups = get_option( 'mainwp_backupsOnServer' );
355 if ( false === $maxBackups ) {
356 $maxBackups = 1;
357 }
358
359 if ( 1 !== $backupTaskProgress->removedFiles ) {
360 $dbBackups = array();
361 $fullBackups = array();
362 if ( $wp_filesystem->exists( $dir ) ) {
363 $dh = opendir( $dir );
364 if ( $dh ) {
365 while ( false !== ( $file = readdir( $dh ) ) ) {
366 if ( '.' !== $file && '..' !== $file ) {
367 $theFile = $dir . $file;
368 if ( $information['db'] && static::is_sql_file( $file ) ) {
369 $dbBackups[ filemtime( $theFile ) . $file ] = $theFile;
370 }
371
372 if ( $information['full'] && static::is_archive( $file ) && ! static::is_sql_archive( $file ) ) {
373 $fullBackups[ filemtime( $theFile ) . $file ] = $theFile;
374 }
375 }
376 }
377 closedir( $dh );
378 }
379 }
380 krsort( $dbBackups );
381 krsort( $fullBackups );
382
383 $cnt = 0;
384 foreach ( $dbBackups as $key => $dbBackup ) {
385 ++$cnt;
386 if ( $cnt >= $maxBackups ) {
387 $wp_filesystem->delete( $dbBackup );
388 }
389 }
390
391 $cnt = 0;
392 foreach ( $fullBackups as $key => $fullBackup ) {
393 ++$cnt;
394 if ( $cnt >= $maxBackups ) {
395 $wp_filesystem->delete( $fullBackup );
396 }
397 }
398 $backupTaskProgress = MainWP_DB_Backup::instance()->update_backup_task_progress( $taskId, $website->id, array( 'removedFiles' => 1 ) );
399 }
400
401 $localBackupFile = null;
402
403 $fm_date = MainWP_Utility::sanitize_file_name( MainWP_Utility::date( get_option( 'date_format' ) ) );
404 $fm_time = MainWP_Utility::sanitize_file_name( MainWP_Utility::date( get_option( 'time_format' ) ) );
405
406 $what = null;
407 $regexBackupFile = null;
408
409 if ( $information['db'] ) {
410 $what = 'db';
411 $regexBackupFile = 'db-' . $websiteCleanUrl . '-(.*)-(.*).sql(\.zip|\.tar|\.tar\.gz|\.tar\.bz2)?';
412 if ( '' === $backupTaskProgress->downloadedDB ) {
413 $localBackupFile = $dir . 'db-' . $websiteCleanUrl . '-' . $fm_date . '-' . $fm_time;
414
415 if ( null !== $pFilename ) {
416 $filename = str_replace(
417 array(
418 '%sitename%',
419 '%url%',
420 '%date%',
421 '%time%',
422 '%type%',
423 ),
424 array(
425 MainWP_Utility::sanitize( $website->name ),
426 $websiteCleanUrl,
427 $fm_date,
428 $fm_time,
429 $what,
430 ),
431 $pFilename
432 );
433 $filename = str_replace( '%', '', $filename );
434 $localBackupFile = $dir . $filename;
435 }
436 $localBackupFile .= static::get_real_extension( $information['db'] );
437
438 $localBackupFile = static::normalize_filename( $localBackupFile );
439
440 $backupTaskProgress = MainWP_DB_Backup::instance()->update_backup_task_progress( $taskId, $website->id, array( 'downloadedDB' => $localBackupFile ) );
441 } else {
442 $localBackupFile = $backupTaskProgress->downloadedDB;
443 }
444
445 if ( 0 === (int) $backupTaskProgress->downloadedDBComplete ) {
446 // MWP-1548: decrypt at the boundary so download_to_file
447 // sees plaintext credentials.
448 $http_user_plain = MainWP_Credential_Storage::decrypt_credential( $website->http_user );
449 $http_pass_plain = MainWP_Credential_Storage::decrypt_credential( $website->http_pass );
450 MainWP_Connect::download_to_file( MainWP_Connect::get_get_data_authed( $website, $information['db'], 'fdl' ), $localBackupFile, $information['size'], $http_user_plain, $http_pass_plain );
451 $backupTaskProgress = MainWP_DB_Backup::instance()->update_backup_task_progress( $taskId, $website->id, array( 'downloadedDBComplete' => 1 ) );
452 }
453 }
454
455 if ( $information['full'] ) {
456 $realExt = static::get_real_extension( $information['full'] );
457 $what = 'full';
458 $regexBackupFile = 'full-' . $websiteCleanUrl . '-(.*)-(.*).(zip|tar|tar.gz|tar.bz2)';
459 if ( '' === $backupTaskProgress->downloadedFULL ) {
460 $localBackupFile = $dir . 'full-' . $websiteCleanUrl . '-' . $fm_date . '-' . $fm_time . $realExt;
461
462 if ( null !== $pFilename ) {
463 $filename = str_replace(
464 array(
465 '%sitename%',
466 '%url%',
467 '%date%',
468 '%time%',
469 '%type%',
470 ),
471 array(
472 MainWP_Utility::sanitize( $website->name ),
473 $websiteCleanUrl,
474 $fm_date,
475 $fm_time,
476 $what,
477 ),
478 $pFilename
479 );
480 $filename = str_replace( '%', '', $filename );
481 $localBackupFile = $dir . $filename . $realExt;
482 }
483
484 $localBackupFile = static::normalize_filename( $localBackupFile );
485
486 $backupTaskProgress = MainWP_DB_Backup::instance()->update_backup_task_progress( $taskId, $website->id, array( 'downloadedFULL' => $localBackupFile ) );
487 } else {
488 $localBackupFile = $backupTaskProgress->downloadedFULL;
489 }
490
491 if ( 0 === (int) $backupTaskProgress->downloadedFULLComplete ) {
492 if ( file_exists( $localBackupFile ) ) {
493 $time = filemtime( $localBackupFile );
494
495 $minutes = gmdate( 'i', time() );
496 $seconds = gmdate( 's', time() );
497
498 $file_minutes = gmdate( 'i', $time );
499 $file_seconds = gmdate( 's', $time );
500
501 $minuteDiff = $minutes - $file_minutes;
502 if ( 59 === $minuteDiff ) {
503 $minuteDiff = 1;
504 }
505 $secondsdiff = ( $minuteDiff * 60 ) + $seconds - $file_seconds;
506
507 if ( 60 > $secondsdiff ) {
508 // still downloading.
509 return false;
510 }
511 }
512
513 // MWP-1548: decrypt at the boundary.
514 $http_user_plain = MainWP_Credential_Storage::decrypt_credential( $website->http_user );
515 $http_pass_plain = MainWP_Credential_Storage::decrypt_credential( $website->http_pass );
516 MainWP_Connect::download_to_file( MainWP_Connect::get_get_data_authed( $website, $information['full'], 'fdl' ), $localBackupFile, $information['size'], $http_user_plain, $http_pass_plain );
517 MainWP_Connect::fetch_url_authed( $website, 'delete_backup', array( 'del' => $information['full'] ) );
518 $backupTaskProgress = MainWP_DB_Backup::instance()->update_backup_task_progress( $taskId, $website->id, array( 'downloadedFULLComplete' => 1 ) );
519 }
520 }
521
522 $unique = $pTask->last_run;
523
524 do_action( 'mainwp_postprocess_backup_site', $localBackupFile, $what, $subfolder, $regexBackupFile, $website, $taskId, $unique );
525 $extra_result = apply_filters( 'mainwp_postprocess_backup_sites_feedback', array(), $unique );
526 if ( is_array( $extra_result ) ) {
527 foreach ( $extra_result as $key => $value ) {
528 $backup_result[ $key ] = $value;
529 }
530 }
531 } else {
532 throw new MainWP_Exception( 'Database backup failed due to an undefined error.' );
533 }
534
535 return $backup_result;
536 }
537
538 /**
539 * Method backup_download_file()
540 *
541 * Download backup file.
542 *
543 * @param mixed $pSiteId Child Site ID.
544 * @param mixed $pType full|db Type of backup.
545 * @param mixed $pUrl Backup location.
546 * @param mixed $pFile Backup File.
547 *
548 * @return bool true|false
549 * @throws MainWP_Exception Error message.
550 *
551 * @uses \MainWP\Dashboard\MainWP_Connect::get_get_data_authed()
552 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
553 * @uses \MainWP\Dashboard\MainWP_Connect::download_to_file()
554 * @uses \MainWP\Dashboard\MainWP_Utility::end_session()
555 */
556 public static function backup_download_file( $pSiteId, $pType, $pUrl, $pFile ) {
557 $hasWPFileSystem = MainWP_System_Utility::get_wp_file_system();
558
559 /**
560 * WordPress filesystem instance.
561 *
562 * @global object
563 */
564 global $wp_filesystem;
565
566 $dir = dirname( $pFile ) . '/';
567 $wp_filesystem->mkdir( $dir, 0750 ); // MWP-1558: tightened from 0777; backup download destination.
568 if ( ! $wp_filesystem->exists( $dir . 'index.php' ) ) {
569 $wp_filesystem->touch( $dir . 'index.php' );
570 }
571 // Clean old backups from our system.
572 $maxBackups = get_option( 'mainwp_backupsOnServer' );
573 if ( false === $maxBackups ) {
574 $maxBackups = 1;
575 }
576
577 $dbBackups = array();
578 $fullBackups = array();
579
580 if ( file_exists( $dir ) ) {
581 $dh = opendir( $dir );
582 if ( $dh ) {
583 while ( false !== ( $file = readdir( $dh ) ) ) {
584 if ( '.' !== $file && '..' !== $file ) {
585 $theFile = $dir . $file;
586 if ( 'db' === $pType && static::is_sql_file( $file ) ) {
587 $dbBackups[ filemtime( $theFile ) . $file ] = $theFile;
588 }
589
590 if ( 'full' === $pType && static::is_archive( $file ) && ! static::is_sql_archive( $file ) ) {
591 $fullBackups[ filemtime( $theFile ) . $file ] = $theFile;
592 }
593 }
594 }
595 closedir( $dh );
596 }
597 }
598 krsort( $dbBackups );
599 krsort( $fullBackups );
600
601 $cnt = 0;
602 foreach ( $dbBackups as $key => $dbBackup ) {
603 ++$cnt;
604 if ( $cnt >= $maxBackups ) {
605 $wp_filesystem->delete( $dbBackup );
606 }
607 }
608
609 $cnt = 0;
610 foreach ( $fullBackups as $key => $fullBackup ) {
611 ++$cnt;
612 if ( $cnt >= $maxBackups ) {
613 $wp_filesystem->delete( $fullBackup );
614 }
615 }
616
617 $website = MainWP_DB::instance()->get_website_by_id( $pSiteId );
618 MainWP_Utility::end_session();
619
620 // MWP-1548: decrypt once at function boundary; both branches use
621 // the same credentials.
622 $http_user_plain = MainWP_Credential_Storage::decrypt_credential( $website->http_user );
623 $http_pass_plain = MainWP_Credential_Storage::decrypt_credential( $website->http_pass );
624
625 if ( 'db' === $pType ) {
626 MainWP_Connect::download_to_file( MainWP_Connect::get_get_data_authed( $website, $pUrl, 'fdl' ), $pFile, false, $http_user_plain, $http_pass_plain );
627 }
628
629 if ( 'full' === $pType ) {
630 MainWP_Connect::download_to_file( MainWP_Connect::get_get_data_authed( $website, $pUrl, 'fdl' ), $pFile, false, $http_user_plain, $http_pass_plain );
631 }
632
633 return true;
634 }
635
636 /**
637 * Method backup_delete_file().
638 *
639 * Delete backup file.
640 *
641 * @param mixed $pSiteId Child Site ID.
642 * @param mixed $pFile File to delete.
643 *
644 * @return bool true
645 *
646 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
647 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
648 */
649 public static function backup_delete_file( $pSiteId, $pFile ) {
650 $website = MainWP_DB::instance()->get_website_by_id( $pSiteId );
651 MainWP_Connect::fetch_url_authed( $website, 'delete_backup', array( 'del' => $pFile ) );
652 return true;
653 }
654
655 /**
656 * Method backup_check_pid()
657 *
658 * Check backup pid.
659 *
660 * @param mixed $pSiteId Child Site id.
661 * @param mixed $pid Backup pid.
662 * @param mixed $type full|db Type of backup.
663 * @param mixed $subfolder Sub folder for backup.
664 * @param mixed $pFilename Backups filename.
665 *
666 * @return array $status, $result.
667 * @throws \MainWP_Exception Error message.
668 *
669 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_mainwp_specific_dir()
670 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
671 * @uses \MainWP\Dashboard\MainWP_Utility::end_session()
672 * @uses \MainWP\Dashboard\MainWP_Utility::sanitize()
673 * @uses \MainWP\Dashboard\MainWP_Utility::get_nice_url()
674 * @uses \MainWP\Dashboard\MainWP_Utility::date()
675 * @uses \MainWP\Dashboard\MainWP_Utility::remove_preslash_spaces()
676 * @uses \MainWP\Dashboard\static::normalize_filename()
677 * @uses \MainWP\Dashboard\MainWP_Utility::sanitize_file_name()
678 * @uses \MainWP\Dashboard\static::get_real_extension()
679 */
680 public static function backup_check_pid( $pSiteId, $pid, $type, $subfolder, $pFilename ) {
681 $website = MainWP_DB::instance()->get_website_by_id( $pSiteId );
682
683 MainWP_Utility::end_session();
684 $information = MainWP_Connect::fetch_url_authed( $website, 'backup_checkpid', array( 'pid' => $pid ) );
685
686 $status = $information['status'];
687
688 $result = isset( $information['file'] ) ? array( 'file' => $information['file'] ) : array();
689 if ( 'done' === $status ) {
690 $result['file'] = $information['file'];
691 $result['size'] = $information['size'];
692
693 $subfolder = str_replace( '%sitename%', MainWP_Utility::sanitize( $website->name ), $subfolder );
694 $subfolder = str_replace( '%url%', MainWP_Utility::sanitize( MainWP_Utility::get_nice_url( $website->url ) ), $subfolder );
695 $subfolder = str_replace( '%type%', $type, $subfolder );
696 $subfolder = str_replace( '%date%', MainWP_Utility::date( 'Ymd' ), $subfolder );
697 $subfolder = str_replace( '%task%', '', $subfolder );
698 $subfolder = str_replace( '%', '', $subfolder );
699 $subfolder = MainWP_Utility::remove_preslash_spaces( $subfolder );
700 $subfolder = static::normalize_filename( $subfolder );
701
702 $result['subfolder'] = $subfolder;
703
704 $websiteCleanUrl = $website->url;
705 if ( '/' === substr( $websiteCleanUrl, - 1 ) ) {
706 $websiteCleanUrl = substr( $websiteCleanUrl, 0, - 1 );
707 }
708 $websiteCleanUrl = str_replace(
709 array( 'http://', 'https://', '/' ),
710 array(
711 '',
712 '',
713 '-',
714 ),
715 $websiteCleanUrl
716 );
717
718 $dir = MainWP_System_Utility::get_mainwp_specific_dir( $pSiteId );
719
720 $fm_date = MainWP_Utility::sanitize_file_name( MainWP_Utility::date( get_option( 'date_format' ) ) );
721 $fm_time = MainWP_Utility::sanitize_file_name( MainWP_Utility::date( get_option( 'time_format' ) ) );
722
723 if ( 'db' === $type ) {
724 $localBackupFile = $dir . 'db-' . $websiteCleanUrl . '-' . $fm_date . '-' . $fm_time . static::get_real_extension( $information['file'] );
725 $localRegexFile = 'db-' . $websiteCleanUrl . '-(.*)-(.*).sql(\.zip|\.tar|\.tar\.gz|\.tar\.bz2)?';
726 } else {
727 $localBackupFile = $dir . 'full-' . $websiteCleanUrl . '-' . $fm_date . '-' . $fm_time . static::get_real_extension( $information['file'] );
728 $localRegexFile = 'full-' . $websiteCleanUrl . '-(.*)-(.*).(zip|tar|tar.gz|tar.bz2)';
729 }
730
731 if ( null !== $pFilename ) {
732 $filename = str_replace(
733 array(
734 '%sitename%',
735 '%url%',
736 '%date%',
737 '%time%',
738 '%type%',
739 ),
740 array(
741 MainWP_Utility::sanitize( $website->name ),
742 $websiteCleanUrl,
743 $fm_date,
744 $fm_time,
745 $type,
746 ),
747 $pFilename
748 );
749 $filename = str_replace( '%', '', $filename );
750 $localBackupFile = $dir . $filename;
751 $localBackupFile = static::normalize_filename( $localBackupFile );
752
753 if ( 'db' === $type ) {
754 $localBackupFile .= static::get_real_extension( $information['file'] );
755 } else {
756 $localBackupFile .= static::get_real_extension( $information['file'] );
757 }
758 }
759
760 $result['local'] = $localBackupFile;
761 $result['regexfile'] = $localRegexFile;
762 }
763
764 return array(
765 'status' => $status,
766 'result' => $result,
767 );
768 }
769
770 /**
771 * Method backup()
772 *
773 * Backup Child Site.
774 *
775 * @param mixed $pSiteId Child Site ID.
776 * @param mixed $pType full|db Typ of backup.
777 * @param mixed $pSubfolder Sub folder to store backup.
778 * @param mixed $pExclude Exclusion list.
779 * @param mixed $excludebackup Exclude backup files.
780 * @param mixed $excludecache Exclude cache files.
781 * @param mixed $excludenonwp Exclude no WP Files.
782 * @param mixed $excludezip Exclude Zip files.
783 * @param null $pFilename Name of backup file.
784 * @param string $pFileNameUID File name unique ID.
785 * @param bool $pArchiveFormat Archive format.
786 * @param bool $pMaximumFileDescriptorsOverride Override maximum file descriptors.
787 * @param bool $pMaximumFileDescriptorsAuto Auto maximum file descriptors.
788 * @param bool $pMaximumFileDescriptors Maximum file descriptors.
789 * @param bool $pLoadFilesBeforeZip Load files before zip.
790 * @param bool $pid Backup pid.
791 * @param bool $append Append to backup.
792 *
793 * @return mixed $backup_result
794 * @throws MainWP_Exception Error message.
795 *
796 * @uses \MainWP\Dashboard\MainWP_Connect::fetch_url_authed()
797 * @uses \MainWP\Dashboard\MainWP_Exception
798 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
799 * @uses \MainWP\Dashboard\MainWP_Logger::debug_for_website()
800 * @uses \MainWP\Dashboard\MainWP_System_Utility::can_edit_website()
801 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_mainwp_specific_dir()
802 * @uses \MainWP\Dashboard\MainWP_Utility::sanitize()
803 * @uses \MainWP\Dashboard\MainWP_Utility::date()
804 * @uses \MainWP\Dashboard\MainWP_Utility::remove_preslash_spaces()
805 * @uses \MainWP\Dashboard\static::normalize_filename()
806 * @uses \MainWP\Dashboard\MainWP_Utility::sanitize_file_name()
807 * @uses \MainWP\Dashboard\MainWP_Utility::end_session()
808 * @uses \MainWP\Dashboard\MainWP_Utility::value_to_string()
809 * @uses \MainWP\Dashboard\static::get_real_extension()
810 */
811 public static function backup(
812 $pSiteId,
813 $pType,
814 $pSubfolder,
815 $pExclude,
816 $excludebackup,
817 $excludecache,
818 $excludenonwp,
819 $excludezip,
820 $pFilename = null,
821 $pFileNameUID = '',
822 $pArchiveFormat = false,
823 $pMaximumFileDescriptorsOverride = false,
824 $pMaximumFileDescriptorsAuto = false,
825 $pMaximumFileDescriptors = false,
826 $pLoadFilesBeforeZip = false,
827 $pid = false,
828 $append = false
829 ) {
830
831 if ( ! get_option( 'mainwp_enableLegacyBackupFeature' ) ) {
832 return false;
833 }
834
835 if ( '' === trim( $pFilename ) ) {
836 $pFilename = null;
837 }
838
839 $backup_result = array();
840
841 $website = MainWP_DB::instance()->get_website_by_id( $pSiteId );
842 $subfolder = str_replace( '%sitename%', MainWP_Utility::sanitize( $website->name ), $pSubfolder );
843 $subfolder = str_replace( '%url%', MainWP_Utility::sanitize( MainWP_Utility::get_nice_url( $website->url ) ), $subfolder );
844 $subfolder = str_replace( '%type%', $pType, $subfolder );
845 $subfolder = str_replace( '%date%', MainWP_Utility::date( 'Ymd' ), $subfolder );
846 $subfolder = str_replace( '%task%', '', $subfolder );
847 $subfolder = str_replace( '%', '', $subfolder );
848 $subfolder = MainWP_Utility::remove_preslash_spaces( $subfolder );
849 $subfolder = static::normalize_filename( $subfolder );
850
851 if ( MainWP_System_Utility::is_suspended_site( $website ) ) {
852 throw new MainWP_Exception( 'Suspended site.', '', 'SUSPENDED_SITE' );
853 }
854
855 if ( ! MainWP_System_Utility::can_edit_website( $website ) ) {
856 throw new MainWP_Exception( 'You are not allowed to backup this site' );
857 }
858
859 $websiteCleanUrl = $website->url;
860 if ( '/' === substr( $websiteCleanUrl, - 1 ) ) {
861 $websiteCleanUrl = substr( $websiteCleanUrl, 0, - 1 );
862 }
863 $websiteCleanUrl = str_replace(
864 array( 'http://', 'https://', '/' ),
865 array( '', '', '-' ),
866 $websiteCleanUrl
867 );
868
869 if ( false === $pMaximumFileDescriptorsOverride ) {
870 if ( 1 === (int) $website->maximumFileDescriptorsOverride ) {
871 $maximumFileDescriptorsAuto = ( 1 === (int) $website->maximumFileDescriptorsAuto );
872 $maximumFileDescriptors = $website->maximumFileDescriptors;
873 } else {
874 $maximumFileDescriptorsAuto = get_option( 'mainwp_maximumFileDescriptorsAuto' );
875 $maximumFileDescriptors = get_option( 'mainwp_maximumFileDescriptors' );
876 $maximumFileDescriptors = ( false === $maximumFileDescriptors ? 150 : $maximumFileDescriptors );
877 }
878 } elseif ( ( 'global' !== $pArchiveFormat ) && ( 1 === (int) $pMaximumFileDescriptorsOverride ) ) {
879 $maximumFileDescriptorsAuto = ( 1 === $pMaximumFileDescriptorsAuto );
880 $maximumFileDescriptors = $pMaximumFileDescriptors;
881 } else {
882 $maximumFileDescriptorsAuto = get_option( 'mainwp_maximumFileDescriptorsAuto' );
883 $maximumFileDescriptors = get_option( 'mainwp_maximumFileDescriptors' );
884 $maximumFileDescriptors = ( false === $maximumFileDescriptors ? 150 : $maximumFileDescriptors );
885 }
886
887 $file = str_replace(
888 array(
889 '%sitename%',
890 '%url%',
891 '%date%',
892 '%time%',
893 '%type%',
894 ),
895 array(
896 MainWP_Utility::sanitize( $website->name ),
897 $websiteCleanUrl,
898 MainWP_Utility::date( 'm-d-Y' ),
899 MainWP_Utility::date( 'G\hi\ms\s' ),
900 $pType,
901 ),
902 $pFilename
903 );
904 $file = str_replace( '%', '', $file );
905 $file = static::normalize_filename( $file );
906
907 // Normal flow: check site settings & fallback to global.
908 if ( false === $pLoadFilesBeforeZip ) {
909 $loadFilesBeforeZip = $website->loadFilesBeforeZip;
910 if ( 1 === $loadFilesBeforeZip ) {
911 $loadFilesBeforeZip = get_option( 'mainwp_options_loadFilesBeforeZip' );
912 $loadFilesBeforeZip = ( 1 === $loadFilesBeforeZip || false === $loadFilesBeforeZip );
913 } else {
914 $loadFilesBeforeZip = ( 2 === $loadFilesBeforeZip );
915 }
916 } elseif ( 'global' === $pArchiveFormat || 1 === $pLoadFilesBeforeZip ) { // Overridden flow: only fallback to global.
917 $loadFilesBeforeZip = get_option( 'mainwp_options_loadFilesBeforeZip' );
918 $loadFilesBeforeZip = ( 1 === $loadFilesBeforeZip || false === $loadFilesBeforeZip );
919 } else {
920 $loadFilesBeforeZip = ( 2 === $pLoadFilesBeforeZip );
921 }
922
923 // Normal flow: check site settings & fallback to global.
924 if ( false === $pArchiveFormat ) {
925 $archiveFormat = static::get_current_archive_extension( $website );
926 } elseif ( 'global' === $pArchiveFormat ) {
927 $archiveFormat = static::get_current_archive_extension();
928 } else {
929 $archiveFormat = $pArchiveFormat;
930 }
931
932 MainWP_Utility::end_session();
933
934 $params = array(
935 'type' => $pType,
936 'exclude' => $pExclude,
937 'excludebackup' => $excludebackup,
938 'excludecache' => $excludecache,
939 'excludenonwp' => $excludenonwp,
940 'excludezip' => $excludezip,
941 'ext' => $archiveFormat,
942 'file_descriptors_auto' => $maximumFileDescriptorsAuto,
943 'file_descriptors' => $maximumFileDescriptors,
944 'loadFilesBeforeZip' => $loadFilesBeforeZip,
945 'f' => $file,
946 'fileUID' => $pFileNameUID,
947 'pid' => $pid,
948 'append' => ( $append ? 1 : 0 ),
949 );
950
951 MainWP_Logger::instance()->debug_for_website( $website, 'backup', 'Requesting backup: ' . MainWP_Utility::value_to_string( $params, 1 ) );
952
953 $information = MainWP_Connect::fetch_url_authed( $website, 'backup', $params, false, false, false );
954 do_action( 'mainwp_managesite_backup', $website, array( 'type' => $pType ), $information );
955
956 if ( isset( $information['error'] ) ) {
957 throw new MainWP_Exception( esc_html( $information['error'] ) ); //phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
958 } elseif ( 'db' === $pType && ! $information['db'] ) {
959 throw new MainWP_Exception( 'Database backup failed.' );
960 } elseif ( 'full' === $pType && ! $information['full'] ) {
961 throw new MainWP_Exception( 'Full backup failed.' );
962 } elseif ( isset( $information['db'] ) || isset( $information['full'] ) ) {
963 if ( ! empty( $information['db'] ) ) {
964 $backup_result['url'] = $information['db'];
965 $backup_result['type'] = 'db';
966 } elseif ( ! empty( $information['full'] ) ) {
967 $backup_result['url'] = $information['full'];
968 $backup_result['type'] = 'full';
969 }
970
971 if ( isset( $information['size'] ) ) {
972 $backup_result['size'] = $information['size'];
973 }
974 $backup_result['subfolder'] = $subfolder;
975
976 $dir = MainWP_System_Utility::get_mainwp_specific_dir( $pSiteId );
977
978 $fm_date = MainWP_Utility::sanitize_file_name( MainWP_Utility::date( get_option( 'date_format' ) ) );
979 $fm_time = MainWP_Utility::sanitize_file_name( MainWP_Utility::date( get_option( 'time_format' ) ) );
980
981 if ( 'db' === $pType ) {
982 $localBackupFile = $dir . 'db-' . $websiteCleanUrl . '-' . $fm_date . '-' . $fm_time . static::get_real_extension( $information['db'] );
983 $localRegexFile = 'db-' . $websiteCleanUrl . '-(.*)-(.*).sql(\.zip|\.tar|\.tar\.gz|\.tar\.bz2)?';
984 } else {
985 $localBackupFile = $dir . 'full-' . $websiteCleanUrl . '-' . $fm_date . '-' . $fm_time . static::get_real_extension( $information['full'] );
986 $localRegexFile = 'full-' . $websiteCleanUrl . '-(.*)-(.*).(zip|tar|tar.gz|tar.bz2)';
987 }
988
989 if ( null !== $pFilename ) {
990 $filename = str_replace(
991 array(
992 '%sitename%',
993 '%url%',
994 '%date%',
995 '%time%',
996 '%type%',
997 ),
998 array(
999 MainWP_Utility::sanitize( $website->name ),
1000 $websiteCleanUrl,
1001 $fm_date,
1002 $fm_time,
1003 $pType,
1004 ),
1005 $pFilename
1006 );
1007 $filename = str_replace( '%', '', $filename );
1008 $localBackupFile = $dir . $filename;
1009 $localBackupFile = static::normalize_filename( $localBackupFile );
1010
1011 if ( 'db' === $pType ) {
1012 $localBackupFile .= static::get_real_extension( $information['db'] );
1013 } else {
1014 $localBackupFile .= static::get_real_extension( $information['full'] );
1015 }
1016 }
1017
1018 $backup_result['local'] = $localBackupFile;
1019 $backup_result['regexfile'] = $localRegexFile;
1020
1021 return $backup_result;
1022 } else {
1023 throw new MainWP_Exception( 'Database backup failed due to an undefined error' );
1024 }
1025 }
1026
1027 /**
1028 * Method normalize_filename()
1029 *
1030 * Normalize filename.
1031 *
1032 * @param mixed $s Filename to normalize.
1033 *
1034 * @return string $s Normalised filename.
1035 */
1036 public static function normalize_filename( $s ) {
1037 $s = preg_replace( '@\x{00c4}@u', 'A', $s );
1038 $s = preg_replace( '@\x{00d6}@u', 'O', $s );
1039 $s = preg_replace( '@\x{00dc}@u', 'U', $s );
1040 $s = preg_replace( '@\x{00cb}@u', 'E', $s );
1041 $s = preg_replace( '@\x{00e4}@u', 'a', $s );
1042 $s = preg_replace( '@\x{00f6}@u', 'o', $s );
1043 $s = preg_replace( '@\x{00fc}@u', 'u', $s );
1044 $s = preg_replace( '@\x{00eb}@u', 'e', $s );
1045 $s = preg_replace( '@\x{00f1}@u', 'n', $s );
1046 $s = preg_replace( '@\x{00ff}@u', 'y', $s );
1047 return $s;
1048 }
1049
1050 /**
1051 * Method is_archive()
1052 *
1053 * Check if Archive.
1054 *
1055 * @param mixed $pFileName File to check.
1056 * @param string $pPrefix File prefix.
1057 * @param string $pSuffix File suffix.
1058 *
1059 * @return mixed Files that are archives.
1060 */
1061 public static function is_archive( $pFileName, $pPrefix = '', $pSuffix = '' ) {
1062 return preg_match( '/' . $pPrefix . '(.*).(zip|tar|tar.gz|tar.bz2)' . $pSuffix . '$/', $pFileName );
1063 }
1064
1065 /**
1066 * Method is_sql_file()
1067 *
1068 * Check if file is SQL.
1069 *
1070 * @param mixed $pFileName File to check.
1071 *
1072 * @return mixed SQL Files.
1073 */
1074 public static function is_sql_file( $pFileName ) {
1075 return preg_match( '/(.*).sql$/', $pFileName ) || static::is_sql_archive( $pFileName );
1076 }
1077
1078 /**
1079 * Method is_sql_archive()
1080 *
1081 * Check if is SQL Archive.
1082 *
1083 * @param mixed $pFileName File to check.
1084 *
1085 * @return mixed SQL archive.
1086 */
1087 public static function is_sql_archive( $pFileName ) {
1088 return preg_match( '/(.*).sql.(zip|tar|tar.gz|tar.bz2)$/', $pFileName );
1089 }
1090
1091 /**
1092 * Method get_current_archive_extension()
1093 *
1094 * Get extension of current Archive.
1095 *
1096 * @param bool $website true|false.
1097 * @param bool|string $task true|false|global|site.
1098 *
1099 * @return mixed $archiveFormat Format of Archive.
1100 *
1101 * @uses \MainWP\Dashboard\MainWP_DB_Backup::get_website_backup_settings()
1102 */
1103 public static function get_current_archive_extension( $website = false, $task = false ) {
1104 $useSite = true;
1105 if ( false !== $task ) {
1106 if ( 'global' === $task->archiveFormat ) {
1107 $useGlobal = true;
1108 $useSite = false;
1109 } elseif ( '' === $task->archiveFormat || 'site' === $task->archiveFormat ) {
1110 $useGlobal = false;
1111 $useSite = true;
1112 } else {
1113 $archiveFormat = $task->archiveFormat;
1114 $useGlobal = false;
1115 $useSite = false;
1116 }
1117 }
1118
1119 if ( $useSite ) {
1120 if ( false === $website ) {
1121 $useGlobal = true;
1122 } else {
1123 $backupSettings = MainWP_DB_Backup::instance()->get_website_backup_settings( $website->id );
1124 $archiveFormat = $backupSettings->archiveFormat;
1125 $useGlobal = ( 'global' === $archiveFormat );
1126 }
1127 }
1128
1129 if ( $useGlobal ) {
1130 $archiveFormat = get_option( 'mainwp_archiveFormat' );
1131 if ( false === $archiveFormat ) {
1132 $archiveFormat = 'tar.gz';
1133 }
1134 }
1135
1136 return $archiveFormat;
1137 }
1138
1139 /**
1140 * Method get_real_extension()
1141 *
1142 * Get full file extension.
1143 *
1144 * @param mixed $path Path to file.
1145 *
1146 * @return mixed $check|pathinfo()
1147 */
1148 public static function get_real_extension( $path ) {
1149 $checks = array( '.sql.zip', '.sql.tar', '.sql.tar.gz', '.sql.tar.bz2', '.tar.gz', '.tar.bz2' );
1150 foreach ( $checks as $check ) {
1151 if ( MainWP_Utility::ends_with( $path, $check ) ) {
1152 return $check;
1153 }
1154 }
1155
1156 return '.' . pathinfo( $path, PATHINFO_EXTENSION );
1157 }
1158
1159
1160 /**
1161 * Method handle_settings_post()
1162 *
1163 * Update Child Site Settings.
1164 *
1165 * @return bool true|false
1166 *
1167 * @uses \MainWP\Dashboard\MainWP_System_Utility::is_admin()
1168 * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
1169 */
1170 public static function handle_settings_post() {
1171 if ( MainWP_System_Utility::is_admin() ) {
1172 if ( isset( $_POST['submit'] ) && isset( $_POST['wp_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['wp_nonce'] ), 'Settings' ) ) {
1173 if ( isset( $_POST['mainwp_options_backupOnServer'] ) && 0 < $_POST['mainwp_options_backupOnServer'] ) {
1174 MainWP_Utility::update_option( 'mainwp_backupsOnServer', ( isset( $_POST['mainwp_options_backupOnServer'] ) ? intval( $_POST['mainwp_options_backupOnServer'] ) : 1 ) );
1175 }
1176 if ( isset( $_POST['mainwp_options_maximumFileDescriptors'] ) && - 1 < $_POST['mainwp_options_maximumFileDescriptors'] ) {
1177 MainWP_Utility::update_option( 'mainwp_maximumFileDescriptors', ( isset( $_POST['mainwp_options_maximumFileDescriptors'] ) ? intval( $_POST['mainwp_options_maximumFileDescriptors'] ) : 1 ) );
1178 }
1179 MainWP_Utility::update_option( 'mainwp_maximumFileDescriptorsAuto', ( ! isset( $_POST['mainwp_maximumFileDescriptorsAuto'] ) ? 0 : 1 ) );
1180 if ( ! empty( $_POST['mainwp_options_backupOnExternalSources'] ) && 0 <= $_POST['mainwp_options_backupOnExternalSources'] ) {
1181 MainWP_Utility::update_option( 'mainwp_backupOnExternalSources', ( isset( $_POST['mainwp_options_backupOnExternalSources'] ) ? intval( $_POST['mainwp_options_backupOnExternalSources'] ) : 1 ) );
1182 }
1183 MainWP_Utility::update_option( 'mainwp_archiveFormat', ( isset( $_POST['mainwp_archiveFormat'] ) ? sanitize_text_field( wp_unslash( $_POST['mainwp_archiveFormat'] ) ) : '' ) );
1184
1185 $old_primaryBackup = get_option( 'mainwp_primaryBackup' );
1186 $old_enableLegacyBackup = get_option( 'mainwp_enableLegacyBackupFeature' );
1187 $updated_enableLegacyBackup = false;
1188
1189 if ( isset( $_POST['mainwp_primaryBackup'] ) ) {
1190 if ( ! empty( $_POST['mainwp_primaryBackup'] ) ) { // not default backup method.
1191 MainWP_Utility::update_option( 'mainwp_notificationOnBackupFail', 0 );
1192 MainWP_Utility::update_option( 'mainwp_notificationOnBackupStart', 0 );
1193 MainWP_Utility::update_option( 'mainwp_chunkedBackupTasks', 0 );
1194 if ( empty( $old_primaryBackup ) ) {
1195 MainWP_Utility::update_option( 'mainwp_enableLegacyBackupFeature', 0 );
1196 $updated_enableLegacyBackup = true;
1197 }
1198 }
1199 MainWP_Utility::update_option( 'mainwp_primaryBackup', sanitize_text_field( wp_unslash( $_POST['mainwp_primaryBackup'] ) ) );
1200 }
1201
1202 if ( ! isset( $_POST['mainwp_primaryBackup'] ) || empty( $_POST['mainwp_primaryBackup'] ) ) {
1203 MainWP_Utility::update_option( 'mainwp_options_loadFilesBeforeZip', ( ! isset( $_POST['mainwp_options_loadFilesBeforeZip'] ) ? 0 : 1 ) );
1204 MainWP_Utility::update_option( 'mainwp_notificationOnBackupFail', ( ! isset( $_POST['mainwp_options_notificationOnBackupFail'] ) ? 0 : 1 ) );
1205 MainWP_Utility::update_option( 'mainwp_notificationOnBackupStart', ( ! isset( $_POST['mainwp_options_notificationOnBackupStart'] ) ? 0 : 1 ) );
1206 MainWP_Utility::update_option( 'mainwp_chunkedBackupTasks', ( ! isset( $_POST['mainwp_options_chunkedBackupTasks'] ) ? 0 : 1 ) );
1207 }
1208
1209 $enableLegacyBackup = ( isset( $_POST['mainwp_options_enableLegacyBackupFeature'] ) && ! empty( $_POST['mainwp_options_enableLegacyBackupFeature'] ) ) ? 1 : 0;
1210 if ( $enableLegacyBackup && empty( $old_enableLegacyBackup ) ) {
1211 MainWP_Utility::update_option( 'mainwp_primaryBackup', '' );
1212 }
1213
1214 if ( ! $updated_enableLegacyBackup ) {
1215 MainWP_Utility::update_option( 'mainwp_enableLegacyBackupFeature', $enableLegacyBackup );
1216 }
1217 return true;
1218 }
1219 }
1220 return false;
1221 }
1222
1223 /**
1224 * Method backup_get_file_size()
1225 *
1226 * Get file size.
1227 *
1228 * @param mixed $pFile Backup file.
1229 *
1230 * @return false|int
1231 *
1232 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_mainwp_specific_dir()
1233 */
1234 public static function backup_get_file_size( $pFile ) {
1235 $dir = MainWP_System_Utility::get_mainwp_specific_dir();
1236
1237 if ( stristr( $pFile, $dir ) && file_exists( $pFile ) ) {
1238 return filesize( $pFile );
1239 }
1240
1241 return 0;
1242 }
1243 }
1244