WP-DB-Backup - Version 2.0

Version Description

Download this release

Release Info

Developer filosofo
Plugin Icon 128x128 WP-DB-Backup
Version 2.0
Comparing to
See all releases

Code changes from version 1.4 to 2.0

wp-db-backup-en_US.mo DELETED
Binary file
wp-db-backup-en_US.po DELETED
@@ -1,137 +0,0 @@
1
- msgid ""
2
- msgstr ""
3
- "Project-Id-Version: wp-db-backup\n"
4
- "POT-Creation-Date: \n"
5
- "PO-Revision-Date: 2005-07-12 10:03-0500\n"
6
- "Last-Translator: skippy <skippy@skippy.net>\n"
7
- "Language-Team: skippy <skippy@skippy.net>\n"
8
- "MIME-Version: 1.0\n"
9
- "Content-Type: text/plain; charset=utf-8\n"
10
- "Content-Transfer-Encoding: 8bit\n"
11
- "X-Poedit-Language: English\n"
12
- "X-Poedit-Country: United States\n"
13
- "X-Poedit-KeywordsList: __;_e\n"
14
- "X-Poedit-Basepath: .\n"
15
- "X-Poedit-SearchPath-0: .\n"
16
-
17
- #: wp-db-backup.php:295
18
- msgid "Attached to this email is"
19
- msgstr "Attached to this email is"
20
-
21
- #: wp-db-backup.php:295
22
- msgid "Size"
23
- msgstr "Size"
24
-
25
- #: wp-db-backup.php:295
26
- msgid "kilobytes"
27
- msgstr "kilobytes"
28
-
29
- #: wp-db-backup.php:313
30
- msgid "Database Backup"
31
- msgstr "Database Backup"
32
-
33
- #: wp-db-backup.php:329
34
- msgid "Backup Successful"
35
- msgstr "Backup Successful"
36
-
37
- #: wp-db-backup.php:333
38
- #: wp-db-backup.php:342
39
- msgid "Your backup file"
40
- msgstr "Your backup file"
41
-
42
- #: wp-db-backup.php:333
43
- msgid "should begin downloading shortly."
44
- msgstr "should begin downloading shortly."
45
-
46
- #: wp-db-backup.php:335
47
- msgid "Your backup has been emailed to "
48
- msgstr "Your backup has been emailed to "
49
-
50
- #: wp-db-backup.php:342
51
- msgid "is ready for download; right click and select \"Save As\""
52
- msgstr "is ready for download; right click and select \"Save As\""
53
-
54
- #: wp-db-backup.php:342
55
- msgid " bytes"
56
- msgstr " bytes"
57
-
58
- #: wp-db-backup.php:346
59
- msgid "The following errors were reported"
60
- msgstr "The following errors were reported"
61
-
62
- #: wp-db-backup.php:355
63
- msgid "Scheduled Backup Options Saved!"
64
- msgstr "Scheduled Backup Options Saved!"
65
-
66
- #: wp-db-backup.php:385
67
- #: wp-db-backup.php:418
68
- msgid "WARNING: Your backup directory is <strong>NOT</strong> writable!</strong>"
69
- msgstr "WARNING: Your backup directory is <strong>NOT</strong> writable!</strong>"
70
-
71
- #: wp-db-backup.php:389
72
- #: wp-db-backup.php:416
73
- #: wp-db-backup.php:425
74
- msgid "Backup"
75
- msgstr "Backup"
76
-
77
- #: wp-db-backup.php:390
78
- msgid "Tables"
79
- msgstr "Tables"
80
-
81
- #: wp-db-backup.php:393
82
- msgid "These core WordPress tables will always be backed up"
83
- msgstr "These core WordPress tables will always be backed up"
84
-
85
- #: wp-db-backup.php:399
86
- msgid "You may choose to include any of the following tables"
87
- msgstr "You may choose to include any of the following tables"
88
-
89
- #: wp-db-backup.php:405
90
- msgid "Backup Options"
91
- msgstr "Backup Options"
92
-
93
- #: wp-db-backup.php:407
94
- msgid "Deliver backup file by"
95
- msgstr "Deliver backup file by"
96
-
97
- #: wp-db-backup.php:408
98
- msgid "None"
99
- msgstr "None"
100
-
101
- #: wp-db-backup.php:409
102
- msgid "Email"
103
- msgstr "Email"
104
-
105
- #: wp-db-backup.php:410
106
- msgid "Download"
107
- msgstr "Download"
108
-
109
- #: wp-db-backup.php:411
110
- #: wp-db-backup.php:446
111
- msgid "Email backup to"
112
- msgstr "Email backup to"
113
-
114
- #: wp-db-backup.php:414
115
- msgid "Use gzip compression"
116
- msgstr "Use gzip compression"
117
-
118
- #: wp-db-backup.php:425
119
- msgid "Scheduled"
120
- msgstr "Scheduled"
121
-
122
- #: wp-db-backup.php:426
123
- msgid "Last WP-Cron Daily Execution"
124
- msgstr "Last WP-Cron Daily Execution"
125
-
126
- #: wp-db-backup.php:427
127
- msgid "Next WP-Cron Daily Execution"
128
- msgstr "Next WP-Cron Daily Execution"
129
-
130
- #: wp-db-backup.php:431
131
- msgid "Schedule: "
132
- msgstr "Schedule: "
133
-
134
- #: wp-db-backup.php:448
135
- msgid "Submit"
136
- msgstr "Submit"
137
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
wp-db-backup.mo ADDED
Binary file
wp-db-backup.php CHANGED
@@ -1,487 +1,963 @@
1
  <?php
2
  /*
3
  Plugin Name: WordPress Database Backup
4
- Plugin URI: http://www.skippy.net/plugins/
5
- Description: On-demand backup of your WordPress database.
6
- Author: Scott Merrill
7
- Version: 1.4
8
- Author URI: http://www.skippy.net/
9
 
10
  Much of this was modified from Mark Ghosh's One Click Backup, which
11
  in turn was derived from phpMyAdmin.
12
 
 
 
13
  */
14
 
15
- add_action('admin_menu', 'add_wp_backup_menu');
16
- add_action('wp_cron_daily', 'wp_cron_db_backup');
17
- global $wp_backup_dir, $wp_backup_error;
18
- $wp_backup_error = '';
19
- $wp_backup_dir = 'wp-content/backup/';
20
-
21
- // this needs to live outside of any function so that the
22
- // download can be sent to the browser
23
- if (isset($_GET['backup'])) {
24
- wp_deliver_backup ($_GET['backup'], 'http');
25
- die();
26
- }
27
- if ( (isset($_POST['do_backup'])) && ('backup' == $_POST['do_backup']) ) {
28
- // should we compress the output?
29
- if ('gzip' == $_POST['gzip']) {
30
- $gzip = TRUE;
31
- } else {
32
- $gzip = FALSE;
33
- }
34
- // are we backing up any other tables?
35
- $also_backup = array();
36
- if (isset($_POST['other_tables'])) {
37
- $also_backup = $_POST['other_tables'];
38
- }
39
- $core_tables = $_POST['core_tables'];
40
- $backup_file = wp_db_backup($gzip, $core_tables, $also_backup);
41
- if (FALSE !== $backup_file) {
42
- if ('smtp' == $_POST['deliver']) {
43
- wp_deliver_backup ($backup_file, $_POST['deliver'], $_POST['backup_recipient']);
44
- } elseif ('http' == $_POST['deliver']) {
45
- header('Refresh: 3; ' . get_settings('siteurl') . "/wp-admin/edit.php?page=wp-db-backup.php&backup=$backup_file");
46
- }
47
- // we do this to say we're done.
48
- $_POST['do_backup'] = 'DONE';
49
- // and we do this to pass the filename, and avoid a global
50
- $_POST['gzip'] = $backup_file;
51
- }
52
- }
53
 
54
- ///////////////////////////////
55
- function add_wp_backup_menu() {
56
- add_management_page('Backup', 'Backup', 9, __FILE__, 'wp_backup_menu');
57
- }
58
 
59
- /////////////////////////////////////////////////////////
60
- function sql_addslashes($a_string = '', $is_like = FALSE)
61
- {
62
- /*
63
- Better addslashes for SQL queries.
64
- Taken from phpMyAdmin.
65
- */
66
- if ($is_like) {
67
- $a_string = str_replace('\\', '\\\\\\\\', $a_string);
68
- } else {
69
- $a_string = str_replace('\\', '\\\\', $a_string);
70
- }
71
- $a_string = str_replace('\'', '\\\'', $a_string);
72
-
73
- return $a_string;
74
- } // function sql_addslashes($a_string = '', $is_like = FALSE)
75
-
76
- ///////////////////////////////////////////////////////////
77
- function backquote($a_name)
78
- {
79
- /*
80
- Add backqouotes to tables and db-names in
81
- SQL queries. Taken from phpMyAdmin.
82
- */
83
- if (!empty($a_name) && $a_name != '*') {
84
- if (is_array($a_name)) {
85
- $result = array();
86
- reset($a_name);
87
- while(list($key, $val) = each($a_name)) {
88
- $result[$key] = '`' . $val . '`';
89
- }
90
- return $result;
91
- } else {
92
- return '`' . $a_name . '`';
93
- }
94
- } else {
95
- return $a_name;
96
- }
97
- } // function backquote($a_name, $do_it = TRUE)
98
-
99
- /////////////////////////////
100
- function backup_table($table) {
101
- global $wp_backup_error, $wpdb;
102
 
103
- /*
104
- Taken partially from phpMyAdmin and partially from
105
- Alain Wolf, Zurich - Switzerland
106
- Website: http://restkultur.ch/personal/wolf/scripts/db_backup/
107
 
108
- Modified by Scott Merril (http://www.skippy.net/)
109
- to use the WordPress $wpdb object
110
- */
111
-
112
- $sql_statements = '';
113
-
114
- //
115
- // Add SQL statement to drop existing table
116
- $sql_statements .= "\n";
117
- $sql_statements .= "\n";
118
- $sql_statements .= "#\n";
119
- $sql_statements .= "# Delete any existing table " . backquote($table) . "\n";
120
- $sql_statements .= "#\n";
121
- $sql_statements .= "\n";
122
- $sql_statements .= "DROP TABLE IF EXISTS " . backquote($table) . ";\n";
123
-
124
- //
125
- //Table structure
126
- // Comment in SQL-file
127
- $sql_statements .= "\n";
128
- $sql_statements .= "\n";
129
- $sql_statements .= "#\n";
130
- $sql_statements .= "# Table structure of table " . backquote($table) . "\n";
131
- $sql_statements .= "#\n";
132
- $sql_statements .= "\n";
133
-
134
- $create_table = $wpdb->get_results("SHOW CREATE TABLE $table", ARRAY_N);
135
- if (FALSE === $create_table) {
136
- $wp_backup_error .= "Error with SHOW CREATE TABLE for $table.\r\n";
137
- return "#\n# Error with SHOW CREATE TABLE for $table!\n#\n";
138
- }
139
- $sql_statements .= $create_table[0][1] . ' ;';
140
-
141
- $table_structure = $wpdb->get_results("DESCRIBE $table");
142
- if (FALSE === $table_structure) {
143
- $wp_backup_error .= "Error getting table structure of $table\r\n";
144
- return "#\n# Error getting table structure of $table!\n#\n";
145
- }
146
 
147
- $table_data = $wpdb->get_results("SELECT * FROM $table", ARRAY_A);
148
- if (FALSE === $table_data) {
149
- $wp_backup_error .= "Error getting table contents from $table\r\n";
150
- return "#\n# Error getting table contents fom $table!\n#\n";
151
- }
152
 
153
- //
154
- // Comment in SQL-file
155
- $sql_statements .= "\n";
156
- $sql_statements .= "\n";
157
- $sql_statements .= "#\n";
158
- $sql_statements .= '# Data contents of table ' . backquote($table) . "\n";
159
- $sql_statements .= "#\n";
160
-
161
- $ints = array();
162
- foreach ($table_structure as $struct) {
163
- if ( (0 === strpos($struct->Type, 'tinyint')) ||
164
- (0 === strpos(strtolower($struct->Type), 'smallint')) ||
165
- (0 === strpos(strtolower($struct->Type), 'mediumint')) ||
166
- (0 === strpos(strtolower($struct->Type), 'int')) ||
167
- (0 === strpos(strtolower($struct->Type), 'bigint')) ||
168
- (0 === strpos(strtolower($struct->Type), 'timestamp')) ) {
169
- $ints[strtolower($struct->Field)] = "1";
170
  }
171
- }
172
 
173
- $entries = 'INSERT INTO ' . backquote($table) . ' VALUES (';
174
- // \x08\\x09, not required
175
- $search = array("\x00", "\x0a", "\x0d", "\x1a");
176
- $replace = array('\0', '\n', '\r', '\Z');
177
- foreach ($table_data as $row) {
178
- $values = array();
179
- foreach ($row as $key => $value) {
180
- if ($ints[strtolower($key)]) {
181
- $values[] = $value;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  } else {
183
- $values[] = "'" . str_replace($search, $replace, sql_addslashes($value)) . "'";
184
  }
185
  }
186
- $sql_statements .= " \n" . $entries . implode(', ', $values) . ') ;';
187
- }
188
- // Create footer/closing comment in SQL-file
189
- $sql_statements .= "\n";
190
- $sql_statements .= "#\n";
191
- $sql_statements .= "# End of data contents of table " . backquote($table) . "\n";
192
- $sql_statements .= "# --------------------------------------------------------\n";
193
- $sql_statements .= "\n";
194
-
195
- return $sql_statements;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
197
- } // end backup_table()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
- ////////////////////////////
200
- function wp_db_backup($gzip = FALSE, $core_tables, $other_tables) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
 
