source: trunk/www.guidonia.net/wp/wp-content/plugins/wp-db-backup/wp-db-backup.php@ 44

Last change on this file since 44 was 44, checked in by luciano, 15 years ago
File size: 52.8 KB
Line 
1<?php
2/*
3Plugin Name: WordPress Database Backup
4Plugin URI: http://www.ilfilosofo.com/blog/wp-db-backup
5Description: On-demand backup of your WordPress database. Navigate to <a href="edit.php?page=wp-db-backup">Tools &rarr; Backup</a> to get started.
6Author: Austin Matzko
7Author URI: http://www.ilfilosofo.com/
8Version: 2.2.2
9
10Development continued from that done by Skippy (http://www.skippy.net/)
11
12Originally modified from Mark Ghosh's One Click Backup, which
13in turn was derived from phpMyAdmin.
14
15Many thanks to Owen (http://asymptomatic.net/wp/) for his patch
16 http://dev.wp-plugins.org/ticket/219
17
18Copyright 2008 Austin Matzko (email : if.website at gmail.com)
19
20 This program is free software; you can redistribute it and/or modify
21 it under the terms of the GNU General Public License as published by
22 the Free Software Foundation; either version 2 of the License, or
23 (at your option) any later version.
24
25 This program is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
29
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
33*/
34
35/**
36 * Change WP_BACKUP_DIR if you want to
37 * use a different backup location
38 */
39
40$rand = substr( md5( md5( DB_PASSWORD ) ), -5 );
41global $wpdbb_content_dir, $wpdbb_content_url, $wpdbb_plugin_dir;
42$wpdbb_content_dir = ( defined('WP_CONTENT_DIR') ) ? WP_CONTENT_DIR : ABSPATH . 'wp-content';
43$wpdbb_content_url = ( defined('WP_CONTENT_URL') ) ? WP_CONTENT_URL : get_option('siteurl') . '/wp-content';
44$wpdbb_plugin_dir = ( defined('WP_PLUGIN_DIR') ) ? WP_PLUGIN_DIR : $wpdbb_content_dir . '/plugins';
45
46if ( ! defined('WP_BACKUP_DIR') ) {
47 define('WP_BACKUP_DIR', $wpdbb_content_dir . '/backup-' . $rand . '/');
48}
49
50if ( ! defined('WP_BACKUP_URL') ) {
51 define('WP_BACKUP_URL', $wpdbb_content_url . '/backup-' . $rand . '/');
52}
53
54if ( ! defined('ROWS_PER_SEGMENT') ) {
55 define('ROWS_PER_SEGMENT', 100);
56}
57
58/**
59 * Set MOD_EVASIVE_OVERRIDE to true
60 * and increase MOD_EVASIVE_DELAY
61 * if the backup stops prematurely.
62 */
63// define('MOD_EVASIVE_OVERRIDE', false);
64if ( ! defined('MOD_EVASIVE_DELAY') ) {
65 define('MOD_EVASIVE_DELAY', '500');
66}
67
68class wpdbBackup {
69
70 var $backup_complete = false;
71 var $backup_file = '';
72 var $backup_filename;
73 var $core_table_names = array();
74 var $errors = array();
75 var $basename;
76 var $page_url;
77 var $referer_check_key;
78 var $version = '2.1.5-alpha';
79
80 function gzip() {
81 return function_exists('gzopen');
82 }
83
84 function module_check() {
85 $mod_evasive = false;
86 if ( true === MOD_EVASIVE_OVERRIDE ) return true;
87 if ( false === MOD_EVASIVE_OVERRIDE ) return false;
88 if ( function_exists('apache_get_modules') )
89 foreach( (array) apache_get_modules() as $mod )
90 if ( false !== strpos($mod,'mod_evasive') || false !== strpos($mod,'mod_dosevasive') )
91 return true;
92 return false;
93 }
94
95 function wpdbBackup() {
96 global $table_prefix, $wpdb;
97 add_action('wp_ajax_save_backup_time', array(&$this, 'save_backup_time'));
98 add_action('init', array(&$this, 'init_textdomain'));
99 add_action('load-update-core.php', array(&$this, 'update_notice_action'));
100 add_action('wp_db_backup_cron', array(&$this, 'cron_backup'));
101 add_action('wp_cron_daily', array(&$this, 'wp_cron_daily'));
102 add_filter('cron_schedules', array(&$this, 'add_sched_options'));
103 add_filter('wp_db_b_schedule_choices', array(&$this, 'schedule_choices'));
104
105 $table_prefix = ( isset( $table_prefix ) ) ? $table_prefix : $wpdb->prefix;
106 $datum = date("Ymd_B");
107 $this->backup_filename = DB_NAME . "_$table_prefix$datum.sql";
108 if ($this->gzip()) $this->backup_filename .= '.gz';
109
110 $possible_names = array(
111 'categories',
112 'comments',
113 'link2cat',
114 'linkcategories',
115 'links',
116 'options',
117 'post2cat',
118 'postmeta',
119 'posts',
120 'terms',
121 'term_taxonomy',
122 'term_relationships',
123 'users',
124 'usermeta',
125 );
126
127 foreach( $possible_names as $name ) {
128 if ( isset( $wpdb->{$name} ) ) {
129 $this->core_table_names[] = $wpdb->{$name};
130 }
131 }
132
133 $this->backup_dir = trailingslashit(apply_filters('wp_db_b_backup_dir', WP_BACKUP_DIR));
134 $this->basename = 'wp-db-backup';
135
136 $this->referer_check_key = $this->basename . '-download_' . DB_NAME;
137 $query_args = array( 'page' => $this->basename );
138 if ( function_exists('wp_create_nonce') )
139 $query_args = array_merge( $query_args, array('_wpnonce' => wp_create_nonce($this->referer_check_key)) );
140 $base = ( function_exists('site_url') ) ? site_url('', 'admin') : get_option('siteurl');
141 $this->page_url = add_query_arg( $query_args, $base . '/wp-admin/edit.php');
142 if (isset($_POST['do_backup'])) {
143 $this->wp_secure('fatal');
144 check_admin_referer($this->referer_check_key);
145 $this->can_user_backup('main');
146 // save exclude prefs
147
148 $exc_revisions = (array) $_POST['exclude-revisions'];
149 $exc_spam = (array) $_POST['exclude-spam'];
150 update_option('wp_db_backup_excs', array('revisions' => $exc_revisions, 'spam' => $exc_spam));
151 switch($_POST['do_backup']) {
152 case 'backup':
153 add_action('init', array(&$this, 'perform_backup'));
154 break;
155 case 'fragments':
156 add_action('admin_menu', array(&$this, 'fragment_menu'));
157 break;
158 }
159 } elseif (isset($_GET['fragment'] )) {
160 $this->can_user_backup('frame');
161 add_action('init', array(&$this, 'init'));
162 } elseif (isset($_GET['backup'] )) {
163 $this->can_user_backup();
164 add_action('init', array(&$this, 'init'));
165 } else {
166 add_action('admin_menu', array(&$this, 'admin_menu'));
167 }
168 }
169
170 function init() {
171 $this->can_user_backup();
172 if (isset($_GET['backup'])) {
173 $via = isset($_GET['via']) ? $_GET['via'] : 'http';
174
175 $this->backup_file = $_GET['backup'];
176 $this->validate_file($this->backup_file);
177
178 switch($via) {
179 case 'smtp':
180 case 'email':
181 $success = $this->deliver_backup($this->backup_file, 'smtp', $_GET['recipient'], 'frame');
182 $this->error_display( 'frame' );
183 if ( $success ) {
184 echo '
185 <!-- ' . $via . ' -->
186 <script type="text/javascript"><!--\\
187 ';
188 echo '
189 alert("' . __('Backup Complete!','wp-db-backup') . '");
190 window.onbeforeunload = null;
191 </script>
192 ';
193 }
194 break;
195 default:
196 $this->deliver_backup($this->backup_file, $via);
197 $this->error_display( 'frame' );
198 }
199 die();
200 }
201 if (isset($_GET['fragment'] )) {
202 list($table, $segment, $filename) = explode(':', $_GET['fragment']);
203 $this->validate_file($filename);
204 $this->backup_fragment($table, $segment, $filename);
205 }
206
207 die();
208 }
209
210 function init_textdomain() {
211 load_plugin_textdomain('wp-db-backup', str_replace(ABSPATH, '', dirname(__FILE__)), dirname(plugin_basename(__FILE__)));
212 }
213
214 /*
215 * Add a link to back up your database when doing a core upgrade
216 */
217 function update_notice_action() {
218 if ( 'upgrade-core' == $_REQUEST['action'] ) :
219 ob_start(array(&$this, 'update_notice'));
220 add_action('admin_footer', create_function('', 'ob_end_flush();'));
221 endif;
222 }
223 function update_notice($text = '') {
224 $pattern = '#(<a href\="' . __('http://codex.wordpress.org/WordPress_Backups') . '">.*?</p>)#';
225 $replace = '$1' . "\n<p>" . sprintf(__('Click <a href="%s" target="_blank">here</a> to back up your database using the WordPress Database Backup plugin. <strong>Note:</strong> WordPress Database Backup does <em>not</em> back up your files, just your database.', 'wp-db-backup'), 'tools.php?page=wp-db-backup') . "</p>\n";
226 $text = preg_replace($pattern, $replace, $text);
227 return $text;
228 }
229
230 function build_backup_script() {
231 global $table_prefix, $wpdb;
232
233 echo "<div class='wrap'>";
234 echo '<fieldset class="options"><legend>' . __('Progress','wp-db-backup') . '</legend>
235 <p><strong>' .
236 __('DO NOT DO THE FOLLOWING AS IT WILL CAUSE YOUR BACKUP TO FAIL:','wp-db-backup').
237 '</strong></p>
238 <ol>
239 <li>'.__('Close this browser','wp-db-backup').'</li>
240 <li>'.__('Reload this page','wp-db-backup').'</li>
241 <li>'.__('Click the Stop or Back buttons in your browser','wp-db-backup').'</li>
242 </ol>
243 <p><strong>' . __('Progress:','wp-db-backup') . '</strong></p>
244 <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;">&nbsp;</div></div>
245 <div id="progress_message"></div>
246 <div id="errors"></div>
247 </fieldset>
248 <iframe id="backuploader" src="about:blank" style="visibility:hidden;border:none;height:1em;width:1px;"></iframe>
249 <script type="text/javascript">
250 //<![CDATA[
251 window.onbeforeunload = function() {
252 return "' . __('Navigating away from this page will cause your backup to fail.', 'wp-db-backup') . '";
253 }
254 function setMeter(pct) {
255 var meter = document.getElementById("meter");
256 meter.style.width = pct + "%";
257 meter.innerHTML = Math.floor(pct) + "%";
258 }
259 function setProgress(str) {
260 var progress = document.getElementById("progress_message");
261 progress.innerHTML = str;
262 }
263 function addError(str) {
264 var errors = document.getElementById("errors");
265 errors.innerHTML = errors.innerHTML + str + "<br />";
266 }
267
268 function backup(table, segment) {
269 var fram = document.getElementById("backuploader");
270 fram.src = "' . $this->page_url . '&fragment=" + table + ":" + segment + ":' . $this->backup_filename . ':";
271 }
272
273 var curStep = 0;
274
275 function nextStep() {
276 backupStep(curStep);
277 curStep++;
278 }
279
280 function finishBackup() {
281 var fram = document.getElementById("backuploader");
282 setMeter(100);
283 ';
284
285 $download_uri = add_query_arg('backup', $this->backup_filename, $this->page_url);
286 switch($_POST['deliver']) {
287 case 'http':
288 echo '
289 setProgress("' . sprintf(__("Backup complete, preparing <a href=\\\"%s\\\">backup</a> for download...",'wp-db-backup'), $download_uri) . '");
290 window.onbeforeunload = null;
291 fram.src = "' . $download_uri . '";
292 ';
293 break;
294 case 'smtp':
295 echo '
296 setProgress("' . sprintf(__("Backup complete, sending <a href=\\\"%s\\\">backup</a> via email...",'wp-db-backup'), $download_uri) . '");
297 window.onbeforeunload = null;
298 fram.src = "' . $download_uri . '&via=email&recipient=' . $_POST['backup_recipient'] . '";
299 ';
300 break;
301 default:
302 echo '
303 setProgress("' . sprintf(__("Backup complete, download <a href=\\\"%s\\\">here</a>.",'wp-db-backup'), $download_uri) . '");
304 window.onbeforeunload = null;
305 ';
306 }
307
308 echo '
309 }
310
311 function backupStep(step) {
312 switch(step) {
313 case 0: backup("", 0); break;
314 ';
315
316 $also_backup = array();
317 if (isset($_POST['other_tables'])) {
318 $also_backup = $_POST['other_tables'];
319 } else {
320 $also_backup = array();
321 }
322 $core_tables = $_POST['core_tables'];
323 $tables = array_merge($core_tables, $also_backup);
324 $step_count = 1;
325 foreach ($tables as $table) {
326 $rec_count = $wpdb->get_var("SELECT count(*) FROM {$table}");
327 $rec_segments = ceil($rec_count / ROWS_PER_SEGMENT);
328 $table_count = 0;
329 if ( $this->module_check() ) {
330 $delay = "setTimeout('";
331 $delay_time = "', " . (int) MOD_EVASIVE_DELAY . ")";
332 }
333 else { $delay = $delay_time = ''; }
334 do {
335 echo "case {$step_count}: {$delay}backup(\"{$table}\", {$table_count}){$delay_time}; break;\n";
336 $step_count++;
337 $table_count++;
338 } while($table_count < $rec_segments);
339 echo "case {$step_count}: {$delay}backup(\"{$table}\", -1){$delay_time}; break;\n";
340 $step_count++;
341 }
342 echo "case {$step_count}: finishBackup(); break;";
343
344 echo '
345 }
346 if(step != 0) setMeter(100 * step / ' . $step_count . ');
347 }
348
349 nextStep();
350 // ]]>
351 </script>
352 </div>
353 ';
354 $this->backup_menu();
355 }
356
357 function backup_fragment($table, $segment, $filename) {
358 global $table_prefix, $wpdb;
359
360 echo "$table:$segment:$filename";
361
362 if($table == '') {
363 $msg = __('Creating backup file...','wp-db-backup');
364 } else {
365 if($segment == -1) {
366 $msg = sprintf(__('Finished backing up table \\"%s\\".','wp-db-backup'), $table);
367 } else {
368 $msg = sprintf(__('Backing up table \\"%s\\"...','wp-db-backup'), $table);
369 }
370 }
371
372 if (is_writable($this->backup_dir)) {
373 $this->fp = $this->open($this->backup_dir . $filename, 'a');
374 if(!$this->fp) {
375 $this->error(__('Could not open the backup file for writing!','wp-db-backup'));
376 $this->error(array('loc' => 'frame', 'kind' => 'fatal', 'msg' => __('The backup file could not be saved. Please check the permissions for writing to your backup directory and try again.','wp-db-backup')));
377 }
378 else {
379 if($table == '') {
380 //Begin new backup of MySql
381 $this->stow("# " . __('WordPress MySQL database backup','wp-db-backup') . "\n");
382 $this->stow("#\n");
383 $this->stow("# " . sprintf(__('Generated: %s','wp-db-backup'),date("l j. F Y H:i T")) . "\n");
384 $this->stow("# " . sprintf(__('Hostname: %s','wp-db-backup'),DB_HOST) . "\n");
385 $this->stow("# " . sprintf(__('Database: %s','wp-db-backup'),$this->backquote(DB_NAME)) . "\n");
386 $this->stow("# --------------------------------------------------------\n");
387 } else {
388 if($segment == 0) {
389 // Increase script execution time-limit to 15 min for every table.
390 if ( !ini_get('safe_mode')) @set_time_limit(15*60);
391 // Create the SQL statements
392 $this->stow("# --------------------------------------------------------\n");
393 $this->stow("# " . sprintf(__('Table: %s','wp-db-backup'),$this->backquote($table)) . "\n");
394 $this->stow("# --------------------------------------------------------\n");
395 }
396 $this->backup_table($table, $segment);
397 }
398 }
399 } else {
400 $this->error(array('kind' => 'fatal', 'loc' => 'frame', 'msg' => __('The backup directory is not writeable! Please check the permissions for writing to your backup directory and try again.','wp-db-backup')));
401 }
402
403 if($this->fp) $this->close($this->fp);
404
405 $this->error_display('frame');
406
407 echo '<script type="text/javascript"><!--//
408 var msg = "' . $msg . '";
409 window.parent.setProgress(msg);
410 window.parent.nextStep();
411 //--></script>
412 ';
413 die();
414 }
415
416 function perform_backup() {
417 // are we backing up any other tables?
418 $also_backup = array();
419 if (isset($_POST['other_tables']))
420 $also_backup = $_POST['other_tables'];
421 $core_tables = $_POST['core_tables'];
422 $this->backup_file = $this->db_backup($core_tables, $also_backup);
423 if (false !== $this->backup_file) {
424 if ('smtp' == $_POST['deliver']) {
425 $this->deliver_backup($this->backup_file, $_POST['deliver'], $_POST['backup_recipient'], 'main');
426 wp_redirect($this->page_url);
427 } elseif ('http' == $_POST['deliver']) {
428 $download_uri = add_query_arg('backup',$this->backup_file,$this->page_url);
429 wp_redirect($download_uri);
430 exit;
431 }
432 // we do this to say we're done.
433 $this->backup_complete = true;
434 }
435 }
436
437 function admin_header() {
438 ?>
439 <script type="text/javascript">
440 //<![CDATA[
441 if ( 'undefined' != typeof addLoadEvent ) {
442 addLoadEvent(function() {
443 var t = {'extra-tables-list':{name: 'other_tables[]'}, 'include-tables-list':{name: 'wp_cron_backup_tables[]'}};
444
445 for ( var k in t ) {
446 t[k].s = null;
447 var d = document.getElementById(k);
448 if ( ! d )
449 continue;
450 var ul = d.getElementsByTagName('ul').item(0);
451 if ( ul ) {
452 var lis = ul.getElementsByTagName('li');
453 if ( 3 > lis.length )
454 return;
455 var text = document.createElement('p');
456 text.className = 'instructions';
457 text.innerHTML = '<?php _e('Click and hold down <code>[SHIFT]</code> to toggle multiple checkboxes', 'wp-db-backup'); ?>';
458 ul.parentNode.insertBefore(text, ul);
459 }
460 t[k].p = d.getElementsByTagName("input");
461 for(var i=0; i < t[k].p.length; i++)
462 if(t[k].name == t[k].p[i].getAttribute('name')) {
463 t[k].p[i].id = k + '-table-' + i;
464 t[k].p[i].onkeyup = t[k].p[i].onclick = function(e) {
465 e = e ? e : event;
466 if ( 16 == e.keyCode )
467 return;
468 var match = /([\w-]*)-table-(\d*)/.exec(this.id);
469 var listname = match[1];
470 var that = match[2];
471 if ( null === t[listname].s )
472 t[listname].s = that;
473 else if ( e.shiftKey ) {
474 var start = Math.min(that, t[listname].s) + 1;
475 var end = Math.max(that, t[listname].s);
476 for( var j=start; j < end; j++)
477 t[listname].p[j].checked = t[listname].p[j].checked ? false : true;
478 t[listname].s = null;
479 }
480 }
481 }
482 }
483
484 <?php if ( function_exists('wp_schedule_event') ) : // needs to be at least WP 2.1 for ajax ?>
485 if ( 'undefined' == typeof XMLHttpRequest )
486 var xml = new ActiveXObject( navigator.userAgent.indexOf('MSIE 5') >= 0 ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP' );
487 else
488 var xml = new XMLHttpRequest();
489
490 var initTimeChange = function() {
491 var timeWrap = document.getElementById('backup-time-wrap');
492 var backupTime = document.getElementById('next-backup-time');
493 if ( !! timeWrap && !! backupTime ) {
494 var span = document.createElement('span');
495 span.className = 'submit';
496 span.id = 'change-wrap';
497 span.innerHTML = '<input type="submit" id="change-backup-time" name="change-backup-time" value="<?php _e('Change','wp-db-backup'); ?>" />';
498 timeWrap.appendChild(span);
499 backupTime.ondblclick = function(e) { span.parentNode.removeChild(span); clickTime(e, backupTime); };
500 span.onclick = function(e) { span.parentNode.removeChild(span); clickTime(e, backupTime); };
501 }
502 }
503
504 var clickTime = function(e, backupTime) {
505 var tText = backupTime.innerHTML;
506 backupTime.innerHTML = '<input type="text" value="' + tText + '" name="backup-time-text" id="backup-time-text" /> <span class="submit"><input type="submit" name="save-backup-time" id="save-backup-time" value="<?php _e('Save', 'wp-db-backup'); ?>" /></span>';
507 backupTime.ondblclick = null;
508 var mainText = document.getElementById('backup-time-text');
509 mainText.focus();
510 var saveTButton = document.getElementById('save-backup-time');
511 if ( !! saveTButton )
512 saveTButton.onclick = function(e) { saveTime(backupTime, mainText); return false; };
513 if ( !! mainText )
514 mainText.onkeydown = function(e) {
515 e = e || window.event;
516 if ( 13 == e.keyCode ) {
517 saveTime(backupTime, mainText);
518 return false;
519 }
520 }
521 }
522
523 var saveTime = function(backupTime, mainText) {
524 var tVal = mainText.value;
525
526 xml.open('POST', 'admin-ajax.php', true);
527 xml.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
528 if ( xml.overrideMimeType )
529 xml.setRequestHeader('Connection', 'close');
530 xml.send('action=save_backup_time&_wpnonce=<?php echo wp_create_nonce($this->referer_check_key); ?>&backup-time='+tVal);
531 xml.onreadystatechange = function() {
532 if ( 4 == xml.readyState && '0' != xml.responseText ) {
533 backupTime.innerHTML = xml.responseText;
534 initTimeChange();
535 }
536 }
537 }
538
539 initTimeChange();
540 <?php endif; // wp_schedule_event exists ?>
541 });
542 }
543 //]]>
544 </script>
545 <style type="text/css">
546 .wp-db-backup-updated {
547 margin-top: 1em;
548 }
549
550 fieldset.options {
551 border: 1px solid;
552 margin-top: 1em;
553 padding: 1em;
554 }
555 fieldset.options div.tables-list {
556 float: left;
557 padding: 1em;
558 }
559
560 fieldset.options input {
561 }
562
563 fieldset.options legend {
564 font-size: larger;
565 font-weight: bold;
566 margin-bottom: .5em;
567 padding: 1em;
568 }
569
570 fieldset.options .instructions {
571 font-size: smaller;
572 }
573
574 fieldset.options ul {
575 list-style-type: none;
576 }
577 fieldset.options li {
578 text-align: left;
579 }
580
581 fieldset.options .submit {
582 border-top: none;
583 }
584 </style>
585 <?php
586 }
587
588 function admin_load() {
589 add_action('admin_head', array(&$this, 'admin_header'));
590 }
591
592 function admin_menu() {
593 $_page_hook = add_management_page(__('Backup','wp-db-backup'), __('Backup','wp-db-backup'), 'import', $this->basename, array(&$this, 'backup_menu'));
594 add_action('load-' . $_page_hook, array(&$this, 'admin_load'));
595 if ( function_exists('add_contextual_help') ) {
596 $text = $this->help_menu();
597 add_contextual_help($_page_hook, $text);
598 }
599 }
600
601 function fragment_menu() {
602 $page_hook = add_management_page(__('Backup','wp-db-backup'), __('Backup','wp-db-backup'), 'import', $this->basename, array(&$this, 'build_backup_script'));
603 add_action('load-' . $page_hook, array(&$this, 'admin_load'));
604 }
605
606 /**
607 * Add WP-DB-Backup-specific help options to the 2.7 =< WP contextual help menu
608 * return string The text of the help menu.
609 */
610 function help_menu() {
611 $text = "\n<a href=\"http://wordpress.org/extend/plugins/wp-db-backup/faq/\" target=\"_blank\">" . __('FAQ', 'wp-db-backup') . '</a>';
612 $text .= "\n<br />\n<a href=\"http://www.ilfilosofo.com/forum/forum/2\" target=\"_blank\">" . __('WP-DB-Backup Support Forum', 'wp-db-backup') . '</a>';
613 return $text;
614 }
615
616 function save_backup_time() {
617 if ( $this->can_user_backup() ) {
618 // try to get a time from the input string
619 $time = strtotime(strval($_POST['backup-time']));
620 if ( ! empty( $time ) && time() < $time ) {
621 wp_clear_scheduled_hook( 'wp_db_backup_cron' ); // unschedule previous
622 $scheds = (array) wp_get_schedules();
623 $name = get_option('wp_cron_backup_schedule');
624 if ( 0 != $time ) {
625 wp_schedule_event($time, $name, 'wp_db_backup_cron');
626 echo gmdate(get_option('date_format') . ' ' . get_option('time_format'), $time + (get_option('gmt_offset') * 3600));
627 exit;
628 }
629 }
630 } else {
631 die(0);
632 }
633 }
634
635 /**
636 * Better addslashes for SQL queries.
637 * Taken from phpMyAdmin.
638 */
639 function sql_addslashes($a_string = '', $is_like = false) {
640 if ($is_like) $a_string = str_replace('\\', '\\\\\\\\', $a_string);
641 else $a_string = str_replace('\\', '\\\\', $a_string);
642 return str_replace('\'', '\\\'', $a_string);
643 }
644
645 /**
646 * Add backquotes to tables and db-names in
647 * SQL queries. Taken from phpMyAdmin.
648 */
649 function backquote($a_name) {
650 if (!empty($a_name) && $a_name != '*') {
651 if (is_array($a_name)) {
652 $result = array();
653 reset($a_name);
654 while(list($key, $val) = each($a_name))
655 $result[$key] = '`' . $val . '`';
656 return $result;
657 } else {
658 return '`' . $a_name . '`';
659 }
660 } else {
661 return $a_name;
662 }
663 }
664
665 function open($filename = '', $mode = 'w') {
666 if ('' == $filename) return false;
667 if ($this->gzip())
668 $fp = @gzopen($filename, $mode);
669 else
670 $fp = @fopen($filename, $mode);
671 return $fp;
672 }
673
674 function close($fp) {
675 if ($this->gzip()) gzclose($fp);
676 else fclose($fp);
677 }
678
679 /**
680 * Write to the backup file
681 * @param string $query_line the line to write
682 * @return null
683 */
684 function stow($query_line) {
685 if ($this->gzip()) {
686 if(! @gzwrite($this->fp, $query_line))
687 $this->error(__('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg);
688 } else {
689 if(false === @fwrite($this->fp, $query_line))
690 $this->error(__('There was an error writing a line to the backup script:','wp-db-backup') . ' ' . $query_line . ' ' . $php_errormsg);
691 }
692 }
693
694 /**
695 * Logs any error messages
696 * @param array $args
697 * @return bool
698 */
699 function error($args = array()) {
700 if ( is_string( $args ) )
701 $args = array('msg' => $args);
702 $args = array_merge( array('loc' => 'main', 'kind' => 'warn', 'msg' => ''), $args);
703 $this->errors[$args['kind']][] = $args['msg'];
704 if ( 'fatal' == $args['kind'] || 'frame' == $args['loc'])
705 $this->error_display($args['loc']);
706 return true;
707 }
708
709 /**
710 * Displays error messages
711 * @param array $errs
712 * @param string $loc
713 * @return string
714 */
715 function error_display($loc = 'main', $echo = true) {
716 $errs = $this->errors;
717 unset( $this->errors );
718 if ( ! count($errs) ) return;
719 $msg = '';
720 $err_list = array_slice(array_merge( (array) $errs['fatal'], (array) $errs['warn']), 0, 10);
721 if ( 10 == count( $err_list ) )
722 $err_list[9] = __('Subsequent errors have been omitted from this log.','wp-db-backup');
723 $wrap = ( 'frame' == $loc ) ? "<script type=\"text/javascript\">\n var msgList = ''; \n %1\$s \n if ( msgList ) alert(msgList); \n </script>" : '%1$s';
724 $line = ( 'frame' == $loc ) ?
725 "try{ window.parent.addError('%1\$s'); } catch(e) { msgList += ' %1\$s';}\n" :
726 "%1\$s<br />\n";
727 foreach( (array) $err_list as $err )
728 $msg .= sprintf($line,str_replace(array("\n","\r"), '', addslashes($err)));
729 $msg = sprintf($wrap,$msg);
730 if ( count($errs['fatal'] ) ) {
731 if ( function_exists('wp_die') && 'frame' != $loc ) wp_die(stripslashes($msg));
732 else die($msg);
733 }
734 else {
735 if ( $echo ) echo $msg;
736 else return $msg;
737 }
738 }
739
740 /**
741 * Taken partially from phpMyAdmin and partially from
742 * Alain Wolf, Zurich - Switzerland
743 * Website: http://restkultur.ch/personal/wolf/scripts/db_backup/
744
745 * Modified by Scott Merrill (http://www.skippy.net/)
746 * to use the WordPress $wpdb object
747 * @param string $table
748 * @param string $segment
749 * @return void
750 */
751 function backup_table($table, $segment = 'none') {
752 global $wpdb;
753
754 $table_structure = $wpdb->get_results("DESCRIBE $table");
755 if (! $table_structure) {
756 $this->error(__('Error getting table details','wp-db-backup') . ": $table");
757 return false;
758 }
759
760 if(($segment == 'none') || ($segment == 0)) {
761 // Add SQL statement to drop existing table
762 $this->stow("\n\n");
763 $this->stow("#\n");
764 $this->stow("# " . sprintf(__('Delete any existing table %s','wp-db-backup'),$this->backquote($table)) . "\n");
765 $this->stow("#\n");
766 $this->stow("\n");
767 $this->stow("DROP TABLE IF EXISTS " . $this->backquote($table) . ";\n");
768
769 // Table structure
770 // Comment in SQL-file
771 $this->stow("\n\n");
772 $this->stow("#\n");
773 $this->stow("# " . sprintf(__('Table structure of table %s','wp-db-backup'),$this->backquote($table)) . "\n");
774 $this->stow("#\n");
775 $this->stow("\n");
776
777 $create_table = $wpdb->get_results("SHOW CREATE TABLE $table", ARRAY_N);
778 if (false === $create_table) {
779 $err_msg = sprintf(__('Error with SHOW CREATE TABLE for %s.','wp-db-backup'), $table);
780 $this->error($err_msg);
781 $this->stow("#\n# $err_msg\n#\n");
782 }
783 $this->stow($create_table[0][1] . ' ;');
784
785 if (false === $table_structure) {
786 $err_msg = sprintf(__('Error getting table structure of %s','wp-db-backup'), $table);
787 $this->error($err_msg);
788 $this->stow("#\n# $err_msg\n#\n");
789 }
790
791 // Comment in SQL-file
792 $this->stow("\n\n");
793 $this->stow("#\n");
794 $this->stow('# ' . sprintf(__('Data contents of table %s','wp-db-backup'),$this->backquote($table)) . "\n");
795 $this->stow("#\n");
796 }
797
798 if(($segment == 'none') || ($segment >= 0)) {
799 $defs = array();
800 $ints = array();
801 foreach ($table_structure as $struct) {
802 if ( (0 === strpos($struct->Type, 'tinyint')) ||
803 (0 === strpos(strtolower($struct->Type), 'smallint')) ||
804 (0 === strpos(strtolower($struct->Type), 'mediumint')) ||
805 (0 === strpos(strtolower($struct->Type), 'int')) ||
806 (0 === strpos(strtolower($struct->Type), 'bigint')) ) {
807 $defs[strtolower($struct->Field)] = ( null === $struct->Default ) ? 'NULL' : $struct->Default;
808 $ints[strtolower($struct->Field)] = "1";
809 }
810 }
811
812
813 // Batch by $row_inc
814
815 if($segment == 'none') {
816 $row_start = 0;
817 $row_inc = ROWS_PER_SEGMENT;
818 } else {
819 $row_start = $segment * ROWS_PER_SEGMENT;
820 $row_inc = ROWS_PER_SEGMENT;
821 }
822
823 do {
824 // don't include extra stuff, if so requested
825 $excs = (array) get_option('wp_db_backup_excs');
826 $where = '';
827 if ( is_array($excs['spam'] ) && in_array($table, $excs['spam']) ) {
828 $where = ' WHERE comment_approved != "spam"';
829 } elseif ( is_array($excs['revisions'] ) && in_array($table, $excs['revisions']) ) {
830 $where = ' WHERE post_type != "revision"';
831 }
832
833 if ( !ini_get('safe_mode')) @set_time_limit(15*60);
834 $table_data = $wpdb->get_results("SELECT * FROM $table $where LIMIT {$row_start}, {$row_inc}", ARRAY_A);
835
836 $entries = 'INSERT INTO ' . $this->backquote($table) . ' VALUES (';
837 // \x08\\x09, not required
838 $search = array("\x00", "\x0a", "\x0d", "\x1a");
839 $replace = array('\0', '\n', '\r', '\Z');
840 if($table_data) {
841 foreach ($table_data as $row) {
842 $values = array();
843 foreach ($row as $key => $value) {
844 if ($ints[strtolower($key)]) {
845 // make sure there are no blank spots in the insert syntax,
846 // yet try to avoid quotation marks around integers
847 $value = ( null === $value || '' === $value) ? $defs[strtolower($key)] : $value;
848 $values[] = ( '' === $value ) ? "''" : $value;
849 } else {
850 $values[] = "'" . str_replace($search, $replace, $this->sql_addslashes($value)) . "'";
851 }
852 }
853 $this->stow(" \n" . $entries . implode(', ', $values) . ');');
854 }
855 $row_start += $row_inc;
856 }
857 } while((count($table_data) > 0) and ($segment=='none'));
858 }
859
860 if(($segment == 'none') || ($segment < 0)) {
861 // Create footer/closing comment in SQL-file
862 $this->stow("\n");
863 $this->stow("#\n");
864 $this->stow("# " . sprintf(__('End of data contents of table %s','wp-db-backup'),$this->backquote($table)) . "\n");
865 $this->stow("# --------------------------------------------------------\n");
866 $this->stow("\n");
867 }
868 } // end backup_table()
869
870 function db_backup($core_tables, $other_tables) {
871 global $table_prefix, $wpdb;
872
873 if (is_writable($this->backup_dir)) {
874 $this->fp = $this->open($this->backup_dir . $this->backup_filename);
875 if(!$this->fp) {
876 $this->error(__('Could not open the backup file for writing!','wp-db-backup'));
877 return false;
878 }
879 } else {
880 $this->error(__('The backup directory is not writeable!','wp-db-backup'));
881 return false;
882 }
883
884 //Begin new backup of MySql
885 $this->stow("# " . __('WordPress MySQL database backup','wp-db-backup') . "\n");
886 $this->stow("#\n");
887 $this->stow("# " . sprintf(__('Generated: %s','wp-db-backup'),date("l j. F Y H:i T")) . "\n");
888 $this->stow("# " . sprintf(__('Hostname: %s','wp-db-backup'),DB_HOST) . "\n");
889 $this->stow("# " . sprintf(__('Database: %s','wp-db-backup'),$this->backquote(DB_NAME)) . "\n");
890 $this->stow("# --------------------------------------------------------\n");
891
892 if ( (is_array($other_tables)) && (count($other_tables) > 0) )
893 $tables = array_merge($core_tables, $other_tables);
894 else
895 $tables = $core_tables;
896
897 foreach ($tables as $table) {
898 // Increase script execution time-limit to 15 min for every table.
899 if ( !ini_get('safe_mode')) @set_time_limit(15*60);
900 // Create the SQL statements
901 $this->stow("# --------------------------------------------------------\n");
902 $this->stow("# " . sprintf(__('Table: %s','wp-db-backup'),$this->backquote($table)) . "\n");
903 $this->stow("# --------------------------------------------------------\n");
904 $this->backup_table($table);
905 }
906
907 $this->close($this->fp);
908
909 if (count($this->errors)) {
910 return false;
911 } else {
912 return $this->backup_filename;
913 }
914
915 } //wp_db_backup
916
917 /**
918 * Sends the backed-up file via email
919 * @param string $to
920 * @param string $subject
921 * @param string $message
922 * @return bool
923 */
924 function send_mail( $to, $subject, $message, $diskfile) {
925 global $phpmailer;
926
927 $filename = basename($diskfile);
928
929 extract( apply_filters( 'wp_mail', compact( 'to', 'subject', 'message' ) ) );
930
931 if ( !is_object( $phpmailer ) || ( strtolower(get_class( $phpmailer )) != 'phpmailer' ) ) {
932 if ( file_exists( ABSPATH . WPINC . '/class-phpmailer.php' ) )
933 require_once ABSPATH . WPINC . '/class-phpmailer.php';
934 if ( file_exists( ABSPATH . WPINC . '/class-smtp.php' ) )
935 require_once ABSPATH . WPINC . '/class-smtp.php';
936 if ( class_exists( 'PHPMailer') )
937 $phpmailer = new PHPMailer();
938 }
939
940 // try to use phpmailer directly (WP 2.2+)
941 if ( is_object( $phpmailer ) && ( strtolower(get_class( $phpmailer )) == 'phpmailer' ) ) {
942
943 // Get the site domain and get rid of www.
944 $sitename = strtolower( $_SERVER['SERVER_NAME'] );
945 if ( substr( $sitename, 0, 4 ) == 'www.' ) {
946 $sitename = substr( $sitename, 4 );
947 }
948 $from_email = 'wordpress@' . $sitename;
949 $from_name = 'WordPress';
950
951 // Empty out the values that may be set
952 $phpmailer->ClearAddresses();
953 $phpmailer->ClearAllRecipients();
954 $phpmailer->ClearAttachments();
955 $phpmailer->ClearBCCs();
956 $phpmailer->ClearCCs();
957 $phpmailer->ClearCustomHeaders();
958 $phpmailer->ClearReplyTos();
959
960 $phpmailer->AddAddress( $to );
961 $phpmailer->AddAttachment($diskfile, $filename);
962 $phpmailer->Body = $message;
963 $phpmailer->CharSet = apply_filters( 'wp_mail_charset', get_bloginfo('charset') );
964 $phpmailer->From = apply_filters( 'wp_mail_from', $from_email );
965 $phpmailer->FromName = apply_filters( 'wp_mail_from_name', $from_name );
966 $phpmailer->IsMail();
967 $phpmailer->Subject = $subject;
968
969 do_action_ref_array( 'phpmailer_init', array( &$phpmailer ) );
970
971 $result = @$phpmailer->Send();
972
973 // old-style: build the headers directly
974 } else {
975 $randomish = md5(time());
976 $boundary = "==WPBACKUP-$randomish";
977 $fp = fopen($diskfile,"rb");
978 $file = fread($fp,filesize($diskfile));
979 $this->close($fp);
980
981 $data = chunk_split(base64_encode($file));
982
983 $headers .= "MIME-Version: 1.0\n";
984 $headers = 'From: wordpress@' . preg_replace('#^www\.#', '', strtolower($_SERVER['SERVER_NAME'])) . "\n";
985 $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\n";
986
987 // Add a multipart boundary above the plain message
988 $message = "This is a multi-part message in MIME format.\n\n" .
989 "--{$boundary}\n" .
990 "Content-Type: text/plain; charset=\"" . get_bloginfo('charset') . "\"\n" .
991 "Content-Transfer-Encoding: 7bit\n\n" .
992 $message . "\n\n";
993
994 // Add file attachment to the message
995 $message .= "--{$boundary}\n" .
996 "Content-Type: application/octet-stream;\n" .
997 " name=\"{$filename}\"\n" .
998 "Content-Disposition: attachment;\n" .
999 " filename=\"{$filename}\"\n" .
1000 "Content-Transfer-Encoding: base64\n\n" .
1001 $data . "\n\n" .
1002 "--{$boundary}--\n";
1003
1004 $result = @wp_mail($to, $subject, $message, $headers);
1005 }
1006 return $result;
1007
1008 }
1009
1010 function deliver_backup($filename = '', $delivery = 'http', $recipient = '', $location = 'main') {
1011 if ('' == $filename) { return false; }
1012
1013 $diskfile = $this->backup_dir . $filename;
1014 if ('http' == $delivery) {
1015 if (! file_exists($diskfile))
1016 $this->error(array('kind' => 'fatal', 'msg' => sprintf(__('File not found:%s','wp-db-backup'), "&nbsp;<strong>$filename</strong><br />") . '<br /><a href="' . $this->page_url . '">' . __('Return to Backup','wp-db-backup') . '</a>'));
1017 header('Content-Description: File Transfer');
1018 header('Content-Type: application/octet-stream');
1019 header('Content-Length: ' . filesize($diskfile));
1020 header("Content-Disposition: attachment; filename=$filename");
1021 $success = readfile($diskfile);
1022 unlink($diskfile);
1023 } elseif ('smtp' == $delivery) {
1024 if (! file_exists($diskfile)) {
1025 $msg = sprintf(__('File %s does not exist!','wp-db-backup'), $diskfile);
1026 $this->error($msg);
1027 return false;
1028 }
1029 if (! is_email($recipient)) {
1030 $recipient = get_option('admin_email');
1031 }
1032 $message = sprintf(__("Attached to this email is\n %1s\n Size:%2s kilobytes\n",'wp-db-backup'), $filename, round(filesize($diskfile)/1024));
1033 $success = $this->send_mail($recipient, get_bloginfo('name') . ' ' . __('Database Backup','wp-db-backup'), $message, $diskfile);
1034
1035 if ( false === $success ) {
1036 $msg = __('The following errors were reported:','wp-db-backup') . "\n ";
1037 if ( function_exists('error_get_last') ) {
1038 $err = error_get_last();
1039 $msg .= $err['message'];
1040 } else {
1041 $msg .= __('ERROR: The mail application has failed to deliver the backup.','wp-db-backup');
1042 }
1043 $this->error(array('kind' => 'fatal', 'loc' => $location, 'msg' => $msg));
1044 } else {
1045 unlink($diskfile);
1046 }
1047 }
1048 return $success;
1049 }
1050
1051 function backup_menu() {
1052 global $table_prefix, $wpdb;
1053 $feedback = '';
1054 $whoops = false;
1055
1056 // did we just do a backup? If so, let's report the status
1057 if ( $this->backup_complete ) {
1058 $feedback = '<div class="updated wp-db-backup-updated"><p>' . __('Backup Successful','wp-db-backup') . '!';
1059 $file = $this->backup_file;
1060 switch($_POST['deliver']) {
1061 case 'http':
1062 $feedback .= '<br />' . sprintf(__('Your backup file: <a href="%1s">%2s</a> should begin downloading shortly.','wp-db-backup'), WP_BACKUP_URL . "{$this->backup_file}", $this->backup_file);
1063 break;
1064 case 'smtp':
1065 if (! is_email($_POST['backup_recipient'])) {
1066 $feedback .= get_option('admin_email');
1067 } else {
1068 $feedback .= $_POST['backup_recipient'];
1069 }
1070 $feedback = '<br />' . sprintf(__('Your backup has been emailed to %s','wp-db-backup'), $feedback);
1071 break;
1072 case 'none':
1073 $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"','wp-db-backup');
1074 $feedback .= ':<br /> <a href="' . WP_BACKUP_URL . "$file\">$file</a> : " . sprintf(__('%s bytes','wp-db-backup'), filesize($this->backup_dir . $file));
1075 }
1076 $feedback .= '</p></div>';
1077 }
1078
1079 // security check
1080 $this->wp_secure();
1081
1082 if (count($this->errors)) {
1083 $feedback .= '<div class="updated wp-db-backup-updated error"><p><strong>' . __('The following errors were reported:','wp-db-backup') . '</strong></p>';
1084 $feedback .= '<p>' . $this->error_display( 'main', false ) . '</p>';
1085 $feedback .= "</p></div>";
1086 }
1087
1088 // did we just save options for wp-cron?
1089 if ( (function_exists('wp_schedule_event') || function_exists('wp_cron_init'))
1090 && isset($_POST['wp_cron_backup_options']) ) :
1091 do_action('wp_db_b_update_cron_options');
1092 if ( function_exists('wp_schedule_event') ) {
1093 wp_clear_scheduled_hook( 'wp_db_backup_cron' ); // unschedule previous
1094 $scheds = (array) wp_get_schedules();
1095 $name = strval($_POST['wp_cron_schedule']);
1096 $interval = ( isset($scheds[$name]['interval']) ) ?
1097 (int) $scheds[$name]['interval'] : 0;
1098 update_option('wp_cron_backup_schedule', $name, false);
1099 if ( 0 !== $interval ) {
1100 wp_schedule_event(time() + $interval, $name, 'wp_db_backup_cron');
1101 }
1102 }
1103 else {
1104 update_option('wp_cron_backup_schedule', intval($_POST['cron_schedule']), false);
1105 }
1106 update_option('wp_cron_backup_tables', $_POST['wp_cron_backup_tables']);
1107 if (is_email($_POST['cron_backup_recipient'])) {
1108 update_option('wp_cron_backup_recipient', $_POST['cron_backup_recipient'], false);
1109 }
1110 $feedback .= '<div class="updated wp-db-backup-updated"><p>' . __('Scheduled Backup Options Saved!','wp-db-backup') . '</p></div>';
1111 endif;
1112
1113 $other_tables = array();
1114 $also_backup = array();
1115
1116 // Get complete db table list
1117 $all_tables = $wpdb->get_results("SHOW TABLES", ARRAY_N);
1118 $all_tables = array_map(create_function('$a', 'return $a[0];'), $all_tables);
1119 // Get list of WP tables that actually exist in this DB (for 1.6 compat!)
1120 $wp_backup_default_tables = array_intersect($all_tables, $this->core_table_names);
1121 // Get list of non-WP tables
1122 $other_tables = array_diff($all_tables, $wp_backup_default_tables);
1123
1124 if ('' != $feedback)
1125 echo $feedback;
1126
1127 if ( ! $this->wp_secure() )
1128 return;
1129
1130 // Give the new dirs the same perms as wp-content.
1131// $stat = stat( ABSPATH . 'wp-content' );
1132// $dir_perms = $stat['mode'] & 0000777; // Get the permission bits.
1133 $dir_perms = '0777';
1134
1135 // the file doesn't exist and can't create it
1136 if ( ! file_exists($this->backup_dir) && ! @mkdir($this->backup_dir) ) {
1137 ?><div class="updated wp-db-backup-updated error"><p><?php _e('WARNING: Your backup directory does <strong>NOT</strong> exist, and we cannot create it.','wp-db-backup'); ?></p>
1138 <p><?php printf(__('Using your FTP client, try to create the backup directory yourself: %s', 'wp-db-backup'), '<code>' . $this->backup_dir . '</code>'); ?></p></div><?php
1139 $whoops = true;
1140 // not writable due to write permissions
1141 } elseif ( !is_writable($this->backup_dir) && ! @chmod($this->backup_dir, $dir_perms) ) {
1142 ?><div class="updated wp-db-backup-updated error"><p><?php _e('WARNING: Your backup directory is <strong>NOT</strong> writable! We cannot create the backup files.','wp-db-backup'); ?></p>
1143 <p><?php printf(__('Using your FTP client, try to set the backup directory&rsquo;s write permission to %1$s or %2$s: %3$s', 'wp-db-backup'), '<code>777</code>', '<code>a+w</code>', '<code>' . $this->backup_dir . '</code>'); ?>
1144 </p></div><?php
1145 $whoops = true;
1146 } else {
1147 $this->fp = $this->open($this->backup_dir . 'test' );
1148 if( $this->fp ) {
1149 $this->close($this->fp);
1150 @unlink($this->backup_dir . 'test' );
1151 // the directory is not writable probably due to safe mode
1152 } else {
1153 ?><div class="updated wp-db-backup-updated error"><p><?php _e('WARNING: Your backup directory is <strong>NOT</strong> writable! We cannot create the backup files.','wp-db-backup'); ?></p><?php
1154 if( ini_get('safe_mode') ){
1155 ?><p><?php _e('This problem seems to be caused by your server&rsquo;s <code>safe_mode</code> file ownership restrictions, which limit what files web applications like WordPress can create.', 'wp-db-backup'); ?></p><?php
1156 }
1157 ?><?php printf(__('You can try to correct this problem by using your FTP client to delete and then re-create the backup directory: %s', 'wp-db-backup'), '<code>' . $this->backup_dir . '</code>');
1158 ?></div><?php
1159 $whoops = true;
1160 }
1161 }
1162
1163
1164
1165 if ( !file_exists($this->backup_dir . 'index.php') )
1166 @ touch($this->backup_dir . 'index.php');
1167 ?><div class='wrap'>
1168 <h2><?php _e('Backup','wp-db-backup') ?></h2>
1169 <form method="post" action="">
1170 <?php if ( function_exists('wp_nonce_field') ) wp_nonce_field($this->referer_check_key); ?>
1171 <fieldset class="options"><legend><?php _e('Tables','wp-db-backup') ?></legend>
1172 <div class="tables-list core-tables alternate">
1173 <h4><?php _e('These core WordPress tables will always be backed up:','wp-db-backup') ?></h4><ul><?php
1174 $excs = (array) get_option('wp_db_backup_excs');
1175 foreach ($wp_backup_default_tables as $table) {
1176 if ( $table == $wpdb->comments ) {
1177 $checked = ( isset($excs['spam']) && is_array($excs['spam'] ) && in_array($table, $excs['spam']) ) ? ' checked=\'checked\'' : '';
1178 echo "<li><input type='hidden' name='core_tables[]' value='$table' /><code>$table</code> <span class='instructions'> <input type='checkbox' name='exclude-spam[]' value='$table' $checked /> " . __('Exclude spam comments', 'wp-db-backup') . '</span></li>';
1179 } elseif ( function_exists('wp_get_post_revisions') && $table == $wpdb->posts ) {
1180 $checked = ( isset($excs['revisions']) && is_array($excs['revisions'] ) && in_array($table, $excs['revisions']) ) ? ' checked=\'checked\'' : '';
1181 echo "<li><input type='hidden' name='core_tables[]' value='$table' /><code>$table</code> <span class='instructions'> <input type='checkbox' name='exclude-revisions[]' value='$table' $checked /> " . __('Exclude post revisions', 'wp-db-backup') . '</span></li>';
1182 } else {
1183 echo "<li><input type='hidden' name='core_tables[]' value='$table' /><code>$table</code></li>";
1184 }
1185 }
1186 ?></ul>
1187 </div>
1188 <div class="tables-list extra-tables" id="extra-tables-list">
1189 <?php
1190 if (count($other_tables) > 0) {
1191 ?>
1192 <h4><?php _e('You may choose to include any of the following tables:','wp-db-backup'); ?></h4>
1193 <ul>
1194 <?php
1195 foreach ($other_tables as $table) {
1196 ?>
1197 <li><label><input type="checkbox" name="other_tables[]" value="<?php echo $table; ?>" /> <code><?php echo $table; ?></code></label>
1198 <?php
1199 }
1200 ?></ul><?php
1201 }
1202 ?></div>
1203 </fieldset>
1204
1205 <fieldset class="options">
1206 <legend><?php _e('Backup Options','wp-db-backup'); ?></legend>
1207 <p><?php _e('What to do with the backup file:','wp-db-backup'); ?></p>
1208 <ul>
1209 <li><label for="do_save">
1210 <input type="radio" id="do_save" name="deliver" value="none" style="border:none;" />
1211 <?php _e('Save to server','wp-db-backup');
1212 echo " (<code>" . $this->backup_dir . "</code>)"; ?>
1213 </label></li>
1214 <li><label for="do_download">
1215 <input type="radio" checked="checked" id="do_download" name="deliver" value="http" style="border:none;" />
1216 <?php _e('Download to your computer','wp-db-backup'); ?>
1217 </label></li>
1218 <li><label for="do_email">
1219 <input type="radio" name="deliver" id="do_email" value="smtp" style="border:none;" />
1220 <?php _e('Email backup to:','wp-db-backup'); ?>
1221 <input type="text" name="backup_recipient" size="20" value="<?php echo get_option('admin_email'); ?>" />
1222 </label></li>
1223 </ul>
1224 <?php if ( ! $whoops ) : ?>
1225 <input type="hidden" name="do_backup" id="do_backup" value="backup" />
1226 <p class="submit">
1227 <input type="submit" name="submit" onclick="document.getElementById('do_backup').value='fragments';" value="<?php _e('Backup now!','wp-db-backup'); ?>" />
1228 </p>
1229 <?php else : ?>
1230 <div class="updated wp-db-backup-updated error"><p><?php _e('WARNING: Your backup directory is <strong>NOT</strong> writable!','wp-db-backup'); ?></p></div>
1231 <?php endif; // ! whoops ?>
1232 </fieldset>
1233 <?php do_action('wp_db_b_backup_opts'); ?>
1234 </form>
1235
1236 <?php
1237 // this stuff only displays if some sort of wp-cron is available
1238 $cron = ( function_exists('wp_schedule_event') ) ? true : false; // wp-cron in WP 2.1+
1239 $cron_old = ( function_exists('wp_cron_init') && ! $cron ) ? true : false; // wp-cron plugin by Skippy
1240 if ( $cron_old || $cron ) :
1241 echo '<fieldset class="options"><legend>' . __('Scheduled Backup','wp-db-backup') . '</legend>';
1242 $datetime = get_option('date_format') . ' ' . get_option('time_format');
1243 if ( $cron ) :
1244 $next_cron = wp_next_scheduled('wp_db_backup_cron');
1245 if ( ! empty( $next_cron ) ) :
1246 ?>
1247 <p id="backup-time-wrap">
1248 <?php printf(__('Next Backup: %s','wp-db-backup'), '<span id="next-backup-time">' . gmdate($datetime, $next_cron + (get_option('gmt_offset') * 3600)) . '</span>'); ?>
1249 </p>
1250 <?php
1251 endif;
1252 elseif ( $cron_old ) :
1253 ?><p><?php printf(__('Last WP-Cron Daily Execution: %s','wp-db-backup'), gmdate($datetime, get_option('wp_cron_daily_lastrun') + (get_option('gmt_offset') * 3600))); ?><br /><?php
1254 printf(__('Next WP-Cron Daily Execution: %s','wp-db-backup'), gmdate($datetime, (get_option('wp_cron_daily_lastrun') + (get_option('gmt_offset') * 3600) + 86400))); ?></p><?php
1255 endif;
1256 ?><form method="post" action="">
1257 <?php if ( function_exists('wp_nonce_field') ) wp_nonce_field($this->referer_check_key); ?>
1258 <div class="tables-list">
1259 <h4><?php _e('Schedule: ','wp-db-backup'); ?></h4>
1260 <?php
1261 if ( $cron_old ) :
1262 $wp_cron_backup_schedule = get_option('wp_cron_backup_schedule');
1263 $schedule = array(0 => __('None','wp-db-backup'), 1 => __('Daily','wp-db-backup'));
1264 foreach ($schedule as $value => $name) {
1265 echo ' <input type="radio" style="border:none;" name="cron_schedule"';
1266 if ($wp_cron_backup_schedule == $value) {
1267 echo ' checked="checked" ';
1268 }
1269 echo 'value="' . $value . '" /> ' . $name;
1270 }
1271 elseif ( $cron ) :
1272 echo apply_filters('wp_db_b_schedule_choices', wp_get_schedules() );
1273 endif;
1274 $cron_recipient = get_option('wp_cron_backup_recipient');
1275 if (! is_email($cron_recipient)) {
1276 $cron_recipient = get_option('admin_email');
1277 }
1278 $cron_recipient_input = '<p><label for="cron_backup_recipient">' . __('Email backup to:','wp-db-backup') . ' <input type="text" name="cron_backup_recipient" id="cron_backup_recipient" size="20" value="' . $cron_recipient . '" /></label></p>';
1279 echo apply_filters('wp_db_b_cron_recipient_input', $cron_recipient_input);
1280 echo '<p class="submit"><input type="submit" name="submit" value="' . __('Schedule backup','wp-db-backup') . '" /></p>';
1281 echo '</div>';
1282 $cron_tables = get_option('wp_cron_backup_tables');
1283 if (! is_array($cron_tables)) {
1284 $cron_tables = array();
1285 }
1286 if (count($other_tables) > 0) {
1287 echo '<div class="tables-list alternate" id="include-tables-list">';
1288 echo '<h4>' . __('Tables to include in the scheduled backup:','wp-db-backup') . '</h4><ul>';
1289 foreach ($other_tables as $table) {
1290 echo '<li><input type="checkbox" ';
1291 if (in_array($table, $cron_tables)) {
1292 echo 'checked="checked" ';
1293 }
1294 echo "name='wp_cron_backup_tables[]' value='{$table}' /> <code>{$table}</code></li>";
1295 }
1296 echo '</ul></div>';
1297 }
1298 echo '<input type="hidden" name="wp_cron_backup_options" value="SET" /></form>';
1299 echo '</fieldset>';
1300 endif; // end of wp_cron (legacy) section
1301
1302 echo '</div><!-- .wrap -->';
1303
1304 } // end wp_backup_menu()
1305
1306 function get_sched() {
1307 $options = array_keys( (array) wp_get_schedules() );
1308 $freq = get_option('wp_cron_backup_schedule');
1309 $freq = ( in_array( $freq , $options ) ) ? $freq : 'never';
1310 return $freq;
1311 }
1312
1313 function schedule_choices($schedule) { // create the cron menu based on the schedule
1314 $wp_cron_backup_schedule = $this->get_sched();
1315 $next_cron = wp_next_scheduled('wp_db_backup_cron');
1316 $wp_cron_backup_schedule = ( empty( $next_cron ) ) ? 'never' : $wp_cron_backup_schedule;
1317 $sort = array();
1318 foreach ( (array) $schedule as $key => $value ) $sort[$key] = $value['interval'];
1319 asort( $sort );
1320 $schedule_sorted = array();
1321 foreach ( (array) $sort as $key => $value ) $schedule_sorted[$key] = $schedule[$key];
1322 $menu = '<ul>';
1323 $schedule = array_merge( array( 'never' => array( 'interval' => 0, 'display' => __('Never','wp-db-backup') ) ),
1324 (array) $schedule_sorted );
1325 foreach ( $schedule as $name => $settings) {
1326 $interval = (int) $settings['interval'];
1327 if ( 0 == $interval && ! 'never' == $name ) continue;
1328 $display = ( ! '' == $settings['display'] ) ? $settings['display'] : sprintf(__('%s seconds','wp-db-backup'),$interval);
1329 $menu .= "<li><input type='radio' name='wp_cron_schedule' style='border:none;' ";
1330 if ($wp_cron_backup_schedule == $name) {
1331 $menu .= " checked='checked' ";
1332 }
1333 $menu .= "value='$name' /> $display</li>";
1334 }
1335 $menu .= '</ul>';
1336 return $menu;
1337 } // end schedule_choices()
1338
1339 function wp_cron_daily() { // for legacy cron plugin
1340 $schedule = intval(get_option('wp_cron_backup_schedule'));
1341 // If scheduled backup is disabled
1342 if (0 == $schedule)
1343 return;
1344 else return $this->cron_backup();
1345 }
1346
1347 function cron_backup() {
1348 global $table_prefix, $wpdb;
1349 $all_tables = $wpdb->get_results("SHOW TABLES", ARRAY_N);
1350 $all_tables = array_map(create_function('$a', 'return $a[0];'), $all_tables);
1351 $core_tables = array_intersect($all_tables, $this->core_table_names);
1352 $other_tables = get_option('wp_cron_backup_tables');
1353 $recipient = get_option('wp_cron_backup_recipient');
1354 $backup_file = $this->db_backup($core_tables, $other_tables);
1355 if (false !== $backup_file)
1356 return $this->deliver_backup($backup_file, 'smtp', $recipient, 'main');
1357 else return false;
1358 }
1359
1360 function add_sched_options($sched) {
1361 $sched['weekly'] = array('interval' => 604800, 'display' => __('Once Weekly','wp-db-backup'));
1362 return $sched;
1363 }
1364
1365 /**
1366 * Checks that WordPress has sufficient security measures
1367 * @param string $kind
1368 * @return bool
1369 */
1370 function wp_secure($kind = 'warn', $loc = 'main') {
1371 global $wp_version;
1372 if ( function_exists('wp_verify_nonce') ) return true;
1373 else {
1374 $this->error(array('kind' => $kind, 'loc' => $loc, 'msg' => sprintf(__('Your WordPress version, %1s, lacks important security features without which it is unsafe to use the WP-DB-Backup plugin. Hence, this plugin is automatically disabled. Please consider <a href="%2s">upgrading WordPress</a> to a more recent version.','wp-db-backup'),$wp_version,'http://wordpress.org/download/')));
1375 return false;
1376 }
1377 }
1378
1379 /**
1380 * Checks that the user has sufficient permission to backup
1381 * @param string $loc
1382 * @return bool
1383 */
1384 function can_user_backup($loc = 'main') {
1385 $can = false;
1386 // make sure WPMU users are site admins, not ordinary admins
1387 if ( function_exists('is_site_admin') && ! is_site_admin() )
1388 return false;
1389 if ( ( $this->wp_secure('fatal', $loc) ) && current_user_can('import') )
1390 $can = $this->verify_nonce($_REQUEST['_wpnonce'], $this->referer_check_key, $loc);
1391 if ( false == $can )
1392 $this->error(array('loc' => $loc, 'kind' => 'fatal', 'msg' => __('You are not allowed to perform backups.','wp-db-backup')));
1393 return $can;
1394 }
1395
1396 /**
1397 * Verify that the nonce is legitimate
1398 * @param string $rec the nonce received
1399 * @param string $nonce what the nonce should be
1400 * @param string $loc the location of the check
1401 * @return bool
1402 */
1403 function verify_nonce($rec = '', $nonce = 'X', $loc = 'main') {
1404 if ( wp_verify_nonce($rec, $nonce) )
1405 return true;
1406 else
1407 $this->error(array('loc' => $loc, 'kind' => 'fatal', 'msg' => sprintf(__('There appears to be an unauthorized attempt from this site to access your database located at %1s. The attempt has been halted.','wp-db-backup'),get_option('home'))));
1408 }
1409
1410 /**
1411 * Check whether a file to be downloaded is
1412 * surreptitiously trying to download a non-backup file
1413 * @param string $file
1414 * @return null
1415 */
1416 function validate_file($file) {
1417 if ( (false !== strpos($file, '..')) || (false !== strpos($file, './')) || (':' == substr($file, 1, 1)) )
1418 $this->error(array('kind' => 'fatal', 'loc' => 'frame', 'msg' => __("Cheatin' uh ?",'wp-db-backup')));
1419 }
1420
1421}
1422
1423function wpdbBackup_init() {
1424 global $mywpdbbackup;
1425 $mywpdbbackup = new wpdbBackup();
1426}
1427
1428add_action('plugins_loaded', 'wpdbBackup_init');
1429?>
Note: See TracBrowser for help on using the repository browser.