PageRenderTime 38ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/better-wp-security/core/modules/backup/class-itsec-backup.php

https://gitlab.com/gabdark/aceit
PHP | 382 lines | 179 code | 125 blank | 78 comment | 40 complexity | d093109048708322b623ec1add900ef4 MD5 | raw file
  1. <?php
  2. /**
  3. * Backup execution.
  4. *
  5. * Handles database backups at scheduled interval.
  6. *
  7. * @since 4.0.0
  8. *
  9. * @package iThemes_Security
  10. */
  11. class ITSEC_Backup {
  12. /**
  13. * The module's saved options
  14. *
  15. * @since 4.0.0
  16. * @access private
  17. * @var array
  18. */
  19. private $settings;
  20. /**
  21. * Setup the module's functionality.
  22. *
  23. * Loads the backup detection module's unpriviledged functionality including
  24. * performing the scans themselves.
  25. *
  26. * @since 4.0.0
  27. *
  28. * @return void
  29. */
  30. function run() {
  31. global $itsec_globals;
  32. $this->settings = ITSEC_Modules::get_settings( 'backup' );
  33. add_action( 'itsec_execute_backup_cron', array( $this, 'do_backup' ) ); //Action to execute during a cron run.
  34. add_filter( 'itsec_logger_modules', array( $this, 'register_logger' ) );
  35. if (
  36. ( ! defined( 'DOING_AJAX' ) || false === DOING_AJAX ) &&
  37. ( ! defined( 'ITSEC_BACKUP_CRON' ) || false === ITSEC_BACKUP_CRON ) &&
  38. ! class_exists( 'pb_backupbuddy' ) &&
  39. ( $this->settings['interval'] > 0 ) &&
  40. ( $itsec_globals['current_time_gmt'] - $this->settings['interval'] * DAY_IN_SECONDS ) > $this->settings['last_run']
  41. ) {
  42. add_action( 'init', array( $this, 'do_backup' ), 10, 0 );
  43. } else if ( defined( 'ITSEC_BACKUP_CRON' ) && true === ITSEC_BACKUP_CRON && ! wp_next_scheduled( 'itsec_execute_backup_cron' ) ) { //Use cron if needed
  44. wp_schedule_event( time(), 'daily', 'itsec_execute_backup_cron' );
  45. }
  46. }
  47. /**
  48. * Public function to get lock and call backup.
  49. *
  50. * Attempts to get a lock to prevent concurrant backups and calls the backup function itself.
  51. *
  52. * @since 4.0.0
  53. *
  54. * @param boolean $one_time whether this is a one time backup
  55. *
  56. * @return mixed false on error or nothing
  57. */
  58. public function do_backup( $one_time = false ) {
  59. ITSEC_Lib::set_minimum_memory_limit( '256M' );
  60. $itsec_files = ITSEC_Core::get_itsec_files();
  61. if ( $itsec_files->get_file_lock( 'backup' ) ) {
  62. $this->execute_backup( $one_time );
  63. $itsec_files->release_file_lock( 'backup' );
  64. switch ( $this->settings['method'] ) {
  65. case 0:
  66. return __( 'Backup complete. The backup was sent to the selected email recipients and was saved locally.', 'better-wp-security' );
  67. case 1:
  68. return __( 'Backup complete. The backup was sent to the selected email recipients.', 'better-wp-security' );
  69. default:
  70. return __( 'Backup complete. The backup was saved locally.', 'better-wp-security' );
  71. }
  72. } else {
  73. return new WP_Error( 'itsec-backup-do-backup-already-running', __( 'Unable to create a backup at this time since a backup is currently being created. If you wish to create an additional backup, please wait a few minutes before trying again.', 'better-wp-security' ) );
  74. }
  75. }
  76. /**
  77. * Executes backup function.
  78. *
  79. * Handles the execution of database backups.
  80. *
  81. * @since 4.0.0
  82. *
  83. * @param bool $one_time whether this is a one-time backup
  84. *
  85. * @return void
  86. */
  87. private function execute_backup( $one_time = false ) {
  88. global $wpdb, $itsec_globals, $itsec_logger;
  89. //get all of the tables
  90. if ( isset( $this->settings['all_sites'] ) && true === $this->settings['all_sites'] ) {
  91. $tables = $wpdb->get_results( 'SHOW TABLES', ARRAY_N ); //retrieve a list of all tables in the DB
  92. } else {
  93. $tables = $wpdb->get_results( 'SHOW TABLES LIKE "' . $wpdb->base_prefix . '%"', ARRAY_N ); //retrieve a list of all tables for this WordPress installation
  94. }
  95. $return = '';
  96. //cycle through each table
  97. foreach ( $tables as $table ) {
  98. $num_fields = sizeof( $wpdb->get_results( 'DESCRIBE `' . $table[0] . '`;' ) );
  99. $return .= 'DROP TABLE IF EXISTS `' . $table[0] . '`;';
  100. $row2 = $wpdb->get_row( 'SHOW CREATE TABLE `' . $table[0] . '`;', ARRAY_N );
  101. $return .= PHP_EOL . PHP_EOL . $row2[1] . ";" . PHP_EOL . PHP_EOL;
  102. if ( ! in_array( substr( $table[0], strlen( $wpdb->prefix ) ), $this->settings['exclude'] ) ) {
  103. $result = $wpdb->get_results( 'SELECT * FROM `' . $table[0] . '`;', ARRAY_N );
  104. foreach ( $result as $row ) {
  105. $return .= 'INSERT INTO `' . $table[0] . '` VALUES(';
  106. for ( $j = 0; $j < $num_fields; $j ++ ) {
  107. $row[$j] = addslashes( $row[$j] );
  108. $row[$j] = preg_replace( '#' . PHP_EOL . '#', "\n", $row[$j] );
  109. if ( isset( $row[$j] ) ) {
  110. $return .= '"' . $row[$j] . '"';
  111. } else {
  112. $return .= '""';
  113. }
  114. if ( $j < ( $num_fields - 1 ) ) {
  115. $return .= ',';
  116. }
  117. }
  118. $return .= ");" . PHP_EOL;
  119. }
  120. }
  121. $return .= PHP_EOL . PHP_EOL;
  122. }
  123. $return .= PHP_EOL . PHP_EOL;
  124. //save file
  125. $file = 'backup-' . substr( sanitize_title( get_bloginfo( 'name' ) ), 0, 20 ) . '-' . current_time( 'Ymd-His' ) . '-' . wp_generate_password( 30, false );
  126. require_once( ITSEC_Core::get_core_dir() . 'lib/class-itsec-lib-directory.php' );
  127. $dir = $this->settings['location'];
  128. ITSEC_Lib_Directory::create( $dir );
  129. $fileext = '.sql';
  130. $handle = @fopen( $dir . '/' . $file . '.sql', 'w+' );
  131. @fwrite( $handle, $return );
  132. @fclose( $handle );
  133. //zip the file
  134. if ( true === $this->settings['zip'] ) {
  135. if ( ! class_exists( 'PclZip' ) ) {
  136. require( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
  137. }
  138. $zip = new PclZip( $dir . '/' . $file . '.zip' );
  139. if ( 0 != $zip->create( $dir . '/' . $file . '.sql', PCLZIP_OPT_REMOVE_PATH, $dir ) ) {
  140. //delete .sql and keep zip
  141. @unlink( $dir . '/' . $file . '.sql' );
  142. $fileext = '.zip';
  143. }
  144. }
  145. if ( 2 !== $this->settings['method'] || true === $one_time ) {
  146. $attachment = array( $dir . '/' . $file . $fileext );
  147. $body = __( 'Attached is the backup file for the database powering', 'better-wp-security' ) . ' ' . get_option( 'siteurl' ) . __( ' taken', 'better-wp-security' ) . ' ' . date( 'l, F jS, Y \a\\t g:i a', $itsec_globals['current_time'] );
  148. //Setup the remainder of the email
  149. $recipients = ITSEC_Modules::get_setting( 'global', 'backup_email' );
  150. $subject = __( 'Site Database Backup', 'better-wp-security' ) . ' ' . date( 'l, F jS, Y \a\\t g:i a', $itsec_globals['current_time'] );
  151. $subject = apply_filters( 'itsec_backup_email_subject', $subject );
  152. $headers = 'From: ' . get_bloginfo( 'name' ) . ' <' . get_option( 'admin_email' ) . '>' . "\r\n";
  153. $mail_success = false;
  154. //Use HTML Content type
  155. add_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
  156. //Send emails to all recipients
  157. foreach ( $recipients as $recipient ) {
  158. if ( is_email( trim( $recipient ) ) ) {
  159. if ( defined( 'ITSEC_DEBUG' ) && true === ITSEC_DEBUG ) {
  160. $body .= '<p>' . __( 'Debug info (source page): ' . esc_url( $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"] ) ) . '</p>';
  161. }
  162. $mail_success = wp_mail( trim( $recipient ), $subject, '<html>' . $body . '</html>', $headers, $attachment );
  163. }
  164. }
  165. //Remove HTML Content type
  166. remove_filter( 'wp_mail_content_type', array( $this, 'set_html_content_type' ) );
  167. }
  168. if ( 1 === $this->settings['method'] ) {
  169. @unlink( $dir . '/' . $file . $fileext );
  170. } else {
  171. $retain = isset( $this->settings['retain'] ) ? absint( $this->settings['retain'] ) : 0;
  172. //delete extra files
  173. if ( 0 < $retain ) {
  174. $files = scandir( $dir, 1 );
  175. $count = 0;
  176. if ( is_array( $files ) && 0 < count( $files ) ) {
  177. foreach ( $files as $file ) {
  178. if ( strstr( $file, 'backup' ) ) {
  179. if ( $count >= $retain ) {
  180. @unlink( trailingslashit( $dir ) . $file );
  181. }
  182. $count ++;
  183. }
  184. }
  185. }
  186. }
  187. }
  188. if ( false === $one_time ) {
  189. ITSEC_Modules::set_setting( 'backup', 'last_run', ITSEC_Core::get_current_time_gmt() );
  190. }
  191. switch ( $this->settings['method'] ) {
  192. case 0:
  193. if ( false === $mail_success ) {
  194. $status = array(
  195. 'status' => __( 'Error', 'better-wp-security' ),
  196. 'details' => __( 'saved locally but email to backup recipients could not be sent.', 'better-wp-security' ),
  197. );
  198. } else {
  199. $status = array(
  200. 'status' => __( 'Success', 'better-wp-security' ),
  201. 'details' => __( 'emailed to backup recipients and saved locally', 'better-wp-security' ),
  202. );
  203. }
  204. break;
  205. case 1:
  206. if ( false === $mail_success ) {
  207. $status = array(
  208. 'status' => __( 'Error', 'better-wp-security' ),
  209. 'details' => __( 'email to backup recipients could not be sent.', 'better-wp-security' ),
  210. );
  211. } else {
  212. $status = array(
  213. 'status' => __( 'Success', 'better-wp-security' ),
  214. 'details' => __( 'emailed to backup recipients', 'better-wp-security' ),
  215. );
  216. }
  217. break;
  218. default:
  219. $status = array(
  220. 'status' => __( 'Success', 'better-wp-security' ),
  221. 'details' => __( 'saved locally', 'better-wp-security' ),
  222. );
  223. break;
  224. }
  225. $itsec_logger->log_event( 'backup', 3, array( $status ) );
  226. }
  227. /**
  228. * Register backups for logger.
  229. *
  230. * Adds the backup module to ITSEC_Logger.
  231. *
  232. * @since 4.0.0
  233. *
  234. * @param array $logger_modules array of logger modules
  235. *
  236. * @return array array of logger modules
  237. */
  238. public function register_logger( $logger_modules ) {
  239. $logger_modules['backup'] = array(
  240. 'type' => 'backup',
  241. 'function' => __( 'Database Backup Executed', 'better-wp-security' ),
  242. );
  243. return $logger_modules;
  244. }
  245. /**
  246. * Set HTML content type for email.
  247. *
  248. * Sets the content type on outgoing emails to HTML.
  249. *
  250. * @since 4.0.0
  251. *
  252. * @return string html content type
  253. */
  254. public function set_html_content_type() {
  255. return 'text/html';
  256. }
  257. }