202
- global $wp_backup_dir, $wp_backup_error, $table_prefix, $wpdb;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
 
204
- $done = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
 
206
- $datum = date("Ymd_B");
207
- $wp_backup_filename = DB_NAME . "_$table_prefix$datum.sql";
208
- if ($gzip) {
209
- $wp_backup_filename .= '.gz';
210
- }
211
 
212
- //Begin new backup of MySql
213
- $sql = "# WordPress MySQL database backup\n";
214
- $sql .= "#\n";
215
- $sql .= "# Generated: " . date("l j. F Y H:i T") . "\n";
216
- $sql .= "# Hostname: " . DB_HOST . "\n";
217
- $sql .= "# Database: " . backquote(DB_NAME) . "\n";
218
- $sql .= "# --------------------------------------------------------\n";
219
-
220
- foreach ($core_tables as $table) {
221
- if (in_array($table, $done)) { continue; }
222
- // Increase script execution time-limit to 15 min for every table.
223
- if ( !ini_get('safe_mode')) @set_time_limit(15*60);
224
- //ini_set('memory_limit', '16M');
225
- // Create the SQL statements
226
- $tbl = "# --------------------------------------------------------\n";
227
- $tbl .= "# Table: " . backquote($table) . "\n";
228
- $tbl .= "# --------------------------------------------------------\n";
229
- $tbl .= backup_table($table);
230
- $sql .= $tbl;
231
- $done[] = $table;
232
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
 
234
- if (count($other_tables) > 0) {
235
- foreach ($other_tables as $other_table) {
236
- if (in_array($other_table, $done)) { continue; }
237
- // Increase script execution time-limit to 15 min for every table.
238
- if ( !ini_get('safe_mode')) @set_time_limit(15*60);
239
- //ini_set('memory_limit', '16M');
240
- // Create the SQL statements
241
- $tbl = "# --------------------------------------------------------\n";
242
- $tbl .= "# Table: " . backquote($other_table) . "\n";
243
- $tbl .= "# --------------------------------------------------------\n";
244
- $tbl .= backup_table($other_table);
245
- $sql .= $tbl;
246
- $done[] = $other_table;
247
- } // foreach
248
- } // if other_tables...
249
-
250
- if (is_writable(ABSPATH . $wp_backup_dir)) {
251
- if ($gzip) {
252
- $sql = gzencode($sql);
253
  }
254
- $cachefp = fopen(ABSPATH . $wp_backup_dir . $wp_backup_filename, "w");
255
- fwrite($cachefp, $sql);
256
- fclose($cachefp);
257
- }
258
 
259
- if ('' == $wp_backup_error) {
260
- return $wp_backup_filename;
261
- } else {
262
- return FALSE;
263
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
 
265
- } //wp_db_backup
266
-
267
- ///////////////////////////
268
- function wp_deliver_backup ($filename = '', $delivery = 'http', $recipient = '') {
269
- global $wp_backup_dir;
270
-
271
- if ('' == $filename) { return FALSE; }
272
-
273
- $diskfile = ABSPATH . $wp_backup_dir . $filename;
274
- if ('http' == $delivery) {
275
- header('Content-Description: File Transfer');
276
- header('Content-Type: application/octet-stream');
277
- header('Content-Length: ' . filesize($diskfile));
278
- header("Content-Disposition: attachment; filename=$filename");
279
- readfile($diskfile);
280
- unlink($diskfile);
281
- } elseif ('smtp' == $delivery) {
282
- if (! is_email ($recipient)) {
283
- $recipient = get_settings('admin_email');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  }
285
- $randomish = md5(time());
286
- $boundary = "==WPBACKUP-BY-SKIPPY-$randomish";
287
- $fp = fopen($diskfile,"rb");
288
- $file = fread($fp,filesize($diskfile));
289
- fclose($fp);
290
- $data = chunk_split(base64_encode($file));
291
- $headers = "MIME-Version: 1.0\n";
292
- $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\n";
293
- $headers .= 'From: ' . get_settings('admin_email') . "\n";
294
-
295
- $message = __('Attached to this email is', 'wp_backup') . "\n $filename\n". __('Size', 'wp_backup') . ": " . round(filesize($diskfile)/1024) . ' ' . __('kilobytes', 'wp_backup') . "\n";
296
- // Add a multipart boundary above the plain message
297
- $message = "This is a multi-part message in MIME format.\n\n" .
298
- "--{$boundary}\n" .
299
- "Content-Type: text/plain; charset=\"iso-8859-1\"\n" .
300
- "Content-Transfer-Encoding: 7bit\n\n" .
301
- $message . "\n\n";
302
 
303
- // Add file attachment to the message
304
- $message .= "--{$boundary}\n" .
305
- "Content-Type: application/octet-stream;\n" .
306
- " name=\"{$filename}\"\n" .
307
- "Content-Disposition: attachment;\n" .
308
- " filename=\"{$filename}\"\n" .
309
- "Content-Transfer-Encoding: base64\n\n" .
310
- $data . "\n\n" .
311
- "--{$boundary}--\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
 
313
- mail ($recipient, get_bloginfo('name') . ' ' . __('Database Backup', 'wp_backup'), $message, $headers);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
 
315
- unlink($diskfile);
316
- }
317
- return;
318
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
 
320
- ////////////////////////////
321
- function wp_backup_menu() {
322
- global $wp_backup_dir, $wp_backup_error, $table_prefix, $wpdb;
323
- $feedback = '';
324
- $gzip = FALSE;
325
- $WHOOPS = FALSE;
326
-
327
- // first, did we just do a backup? If so, let's report the status
328
- if ( (isset($_POST['do_backup'])) && ('DONE' == $_POST['do_backup']) ) {
329
- $feedback = '<div class="updated"><p>' . __('Backup Successful', 'wp_backup') . '!';
330
- // we stuff the filename into gzip to avoid another global
331
- $file = $_POST['gzip'];
332
- if ('http' == $_POST['deliver']) {
333
- $feedback .= '<br />' . __('Your backup file', 'wp_backup') . ': <a href="' . get_settings('siteurl') . "/$wp_backup_dir$file\">$file</a> " . __('should begin downloading shortly.', 'wp_backup');
334
- } elseif ('smtp' == $_POST['deliver']) {
335
- $feedback .= '<br />' . __('Your backup has been emailed to ', 'wp_backup');
336
- if (! is_email($_POST['backup_recipient'])) {
337
- $feedback .= get_settings('admin_email');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
338
  } else {
339
- $feedback .= $_POST['backup_recipient'];
340
  }
341
- } elseif ('none' == $_POST['deliver']) {
342
- $feedback .= '<br />' . __('Your backup file', 'wp_backup') . ' ' . __('is ready for download; right click and select "Save As"', 'wp_backup') . ':<br /> <a href="' . get_settings('siteurl') . "/$wp_backup_dir$file\">$file</a> : " . filesize(ABSPATH . $wp_backup_dir . $file) . __(' bytes', 'wp_backup');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
343
  }
344
- $feedback .= '</p></div>';
345
- } elseif ('' != $wp_backup_error) {
346
- $feedback = '<div class="updated">' . __('The following errors were reported', 'wp_backup') . ":<br /><pre>$wp_backup_error</pre></div>";
347
- }
348
 
349
- // did we just save options for wp-cron?
350
- if ( (function_exists('wp_cron_db_backup')) && isset($_POST['wp_cron_backup_options']) ) {
351
- update_option('wp_cron_backup_schedule', intval($_POST['cron_schedule']), FALSE);
352
- if (is_email($_POST['cron_backup_recipient'])) {
353
- update_option('wp_cron_backup_recipient', $_POST['cron_backup_recipient'], FALSE);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
  }
355
- $feedback .= '<div class="updated"><p>' . __('Scheduled Backup Options Saved!', 'wp_backup') . '</p></div>';
356
- }
357
 
358
- $gzip = FALSE;
359
- $wp_backup_default_tables = array ($table_prefix . categories,
360
- $table_prefix . comments,
361
- $table_prefix . linkcategories,
362
- $table_prefix . links,
363
- $table_prefix . options,
364
- $table_prefix . post2cat,
365
- $table_prefix . postmeta,
366
- $table_prefix . posts,
367
- $table_prefix . users);
368
-
369
- $other_tables = array();
370
- $also_backup = array();
371
-
372
- // let's get other tables in this database
373
- $all_tables = $wpdb->get_results("SHOW TABLES", ARRAY_N);
374
- foreach ($all_tables as $table) {
375
- if (! in_array($table[0], $wp_backup_default_tables)) {
376
- $other_tables[] = $table[0];
377
  }
378
- }
379
-
380
- if ('' != $feedback) {
381
- echo $feedback;
382
- }
383
 
384
- if (! is_writable(ABSPATH . $wp_backup_dir)) {
385
- echo '<div class="updated"><p align="center">' . __('WARNING: Your backup directory is <strong>NOT</strong> writable!</strong>', 'wp_backup') . '<br />' . ABSPATH . "$wp_backup_dir</p></div>";
386
- $WHOOPS = TRUE;
387
- }
388
- echo "<div class='wrap'>";
389
- echo '<h2>' . __('Backup', 'wp_backup') . '</h2>';
390
- echo '<fieldset class="options"><legend>' . __('Tables', 'wp_backup') . '</legend>';
391
- echo '<form method="post">';
392
- echo '<table align="center" cellspacing="5" cellpadding="5"><tr><td width="50%" align="left" class="alternate">';
393
- echo __('These core WordPress tables will always be backed up', 'wp_backup') . ': <br /><ul>';
394
- foreach ($wp_backup_default_tables as $table) {
395
- echo "<input type='hidden' name='core_tables[]' value='$table' /><li>$table</li>";
396
- }
397
- echo '</ul></td><td width="50%" align="left">';
398
- if (count($other_tables) > 0) {
399
- echo __('You may choose to include any of the following tables', 'wp_backup') . ': <br />';
400
- foreach ($other_tables as $table) {
401
- echo "<input type='checkbox' name='other_tables[]' value='$table' />$table<br />";
402
  }
403
- }
404
- echo '</tr></table></fieldset>';
405
- echo '<fieldset class="options"><legend>' . __('Backup Options', 'wp_backup') . '</legend><table width="100%" align="center" cellpadding="5" cellspacing="5">';
406
- echo '<tr><td align="center">';
407
- echo __('Deliver backup file by', 'wp_backup') . ":<br />";
408
- echo '<input type="radio" name="deliver" value="none" /> ' . __('None', 'wp_backup') . '&nbsp;&nbsp;&nbsp;&nbsp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />';
409
- echo '<input type="radio" name="deliver" value="smtp" /> ' . __('Email', 'wp_backup') . '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />';
410
- echo '<input type="radio" name="deliver" value="http" /> ' . __('Download', 'wp_backup');
411
- echo '</td><td align="left">' . __('Email backup to', 'wp_backup') . ':<br /> <input type="text" name="backup_recipient" size="20" value="' . get_settings('admin_email') . '" /></td></tr>';
412
- echo '<tr class="alternate"><td colspan="2" align="center">';
413
- if (! $WHOOPS) {
414
- echo __('Use gzip compression', 'wp_backup') . '? <input type="checkbox" checked="checked" name="gzip" value="gzip" /><br />';
415
- echo '<input type="hidden" name="do_backup" value="backup" />';
416
- echo '<input type="submit" name="submit" value="' . __('Backup', 'wp_backup') . '!" / >';
417
- } else {
418
- echo __('WARNING: Your backup directory is <strong>NOT</strong> writable!</strong>', 'wp_backup');
419
- }
420
- echo '</td></tr></form></table>';
421
- echo '</fieldset>';
422
-
423
- // this stuff only displays if wp_cron is installed
424
- if (function_exists('wp_cron_db_backup')) {
425
- echo '<fieldset class="options"><legend>' . __('Scheduled', 'wp_backup') . ' ' . __('Backup', 'wp_backup') . '</legend>';
426
- echo '<p>' . __('Last WP-Cron Daily Execution', 'wp_backup') . ': ' . date('Y-m-d @ h:i', get_option('wp_cron_daily_lastrun')) . '<br />';
427
- echo __('Next WP-Cron Daily Execution', 'wp_backup') . ': ' . date('Y-m-d @ h:i', (get_option('wp_cron_daily_lastrun') + 86400)) . '</p>';
428
- echo '<form method="post">';
429
- echo '<table width="100%" callpadding="5" cellspacing="5">';
430
- echo '<tr><td align="center">';
431
- echo __('Schedule: ', 'wp_backup');
432
- $wp_cron_backup_schedule = get_option('wp_cron_backup_schedule');
433
- $schedule = array("None" => 0, "Daily" => 1);
434
- foreach ($schedule as $name => $value) {
435
- echo ' <input type="radio" name="cron_schedule"';
436
- if ($wp_cron_backup_schedule == $value) {
437
- echo ' checked="checked" ';
438
- }
439
- echo 'value="' . $value . '" /> ' . __($name, 'wp_backup');
440
- }
441
- echo '</td><td align="center">';
442
- $cron_recipient = get_option('wp_cron_backup_recipient');
443
- if (! is_email($cron_recipient)) {
444
- $cron_recipient = get_settings('admin_email');
445
- }
446
- echo __('Email backup to', 'wp_backup') . ': <input type="text" name="cron_backup_recipient" size="20" value="' . $cron_recipient . '" />';
447
- echo '</td></tr>';
448
- echo '<tr><td colspan="2" align="center"><input type="hidden" name="wp_cron_backup_options" value="SET" /><input type="submit" name="submit" value="' . __('Submit', 'wp_backup') . '" /></td></tr></table></form>';
449
- echo '</fieldset>';
450
- }
451
- // end of wp_cron section
452
 
453
- echo '</fieldset></div>';
 
 
454
 
455
- }// end wp_backup_menu()
 
456
 
457
- /////////////////////////////
458
- function wp_cron_db_backup() {
 
459
 
460
- $schedule = intval(get_option('wp_cron_backup_schedule'));
461
- if (0 == $schedule) {
462
- // Scheduled backup is disabled
463
- return;
464
  }
465
 
466
- global $wp_backup_dir, $wp_backup_error, $table_prefix;
467
- $core_tables = array ($table_prefix . categories,
468
- $table_prefix . comments,
469
- $table_prefix . linkcategories,
470
- $table_prefix . links,
471
- $table_prefix . options,
472
- $table_prefix . post2cat,
473
- $table_prefix . postmeta,
474
- $table_prefix . posts,
475
- $table_prefix . users);
476
-
477
- $recipient = get_option('wp_cron_backup_recipient');
478
-
479
- $backup_file = wp_db_backup(TRUE, $core_tables);
480
- if (FALSE !== $backup_file) {
481
- wp_deliver_backup ($backup_file, 'smtp', $recipient);
482
  }
483
 
484
- return;
485
- } // wp_cron_db_backup
486
 
487
  ?>
1
  <?php
2
  /*
3
  Plugin Name: WordPress Database Backup
4
+ Plugin URI: http://www.ilfilosofo.com/blog/wp-db-backup
5
+ Description: On-demand backup of your WordPress database. Navigate to <a href="edit.php?page=wp-db-backup.php">Manage &rarr; Backup</a> to get started.
6
+ Author: <a href="http://www.skippy.net/">Scott Merrill</a> and <a href="http://www.ilfilosofo.com/blog/">Austin Matzko</a>
7
+ Version: 2.0
 
8
 
9
  Much of this was modified from Mark Ghosh's One Click Backup, which
10
  in turn was derived from phpMyAdmin.
11
 
12
+ Many thanks to Owen (http://asymptomatic.net/wp/) for his patch
13
+ http://dev.wp-plugins.org/ticket/219
14
  */
15
 
16
+ // CHANGE THIS IF YOU WANT TO USE A
17
+ // DIFFERENT BACKUP LOCATION
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ $rand = substr( md5( md5( DB_PASSWORD ) ), -5 );
 
 
 
20
 
21
+ define('WP_BACKUP_DIR', 'wp-content/backup-' . $rand);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ define('ROWS_PER_SEGMENT', 100);
 
 
 
24
 
25
+ class wpdbBackup {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
+ var $backup_complete = false;
28
+ var $backup_file = '';
29
+ var $backup_dir = WP_BACKUP_DIR;
30
+ var $backup_errors = array();
31
+ var $basename;
32
 
33
+ function gzip() {
34
+ return function_exists('gzopen');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
 
36
 
37
+ function wpdbBackup() {
38
+ global $table_prefix, $wpdb;
39
+ add_action('wp_db_backup_cron', array(&$this, 'cron_backup'));
40
+ add_action('wp_cron_daily', array(&$this, 'wp_cron_daily'));
41
+ add_filter('cron_schedules', array(&$this, 'add_sched_options'));
42
+ add_filter('wp_db_b_schedule_choices', array(&$this, 'schedule_choices'));
43
+
44
+ $table_prefix = ( isset( $table_prefix ) ) ? $table_prefix : $wpdb->prefix;
45
+ if ( isset( $wpdb->link2cat ) )
46
+ $this->core_table_names = explode(',',"$wpdb->categories,$wpdb->comments,$wpdb->link2cat,$wpdb->links,$wpdb->options,$wpdb->post2cat,$wpdb->postmeta,$wpdb->posts,$wpdb->users,$wpdb->usermeta");
47
+ else
48
+ $this->core_table_names = explode(',',"$wpdb->categories,$wpdb->comments,$wpdb->linkcategories,$wpdb->links,$wpdb->options,$wpdb->post2cat,$wpdb->postmeta,$wpdb->posts,$wpdb->users,$wpdb->usermeta");
49
+
50
+ $this->backup_dir = trailingslashit($this->backup_dir);
51
+ $this->basename = preg_replace('/^.*wp-content[\\\\\/]plugins[\\\\\/]/', '', __FILE__);
52
+
53
+ if (isset($_POST['do_backup'])) {
54
+ if ( !$this->user_can_backup() ) die(__('You are not allowed to perform backups.'));
55
+ switch($_POST['do_backup']) {
56
+ case 'backup':
57
+ $this->perform_backup();
58
+ break;
59
+ case 'fragments':
60
+ add_action('admin_menu', array(&$this, 'fragment_menu'));
61
+ break;
62
+ }
63
+ } elseif (isset($_GET['fragment'] )) {
64
+ if ( !$this->user_can_backup() ) die(__('You are not allowed to perform backups.'));
65
+ add_action('init', array(&$this, 'init'));
66
+ } elseif (isset($_GET['backup'] )) {
67
+ if ( !$this->user_can_backup() ) die(__('You are not allowed to perform backups.'));
68
+ add_action('init', array(&$this, 'init'));
69
  } else {
70
+ add_action('admin_menu', array(&$this, 'admin_menu'));
71
  }
72
  }
73
+
74
+ function init() {
75
+ if ( !$this->user_can_backup() ) die(__('You are not allowed to perform backups.'));
76
+
77
+ if (isset($_GET['backup'])) {
78
+ $via = isset($_GET['via']) ? $_GET['via'] : 'http';
79
+
80
+ $this->backup_file = $_GET['backup'];
81
+ $this->validate_file($this->backup_file);
82
+
83
+ switch($via) {
84
+ case 'smtp':
85
+ case 'email':
86
+ $this->deliver_backup ($this->backup_file, 'smtp', $_GET['recipient']);
87
+ echo '
88
+ <!-- ' . $via . ' -->
89
+ <script type="text/javascript"><!--\\
90
+ ';
91
+ if($this->backup_errors) {
92
+ foreach($this->backup_errors as $error) {
93
+ echo "window.parent.addError('$error');\n";
94
+ }
95
+ }
96
+ echo '
97
+ alert("' . __('Backup Complete!') . '");
98
+ </script>
99
+ ';
100
+ break;
101
+ default:
102
+ $this->deliver_backup ($this->backup_file, $via);
103
+ }
104
+ die();
105
+ }
106
+ if (isset($_GET['fragment'] )) {
107
+ list($table, $segment, $filename) = explode(':', $_GET['fragment']);
108
+ $this->validate_file($filename);
109
+ $this->backup_fragment($table, $segment, $filename);
110
+ }
111
 
112
+ die();
113
+ }
114
+
115
+ function build_backup_script() {
116
+ global $table_prefix, $wpdb;
117
+
118
+ $datum = date("Ymd_B");
119
+ $backup_filename = DB_NAME . "_$table_prefix$datum.sql";
120
+ if ($this->gzip()) $backup_filename .= '.gz';
121
+
122
+ echo "<div class='wrap'>";
123
+ //echo "<pre>" . print_r($_POST, 1) . "</pre>";
124
+ echo '<h2>' . __('Backup') . '</h2>
125
+ <fieldset class="options"><legend>' . __('Progress') . '</legend>
126
+ <p><strong>' .
127
+ __('DO NOT DO THE FOLLOWING AS IT WILL CAUSE YOUR BACKUP TO FAIL:').
128
+ '</strong></p>
129
+ <ol>
130
+ <li>'.__('Close this browser').'</li>
131
+ <li>'.__('Reload this page').'</li>
132
+ <li>'.__('Click the Stop or Back buttons in your browser').'</li>
133
+ </ol>
134
+ <p><strong>' . __('Progress:') . '</strong></p>
135
+ <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>
136
+ <div id="progress_message"></div>
137
+ <div id="errors"></div>
138
+ </fieldset>
139
+ <iframe id="backuploader" src="about:blank" style="border:0px solid white;height:1em;width:1em;"></iframe>
140
+ <script type="text/javascript"><!--//
141
+ function setMeter(pct) {
142
+ var meter = document.getElementById("meter");
143
+ meter.style.width = pct + "%";
144
+ meter.innerHTML = Math.floor(pct) + "%";
145
+ }
146
+ function setProgress(str) {
147
+ var progress = document.getElementById("progress_message");
148
+ progress.innerHTML = str;
149
+ }
150
+ function addError(str) {
151
+ var errors = document.getElementById("errors");
152
+ errors.innerHTML = errors.innerHTML + str + "<br />";
153
+ }
154
+
155
+ function backup(table, segment) {
156
+ var fram = document.getElementById("backuploader");
157
+ fram.src = "' . $_SERVER['REQUEST_URI'] . '&fragment=" + table + ":" + segment + ":' . $backup_filename . '";
158
+ }
159
+
160
+ var curStep = 0;
161
+
162
+ function nextStep() {
163
+ backupStep(curStep);
164
+ curStep++;
165
+ }
166
+
167
+ function finishBackup() {
168
+ var fram = document.getElementById("backuploader");
169
+ setMeter(100);
170
+ ';
171
+
172
+ $this_basename = preg_replace('/^.*wp-content[\\\\\/]plugins[\\\\\/]/', '', __FILE__);
173
+ $download_uri = get_option('siteurl') . "/wp-admin/edit.php?page={$this_basename}&backup={$backup_filename}";
174
+ switch($_POST['deliver']) {
175
+ case 'http':
176
+ echo '
177
+ setProgress("' . sprintf(__("Backup complete, preparing <a href=\\\"%s\\\">backup</a> for download..."), $download_uri) . '");
178
+ fram.src = "' . $download_uri . '";
179
+ ';
180
+ break;
181
+ case 'smtp':
182
+ echo '
183
+ setProgress("' . sprintf(__("Backup complete, sending <a href=\\\"%s\\\">backup</a> via email..."), $download_uri) . '");
184
+ fram.src = "' . $download_uri . '&via=email&recipient=' . $_POST['backup_recipient'] . '";
185
+ ';
186
+ break;
187
+ default:
188
+ echo '
189
+ setProgress("' . sprintf(__("Backup complete, download <a href=\\\"%s\\\">here</a>."), $download_uri) . '");
190
+ ';
191
+ }
192
+
193
+ echo '
194
+ }
195
+
196
+ function backupStep(step) {
197
+ switch(step) {
198
+ case 0: backup("", 0); break;
199
+ ';
200
+
201
+ $also_backup = array();
202
+ if (isset($_POST['other_tables'])) {
203
+ $also_backup = $_POST['other_tables'];
204
+ } else {
205
+ $also_backup = array();
206
+ }
207
+ $core_tables = $_POST['core_tables'];
208
+ $tables = array_merge($core_tables, $also_backup);
209
+ $step_count = 1;
210
+ foreach ($tables as $table) {
211
+ $rec_count = $wpdb->get_var("SELECT count(*) FROM {$table}");
212
+ $rec_segments = ceil($rec_count / ROWS_PER_SEGMENT);
213
+ $table_count = 0;
214
+ do {
215
+ echo "case {$step_count}: backup(\"{$table}\", {$table_count}); break;\n";
216
+ $step_count++;
217
+ $table_count++;
218
+ } while($table_count < $rec_segments);
219
+ echo "case {$step_count}: backup(\"{$table}\", -1); break;\n";
220
+ $step_count++;
221
+ }
222
+ echo "case {$step_count}: finishBackup(); break;";
223
+
224
+ echo '
225
+ }
226
+ if(step != 0) setMeter(100 * step / ' . $step_count . ');
227
+ }
228
+
229
+ nextStep();
230
+ //--></script>
231
+ </div>
232
+ ';
233
+ }
234
 
235
+ function backup_fragment($table, $segment, $filename) {
236
+ global $table_prefix, $wpdb;
237
+
238
+ echo "$table:$segment:$filename";
239
+
240
+ if($table == '') {
241
+ $msg = __('Creating backup file...');
242
+ } else {
243
+ if($segment == -1) {
244
+ $msg = sprintf(__('Finished backing up table \\"%s\\".'), $table);
245
+ } else {
246
+ $msg = sprintf(__('Backing up table \\"%s\\"...'), $table);
247
+ }
248
+ }
249
+
250
+ echo '<script type="text/javascript"><!--//
251
+ var msg = "' . $msg . '";
252
+ window.parent.setProgress(msg);
253
+ ';
254
+
255
+ if (is_writable(ABSPATH . $this->backup_dir)) {
256
+ $this->fp = $this->open(ABSPATH . $this->backup_dir . $filename, 'a');
257
+ if(!$this->fp) {
258
+ $this->backup_error(__('Could not open the backup file for writing!'));
259
+ $this->fatal_error = __('The backup file could not be saved. Please check the permissions for writing to your backup directory and try again.');
260
+ }
261
+ else {
262
+ if($table == '') {
263
+ //Begin new backup of MySql
264
+ $this->stow("# WordPress MySQL database backup\n");
265
+ $this->stow("#\n");
266
+ $this->stow("# Generated: " . date("l j. F Y H:i T") . "\n");
267
+ $this->stow("# Hostname: " . DB_HOST . "\n");
268
+ $this->stow("# Database: " . $this->backquote(DB_NAME) . "\n");
269
+ $this->stow("# --------------------------------------------------------\n");
270
+ } else {
271
+ if($segment == 0) {
272
+ // Increase script execution time-limit to 15 min for every table.
273
+ if ( !ini_get('safe_mode')) @set_time_limit(15*60);
274
+ //ini_set('memory_limit', '16M');
275
+ // Create the SQL statements
276
+ $this->stow("# --------------------------------------------------------\n");
277
+ $this->stow("# Table: " . $this->backquote($table) . "\n");
278
+ $this->stow("# --------------------------------------------------------\n");
279
+ }
280
+ $this->backup_table($table, $segment);
281
+ }
282
+ }
283
+ } else {
284
+ $this->backup_error(__('The backup directory is not writeable!'));
285
+ $this->fatal_error = __('The backup directory is not writeable! Please check the permissions for writing to your backup directory and try again.');
286
+ }
287
 
288
+ if($this->fp) $this->close($this->fp);
289
+
290
+ if($this->backup_errors) {
291
+ foreach($this->backup_errors as $error) {
292
+ echo "window.parent.addError('$error');\n";
293
+ }
294
+ }
295
+ if($this->fatal_error) {
296
+ echo '
297
+ alert("' . addslashes($this->fatal_error) . '");
298
+ //--></script>
299
+ ';
300
+ }
301
+ else {
302
+ echo '
303
+ window.parent.nextStep();
304
+ //--></script>
305
+ ';
306
+ }
307
+
308
+ die();
309
+ }
310
 
311
+ function perform_backup() {
312
+ // are we backing up any other tables?
313
+ $also_backup = array();
314
+ if (isset($_POST['other_tables'])) {
315
+ $also_backup = $_POST['other_tables'];
316
+ }
317
+
318
+ $core_tables = $_POST['core_tables'];
319
+ $this->backup_file = $this->db_backup($core_tables, $also_backup);
320
+ if (FALSE !== $this->backup_file) {
321
+ if ('smtp' == $_POST['deliver']) {
322
+ $this->deliver_backup ($this->backup_file, $_POST['deliver'], $_POST['backup_recipient']);
323
+ } elseif ('http' == $_POST['deliver']) {
324
+ $this_basename = preg_replace('/^.*wp-content[\\\\\/]plugins[\\\\\/]/', '', __FILE__);
325
+ header('Refresh: 3; ' . get_option('siteurl') . "/wp-admin/edit.php?page={$this_basename}&backup={$this->backup_file}");
326
+ }
327
+ // we do this to say we're done.
328
+ $this->backup_complete = true;
329
+ }
330
+ }
331
+
332
+ function admin_menu() {
333
+ add_management_page(__('Backup'), __('Backup'), 'import', basename(__FILE__), array(&$this, 'backup_menu'));
334
+ }
335
 
336
+ function fragment_menu() {
337
+ add_management_page(__('Backup'), __('Backup'), 'import', basename(__FILE__), array(&$this, 'build_backup_script'));
338
+ }
 
 
339
 
340
+ function sql_addslashes($a_string = '', $is_like = FALSE) {
341
+ /*
342
+ Better addslashes for SQL queries.
343
+ Taken from phpMyAdmin.
344
+ */
345
+ if ($is_like) {
346
+ $a_string = str_replace('\\', '\\\\\\\\', $a_string);
347
+ } else {
348
+ $a_string = str_replace('\\', '\\\\', $a_string);
349
+ }
350
+ $a_string = str_replace('\'', '\\\'', $a_string);
351
+
352
+ return $a_string;
353
+ } // function sql_addslashes($a_string = '', $is_like = FALSE)
354
+
355
+ function backquote($a_name) {
356
+ /*
357
+ Add backqouotes to tables and db-names in
358
+ SQL queries. Taken from phpMyAdmin.
359
+ */
360
+ if (!empty($a_name) && $a_name != '*') {
361
+ if (is_array($a_name)) {
362
+ $result = array();
363
+ reset($a_name);
364
+ while(list($key, $val) = each($a_name)) {
365
+ $result[$key] = '`' . $val . '`';
366
+ }
367
+ return $result;
368
+ } else {
369
+ return '`' . $a_name . '`';
370
+ }
371
+ } else {
372
+ return $a_name;
373
+ }
374
+ } // function backquote($a_name, $do_it = TRUE)
375
+
376
+ function open($filename = '', $mode = 'w') {
377
+ if ('' == $filename) return false;
378
+ if ($this->gzip()) {
379
+ $fp = @gzopen($filename, $mode);
380
+ } else {
381
+ $fp = @fopen($filename, $mode);
382
+ }
383
+ return $fp;
384
+ }
385
 
386
+ function close($fp) {
387
+ if ($this->gzip()) {
388
+ gzclose($fp);
389
+ } else {
390
+ fclose($fp);
391
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
392
  }
 
 
 
 
393
 
394
+ function stow($query_line) {
395
+ if ($this->gzip()) {
396
+ if(@gzwrite($this->fp, $query_line) === FALSE) {
397
+ backup_error(__('There was an error writing a line to the backup script:'));
398
+ backup_error('&nbsp;&nbsp;' . $query_line);
399
+ }
400
+ } else {
401
+ if(@fwrite($this->fp, $query_line) === FALSE) {
402
+ backup_error(__('There was an error writing a line to the backup script:'));
403
+ backup_error('&nbsp;&nbsp;' . $query_line);
404
+ }
405
+ }
406
+ }
407
+
408
+ function backup_error($err) {
409
+ if(count($this->backup_errors) < 20) {
410
+ $this->backup_errors[] = $err;
411
+ } elseif(count($this->backup_errors) == 20) {
412
+ $this->backup_errors[] = __('Subsequent errors have been omitted from this log.');
413
+ }
414
+ }
415
 
416
+ function backup_table($table, $segment = 'none') {
417
+ global $wpdb;
418
+
419
+ /*
420
+ Taken partially from phpMyAdmin and partially from
421
+ Alain Wolf, Zurich - Switzerland
422
+ Website: http://restkultur.ch/personal/wolf/scripts/db_backup/
423
+
424
+ Modified by Scott Merril (http://www.skippy.net/)
425
+ to use the WordPress $wpdb object
426
+ */
427
+
428
+ $table_structure = $wpdb->get_results("DESCRIBE $table");
429
+ if (! $table_structure) {
430
+ backup_errors(__('Error getting table details') . ": $table");
431
+ return FALSE;
432
+ }
433
+
434
+ if(($segment == 'none') || ($segment == 0)) {
435
+ // Add SQL statement to drop existing table
436
+ $this->stow("\n\n");
437
+ $this->stow("#\n");
438
+ $this->stow("# Delete any existing table " . $this->backquote($table) . "\n");
439
+ $this->stow("#\n");
440
+ $this->stow("\n");
441
+ $this->stow("DROP TABLE IF EXISTS " . $this->backquote($table) . ";\n");
442
+
443
+ // Table structure
444
+ // Comment in SQL-file
445
+ $this->stow("\n\n");
446
+ $this->stow("#\n");
447
+ $this->stow("# Table structure of table " . $this->backquote($table) . "\n");
448
+ $this->stow("#\n");
449
+ $this->stow("\n");
450
+
451
+ $create_table = $wpdb->get_results("SHOW CREATE TABLE $table", ARRAY_N);
452
+ if (FALSE === $create_table) {
453
+ $this->backup_error(sprintf(__("Error with SHOW CREATE TABLE for %s."), $table));
454
+ $this->stow("#\n# Error with SHOW CREATE TABLE for $table!\n#\n");
455
+ }
456
+ $this->stow($create_table[0][1] . ' ;');
457
+
458
+ if (FALSE === $table_structure) {
459
+ $this->backup_error(sprintf(__("Error getting table structure of %s"), $table));
460
+ $this->stow("#\n# Error getting table structure of $table!\n#\n");
461
+ }
462
+
463
+ // Comment in SQL-file
464
+ $this->stow("\n\n");
465
+ $this->stow("#\n");
466
+ $this->stow('# Data contents of table ' . $this->backquote($table) . "\n");
467
+ $this->stow("#\n");
468
+ }
469
+
470
+ if(($segment == 'none') || ($segment >= 0)) {
471
+ $ints = array();
472
+ foreach ($table_structure as $struct) {
473
+ if ( (0 === strpos($struct->Type, 'tinyint')) ||
474
+ (0 === strpos(strtolower($struct->Type), 'smallint')) ||
475
+ (0 === strpos(strtolower($struct->Type), 'mediumint')) ||
476
+ (0 === strpos(strtolower($struct->Type), 'int')) ||
477
+ (0 === strpos(strtolower($struct->Type), 'bigint')) ||
478
+ (0 === strpos(strtolower($struct->Type), 'timestamp')) ) {
479
+ $ints[strtolower($struct->Field)] = "1";
480
+ }
481
+ }
482
+
483
+
484
+ // Batch by $row_inc
485
+
486
+ if($segment == 'none') {
487
+ $row_start = 0;
488
+ $row_inc = ROWS_PER_SEGMENT;
489
+ } else {
490
+ $row_start = $segment * ROWS_PER_SEGMENT;
491
+ $row_inc = ROWS_PER_SEGMENT;
492
+ }
493
+
494
+ do {
495
+ if ( !ini_get('safe_mode')) @set_time_limit(15*60);
496
+ $table_data = $wpdb->get_results("SELECT * FROM $table LIMIT {$row_start}, {$row_inc}", ARRAY_A);
497
+
498
+ /*
499
+ if (FALSE === $table_data) {
500
+ $wp_backup_error .= "Error getting table contents from $table\r\n";
501
+ fwrite($fp, "#\n# Error getting table contents fom $table!\n#\n");
502
+ }
503
+ */
504
+
505
+ $entries = 'INSERT INTO ' . $this->backquote($table) . ' VALUES (';
506
+ // \x08\\x09, not required
507
+ $search = array("\x00", "\x0a", "\x0d", "\x1a");
508
+ $replace = array('\0', '\n', '\r', '\Z');
509
+ if($table_data) {
510
+ foreach ($table_data as $row) {
511
+ $values = array();
512
+ foreach ($row as $key => $value) {
513
+ if ($ints[strtolower($key)]) {
514
+ $values[] = $value;
515
+ } else {
516
+ $values[] = "'" . str_replace($search, $replace, $this->sql_addslashes($value)) . "'";
517
+ }
518
+ }
519
+ $this->stow(" \n" . $entries . implode(', ', $values) . ') ;');
520
+ }
521
+ $row_start += $row_inc;
522
+ }
523
+ } while((count($table_data) > 0) and ($segment=='none'));
524
+ }
525
+
526
+
527
+ if(($segment == 'none') || ($segment < 0)) {
528
+ // Create footer/closing comment in SQL-file
529
+ $this->stow("\n");
530
+ $this->stow("#\n");
531
+ $this->stow("# End of data contents of table " . $this->backquote($table) . "\n");
532
+ $this->stow("# --------------------------------------------------------\n");
533
+ $this->stow("\n");
534
+ }
535
+
536
+ } // end backup_table()
537
+
538
+ function return_bytes($val) {
539
+ $val = trim($val);
540
+ $last = strtolower($val{strlen($val)-1});
541
+ switch($last) {
542
+ // The 'G' modifier is available since PHP 5.1.0
543
+ case 'g':
544
+ $val *= 1024;
545
+ case 'm':
546
+ $val *= 1024;
547
+ case 'k':
548
+ $val *= 1024;
549
+ }
550
+
551
+ return $val;
552
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
553
 
554
+ function db_backup($core_tables, $other_tables) {
555
+ global $table_prefix, $wpdb;
556
+
557
+ $datum = date("Ymd_B");
558
+ $wp_backup_filename = DB_NAME . "_$table_prefix$datum.sql";
559
+ if ($this->gzip()) {
560
+ $wp_backup_filename .= '.gz';
561
+ }
562
+
563
+ if (is_writable(ABSPATH . $this->backup_dir)) {
564
+ $this->fp = $this->open(ABSPATH . $this->backup_dir . $wp_backup_filename);
565
+ if(!$this->fp) {
566
+ $this->backup_error(__('Could not open the backup file for writing!'));
567
+ return false;
568
+ }
569
+ } else {
570
+ $this->backup_error(__('The backup directory is not writeable!'));
571
+ return false;
572
+ }
573
+
574
+ //Begin new backup of MySql
575
+ $this->stow("# WordPress MySQL database backup\n");
576
+ $this->stow("#\n");
577
+ $this->stow("# Generated: " . date("l j. F Y H:i T") . "\n");
578
+ $this->stow("# Hostname: " . DB_HOST . "\n");
579
+ $this->stow("# Database: " . $this->backquote(DB_NAME) . "\n");
580
+ $this->stow("# --------------------------------------------------------\n");
581
+
582
+ if ( (is_array($other_tables)) && (count($other_tables) > 0) )
583
+ $tables = array_merge($core_tables, $other_tables);
584
+ else
585
+ $tables = $core_tables;
586
+
587
+ foreach ($tables as $table) {
588
+ // Increase script execution time-limit to 15 min for every table.
589
+ if ( !ini_get('safe_mode')) @set_time_limit(15*60);
590
+ // Create the SQL statements
591
+ $this->stow("# --------------------------------------------------------\n");
592
+ $this->stow("# Table: " . $this->backquote($table) . "\n");
593
+ $this->stow("# --------------------------------------------------------\n");
594
+ $this->backup_table($table);
595
+ }
596
+
597
+ $this->close($this->fp);
598
+
599
+ if (count($this->backup_errors)) {
600
+ return false;
601
+ } else {
602
+ return $wp_backup_filename;
603
+ }
604
+
605
+ } //wp_db_backup
606
 
607
+ function deliver_backup ($filename = '', $delivery = 'http', $recipient = '') {
608
+ if ('' == $filename) { return FALSE; }
609
+
610
+ $diskfile = ABSPATH . $this->backup_dir . $filename;
611
+ if ('http' == $delivery) {
612
+ if (! file_exists($diskfile)) {
613
+ $msg = sprintf(__('File not found:%s'), "<br /><strong>$filename</strong><br />");
614
+ $this_basename = preg_replace('/^.*wp-content[\\\\\/]plugins[\\\\\/]/', '', __FILE__);
615
+ $msg .= '<br /><a href="' . get_option('siteurl') . "/wp-admin/edit.php?page={$this_basename}" . '">' . __('Return to Backup');
616
+ die($msg);
617
+ }
618
+ header('Content-Description: File Transfer');
619
+ header('Content-Type: application/octet-stream');
620
+ header('Content-Length: ' . filesize($diskfile));
621
+ header("Content-Disposition: attachment; filename=$filename");
622
+ readfile($diskfile);
623
+ unlink($diskfile);
624
+ } elseif ('smtp' == $delivery) {
625
+ if (! file_exists($diskfile)) return false;
626
+
627
+ if (! is_email ($recipient)) {
628
+ $recipient = get_option('admin_email');
629
+ }
630
+ $randomish = md5(time());
631
+ $boundary = "==WPBACKUP-BY-SKIPPY-$randomish";
632
+ $fp = fopen($diskfile,"rb");
633
+ $file = fread($fp,filesize($diskfile));
634
+ $this->close($fp);
635
+ $data = chunk_split(base64_encode($file));
636
+ $headers = "MIME-Version: 1.0\n";
637
+ $headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\n";
638
+ $headers .= 'From: ' . get_option('admin_email') . "\n";
639
+
640
+ $message = sprintf(__("Attached to this email is\n %1s\n Size:%2s kilobytes\n"), $filename, round(filesize($diskfile)/1024));
641
+ // Add a multipart boundary above the plain message
642
+ $message = "This is a multi-part message in MIME format.\n\n" .
643
+ "--{$boundary}\n" .
644
+ "Content-Type: text/plain; charset=\"utf-8\"\n" .
645
+ "Content-Transfer-Encoding: 7bit\n\n" .
646
+ $message . "\n\n";
647
+
648
+ // Add file attachment to the message
649
+ $message .= "--{$boundary}\n" .
650
+ "Content-Type: application/octet-stream;\n" .
651
+ " name=\"{$filename}\"\n" .
652
+ "Content-Disposition: attachment;\n" .
653
+ " filename=\"{$filename}\"\n" .
654
+ "Content-Transfer-Encoding: base64\n\n" .
655
+ $data . "\n\n" .
656
+ "--{$boundary}--\n";
657
+
658
+ if (function_exists('wp_mail')) {
659
+ wp_mail ($recipient, get_bloginfo('name') . ' ' . __('Database Backup'), $message, $headers);
660
+ } else {
661
+ mail ($recipient, get_bloginfo('name') . ' ' . __('Database Backup'), $message, $headers);
662
+ }
663
+
664
+ unlink($diskfile);
665
+ }
666
+ return;
667
+ }
668
 
669
+ function backup_menu() {
670
+ global $table_prefix, $wpdb;
671
+ $feedback = '';
672
+ $WHOOPS = FALSE;
673
+
674
+ // did we just do a backup? If so, let's report the status
675
+ if ( $this->backup_complete ) {
676
+ $feedback = '<div class="updated"><p>' . __('Backup Successful') . '!';
677
+ $file = $this->backup_file;
678
+ switch($_POST['deliver']) {
679
+ case 'http':
680
+ $feedback .= '<br />' . sprintf(__('Your backup file: <a href="%1s">%2s</a> should begin downloading shortly.'), get_option('siteurl') . "/{$this->backup_dir}{$this->backup_file}", $this->backup_file);
681
+ break;
682
+ case 'smtp':
683
+ if (! is_email($_POST['backup_recipient'])) {
684
+ $feedback .= get_option('admin_email');
685
+ } else {
686
+ $feedback .= $_POST['backup_recipient'];
687
+ }
688
+ $feedback = '<br />' . sprintf(__('Your backup has been emailed to %s'), $feedback);
689
+ break;
690
+ case 'none':
691
+ $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"');
692
+ $feedback .= ':<br /> <a href="' . get_option('siteurl') . "/{$this->backup_dir}$file\">$file</a> : " . sprintf(__('%s bytes'), filesize(ABSPATH . $this->backup_dir . $file));
693
+ }
694
+ $feedback .= '</p></div>';
695
+ }
696
+
697
+ if (count($this->backup_errors)) {
698
+ $feedback .= '<div class="updated error">' . __('The following errors were reported:') . "<pre>";
699
+ foreach($this->backup_errors as $error) {
700
+ $feedback .= "{$error}\n"; //Errors are already localized
701
+ }
702
+ $feedback .= "</pre></div>";
703
+ }
704
+
705
+ // did we just save options for wp-cron?
706
+ if ( (function_exists('wp_schedule_event') || function_exists('wp_cron_init'))
707
+ && isset($_POST['wp_cron_backup_options']) ) :
708
+ if ( function_exists('wp_schedule_event') ) {
709
+ wp_clear_scheduled_hook( 'wp_db_backup_cron' ); // unschedule previous
710
+ $scheds = (array) wp_get_schedules();
711
+ $name = strval($_POST['wp_cron_schedule']);
712
+ $interval = ( isset($scheds[$name]['interval']) ) ?
713
+ (int) $scheds[$name]['interval'] : 0;
714
+ update_option('wp_cron_backup_schedule', $name, FALSE);
715
+ if ( ! 0 == $interval ) {
716
+ wp_schedule_event(time() + $interval, $name, 'wp_db_backup_cron');
717
+ }
718
+ }
719
+ else {
720
+ update_option('wp_cron_backup_schedule', intval($_POST['cron_schedule']), FALSE);
721
+ }
722
+ update_option('wp_cron_backup_tables', $_POST['wp_cron_backup_tables']);
723
+ if (is_email($_POST['cron_backup_recipient'])) {
724
+ update_option('wp_cron_backup_recipient', $_POST['cron_backup_recipient'], FALSE);
725
+ }
726
+ $feedback .= '<div class="updated"><p>' . __('Scheduled Backup Options Saved!') . '</p></div>';
727
+ endif;
728
+
729
+ $other_tables = array();
730
+ $also_backup = array();
731
+
732
+ // Get complete db table list
733
+ $all_tables = $wpdb->get_results("SHOW TABLES", ARRAY_N);
734
+ $all_tables = array_map(create_function('$a', 'return $a[0];'), $all_tables);
735
+ // Get list of WP tables that actually exist in this DB (for 1.6 compat!)
736
+ $wp_backup_default_tables = array_intersect($all_tables, $this->core_table_names);
737
+ // Get list of non-WP tables
738
+ $other_tables = array_diff($all_tables, $wp_backup_default_tables);
739
+
740
+ if ('' != $feedback) {
741
+ echo $feedback;
742
+ }
743
 
744
+ // Give the new dirs the same perms as wp-content.
745
+ $stat = stat( ABSPATH . 'wp-content' );
746
+ $dir_perms = $stat['mode'] & 0000777; // Get the permission bits.
747
+
748
+ if ( !file_exists( ABSPATH . $this->backup_dir) ) {
749
+ if ( @ mkdir( ABSPATH . $this->backup_dir) ) {
750
+ @ chmod( ABSPATH . $this->backup_dir, $dir_perms);
751
+ } else {
752
+ echo '<div class="updated error"><p align="center">' . __('WARNING: Your wp-content directory is <strong>NOT</strong> writable! We can not create the backup directory.') . '<br />' . ABSPATH . $this->backup_dir . "</p></div>";
753
+ $WHOOPS = TRUE;
754
+ }
755
+ }
756
+
757
+ if ( !is_writable( ABSPATH . $this->backup_dir) ) {
758
+ echo '<div class="updated error"><p align="center">' . __('WARNING: Your backup directory is <strong>NOT</strong> writable! We can not create the backup directory.') . '<br />' . ABSPATH . "</p></div>";
759
+ }
760
+
761
+ if ( !file_exists( ABSPATH . $this->backup_dir . 'index.php') ) {
762
+ @ touch( ABSPATH . $this->backup_dir . "index.php");
763
+ }
764
+
765
+ ?><div class='wrap'>
766
+ <h2><?php _e('Backup') ?></h2>
767
+ <form method="post" action="">
768
+ <fieldset class="options"><legend><?php _e('Tables') ?></legend>
769
+ <table align="center" cellspacing="5" cellpadding="5"><tr><td width="50%" align="left" class="alternate" valign="top">
770
+ <?php _e('These core WordPress tables will always be backed up:') ?><br /><ul><?php
771
+ foreach ($wp_backup_default_tables as $table) {
772
+ echo "<li><input type='hidden' name='core_tables[]' value='$table' />$table</li>";
773
+ }
774
+ ?></ul></td><td width="50%" align="left" valign="top"><?php
775
+ if (count($other_tables) > 0) {
776
+ echo __('You may choose to include any of the following tables:') . ' <br />';
777
+ foreach ($other_tables as $table) {
778
+ echo "<label style=\"display:block;\"><input type='checkbox' name='other_tables[]' value='{$table}' /> {$table}</label>";
779
+ }
780
+ }
781
+ ?></td></tr></table></fieldset>
782
+ <fieldset class="options"><legend><?php _e('Backup Options') ?></legend>
783
+ <?php _e('What to do with the backup file:') ?><br />
784
+ <label for="do_save" style="display:block;"><input type="radio" id="do_save" name="deliver" value="none" style="border:none;" />
785
+ <?php echo __('Save to server') . " ({$this->backup_dir})</label>";
786
+ ?><label for="do_download" style="display:block;"><input type="radio" checked="checked" id="do_download" name="deliver" value="http" style="border:none;" />
787
+ <?php _e('Download to your computer') ?></label>
788
+ <label for="do_email"><input type="radio" name="deliver" id="do_email" value="smtp" style="border:none;" />
789
+ <?php _e('Email backup to:') ?></label><input type="text" name="backup_recipient" size="20" value="<?php echo get_option('admin_email') ?>" />
790
+
791
+ <?php
792
+ // Check DB dize.
793
+ $table_status = $wpdb->get_results("SHOW TABLE STATUS FROM " . $this->backquote(DB_NAME));
794
+ $core_size = $db_size = 0;
795
+ foreach($table_status as $table) {
796
+ $table_size = $table->Data_length - $table->Data_free;
797
+ if(in_array($table->Name, $wp_backup_default_tables)) {
798
+ $core_size += $table_size;
799
+ }
800
+ $db_size += $table_size;
801
+ }
802
+ $mem_limit = ini_get('memory_limit');
803
+ $mem_limit = $this->return_bytes($mem_limit);
804
+ $mem_limit = ($mem_limit == 0) ? 8*1024*1024 : $mem_limit - 2000000;
805
+
806
+ if (! $WHOOPS) {
807
+ echo '<input type="hidden" name="do_backup" id="do_backup" value="backup" />';
808
+ echo '<p class="submit"><input type="submit" name="submit" onclick="document.getElementById(\'do_backup\').value=\'fragments\';" value="' . __('Backup') . '!" /></p>';
809
  } else {
810
+ echo '<p class="alternate">' . __('WARNING: Your backup directory is <strong>NOT</strong> writable!') . '</p>';
811
  }
812
+ echo '</fieldset>';
813
+ echo '</form>';
814
+
815
+ // this stuff only displays if some sort of wp-cron is available
816
+ $cron = ( function_exists('wp_schedule_event') ) ? true : false; // wp-cron in WP 2.1+
817
+ $cron_old = ( function_exists('wp_cron_init') && ! $cron ) ? true : false; // wp-cron plugin by Skippy
818
+ if ( $cron_old || $cron ) :
819
+ echo '<fieldset class="options"><legend>' . __('Scheduled Backup') . '</legend>';
820
+ $datetime = get_option('date_format') . ' @ ' . get_option('time_format');
821
+ if ( $cron ) :
822
+ if ( ! ( 'never' == $this->get_sched() ) ) :
823
+ echo '<p>' . __('Next Backup') . ': ';
824
+ echo gmdate($datetime, wp_next_scheduled('wp_db_backup_cron') + (get_option('gmt_offset') * 3600)) . '</p>';
825
+ endif;
826
+ elseif ( $cron_old ) :
827
+ echo '<p>' . __('Last WP-Cron Daily Execution') . ': ' . gmdate($datetime, get_option('wp_cron_daily_lastrun') + (get_option('gmt_offset') * 3600)) . '<br />';
828
+ echo __('Next WP-Cron Daily Execution') . ': ' . gmdate($datetime, (get_option('wp_cron_daily_lastrun') + (get_option('gmt_offset') * 3600) + 86400)) . '</p>';
829
+ endif;
830
+ ?><form method="post" action="">
831
+ <table width="100%" cellpadding="5" cellspacing="5">
832
+ <tr><td align="center"><?php
833
+ echo __('Schedule: ');
834
+ if ( $cron_old ) :
835
+ $wp_cron_backup_schedule = get_option('wp_cron_backup_schedule');
836
+ $schedule = array(0 => __('None'), 1 => __('Daily'));
837
+ foreach ($schedule as $value => $name) {
838
+ echo ' <input type="radio" style="border:none;" name="cron_schedule"';
839
+ if ($wp_cron_backup_schedule == $value) {
840
+ echo ' checked="checked" ';
841
+ }
842
+ echo 'value="' . $value . '" /> ' . __($name);
843
+ }
844
+ elseif ( $cron ) :
845
+ echo apply_filters('wp_db_b_schedule_choices', wp_get_schedules() );
846
+ endif;
847
+ echo '</td><td align="center">';
848
+ $cron_recipient = get_option('wp_cron_backup_recipient');
849
+ if (! is_email($cron_recipient)) {
850
+ $cron_recipient = get_option('admin_email');
851
+ }
852
+ echo __('Email backup to:') . ' <input type="text" name="cron_backup_recipient" size="20" value="' . $cron_recipient . '" />';
853
+ echo '</td></tr>';
854
+ $cron_tables = get_option('wp_cron_backup_tables');
855
+ if (! is_array($cron_tables)) {
856
+ $cron_tables = array();
857
+ }
858
+ if (count($other_tables) > 0) {
859
+ echo '<tr><td colspan="2" align="left">' . __('Tables to include:') . '<br />';
860
+ foreach ($other_tables as $table) {
861
+ echo '<input type="checkbox" ';
862
+ if (in_array($table, $cron_tables)) {
863
+ echo 'checked=checked ';
864
+ }
865
+ echo "name='wp_cron_backup_tables[]' value='{$table}' /> {$table}<br />";
866
+ }
867
+ echo '</td></tr>';
868
+ }
869
+ echo '<tr><td colspan="2" align="center"><input type="hidden" name="wp_cron_backup_options" value="SET" /><input type="submit" name="submit" value="' . __('Submit') . '" /></td></tr></table></form>';
870
+ echo '</fieldset>';
871
+ endif; // end of wp_cron (legacy) section
872
+
873
+ echo '</div>';
874
+
875
+ } // end wp_backup_menu()
876
+
877
+ function get_sched() {
878
+ $options = array_keys( (array) wp_get_schedules() );
879
+ $freq = get_option('wp_cron_backup_schedule');
880
+ $freq = ( in_array( $freq , $options ) ) ? $freq : 'never';
881
+ return $freq;
882
  }
 
 
 
 
883
 
884
+ function schedule_choices($schedule) { // create the cron menu based on the schedule
885
+ $wp_cron_backup_schedule = $this->get_sched();
886
+ $sort = array();
887
+ foreach ( (array) $schedule as $key => $value ) $sort[$key] = $value['interval'];
888
+ asort( $sort );
889
+ $schedule_sorted = array();
890
+ foreach ( (array) $sort as $key => $value ) $schedule_sorted[$key] = $schedule[$key];
891
+ $menu = '<ul style="list-style: none; text-align: left">';
892
+ $schedule = array_merge( array( 'never' => array( 'interval' => 0, 'display' => __('Never') ) ),
893
+ (array) $schedule_sorted );
894
+ foreach ( $schedule as $name => $settings) {
895
+ $interval = (int) $settings['interval'];
896
+ if ( 0 == $interval && ! 'never' == $name ) continue;
897
+ $display = ( ! '' == $settings['display'] ) ? $settings['display'] : sprintf(__('%s seconds'),$interval);
898
+ $menu .= "<li><input type='radio' name='wp_cron_schedule' style='border:none;'";
899
+ if ($wp_cron_backup_schedule == $name) {
900
+ $menu .= ' checked="checked" ';
901
+ }
902
+ $menu .= "value='$name' /> $display</li>";
903
+ }
904
+ $menu .= '</ul>';
905
+ return $menu;
906
+ } // end schedule_choices()
907
+
908
+ function wp_cron_daily() { // for legacy cron plugin
909
+ $schedule = intval(get_option('wp_cron_backup_schedule'));
910
+ if (0 == $schedule) {
911
+ // Scheduled backup is disabled
912
+ return;
913
+ }
914
+ else { $this->cron_backup(); }
915
+ } // wp_cron_daily
916
+
917
+ function cron_backup() {
918
+ global $table_prefix, $wpdb;
919
+
920
+ $all_tables = $wpdb->get_results("SHOW TABLES", ARRAY_N);
921
+ $all_tables = array_map(create_function('$a', 'return $a[0];'), $all_tables);
922
+ $core_tables = array_intersect($all_tables, $this->core_table_names);
923
+ $other_tables = get_option('wp_cron_backup_tables');
924
+
925
+ $recipient = get_option('wp_cron_backup_recipient');
926
+
927
+ $backup_file = $this->db_backup($core_tables, $other_tables);
928
+ if (FALSE !== $backup_file) {
929
+ $this->deliver_backup ($backup_file, 'smtp', $recipient);
930
+ }
931
+ return;
932
  }
 
 
933
 
934
+ function add_sched_options($sched) {
935
+ $sched['weekly'] = array('interval' => 604800, 'display' => __('Once Weekly'));
936
+ return $sched;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
937
  }
 
 
 
 
 
938
 
939
+ function user_can_backup() {
940
+ return current_user_can('import');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
941
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
942
 
943
+ function validate_file($file) {
944
+ if (false !== strpos($file, '..'))
945
+ die(__("Cheatin' uh ?"));
946
 
947
+ if (false !== strpos($file, './'))
948
+ die(__("Cheatin' uh ?"));
949
 
950
+ if (':' == substr($file, 1, 1))
951
+ die(__("Cheatin' uh ?"));
952
+ }
953
 
 
 
 
 
954
  }
955
 
956
+ function wpdbBackup_init() {
957
+ global $mywpdbbackup;
958
+ $mywpdbbackup = new wpdbBackup();
 
 
 
 
 
 
 
 
 
 
 
 
 
959
  }
960
 
961
+ add_action('plugins_loaded', 'wpdbBackup_init');
 
962
 
963
  ?>
wp-db-backup.pot ADDED
@@ -0,0 +1,235 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ msgid ""
2
+ msgstr ""
3
+ "Project-Id-Version: wp-db-backup 1.6\n"
4
+ "POT-Creation-Date: \n"
5
+ "PO-Revision-Date: 2005-08-07 21:26-0500\n"
6
+ "Last-Translator: skippy <skippy@skippy.net>\n"
7
+ "Language-Team: skippy <skippy@skippy.net>\n"
8
+ "MIME-Version: 1.0\n"
9
+ "Content-Type: text/plain; charset=utf-8\n"
10
+ "Content-Transfer-Encoding: 8bit\n"
11
+ "X-Poedit-Language: English\n"
12
+ "X-Poedit-Country: United States\n"
13
+ "X-Poedit-KeywordsList: __;_e\n"
14
+ "X-Poedit-Basepath: .\n"
15
+ "X-Poedit-SearchPath-0: .\n"
16
+
17
+ #: wp-db-backup.php:86
18
+ msgid " Backup Complete! "
19
+ msgstr ""
20
+
21
+ #: wp-db-backup.php:112
22
+ #: wp-db-backup.php:722
23
+ #: wp-db-backup.php:761
24
+ msgid "Backup"
25
+ msgstr ""
26
+
27
+ #: wp-db-backup.php:113
28
+ msgid "Progress"
29
+ msgstr ""
30
+
31
+ #: wp-db-backup.php:114
32
+ msgid "<p><strong>DO NOT DO THE FOLLOWING AS IT WILL CAUSE YOUR BACKUP TO FAIL:</strong></p> <ol><li>Close this browser</li><li>Reload this page</li><li>Click the Stop or Back buttons in your browser</li></ol>"
33
+ msgstr ""
34
+
35
+ #: wp-db-backup.php:115
36
+ msgid "Progress:"
37
+ msgstr ""
38
+
39
+ #: wp-db-backup.php:157
40
+ #, php-format
41
+ msgid "Backup complete, preparing <a href=\\\"%s\\\">backup</a> for download..."
42
+ msgstr ""
43
+
44
+ #: wp-db-backup.php:163
45
+ #, php-format
46
+ msgid "Backup complete, sending <a href=\\\"%s\\\">backup</a> via email..."
47
+ msgstr ""
48
+
49
+ #: wp-db-backup.php:169
50
+ #, php-format
51
+ msgid "Backup complete, download <a href=\\\"%s\\\">here</a>."
52
+ msgstr ""
53
+
54
+ #: wp-db-backup.php:218
55
+ msgid "Creating backup file..."
56
+ msgstr ""
57
+
58
+ #: wp-db-backup.php:221
59
+ #, php-format
60
+ msgid "Finished backing up table \\\"%s\\\"."
61
+ msgstr ""
62
+
63
+ #: wp-db-backup.php:223
64
+ #, php-format
65
+ msgid "Backing up table \\\"%s\\\"..."
66
+ msgstr ""
67
+
68
+ #: wp-db-backup.php:235
69
+ #: wp-db-backup.php:548
70
+ msgid "Could not open the backup file for writing!"
71
+ msgstr ""
72
+
73
+ #: wp-db-backup.php:239
74
+ #: wp-db-backup.php:552
75
+ msgid "The backup directory is not writeable!"
76
+ msgstr ""
77
+
78
+ #: wp-db-backup.php:374
79
+ #: wp-db-backup.php:379
80
+ msgid "There was an error writing a line to the backup script:"
81
+ msgstr ""
82
+
83
+ #: wp-db-backup.php:389
84
+ msgid "Subsequent errors have been omitted from this log."
85
+ msgstr ""
86
+
87
+ #: wp-db-backup.php:408
88
+ msgid "Error getting table details"
89
+ msgstr ""
90
+
91
+ #: wp-db-backup.php:433
92
+ #, php-format
93
+ msgid "Error with SHOW CREATE TABLE for %s."
94
+ msgstr ""
95
+
96
+ #: wp-db-backup.php:439
97
+ #, php-format
98
+ msgid "Error getting table structure of %s"
99
+ msgstr ""
100
+
101
+ #: wp-db-backup.php:596
102
+ msgid "File not found:"
103
+ msgstr ""
104
+
105
+ #: wp-db-backup.php:598
106
+ msgid "Return to Backup"
107
+ msgstr ""
108
+
109
+ #: wp-db-backup.php:623
110
+ msgid "Attached to this email is"
111
+ msgstr ""
112
+
113
+ #: wp-db-backup.php:623
114
+ msgid "Size"
115
+ msgstr ""
116
+
117
+ #: wp-db-backup.php:623
118
+ msgid "kilobytes"
119
+ msgstr ""
120
+
121
+ #: wp-db-backup.php:641
122
+ msgid "Database Backup"
123
+ msgstr ""
124
+
125
+ #: wp-db-backup.php:656
126
+ msgid "Backup Successful"
127
+ msgstr ""
128
+
129
+ #: wp-db-backup.php:660
130
+ msgid "Your backup file"
131
+ msgstr ""
132
+
133
+ #: wp-db-backup.php:660
134
+ msgid "should begin downloading shortly."
135
+ msgstr ""
136
+
137
+ #: wp-db-backup.php:668
138
+ #, php-format
139
+ msgid "Your backup has been emailed to %s"
140
+ msgstr ""
141
+
142
+ #: wp-db-backup.php:671
143
+ msgid "Your backup file has been saved on the server. If you would like to download it now, right click and select \"Save As\""
144
+ msgstr ""
145
+
146
+ #: wp-db-backup.php:671
147
+ msgid " bytes"
148
+ msgstr ""
149
+
150
+ #: wp-db-backup.php:677
151
+ msgid "The following errors were reported"
152
+ msgstr ""
153
+
154
+ #: wp-db-backup.php:691
155
+ msgid "Scheduled Backup Options Saved!"
156
+ msgstr ""
157
+
158
+ #: wp-db-backup.php:715
159
+ msgid "WARNING: Your backup directory does not exist!"
160
+ msgstr ""
161
+
162
+ #: wp-db-backup.php:718
163
+ #: wp-db-backup.php:763
164
+ msgid "WARNING: Your backup directory is <strong>NOT</strong> writable!"
165
+ msgstr ""
166
+
167
+ #: wp-db-backup.php:723
168
+ msgid "Tables"
169
+ msgstr ""
170
+
171
+ #: wp-db-backup.php:726
172
+ msgid "These core WordPress tables will always be backed up"
173
+ msgstr ""
174
+
175
+ #: wp-db-backup.php:732
176
+ msgid "You may choose to include any of the following tables"
177
+ msgstr ""
178
+
179
+ #: wp-db-backup.php:738
180
+ msgid "Backup Options"
181
+ msgstr ""
182
+
183
+ #: wp-db-backup.php:739
184
+ msgid "What to do with the backup file"
185
+ msgstr ""
186
+
187
+ #: wp-db-backup.php:740
188
+ msgid "Save to server"
189
+ msgstr ""
190
+
191
+ #: wp-db-backup.php:741
192
+ msgid "Download to your computer"
193
+ msgstr ""
194
+
195
+ #: wp-db-backup.php:743
196
+ #, php-format
197
+ msgid "<label for=\"do_email\">Email backup to:</label> %s"
198
+ msgstr ""
199
+
200
+ #: wp-db-backup.php:770
201
+ msgid "Scheduled Backup"
202
+ msgstr ""
203
+
204
+ #: wp-db-backup.php:771
205
+ msgid "Last WP-Cron Daily Execution"
206
+ msgstr ""
207
+
208
+ #: wp-db-backup.php:772
209
+ msgid "Next WP-Cron Daily Execution"
210
+ msgstr ""
211
+
212
+ #: wp-db-backup.php:776
213
+ msgid "Schedule: "
214
+ msgstr ""
215
+
216
+ #: wp-db-backup.php:778
217
+ msgid "None"
218
+ msgstr ""
219
+
220
+ #: wp-db-backup.php:778
221
+ msgid "Daily"
222
+ msgstr ""
223
+
224
+ #: wp-db-backup.php:791
225
+ msgid "Email backup to"
226
+ msgstr ""
227
+
228
+ #: wp-db-backup.php:798
229
+ msgid "Tables to include"
230
+ msgstr ""
231
+
232
+ #: wp-db-backup.php:808
233
+ msgid "Submit"
234
+ msgstr ""
235
+
wp-db-backup.txt CHANGED
@@ -1,10 +1,10 @@
1
  = WP-DB-Backup =
2
  tags: mysql, database, backup
3
- Contributors: Firas, LaughingLizard, MtDewVirus, Podz
4
 
5
- copyright (c) 2005 Scott Merrill (skippy@skippy.net)
6
 
7
- WP-DB-Backup allows you to easily backup your core WordPress database tables. You may also optionally backup other tables in the same database.
8
 
9
  Released under the terms of the GNU GPL, version 2.
10
  http://www.fsf.org/licensing/licenses/gpl.html
@@ -12,14 +12,15 @@ Released under the terms of the GNU GPL, version 2.
12
  NO WARRANTY.
13
 
14
  == Installation ==
15
- 1. Create a directory /wp-content/backup/ inside your WordPress directory.
16
  2. Make this directory writable by your webserver.
17
  For example:
18
  $ cd wordpress/wp-content
19
  $ mkdir backup
20
  $ chgrp www-data backup
21
  $ chmod g+w backup
22
- 3. Install and activate wp-db-backup.php
 
23
 
24
  == Usage ==
25
  1) Click the Manage menu in your WordPress admin area.
@@ -28,7 +29,7 @@ Released under the terms of the GNU GPL, version 2.
28
  The following core WordPress tables will be included in every backup:
29
  * wp_categories
30
  * wp_comments
31
- * wp_linkcategories
32
  * wp_links
33
  * wp_options
34
  * wp_post2cat
@@ -40,18 +41,15 @@ The following core WordPress tables will be included in every backup:
40
  3) The plugin will look for other tables in the same database. You may elect to include other tables in the backup.
41
  ** NOTE **
42
  Including other tables in your backup may substantially increase the
43
- size of the backup, which may in turn cause several problems:
44
- * PHP may run out of memory
45
- * PHP may run out of time
46
- * emailing the backup may fail because it's too big
47
 
48
  4) Select how you'd like the backup to be delivered:
