UpdraftPlus WordPress Backup Plugin - Version 1.1.17

Version Description

  • 01/08/2013 =
  • Make the creation of the database dump also resumable, for people with really slow servers
Download this release

Release Info

Developer DavidAnderson
Plugin Icon 128x128 UpdraftPlus WordPress Backup Plugin
Version 1.1.17
Comparing to
See all releases

Code changes from version 1.1.16 to 1.1.17

Files changed (2) hide show
  1. readme.txt +6 -3
  2. updraftplus.php +121 -59
readme.txt CHANGED
@@ -3,12 +3,12 @@ Contributors: David Anderson
3
  Tags: backup, restore, database, cloud, amazon, s3, Amazon S3, google drive, google, gdrive, ftp, cloud, updraft, back up
4
  Requires at least: 3.2
5
  Tested up to: 3.5
6
- Stable tag: 1.1.15
7
  Donate link: http://david.dw-perspective.org.uk/donate
8
  License: GPLv3 or later
9
 
10
  == Upgrade Notice ==
11
- Provide a 'Test S3 Settings' button for Amazon S3 users
12
 
13
  == Description ==
14
 
@@ -112,7 +112,10 @@ Thanks for asking - yes, I have. Check out my profile page - http://profiles.wor
112
 
113
  == Changelog ==
114
 
115
- = 1.1.15 - 01/07/2013 =
 
 
 
116
  * Requested feature: more frequent scheduling options requested
117
  * Fixed bug which mangled default suggestion for backup working directory on Windows
118
  * Provide a 'Test S3 Settings' button for Amazon S3 users
3
  Tags: backup, restore, database, cloud, amazon, s3, Amazon S3, google drive, google, gdrive, ftp, cloud, updraft, back up
4
  Requires at least: 3.2
5
  Tested up to: 3.5
6
+ Stable tag: 1.1.16
7
  Donate link: http://david.dw-perspective.org.uk/donate
8
  License: GPLv3 or later
9
 
10
  == Upgrade Notice ==
11
+ Make the creation of the database backup resumable
12
 
13
  == Description ==
14
 
112
 
113
  == Changelog ==
114
 
115
+ = 1.1.17 - 01/08/2013 =
116
+ * Make the creation of the database dump also resumable, for people with really slow servers
117
+
118
+ = 1.1.16 - 01/07/2013 =
119
  * Requested feature: more frequent scheduling options requested
120
  * Fixed bug which mangled default suggestion for backup working directory on Windows
121
  * Provide a 'Test S3 Settings' button for Amazon S3 users
updraftplus.php CHANGED
@@ -4,7 +4,7 @@ Plugin Name: UpdraftPlus - Backup/Restore
4
  Plugin URI: http://wordpress.org/extend/plugins/updraftplus
5
  Description: Uploads, themes, plugins, and your DB can be automatically backed up to Amazon S3, Google Drive, FTP, or emailed, on separate schedules.
6
  Author: David Anderson.
7
- Version: 1.1.16
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
10
  Author URI: http://wordshell.net
@@ -56,7 +56,7 @@ define('UPDRAFT_DEFAULT_OTHERS_EXCLUDE','upgrade,cache,updraft,index.php');
56
 
