| [ Index ] |
WordPress Source Cross Reference |
[Summary view] [Print] [Text view]
1 <?php 2 /* 3 Plugin Name: WordPress Database Backup 4 Plugin URI: http://www.skippy.net/blog/plugins/ 5 Description: On-demand backup of your WordPress database. 6 Author: Scott Merrill 7 Version: 1.7 8 Author URI: http://www.skippy.net/ 9 10 Much of this was modified from Mark Ghosh's One Click Backup, which 11 in turn was derived from phpMyAdmin. 12 13 Many thanks to Owen (http://asymptomatic.net/wp/) for his patch 14 http://dev.wp-plugins.org/ticket/219 15 */ 16 17 // CHANGE THIS IF YOU WANT TO USE A 18 // DIFFERENT BACKUP LOCATION 19 20 $rand = substr( md5( md5( DB_PASSWORD ) ), -5 ); 21 22 define('WP_BACKUP_DIR', 'wp-content/backup-' . $rand); 23 24 define('ROWS_PER_SEGMENT', 100); 25 26 class wpdbBackup { 27 28 var $backup_complete = false; 29 var $backup_file = ''; 30 var $backup_dir = WP_BACKUP_DIR; 31 var $backup_errors = array(); 32 var $basename; 33 // Simple table name storage 34 var $wp_table_names = array('categories','comments','link2cat','links','options','post2cat','postmeta','posts','users','usermeta'); 35 36 function gzip() { 37 return function_exists('gzopen'); 38 } 39 40 function wpdbBackup() { 41 add_action('wp_cron_daily', array(&$this, 'wp_cron_daily')); 42 43 $this->backup_dir = trailingslashit($this->backup_dir); 44 $this->basename = preg_replace('/^.*wp-content[\\\\\/]plugins[\\\\\/]/', '', __FILE__); 45 46 if (isset($_POST['do_backup'])) { 47 if ( !current_user_can('import') ) die(__('You are not allowed to perform backups.')); 48 switch($_POST['do_backup']) { 49 case 'backup': 50 $this->perform_backup(); 51 break; 52 case 'fragments': 53 add_action('admin_menu', array(&$this, 'fragment_menu')); 54 break; 55 } 56 } elseif (isset($_GET['fragment'] )) { 57 if ( !current_user_can('import') ) die(__('You are not allowed to perform backups.')); 58 add_action('init', array(&$this, 'init')); 59 } elseif (isset($_GET['backup'] )) { 60 if ( !current_user_can('import') ) die(__('You are not allowed to perform backups.')); 61 add_action('init', array(&$this, 'init')); 62 } else { 63 add_action('admin_menu', array(&$this, 'admin_menu')); 64 } 65 } 66 67 function init() { 68 if ( !current_user_can('import') ) die(__('You are not allowed to perform backups.')); 69 70 if (isset($_GET['backup'])) { 71 $via = isset($_GET['via']) ? $_GET['via'] : 'http'; 72 73 $this->backup_file = $_GET['backup']; 74 75 switch($via) { 76 case 'smtp': 77 case 'email': 78 $this->deliver_backup ($this->backup_file, 'smtp', $_GET['recipient']); 79 echo ' 80 <!-- ' . $via . ' --> 81 <script type="text/javascript"><!--\\ 82 '; 83 if($this->backup_errors) { 84 foreach($this->backup_errors as $error) { 85 echo "window.parent.addError('$error');\n"; 86 } 87 } 88 echo ' 89 alert("' . __('Backup Complete!') . '"); 90 </script> 91 '; 92 break; 93 default: 94 $this->deliver_backup ($this->backup_file, $via); 95 } 96 die(); 97 } 98 if (isset($_GET['fragment'] )) { 99 list($table, $segment, $filename) = explode(':', $_GET['fragment']); 100 $this->backup_fragment($table, $segment, $filename); 101 } 102 103 die(); 104 } 105 106 function build_backup_script() { 107 global $wpdb; 108 109 $datum = date("Ymd_B"); 110 $backup_filename = DB_NAME . '_' . $wpdb->prefix . $datum . '.sql'; 111 if ($this->gzip()) $backup_filename .= '.gz'; 112 113 echo "<div class='wrap'>"; 114 //echo "<pre>" . print_r($_POST, 1) . "</pre>"; 115 echo '<h2>' . __('Backup') . '</h2> 116 <fieldset class="options"><legend>' . __('Progress') . '</legend> 117 <p><strong>' . 118 __('DO NOT DO THE FOLLOWING AS IT WILL CAUSE YOUR BACKUP TO FAIL:'). 119 '</strong></p> 120 <ol> 121 <li>'.__('Close this browser').'</li> 122 <li>'.__('Reload this page').'</li> 123 <li>'.__('Click the Stop or Back buttons in your browser').'</li> 124 </ol> 125 <p><strong>' . __('Progress:') . '</strong></p> 126 <div id="meterbox" style="height:11px;width:80%;padding:3px;border:1px solid #659fff;"><div id="meter" style="height:11px;background-color:#659fff;width:0%;text-align:center;font-size:6pt;"> </div></div> 127 <div id="progress_message"></div> 128 <div id="errors"></div> 129 </fieldset> 130 <iframe id="backuploader" src="about:blank" style="border:0px solid white;height:1em;width:1em;"></iframe> 131 <script type="text/javascript"><!--// 132 function setMeter(pct) { 133 var meter = document.getElementById("meter"); 134 meter.style.width = pct + "%"; 135 meter.innerHTML = Math.floor(pct) + "%"; 136 } 137 function setProgress(str) { 138 var progress = document.getElementById("progress_message"); 139 progress.innerHTML = str; 140 } 141 function addError(str) { 142 var errors = document.getElementById("errors"); 143 errors.innerHTML = errors.innerHTML + str + "<br />"; 144 } 145 146 function backup(table, segment) { 147 var fram = document.getElementById("backuploader"); 148 fram.src = "' . $_SERVER['REQUEST_URI'] . '&fragment=" + table + ":" + segment + ":' . $backup_filename . '"; 149 } 150 151 var curStep = 0; 152 153 function nextStep() { 154 backupStep(curStep); 155 curStep++; 156 } 157 158 function finishBackup() { 159 var fram = document.getElementById("backuploader"); 160 setMeter(100); 161 '; 162 163 $this_basename = preg_replace('/^.*wp-content[\\\\\/]plugins[\\\\\/]/', '', __FILE__); 164 $download_uri = get_settings('siteurl') . "/wp-admin/edit.php?page={$this_basename}&backup={$backup_filename}"; 165 switch($_POST['deliver']) { 166 case 'http': 167 echo ' 168 setProgress("' . sprintf(__("Backup complete, preparing <a href=\\\"%s\\\">backup</a> for download..."), $download_uri) . '"); 169 fram.src = "' . $download_uri . '"; 170 '; 171 break; 172 case 'smtp': 173 echo ' 174 setProgress("' . sprintf(__("Backup complete, sending <a href=\\\"%s\\\">backup</a> via email..."), $download_uri) . '"); 175 fram.src = "' . $download_uri . '&via=email&recipient=' . $_POST['backup_recipient'] . '"; 176 '; 177 break; 178 default: 179 echo ' 180 setProgress("' . sprintf(__("Backup complete, download <a href=\\\"%s\\\">here</a>."), $download_uri) . '"); 181 '; 182 } 183 184 echo ' 185 } 186 187 function backupStep(step) { 188 switch(step) { 189 case 0: backup("", 0); break; 190 '; 191 192 $also_backup = array(); 193 if (isset($_POST['other_tables'])) { 194 $also_backup = $_POST['other_tables']; 195 } else { 196 $also_backup = array(); 197 } 198 $core_tables = $_POST['core_tables']; 199 $tables = array_merge($core_tables, $also_backup); 200 $step_count = 1; 201 foreach ($tables as $table) { 202 $rec_count = $wpdb->get_var("SELECT count(*) FROM {$table}"); 203 $rec_segments = ceil($rec_count / ROWS_PER_SEGMENT); 204 $table_count = 0; 205 do { 206 echo "case {$step_count}: backup(\"{$table}\", {$table_count}); break;\n"; 207 $step_count++; 208 $table_count++; 209 } while($table_count < $rec_segments); 210 echo "case {$step_count}: backup(\"{$table}\", -1); break;\n"; 211 $step_count++; 212 } 213 echo "case {$step_count}: finishBackup(); break;"; 214 215 echo ' 216 } 217 if(step != 0) setMeter(100 * step / ' . $step_count . '); 218 } 219 220 nextStep(); 221 //--></script> 222 </div> 223 '; 224 } 225 226 function backup_fragment($table, $segment, $filename) { 227 global $wpdb; 228 229 echo "$table:$segment:$filename"; 230 231 if($table == '') { 232 $msg = __('Creating backup file...'); 233 } else { 234 if($segment == -1) { 235 $msg = sprintf(__('Finished backing up table \\"%s\\".'), $table); 236 } else { 237 $msg = sprintf(__('Backing up table \\"%s\\"...'), $table); 238 } 239 } 240 241 echo '<script type="text/javascript"><!--// 242 var msg = "' . $msg . '"; 243 window.parent.setProgress(msg); 244 '; 245 246 if (is_writable(ABSPATH . $this->backup_dir)) { 247 $this->fp = $this->open(ABSPATH . $this->backup_dir . $filename, 'a'); 248 if(!$this->fp) { 249 $this->backup_error(__('Could not open the backup file for writing!')); 250 $this->fatal_error = __('The backup file could not be saved. Please check the permissions for writing to your backup directory and try again.'); 251 } 252 else { 253 if($table == '') { 254 //Begin new backup of MySql 255 $this->stow("# WordPress MySQL database backup\n"); 256 $this->stow("#\n"); 257 $this->stow("# Generated: " . date("l j. F Y H:i T") . "\n"); 258 $this->stow("# Hostname: " . DB_HOST . "\n"); 259 $this->stow("# Database: " . $this->backquote(DB_NAME) . "\n"); 260 $this->stow("# --------------------------------------------------------\n"); 261 } else { 262 if($segment == 0) { 263 // Increase script execution time-limit to 15 min for every table. 264 if ( !ini_get('safe_mode')) @set_time_limit(15*60); 265 //ini_set('memory_limit', '16M'); 266 // Create the SQL statements 267 $this->stow("# --------------------------------------------------------\n"); 268 $this->stow("# Table: " . $this->backquote($table) . "\n"); 269 $this->stow("# --------------------------------------------------------\n"); 270 } 271 $this->backup_table($table, $segment); 272 } 273 } 274 } else { 275 $this->backup_error(__('The backup directory is not writeable!')); 276 $this->fatal_error = __('The backup directory is not writeable! Please check the permissions for writing to your backup directory and try again.'); 277 } 278 279 if($this->fp) $this->close($this->fp); 280 281 if($this->backup_errors) { 282 foreach($this->backup_errors as $error) { 283 echo "window.parent.addError('$error');\n"; 284 } 285 } 286 if($this->fatal_error) { 287 echo ' 288 alert("' . addslashes($this->fatal_error) . '"); 289 //--></script> 290 '; 291 } 292 else { 293 echo ' 294 window.parent.nextStep(); 295 //--></script> 296 '; 297 } 298 299 die(); 300 } 301 302 function perform_backup() { 303 // are we backing up any other tables? 304 $also_backup = array(); 305 if (isset($_POST['other_tables'])) { 306 $also_backup = $_POST['other_tables']; 307 } 308 309 $core_tables = $_POST['core_tables']; 310 $this->backup_file = $this->db_backup($core_tables, $also_backup); 311 if (FALSE !== $this->backup_file) { 312 if ('smtp' == $_POST['deliver']) { 313 $this->deliver_backup ($this->backup_file, $_POST['deliver'], $_POST['backup_recipient']); 314 } elseif ('http' == $_POST['deliver']) { 315 $this_basename = preg_replace('/^.*wp-content[\\\\\/]plugins[\\\\\/]/', '', __FILE__); 316 header('Refresh: 3; ' . get_settings('siteurl') . "/wp-admin/edit.php?page={$this_basename}&backup={$this->backup_file}"); 317 } 318 // we do this to say we're done. 319 $this->backup_complete = true; 320 } 321 } 322 323 /////////////////////////////// 324 function admin_menu() { 325 add_management_page(__('Backup'), __('Backup'), 9, basename(__FILE__), array(&$this, 'backup_menu')); 326 } 327 328 function fragment_menu() { 329 add_management_page(__('Backup'), __('Backup'), 9, basename(__FILE__), array(&$this, 'build_backup_script')); 330 } 331 332 ///////////////////////////////////////////////////////// 333 function sql_addslashes($a_string = '', $is_like = FALSE) 334 { 335 /* 336 Better addslashes for SQL queries. 337 Taken from phpMyAdmin. 338 */ 339 if ($is_like) { 340 $a_string = str_replace('\\', '\\\\\\\\', $a_string); 341 } else { 342 $a_string = str_replace('\\', '\\\\', $a_string); 343 } 344 $a_string = str_replace('\'', '\\\'', $a_string); 345 346 return $a_string; 347 } // function sql_addslashes($a_string = '', $is_like = FALSE) 348 349 /////////////////////////////////////////////////////////// 350 function backquote($a_name) 351 { 352 /* 353 Add backqouotes to tables and db-names in 354 SQL queries. Taken from phpMyAdmin. 355 */ 356 if (!empty($a_name) && $a_name != '*') { 357 if (is_array($a_name)) { 358 $result = array(); 359 reset($a_name); 360 while(list($key, $val) = each($a_name)) { 361 $result[$key] = '`' . $val . '`'; 362 } 363 return $result; 364 } else { 365 return '`' . $a_name . '`'; 366 } 367 } else { 368 return $a_name; 369 } 370 } // function backquote($a_name, $do_it = TRUE) 371 372 ///////////// 373 function open($filename = '', $mode = 'w') { 374 if ('' == $filename) return false; 375 if ($this->gzip()) { 376 $fp = @gzopen($filename, $mode); 377 } else { 378 $fp = @fopen($filename, $mode); 379 } 380 return $fp; 381 } 382 383 ////////////// 384 function close($fp) { 385 if ($this->gzip()) { 386 gzclose($fp); 387 } else { 388 fclose($fp); 389 } 390 } 391 392 ////////////// 393 function stow($query_line) { 394 if ($this->gzip()) { 395 if(@gzwrite($this->fp, $query_line) === FALSE) { 396 backup_error(__('There was an error writing a line to the backup script:')); 397 backup_error(' ' . $query_line); 398 } 399 } else { 400 if(@fwrite($this->fp, $query_line) === FALSE) { 401 backup_error(__('There was an error writing a line to the backup script:')); 402 backup_error(' ' . $query_line); 403 } 404 } 405 } 406 407 function backup_error($err) { 408 if(count($this->backup_errors) < 20) { 409 $this->backup_errors[] = $err; 410 } elseif(count($this->backup_errors) == 20) { 411 $this->backup_errors[] = __('Subsequent errors have been omitted from this log.'); 412 } 413 } 414 415 ///////////////////////////// 416 function backup_table($table, $segment = 'none') { 417 global $wpdb; 418 419 /* 420 Taken partially from phpMyAdmin and partially from 421 Alain Wolf, Zurich - Switzerland 422 Website: http://restkultur.ch/personal/wolf/scripts/db_backup/ 423 424 Modified by Scott Merril (http://www.skippy.net/) 425 to use the WordPress $wpdb object 426 */ 427 428 $table_structure = $wpdb->get_results("DESCRIBE $table"); 429 if (! $table_structure) { 430 backup_errors(__('Error getting table details') . ": $table"); 431 return FALSE; 432 } 433 434 if(($segment == 'none') || ($segment == 0)) { 435 // 436 // Add SQL statement to drop existing table 437 $this->stow("\n\n"); 438 $this->stow("#\n"); 439 $this->stow("# Delete any existing table " . $this->backquote($table) . "\n"); 440 $this->stow("#\n"); 441 $this->stow("\n"); 442 $this->stow("DROP TABLE IF EXISTS " . $this->backquote($table) . ";\n"); 443 444 // 445 //Table structure 446 // Comment in SQL-file 447 $this->stow("\n\n"); 448 $this->stow("#\n"); 449 $this->stow("# Table structure of table " . $this->backquote($table) . "\n"); 450 $this->stow("#\n"); 451 $this->stow("\n"); 452 453 $create_table = $wpdb->get_results("SHOW CREATE TABLE $table", ARRAY_N); 454 if (FALSE === $create_table) { 455 $this->backup_error(sprintf(__("Error with SHOW CREATE TABLE for %s."), $table)); 456 $this->stow("#\n# Error with SHOW CREATE TABLE for $table!\n#\n"); 457 } 458 $this->stow($create_table[0][1] . ' ;'); 459 460 if (FALSE === $table_structure) { 461 $this->backup_error(sprintf(__("Error getting table structure of %s"), $table)); 462 $this->stow("#\n# Error getting table structure of $table!\n#\n"); 463 } 464 465 // 466 // Comment in SQL-file 467 $this->stow("\n\n"); 468 $this->stow("#\n"); 469 $this->stow('# Data contents of table ' . $this->backquote($table) . "\n"); 470 $this->stow("#\n"); 471 } 472 473 if(($segment == 'none') || ($segment >= 0)) { 474 $ints = array(); 475 foreach ($table_structure as $struct) { 476 if ( (0 === strpos($struct->Type, 'tinyint')) || 477 (0 === strpos(strtolower($struct->Type), 'smallint')) || 478 (0 === strpos(strtolower($struct->Type), 'mediumint')) || 479 (0 === strpos(strtolower($struct->Type), 'int')) || 480 (0 === strpos(strtolower($struct->Type), 'bigint')) || 481 (0 === strpos(strtolower($struct->Type), 'timestamp')) ) { 482 $ints[strtolower($struct->Field)] = "1"; 483 } 484 } 485 486 487 // Batch by $row_inc 488 489 if($segment == 'none') { 490 $row_start = 0; 491 $row_inc = ROWS_PER_SEGMENT; 492 } else { 493 $row_start = $segment * ROWS_PER_SEGMENT; 494 $row_inc = ROWS_PER_SEGMENT; 495 } 496 497 do { 498 if ( !ini_get('safe_mode')) @set_time_limit(15*60); 499 $table_data = $wpdb->get_results("SELECT * FROM $table LIMIT {$row_start}, {$row_inc}", ARRAY_A); 500 501 /* 502 if (FALSE === $table_data) { 503 $wp_backup_error .= "Error getting table contents from $table\r\n"; 504 fwrite($fp, "#\n# Error getting table contents fom $table!\n#\n"); 505 } 506 */ 507 508 $entries = 'INSERT INTO ' . $this->backquote($table) . ' VALUES ('; 509 // \x08\\x09, not required 510 $search = array("\x00", "\x0a", "\x0d", "\x1a"); 511 $replace = array('\0', '\n', '\r', '\Z'); 512 if($table_data) { 513 foreach ($table_data as $row) { 514 $values = array(); 515 foreach ($row as $key => $value) { 516 if ($ints[strtolower($key)]) { 517 $values[] = $value; 518 } else { 519 $values[] = "'" . str_replace($search, $replace, $this->sql_addslashes($value)) . "'"; 520 } 521 } 522 $this->stow(" \n" . $entries . implode(', ', $values) . ') ;'); 523 } 524 $row_start += $row_inc; 525 } 526 } while((count($table_data) > 0) and ($segment=='none')); 527 } 528 529 530 if(($segment == 'none') || ($segment < 0)) { 531 // Create footer/closing comment in SQL-file 532 $this->stow("\n"); 533 $this->stow("#\n"); 534 $this->stow("# End of data contents of table " . $this->backquote($table) . "\n"); 535 $this->stow("# --------------------------------------------------------\n"); 536 $this->stow("\n"); 537 } 538 539 } // end backup_table() 540 541 function return_bytes($val) { 542 $val = trim($val); 543 $last = strtolower($val{strlen($val)-1}); 544 switch($last) { 545 // The 'G' modifier is available since PHP 5.1.0 546 case 'g': 547 $val *= 1024; 548 case 'm': 549 $val *= 1024; 550 case 'k': 551 $val *= 1024; 552 } 553 554 return $val; 555 } 556 557 //////////////////////////// 558 function db_backup($core_tables, $other_tables) { 559 global $wpdb; 560 561 $datum = date("Ymd_B"); 562 $wp_backup_filename = DB_NAME . '_' . $wpdb->prefix . $datum . '.sql'; 563 if ($this->gzip()) { 564 $wp_backup_filename .= '.gz'; 565 } 566 567 if (is_writable(ABSPATH . $this->backup_dir)) { 568 $this->fp = $this->open(ABSPATH . $this->backup_dir . $wp_backup_filename); 569 if(!$this->fp) { 570 $this->backup_error(__('Could not open the backup file for writing!')); 571 return false; 572 } 573 } else { 574 $this->backup_error(__('The backup directory is not writeable!')); 575 return false; 576 } 577 578 //Begin new backup of MySql 579 $this->stow("# WordPress MySQL database backup\n"); 580 $this->stow("#\n"); 581 $this->stow("# Generated: " . date("l j. F Y H:i T") . "\n"); 582 $this->stow("# Hostname: " . DB_HOST . "\n"); 583 $this->stow("# Database: " . $this->backquote(DB_NAME) . "\n"); 584 $this->stow("# --------------------------------------------------------\n"); 585 586 if ( (is_array($other_tables)) && (count($other_tables) > 0) ) 587 $tables = array_merge($core_tables, $other_tables); 588 else 589 $tables = $core_tables; 590 591 foreach ($tables as $table) { 592 // Increase script execution time-limit to 15 min for every table. 593 if ( !ini_get('safe_mode')) @set_time_limit(15*60); 594 // Create the SQL statements 595 $this->stow("# --------------------------------------------------------\n"); 596 $this->stow("# Table: " . $this->backquote($table) . "\n"); 597 $this->stow("# --------------------------------------------------------\n"); 598 $this->backup_table($table); 599 } 600 601 $this->close($this->fp); 602 603 if (count($this->backup_errors)) { 604 return false; 605 } else { 606 return $wp_backup_filename; 607 } 608 609 } //wp_db_backup 610 611 /////////////////////////// 612 function deliver_backup ($filename = '', $delivery = 'http', $recipient = '') { 613 if ('' == $filename) { return FALSE; } 614 615 $diskfile = ABSPATH . $this->backup_dir . $filename; 616 if ('http' == $delivery) { 617 if (! file_exists($diskfile)) { 618 $msg = sprintf(__('File not found:%s'), "<br /><strong>$filename</strong><br />"); 619 $this_basename = preg_replace('/^.*wp-content[\\\\\/]plugins[\\\\\/]/', '', __FILE__); 620 $msg .= '<br /><a href="' . get_settings('siteurl') . "/wp-admin/edit.php?page={$this_basename}" . '">' . __('Return to Backup'); 621 die($msg); 622 } 623 header('Content-Description: File Transfer'); 624 header('Content-Type: application/octet-stream'); 625 header('Content-Length: ' . filesize($diskfile)); 626 header("Content-Disposition: attachment; filename=$filename"); 627 readfile($diskfile); 628 unlink($diskfile); 629 } elseif ('smtp' == $delivery) { 630 if (! file_exists($diskfile)) return false; 631 632 if (! is_email ($recipient)) { 633 $recipient = get_settings('admin_email'); 634 } 635 $randomish = md5(time()); 636 $boundary = "==WPBACKUP-BY-SKIPPY-$randomish"; 637 $fp = fopen($diskfile,"rb"); 638 $file = fread($fp,filesize($diskfile)); 639 $this->close($fp); 640 $data = chunk_split(base64_encode($file)); 641 $headers = "MIME-Version: 1.0\n"; 642 $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\n"; 643 $headers .= 'From: ' . get_settings('admin_email') . "\n"; 644 645 $message = sprintf(__("Attached to this email is\n %1s\n Size:%2s kilobytes\n"), $filename, round(filesize($diskfile)/1024)); 646 // Add a multipart boundary above the plain message 647 $message = "This is a multi-part message in MIME format.\n\n" . 648 "--{$boundary}\n" . 649 "Content-Type: text/plain; charset=\"utf-8\"\n" . 650 "Content-Transfer-Encoding: 7bit\n\n" . 651 $message . "\n\n"; 652 653 // Add file attachment to the message 654 $message .= "--{$boundary}\n" . 655 "Content-Type: application/octet-stream;\n" . 656 " name=\"{$filename}\"\n" . 657 "Content-Disposition: attachment;\n" . 658 " filename=\"{$filename}\"\n" . 659 "Content-Transfer-Encoding: base64\n\n" . 660 $data . "\n\n" . 661 "--{$boundary}--\n"; 662 663 if (function_exists('wp_mail')) { 664 wp_mail ($recipient, get_bloginfo('name') . ' ' . __('Database Backup'), $message, $headers); 665 } else { 666 mail ($recipient, get_bloginfo('name') . ' ' . __('Database Backup'), $message, $headers); 667 } 668 669 unlink($diskfile); 670 } 671 return; 672 } 673 674 //////////////////////////// 675 function backup_menu() { 676 global $wpdb; 677 $feedback = ''; 678 $WHOOPS = FALSE; 679 680 // did we just do a backup? If so, let's report the status 681 if ( $this->backup_complete ) { 682 $feedback = '<div class="updated"><p>' . __('Backup Successful') . '!'; 683 $file = $this->backup_file; 684 switch($_POST['deliver']) { 685 case 'http': 686 $feedback .= '<br />' . sprintf(__('Your backup file: <a href="%1s">%2s</a> should begin downloading shortly.'), get_settings('siteurl') . "/{$this->backup_dir}{$this->backup_file}", $this->backup_file); 687 break; 688 case 'smtp': 689 if (! is_email($_POST['backup_recipient'])) { 690 $feedback .= get_settings('admin_email'); 691 } else { 692 $feedback .= $_POST['backup_recipient']; 693 } 694 $feedback = '<br />' . sprintf(__('Your backup has been emailed to %s'), $feedback); 695 break; 696 case 'none': 697 $feedback .= '<br />' . __('Your backup file has been saved on the server. If you would like to download it now, right click and select "Save As"'); 698 $feedback .= ':<br /> <a href="' . get_settings('siteurl') . "/{$this->backup_dir}$file\">$file</a> : " . sprintf(__('%s bytes'), filesize(ABSPATH . $this->backup_dir . $file)); 699 } 700 $feedback .= '</p></div>'; 701 } 702 703 if (count($this->backup_errors)) { 704 $feedback .= '<div class="updated error">' . __('The following errors were reported:') . "<pre>"; 705 foreach($this->backup_errors as $error) { 706 $feedback .= "{$error}\n"; //Errors are already localized 707 } 708 $feedback .= "</pre></div>"; 709 } 710 711 // did we just save options for wp-cron? 712 if ( (function_exists('wp_cron_init')) && isset($_POST['wp_cron_backup_options']) ) { 713 update_option('wp_cron_backup_schedule', intval($_POST['cron_schedule']), FALSE); 714 update_option('wp_cron_backup_tables', $_POST['wp_cron_backup_tables']); 715 if (is_email($_POST['cron_backup_recipient'])) { 716 update_option('wp_cron_backup_recipient', $_POST['cron_backup_recipient'], FALSE); 717 } 718 $feedback .= '<div class="updated"><p>' . __('Scheduled Backup Options Saved!') . '</p></div>'; 719 } 720 721 // Apply WP DB prefix to table names 722 $wp_table_names = array_map(create_function('$a', 'global $wpdb;return "{$wpdb->prefix}{$a}";'), $this->wp_table_names); 723 724 $other_tables = array(); 725 $also_backup = array(); 726 727 // Get complete db table list 728 $all_tables = $wpdb->get_results("SHOW TABLES", ARRAY_N); 729 $all_tables = array_map(create_function('$a', 'return $a[0];'), $all_tables); 730 // Get list of WP tables that actually exist in this DB (for 1.6 compat!) 731 $wp_backup_default_tables = array_intersect($all_tables, $wp_table_names); 732 // Get list of non-WP tables 733 $other_tables = array_diff($all_tables, $wp_backup_default_tables); 734 735 if ('' != $feedback) { 736 echo $feedback; 737 } 738 739 // Give the new dirs the same perms as wp-content. 740 $stat = stat( ABSPATH . 'wp-content' ); 741 $dir_perms = $stat['mode'] & 0000777; // Get the permission bits. 742 743 if ( !file_exists( ABSPATH . $this->backup_dir) ) { 744 if ( @ mkdir( ABSPATH . $this->backup_dir) ) { 745 @ chmod( ABSPATH . $this->backup_dir, $dir_perms); 746 } else { 747 echo '<div class="updated error"><p align="center">' . __('WARNING: Your wp-content directory is <strong>NOT</strong> writable! We can not create the backup directory.') . '<br />' . ABSPATH . $this->backup_dir . "</p></div>"; 748 $WHOOPS = TRUE; 749 } 750 } 751 752 if ( !is_writable( ABSPATH . $this->backup_dir) ) { 753 echo '<div class="updated error"><p align="center">' . __('WARNING: Your backup directory is <strong>NOT</strong> writable! We can not create the backup directory.') . '<br />' . ABSPATH . "</p></div>"; 754 } 755 756 if ( !file_exists( ABSPATH . $this->backup_dir . 'index.php') ) { 757 @ touch( ABSPATH . $this->backup_dir . "index.php"); 758 } 759 760 echo "<div class='wrap'>"; 761 echo '<h2>' . __('Backup') . '</h2>'; 762 echo '<fieldset class="options"><legend>' . __('Tables') . '</legend>'; 763 echo '<form method="post">'; 764 echo '<table align="center" cellspacing="5" cellpadding="5"><tr><td width="50%" align="left" class="alternate" valign="top">'; 765 echo __('These core WordPress tables will always be backed up:') . '<br /><ul>'; 766 foreach ($wp_backup_default_tables as $table) { 767 echo "<li><input type='hidden' name='core_tables[]' value='$table' />$table</li>"; 768 } 769 echo '</ul></td><td width="50%" align="left" valign="top">'; 770 if (count($other_tables) > 0) { 771 echo __('You may choose to include any of the following tables:') . ' <br />'; 772 foreach ($other_tables as $table) { 773 echo "<label style=\"display:block;\"><input type='checkbox' name='other_tables[]' value='{$table}' /> {$table}</label>"; 774 } 775 } 776 echo '</tr></table></fieldset>'; 777 echo '<fieldset class="options"><legend>' . __('Backup Options') . '</legend>'; 778 echo __('What to do with the backup file:') . "<br />"; 779 echo '<label style="display:block;"><input type="radio" name="deliver" value="none" /> ' . __('Save to server') . " ({$this->backup_dir})</label>"; 780 echo '<label style="display:block;"><input type="radio" checked="checked" name="deliver" value="http" /> ' . __('Download to your computer') . '</label>'; 781 echo '<div><input type="radio" name="deliver" id="do_email" value="smtp" /> '; 782 echo '<label for="do_email">'.__('Email backup to:').'</label><input type="text" name="backup_recipient" size="20" value="' . get_settings('admin_email') . '" />'; 783 784 // Check DB dize. 785 $table_status = $wpdb->get_results("SHOW TABLE STATUS FROM " . $this->backquote(DB_NAME)); 786 $core_size = $db_size = 0; 787 foreach($table_status as $table) { 788 $table_size = $table->Data_length - $table->Data_free; 789 if(in_array($table->Name, $wp_backup_default_tables)) { 790 $core_size += $table_size; 791 } 792 $db_size += $table_size; 793 } 794 $mem_limit = ini_get('memory_limit'); 795 $mem_limit = $this->return_bytes($mem_limit); 796 $mem_limit = ($mem_limit == 0) ? 8*1024*1024 : $mem_limit - 2000000; 797 798 if (! $WHOOPS) { 799 echo '<input type="hidden" name="do_backup" id="do_backup" value="backup" /></div>'; 800 echo '<p class="submit"><input type="submit" name="submit" onclick="document.getElementById(\'do_backup\').value=\'fragments\';" value="' . __('Backup') . '!" / ></p>'; 801 } else { 802 echo '<p class="alternate">' . __('WARNING: Your backup directory is <strong>NOT</strong> writable!') . '</p>'; 803 } 804 echo '</fieldset>'; 805 echo '</form>'; 806 807 // this stuff only displays if wp_cron is installed 808 if (function_exists('wp_cron_init')) { 809 echo '<fieldset class="options"><legend>' . __('Scheduled Backup') . '</legend>'; 810 $datetime = get_settings('date_format') . ' @ ' . get_settings('time_format'); 811 echo '<p>' . __('Last WP-Cron Daily Execution') . ': ' . date($datetime, get_option('wp_cron_daily_lastrun')) . '<br />'; 812 echo __('Next WP-Cron Daily Execution') . ': ' . date($datetime, (get_option('wp_cron_daily_lastrun') + 86400)) . '</p>'; 813 echo '<form method="post">'; 814 echo '<table width="100%" callpadding="5" cellspacing="5">'; 815 echo '<tr><td align="center">'; 816 echo __('Schedule: '); 817 $wp_cron_backup_schedule = get_option('wp_cron_backup_schedule'); 818 $schedule = array(0 => __('None'), 1 => __('Daily')); 819 foreach ($schedule as $value => $name) { 820 echo ' <input type="radio" name="cron_schedule"'; 821 if ($wp_cron_backup_schedule == $value) { 822 echo ' checked="checked" '; 823 } 824 echo 'value="' . $value . '" /> ' . __($name); 825 } 826 echo '</td><td align="center">'; 827 $cron_recipient = get_option('wp_cron_backup_recipient'); 828 if (! is_email($cron_recipient)) { 829 $cron_recipient = get_settings('admin_email'); 830 } 831 echo __('Email backup to:') . ' <input type="text" name="cron_backup_recipient" size="20" value="' . $cron_recipient . '" />'; 832 echo '</td></tr>'; 833 $cron_tables = get_option('wp_cron_backup_tables'); 834 if (! is_array($cron_tables)) { 835 $cron_tables = array(); 836 } 837 if (count($other_tables) > 0) { 838 echo '<tr><td colspan="2" align="left">' . __('Tables to include:') . '<br />'; 839 foreach ($other_tables as $table) { 840 echo '<input type="checkbox" '; 841 if (in_array($table, $cron_tables)) { 842 echo 'checked=checked '; 843 } 844 echo "name='wp_cron_backup_tables[]' value='{$table}' /> {$table}<br />"; 845 } 846 echo '</td></tr>'; 847 } 848 echo '<tr><td colspan="2" align="center"><input type="hidden" name="wp_cron_backup_options" value="SET" /><input type="submit" name="submit" value="' . __('Submit') . '" /></td></tr></table></form>'; 849 echo '</fieldset>'; 850 } 851 // end of wp_cron section 852 853 echo '</div>'; 854 855 }// end wp_backup_menu() 856 857 ///////////////////////////// 858 function wp_cron_daily() { 859 860 $schedule = intval(get_option('wp_cron_backup_schedule')); 861 if (0 == $schedule) { 862 // Scheduled backup is disabled 863 return; 864 } 865 866 global $wpdb; 867 868 $wp_table_names = array_map(create_function('$a', 'global $wpdb;return "{$wpdb->prefix}{$a}";'), $this->wp_table_names); 869 $all_tables = $wpdb->get_results("SHOW TABLES", ARRAY_N); 870 $all_tables = array_map(create_function('$a', 'return $a[0];'), $all_tables); 871 $core_tables = array_intersect($all_tables, $wp_table_names); 872 $other_tables = get_option('wp_cron_backup_tables'); 873 874 $recipient = get_option('wp_cron_backup_recipient'); 875 876 $backup_file = $this->db_backup($core_tables, $other_tables); 877 if (FALSE !== $backup_file) { 878 $this->deliver_backup ($backup_file, 'smtp', $recipient); 879 } 880 881 return; 882 } // wp_cron_db_backup 883 } 884 885 function wpdbBackup_init() { 886 global $mywpdbbackup; 887 $mywpdbbackup = new wpdbBackup(); 888 } 889 890 add_action('plugins_loaded', 'wpdbBackup_init'); 891 892 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Sat Jul 15 11:57:04 2006 | Courtesy of Taragana |