49
- * None : this will create a file in /wp-content/backup/ for you to retreive later
 
50
  * Email : this will email the backup file to the address you specify
51
- * Download : this will send the backup file to your browser to be downloaded
52
 
53
- 5) Optionally elect to have the backup gzip. This is strongly recommended.
54
- 6) Click "Backup!" and your database backup will be delivered to you.
55
 
56
  The filename of the backup file will be of the form
57
  DB_prefix_date.sql
@@ -61,26 +59,46 @@ date = CCYYmmdd_B format: 20050711_039
61
  the "B" is the internet "Swatch" time.
62
  See the PHP date() function for details.
63
 
64
- When having the database backup emailed or sent to your browser for immediate download, the backup file will be _deleted_ from the server when the transfer is finished. Only if you select delivery method "None" will the backup file remain on your server.
65
 
66
  *** SECURITY WARNING ***
67
  Your database backup contains sensitive information,
68
  and should not be left on the server for any extended
69
- period of time. The "None" delivery method is provided
70
  as a convenience only. I will not accept any responsibility
71
  if other people obtain your backup file.
72
  *** SECURITY WARNING ***
73
 
74
  == Advanced ==
75
- Included with this plugin is a supplemental plugin, wp-cron-db-backup.php, which makes use of my WP-Cron plugin:
76
- http://www.skippy.net/blog/2005/05/26/plugin-wp-cron/
77
 
