PageRenderTime 74ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-content/plugins/worker/backup.class.php

https://bitbucket.org/summitds/bloomsburgpa.org
PHP | 3266 lines | 2238 code | 365 blank | 663 comment | 521 complexity | 8d91a885f7ae53a06e459e4bfa032a93 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.1
  1. <?php
  2. /*************************************************************
  3. *
  4. * backup.class.php
  5. *
  6. * Manage Backups
  7. *
  8. *
  9. * Copyright (c) 2011 Prelovac Media
  10. * www.prelovac.com
  11. **************************************************************/
  12. if(basename($_SERVER['SCRIPT_FILENAME']) == "backup.class.php"):
  13. echo "Sorry but you cannot browse this file directly!";
  14. exit;
  15. endif;
  16. define('MWP_BACKUP_DIR', WP_CONTENT_DIR . '/managewp/backups');
  17. define('MWP_DB_DIR', MWP_BACKUP_DIR . '/mwp_db');
  18. $zip_errors = array(
  19. 'No error',
  20. 'No error',
  21. 'Unexpected end of zip file',
  22. 'A generic error in the zipfile format was detected.',
  23. 'zip was unable to allocate itself memory',
  24. 'A severe error in the zipfile format was detected',
  25. 'Entry too large to be split with zipsplit',
  26. 'Invalid comment format',
  27. 'zip -T failed or out of memory',
  28. 'The user aborted zip prematurely',
  29. 'zip encountered an error while using a temp file',
  30. 'Read or seek error',
  31. 'zip has nothing to do',
  32. 'Missing or empty zip file',
  33. 'Error writing to a file',
  34. 'zip was unable to create a file to write to',
  35. 'bad command line parameters',
  36. 'no error',
  37. 'zip could not open a specified file to read'
  38. );
  39. $unzip_errors = array(
  40. 'No error',
  41. 'One or more warning errors were encountered, but processing completed successfully anyway',
  42. 'A generic error in the zipfile format was detected',
  43. 'A severe error in the zipfile format was detected.',
  44. 'unzip was unable to allocate itself memory.',
  45. 'unzip was unable to allocate memory, or encountered an encryption error',
  46. 'unzip was unable to allocate memory during decompression to disk',
  47. 'unzip was unable allocate memory during in-memory decompression',
  48. 'unused',
  49. 'The specified zipfiles were not found',
  50. 'Bad command line parameters',
  51. 'No matching files were found',
  52. 50 => 'The disk is (or was) full during extraction',
  53. 51 => 'The end of the ZIP archive was encountered prematurely.',
  54. 80 => 'The user aborted unzip prematurely.',
  55. 81 => 'Testing or extraction of one or more files failed due to unsupported compression methods or unsupported decryption.',
  56. 82 => 'No files were found due to bad decryption password(s)'
  57. );
  58. /**
  59. * The main class for processing database and full backups on ManageWP worker.
  60. *
  61. * @copyright 2011-2012 Prelovac Media
  62. * @version 3.9.24
  63. * @package ManageWP
  64. * @subpackage backup
  65. *
  66. */
  67. class MMB_Backup extends MMB_Core {
  68. var $site_name;
  69. var $statuses;
  70. var $tasks;
  71. var $s3;
  72. var $ftp;
  73. var $dropbox;
  74. var $google_drive;
  75. /**
  76. * Initializes site_name, statuses, and tasks attributes.
  77. *
  78. * @return void
  79. */
  80. function __construct() {
  81. parent::__construct();
  82. $this->site_name = str_replace(array(
  83. "_",
  84. "/",
  85. "~"
  86. ), array(
  87. "",
  88. "-",
  89. "-"
  90. ), rtrim($this->remove_http(get_bloginfo('url')), "/"));
  91. $this->statuses = array(
  92. 'db_dump' => 1,
  93. 'db_zip' => 2,
  94. 'files_zip' => 3,
  95. 's3' => 4,
  96. 'dropbox' => 5,
  97. 'ftp' => 6,
  98. 'email' => 7,
  99. 'google_drive' => 8,
  100. 'finished' => 100
  101. );
  102. $this->tasks = get_option('mwp_backup_tasks');
  103. }
  104. /**
  105. * Tries to increase memory limit to 384M and execution time to 600s.
  106. *
  107. * @return array an array with two keys for execution time and memory limit (0 - if not changed, 1 - if succesfully)
  108. */
  109. function set_memory() {
  110. $changed = array('execution_time' => 0, 'memory_limit' => 0);
  111. $memory_limit = trim(ini_get('memory_limit'));
  112. $last = strtolower(substr($memory_limit, -1));
  113. if($last == 'g')
  114. $memory_limit = ((int) $memory_limit)*1024;
  115. else if($last == 'm')
  116. $memory_limit = (int) $memory_limit;
  117. if($last == 'k')
  118. $memory_limit = ((int) $memory_limit)/1024;
  119. if ( $memory_limit < 384 ) {
  120. @ini_set('memory_limit', '384M');
  121. $changed['memory_limit'] = 1;
  122. }
  123. if ( (int) @ini_get('max_execution_time') < 600 ) {
  124. @set_time_limit(600); //ten minutes
  125. $changed['execution_time'] = 1;
  126. }
  127. return $changed;
  128. }
  129. /**
  130. * Returns backup settings from local database for all tasks
  131. *
  132. * @return mixed|boolean
  133. */
  134. function get_backup_settings() {
  135. $backup_settings = get_option('mwp_backup_tasks');
  136. if (!empty($backup_settings))
  137. return $backup_settings;
  138. else
  139. return false;
  140. }
  141. /**
  142. * Sets backup task defined from master, if task name is "Backup Now" this function fires processing backup.
  143. *
  144. * @param mixed $params parameters sent from master
  145. * @return mixed|boolean $this->tasks variable if success, array with error message if error has ocurred, false if $params are empty
  146. */
  147. function set_backup_task($params) {
  148. //$params => [$task_name, $args, $error]
  149. if (!empty($params)) {
  150. //Make sure backup cron job is set
  151. if (!wp_next_scheduled('mwp_backup_tasks')) {
  152. wp_schedule_event( time(), 'tenminutes', 'mwp_backup_tasks' );
  153. }
  154. extract($params);
  155. //$before = $this->get_backup_settings();
  156. $before = $this->tasks;
  157. if (!$before || empty($before))
  158. $before = array();
  159. if (isset($args['remove'])) {
  160. unset($before[$task_name]);
  161. $return = array(
  162. 'removed' => true
  163. );
  164. } else {
  165. if (isset($params['account_info']) && is_array($params['account_info'])) { //only if sends from master first time(secure data)
  166. $args['account_info'] = $account_info;
  167. }
  168. $before[$task_name]['task_args'] = $args;
  169. if (strlen($args['schedule']))
  170. $before[$task_name]['task_args']['next'] = $this->schedule_next($args['type'], $args['schedule']);
  171. $return = $before[$task_name];
  172. }
  173. //Update with error
  174. if (isset($error)) {
  175. if (is_array($error)) {
  176. $before[$task_name]['task_results'][count($before[$task_name]['task_results']) - 1]['error'] = $error['error'];
  177. } else {
  178. $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['error'] = $error;
  179. }
  180. }
  181. if (isset($time) && $time) { //set next result time before backup
  182. if (is_array($before[$task_name]['task_results'])) {
  183. $before[$task_name]['task_results'] = array_values($before[$task_name]['task_results']);
  184. }
  185. $before[$task_name]['task_results'][count($before[$task_name]['task_results'])]['time'] = $time;
  186. }
  187. $this->update_tasks($before);
  188. //update_option('mwp_backup_tasks', $before);
  189. if ($task_name == 'Backup Now') {
  190. $result = $this->backup($args, $task_name);
  191. $backup_settings = $this->tasks;
  192. if (is_array($result) && array_key_exists('error', $result)) {
  193. $return = $result;
  194. } else {
  195. $return = $backup_settings[$task_name];
  196. }
  197. }
  198. return $return;
  199. }
  200. return false;
  201. }
  202. /**
  203. * Checks if scheduled task is ready for execution,
  204. * if it is ready master sends google_drive_token, failed_emails, success_emails if are needed.
  205. *
  206. * @return void
  207. */
  208. function check_backup_tasks() {
  209. $this->check_cron_remove();
  210. $failed_emails = array();
  211. $settings = $this->tasks;
  212. if (is_array($settings) && !empty($settings)) {
  213. foreach ($settings as $task_name => $setting) {
  214. if (isset($setting['task_args']['next']) && $setting['task_args']['next'] < time()) {
  215. //if ($setting['task_args']['next'] && $_GET['force_backup']) {
  216. if ($setting['task_args']['url'] && $setting['task_args']['task_id'] && $setting['task_args']['site_key']) {
  217. //Check orphan task
  218. $check_data = array(
  219. 'task_name' => $task_name,
  220. 'task_id' => $setting['task_args']['task_id'],
  221. 'site_key' => $setting['task_args']['site_key'],
  222. 'worker_version' => MMB_WORKER_VERSION
  223. );
  224. if (isset($setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'])) {
  225. $check_data['mwp_google_drive_refresh_token'] = true;
  226. }
  227. $check = $this->validate_task($check_data, $setting['task_args']['url']);
  228. if($check == 'paused' || $check == 'deleted'){
  229. continue;
  230. }
  231. $worker_upto_3_9_22 = (MMB_WORKER_VERSION <= '3.9.22'); // worker version is less or equals to 3.9.22
  232. // This is the patch done in worker 3.9.22 because old worked provided message in the following format:
  233. // token - not found or token - {...json...}
  234. // The new message is a serialized string with google_drive_token or message.
  235. if ($worker_upto_3_9_22) {
  236. $potential_token = substr($check, 8);
  237. if (substr($check, 0, 8) == 'token - ' && $potential_token != 'not found') {
  238. $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
  239. $settings[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
  240. $setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
  241. }
  242. } else {
  243. $potential_token = isset($check['google_drive_token']) ? $check['google_drive_token'] : false;
  244. if ($potential_token) {
  245. $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
  246. $settings[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
  247. $setting['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $potential_token;
  248. }
  249. }
  250. }
  251. $update = array(
  252. 'task_name' => $task_name,
  253. 'args' => $settings[$task_name]['task_args']
  254. );
  255. if ($check != 'paused') {
  256. $update['time'] = time();
  257. }
  258. //Update task with next schedule
  259. $this->set_backup_task($update);
  260. $result = $this->backup($setting['task_args'], $task_name);
  261. $error = '';
  262. if (is_array($result) && array_key_exists('error', $result)) {
  263. $error = $result;
  264. $this->set_backup_task(array(
  265. 'task_name' => $task_name,
  266. 'args' => $settings[$task_name]['task_args'],
  267. 'error' => $error
  268. ));
  269. } else {
  270. if (@count($setting['task_args']['account_info'])) {
  271. // Old way through sheduling.
  272. // wp_schedule_single_event(time(), 'mmb_scheduled_remote_upload', array('args' => array('task_name' => $task_name)));
  273. $nonce = substr(wp_hash(wp_nonce_tick() . 'mmb-backup-nonce' . 0, 'nonce'), -12, 10);
  274. $cron_url = site_url('index.php');
  275. $backup_file = $this->tasks[$task_name]['task_results'][count($this->tasks[$task_name]['task_results']) - 1]['server']['file_url'];
  276. $del_host_file = $this->tasks[$task_name]['task_args']['del_host_file'];
  277. $public_key = get_option('_worker_public_key');
  278. $args = array(
  279. 'body' => array(
  280. 'backup_cron_action' => 'mmb_remote_upload',
  281. 'args' => json_encode(array('task_name' => $task_name, 'backup_file' => $backup_file, 'del_host_file' => $del_host_file)),
  282. 'mmb_backup_nonce' => $nonce,
  283. 'public_key' => $public_key,
  284. ),
  285. 'timeout' => 0.01,
  286. 'blocking' => false,
  287. 'sslverify' => apply_filters('https_local_ssl_verify', true)
  288. );
  289. wp_remote_post($cron_url, $args);
  290. }
  291. }
  292. break; //Only one backup per cron
  293. }
  294. }
  295. }
  296. }
  297. /**
  298. * Runs backup task invoked from ManageWP master.
  299. *
  300. * @param string $task_name name of backup task
  301. * @param string|bool[optional] $google_drive_token false if backup destination is not Google Drive, json of Google Drive token if it is remote destination (default: false)
  302. * @return mixed array with backup statistics if successful, array with error message if not
  303. */
  304. function task_now($task_name, $google_drive_token = false) {
  305. if ($google_drive_token) {
  306. $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
  307. }
  308. $settings = $this->tasks;
  309. if(!array_key_exists($task_name,$settings)){
  310. return array('error' => $task_name." does not exist.");
  311. } else {
  312. $setting = $settings[$task_name];
  313. }
  314. $this->set_backup_task(array(
  315. 'task_name' => $task_name,
  316. 'args' => $settings[$task_name]['task_args'],
  317. 'time' => time()
  318. ));
  319. //Run backup
  320. $result = $this->backup($setting['task_args'], $task_name);
  321. //Check for error
  322. if (is_array($result) && array_key_exists('error', $result)) {
  323. $this->set_backup_task(array(
  324. 'task_name' => $task_name,
  325. 'args' => $settings[$task_name]['task_args'],
  326. 'error' => $result
  327. ));
  328. return $result;
  329. } else {
  330. return $this->get_backup_stats();
  331. }
  332. }
  333. /**
  334. * Backup a full wordpress instance, including a database dump, which is placed in mwp_db dir in root folder.
  335. * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
  336. *
  337. * @param string $args arguments passed from master
  338. * [type] -> db, full
  339. * [what] -> daily, weekly, monthly
  340. * [account_info] -> remote destinations ftp, amazons3, dropbox, google_drive, email with their parameters
  341. * [include] -> array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
  342. * [exclude] -> array of files of folders to exclude, relative to site's root
  343. * @param bool|string[optional] $task_name the name of backup task, which backup is done (default: false)
  344. * @return bool|array false if $args are missing, array with error if error has occured, ture if is successful
  345. */
  346. function backup($args, $task_name = false) {
  347. if (!$args || empty($args))
  348. return false;
  349. extract($args); //extract settings
  350. if (!empty($account_info)) {
  351. $found = false;
  352. $destinations = array('mwp_ftp', 'mwp_amazon_s3', 'mwp_dropbox', 'mwp_google_drive', 'mwp_email');
  353. foreach($destinations as $dest) {
  354. $found = $found || (isset($account_info[$dest]));
  355. }
  356. if (!$found) {
  357. $error_message = 'Remote destination is not supported, please update your client plugin.';
  358. return array(
  359. 'error' => $error_message
  360. );
  361. }
  362. }
  363. //Try increase memory limit and execution time
  364. $this->set_memory();
  365. //Remove old backup(s)
  366. $removed = $this->remove_old_backups($task_name);
  367. if (is_array($removed) && isset($removed['error'])) {
  368. $error_message = $removed['error'];
  369. return $removed;
  370. }
  371. $new_file_path = MWP_BACKUP_DIR;
  372. if (!file_exists($new_file_path)) {
  373. if (!mkdir($new_file_path, 0755, true))
  374. $error_message = 'Permission denied, make sure you have write permission to wp-content folder.';
  375. return array(
  376. 'error' => $error_message
  377. );
  378. }
  379. @file_put_contents($new_file_path . '/index.php', ''); //safe
  380. //Prepare .zip file name
  381. $hash = md5(time());
  382. $label = $type ? $type : 'manual';
  383. $backup_file = $new_file_path . '/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
  384. $backup_url = WP_CONTENT_URL . '/managewp/backups/' . $this->site_name . '_' . $label . '_' . $what . '_' . date('Y-m-d') . '_' . $hash . '.zip';
  385. $begin_compress = microtime(true);
  386. //Optimize tables?
  387. if (isset($optimize_tables) && !empty($optimize_tables)) {
  388. $this->optimize_tables();
  389. }
  390. //What to backup - db or full?
  391. if (trim($what) == 'db') {
  392. $db_backup = $this->backup_db_compress($task_name, $backup_file);
  393. if (is_array($db_backup) && array_key_exists('error', $db_backup)) {
  394. $error_message = $db_backup['error'];
  395. return array(
  396. 'error' => $error_message
  397. );
  398. }
  399. } elseif (trim($what) == 'full') {
  400. if (!$exclude) {
  401. $exclude = array();
  402. }
  403. if (!$include) {
  404. $include = array();
  405. }
  406. $content_backup = $this->backup_full($task_name, $backup_file, $exclude, $include);
  407. if (is_array($content_backup) && array_key_exists('error', $content_backup)) {
  408. $error_message = $content_backup['error'];
  409. return array(
  410. 'error' => $error_message
  411. );
  412. }
  413. }
  414. $end_compress = microtime(true);
  415. //Update backup info
  416. if ($task_name) {
  417. //backup task (scheduled)
  418. $backup_settings = $this->tasks;
  419. $paths = array();
  420. $size = ceil(filesize($backup_file) / 1024);
  421. $duration = round($end_compress - $begin_compress, 2);
  422. if ($size > 1000) {
  423. $paths['size'] = ceil($size / 1024) . "mb";
  424. } else {
  425. $paths['size'] = $size . 'kb';
  426. }
  427. $paths['duration'] = $duration . 's';
  428. if ($task_name != 'Backup Now') {
  429. $paths['server'] = array(
  430. 'file_path' => $backup_file,
  431. 'file_url' => $backup_url
  432. );
  433. } else {
  434. $paths['server'] = array(
  435. 'file_path' => $backup_file,
  436. 'file_url' => $backup_url
  437. );
  438. }
  439. if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_ftp'])) {
  440. $paths['ftp'] = basename($backup_url);
  441. }
  442. if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_amazon_s3'])) {
  443. $paths['amazons3'] = basename($backup_url);
  444. }
  445. if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_dropbox'])) {
  446. $paths['dropbox'] = basename($backup_url);
  447. }
  448. if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_email'])) {
  449. $paths['email'] = basename($backup_url);
  450. }
  451. if (isset($backup_settings[$task_name]['task_args']['account_info']['mwp_google_drive'])) {
  452. $paths['google_drive'] = basename($backup_url);
  453. }
  454. $temp = $backup_settings[$task_name]['task_results'];
  455. $temp = array_values($temp);
  456. $paths['time'] = time();
  457. if ($task_name != 'Backup Now') {
  458. $paths['status'] = $temp[count($temp) - 1]['status'];
  459. $temp[count($temp) - 1] = $paths;
  460. } else {
  461. $temp[count($temp)] = $paths;
  462. }
  463. $backup_settings[$task_name]['task_results'] = $temp;
  464. $this->update_tasks($backup_settings);
  465. //update_option('mwp_backup_tasks', $backup_settings);
  466. }
  467. // If there are not remote destination, set up task status to finished
  468. if (@count($backup_settings[$task_name]['task_args']['account_info']) == 0) {
  469. $this->update_status($task_name, $this->statuses['finished'], true);
  470. }
  471. return true;
  472. }
  473. /**
  474. * Backup a full wordpress instance, including a database dump, which is placed in mwp_db dir in root folder.
  475. * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
  476. *
  477. * @param string $task_name the name of backup task, which backup is done
  478. * @param string $backup_file relative path to file which backup is stored
  479. * @param array[optional] $exclude the list of files and folders, which are excluded from backup (default: array())
  480. * @param array[optional] $include the list of folders in wordpress root which are included to backup, expect wp-admin, wp-content, wp-includes, which are default (default: array())
  481. * @return bool|array true if backup is successful, or an array with error message if is failed
  482. */
  483. function backup_full($task_name, $backup_file, $exclude = array(), $include = array()) {
  484. $this->update_status($task_name, $this->statuses['db_dump']);
  485. $db_result = $this->backup_db();
  486. if ($db_result == false) {
  487. return array(
  488. 'error' => 'Failed to backup database.'
  489. );
  490. } else if (is_array($db_result) && isset($db_result['error'])) {
  491. return array(
  492. 'error' => $db_result['error']
  493. );
  494. }
  495. $this->update_status($task_name, $this->statuses['db_dump'], true);
  496. $this->update_status($task_name, $this->statuses['db_zip']);
  497. @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
  498. $zip_db_result = $this->zip_backup_db($task_name, $backup_file);
  499. if (!$zip_db_result) {
  500. $zip_archive_db_result = false;
  501. if (class_exists("ZipArchive")) {
  502. $this->_log("DB zip, fallback to ZipArchive");
  503. $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
  504. }
  505. if (!$zip_archive_db_result) {
  506. $this->_log("DB zip, fallback to PclZip");
  507. $pclzip_db_result = $this->pclzip_backup_db($task_name, $backup_file);
  508. if (!$pclzip_db_result) {
  509. @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
  510. @unlink($db_result);
  511. @rmdir(MWP_DB_DIR);
  512. if($archive->error_code!=''){
  513. $archive->error_code = 'pclZip error ('.$archive->error_code . '): .';
  514. }
  515. return array(
  516. 'error' => 'Failed to zip database. ' . $archive->error_code . $archive->error_string
  517. );
  518. }
  519. }
  520. }
  521. @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
  522. @unlink($db_result);
  523. @rmdir(MWP_DB_DIR);
  524. $remove = array(
  525. trim(basename(WP_CONTENT_DIR)) . "/managewp/backups",
  526. trim(basename(WP_CONTENT_DIR)) . "/" . md5('mmb-worker') . "/mwp_backups"
  527. );
  528. $exclude = array_merge($exclude, $remove);
  529. $this->update_status($task_name, $this->statuses['db_zip'], true);
  530. $this->update_status($task_name, $this->statuses['files_zip']);
  531. $zip_result = $this->zip_backup($task_name, $backup_file, $exclude, $include);
  532. if (isset($zip_result['error'])) {
  533. return $zip_result;
  534. }
  535. if (!$zip_result) {
  536. $zip_archive_result = false;
  537. if (class_exists("ZipArchive")) {
  538. $this->_log("Files zip fallback to ZipArchive");
  539. $zip_archive_result = $this->zip_archive_backup($task_name, $backup_file, $exclude, $include);
  540. }
  541. if (!$zip_archive_result) {
  542. $this->_log("Files zip fallback to PclZip");
  543. $pclzip_result = $this->pclzip_backup($task_name, $backup_file, $exclude, $include);
  544. if (!$pclzip_result) {
  545. @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
  546. @unlink($db_result);
  547. @rmdir(MWP_DB_DIR);
  548. if (!$pclzip_result) {
  549. @unlink($backup_file);
  550. return array(
  551. 'error' => 'Failed to zip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
  552. );
  553. }
  554. }
  555. }
  556. }
  557. //Reconnect
  558. $this->wpdb_reconnect();
  559. $this->update_status($task_name, $this->statuses['files_zip'], true);
  560. return true;
  561. }
  562. /**
  563. * Zipping database dump and index.php in folder mwp_db by system zip command, requires zip installed on OS.
  564. *
  565. * @param string $task_name the name of backup task
  566. * @param string $backup_file absolute path to zip file
  567. * @return bool is compress successful or not
  568. */
  569. function zip_backup_db($task_name, $backup_file) {
  570. $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
  571. $comp_level = $disable_comp ? '-0' : '-1';
  572. $zip = $this->get_zip();
  573. //Add database file
  574. chdir(MWP_BACKUP_DIR);
  575. $command = "$zip -q -r $comp_level $backup_file 'mwp_db'";
  576. ob_start();
  577. $this->_log("Executing $command");
  578. $result = $this->mmb_exec($command);
  579. ob_get_clean();
  580. return $result;
  581. }
  582. /**
  583. * Zipping database dump and index.php in folder mwp_db by ZipArchive class, requires php zip extension.
  584. *
  585. * @param string $task_name the name of backup task
  586. * @param string $db_result relative path to database dump file
  587. * @param string $backup_file absolute path to zip file
  588. * @return bool is compress successful or not
  589. */
  590. function zip_archive_backup_db($task_name, $db_result, $backup_file) {
  591. $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
  592. if (!$disable_comp) {
  593. $this->_log("Compression is not supported by ZipArchive");
  594. }
  595. $zip = new ZipArchive();
  596. $result = $zip->open($backup_file, ZIPARCHIVE::OVERWRITE); // Tries to open $backup_file for acrhiving
  597. if ($result === true) {
  598. $result = $result && $zip->addFile(MWP_BACKUP_DIR.'/mwp_db/index.php', "mwp_db/index.php"); // Tries to add mwp_db/index.php to $backup_file
  599. $result = $result && $zip->addFile($db_result, "mwp_db/" . basename($db_result)); // Tries to add db dump form mwp_db dir to $backup_file
  600. $result = $result && $zip->close(); // Tries to close $backup_file
  601. } else {
  602. $result = false;
  603. }
  604. return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
  605. }
  606. /**
  607. * Zipping database dump and index.php in folder mwp_db by PclZip library.
  608. *
  609. * @param string $task_name the name of backup task
  610. * @param string $backup_file absolute path to zip file
  611. * @return bool is compress successful or not
  612. */
  613. function pclzip_backup_db($task_name, $backup_file) {
  614. $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
  615. define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
  616. require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
  617. $zip = new PclZip($backup_file);
  618. if ($disable_comp) {
  619. $result = $zip->add(MWP_BACKUP_DIR, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR, PCLZIP_OPT_NO_COMPRESSION) !== 0;
  620. } else {
  621. $result = $zip->add(MWP_BACKUP_DIR, PCLZIP_OPT_REMOVE_PATH, MWP_BACKUP_DIR) !== 0;
  622. }
  623. return $result;
  624. }
  625. /**
  626. * Zipping whole site root folder and append to backup file with database dump
  627. * by system zip command, requires zip installed on OS.
  628. *
  629. * @param string $task_name the name of backup task
  630. * @param string $backup_file absolute path to zip file
  631. * @param array $exclude array of files of folders to exclude, relative to site's root
  632. * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
  633. * @return array|bool true if successful or an array with error message if not
  634. */
  635. function zip_backup($task_name, $backup_file, $exclude, $include) {
  636. global $zip_errors;
  637. $sys = substr(PHP_OS, 0, 3);
  638. //Exclude paths
  639. $exclude_data = "-x";
  640. $exclude_file_data = '';
  641. // TODO: Prevent to $exclude include blank string '', beacuse zip 12 error will be occured.
  642. if (!empty($exclude)) {
  643. foreach ($exclude as $data) {
  644. if (is_dir(ABSPATH . $data)) {
  645. if ($sys == 'WIN')
  646. $exclude_data .= " $data/*.*";
  647. else
  648. $exclude_data .= " '$data/*'";
  649. } else {
  650. if ($sys == 'WIN'){
  651. if(file_exists(ABSPATH . $data)){
  652. $exclude_data .= " $data";
  653. $exclude_file_data .= " $data";
  654. }
  655. } else {
  656. if(file_exists(ABSPATH . $data)){
  657. $exclude_data .= " '$data'";
  658. $exclude_file_data .= " '$data'";
  659. }
  660. }
  661. }
  662. }
  663. }
  664. if($exclude_file_data){
  665. $exclude_file_data = "-x".$exclude_file_data;
  666. }
  667. //Include paths by default
  668. $add = array(
  669. trim(WPINC),
  670. trim(basename(WP_CONTENT_DIR)),
  671. "wp-admin"
  672. );
  673. $include_data = ". -i";
  674. foreach ($add as $data) {
  675. if ($sys == 'WIN')
  676. $include_data .= " $data/*.*";
  677. else
  678. $include_data .= " '$data/*'";
  679. }
  680. //Additional includes?
  681. if (!empty($include)) {
  682. foreach ($include as $data) {
  683. if ($data) {
  684. if ($sys == 'WIN')
  685. $include_data .= " $data/*.*";
  686. else
  687. $include_data .= " '$data/*'";
  688. }
  689. }
  690. }
  691. $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
  692. $comp_level = $disable_comp ? '-0' : '-1';
  693. $zip = $this->get_zip();
  694. chdir(ABSPATH);
  695. ob_start();
  696. $command = "$zip -q -j $comp_level $backup_file .* * $exclude_file_data";
  697. $this->_log("Executing $command");
  698. $result_f = $this->mmb_exec($command, false, true);
  699. if (!$result_f || $result_f == 18) { // disregard permissions error, file can't be accessed
  700. $command = "$zip -q -r $comp_level $backup_file $include_data $exclude_data";
  701. $result_d = $this->mmb_exec($command, false, true);
  702. $this->_log("Executing $command");
  703. if ($result_d && $result_d != 18) {
  704. @unlink($backup_file);
  705. if ($result_d > 0 && $result_d < 18)
  706. return array(
  707. 'error' => 'Failed to archive files (' . $zip_errors[$result_d] . ') .'
  708. );
  709. else {
  710. if ($result_d === -1) return false;
  711. return array(
  712. 'error' => 'Failed to archive files.'
  713. );
  714. }
  715. }
  716. } else {
  717. return false;
  718. }
  719. ob_get_clean();
  720. return true;
  721. }
  722. /**
  723. * Zipping whole site root folder and append to backup file with database dump
  724. * by ZipArchive class, requires php zip extension.
  725. *
  726. * @param string $task_name the name of backup task
  727. * @param string $backup_file absolute path to zip file
  728. * @param array $exclude array of files of folders to exclude, relative to site's root
  729. * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
  730. * @return array|bool true if successful or an array with error message if not
  731. */
  732. function zip_archive_backup($task_name, $backup_file, $exclude, $include, $overwrite = false) {
  733. $filelist = $this->get_backup_files($exclude, $include);
  734. $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
  735. if (!$disable_comp) {
  736. $this->_log("Compression is not supported by ZipArchive");
  737. }
  738. $zip = new ZipArchive();
  739. if ($overwrite) {
  740. $result = $zip->open($backup_file, ZipArchive::OVERWRITE); // Tries to open $backup_file for acrhiving
  741. } else {
  742. $result = $zip->open($backup_file); // Tries to open $backup_file for acrhiving
  743. }
  744. if ($result === true) {
  745. foreach ($filelist as $file) {
  746. $result = $result && $zip->addFile($file, sprintf("%s", str_replace(ABSPATH, '', $file))); // Tries to add a new file to $backup_file
  747. }
  748. $result = $result && $zip->close(); // Tries to close $backup_file
  749. } else {
  750. $result = false;
  751. }
  752. return $result; // true if $backup_file iz zipped successfully, false if error is occured in zip process
  753. }
  754. /**
  755. * Zipping whole site root folder and append to backup file with database dump
  756. * by PclZip library.
  757. *
  758. * @param string $task_name the name of backup task
  759. * @param string $backup_file absolute path to zip file
  760. * @param array $exclude array of files of folders to exclude, relative to site's root
  761. * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
  762. * @return array|bool true if successful or an array with error message if not
  763. */
  764. function pclzip_backup($task_name, $backup_file, $exclude, $include) {
  765. define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
  766. require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
  767. $zip = new PclZip($backup_file);
  768. $add = array(
  769. trim(WPINC),
  770. trim(basename(WP_CONTENT_DIR)),
  771. "wp-admin"
  772. );
  773. $include_data = array();
  774. if (!empty($include)) {
  775. foreach ($include as $data) {
  776. if ($data && file_exists(ABSPATH . $data))
  777. $include_data[] = ABSPATH . $data . '/';
  778. }
  779. }
  780. $include_data = array_merge($add, $include_data);
  781. if ($handle = opendir(ABSPATH)) {
  782. while (false !== ($file = readdir($handle))) {
  783. if ($file != "." && $file != ".." && !is_dir($file) && file_exists(ABSPATH . $file)) {
  784. $include_data[] = ABSPATH . $file;
  785. }
  786. }
  787. closedir($handle);
  788. }
  789. $disable_comp = $this->tasks[$task_name]['task_args']['disable_comp'];
  790. if ($disable_comp) {
  791. $result = $zip->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH, PCLZIP_OPT_NO_COMPRESSION) !== 0;
  792. } else {
  793. $result = $zip->add($include_data, PCLZIP_OPT_REMOVE_PATH, ABSPATH) !== 0;
  794. }
  795. $exclude_data = array();
  796. if (!empty($exclude)) {
  797. foreach ($exclude as $data) {
  798. if (file_exists(ABSPATH . $data)) {
  799. if (is_dir(ABSPATH . $data))
  800. $exclude_data[] = $data . '/';
  801. else
  802. $exclude_data[] = $data;
  803. }
  804. }
  805. }
  806. $result = $result && $zip->delete(PCLZIP_OPT_BY_NAME, $exclude_data);
  807. return $result;
  808. }
  809. /**
  810. * Gets an array of relative paths of all files in site root recursively.
  811. * By default, there are all files from root folder, all files from folders wp-admin, wp-content, wp-includes recursively.
  812. * Parameter $include adds other folders from site root, and excludes any file or folder by relative path to site's root.
  813. *
  814. * @param array $exclude array of files of folders to exclude, relative to site's root
  815. * @param array $include array of folders from site root which are included to backup (wp-admin, wp-content, wp-includes are default)
  816. * @return array array with all files in site root dir
  817. */
  818. function get_backup_files($exclude, $include) {
  819. $add = array(
  820. trim(WPINC),
  821. trim(basename(WP_CONTENT_DIR)),
  822. "wp-admin"
  823. );
  824. $include = array_merge($add, $include);
  825. $filelist = array();
  826. if ($handle = opendir(ABSPATH)) {
  827. while (false !== ($file = readdir($handle))) {
  828. if (is_dir($file) && file_exists(ABSPATH . $file) && !(in_array($file, $include))) {
  829. $exclude[] = $file;
  830. }
  831. }
  832. closedir($handle);
  833. }
  834. $filelist = get_all_files_from_dir(ABSPATH, $exclude);
  835. return $filelist;
  836. }
  837. /**
  838. * Backup a database dump of WordPress site.
  839. * All backups are compressed by zip and placed in wp-content/managewp/backups folder.
  840. *
  841. * @param string $task_name the name of backup task, which backup is done
  842. * @param string $backup_file relative path to file which backup is stored
  843. * @return bool|array true if backup is successful, or an array with error message if is failed
  844. */
  845. function backup_db_compress($task_name, $backup_file) {
  846. $this->update_status($task_name, $this->statuses['db_dump']);
  847. $db_result = $this->backup_db();
  848. if ($db_result == false) {
  849. return array(
  850. 'error' => 'Failed to backup database.'
  851. );
  852. } else if (is_array($db_result) && isset($db_result['error'])) {
  853. return array(
  854. 'error' => $db_result['error']
  855. );
  856. }
  857. $this->update_status($task_name, $this->statuses['db_dump'], true);
  858. $this->update_status($task_name, $this->statuses['db_zip']);
  859. @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
  860. $zip_db_result = $this->zip_backup_db($task_name, $backup_file);
  861. if (!$zip_db_result) {
  862. $zip_archive_db_result = false;
  863. if (class_exists("ZipArchive")) {
  864. $this->_log("DB zip, fallback to ZipArchive");
  865. $zip_archive_db_result = $this->zip_archive_backup_db($task_name, $db_result, $backup_file);
  866. }
  867. if (!$zip_archive_db_result) {
  868. $this->_log("DB zip, fallback to PclZip");
  869. $pclzip_db_result = $this->pclzip_backup_db($task_name, $backup_file);
  870. if (!$pclzip_db_result) {
  871. @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
  872. @unlink($db_result);
  873. @rmdir(MWP_DB_DIR);
  874. return array(
  875. 'error' => 'Failed to zip database. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
  876. );
  877. }
  878. }
  879. }
  880. @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
  881. @unlink($db_result);
  882. @rmdir(MWP_DB_DIR);
  883. $this->update_status($task_name, $this->statuses['db_zip'], true);
  884. return true;
  885. }
  886. /**
  887. * Creates database dump and places it in mwp_db folder in site's root.
  888. * This function dispatches if OS mysql command does not work calls a php alternative.
  889. *
  890. * @return string|array path to dump file if successful, or an array with error message if is failed
  891. */
  892. function backup_db() {
  893. $db_folder = MWP_DB_DIR . '/';
  894. if (!file_exists($db_folder)) {
  895. if (!mkdir($db_folder, 0755, true))
  896. return array(
  897. 'error' => 'Error creating database backup folder (' . $db_folder . '). Make sure you have corrrect write permissions.'
  898. );
  899. }
  900. $file = $db_folder . DB_NAME . '.sql';
  901. $result = $this->backup_db_dump($file); // try mysqldump always then fallback to php dump
  902. return $result;
  903. }
  904. /**
  905. * Creates database dump by system mysql command.
  906. *
  907. * @param string $file absolute path to file in which dump should be placed
  908. * @return string|array path to dump file if successful, or an array with error message if is failed
  909. */
  910. function backup_db_dump($file) {
  911. global $wpdb;
  912. $paths = $this->check_mysql_paths();
  913. $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
  914. $command = $brace . $paths['mysqldump'] . $brace . ' --force --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" --add-drop-table --skip-lock-tables "' . DB_NAME . '" > ' . $brace . $file . $brace;
  915. ob_start();
  916. $result = $this->mmb_exec($command);
  917. ob_get_clean();
  918. if (!$result) { // Fallback to php
  919. $this->_log("DB dump fallback to php");
  920. $result = $this->backup_db_php($file);
  921. return $result;
  922. }
  923. if (filesize($file) == 0 || !is_file($file) || !$result) {
  924. @unlink($file);
  925. return false;
  926. } else {
  927. return $file;
  928. }
  929. }
  930. /**
  931. * Creates database dump by php functions.
  932. *
  933. * @param string $file absolute path to file in which dump should be placed
  934. * @return string|array path to dump file if successful, or an array with error message if is failed
  935. */
  936. function backup_db_php($file) {
  937. global $wpdb;
  938. $tables = $wpdb->get_results('SHOW TABLES', ARRAY_N);
  939. foreach ($tables as $table) {
  940. //drop existing table
  941. $dump_data = "DROP TABLE IF EXISTS $table[0];";
  942. file_put_contents($file, $dump_data, FILE_APPEND);
  943. //create table
  944. $create_table = $wpdb->get_row("SHOW CREATE TABLE $table[0]", ARRAY_N);
  945. $dump_data = "\n\n" . $create_table[1] . ";\n\n";
  946. file_put_contents($file, $dump_data, FILE_APPEND);
  947. $count = $wpdb->get_var("SELECT count(*) FROM $table[0]");
  948. if ($count > 100)
  949. $count = ceil($count / 100);
  950. else if ($count > 0)
  951. $count = 1;
  952. for ($i = 0; $i < $count; $i++) {
  953. $low_limit = $i * 100;
  954. $qry = "SELECT * FROM $table[0] LIMIT $low_limit, 100";
  955. $rows = $wpdb->get_results($qry, ARRAY_A);
  956. if (is_array($rows)) {
  957. foreach ($rows as $row) {
  958. //insert single row
  959. $dump_data = "INSERT INTO $table[0] VALUES(";
  960. $num_values = count($row);
  961. $j = 1;
  962. foreach ($row as $value) {
  963. $value = addslashes($value);
  964. $value = preg_replace("/\n/Ui", "\\n", $value);
  965. $num_values == $j ? $dump_data .= "'" . $value . "'" : $dump_data .= "'" . $value . "', ";
  966. $j++;
  967. unset($value);
  968. }
  969. $dump_data .= ");\n";
  970. file_put_contents($file, $dump_data, FILE_APPEND);
  971. }
  972. }
  973. }
  974. $dump_data = "\n\n\n";
  975. file_put_contents($file, $dump_data, FILE_APPEND);
  976. unset($rows);
  977. unset($dump_data);
  978. }
  979. if (filesize($file) == 0 || !is_file($file)) {
  980. @unlink($file);
  981. return array(
  982. 'error' => 'Database backup failed. Try to enable MySQL dump on your server.'
  983. );
  984. }
  985. return $file;
  986. }
  987. /**
  988. * Restores full WordPress site or database only form backup zip file.
  989. *
  990. * @param array array of arguments passed to backup restore
  991. * [task_name] -> name of backup task
  992. * [result_id] -> id of baskup task result, which should be restored
  993. * [google_drive_token] -> json of Google Drive token, if it is remote destination
  994. * @return bool|array true if successful, or an array with error message if is failed
  995. */
  996. function restore($args) {
  997. global $wpdb;
  998. if (empty($args)) {
  999. return false;
  1000. }
  1001. extract($args);
  1002. if (isset($google_drive_token)) {
  1003. $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
  1004. }
  1005. $this->set_memory();
  1006. $unlink_file = true; //Delete file after restore
  1007. //Detect source
  1008. if ($backup_url) {
  1009. //This is for clone (overwrite)
  1010. include_once ABSPATH . 'wp-admin/includes/file.php';
  1011. $backup_file = download_url($backup_url);
  1012. if (is_wp_error($backup_file)) {
  1013. return array(
  1014. 'error' => 'Unable to download backup file ('.$backup_file->get_error_message().')'
  1015. );
  1016. }
  1017. $what = 'full';
  1018. } else {
  1019. $tasks = $this->tasks;
  1020. $task = $tasks[$task_name];
  1021. if (isset($task['task_results'][$result_id]['server'])) {
  1022. $backup_file = $task['task_results'][$result_id]['server']['file_path'];
  1023. $unlink_file = false; //Don't delete file if stored on server
  1024. } elseif (isset($task['task_results'][$result_id]['ftp'])) {
  1025. $ftp_file = $task['task_results'][$result_id]['ftp'];
  1026. $args = $task['task_args']['account_info']['mwp_ftp'];
  1027. $args['backup_file'] = $ftp_file;
  1028. $backup_file = $this->get_ftp_backup($args);
  1029. if ($backup_file == false) {
  1030. return array(
  1031. 'error' => 'Failed to download file from FTP.'
  1032. );
  1033. }
  1034. } elseif (isset($task['task_results'][$result_id]['amazons3'])) {
  1035. $amazons3_file = $task['task_results'][$result_id]['amazons3'];
  1036. $args = $task['task_args']['account_info']['mwp_amazon_s3'];
  1037. $args['backup_file'] = $amazons3_file;
  1038. $backup_file = $this->get_amazons3_backup($args);
  1039. if ($backup_file == false) {
  1040. return array(
  1041. 'error' => 'Failed to download file from Amazon S3.'
  1042. );
  1043. }
  1044. } elseif(isset($task['task_results'][$result_id]['dropbox'])){
  1045. $dropbox_file = $task['task_results'][$result_id]['dropbox'];
  1046. $args = $task['task_args']['account_info']['mwp_dropbox'];
  1047. $args['backup_file'] = $dropbox_file;
  1048. $backup_file = $this->get_dropbox_backup($args);
  1049. if ($backup_file == false) {
  1050. return array(
  1051. 'error' => 'Failed to download file from Dropbox.'
  1052. );
  1053. }
  1054. } elseif (isset($task['task_results'][$result_id]['google_drive'])) {
  1055. $google_drive_file = $task['task_results'][$result_id]['google_drive'];
  1056. $args = $task['task_args']['account_info']['mwp_google_drive'];
  1057. $args['backup_file'] = $google_drive_file;
  1058. $backup_file = $this->get_google_drive_backup($args);
  1059. if (is_array($backup_file) && isset($backup_file['error'])) {
  1060. return array(
  1061. 'error' => 'Failed to download file from Google Drive, reason: ' . $backup_file['error']
  1062. );
  1063. } elseif ($backup_file == false) {
  1064. return array(
  1065. 'error' => 'Failed to download file from Google Drive.'
  1066. );
  1067. }
  1068. }
  1069. $what = $tasks[$task_name]['task_args']['what'];
  1070. }
  1071. $this->wpdb_reconnect();
  1072. if ($backup_file && file_exists($backup_file)) {
  1073. if ($overwrite) {
  1074. //Keep old db credentials before overwrite
  1075. if (!copy(ABSPATH . 'wp-config.php', ABSPATH . 'mwp-temp-wp-config.php')) {
  1076. @unlink($backup_file);
  1077. return array(
  1078. 'error' => 'Error creating wp-config. Please check your write permissions.'
  1079. );
  1080. }
  1081. $db_host = DB_HOST;
  1082. $db_user = DB_USER;
  1083. $db_password = DB_PASSWORD;
  1084. $home = rtrim(get_option('home'), "/");
  1085. $site_url = get_option('site_url');
  1086. $clone_options = array();
  1087. if (trim($clone_from_url) || trim($mwp_clone)) {
  1088. $clone_options['_worker_nossl_key'] = get_option('_worker_nossl_key');
  1089. $clone_options['_worker_public_key'] = get_option('_worker_public_key');
  1090. $clone_options['_action_message_id'] = get_option('_action_message_id');
  1091. }
  1092. $clone_options['upload_path'] = get_option('upload_path');
  1093. $clone_options['upload_url_path'] = get_option('upload_url_path');
  1094. $clone_options['mwp_backup_tasks'] = serialize(get_option('mwp_backup_tasks'));
  1095. $clone_options['mwp_notifications'] = serialize(get_option('mwp_notifications'));
  1096. $clone_options['mwp_pageview_alerts'] = serialize(get_option('mwp_pageview_alerts'));
  1097. } else {
  1098. $restore_options = array();
  1099. $restore_options['mwp_notifications'] = get_option('mwp_notifications');
  1100. $restore_options['mwp_pageview_alerts'] = get_option('mwp_pageview_alerts');
  1101. $restore_options['user_hit_count'] = get_option('user_hit_count');
  1102. }
  1103. chdir(ABSPATH);
  1104. $unzip = $this->get_unzip();
  1105. $command = "$unzip -o $backup_file";
  1106. ob_start();
  1107. $result = $this->mmb_exec($command);
  1108. ob_get_clean();
  1109. if (!$result) { //fallback to pclzip
  1110. $this->_log("Files uznip fallback to pclZip");
  1111. define('PCLZIP_TEMPORARY_DIR', MWP_BACKUP_DIR . '/');
  1112. require_once ABSPATH . '/wp-admin/includes/class-pclzip.php';
  1113. $archive = new PclZip($backup_file);
  1114. $result = $archive->extract(PCLZIP_OPT_PATH, ABSPATH, PCLZIP_OPT_REPLACE_NEWER);
  1115. }
  1116. if ($unlink_file) {
  1117. @unlink($backup_file);
  1118. }
  1119. if (!$result) {
  1120. return array(
  1121. 'error' => 'Failed to unzip files. pclZip error (' . $archive->error_code . '): .' . $archive->error_string
  1122. );
  1123. }
  1124. $db_result = $this->restore_db();
  1125. if (!$db_result) {
  1126. return array(
  1127. 'error' => 'Error restoring database.'
  1128. );
  1129. } else if(is_array($db_result) && isset($db_result['error'])){
  1130. return array(
  1131. 'error' => $db_result['error']
  1132. );
  1133. }
  1134. } else {
  1135. return array(
  1136. 'error' => 'Error restoring. Cannot find backup file.'
  1137. );
  1138. }
  1139. $this->wpdb_reconnect();
  1140. //Replace options and content urls
  1141. if ($overwrite) {
  1142. //Get New Table prefix
  1143. $new_table_prefix = trim($this->get_table_prefix());
  1144. //Retrieve old wp_config
  1145. @unlink(ABSPATH . 'wp-config.php');
  1146. //Replace table prefix
  1147. $lines = file(ABSPATH . 'mwp-temp-wp-config.php');
  1148. foreach ($lines as $line) {
  1149. if (strstr($line, '$table_prefix')) {
  1150. $line = '$table_prefix = "' . $new_table_prefix . '";' . PHP_EOL;
  1151. }
  1152. file_put_contents(ABSPATH . 'wp-config.php', $line, FILE_APPEND);
  1153. }
  1154. @unlink(ABSPATH . 'mwp-temp-wp-config.php');
  1155. //Replace options
  1156. $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = 'home'";
  1157. $old = $wpdb->get_var($query);
  1158. $old = rtrim($old, "/");
  1159. $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = 'home'";
  1160. $wpdb->query($wpdb->prepare($query, $home));
  1161. $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = 'siteurl'";
  1162. $wpdb->query($wpdb->prepare($query, $home));
  1163. //Replace content urls
  1164. $regexp1 = 'src="(.*)$old(.*)"';
  1165. $regexp2 = 'href="(.*)$old(.*)"';
  1166. $query = "UPDATE " . $new_table_prefix . "posts SET post_content = REPLACE (post_content, %s,%s) WHERE post_content REGEXP %s OR post_content REGEXP %s";
  1167. $wpdb->query($wpdb->prepare($query, array($old, $home, $regexp1, $regexp2)));
  1168. if (trim($new_password)) {
  1169. $new_password = wp_hash_password($new_password);
  1170. }
  1171. if (!trim($clone_from_url) && !trim($mwp_clone)) {
  1172. if ($new_user && $new_password) {
  1173. $query = "UPDATE " . $new_table_prefix . "users SET user_login = %s, user_pass = %s WHERE user_login = %s";
  1174. $wpdb->query($wpdb->prepare($query, $new_user, $new_password, $old_user));
  1175. }
  1176. } else {
  1177. if ($clone_from_url) {
  1178. if ($new_user && $new_password) {
  1179. $query = "UPDATE " . $new_table_prefix . "users SET user_pass = %s WHERE user_login = %s";
  1180. $wpdb->query($wpdb->prepare($query, $new_password, $new_user));
  1181. }
  1182. }
  1183. if ($mwp_clone) {
  1184. if ($admin_email) {
  1185. //Clean Install
  1186. $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = 'admin_email'";
  1187. $wpdb->query($wpdb->prepare($query, $admin_email));
  1188. $query = "SELECT * FROM " . $new_table_prefix . "users LIMIT 1";
  1189. $temp_user = $wpdb->get_row($query);
  1190. if (!empty($temp_user)) {
  1191. $query = "UPDATE " . $new_table_prefix . "users SET user_email=%s, user_login = %s, user_pass = %s WHERE user_login = %s";
  1192. $wpdb->query($wpdb->prepare($query, $admin_email, $new_user, $new_password, $temp_user->user_login));
  1193. }
  1194. }
  1195. }
  1196. }
  1197. if (is_array($clone_options) && !empty($clone_options)) {
  1198. foreach ($clone_options as $key => $option) {
  1199. if (!empty($key)) {
  1200. $query = "SELECT option_value FROM " . $new_table_prefix . "options WHERE option_name = %s";
  1201. $res = $wpdb->get_var($wpdb->prepare($query, $key));
  1202. if ($res == false) {
  1203. $query = "INSERT INTO " . $new_table_prefix . "options (option_value,option_name) VALUES(%s,%s)";
  1204. $wpdb->query($wpdb->prepare($query, $option, $key));
  1205. } else {
  1206. $query = "UPDATE " . $new_table_prefix . "options SET option_value = %s WHERE option_name = %s";
  1207. $wpdb->query($wpdb->prepare($query, $option, $key));
  1208. }
  1209. }
  1210. }
  1211. }
  1212. //Remove hit count
  1213. $query = "DELETE FROM " . $new_table_prefix . "options WHERE option_name = 'user_hit_count'";
  1214. $wpdb->query($query);
  1215. //Check for .htaccess permalinks update
  1216. $this->replace_htaccess($home);
  1217. } else {
  1218. //restore worker options
  1219. if (is_array($restore_options) && !empty($restore_options)) {
  1220. foreach ($restore_options as $key => $option) {
  1221. update_option($key, $option);
  1222. }
  1223. }
  1224. }
  1225. return true;
  1226. }
  1227. /**
  1228. * This function dispathces database restoring between mysql system command and php functions.
  1229. * If system command fails, it calls the php alternative.
  1230. *
  1231. * @return bool|array true if successful, array with error message if not
  1232. */
  1233. function restore_db() {
  1234. global $wpdb;
  1235. $paths = $this->check_mysql_paths();
  1236. $file_path = ABSPATH . 'mwp_db';
  1237. @chmod($file_path,0755);
  1238. $file_name = glob($file_path . '/*.sql');
  1239. $file_name = $file_name[0];
  1240. if(!$file_name){
  1241. return array('error' => 'Cannot access database file.');
  1242. }
  1243. $brace = (substr(PHP_OS, 0, 3) == 'WIN') ? '"' : '';
  1244. $command = $brace . $paths['mysql'] . $brace . ' --host="' . DB_HOST . '" --user="' . DB_USER . '" --password="' . DB_PASSWORD . '" --default-character-set="utf8" ' . DB_NAME . ' < ' . $brace . $file_name . $brace;
  1245. ob_start();
  1246. $result = $this->mmb_exec($command);
  1247. ob_get_clean();
  1248. if (!$result) {
  1249. $this->_log('DB restore fallback to PHP');
  1250. //try php
  1251. $this->restore_db_php($file_name);
  1252. }
  1253. @unlink($file_name);
  1254. return true;
  1255. }
  1256. /**
  1257. * Restores database dump by php functions.
  1258. *
  1259. * @param string $file_name relative path to database dump, which should be restored
  1260. * @return bool is successful or not
  1261. */
  1262. function restore_db_php($file_name) {
  1263. global $wpdb;
  1264. $current_query = '';
  1265. // Read in entire file
  1266. $lines = file($file_name);
  1267. // Loop through each line
  1268. foreach ($lines as $line) {
  1269. // Skip it if it's a comment
  1270. if (substr($line, 0, 2) == '--' || $line == '')
  1271. continue;
  1272. // Add this line to the current query
  1273. $current_query .= $line;
  1274. // If it has a semicolon at the end, it's the end of the query
  1275. if (substr(trim($line), -1, 1) == ';') {
  1276. // Perform the query
  1277. $result = $wpdb->query($current_query);
  1278. if ($result === false)
  1279. return false;
  1280. // Reset temp variable to empty
  1281. $current_query = '';
  1282. }
  1283. }
  1284. @unlink($file_name);
  1285. return true;
  1286. }
  1287. /**
  1288. * Retruns table_prefix for this WordPress installation.
  1289. * It is used by restore.
  1290. *
  1291. * @return string table prefix from wp-config.php file, (default: wp_)
  1292. */
  1293. function get_table_prefix() {
  1294. $lines = file(ABSPATH . 'wp-config.php');
  1295. foreach ($lines as $line) {
  1296. if (strstr($line, '$table_prefix')) {
  1297. $pattern = "/(\'|\")[^(\'|\")]*/";
  1298. preg_match($pattern, $line, $matches);
  1299. $prefix = substr($matches[0], 1);
  1300. return $prefix;
  1301. break;
  1302. }
  1303. }
  1304. return 'wp_'; //default
  1305. }
  1306. /**
  1307. * Change all tables to InnoDB engine, and executes mysql OPTIMIZE TABLE for each table.
  1308. *
  1309. * @return bool optimized successfully or not
  1310. */
  1311. function optimize_tables() {
  1312. global $wpdb;
  1313. $query = 'SHOW TABLES';
  1314. $tables = $wpdb->get_results($query, ARRAY_A);
  1315. foreach ($tables as $table) {
  1316. if (in_array($table['Engine'], array(
  1317. 'MyISAM',
  1318. 'ISAM',
  1319. 'HEAP',
  1320. 'MEMORY',
  1321. 'ARCHIVE'
  1322. )))
  1323. $table_string .= $table['Name'] . ",";
  1324. elseif ($table['Engine'] == 'InnoDB') {
  1325. $optimize = $wpdb->query("ALTER TABLE {$table['Name']} ENGINE=InnoDB");
  1326. }
  1327. }
  1328. $table_string = rtrim($table_string);
  1329. $optimize = $wpdb->query("OPTIMIZE TABLE $table_string");
  1330. return $optimize ? true : false;
  1331. }
  1332. /**
  1333. * Returns mysql and mysql dump command path on OS.
  1334. *
  1335. * @return array array with system mysql and mysqldump command, blank if does not exist
  1336. */
  1337. function check_mysql_paths() {
  1338. global $wpdb;
  1339. $paths = array(
  1340. 'mysql' => '',
  1341. 'mysqldump' => ''
  1342. );
  1343. if (substr(PHP_OS, 0, 3) == 'WIN') {
  1344. $mysql_install = $wpdb->get_row("SHOW VARIABLES LIKE 'basedir'");
  1345. if ($mysql_install) {
  1346. $install_path = str_replace('\\', '/', $mysql_install->Value);
  1347. $paths['mysql'] = $install_path . 'bin/mysql.exe';
  1348. $paths['mysqldump'] = $install_path . 'bin/mysqldump.exe';
  1349. } else {
  1350. $paths['mysql'] = 'mysql.exe';
  1351. $paths['mysqldump'] = 'mysqldump.exe';
  1352. }
  1353. } else {
  1354. $paths['mysql'] = $this->mmb_exec('which mysql', true);
  1355. if (empty($paths['mysql']))
  1356. $paths['mysql'] = 'mysql'; // try anyway
  1357. $paths['mysqldump'] = $this->mmb_exec('which mysqldump', true);
  1358. if (empty($paths['mysqldump']))
  1359. $paths['mysqldump'] = 'mysqldump'; // try anyway
  1360. }
  1361. return $paths;
  1362. }
  1363. /**
  1364. * Check if exec, system, passthru functions exist
  1365. *
  1366. * @return string|bool exec if exists, then system, then passthru, then false if no one exist
  1367. */
  1368. function check_sys() {
  1369. if ($this->mmb_function_exists('exec'))
  1370. return 'exec';
  1371. if ($this->mmb_function_exists('system'))
  1372. return 'system';
  1373. if ($this->mmb_function_exists('passhtru'))
  1374. return 'passthru';
  1375. return false;
  1376. }
  1377. /**
  1378. * Executes an external system command.
  1379. *
  1380. * @param string $command external command to execute
  1381. * @param bool[optional] $string return as a system output string (default: false)
  1382. * @param bool[optional] $rawreturn return as a status of executed command
  1383. * @return bool|int|string output depends on parameters $string and $rawreturn, -1 if no one execute function is enabled
  1384. */
  1385. function mmb_exec($command, $string = false, $rawreturn = false) {
  1386. if ($command == '')
  1387. return false;
  1388. if ($this->mmb_function_exists('exec')) {
  1389. $log = @exec($command, $output, $return);
  1390. $this->_log("Type: exec");
  1391. $this->_log("Command: ".$command);
  1392. $this->_log("Return: ".$return);
  1393. if ($string)
  1394. return $log;
  1395. if ($rawreturn)
  1396. return $return;
  1397. return $return ? false : true;
  1398. } elseif ($this->mmb_function_exists('system')) {
  1399. $log = @system($command, $return);
  1400. $this->_log("Type: system");
  1401. $this->_log("Command: ".$command);
  1402. $this->_log("Return: ".$return);
  1403. if ($string)
  1404. return $log;
  1405. if ($rawreturn)
  1406. return $return;
  1407. return $return ? false : true;
  1408. } elseif ($this->mmb_function_exists('passthru') && !$string) {
  1409. $log = passthru($command, $return);
  1410. $this->_log("Type: passthru");
  1411. $this->_log("Command: ".$command);
  1412. $this->_log("Return: ".$return);
  1413. if ($rawreturn)
  1414. return $return;
  1415. return $return ? false : true;
  1416. }
  1417. if ($rawreturn)
  1418. return -1;
  1419. return false;
  1420. }
  1421. /**
  1422. * Returns a path to system command for zip execution.
  1423. *
  1424. * @return string command for zip execution
  1425. */
  1426. function get_zip() {
  1427. $zip = $this->mmb_exec('which zip', true);
  1428. if (!$zip)
  1429. $zip = "zip";
  1430. return $zip;
  1431. }
  1432. /**
  1433. * Returns a path to system command for unzip execution.
  1434. *
  1435. * @return string command for unzip execution
  1436. */
  1437. function get_unzip() {
  1438. $unzip = $this->mmb_exec('which unzip', true);
  1439. if (!$unzip)
  1440. $unzip = "unzip";
  1441. return $unzip;
  1442. }
  1443. /**
  1444. * Returns all important information of worker's system status to master.
  1445. *
  1446. * @return mixed associative array with information of server OS, php version, is backup folder writable, execute function, zip and unzip command, execution time, memory limit and path to error log if exists
  1447. */
  1448. function check_backup_compat() {
  1449. $reqs = array();
  1450. if (strpos($_SERVER['DOCUMENT_ROOT'], '/') === 0) {
  1451. $reqs['Server OS']['status'] = 'Linux (or compatible)';
  1452. $reqs['Server OS']['pass'] = true;
  1453. } else {
  1454. $reqs['Server OS']['status'] = 'Windows';
  1455. $reqs['Server OS']['pass'] = true;
  1456. $pass = false;
  1457. }
  1458. $reqs['PHP Version']['status'] = phpversion();
  1459. if ((float) phpversion() >= 5.1) {
  1460. $reqs['PHP Version']['pass'] = true;
  1461. } else {
  1462. $reqs['PHP Version']['pass'] = false;
  1463. $pass = false;
  1464. }
  1465. if (is_writable(WP_CONTENT_DIR)) {
  1466. $reqs['Backup Folder']['status'] = "writable";
  1467. $reqs['Backup Folder']['pass'] = true;
  1468. } else {
  1469. $reqs['Backup Folder']['status'] = "not writable";
  1470. $reqs['Backup Folder']['pass'] = false;
  1471. }
  1472. $file_path = MWP_BACKUP_DIR;
  1473. $reqs['Backup Folder']['status'] .= ' (' . $file_path . ')';
  1474. if ($func = $this->check_sys()) {
  1475. $reqs['Execute Function']['status'] = $func;
  1476. $reqs['Execute Function']['pass'] = true;
  1477. } else {
  1478. $reqs['Execute Function']['status'] = "not found";
  1479. $reqs['Execute Function']['info'] = "(will try PHP replacement)";
  1480. $reqs['Execute Function']['pass'] = false;
  1481. }
  1482. $reqs['Zip']['status'] = $this->get_zip();
  1483. $reqs['Zip']['pass'] = true;
  1484. $reqs['Unzip']['status'] = $this->get_unzip();
  1485. $reqs['Unzip']['pass'] = true;
  1486. $paths = $this->check_mysql_paths();
  1487. if (!empty($paths['mysqldump'])) {
  1488. $reqs['MySQL Dump']['status'] = $paths['mysqldump'];
  1489. $reqs['MySQL Dump']['pass'] = true;
  1490. } else {
  1491. $reqs['MySQL Dump']['status'] = "not found";
  1492. $reqs['MySQL Dump']['info'] = "(will try PHP replacement)";
  1493. $reqs['MySQL Dump']['pass'] = false;
  1494. }
  1495. $exec_time = ini_get('max_execution_time');
  1496. $reqs['Execution time']['status'] = $exec_time ? $exec_time . "s" : 'unknown';
  1497. $reqs['Execution time']['pass'] = true;
  1498. $mem_limit = ini_get('memory_limit');
  1499. $reqs['Memory limit']['status'] = $mem_limit ? $mem_limit : 'unknown';
  1500. $reqs['Memory limit']['pass'] = true;
  1501. $changed = $this->set_memory();
  1502. if($changed['execution_time']){
  1503. $exec_time = ini_get('max_execution_time');
  1504. $reqs['Execution time']['status'] .= $exec_time ? ' (will try '.$exec_time . 's)' : ' (unknown)';
  1505. }
  1506. if($changed['memory_limit']){
  1507. $mem_limit = ini_get('memory_limit');
  1508. $reqs['Memory limit']['status'] .= $mem_limit ? ' (will try '.$mem_limit.')' : ' (unknown)';
  1509. }
  1510. if(defined('MWP_SHOW_LOG') && MWP_SHOW_LOG == true){
  1511. $md5 = get_option('mwp_log_md5');
  1512. if ($md5 !== false) {
  1513. global $mmb_plugin_url;
  1514. $md5 = "<a href='$mmb_plugin_url/log_$md5' target='_blank'>$md5</a>";
  1515. } else {
  1516. $md5 = "not created";
  1517. }
  1518. $reqs['Backup Log']['status'] = $md5;
  1519. $reqs['Backup Log']['pass'] = true;
  1520. }
  1521. return $reqs;
  1522. }
  1523. /**
  1524. * Uploads backup file from server to email.
  1525. * A lot of email service have limitation to 10mb.
  1526. *
  1527. * @param array $args arguments passed to the function
  1528. * [email] -> email address which backup should send to
  1529. * [task_name] -> name of backup task
  1530. * [file_path] -> absolute path of backup file on local server
  1531. * @return bool|array true is successful, array with error message if not
  1532. */
  1533. function email_backup($args) {
  1534. $email = $args['email'];
  1535. if (!is_email($email)) {
  1536. return array(
  1537. 'error' => 'Your email (' . $email . ') is not correct'
  1538. );
  1539. }
  1540. $backup_file = $args['file_path'];
  1541. $task_name = isset($args['task_name']) ? $args['task_name'] : '';
  1542. if (file_exists($backup_file) && $email) {
  1543. $attachments = array(
  1544. $backup_file
  1545. );
  1546. $headers = 'From: ManageWP <no-reply@managewp.com>' . "\r\n";
  1547. $subject = "ManageWP - " . $task_name . " - " . $this->site_name;
  1548. ob_start();
  1549. $result = wp_mail($email, $subject, $subject, $headers, $attachments);
  1550. ob_end_clean();
  1551. }
  1552. if (!$result) {
  1553. return array(
  1554. 'error' => 'Email not sent. Maybe your backup is too big for email or email server is not available on your website.'
  1555. );
  1556. }
  1557. return true;
  1558. }
  1559. /**
  1560. * Uploads backup file from server to remote ftp server.
  1561. *
  1562. * @param array $args arguments passed to the function
  1563. * [ftp_username] -> ftp username on remote server
  1564. * [ftp_password] -> ftp password on remote server
  1565. * [ftp_hostname] -> ftp hostname of remote host
  1566. * [ftp_remote_folder] -> folder on remote site which backup file should be upload to
  1567. * [ftp_site_folder] -> subfolder with site name in ftp_remote_folder which backup file should be upload to
  1568. * [ftp_passive] -> passive mode or not
  1569. * [ftp_ssl] -> ssl or not
  1570. * [ftp_port] -> number of port for ssl protocol
  1571. * [backup_file] -> absolute path of backup file on local server
  1572. * @return bool|array true is successful, array with error message if not
  1573. */
  1574. function ftp_backup($args) {
  1575. extract($args);
  1576. $port = $ftp_port ? $ftp_port : 21; //default port is 21
  1577. if ($ftp_ssl) {
  1578. if (function_exists('ftp_ssl_connect')) {
  1579. $conn_id = ftp_ssl_connect($ftp_hostname,$port);
  1580. if ($conn_id === false) {
  1581. return array(
  1582. 'error' => 'Failed to connect to ' . $ftp_hostname,
  1583. 'partial' => 1
  1584. );
  1585. }
  1586. } else {
  1587. return array(
  1588. 'error' => 'FTPS disabled: Please enable ftp_ssl_connect in PHP',
  1589. 'partial' => 1
  1590. );
  1591. }
  1592. } else {
  1593. if (function_exists('ftp_connect')) {
  1594. $conn_id = ftp_connect($ftp_hostname,$port);
  1595. if ($conn_id === false) {
  1596. return array(
  1597. 'error' => 'Failed to connect to ' . $ftp_hostname,
  1598. 'partial' => 1
  1599. );
  1600. }
  1601. } else {
  1602. return array(
  1603. 'error' => 'FTP disabled: Please enable ftp_connect in PHP',
  1604. 'partial' => 1
  1605. );
  1606. }
  1607. }
  1608. $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
  1609. if ($login === false) {
  1610. return array(
  1611. 'error' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
  1612. 'partial' => 1
  1613. );
  1614. }
  1615. if($ftp_passive){
  1616. @ftp_pasv($conn_id,true);
  1617. }
  1618. @ftp_mkdir($conn_id, $ftp_remote_folder);
  1619. if ($ftp_site_folder) {
  1620. $ftp_remote_folder .= '/' . $this->site_name;
  1621. }
  1622. @ftp_mkdir($conn_id, $ftp_remote_folder);
  1623. $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_BINARY);
  1624. if ($upload === false) { //Try ascii
  1625. $upload = @ftp_put($conn_id, $ftp_remote_folder . '/' . basename($backup_file), $backup_file, FTP_ASCII);
  1626. }
  1627. @ftp_close($conn_id);
  1628. if ($upload === false) {
  1629. return array(
  1630. 'error' => 'Failed to upload file to FTP. Please check your specified path.',
  1631. 'partial' => 1
  1632. );
  1633. }
  1634. return true;
  1635. }
  1636. /**
  1637. * Deletes backup file from remote ftp server.
  1638. *
  1639. * @param array $args arguments passed to the function
  1640. * [ftp_username] -> ftp username on remote server
  1641. * [ftp_password] -> ftp password on remote server
  1642. * [ftp_hostname] -> ftp hostname of remote host
  1643. * [ftp_remote_folder] -> folder on remote site which backup file should be deleted from
  1644. * [ftp_site_folder] -> subfolder with site name in ftp_remote_folder which backup file should be deleted from
  1645. * [backup_file] -> absolute path of backup file on local server
  1646. * @return void
  1647. */
  1648. function remove_ftp_backup($args) {
  1649. extract($args);
  1650. $port = $ftp_port ? $ftp_port : 21; //default port is 21
  1651. if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
  1652. $conn_id = ftp_ssl_connect($ftp_hostname,$port);
  1653. } else if (function_exists('ftp_connect')) {
  1654. $conn_id = ftp_connect($ftp_hostname,$port);
  1655. }
  1656. if ($conn_id) {
  1657. $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
  1658. if ($ftp_site_folder)
  1659. $ftp_remote_folder .= '/' . $this->site_name;
  1660. if($ftp_passive){
  1661. @ftp_pasv($conn_id,true);
  1662. }
  1663. $delete = ftp_delete($conn_id, $ftp_remote_folder . '/' . $backup_file);
  1664. ftp_close($conn_id);
  1665. }
  1666. }
  1667. /**
  1668. * Downloads backup file from server from remote ftp server to root folder on local server.
  1669. *
  1670. * @param array $args arguments passed to the function
  1671. * [ftp_username] -> ftp username on remote server
  1672. * [ftp_password] -> ftp password on remote server
  1673. * [ftp_hostname] -> ftp hostname of remote host
  1674. * [ftp_remote_folder] -> folder on remote site which backup file should be downloaded from
  1675. * [ftp_site_folder] -> subfolder with site name in ftp_remote_folder which backup file should be downloaded from
  1676. * [backup_file] -> absolute path of backup file on local server
  1677. * @return string|array absolute path to downloaded file is successful, array with error message if not
  1678. */
  1679. function get_ftp_backup($args) {
  1680. extract($args);
  1681. $port = $ftp_port ? $ftp_port : 21; //default port is 21
  1682. if ($ftp_ssl && function_exists('ftp_ssl_connect')) {
  1683. $conn_id = ftp_ssl_connect($ftp_hostname,$port);
  1684. } else if (function_exists('ftp_connect')) {
  1685. $conn_id = ftp_connect($ftp_hostname,$port);
  1686. if ($conn_id === false) {
  1687. return false;
  1688. }
  1689. }
  1690. $login = @ftp_login($conn_id, $ftp_username, $ftp_password);
  1691. if ($login === false) {
  1692. return false;
  1693. }
  1694. if ($ftp_site_folder)
  1695. $ftp_remote_folder .= '/' . $this->site_name;
  1696. if($ftp_passive){
  1697. @ftp_pasv($conn_id,true);
  1698. }
  1699. $temp = ABSPATH . 'mwp_temp_backup.zip';
  1700. $get = ftp_get($conn_id, $temp, $ftp_remote_folder . '/' . $backup_file, FTP_BINARY);
  1701. if ($get === false) {
  1702. return false;
  1703. }
  1704. ftp_close($conn_id);
  1705. return $temp;
  1706. }
  1707. /**
  1708. * Uploads backup file from server to Dropbox.
  1709. *
  1710. * @param array $args arguments passed to the function
  1711. * [consumer_key] -> consumer key of ManageWP Dropbox application
  1712. * [consumer_secret] -> consumer secret of ManageWP Dropbox application
  1713. * [oauth_token] -> oauth token of user on ManageWP Dropbox application
  1714. * [oauth_token_secret] -> oauth token secret of user on ManageWP Dropbox application
  1715. * [dropbox_destination] -> folder on user's Dropbox account which backup file should be upload to
  1716. * [dropbox_site_folder] -> subfolder with site name in dropbox_destination which backup file should be upload to
  1717. * [backup_file] -> absolute path of backup file on local server
  1718. * @return bool|array true is successful, array with error message if not
  1719. */
  1720. function dropbox_backup($args) {
  1721. extract($args);
  1722. global $mmb_plugin_dir;
  1723. require_once $mmb_plugin_dir . '/lib/dropbox.php';
  1724. $dropbox = new Dropbox($consumer_key, $consumer_secret);
  1725. $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
  1726. if ($dropbox_site_folder == true)
  1727. $dropbox_destination .= '/' . $this->site_name . '/' . basename($backup_file);
  1728. else
  1729. $dropbox_destination .= '/' . basename($backup_file);
  1730. try {
  1731. $dropbox->upload($backup_file, $dropbox_destination, true);
  1732. } catch (Exception $e) {
  1733. $this->_log($e->getMessage());
  1734. return array(
  1735. 'error' => $e->getMessage(),
  1736. 'partial' => 1
  1737. );
  1738. }
  1739. return true;
  1740. }
  1741. /**
  1742. * Deletes backup file from Dropbox to root folder on local server.
  1743. *
  1744. * @param array $args arguments passed to the function
  1745. * [consumer_key] -> consumer key of ManageWP Dropbox application
  1746. * [consumer_secret] -> consumer secret of ManageWP Dropbox application
  1747. * [oauth_token] -> oauth token of user on ManageWP Dropbox application
  1748. * [oauth_token_secret] -> oauth token secret of user on ManageWP Dropbox application
  1749. * [dropbox_destination] -> folder on user's Dropbox account which backup file should be downloaded from
  1750. * [dropbox_site_folder] -> subfolder with site name in dropbox_destination which backup file should be downloaded from
  1751. * [backup_file] -> absolute path of backup file on local server
  1752. * @return void
  1753. */
  1754. function remove_dropbox_backup($args) {
  1755. extract($args);
  1756. global $mmb_plugin_dir;
  1757. require_once $mmb_plugin_dir . '/lib/dropbox.php';
  1758. $dropbox = new Dropbox($consumer_key, $consumer_secret);
  1759. $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
  1760. if ($dropbox_site_folder == true)
  1761. $dropbox_destination .= '/' . $this->site_name;
  1762. try {
  1763. $dropbox->fileopsDelete($dropbox_destination . '/' . $backup_file);
  1764. } catch (Exception $e) {
  1765. $this->_log($e->getMessage());
  1766. /*return array(
  1767. 'error' => $e->getMessage(),
  1768. 'partial' => 1
  1769. );*/
  1770. }
  1771. //return true;
  1772. }
  1773. /**
  1774. * Downloads backup file from Dropbox to root folder on local server.
  1775. *
  1776. * @param array $args arguments passed to the function
  1777. * [consumer_key] -> consumer key of ManageWP Dropbox application
  1778. * [consumer_secret] -> consumer secret of ManageWP Dropbox application
  1779. * [oauth_token] -> oauth token of user on ManageWP Dropbox application
  1780. * [oauth_token_secret] -> oauth token secret of user on ManageWP Dropbox application
  1781. * [dropbox_destination] -> folder on user's Dropbox account which backup file should be deleted from
  1782. * [dropbox_site_folder] -> subfolder with site name in dropbox_destination which backup file should be deleted from
  1783. * [backup_file] -> absolute path of backup file on local server
  1784. * @return bool|array absolute path to downloaded file is successful, array with error message if not
  1785. */
  1786. function get_dropbox_backup($args) {
  1787. extract($args);
  1788. global $mmb_plugin_dir;
  1789. require_once $mmb_plugin_dir . '/lib/dropbox.php';
  1790. $dropbox = new Dropbox($consumer_key, $consumer_secret);
  1791. $dropbox->setOAuthTokens($oauth_token, $oauth_token_secret);
  1792. if ($dropbox_site_folder == true)
  1793. $dropbox_destination .= '/' . $this->site_name;
  1794. $temp = ABSPATH . 'mwp_temp_backup.zip';
  1795. try {
  1796. $file = $dropbox->download($dropbox_destination.'/'.$backup_file);
  1797. $handle = @fopen($temp, 'w');
  1798. $result = fwrite($handle,$file);
  1799. fclose($handle);
  1800. if($result)
  1801. return $temp;
  1802. else
  1803. return false;
  1804. } catch (Exception $e) {
  1805. $this->_log($e->getMessage());
  1806. return array(
  1807. 'error' => $e->getMessage(),
  1808. 'partial' => 1
  1809. );
  1810. }
  1811. }
  1812. /**
  1813. * Uploads backup file from server to Amazon S3.
  1814. *
  1815. * @param array $args arguments passed to the function
  1816. * [as3_bucket_region] -> Amazon S3 bucket region
  1817. * [as3_bucket] -> Amazon S3 bucket
  1818. * [as3_access_key] -> Amazon S3 access key
  1819. * [as3_secure_key] -> Amazon S3 secure key
  1820. * [as3_directory] -> folder on user's Amazon S3 account which backup file should be upload to
  1821. * [as3_site_folder] -> subfolder with site name in as3_directory which backup file should be upload to
  1822. * [backup_file] -> absolute path of backup file on local server
  1823. * @return bool|array true is successful, array with error message if not
  1824. */
  1825. function amazons3_backup($args) {
  1826. if ($this->mmb_function_exists('curl_init')) {
  1827. require_once('lib/s3.php');
  1828. extract($args);
  1829. if ($as3_site_folder == true)
  1830. $as3_directory .= '/' . $this->site_name;
  1831. $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
  1832. try{
  1833. $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
  1834. if ($s3->putObjectFile($backup_file, $as3_bucket, $as3_directory . '/' . basename($backup_file), mwpS3::ACL_PRIVATE)) {
  1835. return true;
  1836. } else {
  1837. return array(
  1838. 'error' => 'Failed to upload to Amazon S3. Please check your details and set upload/delete permissions on your bucket.',
  1839. 'partial' => 1
  1840. );
  1841. }
  1842. } catch (Exception $e) {
  1843. $err = $e->getMessage();
  1844. if($err){
  1845. return array(
  1846. 'error' => 'Failed to upload to AmazonS3 ('.$err.').'
  1847. );
  1848. } else {
  1849. return array(
  1850. 'error' => 'Failed to upload to Amazon S3.'
  1851. );
  1852. }
  1853. }
  1854. } else {
  1855. return array(
  1856. 'error' => 'You cannot use Amazon S3 on your server. Please enable curl extension first.',
  1857. 'partial' => 1
  1858. );
  1859. }
  1860. }
  1861. /**
  1862. * Deletes backup file from Amazon S3.
  1863. *
  1864. * @param array $args arguments passed to the function
  1865. * [as3_bucket_region] -> Amazon S3 bucket region
  1866. * [as3_bucket] -> Amazon S3 bucket
  1867. * [as3_access_key] -> Amazon S3 access key
  1868. * [as3_secure_key] -> Amazon S3 secure key
  1869. * [as3_directory] -> folder on user's Amazon S3 account which backup file should be deleted from
  1870. * [as3_site_folder] -> subfolder with site name in as3_directory which backup file should be deleted from
  1871. * [backup_file] -> absolute path of backup file on local server
  1872. * @return void
  1873. */
  1874. function remove_amazons3_backup($args) {
  1875. if ($this->mmb_function_exists('curl_init')) {
  1876. require_once('lib/s3.php');
  1877. extract($args);
  1878. if ($as3_site_folder == true)
  1879. $as3_directory .= '/' . $this->site_name;
  1880. $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
  1881. try {
  1882. $s3 = new mwpS3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
  1883. $s3->deleteObject($as3_bucket, $as3_directory . '/' . $backup_file);
  1884. } catch (Exception $e){
  1885. }
  1886. }
  1887. }
  1888. /**
  1889. * Downloads backup file from Amazon S3 to root folder on local server.
  1890. *
  1891. * @param array $args arguments passed to the function
  1892. * [as3_bucket_region] -> Amazon S3 bucket region
  1893. * [as3_bucket] -> Amazon S3 bucket
  1894. * [as3_access_key] -> Amazon S3 access key
  1895. * [as3_secure_key] -> Amazon S3 secure key
  1896. * [as3_directory] -> folder on user's Amazon S3 account which backup file should be downloaded from
  1897. * [as3_site_folder] -> subfolder with site name in as3_directory which backup file should be downloaded from
  1898. * [backup_file] -> absolute path of backup file on local server
  1899. * @return bool|array absolute path to downloaded file is successful, array with error message if not
  1900. */
  1901. function get_amazons3_backup($args) {
  1902. require_once('lib/s3.php');
  1903. extract($args);
  1904. $endpoint = isset($as3_bucket_region) ? $as3_bucket_region : 's3.amazonaws.com';
  1905. $temp = '';
  1906. try {
  1907. $s3 = new mwpS3($as3_access_key, str_replace(' ', '+', $as3_secure_key), false, $endpoint);
  1908. if ($as3_site_folder == true)
  1909. $as3_directory .= '/' . $this->site_name;
  1910. $temp = ABSPATH . 'mwp_temp_backup.zip';
  1911. $s3->getObject($as3_bucket, $as3_directory . '/' . $backup_file, $temp);
  1912. } catch (Exception $e) {
  1913. return $temp;
  1914. }
  1915. return $temp;
  1916. }
  1917. /**
  1918. * Uploads backup file from server to Google Drive.
  1919. *
  1920. * @param array $args arguments passed to the function
  1921. * [google_drive_token] -> user's Google drive token in json form
  1922. * [google_drive_directory] -> folder on user's Google Drive account which backup file should be upload to
  1923. * [google_drive_site_folder] -> subfolder with site name in google_drive_directory which backup file should be upload to
  1924. * [backup_file] -> absolute path of backup file on local server
  1925. * @return bool|array true is successful, array with error message if not
  1926. */
  1927. function google_drive_backup($args) {
  1928. extract($args);
  1929. global $mmb_plugin_dir;
  1930. require_once("$mmb_plugin_dir/lib/google-api-client/Google_Client.php");
  1931. require_once("$mmb_plugin_dir/lib/google-api-client/contrib/Google_DriveService.php");
  1932. $gdrive_client = new Google_Client();
  1933. $gdrive_client->setUseObjects(true);
  1934. $gdrive_client->setAccessToken($google_drive_token);
  1935. $gdrive_service = new Google_DriveService($gdrive_client);
  1936. try {
  1937. $about = $gdrive_service->about->get();
  1938. $root_folder_id = $about->getRootFolderId();
  1939. } catch (Exception $e) {
  1940. return array(
  1941. 'error' => $e->getMessage(),
  1942. );
  1943. }
  1944. try {
  1945. $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$google_drive_directory' and '$root_folder_id' in parents and trashed = false"));
  1946. $files = $list_files->getItems();
  1947. } catch (Exception $e) {
  1948. return array(
  1949. 'error' => $e->getMessage(),
  1950. );
  1951. }
  1952. if (isset($files[0])) {
  1953. $managewp_folder = $files[0];
  1954. }
  1955. if (!isset($managewp_folder)) {
  1956. try {
  1957. $_managewp_folder = new Google_DriveFile();
  1958. $_managewp_folder->setTitle($google_drive_directory);
  1959. $_managewp_folder->setMimeType('application/vnd.google-apps.folder');
  1960. if ($root_folder_id != null) {
  1961. $parent = new Google_ParentReference();
  1962. $parent->setId($root_folder_id);
  1963. $_managewp_folder->setParents(array($parent));
  1964. }
  1965. $managewp_folder = $gdrive_service->files->insert($_managewp_folder, array());
  1966. } catch (Exception $e) {
  1967. return array(
  1968. 'error' => $e->getMessage(),
  1969. );
  1970. }
  1971. }
  1972. if ($google_drive_site_folder) {
  1973. try {
  1974. $subfolder_title = $this->site_name;
  1975. $managewp_folder_id = $managewp_folder->getId();
  1976. $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$subfolder_title' and '$managewp_folder_id' in parents and trashed = false"));
  1977. $files = $list_files->getItems();
  1978. } catch (Exception $e) {
  1979. return array(
  1980. 'error' => $e->getMessage(),
  1981. );
  1982. }
  1983. if (isset($files[0])) {
  1984. $backup_folder = $files[0];
  1985. } else {
  1986. try {
  1987. $_backup_folder = new Google_DriveFile();
  1988. $_backup_folder->setTitle($subfolder_title);
  1989. $_backup_folder->setMimeType('application/vnd.google-apps.folder');
  1990. if (isset($managewp_folder)) {
  1991. $_backup_folder->setParents(array($managewp_folder));
  1992. }
  1993. $backup_folder = $gdrive_service->files->insert($_backup_folder, array());
  1994. } catch (Exception $e) {
  1995. return array(
  1996. 'error' => $e->getMessage(),
  1997. );
  1998. }
  1999. }
  2000. } else {
  2001. $backup_folder = $managewp_folder;
  2002. }
  2003. $file_path = explode('/', $backup_file);
  2004. $new_file = new Google_DriveFile();
  2005. $new_file->setTitle(end($file_path));
  2006. $new_file->setDescription('Backup file of site: ' . $this->site_name . '.');
  2007. if ($backup_folder != null) {
  2008. $new_file->setParents(array($backup_folder));
  2009. }
  2010. $tries = 1;
  2011. while($tries <= 2) {
  2012. try {
  2013. $data = file_get_contents($backup_file);
  2014. $createdFile = $gdrive_service->files->insert($new_file, array(
  2015. 'data' => $data,
  2016. ));
  2017. break;
  2018. } catch (Exception $e) {
  2019. if ($e->getCode() >= 500 && $e->getCode() <= 504 && $mmb_gdrive_upload_tries <= 2) {
  2020. sleep(2);
  2021. $tries++;
  2022. } else {
  2023. return array(
  2024. 'error' => $e->getMessage(),
  2025. );
  2026. }
  2027. }
  2028. }
  2029. return true;
  2030. }
  2031. /**
  2032. * Deletes backup file from Google Drive.
  2033. *
  2034. * @param array $args arguments passed to the function
  2035. * [google_drive_token] -> user's Google drive token in json form
  2036. * [google_drive_directory] -> folder on user's Google Drive account which backup file should be deleted from
  2037. * [google_drive_site_folder] -> subfolder with site name in google_drive_directory which backup file should be deleted from
  2038. * [backup_file] -> absolute path of backup file on local server
  2039. * @return void
  2040. */
  2041. function remove_google_drive_backup($args) {
  2042. extract($args);
  2043. global $mmb_plugin_dir;
  2044. require_once("$mmb_plugin_dir/lib/google-api-client/Google_Client.php");
  2045. require_once("$mmb_plugin_dir/lib/google-api-client/contrib/Google_DriveService.php");
  2046. try {
  2047. $gdrive_client = new Google_Client();
  2048. $gdrive_client->setUseObjects(true);
  2049. $gdrive_client->setAccessToken($google_drive_token);
  2050. } catch (Exception $e) {
  2051. $this->_log($e->getMessage());
  2052. /*eturn array(
  2053. 'error' => $e->getMessage(),
  2054. );*/
  2055. }
  2056. $gdrive_service = new Google_DriveService($gdrive_client);
  2057. try {
  2058. $about = $gdrive_service->about->get();
  2059. $root_folder_id = $about->getRootFolderId();
  2060. } catch (Exception $e) {
  2061. $this->_log($e->getMessage());
  2062. /*return array(
  2063. 'error' => $e->getMessage(),
  2064. );*/
  2065. }
  2066. try {
  2067. $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$google_drive_directory' and '$root_folder_id' in parents and trashed = false"));
  2068. $files = $list_files->getItems();
  2069. } catch (Exception $e) {
  2070. $this->_log($e->getMessage());
  2071. /*return array(
  2072. 'error' => $e->getMessage(),
  2073. );*/
  2074. }
  2075. if (isset($files[0])) {
  2076. $managewp_folder = $files[0];
  2077. } else {
  2078. $this->_log("This file does not exist.");
  2079. /*return array(
  2080. 'error' => "This file does not exist.",
  2081. );*/
  2082. }
  2083. if ($google_drive_site_folder) {
  2084. try {
  2085. $subfolder_title = $this->site_name;
  2086. $managewp_folder_id = $managewp_folder->getId();
  2087. $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$subfolder_title' and '$managewp_folder_id' in parents and trashed = false"));
  2088. $files = $list_files->getItems();
  2089. } catch (Exception $e) {
  2090. $this->_log($e->getMessage());
  2091. /*return array(
  2092. 'error' => $e->getMessage(),
  2093. );*/
  2094. }
  2095. if (isset($files[0])) {
  2096. $backup_folder = $files[0];
  2097. }
  2098. } else {
  2099. $backup_folder = $managewp_folder;
  2100. }
  2101. if (isset($backup_folder)) {
  2102. try {
  2103. $backup_folder_id = $backup_folder->getId();
  2104. $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$backup_file' and '$backup_folder_id' in parents and trashed = false"));
  2105. $files = $list_files->getItems();;
  2106. } catch (Exception $e) {
  2107. $this->_log($e->getMessage());
  2108. /*return array(
  2109. 'error' => $e->getMessage(),
  2110. );*/
  2111. }
  2112. if (isset($files[0])) {
  2113. try {
  2114. $gdrive_service->files->delete($files[0]->getId());
  2115. } catch (Exception $e) {
  2116. $this->_log($e->getMessage());
  2117. /*return array(
  2118. 'error' => $e->getMessage(),
  2119. );*/
  2120. }
  2121. } else {
  2122. $this->_log("This file does not exist.");
  2123. /*return array(
  2124. 'error' => "This file does not exist.",
  2125. );*/
  2126. }
  2127. } else {
  2128. $this->_log("This file does not exist.");
  2129. /*return array(
  2130. 'error' => "This file does not exist.",
  2131. );*/
  2132. }
  2133. //return true;
  2134. }
  2135. /**
  2136. * Downloads backup file from Google Drive to root folder on local server.
  2137. *
  2138. * @param array $args arguments passed to the function
  2139. * [google_drive_token] -> user's Google drive token in json form
  2140. * [google_drive_directory] -> folder on user's Google Drive account which backup file should be downloaded from
  2141. * [google_drive_site_folder] -> subfolder with site name in google_drive_directory which backup file should be downloaded from
  2142. * [backup_file] -> absolute path of backup file on local server
  2143. * @return bool|array absolute path to downloaded file is successful, array with error message if not
  2144. */
  2145. function get_google_drive_backup($args) {
  2146. extract($args);
  2147. global $mmb_plugin_dir;
  2148. require_once("$mmb_plugin_dir/lib/google-api-client/Google_Client.php");
  2149. require_once("$mmb_plugin_dir/lib/google-api-client/contrib/Google_DriveService.php");
  2150. try {
  2151. $gdrive_client = new Google_Client();
  2152. $gdrive_client->setUseObjects(true);
  2153. $gdrive_client->setAccessToken($google_drive_token);
  2154. } catch (Exception $e) {
  2155. return array(
  2156. 'error' => $e->getMessage(),
  2157. );
  2158. }
  2159. $gdrive_service = new Google_DriveService($gdrive_client);
  2160. try {
  2161. $about = $gdrive_service->about->get();
  2162. $root_folder_id = $about->getRootFolderId();
  2163. } catch (Exception $e) {
  2164. return array(
  2165. 'error' => $e->getMessage(),
  2166. );
  2167. }
  2168. try {
  2169. $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$google_drive_directory' and '$root_folder_id' in parents and trashed = false"));
  2170. $files = $list_files->getItems();
  2171. } catch (Exception $e) {
  2172. return array(
  2173. 'error' => $e->getMessage(),
  2174. );
  2175. }
  2176. if (isset($files[0])) {
  2177. $managewp_folder = $files[0];
  2178. } else {
  2179. return array(
  2180. 'error' => "This file does not exist.",
  2181. );
  2182. }
  2183. if ($google_drive_site_folder) {
  2184. try {
  2185. $subfolder_title = $this->site_name;
  2186. $managewp_folder_id = $managewp_folder->getId();
  2187. $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$subfolder_title' and '$managewp_folder_id' in parents and trashed = false"));
  2188. $files = $list_files->getItems();
  2189. } catch (Exception $e) {
  2190. return array(
  2191. 'error' => $e->getMessage(),
  2192. );
  2193. }
  2194. if (isset($files[0])) {
  2195. $backup_folder = $files[0];
  2196. }
  2197. } else {
  2198. $backup_folder = $managewp_folder;
  2199. }
  2200. if (isset($backup_folder)) {
  2201. try {
  2202. $backup_folder_id = $backup_folder->getId();
  2203. $list_files = $gdrive_service->files->listFiles(array("q"=>"title='$backup_file' and '$backup_folder_id' in parents and trashed = false"));
  2204. $files = $list_files->getItems();
  2205. } catch (Exception $e) {
  2206. return array(
  2207. 'error' => $e->getMessage(),
  2208. );
  2209. }
  2210. if (isset($files[0])) {
  2211. try {
  2212. $download_url = $files[0]->getDownloadUrl();
  2213. if ($download_url) {
  2214. $request = new Google_HttpRequest($download_url, 'GET', null, null);
  2215. $http_request = Google_Client::$io->authenticatedRequest($request);
  2216. if ($http_request->getResponseHttpCode() == 200) {
  2217. $stream = $http_request->getResponseBody();
  2218. $local_destination = ABSPATH . 'mwp_temp_backup.zip';
  2219. $handle = @fopen($local_destination, 'w+');
  2220. $result = fwrite($handle, $stream);
  2221. fclose($handle);
  2222. if($result)
  2223. return $local_destination;
  2224. else
  2225. return array(
  2226. 'error' => "Write permission error.",
  2227. );
  2228. } else {
  2229. return array(
  2230. 'error' => "This file does not exist.",
  2231. );
  2232. }
  2233. } else {
  2234. return array(
  2235. 'error' => "This file does not exist.",
  2236. );
  2237. }
  2238. } catch (Exception $e) {
  2239. return array(
  2240. 'error' => $e->getMessage(),
  2241. );
  2242. }
  2243. } else {
  2244. return array(
  2245. 'error' => "This file does not exist.",
  2246. );
  2247. }
  2248. } else {
  2249. return array(
  2250. 'error' => "This file does not exist.",
  2251. );
  2252. }
  2253. return false;
  2254. }
  2255. /**
  2256. * Schedules the next execution of some backup task.
  2257. *
  2258. * @param string $type daily, weekly or monthly
  2259. * @param string $schedule format: task_time (if daily), task_time|task_day (if weekly), task_time|task_date (if monthly)
  2260. * @return bool|int timestamp if sucessful, false if not
  2261. */
  2262. function schedule_next($type, $schedule) {
  2263. $schedule = explode("|", $schedule);
  2264. if (empty($schedule))
  2265. return false;
  2266. switch ($type) {
  2267. case 'daily':
  2268. if (isset($schedule[1]) && $schedule[1]) {
  2269. $delay_time = $schedule[1] * 60;
  2270. }
  2271. $current_hour = date("H");
  2272. $schedule_hour = $schedule[0];
  2273. if ($current_hour >= $schedule_hour)
  2274. $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 1, date("Y"));
  2275. else
  2276. $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
  2277. break;
  2278. case 'weekly':
  2279. if (isset($schedule[2]) && $schedule[2]) {
  2280. $delay_time = $schedule[2] * 60;
  2281. }
  2282. $current_weekday = date('w');
  2283. $schedule_weekday = $schedule[1];
  2284. $current_hour = date("H");
  2285. $schedule_hour = $schedule[0];
  2286. if ($current_weekday > $schedule_weekday)
  2287. $weekday_offset = 7 - ($week_day - $task_schedule[1]);
  2288. else
  2289. $weekday_offset = $schedule_weekday - $current_weekday;
  2290. if (!$weekday_offset) { //today is scheduled weekday
  2291. if ($current_hour >= $schedule_hour)
  2292. $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + 7, date("Y"));
  2293. else
  2294. $time = mktime($schedule_hour, 0, 0, date("m"), date("d"), date("Y"));
  2295. } else {
  2296. $time = mktime($schedule_hour, 0, 0, date("m"), date("d") + $weekday_offset, date("Y"));
  2297. }
  2298. break;
  2299. case 'monthly':
  2300. if (isset($schedule[2]) && $schedule[2]) {
  2301. $delay_time = $schedule[2] * 60;
  2302. }
  2303. $current_monthday = date('j');
  2304. $schedule_monthday = $schedule[1];
  2305. $current_hour = date("H");
  2306. $schedule_hour = $schedule[0];
  2307. if ($current_monthday > $schedule_monthday) {
  2308. $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
  2309. } else if ($current_monthday < $schedule_monthday) {
  2310. $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
  2311. } else if ($current_monthday == $schedule_monthday) {
  2312. if ($current_hour >= $schedule_hour)
  2313. $time = mktime($schedule_hour, 0, 0, date("m") + 1, $schedule_monthday, date("Y"));
  2314. else
  2315. $time = mktime($schedule_hour, 0, 0, date("m"), $schedule_monthday, date("Y"));
  2316. break;
  2317. }
  2318. break;
  2319. default:
  2320. break;
  2321. }
  2322. if (isset($delay_time) && $delay_time) {
  2323. $time += $delay_time;
  2324. }
  2325. return $time;
  2326. }
  2327. /**
  2328. * Parse task arguments for info on master.
  2329. *
  2330. * @return mixed associative array with stats for every backup task or error if backup is manually deleted on server
  2331. */
  2332. function get_backup_stats() {
  2333. $stats = array();
  2334. $tasks = $this->tasks;
  2335. if (is_array($tasks) && !empty($tasks)) {
  2336. foreach ($tasks as $task_name => $info) {
  2337. if (is_array($info['task_results']) && !empty($info['task_results'])) {
  2338. foreach ($info['task_results'] as $key => $result) {
  2339. if (isset($result['server']) && !isset($result['error'])) {
  2340. if (isset($result['server']['file_path']) && !$info['task_args']['del_host_file']) {
  2341. if (!file_exists($result['server']['file_path'])) {
  2342. $info['task_results'][$key]['error'] = 'Backup created but manually removed from server.';
  2343. }
  2344. }
  2345. }
  2346. }
  2347. }
  2348. if (is_array($info['task_results']))
  2349. $stats[$task_name] = array_values($info['task_results']);
  2350. }
  2351. }
  2352. return $stats;
  2353. }
  2354. /**
  2355. * Returns all backup tasks with information when the next schedule will be.
  2356. *
  2357. * @return mixed associative array with timestamp with next schedule for every backup task
  2358. */
  2359. function get_next_schedules() {
  2360. $stats = array();
  2361. $tasks = $this->tasks;
  2362. if (is_array($tasks) && !empty($tasks)) {
  2363. foreach ($tasks as $task_name => $info) {
  2364. $stats[$task_name] = isset($info['task_args']['next']) ? $info['task_args']['next'] : array();
  2365. }
  2366. }
  2367. return $stats;
  2368. }
  2369. /**
  2370. * Deletes all old backups from local server.
  2371. * It depends on configuration on master (Number of backups to keep).
  2372. *
  2373. * @param string $task_name name of backup task
  2374. * @return bool|void true if there are backups for deletion, void if not
  2375. */
  2376. function remove_old_backups($task_name) {
  2377. //Check for previous failed backups first
  2378. $this->cleanup();
  2379. //Remove by limit
  2380. $backups = $this->tasks;
  2381. if ($task_name == 'Backup Now') {
  2382. $num = 0;
  2383. } else {
  2384. $num = 1;
  2385. }
  2386. if ((count($backups[$task_name]['task_results']) - $num) >= $backups[$task_name]['task_args']['limit']) {
  2387. //how many to remove ?
  2388. $remove_num = (count($backups[$task_name]['task_results']) - $num - $backups[$task_name]['task_args']['limit']) + 1;
  2389. for ($i = 0; $i < $remove_num; $i++) {
  2390. //Remove from the server
  2391. if (isset($backups[$task_name]['task_results'][$i]['server'])) {
  2392. @unlink($backups[$task_name]['task_results'][$i]['server']['file_path']);
  2393. }
  2394. //Remove from ftp
  2395. if (isset($backups[$task_name]['task_results'][$i]['ftp']) && isset($backups[$task_name]['task_args']['account_info']['mwp_ftp'])) {
  2396. $ftp_file = $backups[$task_name]['task_results'][$i]['ftp'];
  2397. $args = $backups[$task_name]['task_args']['account_info']['mwp_ftp'];
  2398. $args['backup_file'] = $ftp_file;
  2399. $this->remove_ftp_backup($args);
  2400. }
  2401. if (isset($backups[$task_name]['task_results'][$i]['amazons3']) && isset($backups[$task_name]['task_args']['account_info']['mwp_amazon_s3'])) {
  2402. $amazons3_file = $backups[$task_name]['task_results'][$i]['amazons3'];
  2403. $args = $backups[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
  2404. $args['backup_file'] = $amazons3_file;
  2405. $this->remove_amazons3_backup($args);
  2406. }
  2407. if (isset($backups[$task_name]['task_results'][$i]['dropbox']) && isset($backups[$task_name]['task_args']['account_info']['mwp_dropbox'])) {
  2408. //To do: dropbox remove
  2409. $dropbox_file = $backups[$task_name]['task_results'][$i]['dropbox'];
  2410. $args = $backups[$task_name]['task_args']['account_info']['mwp_dropbox'];
  2411. $args['backup_file'] = $dropbox_file;
  2412. $this->remove_dropbox_backup($args);
  2413. }
  2414. if (isset($backups[$task_name]['task_results'][$i]['google_drive']) && isset($backups[$task_name]['task_args']['account_info']['mwp_google_drive'])) {
  2415. $google_drive_file = $backups[$task_name]['task_results'][$i]['google_drive'];
  2416. $args = $backups[$task_name]['task_args']['account_info']['mwp_google_drive'];
  2417. $args['backup_file'] = $google_drive_file;
  2418. $this->remove_google_drive_backup($args);
  2419. }
  2420. //Remove database backup info
  2421. unset($backups[$task_name]['task_results'][$i]);
  2422. } //end foreach
  2423. if (is_array($backups[$task_name]['task_results']))
  2424. $backups[$task_name]['task_results'] = array_values($backups[$task_name]['task_results']);
  2425. else
  2426. $backups[$task_name]['task_results']=array();
  2427. $this->update_tasks($backups);
  2428. return true;
  2429. }
  2430. }
  2431. /**
  2432. * Deletes specified backup.
  2433. *
  2434. * @param array $args arguments passed to function
  2435. * [task_name] -> name of backup task
  2436. * [result_id] -> id of baskup task result, which should be restored
  2437. * [google_drive_token] -> json of Google Drive token, if it is remote destination
  2438. * @return bool true if successful, false if not
  2439. */
  2440. function delete_backup($args) {
  2441. if (empty($args))
  2442. return false;
  2443. extract($args);
  2444. if (isset($google_drive_token)) {
  2445. $this->tasks[$task_name]['task_args']['account_info']['mwp_google_drive']['google_drive_token'] = $google_drive_token;
  2446. }
  2447. $tasks = $this->tasks;
  2448. $task = $tasks[$task_name];
  2449. $backups = $task['task_results'];
  2450. $backup = $backups[$result_id];
  2451. if (isset($backup['server'])) {
  2452. @unlink($backup['server']['file_path']);
  2453. }
  2454. //Remove from ftp
  2455. if (isset($backup['ftp'])) {
  2456. $ftp_file = $backup['ftp'];
  2457. $args = $tasks[$task_name]['task_args']['account_info']['mwp_ftp'];
  2458. $args['backup_file'] = $ftp_file;
  2459. $this->remove_ftp_backup($args);
  2460. }
  2461. if (isset($backup['amazons3'])) {
  2462. $amazons3_file = $backup['amazons3'];
  2463. $args = $tasks[$task_name]['task_args']['account_info']['mwp_amazon_s3'];
  2464. $args['backup_file'] = $amazons3_file;
  2465. $this->remove_amazons3_backup($args);
  2466. }
  2467. if (isset($backup['dropbox'])) {
  2468. $dropbox_file = $backup['dropbox'];
  2469. $args = $tasks[$task_name]['task_args']['account_info']['mwp_dropbox'];
  2470. $args['backup_file'] = $dropbox_file;
  2471. $this->remove_dropbox_backup($args);
  2472. }
  2473. if (isset($backup['google_drive'])) {
  2474. $google_drive_file = $backup['google_drive'];
  2475. $args = $tasks[$task_name]['task_args']['account_info']['mwp_google_drive'];
  2476. $args['backup_file'] = $google_drive_file;
  2477. $this->remove_google_drive_backup($args);
  2478. }
  2479. unset($backups[$result_id]);
  2480. if (count($backups)) {
  2481. $tasks[$task_name]['task_results'] = $backups;
  2482. } else {
  2483. unset($tasks[$task_name]['task_results']);
  2484. }
  2485. $this->update_tasks($tasks);
  2486. //update_option('mwp_backup_tasks', $tasks);
  2487. return true;
  2488. }
  2489. /**
  2490. * Deletes all unneeded files produced by backup process.
  2491. *
  2492. * @return array array of deleted files
  2493. */
  2494. function cleanup() {
  2495. $tasks = $this->tasks;
  2496. $backup_folder = WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups/';
  2497. $backup_folder_new = MWP_BACKUP_DIR . '/';
  2498. $files = glob($backup_folder . "*");
  2499. $new = glob($backup_folder_new . "*");
  2500. //Failed db files first
  2501. $db_folder = MWP_DB_DIR . '/';
  2502. $db_files = glob($db_folder . "*");
  2503. if (is_array($db_files) && !empty($db_files)) {
  2504. foreach ($db_files as $file) {
  2505. @unlink($file);
  2506. }
  2507. @unlink(MWP_BACKUP_DIR.'/mwp_db/index.php');
  2508. @rmdir(MWP_DB_DIR);
  2509. }
  2510. //clean_old folder?
  2511. if ((isset($files[0]) && basename($files[0]) == 'index.php' && count($files) == 1) || (empty($files))) {
  2512. if (!empty($files)) {
  2513. foreach ($files as $file) {
  2514. @unlink($file);
  2515. }
  2516. }
  2517. @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker') . '/mwp_backups');
  2518. @rmdir(WP_CONTENT_DIR . '/' . md5('mmb-worker'));
  2519. }
  2520. if (!empty($new)) {
  2521. foreach ($new as $b) {
  2522. $files[] = $b;
  2523. }
  2524. }
  2525. $deleted = array();
  2526. if (is_array($files) && count($files)) {
  2527. $results = array();
  2528. if (!empty($tasks)) {
  2529. foreach ((array) $tasks as $task) {
  2530. if (isset($task['task_results']) && count($task['task_results'])) {
  2531. foreach ($task['task_results'] as $backup) {
  2532. if (isset($backup['server'])) {
  2533. $results[] = $backup['server']['file_path'];
  2534. }
  2535. }
  2536. }
  2537. }
  2538. }
  2539. $num_deleted = 0;
  2540. foreach ($files as $file) {
  2541. if (!in_array($file, $results) && basename($file) != 'index.php') {
  2542. @unlink($file);
  2543. $deleted[] = basename($file);
  2544. $num_deleted++;
  2545. }
  2546. }
  2547. }
  2548. return $deleted;
  2549. }
  2550. /**
  2551. * Uploads to remote destination in the second step, invoked from master.
  2552. *
  2553. * @param array $args arguments passed to function
  2554. * [task_name] -> name of backup task
  2555. * @return array|void void if success, array with error message if not
  2556. */
  2557. function remote_backup_now($args) {
  2558. $this->set_memory();
  2559. if (!empty($args))
  2560. extract($args);
  2561. $tasks = $this->tasks;
  2562. $task = $tasks[$task_name];
  2563. if (!empty($task)) {
  2564. extract($task['task_args']);
  2565. }
  2566. $results = $task['task_results'];
  2567. if (is_array($results) && count($results)) {
  2568. $backup_file = $results[count($results) - 1]['server']['file_path'];
  2569. }
  2570. if ($backup_file && file_exists($backup_file)) {
  2571. //FTP, Amazon S3, Dropbox or Google Drive
  2572. if (isset($account_info['mwp_ftp']) && !empty($account_info['mwp_ftp'])) {
  2573. $this->update_status($task_name, $this->statuses['ftp']);
  2574. $account_info['mwp_ftp']['backup_file'] = $backup_file;
  2575. $return = $this->ftp_backup($account_info['mwp_ftp']);
  2576. $this->wpdb_reconnect();
  2577. if (!(is_array($return) && isset($return['error']))) {
  2578. $this->update_status($task_name, $this->statuses['ftp'], true);
  2579. $this->update_status($task_name, $this->statuses['finished'], true);
  2580. }
  2581. }
  2582. if (isset($account_info['mwp_amazon_s3']) && !empty($account_info['mwp_amazon_s3'])) {
  2583. $this->update_status($task_name, $this->statuses['s3']);
  2584. $account_info['mwp_amazon_s3']['backup_file'] = $backup_file;
  2585. $return = $this->amazons3_backup($account_info['mwp_amazon_s3']);
  2586. $this->wpdb_reconnect();
  2587. if (!(is_array($return) && isset($return['error']))) {
  2588. $this->update_status($task_name, $this->statuses['s3'], true);
  2589. $this->update_status($task_name, $this->statuses['finished'], true);
  2590. }
  2591. }
  2592. if (isset($account_info['mwp_dropbox']) && !empty($account_info['mwp_dropbox'])) {
  2593. $this->update_status($task_name, $this->statuses['dropbox']);
  2594. $account_info['mwp_dropbox']['backup_file'] = $backup_file;
  2595. $return = $this->dropbox_backup($account_info['mwp_dropbox']);
  2596. $this->wpdb_reconnect();
  2597. if (!(is_array($return) && isset($return['error']))) {
  2598. $this->update_status($task_name, $this->statuses['dropbox'], true);
  2599. $this->update_status($task_name, $this->statuses['finished'], true);
  2600. }
  2601. }
  2602. if (isset($account_info['mwp_email']) && !empty($account_info['mwp_email'])) {
  2603. $this->update_status($task_name, $this->statuses['email']);
  2604. $account_info['mwp_email']['task_name'] = $task_name;
  2605. $account_info['mwp_email']['file_path'] = $backup_file;
  2606. $return = $this->email_backup($account_info['mwp_email']);
  2607. $this->wpdb_reconnect();
  2608. if (!(is_array($return) && isset($return['error']))) {
  2609. $this->update_status($task_name, $this->statuses['email'], true);
  2610. $this->update_status($task_name, $this->statuses['finished'], true);
  2611. }
  2612. }
  2613. if (isset($account_info['mwp_google_drive']) && !empty($account_info['mwp_google_drive'])) {
  2614. $this->update_status($task_name, $this->statuses['google_drive']);
  2615. $account_info['mwp_google_drive']['backup_file'] = $backup_file;
  2616. $return = $this->google_drive_backup($account_info['mwp_google_drive']);
  2617. $this->wpdb_reconnect();
  2618. if (!(is_array($return) && isset($return['error']))) {
  2619. $this->update_status($task_name, $this->statuses['google_drive'], true);
  2620. $this->update_status($task_name, $this->statuses['finished'], true);
  2621. }
  2622. }
  2623. $tasks = $this->tasks;
  2624. @file_put_contents(MWP_BACKUP_DIR.'/mwp_db/index.php', '');
  2625. if ($return == true && $del_host_file) {
  2626. @unlink($backup_file);
  2627. unset($tasks[$task_name]['task_results'][count($tasks[$task_name]['task_results']) - 1]['server']);
  2628. }
  2629. $this->update_tasks($tasks);
  2630. } else {
  2631. $return = array(
  2632. 'error' => 'Backup file not found on your server. Please try again.'
  2633. );
  2634. }
  2635. return $return;
  2636. }
  2637. /**
  2638. * Checks if scheduled backup tasks should be executed.
  2639. *
  2640. * @param array $args arguments passed to function
  2641. * [task_name] -> name of backup task
  2642. * [task_id] -> id of backup task
  2643. * [$site_key] -> hash key of backup task
  2644. * [worker_version] -> version of worker
  2645. * [mwp_google_drive_refresh_token] -> should be Google Drive token be refreshed, true if it is remote destination of task
  2646. * @param string $url url on master where worker validate task
  2647. * @return string|array|boolean
  2648. */
  2649. function validate_task($args, $url) {
  2650. if (!class_exists('WP_Http')) {
  2651. include_once(ABSPATH . WPINC . '/class-http.php');
  2652. }
  2653. $worker_upto_3_9_22 = (MMB_WORKER_VERSION <= '3.9.22'); // worker version is less or equals to 3.9.22
  2654. $params = array('timeout'=>100);
  2655. $params['body'] = $args;
  2656. $result = wp_remote_post($url, $params);
  2657. if ($worker_upto_3_9_22) {
  2658. if (is_array($result) && $result['body'] == 'mwp_delete_task') {
  2659. //$tasks = $this->get_backup_settings();
  2660. $tasks = $this->tasks;
  2661. unset($tasks[$args['task_name']]);
  2662. $this->update_tasks($tasks);
  2663. $this->cleanup();
  2664. return 'deleted';
  2665. } elseif(is_array($result) && $result['body'] == 'mwp_pause_task'){
  2666. return 'paused';
  2667. } elseif(is_array($result) && substr($result['body'], 0, 8) == 'token - '){
  2668. return $result['body'];
  2669. }
  2670. } else {
  2671. if (is_array($result) && $result['body']) {
  2672. $response = unserialize($result['body']);
  2673. if ($response['message'] == 'mwp_delete_task') {
  2674. $tasks = $this->tasks;
  2675. unset($tasks[$args['task_name']]);
  2676. $this->update_tasks($tasks);
  2677. $this->cleanup();
  2678. return 'deleted';
  2679. } elseif ($response['message'] == 'mwp_pause_task') {
  2680. return 'paused';
  2681. } elseif ($response['message'] == 'mwp_do_task') {
  2682. return $response;
  2683. }
  2684. }
  2685. }
  2686. return false;
  2687. }
  2688. /**
  2689. * Updates status of backup task.
  2690. * Positive number if completed, negative if not.
  2691. *
  2692. * @param string $task_name name of backup task
  2693. * @param int $status status which tasks should be updated to
  2694. * (
  2695. * 0 - Backup started,
  2696. * 1 - DB dump,
  2697. * 2 - DB ZIP,
  2698. * 3 - Files ZIP,
  2699. * 4 - Amazon S3,
  2700. * 5 - Dropbox,
  2701. * 6 - FTP,
  2702. * 7 - Email,
  2703. * 8 - Google Drive,
  2704. * 100 - Finished
  2705. * )
  2706. * @param bool $completed completed or not
  2707. * @return void
  2708. */
  2709. function update_status($task_name, $status, $completed = false) {
  2710. if ($task_name != 'Backup Now') {
  2711. $tasks = $this->tasks;
  2712. $index = count($tasks[$task_name]['task_results']) - 1;
  2713. if (!is_array($tasks[$task_name]['task_results'][$index]['status'])) {
  2714. $tasks[$task_name]['task_results'][$index]['status'] = array();
  2715. }
  2716. if (!$completed) {
  2717. $tasks[$task_name]['task_results'][$index]['status'][] = (int) $status * (-1);
  2718. } else {
  2719. $status_index = count($tasks[$task_name]['task_results'][$index]['status']) - 1;
  2720. $tasks[$task_name]['task_results'][$index]['status'][$status_index] = abs($tasks[$task_name]['task_results'][$index]['status'][$status_index]);
  2721. }
  2722. $this->update_tasks($tasks);
  2723. //update_option('mwp_backup_tasks',$tasks);
  2724. }
  2725. }
  2726. /**
  2727. * Update $this->tasks attribute and save it to wp_options with key mwp_backup_tasks.
  2728. *
  2729. * @param mixed $tasks associative array with all tasks data
  2730. * @return void
  2731. */
  2732. function update_tasks($tasks) {
  2733. $this->tasks = $tasks;
  2734. update_option('mwp_backup_tasks', $tasks);
  2735. }
  2736. /**
  2737. * Reconnects to database to avoid timeout problem after ZIP files.
  2738. *
  2739. * @return void
  2740. */
  2741. function wpdb_reconnect() {
  2742. global $wpdb;
  2743. if(class_exists('wpdb') && function_exists('wp_set_wpdb_vars')){
  2744. @mysql_close($wpdb->dbh);
  2745. $wpdb = new wpdb( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
  2746. wp_set_wpdb_vars();
  2747. }
  2748. }
  2749. /**
  2750. * Replaces .htaccess file in process of restoring WordPress site.
  2751. *
  2752. * @param string $url url of current site
  2753. * @return void
  2754. */
  2755. function replace_htaccess($url) {
  2756. $file = @file_get_contents(ABSPATH.'.htaccess');
  2757. if ($file && strlen($file)) {
  2758. $args = parse_url($url);
  2759. $string = rtrim($args['path'], "/");
  2760. $regex = "/BEGIN WordPress(.*?)RewriteBase(.*?)\n(.*?)RewriteRule \.(.*?)index\.php(.*?)END WordPress/sm";
  2761. $replace = "BEGIN WordPress$1RewriteBase " . $string . "/ \n$3RewriteRule . " . $string . "/index.php$5END WordPress";
  2762. $file = preg_replace($regex, $replace, $file);
  2763. @file_put_contents(ABSPATH.'.htaccess', $file);
  2764. }
  2765. }
  2766. /**
  2767. * Removes cron for checking scheduled tasks, if there are not any scheduled task.
  2768. *
  2769. * @return void
  2770. */
  2771. function check_cron_remove() {
  2772. if(empty($this->tasks) || (count($this->tasks) == 1 && isset($this->tasks['Backup Now'])) ){
  2773. wp_clear_scheduled_hook('mwp_backup_tasks');
  2774. exit;
  2775. }
  2776. }
  2777. /**
  2778. * Re-add tasks on website re-add.
  2779. *
  2780. * @param array $params arguments passed to function
  2781. * @return array $params without backups
  2782. */
  2783. public function readd_tasks($params = array()) {
  2784. global $mmb_core;
  2785. if( empty($params) || !isset($params['backups']) )
  2786. return $params;
  2787. $before = array();
  2788. $tasks = $params['backups'];
  2789. if( !empty($tasks) ){
  2790. $mmb_backup = new MMB_Backup();
  2791. if( function_exists( 'wp_next_scheduled' ) ){
  2792. if ( !wp_next_scheduled('mwp_backup_tasks') ) {
  2793. wp_schedule_event( time(), 'tenminutes', 'mwp_backup_tasks' );
  2794. }
  2795. }
  2796. foreach( $tasks as $task ){
  2797. $before[$task['task_name']] = array();
  2798. if(isset($task['secure'])){
  2799. if($decrypted = $mmb_core->_secure_data($task['secure'])){
  2800. $decrypted = maybe_unserialize($decrypted);
  2801. if(is_array($decrypted)){
  2802. foreach($decrypted as $key => $val){
  2803. if(!is_numeric($key))
  2804. $task[$key] = $val;
  2805. }
  2806. unset($task['secure']);
  2807. } else
  2808. $task['secure'] = $decrypted;
  2809. }
  2810. }
  2811. if (isset($task['account_info']) && is_array($task['account_info'])) { //only if sends from master first time(secure data)
  2812. $task['args']['account_info'] = $task['account_info'];
  2813. }
  2814. $before[$task['task_name']]['task_args'] = $task['args'];
  2815. $before[$task['task_name']]['task_args']['next'] = $mmb_backup->schedule_next($task['args']['type'], $task['args']['schedule']);
  2816. }
  2817. }
  2818. update_option('mwp_backup_tasks', $before);
  2819. unset($params['backups']);
  2820. return $params;
  2821. }
  2822. }
  2823. /*if( function_exists('add_filter') ) {
  2824. add_filter( 'mwp_website_add', 'MMB_Backup::readd_tasks' );
  2825. }*/
  2826. if(!function_exists('get_all_files_from_dir')) {
  2827. /**
  2828. * Get all files in directory
  2829. *
  2830. * @param string $path Relative or absolute path to folder
  2831. * @param array $exclude List of excluded files or folders, relative to $path
  2832. * @return array List of all files in folder $path, exclude all files in $exclude array
  2833. */
  2834. function get_all_files_from_dir($path, $exclude = array()) {
  2835. if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
  2836. global $directory_tree, $ignore_array;
  2837. $directory_tree = array();
  2838. foreach ($exclude as $file) {
  2839. if (!in_array($file, array('.', '..'))) {
  2840. if ($file[0] === "/") $path = substr($file, 1);
  2841. $ignore_array[] = "$path/$file";
  2842. }
  2843. }
  2844. get_all_files_from_dir_recursive($path);
  2845. return $directory_tree;
  2846. }
  2847. }
  2848. if (!function_exists('get_all_files_from_dir_recursive')) {
  2849. /**
  2850. * Get all files in directory,
  2851. * wrapped function which writes in global variable
  2852. * and exclued files or folders are read from global variable
  2853. *
  2854. * @param string $path Relative or absolute path to folder
  2855. * @return void
  2856. */
  2857. function get_all_files_from_dir_recursive($path) {
  2858. if ($path[strlen($path) - 1] === "/") $path = substr($path, 0, -1);
  2859. global $directory_tree, $ignore_array;
  2860. $directory_tree_temp = array();
  2861. $dh = @opendir($path);
  2862. while (false !== ($file = @readdir($dh))) {
  2863. if (!in_array($file, array('.', '..'))) {
  2864. if (!in_array("$path/$file", $ignore_array)) {
  2865. if (!is_dir("$path/$file")) {
  2866. $directory_tree[] = "$path/$file";
  2867. } else {
  2868. get_all_files_from_dir_recursive("$path/$file");
  2869. }
  2870. }
  2871. }
  2872. }
  2873. @closedir($dh);
  2874. }
  2875. }
  2876. ?>