57
  class UpdraftPlus {
58
 
59
- var $version = '1.1.16';
60
 
61
  // Choices will be shown in the admin menu in the order used here
62
  var $backup_methods = array (
@@ -67,6 +67,7 @@ class UpdraftPlus {
67
  );
68
 
69
  var $dbhandle;
 
70
  var $errors = array();
71
  var $nonce;
72
  var $cronrun_type = "none";
@@ -175,6 +176,23 @@ class UpdraftPlus {
175
  $our_files=$backup_history[$btime];
176
  $undone_files = array();
177
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  // Potentially encrypt the database if it is not already
179
  if (isset($our_files['db']) && !preg_match("/\.crypt$/", $our_files['db'])) {
180
  $our_files['db'] = $this->encrypt_file($our_files['db']);
@@ -300,6 +318,7 @@ class UpdraftPlus {
300
  $this->log("In case we run out of time, scheduled a resumption at: $resume_delay seconds from now");
301
 
302
  $backup_contains = "";
 
303
 
304
  $backup_array = array();
305
 
@@ -310,23 +329,31 @@ class UpdraftPlus {
310
  $this->log("Beginning backup of directories");
311
  $backup_array = $this->backup_dirs();
312
  $backup_contains = "Files only (no database)";
 
 
313
  }
314
 
 
 
 
 
 
 
315
  $this->check_backup_race($backup_array);
316
 
317
- //backup DB and return string of file path
318
  if ($backup_database) {
319
  $this->log("Beginning backup of database");
320
  $db_backup = $this->backup_db();
321
- // add db path to rest of files
322
  if(is_array($backup_array)) $backup_array['db'] = $db_backup;
323
- $backup_contains = ($backup_files) ? "Files and database" : "Database only (no files)";
 
 
324
  }
325
 
326
  $this->check_backup_race($backup_array);
327
- set_transient("updraftplus_backupcontains", $backup_contains, 3600*3);
328
 
329
- //save this to our history so we can track backups for the retain feature
330
  $this->log("Saving backup history");
331
  // This is done before cloud despatch, because we want a record of what *should* be in the backup. Whether it actually makes it there or not is not yet known.
332
  $this->save_backup_history($backup_array);
@@ -429,7 +456,7 @@ class UpdraftPlus {
429
 
430
  $append_log = (get_option('updraft_debug_mode') && $this->logfile_name != "") ? "\r\nLog contents:\r\n".file_get_contents($this->logfile_name) : "" ;
431
 
432
- wp_mail($sendmail_to,'Backed up: '.get_bloginfo('name').' (UpdraftPlus '.$this->version.') '.date('Y-m-d H:i',time()),'Site: '.site_url()."\r\nUpdraftPlus WordPress backup is complete.\r\nBackup contains: ".get_transient("updraftplus_backupcontains")."\r\n\r\n".$this->wordshell_random_advert(0)."\r\n".$append_log);
433
 
434
  }
435
 
@@ -737,48 +764,30 @@ class UpdraftPlus {
737
  }
738
  return $backup_history;
739
  }
740
-
741
-
742
- /*START OF WB-DB-BACKUP BLOCK*/
743
 
744
- function backup_db() {
745
-
746
- $total_tables = 0;
747
-
748
- global $table_prefix, $wpdb;
749
- if(!$this->backup_time) $this->backup_time_nonce();
750
-
751
- $all_tables = $wpdb->get_results("SHOW TABLES", ARRAY_N);
752
- $all_tables = array_map(create_function('$a', 'return $a[0];'), $all_tables);
753
-
754
- $updraft_dir = $this->backups_dir_location();
755
- //get the blog name and rip out all non-alphanumeric chars other than _
756
- $blog_name = str_replace(' ','_',get_bloginfo());
757
- $blog_name = preg_replace('/[^A-Za-z0-9_]/','', $blog_name);
758
- if (!$blog_name) $blog_name = 'non_alpha_name';
759
-
760
- $backup_file_base = $updraft_dir.'/backup_'.date('Y-m-d-Hi',$this->backup_time).'_'.$blog_name.'_'.$this->nonce;
761
- if (is_writable($updraft_dir)) {
762
- if (function_exists('gzopen')) {
763
- $this->dbhandle = @gzopen($backup_file_base.'-db.gz','w');
764
- } else {
765
- $this->dbhandle = @fopen($backup_file_base.'-db.gz', 'w');
766
- }
767
- if(!$this->dbhandle) {
768
- //$this->error(__('Could not open the backup file for writing!','wp-db-backup'));
769
- }
770
  } else {
771
- //$this->error(__('The backup directory is not writable!','wp-db-backup'));
 
772
  }
773
-
 
 
 
 
 
 
774
  //Begin new backup of MySql
775
- $this->stow("# " . __('WordPress MySQL database backup','wp-db-backup') . "\n");
776
  $this->stow("#\n");
777
  $this->stow("# " . sprintf(__('Generated: %s','wp-db-backup'),date("l j. F Y H:i T")) . "\n");
778
  $this->stow("# " . sprintf(__('Hostname: %s','wp-db-backup'),DB_HOST) . "\n");
779
  $this->stow("# " . sprintf(__('Database: %s','wp-db-backup'),$this->backquote(DB_NAME)) . "\n");
780
  $this->stow("# --------------------------------------------------------\n");
781
-
782
 
783
  if (defined("DB_CHARSET")) {
784
  $this->stow("/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n");
@@ -787,31 +796,87 @@ class UpdraftPlus {
787
  $this->stow("/*!40101 SET NAMES " . DB_CHARSET . " */;\n");
788
  }
789
  $this->stow("/*!40101 SET foreign_key_checks = 0 */;\n");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
790
 
791
  foreach ($all_tables as $table) {
792
  $total_tables++;
793
  // Increase script execution time-limit to 15 min for every table.
794
  if ( !ini_get('safe_mode') || strtolower(ini_get('safe_mode')) == "off") @set_time_limit(15*60);
795
- # === is needed, otherwise 'false' matches (i.e. prefix does not match)
796
- if ( strpos($table, $table_prefix) === 0 ) {
797
- // Create the SQL statements
798
- $this->stow("# --------------------------------------------------------\n");
799
- $this->stow("# " . sprintf(__('Table: %s','wp-db-backup'),$this->backquote($table)) . "\n");
800
- $this->stow("# --------------------------------------------------------\n");
801
- $this->backup_table($table);
802
  } else {
803
- $this->stow("# --------------------------------------------------------\n");
804
- $this->stow("# " . sprintf(__('Skipping non-WP table: %s','wp-db-backup'),$this->backquote($table)) . "\n");
805
- $this->stow("# --------------------------------------------------------\n");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
806
  }
 
807
  }
808
 
 
 
 
809
  if (defined("DB_CHARSET")) {
810
  $this->stow("/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n");
811
  $this->stow("/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n");
812
  $this->stow("/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
813
  }
814
-
 
 
 
 
 
 
 
815
  $this->close($this->dbhandle);
816
 
817
  if (count($this->errors)) {
@@ -897,7 +962,6 @@ class UpdraftPlus {
897
  }
898
  }
899
 
900
-
901
  // Batch by $row_inc
902
  if ( ! defined('ROWS_PER_SEGMENT') ) {
903
  define('ROWS_PER_SEGMENT', 100);
@@ -951,9 +1015,8 @@ class UpdraftPlus {
951
 
952
  } // end backup_table()
953
 
954
-
955
  function stow($query_line) {
956
- if (function_exists('gzopen')) {
957
  if(! @gzwrite($this->dbhandle, $query_line)) {
958
  //$this->error(__('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg);
959
  }
@@ -964,9 +1027,8 @@ class UpdraftPlus {
964
  }
965
  }
966
 
967
-
968
  function close($handle) {
969
- if (function_exists('gzopen')) {
970
  gzclose($handle);
971
  } else {
972
  fclose($handle);
@@ -1542,7 +1604,7 @@ ENDHERE;
1542
  <div style="float:left; width:200px; padding-top: 100px;">
1543
  <form method="post" action="">
1544
  <input type="hidden" name="action" value="updraft_backup" />
1545
- <p><input type="submit" <?php echo $backup_disabled ?> class="button-primary" value="Backup Now!" style="padding-top:7px;padding-bottom:7px;font-size:24px !important" onclick="return(confirm('This will schedule a one-time backup. To trigger the backup you should go ahead, then wait 10 seconds, then load a page on your site.'))" /></p>
1546
  </form>
1547
  <div style="position:relative">
1548
  <div style="position:absolute;top:0;left:0">
@@ -1551,7 +1613,7 @@ ENDHERE;
1551
  $backup_history = (is_array($backup_history))?$backup_history:array();
1552
  $restore_disabled = (count($backup_history) == 0) ? 'disabled="disabled"' : "";
1553
  ?>
1554
- <input type="button" class="button-primary" <?php echo $restore_disabled ?> value="Restore" style="padding-top:7px;padding-bottom:7px;font-size:24px !important" onclick="jQuery('#backup-restore').fadeIn('slow');jQuery(this).parent().fadeOut('slow')" />
1555
  </div>
1556
  <div style="display:none;position:absolute;top:0;left:0" id="backup-restore">
1557
  <form method="post" action="">
4
  Plugin URI: http://wordpress.org/extend/plugins/updraftplus
5
  Description: Uploads, themes, plugins, and your DB can be automatically backed up to Amazon S3, Google Drive, FTP, or emailed, on separate schedules.
6
  Author: David Anderson.
7
+ Version: 1.1.17
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
10
  Author URI: http://wordshell.net
56
 
57
  class UpdraftPlus {
58
 
59
+ var $version = '1.1.17';
60
 
61
  // Choices will be shown in the admin menu in the order used here
62
  var $backup_methods = array (
67
  );
68
 
69
  var $dbhandle;
70
+ var $dbhandle_isgz;
71
  var $errors = array();
72
  var $nonce;
73
  var $cronrun_type = "none";
176
  $our_files=$backup_history[$btime];
177
  $undone_files = array();
178
 
179
+ $backup_database = get_transient("updraft_backdb_".$bnonce);
180
+
181
+ // The transient is read and written below (instead of using the existing variable) so that we can copy-and-paste this part as needed.
182
+ if ($backup_database) {
183
+ $this->log("Beginning backup of database");
184
+ $db_backup = $this->backup_db();
185
+ if(is_array($our_files)) $our_files['db'] = $db_backup;
186
+ $backup_contains = get_transient("updraft_backupcontains_".$this->nonce);
187
+ $backup_contains = (substr($backup_contains,0,10) == "Files only") ? "Files and database" : "Database only (no files)";
188
+ set_transient("updraft_backupcontains_".$this->nonce, $backup_contains, 3600*3);
189
+ }
190
+
191
+ // Save this to our history so we can track backups for the retain feature
192
+ $this->log("Saving backup history");
193
+ // This is done before cloud despatch, because we want a record of what *should* be in the backup. Whether it actually makes it there or not is not yet known.
194
+ $this->save_backup_history($our_files);
195
+
196
  // Potentially encrypt the database if it is not already
197
  if (isset($our_files['db']) && !preg_match("/\.crypt$/", $our_files['db'])) {
198
  $our_files['db'] = $this->encrypt_file($our_files['db']);
318
  $this->log("In case we run out of time, scheduled a resumption at: $resume_delay seconds from now");
319
 
320
  $backup_contains = "";
321
+ set_transient("updraft_backupcontains_".$this->nonce, "");
322
 
323
  $backup_array = array();
324
 
329
  $this->log("Beginning backup of directories");
330
  $backup_array = $this->backup_dirs();
331
  $backup_contains = "Files only (no database)";
332
+ // This can get over-written later
333
+ set_transient("updraft_backupcontains_".$this->nonce, $backup_contains, 3600*3);
334
  }
335
 
336
+ // Save what *should* be done, to make it resumable from this point on
337
+ set_transient("updraft_backdb_".$this->nonce, $backup_database, 3600*3);
338
+ // Save this to our history so we can track backups for the retain feature
339
+ $this->log("Saving backup history");
340
+ $this->save_backup_history($backup_array);
341
+
342
  $this->check_backup_race($backup_array);
343
 
344
+ // The transient is read and written below (instead of using the existing variable) so that we can copy-and-paste this part as needed.
345
  if ($backup_database) {
346
  $this->log("Beginning backup of database");
347
  $db_backup = $this->backup_db();
 
348
  if(is_array($backup_array)) $backup_array['db'] = $db_backup;
349
+ $backup_contains = get_transient("updraft_backupcontains_".$this->nonce);
350
+ $backup_contains = (substr($backup_contains,0,10) == "Files only") ? "Files and database" : "Database only (no files)";
351
+ set_transient("updraft_backupcontains_".$this->nonce, $backup_contains, 3600*3);
352
  }
353
 
354
  $this->check_backup_race($backup_array);
 
355
 
356
+ // Save this to our history so we can track backups for the retain feature
357
  $this->log("Saving backup history");
358
  // This is done before cloud despatch, because we want a record of what *should* be in the backup. Whether it actually makes it there or not is not yet known.
359
  $this->save_backup_history($backup_array);
456
 
457
  $append_log = (get_option('updraft_debug_mode') && $this->logfile_name != "") ? "\r\nLog contents:\r\n".file_get_contents($this->logfile_name) : "" ;
458
 
459
+ wp_mail($sendmail_to,'Backed up: '.get_bloginfo('name').' (UpdraftPlus '.$this->version.') '.date('Y-m-d H:i',time()),'Site: '.site_url()."\r\nUpdraftPlus WordPress backup is complete.\r\nBackup contains: ".get_transient("updraft_backupcontains_".$this->nonce)."\r\n\r\n".$this->wordshell_random_advert(0)."\r\n".$append_log);
460
 
461
  }
462
 
764
  }
765
  return $backup_history;
766
  }
 
 
 
767
 
768
+ // Open a file, store its filehandle
769
+ function backup_db_open($file, $allow_gz = true) {
770
+ if (function_exists('gzopen') && $allow_gz == true) {
771
+ $this->dbhandle = @gzopen($file, 'w');
772
+ $this->dbhandle_isgz = true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
773
  } else {
774
+ $this->dbhandle = @fopen($file, 'w');
775
+ $this->dbhandle_isgz = false;
776
  }
777
+ if(!$this->dbhandle) {
778
+ //$this->error(__('Could not open the backup file for writing!','wp-db-backup'));
779
+ }
780
+ }
781
+
782
+ function backup_db_header() {
783
+
784
  //Begin new backup of MySql
785
+ $this->stow("# " . 'WordPress MySQL database backup' . "\n");
786
  $this->stow("#\n");
787
  $this->stow("# " . sprintf(__('Generated: %s','wp-db-backup'),date("l j. F Y H:i T")) . "\n");
788
  $this->stow("# " . sprintf(__('Hostname: %s','wp-db-backup'),DB_HOST) . "\n");
789
  $this->stow("# " . sprintf(__('Database: %s','wp-db-backup'),$this->backquote(DB_NAME)) . "\n");
790
  $this->stow("# --------------------------------------------------------\n");
 
791
 
792
  if (defined("DB_CHARSET")) {
793
  $this->stow("/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;\n");
796
  $this->stow("/*!40101 SET NAMES " . DB_CHARSET . " */;\n");
797
  }
798
  $this->stow("/*!40101 SET foreign_key_checks = 0 */;\n");
799
+ }
800
+
801
+ /* This function is resumable, using the following method:
802
+ - Each table is written out to ($final_filename).table.tmp
803
+ - When the writing finishes, it is renamed to ($final_filename).table
804
+ - When all tables are finished, they are concatenated into the final file
805
+ */
806
+ function backup_db() {
807
+
808
+ $total_tables = 0;
809
+
810
+ global $table_prefix, $wpdb;
811
+ if(!$this->backup_time) $this->backup_time_nonce();
812
+
813
+ $all_tables = $wpdb->get_results("SHOW TABLES", ARRAY_N);
814
+ $all_tables = array_map(create_function('$a', 'return $a[0];'), $all_tables);
815
+
816
+ // Get the file prefix
817
+ $updraft_dir = $this->backups_dir_location();
818
+
819
+ if (!is_writable($updraft_dir)) {
820
+ $this->error('The backup directory is not writable.');
821
+ return false;
822
+ }
823
+
824
+ // Get the blog name and rip out all non-alphanumeric chars other than _
825
+ $blog_name = str_replace(' ','_',get_bloginfo());
826
+ $blog_name = preg_replace('/[^A-Za-z0-9_]/','', $blog_name);
827
+ if (!$blog_name) $blog_name = 'non_alpha_name';
828
+ $file_base = 'backup_'.date('Y-m-d-Hi',$this->backup_time).'_'.$blog_name.'_'.$this->nonce;
829
+ $backup_file_base = $updraft_dir.'/'.$file_base;
830
+
831
+ $stitch_files = array();
832
 
833
  foreach ($all_tables as $table) {
834
  $total_tables++;
835
  // Increase script execution time-limit to 15 min for every table.
836
  if ( !ini_get('safe_mode') || strtolower(ini_get('safe_mode')) == "off") @set_time_limit(15*60);
837
+ // The table file may already exist if we have produced it on a previous run
838
+ $table_file_prefix = $file_base.'-db-table-'.$table.'.table';
839
+ if (file_exists($updraft_dir.'/'.$table_file_prefix)) {
840
+ $this->log("Table $table: corresponding file already exists; moving on");
 
 
 
841
  } else {
842
+ // Open file, store the handle
843
+ $this->backup_db_open($updraft_dir.'/'.$table_file_prefix.'.tmp', false);
844
+ # === is needed, otherwise 'false' matches (i.e. prefix does not match)
845
+ if ( strpos($table, $table_prefix) === 0 ) {
846
+ // Create the SQL statements
847
+ $this->stow("# --------------------------------------------------------\n");
848
+ $this->stow("# " . sprintf(__('Table: %s','wp-db-backup'),$this->backquote($table)) . "\n");
849
+ $this->stow("# --------------------------------------------------------\n");
850
+ $this->backup_table($table);
851
+ } else {
852
+ $this->stow("# --------------------------------------------------------\n");
853
+ $this->stow("# " . sprintf(__('Skipping non-WP table: %s','wp-db-backup'),$this->backquote($table)) . "\n");
854
+ $this->stow("# --------------------------------------------------------\n");
855
+ }
856
+ // Close file
857
+ $this->close($this->dbhandle);
858
+ $this->log("Table $table: finishing file (${table_file_prefix})");
859
+ rename($updraft_dir.'/'.$table_file_prefix.'.tmp', $updraft_dir.'/'.$table_file_prefix);
860
  }
861
+ $stitch_files[] = $table_file_prefix;
862
  }
863
 
864
+ // Finally, stitch the files together
865
+ $this->backup_db_open($backup_file_base.'-db.gz', true);
866
+ $this->backup_db_header();
867
  if (defined("DB_CHARSET")) {
868
  $this->stow("/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n");
869
  $this->stow("/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n");
870
  $this->stow("/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
871
  }
872
+ foreach ($stitch_files as $table_file) {
873
+ $this->log("$table_file: adding to final database dump");
874
+ $handle = fopen($updraft_dir.'/'.$table_file, "r");
875
+ while (!feof($handle)) { $this->stow(fread($handle, 32768)); }
876
+ fclose($handle);
877
+ @unlink($updraft_dir.'/'.$table_file);
878
+ }
879
+ $this->log($file_base.'-db.gz: finished writing out complete database file');
880
  $this->close($this->dbhandle);
881
 
882
  if (count($this->errors)) {
962
  }
963
  }
964
 
 
965
  // Batch by $row_inc
966
  if ( ! defined('ROWS_PER_SEGMENT') ) {
967
  define('ROWS_PER_SEGMENT', 100);
1015
 
1016
  } // end backup_table()
1017
 
 
1018
  function stow($query_line) {
1019
+ if ($this->dbhandle_isgz) {
1020
  if(! @gzwrite($this->dbhandle, $query_line)) {
1021
  //$this->error(__('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg);
1022
  }
1027
  }
1028
  }
1029
 
 
1030
  function close($handle) {
1031
+ if ($this->dbhandle_isgz) {
1032
  gzclose($handle);
1033
  } else {
1034
  fclose($handle);
1604
  <div style="float:left; width:200px; padding-top: 100px;">
1605
  <form method="post" action="">
1606
  <input type="hidden" name="action" value="updraft_backup" />
1607
+ <p><input type="submit" <?php echo $backup_disabled ?> class="button-primary" value="Backup Now!" style="padding-top:3px;padding-bottom:3px;font-size:24px !important" onclick="return(confirm('This will schedule a one-time backup. To trigger the backup you should go ahead, then wait 10 seconds, then load a page on your site.'))" /></p>
1608
  </form>
1609
  <div style="position:relative">
1610
  <div style="position:absolute;top:0;left:0">
1613
  $backup_history = (is_array($backup_history))?$backup_history:array();
1614
  $restore_disabled = (count($backup_history) == 0) ? 'disabled="disabled"' : "";
1615
  ?>
1616
+ <input type="button" class="button-primary" <?php echo $restore_disabled ?> value="Restore" style="padding-top:3px;padding-bottom:3px;font-size:24px !important" onclick="jQuery('#backup-restore').fadeIn('slow');jQuery(this).parent().fadeOut('slow')" />
1617
  </div>
1618
  <div style="display:none;position:absolute;top:0;left:0" id="backup-restore">
1619
  <form method="post" action="">