78
- If you also have installed and activated WP-Cron, you will have another set of options available at Manage -> Backup.
 
 
 
79
 
80
- Here you can schedule automated backups of your core WordPress tables, and have them emailed to the address of your choice.
 
81
 
82
- ONLY the core WordPress tables will be backed up
83
- no plugin tables will be included.
84
 
85
- This backup will occur once per day. To disable, select "None" for the schedule.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
1
  = WP-DB-Backup =
2
  tags: mysql, database, backup
3
+ Contributors: Scott Merrill, Firas, LaughingLizard, MtDewVirus, Podz, Ringmaster
4
 
5
+ copyright (c) 2007 Austin Matzko
6
 
7
+ WP-DB-Backup allows you easily to backup your core WordPress database tables. You may also backup other tables in the same database.
8
 
9
  Released under the terms of the GNU GPL, version 2.
10
  http://www.fsf.org/licensing/licenses/gpl.html
12
  NO WARRANTY.
13
 
14
  == Installation ==
15
+ 1. Create a directory /wp-content/backup-*/ inside your WordPress directory.
16
  2. Make this directory writable by your webserver.
17
  For example:
18
  $ cd wordpress/wp-content
19
  $ mkdir backup
20
  $ chgrp www-data backup
21
  $ chmod g+w backup
