PageRenderTime 40ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

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

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