BackUpWordPress - Version 1.6

Version Description

Download this release

Release Info

Developer willmot
Plugin Icon 128x128 BackUpWordPress
Version 1.6
Comparing to
See all releases

Code changes from version 1.5.1 to 1.6

admin.actions.php CHANGED
@@ -28,13 +28,13 @@ function hmbkp_option_save() {
28
 
29
  } else {
30
  delete_option( 'hmbkp_disable_automatic_backup');
31
-
32
  }
33
 
34
  // Update schedule frequency settings. Or reset to default of daily.
35
  if ( isset( $_POST['hmbkp_frequency'] ) && $_POST['hmbkp_frequency'] != 'daily' )
36
  update_option( 'hmbkp_schedule_frequency', esc_attr( $_POST['hmbkp_frequency'] ) );
37
-
38
  else
39
  delete_option( 'hmbkp_schedule_frequency' );
40
 
@@ -71,7 +71,7 @@ function hmbkp_option_save() {
71
 
72
  }
73
 
74
- if ( isset( $_POST['hmbkp_email_address'] ) && !is_email( $_POST['hmbkp_email_address'] ) && !empty( $_POST['hmbkp_email_address'] ) ) {
75
  $hmbkp_errors->add( 'invalid_email', __( 'You have entered an invalid email address.', 'hmbkp' ) );
76
 
77
  } elseif( isset( $_POST['hmbkp_email_address'] ) && !empty( $_POST['hmbkp_email_address'] ) ) {
@@ -88,7 +88,7 @@ function hmbkp_option_save() {
88
  delete_option( 'hmbkp_excludes' );
89
 
90
  }
91
-
92
  delete_transient( 'hmbkp_estimated_filesize' );
93
 
94
  if ( $hmbkp_errors->get_error_code() )
@@ -117,7 +117,7 @@ function hmbkp_request_delete_backup() {
117
  add_action( 'load-tools_page_' . HMBKP_PLUGIN_SLUG, 'hmbkp_request_delete_backup' );
118
 
119
  /**
120
- * Schedule a one time backup and then
121
  * redirect back to the backups page
122
  */
123
  function hmbkp_request_do_backup() {
@@ -126,48 +126,63 @@ function hmbkp_request_do_backup() {
126
  if ( ! isset( $_GET['action'] ) || $_GET['action'] !== 'hmbkp_backup_now' || hmbkp_is_in_progress() || ! hmbkp_possible() )
127
  return false;
128
 
129
- // If cron is disabled for manual backups
130
- if ( ( defined( 'HMBKP_DISABLE_MANUAL_BACKUP_CRON' ) && HMBKP_DISABLE_MANUAL_BACKUP_CRON ) || ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ) ) {
131
 
132
- hmbkp_do_backup();
 
 
133
 
134
- // If not fire the cron
135
- } else {
136
 
137
- // Schedule a single backup
138
- wp_schedule_single_event( time(), 'hmbkp_schedule_single_backup_hook' );
 
 
139
 
140
- // Remove the once every 60 seconds limitation
141
- delete_transient( 'doing_cron' );
142
-
143
- // Fire the cron now
144
- spawn_cron();
145
 
146
- }
 
 
147
 
148
- // Redirect back
149
- wp_redirect( remove_query_arg( 'action' ), 303 );
150
- exit;
151
 
152
  }
153
- add_action( 'load-tools_page_' . HMBKP_PLUGIN_SLUG, 'hmbkp_request_do_backup' );
154
 
155
  /**
156
  * Send the download file to the browser and
157
  * then redirect back to the backups page
158
- *
159
- * @todo We need to find a way to do this without streaming the file through PHP
160
  */
161
  function hmbkp_request_download_backup() {
162
 
163
- if ( ! isset( $_GET['hmbkp_download'] ) || empty( $_GET['hmbkp_download'] ) )
164
  return false;
165
 
166
- hmbkp_send_file( base64_decode( $_GET['hmbkp_download'] ) );
 
 
 
 
 
 
167
 
168
  }
169
  add_action( 'load-tools_page_' . HMBKP_PLUGIN_SLUG, 'hmbkp_request_download_backup' );
170
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  /**
172
  * Display the running status via ajax
173
  *
@@ -178,11 +193,8 @@ function hmbkp_ajax_is_backup_in_progress() {
178
  if ( ! hmbkp_is_in_progress() )
179
  echo 0;
180
 
181
- elseif ( $status = hmbkp_get_status() )
182
- echo $status;
183
-
184
  else
185
- echo 1;
186
 
187
  exit;
188
  }
@@ -209,7 +221,7 @@ function hmbkp_ajax_cron_test() {
209
  $response = wp_remote_get( site_url( 'wp-cron.php' ) );
210
 
211
  if ( ! is_wp_error( $response ) && $response['response']['code'] != '200' )
212
- echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( '%s is returning a %s response which could mean cron jobs aren\'t getting fired properly. BackUpWordPress relies on wp-cron to run back ups in a separate process.', 'hmbkp' ), '<code>wp-cron.php</code>', '<code>' . $response['response']['code'] . '</code>' ) . '</p></div>';
213
  else
214
  echo 1;
215
 
28
 
29
  } else {
30
  delete_option( 'hmbkp_disable_automatic_backup');
31
+
32
  }
33
 
34
  // Update schedule frequency settings. Or reset to default of daily.
35
  if ( isset( $_POST['hmbkp_frequency'] ) && $_POST['hmbkp_frequency'] != 'daily' )
36
  update_option( 'hmbkp_schedule_frequency', esc_attr( $_POST['hmbkp_frequency'] ) );
37
+
38
  else
39
  delete_option( 'hmbkp_schedule_frequency' );
40
 
71
 
72
  }
73
 
74
+ if ( isset( $_POST['hmbkp_email_address'] ) && ! is_email( $_POST['hmbkp_email_address'] ) && !empty( $_POST['hmbkp_email_address'] ) ) {
75
  $hmbkp_errors->add( 'invalid_email', __( 'You have entered an invalid email address.', 'hmbkp' ) );
76
 
77
  } elseif( isset( $_POST['hmbkp_email_address'] ) && !empty( $_POST['hmbkp_email_address'] ) ) {
88
  delete_option( 'hmbkp_excludes' );
89
 
90
  }
91
+
92
  delete_transient( 'hmbkp_estimated_filesize' );
93
 
94
  if ( $hmbkp_errors->get_error_code() )
117
  add_action( 'load-tools_page_' . HMBKP_PLUGIN_SLUG, 'hmbkp_request_delete_backup' );
118
 
119
  /**
120
+ * Perform a manual backup and then
121
  * redirect back to the backups page
122
  */
123
  function hmbkp_request_do_backup() {
126
  if ( ! isset( $_GET['action'] ) || $_GET['action'] !== 'hmbkp_backup_now' || hmbkp_is_in_progress() || ! hmbkp_possible() )
127
  return false;
128
 
129
+ hmbkp_do_backup();
 
130
 
131
+ // Redirect back
132
+ wp_redirect( remove_query_arg( 'action' ), 303 );
133
+ exit;
134
 
135
+ }
136
+ add_action( 'load-tools_page_' . HMBKP_PLUGIN_SLUG, 'hmbkp_request_do_backup' );
137
 
138
+ /**
139
+ * Perform a manual backup via ajax
140
+ */
141
+ function hmbkp_ajax_request_do_backup() {
142
 
143
+ ignore_user_abort( true );
 
 
 
 
144
 
145
+ // Are we sure
146
+ if ( hmbkp_is_in_progress() || ! hmbkp_possible() )
147
+ return false;
148
 
149
+ hmbkp_do_backup();
 
 
150
 
151
  }
152
+ add_action( 'wp_ajax_hmbkp_backup', 'hmbkp_ajax_request_do_backup' );
153
 
154
  /**
155
  * Send the download file to the browser and
156
  * then redirect back to the backups page
 
 
157
  */
158
  function hmbkp_request_download_backup() {
159
 
160
+ if ( empty( $_GET['hmbkp_download'] ) )
161
  return false;
162
 
163
+ if ( file_exists( hmbkp_path() . '/.htaccess' ) )
164
+ unlink( hmbkp_path() . '/.htaccess' );
165
+
166
+ hmbkp_path();
167
+
168
+ wp_redirect( add_query_arg( 'key', md5( SECURE_AUTH_KEY ), str_replace( ABSPATH, site_url( '/' ), base64_decode( $_GET['hmbkp_download'] ) ) ), 303 );
169
+ exit;
170
 
171
  }
172
  add_action( 'load-tools_page_' . HMBKP_PLUGIN_SLUG, 'hmbkp_request_download_backup' );
173
 
174
+ function hmbkp_request_cancel_backup() {
175
+
176
+ if ( ! isset( $_GET['action'] ) || $_GET['action'] !== 'hmbkp_cancel' )
177
+ return false;
178
+
179
+ hmbkp_cleanup();
180
+
181
+ wp_redirect( remove_query_arg( 'action' ), 303 );
182
+
183
+ }
184
+ add_action( 'load-tools_page_' . HMBKP_PLUGIN_SLUG, 'hmbkp_request_cancel_backup' );
185
+
186
  /**
187
  * Display the running status via ajax
188
  *
193
  if ( ! hmbkp_is_in_progress() )
194
  echo 0;
195
 
 
 
 
196
  else
197
+ include( HMBKP_PLUGIN_PATH . '/admin.backup-button.php' );
198
 
199
  exit;
200
  }
221
  $response = wp_remote_get( site_url( 'wp-cron.php' ) );
222
 
223
  if ( ! is_wp_error( $response ) && $response['response']['code'] != '200' )
224
+ echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( '%s is returning a %s response which could mean cron jobs aren\'t getting fired properly. BackUpWordPress relies on wp-cron to run scheduled back ups. See the %s for more details.', 'hmbkp' ), '<code>wp-cron.php</code>', '<code>' . $response['response']['code'] . '</code>', '<a href="http://wordpress.org/extend/plugins/backupwordpress/faq/">FAQ</a>' ) . '</p></div>';
225
  else
226
  echo 1;
227
 
admin.backup-button.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php if ( hmbkp_is_in_progress() ) : ?>
2
+
3
+ <a id="hmbkp_backup" class="add-new-h2 hmbkp_running" href="tools.php?page=<?php echo HMBKP_PLUGIN_SLUG; ?>&amp;action=hmbkp_cancel"><?php echo hmbkp_get_status(); ?> [cancel]</a>
4
+
5
+ <?php elseif ( hmbkp_possible() ) : ?>
6
+
7
+ <a id="hmbkp_backup" class="add-new-h2" href="tools.php?page=<?php echo HMBKP_PLUGIN_SLUG; ?>&amp;action=hmbkp_backup_now"><?php _e( 'Back Up Now', 'hmbkp' ); ?></a>
8
+
9
+ <?php endif; ?>
admin.constants.php CHANGED
@@ -33,9 +33,6 @@
33
 
34
  <dt<?php if ( defined( 'HMBKP_EXCLUDE' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_EXCLUDE</code></dt>
35
  <dd><p><?php _e( 'Comma separated list of files or directories to exclude, the backups directory is automatically excluded.', 'hmbkp' ); ?><p class="example">e.g. <code>define( 'HMBKP_EXCLUDE', '/wp-content/uploads/, /stats/, .svn/, *.txt' );</code></p></dd>
36
-
37
- <dt<?php if ( defined( 'HMBKP_DISABLE_MANUAL_BACKUP_CRON' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_DISABLE_MANUAL_BACKUP_CRON</code></dt>
38
- <dd><p><?php _e( 'Disable the use of wp-cron for manual backups.', 'hmbkp' ); ?><p class="example">e.g. <code>define( 'HMBKP_DISABLE_MANUAL_BACKUP_CRON', true );</code></p></dd>
39
 
40
  <dt<?php if ( defined( 'HMBKP_CAPABILITY' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_CAPABILITY</code></dt>
41
  <dd><p><?php printf( __( 'The capability to use when calling %s. Defaults to %s.', 'hmbkp' ), '<code>add_menu_page</code>', '<code>manage_options</code>' ); ?><p class="example">e.g. <code>define( 'HMBKP_CAPABILITY', 'edit_posts' );</code></p></dd>
33
 
34
  <dt<?php if ( defined( 'HMBKP_EXCLUDE' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_EXCLUDE</code></dt>
35
  <dd><p><?php _e( 'Comma separated list of files or directories to exclude, the backups directory is automatically excluded.', 'hmbkp' ); ?><p class="example">e.g. <code>define( 'HMBKP_EXCLUDE', '/wp-content/uploads/, /stats/, .svn/, *.txt' );</code></p></dd>
 
 
 
36
 
37
  <dt<?php if ( defined( 'HMBKP_CAPABILITY' ) ) { ?> class="hmbkp_active"<?php } ?>><code>HMBKP_CAPABILITY</code></dt>
38
  <dd><p><?php printf( __( 'The capability to use when calling %s. Defaults to %s.', 'hmbkp' ), '<code>add_menu_page</code>', '<code>manage_options</code>' ); ?><p class="example">e.g. <code>define( 'HMBKP_CAPABILITY', 'edit_posts' );</code></p></dd>
admin.page.php CHANGED
@@ -5,16 +5,10 @@
5
  <h2>
6
 
7
  <?php _e( 'Manage Backups', 'hmbkp' ); ?>
 
 
8
 
9
- <?php if ( hmbkp_is_in_progress() ) : ?>
10
- <a class="add-new-h2" <?php disabled( true ); ?>><img src="<?php echo site_url( 'wp-admin/images/wpspin_light.gif' ); ?>" width="16" height="16" /><?php echo hmbkp_get_status(); ?></a>
11
-
12
- <?php elseif ( hmbkp_possible() ) : ?>
13
- <a class="add-new-h2" href="tools.php?page=<?php echo $_GET['page']; ?>&amp;action=hmbkp_backup_now"><?php _e( 'Back Up Now', 'hmbkp' ); ?></a>
14
-
15
- <?php endif; ?>
16
-
17
- <a href="#hmbkp-settings" class="add-new-h2 hmbkp-settings-toggle"><?php _e( 'Settings', 'hmbkp' ); ?></a>
18
 
19
  </h2>
20
 
@@ -31,7 +25,7 @@
31
  <?php endif; ?>
32
 
33
  <?php include_once( HMBKP_PLUGIN_PATH . '/admin.settings.php' ); ?>
34
-
35
  <p class="howto"><?php printf( __( 'If you need help getting things working you are more than welcome to email us at %s and we\'ll do what we can to help.', 'hmbkp' ), '<a href="mailto:support@humanmade.co.uk">support@humanmade.co.uk</a>' ); ?></p>
36
 
37
  </div>
5
  <h2>
6
 
7
  <?php _e( 'Manage Backups', 'hmbkp' ); ?>
8
+
9
+ <?php include_once( HMBKP_PLUGIN_PATH . '/admin.backup-button.php' ); ?>
10
 
11
+ <a class="add-new-h2 hmbkp-settings-toggle" href="#hmbkp-settings"><?php _e( 'Settings', 'hmbkp' ); ?></a>
 
 
 
 
 
 
 
 
12
 
13
  </h2>
14
 
25
  <?php endif; ?>
26
 
27
  <?php include_once( HMBKP_PLUGIN_PATH . '/admin.settings.php' ); ?>
28
+
29
  <p class="howto"><?php printf( __( 'If you need help getting things working you are more than welcome to email us at %s and we\'ll do what we can to help.', 'hmbkp' ), '<a href="mailto:support@humanmade.co.uk">support@humanmade.co.uk</a>' ); ?></p>
30
 
31
  </div>
admin.settings.php CHANGED
@@ -40,7 +40,7 @@
40
  <?php _e( 'Automatic backups will occur', 'hmbkp' ); ?>
41
 
42
  <select name="hmbkp_frequency" id="hmbkp_frequency">
43
- <option value="daily" <?php selected( !get_option( 'hmbkp_schedule_frequency' ) ); ?>><?php _e( 'Daily', 'hmbkp' ); ?></option>
44
  <option value="hmbkp_weekly" <?php selected( get_option( 'hmbkp_schedule_frequency' ), 'hmbkp_weekly' ); ?>><?php _e( 'Weekly', 'hmbkp' ); ?></option>
45
  <option value="hmbkp_fortnightly" <?php selected( get_option( 'hmbkp_schedule_frequency' ), 'hmbkp_fortnightly' ); ?>><?php _e( 'Fortnightly', 'hmbkp' ); ?></option>
46
  <option value="hmbkp_monthly" <?php selected( get_option( 'hmbkp_schedule_frequency' ), 'hmbkp_monthly' ); ?>><?php _e( 'Monthly', 'hmbkp' ); ?></option>
@@ -59,7 +59,7 @@
59
  <?php _e( 'Backup my', 'hmbkp' ); ?>
60
 
61
  <select name="hmbkp_what_to_backup" id="hmbkp_what_to_backup" <?php disabled( defined( 'HMBKP_FILES_ONLY' ) || defined( 'HMBKP_DATABASE_ONLY' ) ); ?>>
62
- <option value="default" <?php selected( !get_option( 'hmbkp_files_only' ) && !get_option( 'hmbkp_database_only' ) ); ?>><?php _e( 'database &amp; files', 'hmbkp' ); ?></option>
63
  <option <?php selected( hmbkp_get_database_only() ); ?>><?php _e( 'database only', 'hmbkp' ); ?></option>
64
  <option <?php selected( hmbkp_get_files_only() ); ?>><?php _e( 'files only', 'hmbkp' ); ?></option>
65
  </select>
40
  <?php _e( 'Automatic backups will occur', 'hmbkp' ); ?>
41
 
42
  <select name="hmbkp_frequency" id="hmbkp_frequency">
43
+ <option value="daily" <?php selected( ! get_option( 'hmbkp_schedule_frequency' ) ); ?>><?php _e( 'Daily', 'hmbkp' ); ?></option>
44
  <option value="hmbkp_weekly" <?php selected( get_option( 'hmbkp_schedule_frequency' ), 'hmbkp_weekly' ); ?>><?php _e( 'Weekly', 'hmbkp' ); ?></option>
45
  <option value="hmbkp_fortnightly" <?php selected( get_option( 'hmbkp_schedule_frequency' ), 'hmbkp_fortnightly' ); ?>><?php _e( 'Fortnightly', 'hmbkp' ); ?></option>
46
  <option value="hmbkp_monthly" <?php selected( get_option( 'hmbkp_schedule_frequency' ), 'hmbkp_monthly' ); ?>><?php _e( 'Monthly', 'hmbkp' ); ?></option>
59
  <?php _e( 'Backup my', 'hmbkp' ); ?>
60
 
61
  <select name="hmbkp_what_to_backup" id="hmbkp_what_to_backup" <?php disabled( defined( 'HMBKP_FILES_ONLY' ) || defined( 'HMBKP_DATABASE_ONLY' ) ); ?>>
62
+ <option value="default" <?php selected( ! get_option( 'hmbkp_files_only' ) && !get_option( 'hmbkp_database_only' ) ); ?>><?php _e( 'database &amp; files', 'hmbkp' ); ?></option>
63
  <option <?php selected( hmbkp_get_database_only() ); ?>><?php _e( 'database only', 'hmbkp' ); ?></option>
64
  <option <?php selected( hmbkp_get_files_only() ); ?>><?php _e( 'files only', 'hmbkp' ); ?></option>
65
  </select>
admin.status.php CHANGED
@@ -1,5 +1,5 @@
1
  <?php // If the form has been submitted, things may have changed.
2
- if ( ( !empty( $_POST['hmbkp_settings_submit'] ) ) && ( ! wp_next_scheduled( 'hmbkp_schedule_backup_hook') || hmbkp_get_disable_automatic_backup() ) )
3
  hmbkp_constant_changes(); ?>
4
 
5
  <p>&#10003;
1
  <?php // If the form has been submitted, things may have changed.
2
+ if ( ( ! empty( $_POST['hmbkp_settings_submit'] ) ) && ( ! wp_next_scheduled( 'hmbkp_schedule_backup_hook') || hmbkp_get_disable_automatic_backup() ) )
3
  hmbkp_constant_changes(); ?>
4
 
5
  <p>&#10003;
assets/hmbkp.css CHANGED
@@ -19,4 +19,5 @@ tfoot p { margin: 0; font-weight: normal; }
19
  .completed th, .completed td { background-color: #FFFFE0; }
20
  .hmbkp_active:before { content: "\00a0 \2713 "; font-size: 11px; }
21
  .hmbkp_active, .hmbkp_active code, #hmbkp-constants .hmbkp_active + dd { background: #E5F7E8; }
22
- .contextual-help-tabs-wrap .updated { margin: 15px 0 0; }
 
19
  .completed th, .completed td { background-color: #FFFFE0; }
20
  .hmbkp_active:before { content: "\00a0 \2713 "; font-size: 11px; }
21
  .hmbkp_active, .hmbkp_active code, #hmbkp-constants .hmbkp_active + dd { background: #E5F7E8; }
22
+ .contextual-help-tabs-wrap .updated { margin: 15px 0 0; }
23
+ #hmbkp_backup.hmbkp_running { background-image: url('../../../../wp-admin/images/wpspin_light.gif'); background-repeat: no-repeat; background-position: 2px 2px; padding-left: 20px; }
assets/hmbkp.js CHANGED
@@ -13,7 +13,7 @@ jQuery( document ).ready( function( $ ) {
13
  }
14
  );
15
  }
16
-
17
  $.get( ajaxurl, { 'action' : 'hmbkp_cron_test' },
18
  function( data ) {
19
  if ( data != 1 ) {
@@ -22,29 +22,43 @@ jQuery( document ).ready( function( $ ) {
22
  }
23
  );
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  $( '.hmbkp-settings-toggle' ).click( function( e ) {
26
 
27
  $( '#hmbkp-settings' ).toggle();
28
-
29
  e.preventDefault();
30
 
31
  } );
32
-
33
  if ( typeof( screenMeta ) != 'undefined' ) {
34
  $( '.hmbkp-show-help-tab' ).click( screenMeta.toggleEvent );
35
  }
36
-
37
  if ( window.location.hash == '#hmbkp-settings' ){
38
- $( '#hmbkp-settings' ).show();
39
  }
40
-
41
 
42
  } );
43
 
44
  function hmbkpRedirectOnBackupComplete() {
45
 
46
- img = jQuery( '<div>' ).append( jQuery( '.hmbkp_running a.add-new-h2[disabled]:first img' ).clone() ).remove().html();
47
-
48
  jQuery.get( ajaxurl, { 'action' : 'hmbkp_is_in_progress' },
49
 
50
  function( data ) {
@@ -55,9 +69,9 @@ function hmbkpRedirectOnBackupComplete() {
55
 
56
  } else {
57
 
58
- setTimeout( 'hmbkpRedirectOnBackupComplete();', 5000 );
59
 
60
- jQuery( '.hmbkp_running a.add-new-h2[disabled]:first' ).html( img + data );
61
 
62
  }
63
  }
13
  }
14
  );
15
  }
16
+
17
  $.get( ajaxurl, { 'action' : 'hmbkp_cron_test' },
18
  function( data ) {
19
  if ( data != 1 ) {
22
  }
23
  );
24
 
25
+ $( '#hmbkp_backup:not(.hmbkp_running)' ).live( 'click', function( e ) {
26
+
27
+ ajaxRequest = $.get( ajaxurl, { 'action' : 'hmbkp_backup' } );
28
+
29
+ setTimeout( function() {
30
+
31
+ ajaxRequest.abort();
32
+
33
+ hmbkpRedirectOnBackupComplete();
34
+
35
+ }, 50 );
36
+
37
+ e.preventDefault();
38
+
39
+ } );
40
+
41
  $( '.hmbkp-settings-toggle' ).click( function( e ) {
42
 
43
  $( '#hmbkp-settings' ).toggle();
44
+
45
  e.preventDefault();
46
 
47
  } );
48
+
49
  if ( typeof( screenMeta ) != 'undefined' ) {
50
  $( '.hmbkp-show-help-tab' ).click( screenMeta.toggleEvent );
51
  }
52
+
53
  if ( window.location.hash == '#hmbkp-settings' ){
54
+ $( '#hmbkp-settings' ).show();
55
  }
56
+
57
 
58
  } );
59
 
60
  function hmbkpRedirectOnBackupComplete() {
61
 
 
 
62
  jQuery.get( ajaxurl, { 'action' : 'hmbkp_is_in_progress' },
63
 
64
  function( data ) {
69
 
70
  } else {
71
 
72
+ setTimeout( 'hmbkpRedirectOnBackupComplete();', 1000 );
73
 
74
+ jQuery( '#hmbkp_backup' ).replaceWith( data );
75
 
76
  }
77
  }
functions/backup.actions.php CHANGED
@@ -5,7 +5,7 @@ add_action( 'hmbkp_backup_started', 'hmbkp_set_status', 10, 0 );
5
 
6
  /**
7
  * Set the backup status to dumping database
8
- *
9
  * @return null
10
  */
11
  function hmbkp_set_status_dumping_database() {
@@ -15,10 +15,47 @@ add_action( 'hmbkp_mysqldump_started', 'hmbkp_set_status_dumping_database' );
15
 
16
  /**
17
  * Set the backup status to archiving
18
- *
19
  * @return null
20
  */
21
  function hmbkp_set_status_archiving() {
22
  hmbkp_set_status( __( 'Creating zip archive', 'hmbkp' ) );
23
  }
24
- add_action( 'hmbkp_archive_started', 'hmbkp_set_status_archiving' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  /**
7
  * Set the backup status to dumping database
8
+ *
9
  * @return null
10
  */
11
  function hmbkp_set_status_dumping_database() {
15
 
16
  /**
17
  * Set the backup status to archiving
18
+ *
19
  * @return null
20
  */
21
  function hmbkp_set_status_archiving() {
22
  hmbkp_set_status( __( 'Creating zip archive', 'hmbkp' ) );
23
  }
24
+ add_action( 'hmbkp_archive_started', 'hmbkp_set_status_archiving' );
25
+
26
+ function hmbkp_backup_complete( $backup ) {
27
+
28
+ if ( $backup->errors() ) {
29
+
30
+ hmbkp_cleanup();
31
+
32
+ $file = hmbkp_path() . '/.backup_errors';
33
+
34
+ if ( file_exists( $file ) )
35
+ unlink( $file );
36
+
37
+ if ( ! $handle = @fopen( $file, 'w' ) )
38
+ return;
39
+
40
+ fwrite( $handle, json_encode( $backup->errors() ) );
41
+
42
+ fclose( $handle );
43
+
44
+ } elseif ( $backup->warnings() ) {
45
+
46
+ $file = hmbkp_path() . '/.backup_warnings';
47
+
48
+ if ( file_exists( $file ) )
49
+ unlink( $file );
50
+
51
+ if ( ! $handle = @fopen( $file, 'w' ) )
52
+ return;
53
+
54
+ fwrite( $handle, json_encode( $backup->warnings() ) );
55
+
56
+ fclose( $handle );
57
+
58
+ }
59
+
60
+ }
61
+ add_action( 'hmbkp_backup_complete', 'hmbkp_backup_complete' );
functions/backup.functions.php CHANGED
@@ -1,50 +1,50 @@
1
  <?php
2
 
3
- /**
4
  * Run HM Backup
5
  *
6
  * @return null
7
  */
8
  function hmbkp_do_backup() {
9
-
10
  // Make sure it's possible to do a backup
11
  if ( ! hmbkp_possible() )
12
  return;
13
-
14
- // Clean up any mess left by the last backup
15
  hmbkp_cleanup();
16
-
17
  HM_Backup::get_instance()->backup();
18
-
19
  // Email Backup
20
- hmbkp_email_backup( HM_Backup::get_instance()->archive_filepath() );
21
-
22
  hmbkp_set_status( __( 'Removing old backups', 'hmbkp' ) );
23
-
24
  // Delete any old backup files
25
  hmbkp_delete_old_backups();
26
-
27
  if ( file_exists( hmbkp_path() . '/.backup_running' ) )
28
  unlink( hmbkp_path() . '/.backup_running' );
29
-
30
  if ( file_exists( HM_Backup::get_instance()->archive_filepath() ) ) {
31
 
32
  $file = hmbkp_path() . '/.backup_complete';
33
-
34
- if ( !$handle = @fopen( $file, 'w' ) )
35
- return false;
36
-
37
  fwrite( $handle, '' );
38
-
39
  fclose( $handle );
40
-
41
  }
42
-
43
  }
44
 
45
  /**
46
  * Deletes old backup files
47
- *
48
  * @return null
49
  */
50
  function hmbkp_delete_old_backups() {
@@ -61,8 +61,9 @@ function hmbkp_delete_old_backups() {
61
 
62
  /**
63
  * Returns an array of backup files
64
- *
65
  * @todo exclude the currently running backup
 
66
  * @return array $files
67
  */
68
  function hmbkp_get_backups() {
@@ -71,7 +72,7 @@ function hmbkp_get_backups() {
71
 
72
  $hmbkp_path = hmbkp_path();
73
 
74
- if ( $handle = opendir( $hmbkp_path ) ) :
75
 
76
  while ( false !== ( $file = readdir( $handle ) ) )
77
  if ( end( explode( '.', $file ) ) == 'zip' )
@@ -112,7 +113,7 @@ function hmbkp_delete_backup( $file ) {
112
 
113
  // Delete the file
114
  if ( strpos( $file, hmbkp_path() ) !== false || strpos( $file, WP_CONTENT_DIR . '/backups' ) !== false )
115
- unlink( $file );
116
 
117
  }
118
 
@@ -122,15 +123,17 @@ function hmbkp_delete_backup( $file ) {
122
  * @param $file
123
  * @return bool
124
  */
125
- function hmbkp_email_backup( $file ) {
126
 
127
- if ( !hmbkp_get_email_address() )
128
- return;
 
 
129
 
130
  // Raise the memory and time limit
131
  @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
132
  @set_time_limit( 0 );
133
-
134
  // @todo admin_url?
135
  $download = get_bloginfo( 'wpurl' ) . '/wp-admin/tools.php?page=' . HMBKP_PLUGIN_SLUG . '&hmbkp_download=' . base64_encode( $file );
136
  $domain = parse_url( get_bloginfo( 'url' ), PHP_URL_HOST ) . parse_url( get_bloginfo( 'url' ), PHP_URL_PATH );
@@ -165,35 +168,35 @@ function hmbkp_email_backup( $file ) {
165
 
166
  /**
167
  * Set the status of the running backup
168
- *
169
  * @param string $message. (default: '')
170
  * @return void
171
  */
172
  function hmbkp_set_status( $message = '' ) {
173
-
174
  $file = hmbkp_path() . '/.backup_running';
175
-
176
  if ( ! $handle = @fopen( $file, 'w' ) )
177
  return;
178
-
179
  fwrite( $handle, $message );
180
-
181
  fclose( $handle );
182
-
183
  }
184
 
185
  /**
186
  * Get the status of the running backup
187
- *
188
  * @return string
189
  */
190
  function hmbkp_get_status() {
191
-
192
  if ( ! file_exists( hmbkp_path() . '/.backup_running' ) )
193
  return '';
194
-
195
  return file_get_contents( hmbkp_path() .'/.backup_running' );
196
-
197
  }
198
 
199
  /**
@@ -209,7 +212,7 @@ function hmbkp_get_excludes() {
209
  if ( get_option( 'hmbkp_excludes' ) )
210
  return get_option( 'hmbkp_excludes' );
211
 
212
- return false;
213
 
214
  }
215
 
@@ -224,9 +227,9 @@ function hmbkp_invalid_custom_excludes() {
224
 
225
  // Check if any absolute path excludes actually exist
226
  if ( $excludes = hmbkp_get_excludes() )
227
-
228
  foreach ( explode( ',', $excludes ) as $rule )
229
- if ( ( $rule = trim( $rule ) ) && in_array( substr( $rule, 0, 1 ), array( '/', '\\' ) ) && !file_exists( $rule ) && ! file_exists( ABSPATH . $rule ) && ! file_exists( trailingslashit( ABSPATH ) . $rule ) )
230
  $invalid_rules[] = $rule;
231
 
232
  return array_filter( $invalid_rules );
@@ -261,10 +264,28 @@ function hmbkp_is_in_progress() {
261
 
262
  /**
263
  * Get the exclude string from HM Backup
264
- *
265
  * @param string $context
266
  * @return string
267
  */
268
  function hmbkp_exclude_string( $context ) {
269
  return HM_Backup::get_instance()->exclude_string( $context );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
  }
1
  <?php
2
 
3
+ /**
4
  * Run HM Backup
5
  *
6
  * @return null
7
  */
8
  function hmbkp_do_backup() {
9
+
10
  // Make sure it's possible to do a backup
11
  if ( ! hmbkp_possible() )
12
  return;
13
+
14
+ // Clean up any mess left by a previous backup
15
  hmbkp_cleanup();
16
+
17
  HM_Backup::get_instance()->backup();
18
+
19
  // Email Backup
20
+ hmbkp_email_backup();
21
+
22
  hmbkp_set_status( __( 'Removing old backups', 'hmbkp' ) );
23
+
24
  // Delete any old backup files
25
  hmbkp_delete_old_backups();
26
+
27
  if ( file_exists( hmbkp_path() . '/.backup_running' ) )
28
  unlink( hmbkp_path() . '/.backup_running' );
29
+
30
  if ( file_exists( HM_Backup::get_instance()->archive_filepath() ) ) {
31
 
32
  $file = hmbkp_path() . '/.backup_complete';
33
+
34
+ if ( ! $handle = @fopen( $file, 'w' ) )
35
+ return;
36
+
37
  fwrite( $handle, '' );
38
+
39
  fclose( $handle );
40
+
41
  }
42
+
43
  }
44
 
45
  /**
46
  * Deletes old backup files
47
+ *
48
  * @return null
49
  */
50
  function hmbkp_delete_old_backups() {
61
 
62
  /**
63
  * Returns an array of backup files
64
+ *
65
  * @todo exclude the currently running backup
66
+ * @todo use RecursiveDirectoryIterator
67
  * @return array $files
68
  */
69
  function hmbkp_get_backups() {
72
 
73
  $hmbkp_path = hmbkp_path();
74
 
75
+ if ( $handle = @opendir( $hmbkp_path ) ) :
76
 
77
  while ( false !== ( $file = readdir( $handle ) ) )
78
  if ( end( explode( '.', $file ) ) == 'zip' )
113
 
114
  // Delete the file
115
  if ( strpos( $file, hmbkp_path() ) !== false || strpos( $file, WP_CONTENT_DIR . '/backups' ) !== false )
116
+ unlink( $file );
117
 
118
  }
119
 
123
  * @param $file
124
  * @return bool
125
  */
126
+ function hmbkp_email_backup() {
127
 
128
+ if ( ! hmbkp_get_email_address() )
129
+ return false;
130
+
131
+ $file = HM_Backup::get_instance()->archive_filepath();
132
 
133
  // Raise the memory and time limit
134
  @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
135
  @set_time_limit( 0 );
136
+
137
  // @todo admin_url?
138
  $download = get_bloginfo( 'wpurl' ) . '/wp-admin/tools.php?page=' . HMBKP_PLUGIN_SLUG . '&hmbkp_download=' . base64_encode( $file );
139
  $domain = parse_url( get_bloginfo( 'url' ), PHP_URL_HOST ) . parse_url( get_bloginfo( 'url' ), PHP_URL_PATH );
168
 
169
  /**
170
  * Set the status of the running backup
171
+ *
172
  * @param string $message. (default: '')
173
  * @return void
174
  */
175
  function hmbkp_set_status( $message = '' ) {
176
+
177
  $file = hmbkp_path() . '/.backup_running';
178
+
179
  if ( ! $handle = @fopen( $file, 'w' ) )
180
  return;
181
+
182
  fwrite( $handle, $message );
183
+
184
  fclose( $handle );
185
+
186
  }
187
 
188
  /**
189
  * Get the status of the running backup
190
+ *
191
  * @return string
192
  */
193
  function hmbkp_get_status() {
194
+
195
  if ( ! file_exists( hmbkp_path() . '/.backup_running' ) )
196
  return '';
197
+
198
  return file_get_contents( hmbkp_path() .'/.backup_running' );
199
+
200
  }
201
 
202
  /**
212
  if ( get_option( 'hmbkp_excludes' ) )
213
  return get_option( 'hmbkp_excludes' );
214
 
215
+ return '';
216
 
217
  }
218
 
227
 
228
  // Check if any absolute path excludes actually exist
229
  if ( $excludes = hmbkp_get_excludes() )
230
+
231
  foreach ( explode( ',', $excludes ) as $rule )
232
+ if ( ( $rule = trim( $rule ) ) && in_array( substr( $rule, 0, 1 ), array( '/', '\\' ) ) && ! file_exists( $rule ) && ! file_exists( ABSPATH . $rule ) && ! file_exists( trailingslashit( ABSPATH ) . $rule ) )
233
  $invalid_rules[] = $rule;
234
 
235
  return array_filter( $invalid_rules );
264
 
265
  /**
266
  * Get the exclude string from HM Backup
267
+ *
268
  * @param string $context
269
  * @return string
270
  */
271
  function hmbkp_exclude_string( $context ) {
272
  return HM_Backup::get_instance()->exclude_string( $context );
273
+ }
274
+
275
+ function hmbkp_backup_errors() {
276
+
277
+ if ( ! file_exists( hmbkp_path() . '/.backup_errors' ) )
278
+ return '';
279
+
280
+ return file_get_contents( hmbkp_path() . '/.backup_errors' );
281
+
282
+ }
283
+
284
+ function hmbkp_backup_warnings() {
285
+
286
+ if ( ! file_exists( hmbkp_path() . '/.backup_warnings' ) )
287
+ return '';
288
+
289
+ return file_get_contents( hmbkp_path() . '/.backup_warnings' );
290
+
291
  }
functions/core.functions.php CHANGED
@@ -183,53 +183,6 @@ function hmbkp_more_reccurences( $recc ) {
183
  }
184
  add_filter( 'cron_schedules', 'hmbkp_more_reccurences' );
185
 
186
- /**
187
- * Send a flie to the browser for download
188
- *
189
- * @param string $path
190
- */
191
- function hmbkp_send_file( $path ) {
192
-
193
- session_write_close();
194
-
195
- ob_end_clean();
196
-
197
- if ( !is_file( $path ) || connection_status() != 0 )
198
- return false;
199
-
200
- // Overide max_execution_time
201
- @set_time_limit( 0 );
202
-
203
- $name = basename( $path );
204
-
205
- // Filenames in IE containing dots will screw up the filename unless we add this
206
- if ( strstr( $_SERVER['HTTP_USER_AGENT'], 'MSIE' ) )
207
- $name = preg_replace( '/\./', '%2e', $name, substr_count( $name, '.' ) - 1 );
208
-
209
- // Force
210
- header( 'Cache-Control: ' );
211
- header( 'Pragma: ' );
212
- header( 'Content-Type: application/octet-stream' );
213
- header( 'Content-Length: ' . (string) ( filesize( $path ) ) );
214
- header( 'Content-Disposition: attachment; filename=" ' . $name . '"' );
215
- header( 'Content-Transfer-Encoding: binary\n' );
216
-
217
- if ( $file = fopen( $path, 'rb' ) ) :
218
-
219
- while ( ( !feof( $file ) ) && ( connection_status() == 0) ) :
220
-
221
- print( fread( $file, 1024 * 8 ) );
222
- flush();
223
-
224
- endwhile;
225
-
226
- fclose( $file );
227
-
228
- endif;
229
-
230
- return ( connection_status() == 0 ) and !connection_aborted();
231
- }
232
-
233
  /**
234
  * Recursively delete a directory including
235
  * all the files and sub-directories.
@@ -241,43 +194,22 @@ function hmbkp_rmdirtree( $dir ) {
241
  if ( is_file( $dir ) )
242
  unlink( $dir );
243
 
244
- if ( !is_dir( $dir ) )
245
  return false;
246
 
247
- $result = array();
248
-
249
- $dir = trailingslashit( $dir );
250
-
251
- $handle = opendir( $dir );
252
-
253
- while ( false !== ( $file = readdir( $handle ) ) ) :
254
-
255
- // Ignore . and ..
256
- if ( $file != '.' && $file != '..' ) :
257
-
258
- $path = $dir . $file;
259
-
260
- // Recurse if subdir, Delete if file
261
- if ( is_dir( $path ) ) :
262
- $result = array_merge( $result, hmbkp_rmdirtree( $path ) );
263
-
264
- else :
265
- unlink( $path );
266
- $result[] .= $path;
267
 
268
- endif;
269
 
270
- endif;
 
271
 
272
- endwhile;
 
273
 
274
- closedir( $handle );
275
-
276
- rmdir( $dir );
277
-
278
- $result[] .= $dir;
279
 
280
- return $result;
281
 
282
  }
283
 
@@ -316,23 +248,8 @@ function hmbkp_calculate() {
316
  // Get rid of any cached filesizes
317
  clearstatcache();
318
 
319
- $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( ABSPATH ), RecursiveIteratorIterator::SELF_FIRST );
320
-
321
- $excludes = hmbkp_exclude_string( 'regex' );
322
-
323
- foreach ( $files as $file ) {
324
-
325
- // Skip bad files
326
- if ( ! is_readable( $file ) || ! file_exists( $file ) || is_link( $file ) )
327
- continue;
328
-
329
- // Excludes
330
- if ( $excludes && preg_match( '(' . $excludes . ')', str_replace( ABSPATH, '', $file ) ) )
331
- continue;
332
-
333
- $filesize += (float) @filesize( $file );
334
-
335
- }
336
 
337
  }
338
 
@@ -421,11 +338,11 @@ function hmbkp_path() {
421
  $path = HMBKP_PATH;
422
 
423
  // If the dir doesn't exist or isn't writable then use wp-content/backups instead
424
- if ( ( !$path || !is_writable( $path ) ) && hmbkp_conform_dir( $path ) != hmbkp_path_default() )
425
  $path = hmbkp_path_default();
426
 
427
  // Create the backups directory if it doesn't exist
428
- if ( is_writable( dirname( $path ) ) && !is_dir( $path ) )
429
  mkdir( $path, 0755 );
430
 
431
  if ( get_option( 'hmbkp_path' ) != $path )
@@ -436,10 +353,12 @@ function hmbkp_path() {
436
 
437
  $contents[] = '# ' . __( 'This .htaccess file ensures that other people cannot download your backup files.', 'hmbkp' );
438
  $contents[] = '';
439
- $contents[] = 'deny from all';
 
 
440
  $contents[] = '';
441
 
442
- if ( !file_exists( $htaccess ) && is_writable( $path ) && require_once( ABSPATH . '/wp-admin/includes/misc.php' ) )
443
  insert_with_markers( $htaccess, 'BackUpWordPress', $contents );
444
 
445
  return hmbkp_conform_dir( $path );
@@ -465,7 +384,7 @@ function hmbkp_path_default() {
465
  function hmbkp_path_move( $from, $to ) {
466
 
467
  // Create the custom backups directory if it doesn't exist
468
- if ( is_writable( dirname( $to ) ) && !is_dir( $to ) )
469
  mkdir( $to, 0755 );
470
 
471
  if ( !is_dir( $to ) || !is_writable( $to ) || !is_dir( $from ) )
@@ -585,7 +504,7 @@ function hmbkp_get_disable_automatic_backup() {
585
  */
586
  function hmbkp_possible() {
587
 
588
- if ( !is_writable( hmbkp_path() ) || !is_dir( hmbkp_path() ) || hmbkp_is_safe_mode_active() )
589
  return false;
590
 
591
  if ( defined( 'HMBKP_FILES_ONLY' ) && HMBKP_FILES_ONLY && defined( 'HMBKP_DATABASE_ONLY' ) && HMBKP_DATABASE_ONLY )
183
  }
184
  add_filter( 'cron_schedules', 'hmbkp_more_reccurences' );
185
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  /**
187
  * Recursively delete a directory including
188
  * all the files and sub-directories.
194
  if ( is_file( $dir ) )
195
  unlink( $dir );
196
 
197
+ if ( ! is_dir( $dir ) )
198
  return false;
199
 
200
+ $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ), RecursiveIteratorIterator::CHILD_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
 
202
+ foreach ( $files as $file ) {
203
 
204
+ if ( $file->isDir() )
205
+ @rmdir( $file->getPathname() );
206
 
207
+ else
208
+ @unlink( $file->getPathname() );
209
 
210
+ }
 
 
 
 
211
 
212
+ @rmdir( $dir );
213
 
214
  }
215
 
248
  // Get rid of any cached filesizes
249
  clearstatcache();
250
 
251
+ foreach ( HM_Backup::get_instance()->files() as $file )
252
+ $filesize += (float) @filesize( ABSPATH . $file );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
 
254
  }
255
 
338
  $path = HMBKP_PATH;
339
 
340
  // If the dir doesn't exist or isn't writable then use wp-content/backups instead
341
+ if ( ( ! $path || ! is_writable( $path ) ) && hmbkp_conform_dir( $path ) != hmbkp_path_default() )
342
  $path = hmbkp_path_default();
343
 
344
  // Create the backups directory if it doesn't exist
345
+ if ( is_writable( dirname( $path ) ) && ! is_dir( $path ) )
346
  mkdir( $path, 0755 );
347
 
348
  if ( get_option( 'hmbkp_path' ) != $path )
353
 
354
  $contents[] = '# ' . __( 'This .htaccess file ensures that other people cannot download your backup files.', 'hmbkp' );
355
  $contents[] = '';
356
+ $contents[] = 'RewriteEngine On';
357
+ $contents[] = 'RewriteCond %{QUERY_STRING} !key=' . md5( SECURE_AUTH_KEY );
358
+ $contents[] = 'RewriteRule (.*) - [F]';
359
  $contents[] = '';
360
 
361
+ if ( ! file_exists( $htaccess ) && is_writable( $path ) && require_once( ABSPATH . '/wp-admin/includes/misc.php' ) )
362
  insert_with_markers( $htaccess, 'BackUpWordPress', $contents );
363
 
364
  return hmbkp_conform_dir( $path );
384
  function hmbkp_path_move( $from, $to ) {
385
 
386
  // Create the custom backups directory if it doesn't exist
387
+ if ( is_writable( dirname( $to ) ) && ! is_dir( $to ) )
388
  mkdir( $to, 0755 );
389
 
390
  if ( !is_dir( $to ) || !is_writable( $to ) || !is_dir( $from ) )
504
  */
505
  function hmbkp_possible() {
506
 
507
+ if ( ! is_writable( hmbkp_path() ) || ! is_dir( hmbkp_path() ) || hmbkp_is_safe_mode_active() )
508
  return false;
509
 
510
  if ( defined( 'HMBKP_FILES_ONLY' ) && HMBKP_FILES_ONLY && defined( 'HMBKP_DATABASE_ONLY' ) && HMBKP_DATABASE_ONLY )
functions/interface.functions.php CHANGED
@@ -49,7 +49,7 @@ function hmbkp_admin_notices() {
49
 
50
  global $hmbkp_errors;
51
 
52
- if ( !empty( $hmbkp_errors ) && $hmbkp_errors->get_error_code() )
53
  foreach( $hmbkp_errors->get_error_messages() as $hmbkp_error )
54
  echo '<div class="error"><p>' . $hmbkp_error . '</p></div>';
55
 
@@ -59,7 +59,7 @@ function hmbkp_admin_notices() {
59
  endif;
60
 
61
  // If the backups directory doesn't exist and can't be automatically created
62
- if ( !is_dir( hmbkp_path() ) ) :
63
 
64
  function hmbkp_path_exists_warning() {
65
  $php_user = exec( 'whoami' );
@@ -71,7 +71,7 @@ function hmbkp_admin_notices() {
71
  endif;
72
 
73
  // If the backups directory exists but isn't writable
74
- if ( is_dir( hmbkp_path() ) && !is_writable( hmbkp_path() ) ) :
75
 
76
  function hmbkp_writable_path_warning() {
77
  $php_user = exec( 'whoami' );
@@ -103,10 +103,10 @@ function hmbkp_admin_notices() {
103
  endif;
104
 
105
  // If the email address is invalid
106
- if ( defined( 'HMBKP_EMAIL' ) && !is_email( HMBKP_EMAIL ) ) :
107
 
108
  function hmbkp_email_invalid_warning() {
109
- echo '<div id="hmbkp-email_invalid" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( '%s is not a valid email address.', 'hmbkp' ), '<code>' . HMBKP_EMAIL . '</code>' ) . '</p></div>';
110
  }
111
  add_action( 'admin_notices', 'hmbkp_email_invalid_warning' );
112
 
@@ -116,27 +116,27 @@ function hmbkp_admin_notices() {
116
  if ( defined( 'HMBKP_EMAIL' ) && get_option( 'hmbkp_email_error' ) ) :
117
 
118
  function hmbkp_email_failed_warning() {
119
- echo '<div id="hmbkp-email_invalid" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . __( 'The last backup email failed to send.', 'hmbkp' ) . '</p></div>';
120
  }
121
  add_action( 'admin_notices', 'hmbkp_email_failed_warning' );
122
 
123
  endif;
124
 
125
  // If a custom backups directory is defined and it doesn't exist and can't be created
126
- if ( defined( 'HMBKP_PATH' ) && HMBKP_PATH && !is_dir( HMBKP_PATH ) ) :
127
 
128
  function hmbkp_custom_path_exists_warning() {
129
- echo '<div id="hmbkp-email_invalid" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( 'Your custom backups directory %s doesn\'t exist and can\'t be created, your backups will be saved to %s instead.', 'hmbkp' ), '<code>' . HMBKP_PATH . '</code>', '<code>' . hmbkp_path() . '</code>' ) . '</p></div>';
130
  }
131
  add_action( 'admin_notices', 'hmbkp_custom_path_exists_warning' );
132
 
133
  endif;
134
 
135
  // If a custom backups directory is defined and exists but isn't writable
136
- if ( defined( 'HMBKP_PATH' ) && HMBKP_PATH && is_dir( HMBKP_PATH ) && !is_writable( HMBKP_PATH ) ) :
137
 
138
  function hmbkp_custom_path_writable_notice() {
139
- echo '<div id="hmbkp-email_invalid" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( 'Your custom backups directory %s isn\'t writable, new backups will be saved to %s instead.', 'hmbkp' ), '<code>' . HMBKP_PATH . '</code>', '<code>' . hmbkp_path() . '</code>' ) . '</p></div>';
140
  }
141
  add_action( 'admin_notices', 'hmbkp_custom_path_writable_notice' );
142
 
@@ -146,12 +146,33 @@ function hmbkp_admin_notices() {
146
  if ( hmbkp_invalid_custom_excludes() ) :
147
 
148
  function hmbkp_invalid_exclude_notice() {
149
- echo '<div id="hmbkp-email_invalid" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( 'You have defined a custom exclude list but the following paths don\'t exist %s, are you sure you entered them correctly?', 'hmbkp' ), '<code>' . implode( '</code>, <code>', (array) hmbkp_invalid_custom_excludes() ) . '</code>' ) . '</p></div>';
150
  }
151
  add_action( 'admin_notices', 'hmbkp_invalid_exclude_notice' );
152
 
153
  endif;
154
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  }
156
  add_action( 'admin_head', 'hmbkp_admin_notices' );
157
 
@@ -169,4 +190,28 @@ function hmbkp_plugin_row( $plugins ) {
169
  return $plugins;
170
 
171
  }
172
- add_filter( 'all_plugins', 'hmbkp_plugin_row', 10 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  global $hmbkp_errors;
51
 
52
+ if ( ! empty( $hmbkp_errors ) && $hmbkp_errors->get_error_code() )
53
  foreach( $hmbkp_errors->get_error_messages() as $hmbkp_error )
54
  echo '<div class="error"><p>' . $hmbkp_error . '</p></div>';
55
 
59
  endif;
60
 
61
  // If the backups directory doesn't exist and can't be automatically created
62
+ if ( ! is_dir( hmbkp_path() ) ) :
63
 
64
  function hmbkp_path_exists_warning() {
65
  $php_user = exec( 'whoami' );
71
  endif;
72
 
73
  // If the backups directory exists but isn't writable
74
+ if ( is_dir( hmbkp_path() ) && ! is_writable( hmbkp_path() ) ) :
75
 
76
  function hmbkp_writable_path_warning() {
77
  $php_user = exec( 'whoami' );
103
  endif;
104
 
105
  // If the email address is invalid
106
+ if ( defined( 'HMBKP_EMAIL' ) && ! is_email( HMBKP_EMAIL ) ) :
107
 
108
  function hmbkp_email_invalid_warning() {
109
+ echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( '%s is not a valid email address.', 'hmbkp' ), '<code>' . HMBKP_EMAIL . '</code>' ) . '</p></div>';
110
  }
111
  add_action( 'admin_notices', 'hmbkp_email_invalid_warning' );
112
 
116
  if ( defined( 'HMBKP_EMAIL' ) && get_option( 'hmbkp_email_error' ) ) :
117
 
118
  function hmbkp_email_failed_warning() {
119
+ echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . __( 'The last backup email failed to send.', 'hmbkp' ) . '</p></div>';
120
  }
121
  add_action( 'admin_notices', 'hmbkp_email_failed_warning' );
122
 
123
  endif;
124
 
125
  // If a custom backups directory is defined and it doesn't exist and can't be created
126
+ if ( defined( 'HMBKP_PATH' ) && HMBKP_PATH && ! is_dir( HMBKP_PATH ) ) :
127
 
128
  function hmbkp_custom_path_exists_warning() {
129
+ echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( 'Your custom backups directory %s doesn\'t exist and can\'t be created, your backups will be saved to %s instead.', 'hmbkp' ), '<code>' . HMBKP_PATH . '</code>', '<code>' . hmbkp_path() . '</code>' ) . '</p></div>';
130
  }
131
  add_action( 'admin_notices', 'hmbkp_custom_path_exists_warning' );
132
 
133
  endif;
134
 
135
  // If a custom backups directory is defined and exists but isn't writable
136
+ if ( defined( 'HMBKP_PATH' ) && HMBKP_PATH && is_dir( HMBKP_PATH ) && ! is_writable( HMBKP_PATH ) ) :
137
 
138
  function hmbkp_custom_path_writable_notice() {
139
+ echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( 'Your custom backups directory %s isn\'t writable, new backups will be saved to %s instead.', 'hmbkp' ), '<code>' . HMBKP_PATH . '</code>', '<code>' . hmbkp_path() . '</code>' ) . '</p></div>';
140
  }
141
  add_action( 'admin_notices', 'hmbkp_custom_path_writable_notice' );
142
 
146
  if ( hmbkp_invalid_custom_excludes() ) :
147
 
148
  function hmbkp_invalid_exclude_notice() {
149
+ echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress has detected a problem.', 'hmbkp' ) . '</strong> ' . sprintf( __( 'You have defined a custom exclude list but the following paths don\'t exist %s, are you sure you entered them correctly?', 'hmbkp' ), '<code>' . implode( '</code>, <code>', (array) hmbkp_invalid_custom_excludes() ) . '</code>' ) . '</p></div>';
150
  }
151
  add_action( 'admin_notices', 'hmbkp_invalid_exclude_notice' );
152
 
153
  endif;
154
 
155
+ // If there are any errors reported in the backup
156
+ if ( hmbkp_backup_errors() ) :
157
+
158
+ function hmbkp_backup_errors_notice() {
159
+ echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress detected that your last backup failed.', 'hmbkp' ) . '</strong></p>' . hmbkp_backup_errors_message() . '</div>';
160
+ }
161
+ add_action( 'admin_notices', 'hmbkp_backup_errors_notice' );
162
+
163
+ endif;
164
+
165
+ // If there are any warnings reported in the backup
166
+ if ( hmbkp_backup_warnings() ) :
167
+
168
+ function hmbkp_backup_warnings_notice() {
169
+ echo '<div id="hmbkp-warning" class="updated fade"><p><strong>' . __( 'BackUpWordPress detected an issue with your last backup.', 'hmbkp' ) . '</strong></p>' . hmbkp_backup_warnings_message() . '</div>';
170
+ }
171
+ add_action( 'admin_notices', 'hmbkp_backup_warnings_notice' );
172
+
173
+ endif;
174
+
175
+
176
  }
177
  add_action( 'admin_head', 'hmbkp_admin_notices' );
178
 
190
  return $plugins;
191
 
192
  }
193
+ add_filter( 'all_plugins', 'hmbkp_plugin_row', 10 );
194
+
195
+ function hmbkp_backup_errors_message() {
196
+
197
+ $message = '';
198
+
199
+ foreach ( json_decode( hmbkp_backup_errors() ) as $key => $errors )
200
+ foreach ( $errors as $error )
201
+ $message .= '<p><strong>' . $key . '</strong>: <code>' . implode( ':', (array) $error ) . '</code></p>';
202
+
203
+ return $message;
204
+
205
+ }
206
+
207
+ function hmbkp_backup_warnings_message() {
208
+
209
+ $message = '';
210
+
211
+ foreach ( json_decode( hmbkp_backup_warnings() ) as $key => $errors )
212
+ foreach ( $errors as $error )
213
+ $message .= '<p><strong>' . $key . '</strong>: <code>' . implode( ':', (array) $error ) . '</code></p>';
214
+
215
+ return $message;
216
+
217
+ }
functions/wp-cli.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Implement backup command
5
+ *
6
+ * @package wp-cli
7
+ * @subpackage commands/third-party
8
+ */
9
+ class BackUpCommand extends WP_CLI_Command {
10
+
11
+ function __construct( $args, $assoc_args ) {
12
+
13
+ // Make sure it's possible to do a backup
14
+ if ( hmbkp_is_safe_mode_active() ) {
15
+ WP_CLI::error( 'Backup not possible when php is running safe_mode on' );
16
+ return false;
17
+ }
18
+
19
+ remove_action( 'hmbkp_backup_started', 'hmbkp_set_status', 10, 0 );
20
+ remove_action( 'hmbkp_mysqldump_started', 'hmbkp_set_status_dumping_database' );
21
+ remove_action( 'hmbkp_archive_started', 'hmbkp_set_status_archiving' );
22
+
23
+ add_action( 'hmbkp_mysqldump_started', function() {
24
+ WP_CLI::line( 'Backup: Dumping database...' );
25
+ } );
26
+
27
+ add_action( 'hmbkp_archive_started', function() {
28
+ WP_CLI::line( 'Backup: Zipping everything up...' );
29
+ } );
30
+
31
+ // Clean up any mess left by a previous backup
32
+ hmbkp_cleanup();
33
+
34
+ $hm_backup = HM_Backup::get_instance();
35
+
36
+ if ( ! empty( $assoc_args['path'] ) )
37
+ $hm_backup->path = $assoc_args['path'];
38
+
39
+ if ( ! empty( $assoc_args['root'] ) )
40
+ $hm_backup->root = $assoc_args['root'];
41
+
42
+ if ( ( ! is_dir( $hm_backup->path() ) && ( ! is_writable( dirname( $hm_backup->path() ) ) || ! mkdir( $hm_backup->path() ) ) ) || ! is_writable( $hm_backup->path() ) ) {
43
+ WP_CLI::error( 'Invalid backup path' );
44
+ return false;
45
+ }
46
+
47
+
48
+ if ( ! is_dir( $hm_backup->root() ) || ! is_readable( $hm_backup->root() ) ) {
49
+ WP_CLI::error( 'Invalid root path' );
50
+ return false;
51
+ }
52
+
53
+ // Default to both
54
+ $hm_backup->files_only = false;
55
+ $hm_backup->database_only = false;
56
+
57
+ if ( ! empty( $assoc_args['files_only'] ) )
58
+ $hm_backup->files_only = true;
59
+
60
+ if ( ! empty( $assoc_args['database_only'] ) )
61
+ $hm_backup->database_only = true;
62
+
63
+ if ( ! empty( $assoc_args['mysqldump_command_path'] ) )
64
+ $hm_backup->mysqldump_command_path = empty( $assoc_args['mysqldump_command_path'] ) || $assoc_args['mysqldump_command_path'] === 'false' ? false : true;
65
+
66
+ if ( ! empty( $assoc_args['zip_command_path'] ) )
67
+ $hm_backup->zip_command_path = empty( $assoc_args['zip_command_path'] ) || $assoc_args['zip_command_path'] === 'false' ? false : true;
68
+
69
+ if ( ! empty( $assoc_args['excludes'] ) )
70
+ $hm_backup->excludes = $valid_rules = array_filter( array_map( 'trim', explode( ',', $assoc_args['excludes'] ) ) );
71
+
72
+ $hm_backup->backup();
73
+
74
+ WP_CLI::line( 'Backup: deleting old backups...' );
75
+
76
+ // Delete any old backup files
77
+ hmbkp_delete_old_backups();
78
+
79
+ if ( file_exists( HM_Backup::get_instance()->archive_filepath() ) )
80
+ WP_CLI::success( 'Backup Complete: ' . HM_Backup::get_instance()->archive_filepath() );
81
+
82
+ else
83
+ WP_CLI::success( 'Backup Failed' );
84
+
85
+ }
86
+
87
+ static function help() {
88
+
89
+ WP_CLI::line( <<<EOB
90
+ usage: wp backup [--files_only] [--database_only] [--path<dir>] [--root<dir>] [--zip_command_path=<path>] [--mysqldump_command_path=<path>]
91
+
92
+ --files_only Backup files only, default to off
93
+ --database_only Backup database only, defaults to off
94
+ --path dir that the backup should be save in, defaults to wp-content/backups/
95
+ --root dir that should be backed up, defaults to ABSPATH
96
+ --zip_command_path path to your zip binary, standard locations are automatically used
97
+ --mysqldump_command_path path to your mysqldump binary, standard locations are automatically used
98
+
99
+ EOB
100
+ );
101
+
102
+ }
103
+
104
+ }
105
+ WP_CLI::addCommand( 'backup', 'BackUpCommand' );
hm-backup/hm-backup.php CHANGED
@@ -1,9 +1,9 @@
1
  <?php
2
 
3
  /**
4
- * Runs the backup process
5
  *
6
- * @version 1.2
7
  */
8
  class HM_Backup {
9
 
@@ -87,7 +87,55 @@ class HM_Backup {
87
  */
88
  private $db;
89
 
90
- static $instance;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  /**
93
  * Sets up the default properties
@@ -101,8 +149,12 @@ class HM_Backup {
101
  @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
102
  @set_time_limit( 0 );
103
 
 
 
 
 
104
  // Defaults
105
- $this->root = ABSPATH;
106
 
107
  $this->path = $this->conform_dir( WP_CONTENT_DIR . '/backups' );
108
 
@@ -118,6 +170,13 @@ class HM_Backup {
118
 
119
  }
120
 
 
 
 
 
 
 
 
121
  public static function get_instance() {
122
 
123
  if ( empty( self::$instance ) )
@@ -128,27 +187,57 @@ class HM_Backup {
128
  }
129
 
130
  /**
131
- * The full filepath to the archive filepath.
132
  *
133
  * @access public
134
  * @return string
135
  */
136
  public function archive_filepath() {
137
- return trailingslashit( $this->path ) . $this->archive_filename;
 
 
 
 
 
 
 
 
 
 
138
  }
139
 
140
  /**
141
- * The full filepath to the database dump filepath.
142
  *
143
  * @access public
144
  * @return string
145
  */
146
  public function database_dump_filepath() {
147
- return trailingslashit( $this->path ) . $this->database_dump_filename;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  }
149
 
150
  /**
151
- * Run the backup
152
  *
153
  * @access public
154
  * @return bool
@@ -164,7 +253,7 @@ class HM_Backup {
164
  // Zip everything up
165
  $this->archive();
166
 
167
- do_action( 'hmbkp_backup_complete' );
168
 
169
  }
170
 
@@ -181,6 +270,8 @@ class HM_Backup {
181
 
182
  do_action( 'hmbkp_mysqldump_started' );
183
 
 
 
184
  // Use mysqldump if we can
185
  if ( $this->mysqldump_command_path ) {
186
 
@@ -232,13 +323,15 @@ class HM_Backup {
232
  */
233
  public function mysqldump_fallback() {
234
 
 
 
235
  $this->db = mysql_pconnect( DB_HOST, DB_USER, DB_PASSWORD );
236
 
237
  mysql_select_db( DB_NAME, $this->db );
238
  mysql_set_charset( DB_CHARSET, $this->db );
239
 
240
  // Begin new backup of MySql
241
- $tables = mysql_list_tables( DB_NAME );
242
 
243
  $sql_file = "# WordPress : " . get_bloginfo( 'url' ) . " MySQL database backup\n";
244
  $sql_file .= "#\n";
@@ -263,11 +356,11 @@ class HM_Backup {
263
  }
264
 
265
  /**
266
- * Zip up all the wordpress files.
267
  *
268
  * Attempts to use the shell zip command, if
269
- * thats not available then it fallsback on
270
- * PHP zip classes.
271
  *
272
  * @access public
273
  * @return null
@@ -281,11 +374,11 @@ class HM_Backup {
281
  $this->zip();
282
 
283
  // If not or if the shell zip failed then use ZipArchive
284
- if ( ! file_exists( $this->archive_filepath() ) && class_exists( 'ZipArchive' ) && empty( $this->skip_zip_archive ) )
285
  $this->zip_archive();
286
 
287
  // If ZipArchive is unavailable or one of the above failed
288
- if ( ! file_exists( $this->archive_filepath() ) )
289
  $this->pcl_zip();
290
 
291
  // Delete the database dump file
@@ -296,19 +389,29 @@ class HM_Backup {
296
 
297
  }
298
 
 
 
 
 
 
 
299
  public function zip() {
300
 
 
 
301
  // Zip up $this->root with excludes
302
  if ( ! $this->database_only && $this->exclude_string( 'zip' ) )
303
- shell_exec( 'cd ' . escapeshellarg( $this->root ) . ' && ' . escapeshellarg( $this->zip_command_path ) . ' -rq ' . escapeshellarg( $this->archive_filepath() ) . ' ./' . ' -x ' . $this->exclude_string( 'zip' ) . ' 2> /dev/null' );
304
 
305
- // Zip up $this->root
306
  elseif ( ! $this->database_only )
307
- shell_exec( 'cd ' . escapeshellarg( $this->root ) . ' && ' . escapeshellarg( $this->zip_command_path ) . ' -rq ' . escapeshellarg( $this->archive_filepath() ) . ' ./' . ' 2> /dev/null' );
308
 
309
  // Add the database dump to the archive
310
  if ( ! $this->files_only )
311
- shell_exec( 'cd ' . escapeshellarg( $this->path ) . ' && ' . escapeshellarg( $this->zip_command_path ) . ' -uq ' . escapeshellarg( $this->archive_filepath() ) . ' ' . escapeshellarg( $this->database_dump_filename ) . ' 2> /dev/null' );
 
 
312
 
313
  }
314
 
@@ -321,6 +424,8 @@ class HM_Backup {
321
  */
322
  public function zip_archive() {
323
 
 
 
324
  $zip = new ZipArchive();
325
 
326
  if ( ! class_exists( 'ZipArchive' ) || ! $zip->open( $this->archive_filepath(), ZIPARCHIVE::CREATE ) )
@@ -328,27 +433,15 @@ class HM_Backup {
328
 
329
  if ( ! $this->database_only ) {
330
 
331
- $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $this->root ), RecursiveIteratorIterator::SELF_FIRST );
332
-
333
  $files_added = 0;
334
 
335
- $excludes = $this->exclude_string( 'regex' );
336
-
337
- foreach ( $files as $file ) {
338
 
339
- // Skip bad files
340
- if ( ! is_readable( $file ) || ! file_exists( $file ) || is_link( $file ) )
341
- continue;
342
-
343
- // Excludes
344
- if ( $excludes && preg_match( '(' . $excludes . ')', str_replace( $this->root, '', $this->conform_dir( $file ) ) ) )
345
- continue;
346
 
347
- if ( is_dir( $file ) )
348
- $zip->addEmptyDir( str_replace( trailingslashit( $this->root ), '', trailingslashit( $file ) ) );
349
-
350
- elseif ( is_file( $file ) )
351
- $zip->addFile( $file, str_replace( trailingslashit( $this->root ), '', $file ) );
352
 
353
  if ( ++$files_added % 500 === 0 )
354
  if ( ! $zip->close() || ! $zip->open( $this->archive_filepath(), ZIPARCHIVE::CREATE ) )
@@ -360,10 +453,18 @@ class HM_Backup {
360
 
361
  // Add the database
362
  if ( ! $this->files_only )
363
- $zip->addFile( $this->database_dump_filepath(), $this->database_dump_filename );
 
 
 
 
 
 
364
 
365
  $zip->close();
366
 
 
 
367
  }
368
 
369
  /**
@@ -377,27 +478,200 @@ class HM_Backup {
377
  */
378
  public function pcl_zip() {
379
 
 
 
380
  global $_hmbkp_exclude_string;
381
 
382
  $_hmbkp_exclude_string = $this->exclude_string( 'regex' );
383
 
384
- if ( ! defined( 'PCLZIP_TEMPORARY_DIR' ) )
385
- define( 'PCLZIP_TEMPORARY_DIR', $this->path );
386
-
387
- require_once( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
388
 
389
  $archive = new PclZip( $this->archive_filepath() );
390
 
391
  // Zip up everything
392
  if ( ! $this->database_only )
393
- $archive->add( $this->root, PCLZIP_OPT_REMOVE_PATH, $this->root, PCLZIP_CB_PRE_ADD, 'hmbkp_pclzip_callback' );
 
394
 
395
  // Add the database
396
  if ( ! $this->files_only )
397
- $archive->add( $this->database_dump_filepath(), PCLZIP_OPT_REMOVE_PATH, $this->path );
 
398
 
399
  unset( $GLOBALS['_hmbkp_exclude_string'] );
400
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
401
  }
402
 
403
  /**
@@ -498,6 +772,10 @@ class HM_Backup {
498
  // Sanitize the excludes
499
  $excludes = array_filter( array_unique( array_map( 'trim', (array) $this->excludes ) ) );
500
 
 
 
 
 
501
  foreach( $excludes as $key => &$rule ) {
502
 
503
  $file = $absolute = $fragment = false;
@@ -515,7 +793,7 @@ class HM_Backup {
515
  $fragment = true;
516
 
517
  // Strip $this->root and conform
518
- $rule = str_replace( $this->conform_dir( $this->root ), '', untrailingslashit( $this->conform_dir( $rule ) ) );
519
 
520
  // Strip the preceeding slash
521
  if ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) )
@@ -556,7 +834,7 @@ class HM_Backup {
556
  }
557
 
558
  /**
559
- * Check whether safe mode if active or not
560
  *
561
  * @access private
562
  * @return bool
@@ -593,7 +871,7 @@ class HM_Backup {
593
  /**
594
  * Sanitize a directory path
595
  *
596
- * @access private
597
  * @param string $dir
598
  * @param bool $rel. (default: false)
599
  * @return string $dir
@@ -608,8 +886,8 @@ class HM_Backup {
608
  $dir = untrailingslashit( $dir );
609
 
610
  // Carry on until completely normalized
611
- if ( ! $recursive && self::conform_dir( $dir, true ) != $dir )
612
- return self::conform_dir( $dir );
613
 
614
  return $dir;
615
  }
@@ -663,7 +941,7 @@ class HM_Backup {
663
  private function make_sql( $sql_file, $table ) {
664
 
665
  // Add SQL statement to drop existing table
666
- $sql_file = "\n";
667
  $sql_file .= "\n";
668
  $sql_file .= "#\n";
669
  $sql_file .= "# Delete any existing table " . $this->sql_backquote( $table ) . "\n";
@@ -717,11 +995,13 @@ class HM_Backup {
717
 
718
  // Checks whether the field is an integer or not
719
  for ( $j = 0; $j < $fields_cnt; $j++ ) {
 
720
  $field_set[$j] = $this->sql_backquote( mysql_field_name( $result, $j ) );
721
  $type = mysql_field_type( $result, $j );
722
 
723
  if ( $type == 'tinyint' || $type == 'smallint' || $type == 'mediumint' || $type == 'int' || $type == 'bigint' || $type == 'timestamp')
724
  $field_num[$j] = true;
 
725
  else
726
  $field_num[$j] = false;
727
 
@@ -836,10 +1116,96 @@ class HM_Backup {
836
 
837
  }
838
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
839
  }
840
 
841
  /**
842
- * Add file callback, excludes files in the backups directory
843
  * and sets the database dump to be stored in the root
844
  * of the zip
845
  *
@@ -853,7 +1219,7 @@ function hmbkp_pclzip_callback( $event, &$file ) {
853
  global $_hmbkp_exclude_string;
854
 
855
  // Don't try to add unreadable files.
856
- if ( ! is_readable( $file['filename'] ) || ! file_exists( $file['filename'] ) || is_link( $file['filename'] ) )
857
  return false;
858
 
859
  // Match everything else past the exclude list
1
  <?php
2
 
3
  /**
4
+ * Generic file and database backup class
5
  *
6
+ * @version 1.3
7
  */
8
  class HM_Backup {
9
 
87
  */
88
  private $db;
89
 
90
+ /**
91
+ * Store the current backup instance
92
+ *
93
+ * @var object
94
+ * @static
95
+ * @access public
96
+ */
97
+ private static $instance;
98
+
99
+ /**
100
+ * An array of all the files in root
101
+ * excluding excludes
102
+ *
103
+ * @var array
104
+ * @access private
105
+ */
106
+ private $files;
107
+
108
+ /**
109
+ * Contains an array of errors
110
+ *
111
+ * @var mixed
112
+ * @access private
113
+ */
114
+ private $errors;
115
+
116
+ /**
117
+ * Contains an array of warnings
118
+ *
119
+ * @var mixed
120
+ * @access private
121
+ */
122
+ private $warnings;
123
+
124
+ /**
125
+ * The archive method used
126
+ *
127
+ * @var string
128
+ * @access private
129
+ */
130
+ private $archive_method;
131
+
132
+ /**
133
+ * The mysqldump method used
134
+ *
135
+ * @var string
136
+ * @access private
137
+ */
138
+ private $mysqldump_method;
139
 
140
  /**
141
  * Sets up the default properties
149
  @ini_set( 'memory_limit', apply_filters( 'admin_memory_limit', WP_MAX_MEMORY_LIMIT ) );
150
  @set_time_limit( 0 );
151
 
152
+ $this->errors = array();
153
+
154
+ set_error_handler( array( &$this, 'error_handler' ) );
155
+
156
  // Defaults
157
+ $this->root = $this->conform_dir( ABSPATH );
158
 
159
  $this->path = $this->conform_dir( WP_CONTENT_DIR . '/backups' );
160
 
170
 
171
  }
172
 
173
+ /**
174
+ * Return the current instance
175
+ *
176
+ * @access public
177
+ * @static
178
+ * @return object
179
+ */
180
  public static function get_instance() {
181
 
182
  if ( empty( self::$instance ) )
187
  }
188
 
189
  /**
190
+ * The full filepath to the archive file.
191
  *
192
  * @access public
193
  * @return string
194
  */
195
  public function archive_filepath() {
196
+ return trailingslashit( $this->path() ) . $this->archive_filename();
197
+ }
198
+
199
+ /**
200
+ * The full filepath to the archive file.
201
+ *
202
+ * @access public
203
+ * @return string
204
+ */
205
+ public function archive_filename() {
206
+ return sanitize_file_name( $this->archive_filename );
207
  }
208
 
209
  /**
210
+ * The full filepath to the database dump file.
211
  *
212
  * @access public
213
  * @return string
214
  */
215
  public function database_dump_filepath() {
216
+ return trailingslashit( $this->path() ) . $this->database_dump_filename();
217
+ }
218
+
219
+ public function database_dump_filename() {
220
+ return sanitize_file_name( $this->database_dump_filename );
221
+ }
222
+
223
+ public function root() {
224
+ return $this->conform_dir( $this->root );
225
+ }
226
+
227
+ public function path() {
228
+ return $this->conform_dir( $this->path );
229
+ }
230
+
231
+ public function archive_method() {
232
+ return $this->archive_method;
233
+ }
234
+
235
+ public function mysqldump_method() {
236
+ return $this->mysqldump_method;
237
  }
238
 
239
  /**
240
+ * Kick off a backup
241
  *
242
  * @access public
243
  * @return bool
253
  // Zip everything up
254
  $this->archive();
255
 
256
+ do_action( 'hmbkp_backup_complete', $this );
257
 
258
  }
259
 
270
 
271
  do_action( 'hmbkp_mysqldump_started' );
272
 
273
+ $this->mysqldump_method = 'mysqldump';
274
+
275
  // Use mysqldump if we can
276
  if ( $this->mysqldump_command_path ) {
277
 
323
  */
324
  public function mysqldump_fallback() {
325
 
326
+ $this->mysqldump_method = 'mysqldump_fallback';
327
+
328
  $this->db = mysql_pconnect( DB_HOST, DB_USER, DB_PASSWORD );
329
 
330
  mysql_select_db( DB_NAME, $this->db );
331
  mysql_set_charset( DB_CHARSET, $this->db );
332
 
333
  // Begin new backup of MySql
334
+ $tables = mysql_query( 'SHOW TABLES' );
335
 
336
  $sql_file = "# WordPress : " . get_bloginfo( 'url' ) . " MySQL database backup\n";
337
  $sql_file .= "#\n";
356
  }
357
 
358
  /**
359
+ * Zip up all the files.
360
  *
361
  * Attempts to use the shell zip command, if
362
+ * thats not available then it fallsback to
363
+ * PHP ZipArchive and finally PclZip.
364
  *
365
  * @access public
366
  * @return null
374
  $this->zip();
375
 
376
  // If not or if the shell zip failed then use ZipArchive
377
+ if ( ( empty( $this->archive_verified ) || $this->errors() ) && class_exists( 'ZipArchive' ) && empty( $this->skip_zip_archive ) )
378
  $this->zip_archive();
379
 
380
  // If ZipArchive is unavailable or one of the above failed
381
+ if ( ( empty( $this->archive_verified ) || $this->errors() ) )
382
  $this->pcl_zip();
383
 
384
  // Delete the database dump file
389
 
390
  }
391
 
392
+ /**
393
+ * Zip using the native zip command
394
+ *
395
+ * @access public
396
+ * @return null
397
+ */
398
  public function zip() {
399
 
400
+ $this->archive_method = 'zip';
401
+
402
  // Zip up $this->root with excludes
403
  if ( ! $this->database_only && $this->exclude_string( 'zip' ) )
404
+ $this->error( 'zip', shell_exec( 'cd ' . escapeshellarg( $this->root() ) . ' && ' . escapeshellarg( $this->zip_command_path ) . ' -rq ' . escapeshellarg( $this->archive_filepath() ) . ' ./' . ' -x ' . $this->exclude_string( 'zip' ) . ' 2>&1' ) );
405
 
406
+ // Zip up $this->root without excludes
407
  elseif ( ! $this->database_only )
408
+ $this->error( 'zip', shell_exec( 'cd ' . escapeshellarg( $this->root() ) . ' && ' . escapeshellarg( $this->zip_command_path ) . ' -rq ' . escapeshellarg( $this->archive_filepath() ) . ' ./' . ' 2>&1' ) );
409
 
410
  // Add the database dump to the archive
411
  if ( ! $this->files_only )
412
+ $this->error( 'zip', shell_exec( 'cd ' . escapeshellarg( $this->path() ) . ' && ' . escapeshellarg( $this->zip_command_path ) . ' -uq ' . escapeshellarg( $this->archive_filepath() ) . ' ' . escapeshellarg( $this->database_dump_filename() ) . ' 2>&1' ) );
413
+
414
+ $this->check_archive();
415
 
416
  }
417
 
424
  */
425
  public function zip_archive() {
426
 
427
+ $this->archive_method = 'ziparchive';
428
+
429
  $zip = new ZipArchive();
430
 
431
  if ( ! class_exists( 'ZipArchive' ) || ! $zip->open( $this->archive_filepath(), ZIPARCHIVE::CREATE ) )
433
 
434
  if ( ! $this->database_only ) {
435
 
 
 
436
  $files_added = 0;
437
 
438
+ foreach ( $this->files() as $file ) {
 
 
439
 
440
+ if ( is_dir( trailingslashit( $this->root() ) . $file ) )
441
+ $zip->addEmptyDir( trailingslashit( $file ) );
 
 
 
 
 
442
 
443
+ elseif ( is_file( trailingslashit( $this->root() ) . $file ) )
444
+ $zip->addFile( trailingslashit( $this->root() ) . $file, $file );
 
 
 
445
 
446
  if ( ++$files_added % 500 === 0 )
447
  if ( ! $zip->close() || ! $zip->open( $this->archive_filepath(), ZIPARCHIVE::CREATE ) )
453
 
454
  // Add the database
455
  if ( ! $this->files_only )
456
+ $zip->addFile( $this->database_dump_filepath(), $this->database_dump_filename() );
457
+
458
+ if ( $zip->status )
459
+ $this->error( 'ziparchive', $zip->status );
460
+
461
+ if ( $zip->statusSys )
462
+ $this->error( 'ziparchive', $zip->statusSys );
463
 
464
  $zip->close();
465
 
466
+ $this->check_archive();
467
+
468
  }
469
 
470
  /**
478
  */
479
  public function pcl_zip() {
480
 
481
+ $this->archive_method = 'pclzip';
482
+
483
  global $_hmbkp_exclude_string;
484
 
485
  $_hmbkp_exclude_string = $this->exclude_string( 'regex' );
486
 
487
+ $this->load_pclzip();
 
 
 
488
 
489
  $archive = new PclZip( $this->archive_filepath() );
490
 
491
  // Zip up everything
492
  if ( ! $this->database_only )
493
+ if ( ! $archive->add( $this->root(), PCLZIP_OPT_REMOVE_PATH, $this->root(), PCLZIP_CB_PRE_ADD, 'hmbkp_pclzip_callback' ) )
494
+ $this->error( 'pclzip', $archive->errorInfo( true ) );
495
 
496
  // Add the database
497
  if ( ! $this->files_only )
498
+ if ( ! $archive->add( $this->database_dump_filepath(), PCLZIP_OPT_REMOVE_PATH, $this->path() ) )
499
+ $this->error( 'pclzip', $archive->errorInfo( true ) );
500
 
501
  unset( $GLOBALS['_hmbkp_exclude_string'] );
502
 
503
+ $this->check_archive();
504
+
505
+ }
506
+
507
+ /**
508
+ * Verify that the archive is valid and contains all the files it should contain.
509
+ *
510
+ * @access public
511
+ * @return bool
512
+ */
513
+ public function check_archive() {
514
+
515
+ // If we've already passed then no need to check again
516
+ if ( ! empty( $this->archive_verified ) )
517
+ return true;
518
+
519
+ if ( ! file_exists( $this->archive_filepath() ) )
520
+ $this->error( $this->archive_method(), __( 'The backup file was not created', 'hmbkp' ) );
521
+
522
+ // Verify using the zip command if possible
523
+ if ( ! $this->errors() && $this->zip_command_path ) {
524
+
525
+ $verify = shell_exec( escapeshellarg( $this->zip_command_path ) . ' -T ' . escapeshellarg( $this->archive_filepath() ) . ' 2> /dev/null' );
526
+
527
+ if ( strpos( $verify, 'OK' ) === false )
528
+ $this->error( $this->archive_method(), $verify );
529
+
530
+ }
531
+
532
+ if ( ! $this->errors() ) {
533
+
534
+ // If it's a file backup, get an array of all the files that should have been backed up
535
+ if ( ! $this->database_only )
536
+ $files = $this->files();
537
+
538
+ // Check that the database was backed up
539
+ if ( ! $this->files_only )
540
+ $files[] = $this->database_dump_filename();
541
+
542
+ $this->load_pclzip();
543
+
544
+ $archive = new PclZip( $this->archive_filepath() );
545
+ $filesystem = $archive->extract( PCLZIP_OPT_EXTRACT_AS_STRING );
546
+
547
+ foreach( $filesystem as $file )
548
+ $archive_files[] = untrailingslashit( $file['filename'] );
549
+
550
+ // Check that the array of files that should have been backed up matches the array of files in the zip
551
+ if ( $files !== $archive_files )
552
+ $this->error( $this->archive_method(), __( 'Backup file doesn\'t contain the the following files: ', 'hmbkp' ) . implode( ', ', array_diff( $files, $archive_files ) ) );
553
+
554
+ }
555
+
556
+ // If there are errors delete the backup file.
557
+ if ( $this->errors() && file_exists( $this->archive_filepath() ) )
558
+ unlink( $this->archive_filepath() );
559
+
560
+ if ( $this->errors() )
561
+ return false;
562
+
563
+ return $this->archive_verified = true;
564
+
565
+ }
566
+
567
+ /**
568
+ * Generate the array of files to be backed up by looping through
569
+ * root, ignored unreadable files and excludes
570
+ *
571
+ * @access public
572
+ * @return array
573
+ */
574
+ public function files() {
575
+
576
+ if ( ! empty( $this->files ) )
577
+ return $this->files;
578
+
579
+ $this->files = array();
580
+
581
+ if ( defined( 'RecursiveDirectoryIterator::FOLLOW_SYMLINKS' ) ) {
582
+
583
+ $filesystem = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $this->root(), RecursiveDirectoryIterator::FOLLOW_SYMLINKS ), RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD );
584
+
585
+ $excludes = $this->exclude_string( 'regex' );
586
+
587
+ foreach ( $filesystem as $file ) {
588
+
589
+ if ( ! $file->isReadable() ) {
590
+ $this->unreadable_files[] = $file->getPathName();
591
+ continue;
592
+ }
593
+
594
+ $pathname = str_ireplace( trailingslashit( $this->root() ), '', $this->conform_dir( $file->getPathname() ) );
595
+
596
+ // Excludes
597
+ if ( $excludes && preg_match( '(' . $excludes . ')', $pathname ) )
598
+ continue;
599
+
600
+ // Don't include database dump as it's added separately
601
+ if ( basename( $pathname ) == $this->database_dump_filename() )
602
+ continue;
603
+
604
+ $this->files[] = $pathname;
605
+
606
+ }
607
+
608
+ } else {
609
+
610
+ $this->files = $this->files_fallback( $this->root() );
611
+
612
+ }
613
+
614
+ if ( ! empty( $this->unreadable_files ) )
615
+ $this->warning( $this->archive_method(), __( 'The following files are unreadable and couldn\'t be backed up: ', 'hmbkp' ) . implode( ', ', $this->unreadable_files ) );
616
+
617
+ return $this->files;
618
+
619
+ }
620
+
621
+ /**
622
+ * Fallback function for generating a filesystem
623
+ * array
624
+ *
625
+ * Used if RecursiveDirectoryIterator::FOLLOW_SYMLINKS isn't available
626
+ *
627
+ * @access private
628
+ * @param stromg $dir
629
+ * @param array $files. (default: array())
630
+ * @return array
631
+ */
632
+ private function files_fallback( $dir, $files = array() ) {
633
+
634
+ $handle = opendir( $dir );
635
+
636
+ $excludes = $this->exclude_string( 'regex' );
637
+
638
+ while ( $file = readdir( $handle ) ) :
639
+
640
+ // Ignore current dir and containing dir and any unreadable files or directories
641
+ if ( $file == '.' || $file == '..' )
642
+ continue;
643
+
644
+ $filepath = $this->conform_dir( trailingslashit( $dir ) . $file );
645
+ $file = str_ireplace( trailingslashit( $this->root() ), '', $filepath );
646
+
647
+ if ( ! is_readable( $filepath ) ) {
648
+ $this->unreadable_files[] = $filepath;
649
+ continue;
650
+ }
651
+
652
+ // Skip the backups dir and any excluded paths
653
+ if ( ( $excludes && preg_match( '(' . $excludes . ')', $file ) ) )
654
+ continue;
655
+
656
+ $files[] = $file;
657
+
658
+ if ( is_dir( $filepath ) )
659
+ $files = $this->files_fallback( $filepath, $files );
660
+
661
+ endwhile;
662
+
663
+ return $files;
664
+
665
+ }
666
+
667
+ private function load_pclzip() {
668
+
669
+ // Load PclZip
670
+ if ( ! defined( 'PCLZIP_TEMPORARY_DIR' ) )
671
+ define( 'PCLZIP_TEMPORARY_DIR', $this->path() );
672
+
673
+ require_once( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
674
+
675
  }
676
 
677
  /**
772
  // Sanitize the excludes
773
  $excludes = array_filter( array_unique( array_map( 'trim', (array) $this->excludes ) ) );
774
 
775
+ // If path is inside root, exclude it
776
+ if ( strpos( $this->path(), $this->root() ) !== false )
777
+ $excludes[] = trailingslashit( $this->path() );
778
+
779
  foreach( $excludes as $key => &$rule ) {
780
 
781
  $file = $absolute = $fragment = false;
793
  $fragment = true;
794
 
795
  // Strip $this->root and conform
796
+ $rule = str_ireplace( $this->root(), '', untrailingslashit( $this->conform_dir( $rule ) ) );
797
 
798
  // Strip the preceeding slash
799
  if ( in_array( substr( $rule, 0, 1 ), array( '\\', '/' ) ) )
834
  }
835
 
836
  /**
837
+ * Check whether safe mode is active or not
838
  *
839
  * @access private
840
  * @return bool
871
  /**
872
  * Sanitize a directory path
873
  *
874
+ * @access public
875
  * @param string $dir
876
  * @param bool $rel. (default: false)
877
  * @return string $dir
886
  $dir = untrailingslashit( $dir );
887
 
888
  // Carry on until completely normalized
889
+ if ( ! $recursive && $this->conform_dir( $dir, true ) != $dir )
890
+ return $this->conform_dir( $dir );
891
 
892
  return $dir;
893
  }
941
  private function make_sql( $sql_file, $table ) {
942
 
943
  // Add SQL statement to drop existing table
944
+ $sql_file .= "\n";
945
  $sql_file .= "\n";
946
  $sql_file .= "#\n";
947
  $sql_file .= "# Delete any existing table " . $this->sql_backquote( $table ) . "\n";
995
 
996
  // Checks whether the field is an integer or not
997
  for ( $j = 0; $j < $fields_cnt; $j++ ) {
998
+
999
  $field_set[$j] = $this->sql_backquote( mysql_field_name( $result, $j ) );
1000
  $type = mysql_field_type( $result, $j );
1001
 
1002
  if ( $type == 'tinyint' || $type == 'smallint' || $type == 'mediumint' || $type == 'int' || $type == 'bigint' || $type == 'timestamp')
1003
  $field_num[$j] = true;
1004
+
1005
  else
1006
  $field_num[$j] = false;
1007
 
1116
 
1117
  }
1118
 
1119
+ /**
1120
+ * Get the errors
1121
+ *
1122
+ * @access public
1123
+ * @return null
1124
+ */
1125
+ public function errors() {
1126
+
1127
+ return $this->errors;
1128
+
1129
+ }
1130
+
1131
+
1132
+ /**
1133
+ * Add an error to the errors stack
1134
+ *
1135
+ * @access private
1136
+ * @param string $context
1137
+ * @param mixed $error
1138
+ * @return null
1139
+ */
1140
+ private function error( $context, $error ) {
1141
+
1142
+ if ( empty( $context ) || empty( $error ) )
1143
+ return;
1144
+
1145
+ if ( $context == 'zip' && strpos( $error, 'zip warning' ) !== false )
1146
+ return $this->warning( $context, $error );
1147
+
1148
+
1149
+ $this->errors[$context][$_key = md5( implode( ':' , (array) $error ) )] = $error;
1150
+
1151
+ }
1152
+
1153
+ /**
1154
+ * Get the warnings
1155
+ *
1156
+ * @access public
1157
+ * @return null
1158
+ */
1159
+ public function warnings() {
1160
+
1161
+ return $this->warnings;
1162
+
1163
+ }
1164
+
1165
+
1166
+ /**
1167
+ * Add an warning to the warnings stack
1168
+ *
1169
+ * @access private
1170
+ * @param string $context
1171
+ * @param mixed $warning
1172
+ * @return null
1173
+ */
1174
+ private function warning( $context, $warning ) {
1175
+
1176
+ if ( empty( $context ) || empty( $warning ) )
1177
+ return;
1178
+
1179
+ $this->warnings[$context][$_key = md5( implode( ':' , (array) $warning ) )] = $warning;
1180
+
1181
+ }
1182
+
1183
+
1184
+ /**
1185
+ * Custom error handler for catching errors
1186
+ *
1187
+ * @access private
1188
+ * @param string $type
1189
+ * @param string $message
1190
+ * @param string $file
1191
+ * @param string $line
1192
+ * @return null
1193
+ */
1194
+ public function error_handler( $type ) {
1195
+
1196
+ if ( in_array( $type, array( E_STRICT, E_DEPRECATED ) ) || error_reporting() === 0 )
1197
+ return false;
1198
+
1199
+ $this->error( 'php', array_splice( func_get_args(), 0, 4 ) );
1200
+
1201
+ return false;
1202
+
1203
+ }
1204
+
1205
  }
1206
 
1207
  /**
1208
+ * Add file callback for PclZip, excludes files
1209
  * and sets the database dump to be stored in the root
1210
  * of the zip
1211
  *
1219
  global $_hmbkp_exclude_string;
1220
 
1221
  // Don't try to add unreadable files.
1222
+ if ( ! is_readable( $file['filename'] ) || ! file_exists( $file['filename'] ) )
1223
  return false;
1224
 
1225
  // Match everything else past the exclude list
plugin.php CHANGED
@@ -5,7 +5,7 @@ Plugin Name: BackUpWordPress
5
  Plugin URI: http://hmn.md/backupwordpress/
6
  Description: Simple automated backups of your WordPress powered website. Once activated you'll find me under <strong>Tools &rarr; Backups</strong>.
7
  Author: Human Made Limited
8
- Version: 1.5.1
9
  Author URI: http://hmn.md/
10
  */
11
 
@@ -58,7 +58,7 @@ if ( version_compare( get_bloginfo('version'), HMBKP_REQUIRED_WP_VERSION, '<' )
58
 
59
  /**
60
  * Plugin setup
61
- *
62
  * @return null
63
  */
64
  function hmbkp_actions() {
@@ -89,28 +89,27 @@ add_action( 'admin_init', 'hmbkp_actions' );
89
 
90
  /**
91
  * Setup the HM_Backup class
92
- *
93
  * @return null
94
  */
95
  function hmbkp_setup_hm_backup() {
96
 
97
  $hm_backup = HM_Backup::get_instance();
98
-
99
  $hm_backup->path = hmbkp_path();
100
- $hm_backup->root = ABSPATH;
101
  $hm_backup->files_only = hmbkp_get_files_only();
102
  $hm_backup->database_only = hmbkp_get_database_only();
103
-
104
  if ( defined( 'HMBKP_MYSQLDUMP_PATH' ) )
105
  $hm_backup->mysql_command_path = HMBKP_MYSQLDUMP_PATH;
106
-
107
  if ( defined( 'HMBKP_ZIP_PATH' ) )
108
  $hm_backup->zip_command_path = HMBKP_ZIP_PATH;
109
-
110
  $hm_backup->excludes = hmbkp_valid_custom_excludes();
111
-
112
  // If the backup path is inside ABSPATH then exclude it by default
113
- if ( strpos( hmbkp_path(), ABSPATH ) === 0 )
114
  $hm_backup->excludes[] = trailingslashit( str_replace( untrailingslashit( ABSPATH ), '', hmbkp_path() ) );
115
 
116
  }
@@ -128,6 +127,10 @@ require_once( HMBKP_PLUGIN_PATH . '/functions/core.functions.php' );
128
  require_once( HMBKP_PLUGIN_PATH . '/functions/interface.functions.php' );
129
  require_once( HMBKP_PLUGIN_PATH . '/functions/backup.functions.php' );
130
 
 
 
 
 
131
  // Plugin activation and deactivation
132
  add_action( 'activate_' . HMBKP_PLUGIN_SLUG . '/plugin.php', 'hmbkp_activate' );
133
  add_action( 'deactivate_' . HMBKP_PLUGIN_SLUG . '/plugin.php', 'hmbkp_deactivate' );
5
  Plugin URI: http://hmn.md/backupwordpress/
6
  Description: Simple automated backups of your WordPress powered website. Once activated you'll find me under <strong>Tools &rarr; Backups</strong>.
7
  Author: Human Made Limited
8
+ Version: 1.6
9
  Author URI: http://hmn.md/
10
  */
11
 
58
 
59
  /**
60
  * Plugin setup
61
+ *
62
  * @return null
63
  */
64
  function hmbkp_actions() {
89
 
90
  /**
91
  * Setup the HM_Backup class
92
+ *
93
  * @return null
94
  */
95
  function hmbkp_setup_hm_backup() {
96
 
97
  $hm_backup = HM_Backup::get_instance();
98
+
99
  $hm_backup->path = hmbkp_path();
 
100
  $hm_backup->files_only = hmbkp_get_files_only();
101
  $hm_backup->database_only = hmbkp_get_database_only();
102
+
103
  if ( defined( 'HMBKP_MYSQLDUMP_PATH' ) )
104
  $hm_backup->mysql_command_path = HMBKP_MYSQLDUMP_PATH;
105
+
106
  if ( defined( 'HMBKP_ZIP_PATH' ) )
107
  $hm_backup->zip_command_path = HMBKP_ZIP_PATH;
108
+
109
  $hm_backup->excludes = hmbkp_valid_custom_excludes();
110
+
111
  // If the backup path is inside ABSPATH then exclude it by default
112
+ if ( strpos( hmbkp_path(), hmbkp_conform_dir( ABSPATH ) ) === 0 )
113
  $hm_backup->excludes[] = trailingslashit( str_replace( untrailingslashit( ABSPATH ), '', hmbkp_path() ) );
114
 
115
  }
127
  require_once( HMBKP_PLUGIN_PATH . '/functions/interface.functions.php' );
128
  require_once( HMBKP_PLUGIN_PATH . '/functions/backup.functions.php' );
129
 
130
+ // Load the wp cli command
131
+ if ( defined( 'WP_CLI' ) && WP_CLI )
132
+ include( HMBKP_PLUGIN_PATH . '/functions/wp-cli.php' );
133
+
134
  // Plugin activation and deactivation
135
  add_action( 'activate_' . HMBKP_PLUGIN_SLUG . '/plugin.php', 'hmbkp_activate' );
136
  add_action( 'deactivate_' . HMBKP_PLUGIN_SLUG . '/plugin.php', 'hmbkp_deactivate' );
readme.txt CHANGED
@@ -1,9 +1,9 @@
1
  === BackUpWordPress ===
2
  Contributors: humanmade, joehoyle, mattheu, tcrsavage, willmot
3
- Tags: back up, backup, backups, database, zip, db, files, archive, humanmade
4
  Requires at least: 3.1
5
  Tested up to: 3.3
6
- Stable tag: 1.5.1
7
 
8
  Simple automated back ups of your WordPress powered website.
9
 
@@ -41,7 +41,7 @@ The plugin will try to use the `mysqldump` and `zip` commands via shell if they
41
 
42
  **Where does BackUpWordPress store the backup files?**
43
 
44
- Backups are stored on your server in `wp-content/backups`, you can change the directory.
45
 
46
  **Important:** By default BackUpWordPress backs up everything in your site root as well as your database, this includes any non WordPress folders that happen to be in your site root. This does means that your backup directory can get quite large.
47
 
@@ -53,6 +53,10 @@ You need to download the latest backup file either by clicking download on the b
53
 
54
  No.
55
 
 
 
 
 
56
  **How many backups are stored by default?**
57
 
58
  BackUpWordPress stores the last 10 backups by default.
@@ -90,6 +94,23 @@ You can also tweet <a href="http://twitter.com/humanmadeltd">@humanmadeltd</a> o
90
 
91
  == Changelog ==
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  #### 1.5.1
94
 
95
  * Better detection of `zip` command.
1
  === BackUpWordPress ===
2
  Contributors: humanmade, joehoyle, mattheu, tcrsavage, willmot
3
+ Tags: back up, backup, backups, database, zip, db, files, archive, wp-cli, humanmade
4
  Requires at least: 3.1
5
  Tested up to: 3.3
6
+ Stable tag: 1.6
7
 
8
  Simple automated back ups of your WordPress powered website.
9
 
41
 
42
  **Where does BackUpWordPress store the backup files?**
43
 
44
+ Backups are stored on your server in `/wp-content/backups`, you can change the directory.
45
 
46
  **Important:** By default BackUpWordPress backs up everything in your site root as well as your database, this includes any non WordPress folders that happen to be in your site root. This does means that your backup directory can get quite large.
47
 
53
 
54
  No.
55
 
56
+ **I'm not receiving my backups by email**
57
+
58
+ Most servers have a filesize limit on email attachments, it's generally about 10mb. If your backup file is over that limit it won't be sent attached to the email, instead you should receive an email with a link to download the backup, if you aren't even receiving that then you likely have a mail issue on your server that you'll need to contact your host about.
59
+
60
  **How many backups are stored by default?**
61
 
62
  BackUpWordPress stores the last 10 backups by default.
94
 
95
  == Changelog ==
96
 
97
+ #### 1.6
98
+
99
+ * Fixes issue with backups dir being included in backups on some Windows Servers.
100
+ * Consistent handling of symlinks across all archive methods (they are followed).
101
+ * Use .htaccess rewrite cond authentication to allow for secure http downloads of backup files.
102
+ * Track errors and warnings that happen during backup and expose them through admin.
103
+ * Fire manual backups using ajax instead of wp-cron, `HMBKP_DISABLE_MANUAL_BACKUP_CRON` is no longer needed and has been removed.
104
+ * Ability to cancel a running backup.
105
+ * Zip files are now integrity checked after every backup.
106
+ * More robust handling of failed / corrupt zips, backup process now fallsback through the various zip methods until one works.
107
+ * Use `mysql_query` instead of the depreciated `mysql_list_tables`.
108
+
109
+ #### 1.5.2
110
+
111
+ * Better handling of unreadable files in ZipArchive and the backup size calculation.
112
+ * Support for wp-cli, usage: `wp backup [--files_only] [--database_only] [--path<dir>] [--root<dir>] [--zip_command_path=<path>] [--mysqldump_command_path=<path>]`
113
+
114
  #### 1.5.1
115
 
116
  * Better detection of `zip` command.