22
+ 3. Copy the wp-db-backup.php file to /wp-content/plugins/
23
+ 4. Activate the plugin at your blog Admin -> Plugins screen
24
 
25
  == Usage ==
26
  1) Click the Manage menu in your WordPress admin area.
29
  The following core WordPress tables will be included in every backup:
30
  * wp_categories
31
  * wp_comments
32
+ * wp_linkcategories / wp_link2cat
33
  * wp_links
34
  * wp_options
35
  * wp_post2cat
41
  3) The plugin will look for other tables in the same database. You may elect to include other tables in the backup.
42
  ** NOTE **
43
  Including other tables in your backup may substantially increase the
44
+ size of the backup file!
45
+ This may prevent you from emailing the backup file because it's too big.
 
 
46
 
47
  4) Select how you'd like the backup to be delivered:
48
+ * Save to server : this will create a file in /wp-content/backup-*/ for you to retreive later
49
+ * Download to your computer : this will send the backup file to your browser to be downloaded
50
  * Email : this will email the backup file to the address you specify
 
51
 
52
+ 5) Click "Backup!" and your database backup will be delivered to you.
 
53
 
54
  The filename of the backup file will be of the form
55
  DB_prefix_date.sql
59
  the "B" is the internet "Swatch" time.
60
  See the PHP date() function for details.
