XPressME Integration Kit

Trac

source: trunk/extras/wp_plugin/xpressme-backup/xpressme-backup.php @ 608

Last change on this file since 608 was 608, checked in by toemon, 14 years ago

EUC->UTF8変換を含むバックアップツール Fixes#345

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