61
 
62
+ When having the database backup emailed or sent to your browser for immediate download, the backup file will be _deleted_ from the server when the transfer is finished. Only if you select delivery method "Save to server" will the backup file remain on your server.
63
 
64
  *** SECURITY WARNING ***
65
  Your database backup contains sensitive information,
66
  and should not be left on the server for any extended
67
+ period of time. The "Save to server" delivery method is provided
68
  as a convenience only. I will not accept any responsibility
69
  if other people obtain your backup file.
70
  *** SECURITY WARNING ***
71
 
72
  == Advanced ==
73
+ If you are using WordPress version 2.1 or newer, you can schedule automated backups to be sent to the email address
74
+ of your choice.
75
 
76
+ == Frequently Asked Questions ==
77
+ Q. What are wp-db-backup.mo and wp-db-backup.pot for?
78
+ A. These files are used by non-English users to translate the display into their native language. Translators are encouraged to send me translated files, which will be made available to others here:
79
+ http://dev.wp-plugins.org/browser/wp-db-backup/i18n/
80
 
81
+ Q. Why are only the core database files backed up by default?
82
+ A. Because it's a fairly safe bet that the core WordPress files will be successfully backed up. Plugins vary wildly in the amount of data that they store. For instance, it's not uncommon for some statistics plugins to have tens of megabytes worth of visitor statistics. These are not exactly essential items to restore after a catastrophic failure. Most poeple can reasonably live without this data in their backups.
83
 
84
+ Q. Will you add a button so that I can automatically select all my other tables to back up?
85
+ A. No. Such a button would encourage people to click it. The way it is now, you must deliberately select which additional tables to include in the backup. This is a safety mechanism as much for me as it is for you.
86
 
87
+ == Changelog ==
88
+ 2.0
89
+ Support for WordPress 2.1's built-in cron, for automated scheduled backups.
90
+
91
+ 1.7
92
+ Better error handling. Updated documentation.
93
+
94
+ 1.6
95
+ Integrated Owen's massive rewrite, the most noticable element being the introduction of a progress meter. The backup is now spooled to disk, a few rows at a time, to ensure that databases of all sizes can be backed up. Additionally, gzip support is now automatically detected, and used if available. This has been tested on a database over 30 megabytes uncompressed. Version 1.6 of wp-db-backup successfully backed up the whole thing without error, and transparently compressed it to just over 10 megabytes (many thanks to Lorelle for being such a willing guinea pig!).
96
+
97
+ 1.5
98
+ Applied patch from Owen (http://dev.wp-plugins.org/ticket/219)
99
+ -- the database dump is now spooled to disk to better support large databases.
100
+ If the user has selected immediate delivery, the file size will be evaluated. If less than 2 MB, the file will be gzip compressed (if the user asked for it); otherwise a helpful error message will be displayed.
101
+
102
+ 1.4
103
+ Initial relase.
104