UpdraftPlus WordPress Backup Plugin - Version 1.5.16

Version Description

New features: selective restoration, importing remote backups; plus many tweaks, optimisations + small bug-fixes: recommended upgrade for all

Download this release

Release Info

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

Code changes from version 1.5.6 to 1.5.16

admin.php ADDED
@@ -0,0 +1,1710 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!defined ('ABSPATH')) die ('No direct access allowed');
4
+
5
+ // For the purposes of improving site performance (don't load in 10s of Kilobytes of un-needed code on every page load), admin-area code is being progressively moved here.
6
+
7
+ // This gets called in wp_loaded, which is slightly before admin_init (so our object can get used by those hooking admin_init)
8
+
9
+ global $updraftplus_admin;
10
+ if (empty($updraftplus_admin)) $updraftplus_admin = new UpdraftPlus_Admin();
11
+
12
+ class UpdraftPlus_Admin {
13
+
14
+ function __construct() {
15
+
16
+ $this->wp_loaded();
17
+
18
+ }
19
+
20
+ function wp_loaded() {
21
+
22
+ add_action('admin_head', array($this,'admin_head'));
23
+ add_action('admin_init', array($this,'admin_init'));
24
+ add_filter('plugin_action_links', array($this, 'plugin_action_links'), 10, 2);
25
+ add_action('wp_ajax_updraft_download_backup', array($this, 'updraft_download_backup'));
26
+ add_action('wp_ajax_updraft_ajax', array($this, 'updraft_ajax_handler'));
27
+ add_action('wp_ajax_plupload_action', array($this,'plupload_action'));
28
+ add_action('wp_ajax_plupload_action2', array($this,'plupload_action2'));
29
+
30
+ }
31
+
32
+ function admin_init() {
33
+ global $updraftplus;
34
+
35
+ if(UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
36
+ @ini_set('display_errors',1);
37
+ @error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
38
+ }
39
+
40
+ if (UpdraftPlus_Options::user_can_manage() && UpdraftPlus_Options::get_updraft_option('updraft_service') == "googledrive" && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_clientid','') != '' && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_token','') == '') {
41
+ add_action('admin_notices', array($this,'show_admin_warning_googledrive') );
42
+ }
43
+
44
+ if (UpdraftPlus_Options::user_can_manage() && UpdraftPlus_Options::get_updraft_option('updraft_service') == "dropbox" && UpdraftPlus_Options::get_updraft_option('updraft_dropboxtk_request_token','') == '') {
45
+ add_action('admin_notices', array($this,'show_admin_warning_dropbox') );
46
+ }
47
+
48
+ if (UpdraftPlus_Options::user_can_manage() && $this->disk_space_check(1024*1024*35) === false) add_action('admin_notices', array($this, 'show_admin_warning_diskspace'));
49
+
50
+ global $wp_version, $pagenow;
51
+ if ($pagenow == 'options-general.php' && version_compare($wp_version, '3.2', '<')) add_action('admin_notices', array($this, 'show_admin_warning_wordpressversion'));
52
+
53
+ if ($pagenow == 'options-general.php' && isset($_REQUEST['page']) && 'updraftplus' == $_REQUEST['page']) {
54
+ wp_enqueue_script('jquery');
55
+ wp_enqueue_script('jquery-ui-dialog');
56
+ wp_enqueue_script('plupload-all');
57
+ wp_register_script('updraftplus-plupload', UPDRAFTPLUS_URL.'/includes/ud-plupload.js', array('jquery'));
58
+ wp_enqueue_script('updraftplus-plupload');
59
+ }
60
+ }
61
+
62
+ function admin_head() {
63
+
64
+ global $pagenow;
65
+ if ($pagenow != 'options-general.php' || !isset($_REQUEST['page']) && 'updraftplus' != $_REQUEST['page']) return;
66
+
67
+ $chunk_size = min(wp_max_upload_size()-1024, 1024*1024*2);
68
+
69
+ $plupload_init = array(
70
+ 'runtimes' => 'html5,silverlight,flash,html4',
71
+ 'browse_button' => 'plupload-browse-button',
72
+ 'container' => 'plupload-upload-ui',
73
+ 'drop_element' => 'drag-drop-area',
74
+ 'file_data_name' => 'async-upload',
75
+ 'multiple_queues' => true,
76
+ 'max_file_size' => '100Gb',
77
+ 'chunk_size' => $chunk_size.'b',
78
+ 'url' => admin_url('admin-ajax.php'),
79
+ 'flash_swf_url' => includes_url('js/plupload/plupload.flash.swf'),
80
+ 'silverlight_xap_url' => includes_url('js/plupload/plupload.silverlight.xap'),
81
+ 'filters' => array(array('title' => __('Allowed Files'), 'extensions' => 'zip,gz,crypt')),
82
+ 'multipart' => true,
83
+ 'multi_selection' => true,
84
+ 'urlstream_upload' => true,
85
+ // additional post data to send to our ajax hook
86
+ 'multipart_params' => array(
87
+ '_ajax_nonce' => wp_create_nonce('updraft-uploader'),
88
+ 'action' => 'plupload_action'
89
+ )
90
+ );
91
+
92
+ ?><script type="text/javascript">var updraft_plupload_config=<?php echo json_encode($plupload_init); ?>;</script>
93
+ <?php
94
+ $plupload_init['browse_button'] = 'plupload-browse-button2';
95
+ $plupload_init['container'] = 'plupload-upload-ui2';
96
+ $plupload_init['drop_element'] = 'drag-drop-area2';
97
+ $plupload_init['multipart_params']['action'] = 'plupload_action2';
98
+ $plupload_init['filters'] = array(array('title' => __('Allowed Files'), 'extensions' => 'crypt'));
99
+ ?><script type="text/javascript">var updraft_plupload_config2=<?php echo json_encode($plupload_init); ?>;
100
+ var updraft_downloader_nonce = '<?php wp_create_nonce("updraftplus_download"); ?>'
101
+ </script>
102
+ <style type="text/css">
103
+ .drag-drop #drag-drop-area2 {
104
+ border: 4px dashed #ddd;
105
+ height: 200px;
106
+ }
107
+ #drag-drop-area2 .drag-drop-inside {
108
+ margin: 36px auto 0;
109
+ width: 350px;
110
+ }
111
+ #filelist, #filelist2 {
112
+ width: 100%;
113
+ }
114
+ #filelist .file, #filelist2 .file, #ud_downloadstatus .file {
115
+ padding: 5px;
116
+ background: #ececec;
117
+ border: solid 1px #ccc;
118
+ margin: 4px 0;
119
+ }
120
+ #filelist .fileprogress, #filelist2 .fileprogress, #ud_downloadstatus .dlfileprogress {
121
+ width: 0%;
122
+ background: #f6a828;
123
+ height: 5px;
124
+ }
125
+ #ud_downloadstatus .raw {
126
+ margin-top: 8px;
127
+ clear:left;
128
+ }
129
+ #ud_downloadstatus .file {
130
+ margin-top: 8px;
131
+ }
132
+ </style>
133
+ <?php
134
+
135
+ }
136
+
137
+ function disk_space_check($space) {
138
+ global $updraftplus;
139
+ $updraft_dir = $updraftplus->backups_dir_location();
140
+ $disk_free_space = @disk_free_space($updraft_dir);
141
+ if ($disk_free_space == false) return -1;
142
+ return ($disk_free_space > $space) ? true : false;
143
+ }
144
+
145
+ # Adds the settings link under the plugin on the plugin screen.
146
+ function plugin_action_links($links, $file) {
147
+ if ($file == 'updraftplus/updraftplus.php'){
148
+ $settings_link = '<a href="'.site_url().'/wp-admin/options-general.php?page=updraftplus">'.__("Settings", "updraftplus").'</a>';
149
+ array_unshift($links, $settings_link);
150
+ // $settings_link = '<a href="http://david.dw-perspective.org.uk/donate">'.__("Donate","UpdraftPlus").'</a>';
151
+ // array_unshift($links, $settings_link);
152
+ $settings_link = '<a href="http://updraftplus.com">'.__("Add-Ons / Pro Support","updraftplus").'</a>';
153
+ array_unshift($links, $settings_link);
154
+ }
155
+ return $links;
156
+ }
157
+
158
+
159
+ function show_admin_warning($message, $class = "updated") {
160
+ echo '<div id="updraftmessage" class="'.$class.' fade">'."<p>$message</p></div>";
161
+ }
162
+
163
+ function show_admin_warning_diskspace() {
164
+ $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('You have less than %s of free disk space on the disk which UpdraftPlus is configured to use to create backups. UpdraftPlus could well run out of space. Contact your the operator of your server (e.g. your web hosting company) to resolve this issue.','updraftplus'),'35 Mb'));
165
+ }
166
+
167
+ function show_admin_warning_wordpressversion() {
168
+ $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('UpdraftPlus does not officially support versions of WordPress before %s. It may work for you, but if it does not, then please be aware that no support is available until you upgrade WordPress.'),'3.2'),'updraftplus');
169
+ }
170
+
171
+ function show_admin_warning_dropbox() {
172
+ $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus')/':</strong> <a href="options-general.php?page=updraftplus&action=updraftmethod-dropbox-auth&updraftplus_dropboxauth=doit">.'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'),'Dropbox','Dropbox').'</a>');
173
+ }
174
+
175
+ function show_admin_warning_googledrive() {
176
+ $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a href="options-general.php?page=updraftplus&action=updraftmethod-googledrive-auth&updraftplus_googleauth=doit">.'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'),'Google Drive','Google Drive').'</a>');
177
+ }
178
+
179
+ // This options filter removes ABSPATH off the front of updraft_dir, if it is given absolutely and contained within it
180
+ function prune_updraft_dir_prefix($updraft_dir) {
181
+ if ('/' == substr($updraft_dir, 0, 1) || "\\" == substr($updraft_dir, 0, 1) || preg_match('/^[a-zA-Z]:/', $updraft_dir)) {
182
+ if (strpos($updraft_dir, ABSPATH) === 0) {
183
+ $updraft_dir = substr($updraft_dir, strlen(ABSPATH));
184
+ }
185
+ }
186
+ return $updraft_dir;
187
+ }
188
+
189
+ function updraft_download_backup() {
190
+
191
+ @set_time_limit(900);
192
+
193
+ global $updraftplus;
194
+
195
+ if (!isset($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'], 'updraftplus_download')) die;
196
+
197
+ if (!isset($_REQUEST['timestamp']) || !is_numeric($_REQUEST['timestamp']) || !isset($_REQUEST['type'])) exit;
198
+
199
+ $backupable_entities = $updraftplus->get_backupable_file_entities(true);
200
+ $type_match = false;
201
+ foreach ($backupable_entities as $type => $info) {
202
+ if ($_REQUEST['type'] == $type) $type_match = true;
203
+ }
204
+
205
+ if (!$type_match && $_REQUEST['type'] != 'db') exit;
206
+
207
+ // Get the information on what is wanted
208
+ $type = $_REQUEST['type'];
209
+ $timestamp = $_REQUEST['timestamp'];
210
+
211
+ // You need a nonce before you can set job data. And we certainly don't yet have one.
212
+ $updraftplus->backup_time_nonce();
213
+
214
+ $debug_mode = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
215
+
216
+ // Set the job type before logging, as there can be different logging destinations
217
+ $updraftplus->jobdata_set('job_type', 'download');
218
+
219
+ // Retrieve the information from our backup history
220
+ $backup_history = $updraftplus->get_backup_history();
221
+ // Base name
222
+ $file = $backup_history[$timestamp][$type];
223
+
224
+ // Where it should end up being downloaded to
225
+ $fullpath = $updraftplus->backups_dir_location().'/'.$file;
226
+
227
+ if (isset($_GET['stage']) && '2' == $_GET['stage']) {
228
+ $updraftplus->spool_file($type, $fullpath);
229
+ die;
230
+ }
231
+
232
+ if (isset($_POST['stage']) && 'delete' == $_POST['stage']) {
233
+ @unlink($fullpath);
234
+ echo 'deleted';
235
+ $updraftplus->log('The file has been deleted');
236
+ die;
237
+ }
238
+
239
+ // TODO: FIXME: Failed downloads may leave log files forever (though they are small)
240
+ // Note that log() assumes that the data is in _POST, not _GET
241
+ if ($debug_mode) $updraftplus->logfile_open($updraftplus->nonce);
242
+
243
+ $updraftplus->log("Requested to obtain file: timestamp=$timestamp, type=$type");
244
+
245
+ $known_size = isset($backup_history[$timestamp][$type.'-size']) ? $backup_history[$timestamp][$type.'-size'] : 0;
246
+
247
+ $service = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
248
+ $updraftplus->jobdata_set('service', $service);
249
+
250
+ // Fetch it from the cloud, if we have not already got it
251
+
252
+ $needs_downloading = false;
253
+
254
+ if(!file_exists($fullpath)) {
255
+ //if the file doesn't exist and they're using one of the cloud options, fetch it down from the cloud.
256
+ $needs_downloading = true;
257
+ $updraftplus->log('File does not yet exist locally - needs downloading');
258
+ } elseif ($known_size>0 && filesize($fullpath) < $known_size) {
259
+ $updraftplus->log('The file was found locally but did not match the size in the backup history - will resume downloading');
260
+ $needs_downloading = true;
261
+ } elseif ($known_size>0) {
262
+ $updraftplus->log('The file was found locally and matched the recorded size from the backup history ('.round($known_size/1024,1).' Kb)');
263
+ } else {
264
+ $updraftplus->log('No file size was found recorded in the backup history. We will assume the local one is complete.');
265
+ $known_size = filesize($fullpath);
266
+ }
267
+
268
+ // The AJAX responder that updates on progress wants to see this
269
+ set_transient('ud_dlfile_'.$timestamp.'_'.$type, "downloading:$known_size:$fullpath", 3600);
270
+
271
+ if ($needs_downloading) {
272
+ // Close browser connection so that it can resume AJAX polling
273
+ header('Connection: close');
274
+ header('Content-Length: 0');
275
+ header('Content-Encoding: none');
276
+ session_write_close();
277
+ echo "\r\n\r\n";
278
+ $this->download_file($file, $service);
279
+ if (is_readable($fullpath)) {
280
+ $updraftplus->log('Remote fetch was successful (file size: '.round(filesize($fullpath)/1024,1).' Kb)');
281
+ } else {
282
+ $updraftplus->log('Remote fetch failed');
283
+ }
284
+ }
285
+
286
+ // Now, spool the thing to the browser
287
+ if(is_file($fullpath) && is_readable($fullpath)) {
288
+
289
+ // That message is then picked up by the AJAX listener
290
+ set_transient('ud_dlfile_'.$timestamp.'_'.$type, 'downloaded:'.filesize($fullpath).":$fullpath", 3600);
291
+
292
+ } else {
293
+
294
+ set_transient('ud_dlfile_'.$timestamp.'_'.$type, 'failed', 3600);
295
+ set_transient('ud_dlerrors_'.$timestamp.'_'.$type, $updraftplus->errors, 3600);
296
+
297
+ echo 'Remote fetch failed. File '.$fullpath.' did not exist or was unreadable. If you delete local backups then remote retrieval may have failed.';
298
+ }
299
+
300
+ @fclose($updraftplus->logfile_handle);
301
+ if (!$debug_mode) @unlink($updraftplus->logfile_name);
302
+
303
+ exit;
304
+
305
+ }
306
+
307
+ function download_file($file, $service=false) {
308
+
309
+ global $updraftplus;
310
+
311
+ @set_time_limit(900);
312
+
313
+ if (!$service) $service = UpdraftPlus_Options::get_updraft_option('updraft_service');
314
+
315
+ $updraftplus->log("Requested file from remote service: $service:$file");
316
+
317
+ $method_include = UPDRAFTPLUS_DIR.'/methods/'.$service.'.php';
318
+ if (file_exists($method_include)) require_once($method_include);
319
+
320
+ $objname = "UpdraftPlus_BackupModule_${service}";
321
+ if (method_exists($objname, "download")) {
322
+ $remote_obj = new $objname;
323
+ $remote_obj->download($file);
324
+ } else {
325
+ $updraftplus->log("Automatic backup restoration is not available with the method: $service.");
326
+ $updraftplus->error("$file: ".sprintf(__("The backup archive for restoring this file could not be found. The remote storage method in use (%s) does not allow us to retrieve files. To proceed with this restoration, you need to obtain a copy of this file and place it inside UpdraftPlus's working folder", 'updraftplus'), $service)." (".$this->prune_updraft_dir_prefix($updraftplus->backups_dir_location()).")");
327
+ }
328
+
329
+ }
330
+
331
+ // Called via AJAX
332
+ function updraft_ajax_handler() {
333
+
334
+ global $updraftplus;
335
+
336
+ // Test the nonce (probably not needed, since we're presumably admin-authed, but there's no harm)
337
+ $nonce = (empty($_REQUEST['nonce'])) ? "" : $_REQUEST['nonce'];
338
+ if (! wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce') || empty($_REQUEST['subaction'])) die('Security check');
339
+
340
+ if ('lastlog' == $_GET['subaction']) {
341
+ echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', '('.__('Nothing yet logged', 'updraftplus').')'));
342
+ } elseif ('lastbackup' == $_GET['subaction']) {
343
+ echo $this->last_backup_html();
344
+ } elseif ('diskspaceused' == $_GET['subaction']) {
345
+ echo $this->recursive_directory_size($updraftplus->backups_dir_location());
346
+ } elseif ('historystatus' == $_GET['subaction']) {
347
+ $rescan = (isset($_GET['rescan']) && $_GET['rescan'] == 1);
348
+ if ($rescan) $this->rebuild_backup_history();
349
+ echo $this->existing_backup_table();
350
+ } elseif ('downloadstatus' == $_GET['subaction'] && isset($_GET['timestamp']) && isset($_GET['type'])) {
351
+
352
+ $response = array();
353
+
354
+ $response['m'] = get_transient('ud_dlmess_'.$_GET['timestamp'].'_'.$_GET['type']).'<br>';
355
+
356
+ if ($file = get_transient('ud_dlfile_'.$_GET['timestamp'].'_'.$_GET['type'])) {
357
+ if ('failed' == $file) {
358
+ $response['e'] = __('Download failed','updraftplus').'<br>';
359
+ $errs = get_transient('ud_dlerrors_'.$_GET['timestamp'].'_'.$_GET['type']);
360
+ if (is_array($errs) && !empty($errs)) {
361
+ $response['e'] .= '<ul style="list-style: disc inside;">';
362
+ foreach ($errs as $err) {
363
+ $response['e'] .= '<li>'.htmlspecialchars($err).'</li>';
364
+ }
365
+ $response['e'] .= '</ul>';
366
+ }
367
+ } elseif (preg_match('/^downloaded:(\d+):(.*)$/', $file, $matches) && file_exists($matches[2])) {
368
+ $response['p'] = 100;
369
+ $response['f'] = $matches[2];
370
+ $response['s'] = (int)$matches[1];
371
+ $response['t'] = (int)$matches[1];
372
+ $response['m'] = __('File ready.', 'updraftplus');
373
+ } elseif (preg_match('/^downloading:(\d+):(.*)$/', $file, $matches) && file_exists($matches[2])) {
374
+ // Convert to bytes
375
+ $response['f'] = $matches[2];
376
+ $total_size = (int)max($matches[1], 1);
377
+ $cur_size = filesize($matches[2]);
378
+ $response['s'] = $cur_size;
379
+ $response['t'] = $total_size;
380
+ $response['m'] .= __("Download in progress", 'updraftplus').' ('.round($cur_size/1024).' / '.round($total_size, 1024).' Kb)';
381
+ $response['p'] = round(100*$cur_size/$total_size);
382
+ } else {
383
+ $response['m'] .= __('No local copy present.', 'updraftplus');
384
+ $response['p'] = 0;
385
+ $response['s'] = 0;
386
+ $response['t'] = 1;
387
+ }
388
+ }
389
+
390
+ echo json_encode($response);
391
+
392
+ } elseif ($_POST['subaction'] == 'credentials_test') {
393
+ $method = (preg_match("/^[a-z0-9]+$/", $_POST['method'])) ? $_POST['method'] : "";
394
+
395
+ // Test the credentials, return a code
396
+ require_once(UPDRAFTPLUS_DIR."/methods/$method.php");
397
+
398
+ $objname = "UpdraftPlus_BackupModule_${method}";
399
+ if (method_exists($objname, "credentials_test")) call_user_func(array('UpdraftPlus_BackupModule_'.$method, 'credentials_test'));
400
+ }
401
+
402
+ die;
403
+
404
+ }
405
+
406
+ function upload_dir($uploads) {
407
+ global $updraftplus;
408
+ $updraft_dir = $updraftplus->backups_dir_location();
409
+ if (is_writable($updraft_dir)) $uploads['path'] = $updraft_dir;
410
+ return $uploads;
411
+ }
412
+
413
+ // We do actually want to over-write
414
+ function unique_filename_callback($dir, $name, $ext) {
415
+ return $name.$ext;
416
+ }
417
+
418
+ function sanitize_file_name($filename) {
419
+ // WordPress 3.4.2 on multisite (at least) adds in an unwanted underscore
420
+ return preg_replace('/-db\.gz_\.crypt$/', '-db.gz.crypt', $filename);
421
+ }
422
+
423
+ function plupload_action() {
424
+ // check ajax noonce
425
+
426
+ global $updraftplus;
427
+ @set_time_limit(900);
428
+
429
+ check_ajax_referer('updraft-uploader');
430
+
431
+ $updraft_dir = $updraftplus->backups_dir_location();
432
+ if (!is_writable($updraft_dir)) exit;
433
+
434
+ add_filter('upload_dir', array($this, 'upload_dir'));
435
+ add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
436
+ // handle file upload
437
+
438
+ $farray = array( 'test_form' => true, 'action' => 'plupload_action' );
439
+
440
+ $farray['test_type'] = false;
441
+ $farray['ext'] = 'x-gzip';
442
+ $farray['type'] = 'application/octet-stream';
443
+
444
+ if (isset($_POST['chunks'])) {
445
+
446
+ } else {
447
+ $farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
448
+ }
449
+
450
+ $status = wp_handle_upload(
451
+ $_FILES['async-upload'],
452
+ $farray
453
+ );
454
+ remove_filter('upload_dir', array($this, 'upload_dir'));
455
+ remove_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
456
+
457
+ if (isset($status['error'])) {
458
+ echo 'ERROR:'.$status['error'];
459
+ exit;
460
+ }
461
+
462
+ // If this was the chunk, then we should instead be concatenating onto the final file
463
+ if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
464
+ $final_file = $_POST['name'];
465
+ rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
466
+ $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
467
+
468
+ // Final chunk? If so, then stich it all back together
469
+ if ($_POST['chunk'] == $_POST['chunks']-1) {
470
+ if ($wh = fopen($updraft_dir.'/'.$final_file, 'wb')) {
471
+ for ($i=0 ; $i<$_POST['chunks']; $i++) {
472
+ $rf = $updraft_dir.'/'.$final_file.'.'.$i.'.zip.tmp';
473
+ if ($rh = fopen($rf, 'rb')) {
474
+ while ($line = fread($rh, 32768)) fwrite($wh, $line);
475
+ fclose($rh);
476
+ @unlink($rf);
477
+ }
478
+ }
479
+ fclose($wh);
480
+ $status['file'] = $updraft_dir.'/'.$final_file;
481
+ }
482
+ }
483
+
484
+ }
485
+
486
+ if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
487
+ $file = basename($status['file']);
488
+ if (!preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(zip|gz|gz\.crypt)$/i', $file)) {
489
+
490
+ @unlink($status['file']);
491
+ echo 'ERROR:'.__('Bad filename format - this does not look like a file created by UpdraftPlus','updraftplus');
492
+ exit;
493
+ }
494
+ }
495
+
496
+ // send the uploaded file url in response
497
+ echo 'OK:'.$status['url'];
498
+ exit;
499
+ }
500
+
501
+ function plupload_action2() {
502
+
503
+ @set_time_limit(900);
504
+ global $updraftplus;
505
+
506
+ // check ajax nonce
507
+ check_ajax_referer('updraft-uploader');
508
+
509
+ $updraft_dir = $updraftplus->backups_dir_location();
510
+ if (!is_writable($updraft_dir)) exit;
511
+
512
+ add_filter('upload_dir', array($this, 'upload_dir'));
513
+ add_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
514
+ // handle file upload
515
+
516
+ $farray = array( 'test_form' => true, 'action' => 'plupload_action2' );
517
+
518
+ $farray['test_type'] = false;
519
+ $farray['ext'] = 'crypt';
520
+ $farray['type'] = 'application/octet-stream';
521
+
522
+ if (isset($_POST['chunks'])) {
523
+ // $farray['ext'] = 'zip';
524
+ // $farray['type'] = 'application/zip';
525
+ } else {
526
+ $farray['unique_filename_callback'] = array($this, 'unique_filename_callback');
527
+ }
528
+
529
+ $status = wp_handle_upload(
530
+ $_FILES['async-upload'],
531
+ $farray
532
+ );
533
+ remove_filter('upload_dir', array($this, 'upload_dir'));
534
+ remove_filter('sanitize_file_name', array($this, 'sanitize_file_name'));
535
+
536
+ if (isset($status['error'])) {
537
+ echo 'ERROR:'.$status['error'];
538
+ exit;
539
+ }
540
+
541
+ // If this was the chunk, then we should instead be concatenating onto the final file
542
+ if (isset($_POST['chunks']) && isset($_POST['chunk']) && preg_match('/^[0-9]+$/',$_POST['chunk'])) {
543
+ $final_file = $_POST['name'];
544
+ rename($status['file'], $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp');
545
+ $status['file'] = $updraft_dir.'/'.$final_file.'.'.$_POST['chunk'].'.zip.tmp';
546
+
547
+ // Final chunk? If so, then stich it all back together
548
+ if ($_POST['chunk'] == $_POST['chunks']-1) {
549
+ if ($wh = fopen($updraft_dir.'/'.$final_file, 'wb')) {
550
+ for ($i=0 ; $i<$_POST['chunks']; $i++) {
551
+ $rf = $updraft_dir.'/'.$final_file.'.'.$i.'.zip.tmp';
552
+ if ($rh = fopen($rf, 'rb')) {
553
+ while ($line = fread($rh, 32768)) fwrite($wh, $line);
554
+ fclose($rh);
555
+ @unlink($rf);
556
+ }
557
+ }
558
+ fclose($wh);
559
+ $status['file'] = $updraft_dir.'/'.$final_file;
560
+ }
561
+ }
562
+
563
+ }
564
+
565
+ if (!isset($_POST['chunks']) || (isset($_POST['chunk']) && $_POST['chunk'] == $_POST['chunks']-1)) {
566
+ $file = basename($status['file']);
567
+ if (!preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(gz\.crypt)$/i', $file)) {
568
+
569
+ @unlink($status['file']);
570
+ echo 'ERROR:'.__('Bad filename format - this does not look like an encrypted database file created by UpdraftPlus','updraftplus');
571
+
572
+ exit;
573
+ }
574
+ }
575
+
576
+ // send the uploaded file url in response
577
+ // echo 'OK:'.$status['url'];
578
+ echo 'OK:'.$file;
579
+ exit;
580
+ }
581
+
582
+
583
+ function settings_output() {
584
+
585
+ global $updraftplus;
586
+
587
+ wp_enqueue_style('jquery-ui', UPDRAFTPLUS_URL.'/includes/jquery-ui-1.8.22.custom.css');
588
+
589
+ /*
590
+ we use request here because the initial restore is triggered by a POSTed form. we then may need to obtain credentials
591
+ for the WP_Filesystem. to do this WP outputs a form that we can't insert variables into (apparently). So the values are
592
+ passed back in as GET parameters. REQUEST covers both GET and POST so this weird logic works.
593
+ */
594
+ if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_restore' && isset($_REQUEST['backup_timestamp'])) {
595
+ $backup_success = $this->restore_backup($_REQUEST['backup_timestamp']);
596
+ if(empty($updraftplus->errors) && $backup_success == true) {
597
+ echo '<p><strong>'.__('Restore successful!','updraftplus').'</strong></p>';
598
+ echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus&updraft_restore_success=true">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
599
+ return;
600
+ } else {
601
+ echo '<p>Restore failed...</p><ul style="list-style: disc inside;">';
602
+ foreach ($updraftplus->errors as $err) {
603
+ if (is_wp_error($err)) {
604
+ foreach ($err->get_error_messages() as $msg) {
605
+ echo '<li>'.htmlspecialchars($msg).'<li>';
606
+ }
607
+ } elseif (is_string($err)) {
608
+ echo "<li>".htmlspecialchars($err)."</li>";
609
+ } else {
610
+ print "<li>".print_r($err,true)."</li>";
611
+ }
612
+ }
613
+ echo '</ul><b>Actions:</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
614
+ return;
615
+ }
616
+ //uncomment the below once i figure out how i want the flow of a restoration to work.
617
+ //echo '<b>'__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">Return to UpdraftPlus Configuration</a>';
618
+ }
619
+ $deleted_old_dirs = false;
620
+ if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_delete_old_dirs') {
621
+
622
+ echo '<h1>UpdraftPlus - '.__('Remove old directories','updraftplus').'</h1>';
623
+
624
+ $nonce = (empty($_REQUEST['_wpnonce'])) ? "" : $_REQUEST['_wpnonce'];
625
+ if (!wp_verify_nonce($nonce, 'updraft_delete_old_dirs')) die('Security check');
626
+
627
+ if($this->delete_old_dirs()) {
628
+ echo '<p>'.__('Old directories successfully removed.','updraftplus').'</p><br/>';
629
+ $deleted_old_dirs = true;
630
+ } else {
631
+ echo '<p>',__('Old directory removal failed for some reason. You may want to do this manually.','updraftplus').'</p><br/>';
632
+ }
633
+ echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
634
+ return;
635
+ }
636
+
637
+ if(isset($_GET['error'])) $this->show_admin_warning(htmlspecialchars($_GET['error']), 'error');
638
+ if(isset($_GET['message'])) $this->show_admin_warning(htmlspecialchars($_GET['message']));
639
+
640
+ if(isset($_GET['action']) && $_GET['action'] == 'updraft_create_backup_dir') {
641
+ if(!$this->create_backup_dir()) {
642
+ echo '<p>'.__('Backup directory could not be created','updraftplus').'...</p><br/>';
643
+ }
644
+ echo '<p>'.__('Backup directory successfully created.','updraftplus').'</p><br/>';
645
+ echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
646
+ return;
647
+ }
648
+
649
+ if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup') {
650
+ // For unknown reasons, the <script> runs twice if put inside the <div>
651
+ echo '<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;"><strong>',__('Schedule backup','updraftplus').':</strong> ';
652
+ if (wp_schedule_single_event(time()+5, 'updraft_backup_all') === false) {
653
+ $updraftplus->log("A backup run failed to schedule");
654
+ echo __("Failed.",'updraftplus')."</div>";
655
+ } else {
656
+ echo htmlspecialchars(__('OK. Now load any page from your site to make sure the schedule can trigger. You should then see activity in the "Last log message" field below.','updraftplus'))." <a href=\"http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/\">".__('Nothing happening? Follow this link for help.','updraftplus')."</a></div><script>setTimeout(function(){updraft_showlastbackup();}, 7000);</script>";
657
+ $updraftplus->log("A backup run has been scheduled");
658
+ }
659
+ }
660
+
661
+ // updraft_file_ids is not deleted
662
+ if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_all') { $updraftplus->boot_backup(true,true); }
663
+ elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_db') { $updraftplus->backup_db(); }
664
+ elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_wipesettings') {
665
+ $settings = array('updraft_interval', 'updraft_interval_database', 'updraft_retain', 'updraft_retain_db', 'updraft_encryptionphrase', 'updraft_service', 'updraft_dropbox_appkey', 'updraft_dropbox_secret', 'updraft_googledrive_clientid', 'updraft_googledrive_secret', 'updraft_googledrive_remotepath', 'updraft_ftp_login', 'updraft_ftp_pass', 'updraft_ftp_remote_path', 'updraft_server_address', 'updraft_dir', 'updraft_email', 'updraft_delete_local', 'updraft_debug_mode', 'updraft_include_plugins', 'updraft_include_themes', 'updraft_include_uploads', 'updraft_include_others', 'updraft_include_blogs', 'updraft_include_mu-plugins', 'updraft_include_others_exclude', 'updraft_lastmessage', 'updraft_googledrive_clientid', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder', 'updraft_last_backup', 'updraft_starttime_files', 'updraft_starttime_db', 'updraft_sftp_settings', 'updraft_disable_ping');
666
+ foreach ($settings as $s) {
667
+ UpdraftPlus_Options::delete_updraft_option($s);
668
+ }
669
+ $this->show_admin_warning(__("Your settings have been wiped.",'updraftplus'));
670
+ }
671
+
672
+ ?>
673
+ <div class="wrap">
674
+ <h1><?php echo $updraftplus->plugin_title; ?></h1>
675
+
676
+ <?php _e('By UpdraftPlus.Com','updraftplus')?> ( <a href="http://updraftplus.com">UpdraftPlus.Com</a> | <a href="http://david.dw-perspective.org.uk"><?php _e("Lead developer's homepage",'updraftplus');?></a> | <?php if (!defined('UPDRAFTPLUS_NOADS')) { ?><a href="http://wordshell.net">WordShell - WordPress command line</a> | <a href="http://david.dw-perspective.org.uk/donate"><?php _e('Donate','updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/frequently-asked-questions/">FAQs</a> | <a href="http://profiles.wordpress.org/davidanderson/"><?php _e('Other WordPress plugins','updraftplus');?></a>). <?php _e('Version','updraftplus');?>: <?php echo $updraftplus->version; ?>
677
+ <br>
678
+ <?php
679
+ if(isset($_GET['updraft_restore_success'])) {
680
+ // If we restored the database, then that will have out-of-date information which may confuse the user - so automatically re-scan for them.
681
+ $this->rebuild_backup_history();
682
+ echo "<div class=\"updated fade\" style=\"padding:8px;\"><strong>".__('Your backup has been restored.','updraftplus').'</strong> '.__('Your old (themes, uploads, plugins, whatever) directories have been retained with "-old" appended to their name. Remove them when you are satisfied that the backup worked properly.')."</div>";
683
+ }
684
+
685
+ $ws_advert = $updraftplus->wordshell_random_advert(1);
686
+ if ($ws_advert) { echo '<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;">'.$ws_advert.'</div>'; }
687
+
688
+ if($deleted_old_dirs) echo '<div style="color:blue" class=\"updated fade\">'.__('Old directories successfully deleted.','updraftplus').'</div>';
689
+
690
+ if(!$updraftplus->memory_check(96)) {?>
691
+ <div style="color:orange"><?php _e("Your PHP memory limit is quite low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may not work properly with a memory limit of less than 96 Mb (though on the other hand, it has been used successfully with a 32Mb limit - your experience may vary, but don't blame us!).",'updraftplus');?> <?php _e('Current limit is:','updraftplus');?> <?php echo $this->memory_check_current(); ?> Mb</div>
692
+ <?php
693
+ }
694
+ if(1==0 && !$this->execution_time_check(60)) {?>
695
+ <div style="color:orange"><?php _e("Your PHP max_execution_time is less than 60 seconds. This possibly means you're running in safe_mode. Either disable safe_mode or modify your php.ini to set max_execution_time to a higher number. If you do not, then longer will be needed to complete a backup (but that is all). Present limit is:",'updraftplus');?> <?php echo ini_get('max_execution_time').' '.__('seconds','updraftplus')?>.</div>
696
+ <?php
697
+ }
698
+
699
+ if($this->scan_old_dirs()) {?>
700
+ <div class="updated fade" style="padding:8px;"><?php _e('You have old directories from a previous backup (technical information: these are found in wp-content, and suffixed with -old). Use this button to delete them (if you have verified that the restoration worked).','updraftplus');?>
701
+ <form method="post" action="<?php echo remove_query_arg(array('updraft_restore_success','action')) ?>">
702
+ <?php wp_nonce_field('updraft_delete_old_dirs'); ?>
703
+ <input type="hidden" name="action" value="updraft_delete_old_dirs" />
704
+ <input type="submit" class="button-primary" value="<?php _e('Delete Old Directories','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('Are you sure you want to delete the old directories? This cannot be undone.','updraftplus'));?>'))" />
705
+ </form>
706
+ </div>
707
+ <?php
708
+ }
709
+ if(!empty($updraftplus->errors)) {
710
+ foreach($updraftplus->errors as $error) {
711
+ // ignoring severity
712
+ echo '<div style="color:red">'.$error['error'].'</div>';
713
+ }
714
+ }
715
+ ?>
716
+
717
+ <h2 style="clear:left;"><?php _e('Existing Schedule And Backups','updraftplus');?></h2>
718
+ <table class="form-table" style="float:left; clear: both; width:545px;">
719
+ <noscript>
720
+ <tr>
721
+ <th><?php _e(' avaScript warning','updraftplus');?>:</th>
722
+ <td style="color:red"><?php _e('This admin interface uses JavaScript heavily. You either need to activate it within your browser, or to use a JavaScript-capable browser.','updraftplus');?></td>
723
+ </tr>
724
+ </noscript>
725
+ <?php
726
+ $updraft_dir = $updraftplus->backups_dir_location();
727
+ // UNIX timestamp
728
+ $next_scheduled_backup = wp_next_scheduled('updraft_backup');
729
+ if ($next_scheduled_backup) {
730
+ // Convert to GMT
731
+ $next_scheduled_backup_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup);
732
+ // Convert to blog time zone
733
+ $next_scheduled_backup = get_date_from_gmt($next_scheduled_backup_gmt, 'D, F j, Y H:i T');
734
+ } else {
735
+ $next_scheduled_backup = __('Nothing currently scheduled','updraftplus');
736
+ }
737
+
738
+ $next_scheduled_backup_database = wp_next_scheduled('updraft_backup_database');
739
+ if (UpdraftPlus_Options::get_updraft_option('updraft_interval_database',UpdraftPlus_Options::get_updraft_option('updraft_interval')) == UpdraftPlus_Options::get_updraft_option('updraft_interval')) {
740
+ $next_scheduled_backup_database = ('Nothing currently scheduled' == $next_scheduled_backup) ? $next_scheduled_backup : __("At the same time as the files backup", 'updraftplus');
741
+ } else {
742
+ if ($next_scheduled_backup_database) {
743
+ // Convert to GMT
744
+ $next_scheduled_backup_database_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup_database);
745
+ // Convert to blog time zone
746
+ $next_scheduled_backup_database = get_date_from_gmt($next_scheduled_backup_database_gmt, 'D, F j, Y H:i T');
747
+ } else {
748
+ $next_scheduled_backup_database = __('Nothing currently scheduled','updraftplus');
749
+ }
750
+ }
751
+ $current_time = get_date_from_gmt(gmdate('Y-m-d H:i:s'), 'D, F j, Y H:i T');
752
+
753
+ $backup_disabled = (is_writable($updraft_dir)) ? '' : 'disabled="disabled"';
754
+
755
+ $last_backup_html = $this->last_backup_html();
756
+
757
+ ?>
758
+
759
+ <tr>
760
+ <th><?php _e('Next scheduled backups','updraftplus');?>:</th>
761
+ <td>
762
+ <div style="width: 76px; float:left;"><?php _e('Files','updraftplus'); ?>:</div><div style="color:blue; float:left;"><?php echo $next_scheduled_backup?></div>
763
+ <div style="width: 76px; clear: left; float:left;"><?php _e('Database','updraftplus');?>: </div><div style="color:blue; float:left;"><?php echo $next_scheduled_backup_database?></div>
764
+ <div style="width: 76px; clear: left; float:left;"><?php _e('Time now','updraftplus');?>: </div><div style="color:blue; float:left;"><?php echo $current_time?></div>
765
+ </td>
766
+ </tr>
767
+ <tr>
768
+ <th><?php _e('Last finished backup run','updraftplus');?>:</th>
769
+ <td id="updraft_last_backup"><?php echo $last_backup_html ?></td>
770
+ </tr>
771
+ </table>
772
+ <div style="float:left; width:200px; padding-top: 20px;">
773
+ <p><button type="button" <?php echo $backup_disabled ?> class="button-primary" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px;" onclick="jQuery('#updraft-backupnow-modal').dialog('open');"><?php _e('Backup Now','updraftplus');?></button></p>
774
+ <div style="position:relative">
775
+ <div style="position:absolute;top:0;left:0">
776
+ <?php
777
+ $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
778
+ $backup_history = (is_array($backup_history))?$backup_history:array();
779
+ $restore_disabled = (count($backup_history) == 0) ? 'disabled="disabled"' : "";
780
+ ?>
781
+ <input type="button" class="button-primary" <?php echo $restore_disabled ?> value="<?php _e('Restore','updraftplus');?>" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px;" onclick="jQuery('.download-backups').slideDown(); updraft_historytimertoggle(1); jQuery('html,body').animate({scrollTop: jQuery('#updraft_lastlogcontainer').offset().top},'slow');">
782
+ </div>
783
+ </div>
784
+ </div>
785
+ <br style="clear:both" />
786
+ <table class="form-table">
787
+ <tr>
788
+ <th><?php _e('Last log message','updraftplus');?>:</th>
789
+ <td id="updraft_lastlogcontainer"><?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', __('(Nothing yet logged)','updraftplus')) ); ?></td>
790
+ </tr>
791
+ <tr>
792
+ <th><?php echo htmlspecialchars(__('Backups, logs & restoring','updraftplus')); ?>:</th>
793
+ <td><a id="updraft_showbackups" href="#" title="<?php _e('Press to see available backups','updraftplus');?>" onclick="jQuery('.download-backups').toggle(); updraft_historytimertoggle(0);"><?php echo sprintf(__('%d set(s) available', 'updraftplus'), count($backup_history)); ?> available</a></td>
794
+ </tr>
795
+ <tr>
796
+ <td></td><td class="download-backups" style="display:none; border: 1px dotted;">
797
+ <p style="max-width: 740px;"><ul style="list-style: disc inside;">
798
+ <li><strong><?php _e('Downloading','updraftplus');?>:</strong> <?php _e("Pressing a button for Database/Plugins/Themes/Uploads/Others will make UpdraftPlus try to bring the backup file back from the remote storage (if any - e.g. Amazon S3, Dropbox, Google Drive, FTP) to your webserver. Then you will be allowed to download it to your computer. If the fetch from the remote storage stops progressing (wait 30 seconds to make sure), then press again to resume. Remember that you can also visit the cloud storage vendor's website directly.",'updraftplus');?></li>
799
+ <li><strong><?php _e('Restoring','updraftplus');?>:</strong> <?php _e("Press the button for the backup you wish to restore. If your site is large and you are using remote storage, then you should first click on each entity in order to retrieve it back to the webserver. This will prevent time-outs from occuring during the restore process itself.",'updraftplus');?> <?php _e('More tasks:','updraftplus');?> <a href="#" onclick="jQuery('#updraft-plupload-modal').slideToggle(); return false;"><?php _e('upload backup files','updraftplus');?></a> | <a href="#" onclick="updraft_updatehistory(1); return false;" title="<?php _e('Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below.','updraftplus'); ?>"><?php _e('rescan folder for new backup sets','updraftplus');?></a></li>
800
+ <li><strong><?php _e('Opera web browser','updraftplus');?>:</strong> <?php _e('If you are using this, then turn Turbo/Road mode off.','updraftplus');?></li>
801
+ <li title="<?php _e('This is a count of the contents of your Updraft directory','updraftplus');?>"><strong><?php _e('Web-server disk space in use by UpdraftPlus','updraftplus');?>:</strong> <span id="updraft_diskspaceused"><em>(calculating...)</em></span> <a href="#" onclick="updraftplus_diskspace(); return false;"><?php _e('refresh','updraftplus');?></a></li></ul>
802
+
803
+ <div id="updraft-plupload-modal" title="<?php _e('UpdraftPlus - Upload backup files','updraftplus'); ?>" style="width: 75%; margin: 16px; display:none; margin-left: 100px;">
804
+ <p><em><?php _e("Upload files into UpdraftPlus. Use this to import backups made on a different WordPress installation." ,'updraftplus');?></em></p>
805
+ <div id="plupload-upload-ui" style="width: 70%;">
806
+ <div id="drag-drop-area">
807
+ <div class="drag-drop-inside">
808
+ <p class="drag-drop-info"><?php _e('Drop backup zips here'); ?></p>
809
+ <p><?php _ex('or', 'Uploader: Drop zip files here - or - Select Files'); ?></p>
810
+ <p class="drag-drop-buttons"><input id="plupload-browse-button" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
811
+ </div>
812
+ </div>
813
+ <div id="filelist">
814
+ </div>
815
+ </div>
816
+
817
+ </div>
818
+
819
+ <div id="ud_downloadstatus"></div>
820
+ <script>
821
+ function updraftplus_diskspace() {
822
+ jQuery('#updraft_diskspaceused').html('<em><?php _e('calculating...','updraftplus');?></em>');
823
+ jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'diskspaceused', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>' }, function(response) {
824
+ jQuery('#updraft_diskspaceused').html(response);
825
+ });
826
+ }
827
+ var lastlog_lastmessage = "";
828
+ function updraftplus_deletefromserver(timestamp, type) {
829
+ var pdata = {
830
+ action: 'updraft_download_backup',
831
+ stage: 'delete',
832
+ timestamp: timestamp,
833
+ type: type,
834
+ _wpnonce: '<?php echo wp_create_nonce("updraftplus_download"); ?>'
835
+ };
836
+ jQuery.post(ajaxurl, pdata, function(response) {
837
+ if (response == 'deleted') {
838
+
839
+ } else {
840
+ alert('We requested to delete the file, but could not understand the server\'s response '+response);
841
+ }
842
+ });
843
+ }
844
+ function updraftplus_downloadstage2(timestamp, type) {
845
+ location.href=ajaxurl+'?_wpnonce=<?php echo wp_create_nonce("updraftplus_download"); ?>&timestamp='+timestamp+'&type='+type+'&stage=2&action=updraft_download_backup';
846
+ }
847
+ function updraft_downloader(base, nonce, what) {
848
+ // Create somewhere for the status to be found
849
+ var stid = base+nonce+'_'+what;
850
+ if (!jQuery('#'+stid).length) {
851
+ jQuery('#ud_downloadstatus').append('<div style="clear:left; border: 1px solid; padding: 8px; margin-top: 4px; max-width:840px;" id="'+stid+'"><button onclick="jQuery(\'#'+stid+'\').fadeOut().remove();" type="button" style="float:right; margin-bottom: 8px;">X</button><strong>Download '+what+' ('+nonce+')</strong>:<div class="raw">Begun looking for this entity</div><div class="file" id="'+stid+'_st"><div class="dlfileprogress" style="width: 0;"></div></div>');
852
+ // <b><span class="dlname">??</span></b> (<span class="dlsofar">?? KB</span>/<span class="dlsize">??</span> KB)
853
+ setTimeout(function(){updraft_downloader_status(base, nonce, what)}, 200);
854
+ }
855
+ // Now send the actual request to kick it all off
856
+ jQuery.post(ajaxurl, jQuery('#uddownloadform_'+what+'_'+nonce).serialize());
857
+ // We don't want the form to submit as that replaces the document
858
+ return false;
859
+ }
860
+ var dlstatus_sdata = {
861
+ action: 'updraft_ajax',
862
+ subaction: 'downloadstatus',
863
+ nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
864
+ };
865
+ dlstatus_lastlog = '';
866
+ function updraft_downloader_status(base, nonce, what) {
867
+ // Get the DOM id of the status div (add _st for the id of the file itself)
868
+ var stid = base+nonce+'_'+what;
869
+ if (jQuery('#'+stid).length) {
870
+ dlstatus_sdata.timestamp = nonce;
871
+ dlstatus_sdata.type = what;
872
+ jQuery.get(ajaxurl, dlstatus_sdata, function(response) {
873
+ nexttimer = 1250;
874
+ if (dlstatus_lastlog == response) { nexttimer = 3000; }
875
+ try {
876
+ var resp = jQuery.parseJSON(response);
877
+ if (resp.e != null) {
878
+ jQuery('#'+stid+' .raw').html('<strong><?php _e('Error:','updraftplus'); ?></strong> '+resp.e);
879
+ console.log(resp);
880
+ } else if (resp.p != null) {
881
+ setTimeout(function(){updraft_downloader_status(base, nonce, what)}, nexttimer);
882
+ jQuery('#'+stid+'_st .dlfileprogress').width(resp.p+'%');
883
+ //jQuery('#'+stid+'_st .dlsofar').html(Math.round(resp.s/1024));
884
+ //jQuery('#'+stid+'_st .dlsize').html(Math.round(resp.t/1024));
885
+ if (resp.m != null) {
886
+ if (resp.p < 100 || base != 'uddlstatus_') {
887
+ jQuery('#'+stid+' .raw').html(resp.m);
888
+ } else {
889
+ jQuery('#'+stid+' .raw').html('<?php _e('File ready.','updraftplus'); ?> <?php _e('You should:','updraftplus'); ?> <button type="button" onclick="updraftplus_downloadstage2(\''+nonce+'\', \''+what+'\')\">Download to your computer</button> and then, if you wish, <button id="uddownloaddelete_'+nonce+'_'+what+'" type="button" onclick="updraftplus_deletefromserver(\''+nonce+'\', \''+what+'\')\">Delete from your web server</button>');
890
+ }
891
+ }
892
+ dlstatus_lastlog = response;
893
+ } else if (resp.m != null) {
894
+ jQuery('#'+stid+' .raw').html(resp.m);
895
+ } else {
896
+ alert('<?php _e('Download error: the server sent us a response (JSON) which we did not understand', 'updraftplus'); ?> ('+response+')');
897
+ }
898
+ } catch(err) {
899
+ alert('<?php _e('Download error: the server sent us a response which we did not understand.', 'updraftplus'); ?> <?php _e("Error:",'updraftplus');?> '+err);
900
+ }
901
+ });
902
+ }
903
+ }
904
+ </script>
905
+ <div id="updraft_existing_backups" style="margin-bottom:12px;">
906
+ <?php
907
+ print $this->existing_backup_table($backup_history);
908
+ ?>
909
+ </div>
910
+ </td>
911
+ </tr>
912
+ </table>
913
+
914
+ <div id="updraft-restore-modal" title="UpdraftPlus - <?php _e('Restore backup','updraftplus');?>">
915
+ <p><strong><?php _e('Restore backup from','updraftplus');?>:</strong> <span id="updraft_restore_date"></span></p>
916
+ <p><?php _e("Restoring will replace this site's themes, plugins, uploads, database and/or other content directories (according to what is contained in the backup set, and your selection",'updraftplus');?>). <?php _e('Choose the components to restore','updraftplus');?>:</p>
917
+ <form id="updraft_restore_form" method="post">
918
+ <fieldset>
919
+ <input type="hidden" name="action" value="updraft_restore">
920
+ <input type="hidden" name="backup_timestamp" value="0" id="updraft_restore_timestamp">
921
+ <?php
922
+
923
+ # The 'off' check is for badly configured setups - http://wordpress.org/support/topic/plugin-wp-super-cache-warning-php-safe-mode-enabled-but-safe-mode-is-off
924
+ if(@ini_get('safe_mode') && strtolower(@ini_get('safe_mode')) != "off") {
925
+ echo "<p><em>".__('Your web server has PHP\'s so-called safe_mode active.','updraftplus').' '.__('This makes time-outs much more likely. You are recommended to turn safe_mode off, or to restore only one entity at a time, <a href="http://updraftplus.com/faqs/i-want-to-restore-but-have-either-cannot-or-have-failed-to-do-so-from-the-wp-admin-console/">or to restore manually</a>.', 'updraftplus')."</em></p><br/>";
926
+ }
927
+
928
+ $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
929
+ foreach ($backupable_entities as $type => $info) {
930
+ echo '<div><input id="updraft_restore_'.$type.'" type="checkbox" name="updraft_restore[]" value="'.$type.'"> <label for="updraft_restore_'.$type.'">'.$info['description'].'</label><br></div>';
931
+ }
932
+ ?>
933
+ <div><input id="updraft_restore_db" type="checkbox" name="updraft_restore[]" value="db"> <label for="updraft_restore_db"><?php _e('Database','updraftplus'); ?></label><br></div>
934
+ </fieldset>
935
+ </form>
936
+ </div>
937
+
938
+ <div id="updraft-backupnow-modal" title="UpdraftPlus - <?php _e('Perform a backup now','updraftplus'); ?>">
939
+ <p><?php _e("This will schedule a one-time backup. To proceed, press 'Backup Now', then wait 10 seconds, then visit any page on your site. WordPress should then start the backup running in the background.",'updraftplus');?></p>
940
+
941
+ <form id="updraft-backupnow-form" method="post" action="">
942
+ <input type="hidden" name="action" value="updraft_backup" />
943
+ </form>
944
+
945
+ <p><?php _e('Does nothing happen when you schedule backups?','updraftplus');?> <a href="http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/"><?php _e('Go here for help.','updraft');?></a></p>
946
+ </div>
947
+
948
+ <?php
949
+ if (is_multisite() && !file_exists(UPDRAFTPLUS_DIR.'/addons/multisite.php')) {
950
+ ?>
951
+ <h2>UpdraftPlus <?php _e('Multisite','updraftplus');?></h2>
952
+ <table>
953
+ <tr>
954
+ <td>
955
+ <p style="max-width:800px;"><?php echo __('Do you need WordPress Multisite support?','updraftplus').' <a href="http://updraftplus.com/">'. __('Please check out UpdraftPlus Premium, or the stand-alone Multisite add-on.','updraftplus');?></a>.</p>
956
+ </td>
957
+ </tr>
958
+ </table>
959
+ <?php } ?>
960
+ <h2><?php _e('Configure Backup Contents And Schedule','updraftplus');?></h2>
961
+ <?php UpdraftPlus_Options::options_form_begin(); ?>
962
+ <?php $this->settings_formcontents($last_backup_html); ?>
963
+ </form>
964
+ <div style="padding-top: 40px; display:none;" class="expertmode">
965
+ <hr>
966
+ <h3><?php _e('Debug Information And Expert Options','updraftplus');?></h3>
967
+ <p>
968
+ <?php
969
+ $peak_memory_usage = memory_get_peak_usage(true)/1024/1024;
970
+ $memory_usage = memory_get_usage(true)/1024/1024;
971
+ echo __('Peak memory usage','updraftplus').': '.$peak_memory_usage.' MB<br/>';
972
+ echo __('Current memory usage','updraftplus').': '.$memory_usage.' MB<br/>';
973
+ echo __('PHP memory limit','updraftplus').': '.ini_get('memory_limit').' <br/>';
974
+ ?>
975
+ </p>
976
+ <p style="max-width: 600px;"><?php _e('The buttons below will immediately execute a backup run, independently of WordPress\'s scheduler. If these work whilst your scheduled backups and the "Backup Now" button do absolutely nothing (i.e. not even produce a log file), then it means that your scheduler is broken. You should then disable all your other plugins, and try the "Backup Now" button. If that fails, then contact your web hosting company and ask them if they have disabled wp-cron. If it succeeds, then re-activate your other plugins one-by-one, and find the one that is the problem and report a bug to them.','updraftplus');?></p>
977
+
978
+ <form method="post">
979
+ <input type="hidden" name="action" value="updraft_backup_debug_all" />
980
+ <p><input type="submit" class="button-primary" <?php echo $backup_disabled ?> value="<?php _e('Debug Full Backup','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will cause an immediate backup. The page will stall loading until it finishes (ie, unscheduled).','updraftplus'));?>'))" /></p>
981
+ </form>
982
+ <form method="post">
983
+ <input type="hidden" name="action" value="updraft_backup_debug_db" />
984
+ <p><input type="submit" class="button-primary" <?php echo $backup_disabled ?> value="<?php _e('Debug Database Backup','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will cause an immediate DB backup. The page will stall loading until it finishes (ie, unscheduled). The backup may well run out of time; really this button is only helpful for checking that the backup is able to get through the initial stages, or for small WordPress sites..','updraftplus'));?>'))" /></p>
985
+ </form>
986
+ <h3><?php _e('Wipe Settings','updraftplus');?></h3>
987
+ <p style="max-width: 600px;"><?php _e('This button will delete all UpdraftPlus settings (but not any of your existing backups from your cloud storage). You will then need to enter all your settings again. You can also do this before deactivating/deinstalling UpdraftPlus if you wish.','updraftplus');?></p>
988
+ <form method="post">
989
+ <input type="hidden" name="action" value="updraft_wipesettings" />
990
+ <p><input type="submit" class="button-primary" value="<?php _e('Wipe All Settings','updraftplus'); ?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will delete all your UpdraftPlus settings - are you sure you want to do this?'));?>'))" /></p>
991
+ </form>
992
+ </div>
993
+
994
+ <script type="text/javascript">
995
+ /* <![CDATA[ */
996
+ jQuery(document).ready(function() {
997
+ jQuery('#updraft-service').change(function() {
998
+ jQuery('.updraftplusmethod').hide();
999
+ var active_class = jQuery(this).val();
1000
+ jQuery('.'+active_class).show();
1001
+ });
1002
+ })
1003
+ jQuery(window).load(function() {
1004
+ //this is for hiding the restore progress at the top after it is done
1005
+ setTimeout('jQuery("#updraft-restore-progress").toggle(1000)',3000)
1006
+ jQuery('#updraft-restore-progress-toggle').click(function() {
1007
+ jQuery('#updraft-restore-progress').toggle(500)
1008
+ })
1009
+ })
1010
+ /* ]]> */
1011
+ </script>
1012
+ <?php
1013
+ }
1014
+
1015
+ //deletes the -old directories that are created when a backup is restored.
1016
+ function delete_old_dirs() {
1017
+ global $wp_filesystem;
1018
+ $credentials = request_filesystem_credentials(wp_nonce_url("options-general.php?page=updraftplus&action=updraft_delete_old_dirs", 'updraft_delete_old_dirs'));
1019
+ WP_Filesystem($credentials);
1020
+ if ( $wp_filesystem->errors->get_error_code() ) {
1021
+ foreach ( $wp_filesystem->errors->get_error_messages() as $message )
1022
+ show_message($message);
1023
+ exit;
1024
+ }
1025
+
1026
+ $list = $wp_filesystem->dirlist(WP_CONTENT_DIR);
1027
+
1028
+ $return_code = true;
1029
+
1030
+ foreach ($list as $item) {
1031
+ if (substr($item['name'], -4, 4) == "-old") {
1032
+ //recursively delete
1033
+ print "<strong>".__('Delete','updraftplus').": </strong>".htmlspecialchars($item['name']).": ";
1034
+ if(!$wp_filesystem->delete(WP_CONTENT_DIR.'/'.$item['name'], true)) {
1035
+ $return_code = false;
1036
+ print "<strong>Failed</strong><br>";
1037
+ } else {
1038
+ print "<strong>OK</strong><br>";
1039
+ }
1040
+ }
1041
+ }
1042
+
1043
+ return $return_code;
1044
+ }
1045
+
1046
+ function create_backup_dir() {
1047
+ global $wp_filesystem, $updraftplus;
1048
+ $credentials = request_filesystem_credentials("options-general.php?page=updraftplus&action=updraft_create_backup_dir");
1049
+ WP_Filesystem($credentials);
1050
+ if ( $wp_filesystem->errors->get_error_code() ) {
1051
+ foreach ( $wp_filesystem->errors->get_error_messages() as $message ) show_message($message);
1052
+ exit;
1053
+ }
1054
+
1055
+ $updraft_dir = $updraftplus->backups_dir_location();
1056
+ $default_backup_dir = WP_CONTENT_DIR.'/updraft';
1057
+ $updraft_dir = ($updraft_dir)?$updraft_dir:$default_backup_dir;
1058
+
1059
+ if (!$wp_filesystem->mkdir($updraft_dir, 0775)) return false;
1060
+
1061
+ return true;
1062
+ }
1063
+
1064
+ function execution_time_check($time) {
1065
+ $setting = ini_get('max_execution_time');
1066
+ return ( $setting==0 || $setting >= $time) ? true : false;
1067
+ }
1068
+
1069
+ //scans the content dir to see if any -old dirs are present
1070
+ function scan_old_dirs() {
1071
+ $dirArr = scandir(WP_CONTENT_DIR);
1072
+ foreach($dirArr as $dir) {
1073
+ if(strpos($dir,'-old') !== false) return true;
1074
+ }
1075
+ return false;
1076
+ }
1077
+
1078
+ function last_backup_html() {
1079
+
1080
+ global $updraftplus;
1081
+
1082
+ $updraft_last_backup = UpdraftPlus_Options::get_updraft_option('updraft_last_backup');
1083
+
1084
+ $updraft_dir = $updraftplus->backups_dir_location();
1085
+
1086
+ if($updraft_last_backup) {
1087
+
1088
+ if ($updraft_last_backup['success']) {
1089
+ // Convert to GMT, then to blog time
1090
+ $last_backup_text = get_date_from_gmt(gmdate('Y-m-d H:i:s', $updraft_last_backup['backup_time']), 'D, F j, Y H:i T');
1091
+ } else {
1092
+ $last_backup_text = implode("<br>",$updraft_last_backup['errors']);
1093
+ }
1094
+
1095
+ if (!empty($updraft_last_backup['backup_nonce'])) {
1096
+ $potential_log_file = $updraft_dir."/log.".$updraft_last_backup['backup_nonce'].".txt";
1097
+ if (is_readable($potential_log_file)) $last_backup_text .= "<br><a href=\"?page=updraftplus&action=downloadlog&updraftplus_backup_nonce=".$updraft_last_backup['backup_nonce']."\">".__('Download log file','updraftplus')."</a>";
1098
+ }
1099
+
1100
+ $last_backup_color = ($updraft_last_backup['success']) ? 'green' : 'red';
1101
+
1102
+ } else {
1103
+ $last_backup_text = __('No backup has been completed.','updraftplus');
1104
+ $last_backup_color = 'blue';
1105
+ }
1106
+
1107
+ return "<span style=\"color:${last_backup_color}\">${last_backup_text}</span>";
1108
+
1109
+ }
1110
+
1111
+ function settings_formcontents($last_backup_html) {
1112
+
1113
+ global $updraftplus;
1114
+
1115
+ $updraft_dir = $updraftplus->backups_dir_location();
1116
+
1117
+ ?>
1118
+ <table class="form-table" style="width:900px;">
1119
+ <tr>
1120
+ <th><?php _e('File backup intervals','updraftplus'); ?>:</th>
1121
+ <td><select id="updraft_interval" name="updraft_interval" onchange="updraft_check_same_times();">
1122
+ <?php
1123
+ $intervals = array ("manual" => _x("Manual",'i.e. Non-automatic','updraftplus'), 'every4hours' => __("Every 4 hours",'updraftplus'), 'every8hours' => __("Every 8 hours",'updraftplus'), 'twicedaily' => __("Every 12 hours",'updraftplus'), 'daily' => __("Daily",'updraftplus'), 'weekly' => __("Weekly",'updraftplus'), 'fortnightly' => __("Fortnightly",'updraftplus'), 'monthly' => __("Monthly",'updraftplus'));
1124
+ foreach ($intervals as $cronsched => $descrip) {
1125
+ echo "<option value=\"$cronsched\" ";
1126
+ if ($cronsched == UpdraftPlus_Options::get_updraft_option('updraft_interval','manual')) echo 'selected="selected"';
1127
+ echo ">$descrip</option>\n";
1128
+ }
1129
+ ?>
1130
+ </select> <?php echo apply_filters('updraftplus_schedule_showfileconfig', '<input type="hidden" name="updraftplus_starttime_files" value="">'); ?>
1131
+ <?php
1132
+ echo __('and retain this many backups', 'updraftplus').': ';
1133
+ $updraft_retain = UpdraftPlus_Options::get_updraft_option('updraft_retain', 1);
1134
+ $updraft_retain = ((int)$updraft_retain > 0) ? (int)$updraft_retain : 1;
1135
+ ?> <input type="text" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:40px;" />
1136
+ </td>
1137
+ </tr>
1138
+ <tr>
1139
+ <th><?php _e('Database backup intervals','updraftplus'); ?>:</th>
1140
+ <td><select id="updraft_interval_database" name="updraft_interval_database" onchange="updraft_check_same_times();">
1141
+ <?php
1142
+ foreach ($intervals as $cronsched => $descrip) {
1143
+ echo "<option value=\"$cronsched\" ";
1144
+ if ($cronsched == UpdraftPlus_Options::get_updraft_option('updraft_interval_database', UpdraftPlus_Options::get_updraft_option('updraft_interval'))) echo 'selected="selected"';
1145
+ echo ">$descrip</option>\n";
1146
+ }
1147
+ ?>
1148
+ </select> <span id="updraft_db_timings"><?php echo apply_filters('updraftplus_schedule_showdbconfig', '<input type="hidden" name="updraftplus_starttime_db" value="">'); ?></span>
1149
+ <?php
1150
+ echo __('and retain this many backups', 'updraftplus').': ';
1151
+ $updraft_retain_db = UpdraftPlus_Options::get_updraft_option('updraft_retain_db', $updraft_retain);
1152
+ $updraft_retain_db = ((int)$updraft_retain_db > 0) ? (int)$updraft_retain_db : 1;
1153
+ ?> <input type="text" name="updraft_retain_db" value="<?php echo $updraft_retain_db ?>" style="width:40px" />
1154
+ </td>
1155
+ </tr>
1156
+ <tr class="backup-interval-description">
1157
+ <td></td><td><p><?php echo htmlspecialchars(__('If you would like to automatically schedule backups, choose schedules from the dropdowns above. Backups will occur at the intervals specified. If the two schedules are the same, then the two backups will take place together. If you choose "manual" then you must click the "Backup Now" button whenever you wish a backup to occur.', 'updraftplus')); ?></p>
1158
+ <?php echo apply_filters('updraftplus_fixtime_advert', '<p><strong>'.__('To fix the time at which a backup should take place,','updraftplus').' </strong> ('.__('e.g. if your server is busy at day and you want to run overnight','updraftplus').'), <a href="http://updraftplus.com/shop/fix-time/">'.htmlspecialchars(__('use the "Fix Time" add-on','updraftplus')).'</a></p>'); ?>
1159
+ </td>
1160
+ </tr>
1161
+ <tr>
1162
+ <th>Include in files backup:</th>
1163
+ <td>
1164
+
1165
+ <?php
1166
+ $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
1167
+ $include_others_exclude = UpdraftPlus_Options::get_updraft_option('updraft_include_others_exclude',UPDRAFT_DEFAULT_OTHERS_EXCLUDE);
1168
+ # The true (default value if non-existent) here has the effect of forcing a default of on.
1169
+ foreach ($backupable_entities as $key => $info) {
1170
+ $included = (UpdraftPlus_Options::get_updraft_option("updraft_include_$key",true)) ? 'checked="checked"' : "";
1171
+ if ('others' == $key) {
1172
+ ?><input id="updraft_include_others" type="checkbox" name="updraft_include_others" value="1" <?php echo $included; ?> /> <label for="updraft_include_<?php echo $key ?>"><?php echo __('Any other directories found inside wp-content but exclude these directories:', 'updraftplus');?></label> <input type="text" name="updraft_include_others_exclude" size="44" value="<?php echo htmlspecialchars($include_others_exclude); ?>"/><br><?php
1173
+ } else {
1174
+ echo "<input id=\"updraft_include_$key\" type=\"checkbox\" name=\"updraft_include_$key\" value=\"1\" $included /><label for=\"updraft_include_$key\">".$info['description']."</label><br>";
1175
+ }
1176
+ }
1177
+ ?>
1178
+ <p><?php echo __('Include all of these, unless you are backing them up outside of UpdraftPlus. The above directories are usually everything (except for WordPress core itself which you can download afresh from WordPress.org). But if you have made customised modifications outside of these directories, you need to back them up another way.', 'updraftplus') ?> (<a href="http://wordshell.net"><?php echo __('Use WordShell for automatic backup, version control and patching', 'updraftplus');?></a>).</p></td>
1179
+ </td>
1180
+ </tr>
1181
+ <tr>
1182
+ <th><?php _e('Email','updraftplus'); ?>:</th>
1183
+ <td><input type="text" style="width:260px" name="updraft_email" value="<?php echo UpdraftPlus_Options::get_updraft_option('updraft_email'); ?>" /> <br><?php _e('Enter an address here to have a report sent (and the whole backup, if you choose) to it.','updraftplus'); ?></td>
1184
+ </tr>
1185
+
1186
+ <tr>
1187
+ <th><?php _e('Database encryption phrase','updraftplus');?>:</th>
1188
+ <?php
1189
+ $updraft_encryptionphrase = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
1190
+ ?>
1191
+ <td><input type="text" name="updraft_encryptionphrase" id="updraft_encryptionphrase" value="<?php echo $updraft_encryptionphrase ?>" style="width:132px" /></td>
1192
+ </tr>
1193
+ <tr class="backup-crypt-description">
1194
+ <td></td><td><p><?php _e('If you enter text here, it is used to encrypt backups (Rijndael). <strong>Do make a separate record of it and do not lose it, or all your backups <em>will</em> be useless.</strong> Presently, only the database file is encrypted. This is also the key used to decrypt backups from this admin interface (so if you change it, then automatic decryption will not work until you change it back).','updraftplus');?> <a href="#" onclick="jQuery('#updraftplus_db_decrypt').val(jQuery('#updraft_encryptionphrase').val()); jQuery('#updraft-manualdecrypt-modal').slideToggle(); return false;"><?php _e('You can also decrypt a database manually here.','updraftplus');?></a></p>
1195
+
1196
+ <div id="updraft-manualdecrypt-modal" style="width: 85%; margin: 16px; display:none; margin-left: 100px;">
1197
+ <p><h3><?php _e("Manually decrypt a database backup file" ,'updraftplus');?></h3></p>
1198
+ <div id="plupload-upload-ui2" style="width: 80%;">
1199
+ <div id="drag-drop-area2">
1200
+ <div class="drag-drop-inside">
1201
+ <p class="drag-drop-info"><?php _e('Drop encrypted database files (db.crypt.gz files) here to upload them for decryption'); ?></p>
1202
+ <p><?php _ex('or', 'Uploader: Drop .crypt.db.gz files here to upload them for decryption - or - Select Files'); ?></p>
1203
+ <p class="drag-drop-buttons"><input id="plupload-browse-button2" type="button" value="<?php esc_attr_e('Select Files'); ?>" class="button" /></p>
1204
+ <p style="margin-top: 18px;"><?php _e('Use decryption key','updraftplus')?>: <input id="updraftplus_db_decrypt" type="text" size="12"></input></p>
1205
+ </div>
1206
+ </div>
1207
+ <div id="filelist2">
1208
+ </div>
1209
+ </div>
1210
+
1211
+ </div>
1212
+
1213
+
1214
+ </td>
1215
+ </tr>
1216
+ </table>
1217
+
1218
+ <h2><?php _e('Copying Your Backup To Remote Storage','updraftplus');?></h2>
1219
+
1220
+ <table class="form-table" style="width:900px;">
1221
+ <tr>
1222
+ <th><?php _e('Choose your remote storage','updraftplus');?>:</th>
1223
+ <td><select name="updraft_service" id="updraft-service">
1224
+ <?php
1225
+ $debug_mode = (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) ? 'checked="checked"' : "";
1226
+
1227
+ $set = 'selected="selected"';
1228
+
1229
+ // Should be one of s3, dropbox, ftp, googledrive, email, or whatever else is added
1230
+ $active_service = UpdraftPlus_Options::get_updraft_option('updraft_service');
1231
+
1232
+ ?>
1233
+ <option value="none" <?php
1234
+ if ($active_service == "none") echo $set; ?>><?php _e('None','updraftplus'); ?></option>
1235
+ <?php
1236
+ foreach ($updraftplus->backup_methods as $method => $description) {
1237
+ echo "<option value=\"$method\"";
1238
+ if ($active_service == $method) echo ' '.$set;
1239
+ echo '>'.$description;
1240
+ echo "</option>\n";
1241
+ }
1242
+ ?>
1243
+ </select></td>
1244
+ </tr>
1245
+ <?php
1246
+ foreach ($updraftplus->backup_methods as $method => $description) {
1247
+ require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
1248
+ $call_method = "UpdraftPlus_BackupModule_$method";
1249
+ call_user_func(array($call_method, 'config_print'));
1250
+ }
1251
+ ?>
1252
+ </table>
1253
+ <script type="text/javascript">
1254
+ /* <![CDATA[ */
1255
+ var lastlog_lastmessage = "";
1256
+ var lastlog_sdata = {
1257
+ action: 'updraft_ajax',
1258
+ subaction: 'lastlog',
1259
+ nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
1260
+ };
1261
+ function updraft_showlastlog(){
1262
+ jQuery.get(ajaxurl, lastlog_sdata, function(response) {
1263
+ nexttimer = 1500;
1264
+ if (lastlog_lastmessage == response) { nexttimer = 4500; }
1265
+ setTimeout(function(){updraft_showlastlog()}, nexttimer);
1266
+ jQuery('#updraft_lastlogcontainer').html(response);
1267
+ lastlog_lastmessage = response;
1268
+ });
1269
+ }
1270
+ var lastbackup_sdata = {
1271
+ action: 'updraft_ajax',
1272
+ subaction: 'lastbackup',
1273
+ nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
1274
+ };
1275
+ var lastbackup_laststatus = '<?php echo $last_backup_html?>'
1276
+ function updraft_showlastbackup(){
1277
+ jQuery.get(ajaxurl, lastbackup_sdata, function(response) {
1278
+ if (lastbackup_laststatus == response) {
1279
+ setTimeout(function(){updraft_showlastbackup()}, 7000);
1280
+ } else {
1281
+ jQuery('#updraft_last_backup').html(response);
1282
+ }
1283
+ lastbackup_laststatus = response;
1284
+ });
1285
+ }
1286
+ var updraft_historytimer = 0;
1287
+ var calculated_diskspace = 0;
1288
+ function updraft_historytimertoggle(forceon) {
1289
+ if (!updraft_historytimer || forceon == 1) {
1290
+ updraft_updatehistory(0);
1291
+ updraft_historytimer = setInterval(function(){updraft_updatehistory(0)}, 30000);
1292
+ if (!calculated_diskspace) {
1293
+ updraftplus_diskspace();
1294
+ calculated_diskspace=1;
1295
+ }
1296
+ } else {
1297
+ clearTimeout(updraft_historytimer);
1298
+ updraft_historytimer = 0;
1299
+ }
1300
+ }
1301
+ function updraft_updatehistory(rescan) {
1302
+ if (rescan == 1) {
1303
+ jQuery('#updraft_existing_backups').html('<p style="text-align:center;"><em>Rescanning (looking for backups that you have uploaded manually into the internal backup store)...</em></p>');
1304
+ }
1305
+ jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'historystatus', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>', rescan: rescan }, function(response) {
1306
+ jQuery('#updraft_existing_backups').html(response);
1307
+ });
1308
+ }
1309
+
1310
+ function updraft_check_same_times() {
1311
+ if (jQuery('#updraft_interval').val() == jQuery('#updraft_interval_database').val() && jQuery('#updraft_interval').val() != 'manual') {
1312
+ jQuery('#updraft_db_timings').css('opacity','0.25');
1313
+ } else {
1314
+ jQuery('#updraft_db_timings').css('opacity','1');
1315
+ }
1316
+ }
1317
+
1318
+ jQuery(document).ready(function() {
1319
+
1320
+ updraft_check_same_times();
1321
+
1322
+ jQuery( "#updraft-restore-modal" ).dialog({
1323
+ autoOpen: false, height: 385, width: 480, modal: true,
1324
+ buttons: {
1325
+ '<?php _e('Restore','updraftplus');?>': function() {
1326
+ var anyselected = 0;
1327
+ jQuery('input[name="updraft_restore[]"]').each(function(x,y){
1328
+ if (jQuery(y).is(':checked')) {
1329
+ anyselected = 1;
1330
+ //alert(jQuery(y).val());
1331
+ }
1332
+ });
1333
+ if (anyselected == 1) {
1334
+ jQuery('#updraft_restore_form').submit();
1335
+ } else {
1336
+ alert('You did not select any components to restore. Please select at least one, and then try again.');
1337
+ }
1338
+ },
1339
+ '<?php _e('Cancel','updraftplus');?>': function() { jQuery(this).dialog("close"); }
1340
+ }
1341
+ });
1342
+
1343
+ jQuery( "#updraft-backupnow-modal" ).dialog({
1344
+ autoOpen: false, height: 265, width: 375, modal: true,
1345
+ buttons: {
1346
+ '<?php _e('Backup Now','updraftplus');?>': function() {
1347
+ jQuery('#updraft-backupnow-form').submit();
1348
+ },
1349
+ '<?php _e('Cancel','updraftplus');?>': function() { jQuery(this).dialog("close"); }
1350
+ }
1351
+ });
1352
+
1353
+ jQuery('#enableexpertmode').click(function() {
1354
+ jQuery('.expertmode').fadeIn();
1355
+ return false;
1356
+ });
1357
+ <?php if (!@is_writable($updraft_dir)) echo "jQuery('.backupdirrow').show();\n"; ?>
1358
+ setTimeout(function(){updraft_showlastlog();}, 1200);
1359
+ jQuery('.updraftplusmethod').hide();
1360
+ <?php
1361
+ if ($active_service) echo "jQuery('.${active_service}').show();";
1362
+ foreach ($updraftplus->backup_methods as $method => $description) {
1363
+ // already done: require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
1364
+ $call_method = "UpdraftPlus_BackupModule_$method";
1365
+ if (method_exists($call_method, 'config_print_javascript_onready')) call_user_func(array($call_method, 'config_print_javascript_onready'));
1366
+ }
1367
+ ?>
1368
+ });
1369
+ /* ]]> */
1370
+ </script>
1371
+ <table class="form-table" style="width:900px;">
1372
+ <tr>
1373
+ <td colspan="2"><h2><?php _e('Advanced / Debugging Settings','updraftplus'); ?></h2></td>
1374
+ </tr>
1375
+ <tr>
1376
+ <th><?php _e('Debug mode','updraftplus');?>:</th>
1377
+ <td><input type="checkbox" id="updraft_debug_mode" name="updraft_debug_mode" value="1" <?php echo $debug_mode; ?> /> <br><label for="updraft_debug_mode"><?php _e('Check this to receive more information and emails on the backup process - useful if something is going wrong. You <strong>must</strong> send us this log if you are filing a bug report.','updraftplus');?></label></td>
1378
+ </tr>
1379
+ <tr>
1380
+ <th><?php _e('Expert settings','updraftplus');?>:</th>
1381
+ <td><a id="enableexpertmode" href="#"><?php _e('Show expert settings','updraftplus');?></a> - <?php _e("click this to show some further options; don't bother with this unless you have a problem or are curious.",'updraftplus');?> <?php do_action('updraftplus_expertsettingsdescription'); ?></td>
1382
+ </tr>
1383
+ <?php
1384
+ $delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
1385
+ ?>
1386
+
1387
+ <tr class="deletelocal expertmode" style="display:none;">
1388
+ <th><?php _e('Delete local backup','updraftplus');?>:</th>
1389
+ <td><input type="checkbox" id="updraft_delete_local" name="updraft_delete_local" value="1" <?php if ($delete_local) echo 'checked="checked"'; ?>> <br><label for="updraft_delete_local"><?php _e('Uncheck this to prevent deletion of any superfluous backup files from your server after the backup run finishes (i.e. any files despatched remotely will also remain locally, and any files being kept locally will not be subject to the retention limits).','updraftplus');?></label></td>
1390
+ </tr>
1391
+
1392
+ <tr class="expertmode backupdirrow" style="display:none;">
1393
+ <th><?php _e('Backup directory','updraftplus');?>:</th>
1394
+ <td><input type="text" name="updraft_dir" id="updraft_dir" style="width:525px" value="<?php echo htmlspecialchars($this->prune_updraft_dir_prefix($updraft_dir)); ?>" /></td>
1395
+ </tr>
1396
+ <tr class="expertmode backupdirrow" style="display:none;">
1397
+ <td></td><td><?php
1398
+
1399
+ // Suppress warnings, since if the user is dumping warnings to screen, then invalid JavaScript results and the screen breaks.
1400
+ if(@is_writable($updraft_dir)) {
1401
+ $dir_info = '<span style="color:green">'.__('Backup directory specified is writable, which is good.','updraftplus').'</span>';
1402
+ } else {
1403
+ $dir_info = '<span style="color:red">'.__('Backup directory specified is <b>not</b> writable, or does not exist.','updraftplus').' <span style="font-size:110%;font-weight:bold"><a href="options-general.php?page=updraftplus&action=updraft_create_backup_dir">'.__('Click here to attempt to create the directory and set the permissions','updraftplus').'</a></span>, '.__('or, to reset this option','updraftplus').' <a href="#" onclick="jQuery(\'#updraft_dir\').val(\''.WP_CONTENT_DIR.'/updraft\'); return false;">'.__('click here','updraftplus').'</a>. '.__('If that is unsuccessful check the permissions on your server or change it to another directory that is writable by your web server process.','updraftplus').'</span>';
1404
+ }
1405
+
1406
+ echo $dir_info.' '.__("This is where UpdraftPlus will write the zip files it creates initially. This directory must be writable by your web server. Typically you'll want to have it inside your wp-content folder (this is the default). <b>Do not</b> place it inside your uploads dir, as that will cause recursion issues (backups of backups of backups of...).",'updraftplus');?></td>
1407
+ </tr>
1408
+ <?php do_action('updraftplus_configprint_expertoptions'); ?>
1409
+ <tr>
1410
+ <td></td>
1411
+ <td>
1412
+ <?php
1413
+ $ws_ad = $updraftplus->wordshell_random_advert(1);
1414
+ if ($ws_ad) {
1415
+ ?>
1416
+ <p style="margin: 10px 0; padding: 10px; font-size: 140%; background-color: lightYellow; border-color: #E6DB55; border: 1px solid; border-radius: 4px;">
1417
+ <?php echo $ws_ad; ?>
1418
+ </p>
1419
+ <?php
1420
+ }
1421
+ ?>
1422
+ </td>
1423
+ </tr>
1424
+ <tr>
1425
+ <td></td>
1426
+ <td>
1427
+ <input type="hidden" name="action" value="update" />
1428
+ <input type="submit" class="button-primary" value="<?php _e('Save Changes','updraftplus');?>" />
1429
+ </td>
1430
+ </tr>
1431
+ </table>
1432
+ <?php
1433
+ }
1434
+
1435
+ function recursive_directory_size($directory) {
1436
+ $size = 0;
1437
+ if(substr($directory,-1) == '/') $directory = substr($directory,0,-1);
1438
+
1439
+ if(!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) return -1;
1440
+
1441
+ if($handle = opendir($directory)) {
1442
+ while(($file = readdir($handle)) !== false) {
1443
+ $path = $directory.'/'.$file;
1444
+ if($file != '.' && $file != '..') {
1445
+ if(is_file($path)) {
1446
+ $size += filesize($path);
1447
+ } elseif(is_dir($path)) {
1448
+ $handlesize = $this->recursive_directory_size($path);
1449
+ if($handlesize >= 0) { $size += $handlesize; } else { return -1; }
1450
+ }
1451
+ }
1452
+ }
1453
+ closedir($handle);
1454
+ }
1455
+ if ($size > 1073741824) {
1456
+ return round($size / 1048576, 1).' Gb';
1457
+ } elseif ($size > 1048576) {
1458
+ return round($size / 1048576, 1).' Mb';
1459
+ } elseif ($size > 1024) {
1460
+ return round($size / 1024, 1).' Kb';
1461
+ } else {
1462
+ return round($size, 1).' b';
1463
+ }
1464
+ }
1465
+
1466
+ function existing_backup_table($backup_history = false) {
1467
+
1468
+ global $updraftplus;
1469
+
1470
+ // Fetch it if it was not passed
1471
+ if ($backup_history === false) $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1472
+ if (!is_array($backup_history)) $backup_history=array();
1473
+
1474
+ $updraft_dir = $updraftplus->backups_dir_location();
1475
+
1476
+ $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
1477
+
1478
+ echo '<table>';
1479
+
1480
+ krsort($backup_history);
1481
+
1482
+ foreach($backup_history as $key=>$value) {
1483
+ $pretty_date = date('Y-m-d G:i',$key);
1484
+ $entities = '';
1485
+ ?>
1486
+ <tr>
1487
+ <td><b><?php echo $pretty_date?></b></td>
1488
+ <td>
1489
+ <?php if (isset($value['db'])) {
1490
+ $entities .= '/db/';
1491
+ $sdescrip = preg_replace('/ \(.*\)$/', '', __('Database','updraftplus'));
1492
+ ?>
1493
+ <form id="uddownloadform_db_<?php echo $key;?>" action="admin-ajax.php" onsubmit="return updraft_downloader('uddlstatus_', <?php echo $key;?>, 'db')" method="post">
1494
+ <?php wp_nonce_field('updraftplus_download'); ?>
1495
+ <input type="hidden" name="action" value="updraft_download_backup" />
1496
+ <input type="hidden" name="type" value="db" />
1497
+ <input type="hidden" name="timestamp" value="<?php echo $key?>" />
1498
+ <input type="submit" value="<?php _e('Database','updraftplus');?>" />
1499
+ </form>
1500
+ <?php } else { echo "(No&nbsp;database)"; } ?>
1501
+ </td>
1502
+
1503
+ <?php
1504
+ foreach ($backupable_entities as $type => $info) {
1505
+ echo '<td>';
1506
+ if (isset($value[$type])) {
1507
+ $entities .= '/'.$type.'/';
1508
+ $sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']);
1509
+ ?>
1510
+ <form id="uddownloadform_<?php echo $type.'_'.$key;?>" action="admin-ajax.php" onsubmit="return updraft_downloader('uddlstatus_', '<?php echo $key."', '".$type;?>')" method="post">
1511
+ <?php wp_nonce_field('updraftplus_download'); ?>
1512
+ <input type="hidden" name="action" value="updraft_download_backup" />
1513
+ <input type="hidden" name="type" value="<?php echo $type; ?>" />
1514
+ <input type="hidden" name="timestamp" value="<?php echo $key?>" />
1515
+ <input type="submit" title="<?php echo __('Press here to download','updraftplus').' '.strtolower($info['description']); ?>" value="<?php echo $sdescrip;?>" />
1516
+ </form>
1517
+ <?php } else { printf(_x('(No %s)','Message shown when no such object is available','updraftplus'), strtolower($info['description'])); } ?>
1518
+ </td>
1519
+ <?php }; ?>
1520
+
1521
+ <td>
1522
+ <?php if (isset($value['nonce']) && preg_match("/^[0-9a-f]{12}$/",$value['nonce']) && is_readable($updraft_dir.'/log.'.$value['nonce'].'.txt')) { ?>
1523
+ <form action="options-general.php" method="get">
1524
+ <input type="hidden" name="action" value="downloadlog" />
1525
+ <input type="hidden" name="page" value="updraftplus" />
1526
+ <input type="hidden" name="updraftplus_backup_nonce" value="<?php echo $value['nonce']; ?>" />
1527
+ <input type="submit" value="<?php _e('Backup Log','updraftplus');?>" />
1528
+ </form>
1529
+ <?php } else { echo "(No&nbsp;backup&nbsp;log)"; } ?>
1530
+ </td>
1531
+ <td>
1532
+ <form method="post" action="">
1533
+ <input type="hidden" name="backup_timestamp" value="<?php echo $key;?>">
1534
+ <input type="hidden" name="action" value="updraft_restore" />
1535
+ <?php if ($entities) { ?><button title="<?php _e('After pressing this button, you will be given the option to choose which components you wish to restore','updraftplus');?>" type="button" <?php echo $restore_disabled ?> class="button-primary" style="padding-top:2px;padding-bottom:2px;font-size:16px !important; min-height:26px;" onclick="updraft_restore_options('<?php echo $entities;?>'); jQuery('#updraft_restore_timestamp').val('<?php echo $key;?>'); jQuery('#updraft_restore_date').html('<?php echo $pretty_date;?>'); jQuery('#updraft-restore-modal').dialog('open');"><?php _e('Restore','updraftplus');?></button><?php } ?>
1536
+ </form>
1537
+ </td>
1538
+ </tr>
1539
+ <script>
1540
+ function updraft_restore_options(entities) {
1541
+ jQuery('input[name="updraft_restore[]"]').each(function(x,y){
1542
+ var entity = jQuery(y).val();
1543
+ if (entities.indexOf('/'+entity+'/') != -1) {
1544
+ jQuery(y).removeAttr('disabled').parent().show();
1545
+ } else {
1546
+ jQuery(y).attr('disabled','disabled').parent().hide();
1547
+ }
1548
+ });
1549
+ }
1550
+ </script>
1551
+ <?php }
1552
+ echo '</table>';
1553
+ }
1554
+
1555
+ // This function examines inside the updraft directory to see if any new archives have been uploaded. If so, it adds them to the backup set. (No removal of items from the backup set is done)
1556
+ function rebuild_backup_history() {
1557
+
1558
+ global $updraftplus;
1559
+
1560
+ $known_files = array();
1561
+ $known_nonces = array();
1562
+ $changes = false;
1563
+
1564
+ $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1565
+ if (!is_array($backup_history)) $backup_history = array();
1566
+
1567
+ // Accumulate a list of known files
1568
+ foreach ($backup_history as $btime => $bdata) {
1569
+ foreach ($bdata as $key => $value) {
1570
+ // Record which set this file is found in
1571
+ if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(zip|gz|gz\.crypt)$/i', $value, $matches)) {
1572
+ $nonce = $matches[2];
1573
+ $known_files[$value] = $nonce;
1574
+ $known_nonces[$nonce] = $btime;
1575
+ }
1576
+ }
1577
+ }
1578
+
1579
+ $updraft_dir = $updraftplus->backups_dir_location();
1580
+
1581
+ if (!is_dir($updraft_dir)) return;
1582
+
1583
+ if (!$handle = opendir($updraft_dir)) return;
1584
+
1585
+ while (false !== ($entry = readdir($handle))) {
1586
+ if ($entry != "." && $entry != "..") {
1587
+ if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)\.(zip|gz|gz\.crypt)$/i', $entry, $matches)) {
1588
+ $btime = strtotime($matches[1]);
1589
+ if ($btime > 100) {
1590
+ if (!isset($known_files[$entry])) {
1591
+ $changes = true;
1592
+ $nonce = $matches[2];
1593
+ $type = $matches[3];
1594
+ // The time from the filename does not include seconds. Need to identify the seconds to get the right time
1595
+ if (isset($known_nonces[$nonce])) $btime = $known_nonces[$nonce];
1596
+ if (!isset($backup_history[$btime])) $backup_history[$btime] = array();
1597
+ $backup_history[$btime][$type] = $entry;
1598
+ $backup_history[$btime][$type.'-size'] = filesize($updraft_dir.'/'.$entry);
1599
+ $backup_history[$btime]['nonce'] = $nonce;
1600
+ }
1601
+ }
1602
+ }
1603
+ }
1604
+ }
1605
+
1606
+
1607
+ if ($changes) UpdraftPlus_Options::update_updraft_option('updraft_backup_history', $backup_history);
1608
+
1609
+ }
1610
+
1611
+ function restore_backup($timestamp) {
1612
+
1613
+ @set_time_limit(900);
1614
+
1615
+ global $wp_filesystem, $updraftplus;
1616
+ $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1617
+ if(!is_array($backup_history[$timestamp])) {
1618
+ echo '<p>'.__('This backup does not exist in the backup history - restoration aborted. Timestamp:','updraftplus')." $timestamp</p><br/>";
1619
+ return false;
1620
+ }
1621
+
1622
+ $credentials = request_filesystem_credentials("options-general.php?page=updraftplus&action=updraft_restore&backup_timestamp=$timestamp");
1623
+ WP_Filesystem($credentials);
1624
+ if ( $wp_filesystem->errors->get_error_code() ) {
1625
+ foreach ( $wp_filesystem->errors->get_error_messages() as $message )
1626
+ show_message($message);
1627
+ exit;
1628
+ }
1629
+
1630
+ //if we make it this far then WP_Filesystem has been instantiated and is functional (tested with ftpext, what about suPHP and other situations where direct may work?)
1631
+ echo '<h1>'.__('UpdraftPlus Restoration: Progress', 'updraftplus').'</h1><div id="updraft-restore-progress">';
1632
+
1633
+ $updraft_dir = $updraftplus->backups_dir_location().'/';
1634
+
1635
+ $service = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
1636
+
1637
+ if (!isset($_POST['updraft_restore']) || !is_array($_POST['updraft_restore'])) {
1638
+ echo '<p>'.__('ABORT: Could not find the information on which entities to restore.', 'updraftplus').'</p>';
1639
+ return false;
1640
+ }
1641
+
1642
+ $entities_to_restore = array_flip($_POST['updraft_restore']);
1643
+
1644
+ $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
1645
+
1646
+ foreach($backup_history[$timestamp] as $type => $file) {
1647
+ // All restorable entities must be given explicitly, as we can store other arbitrary data in the history array
1648
+
1649
+ if (!isset($backupable_entities[$type]) && 'db' != $type) continue;
1650
+
1651
+ if ($type == 'db') {
1652
+ echo "<h2>".__('Database','updraftplus')."</h2>";
1653
+ } else {
1654
+ echo "<h2>".$backupable_entities[$type]['description']."</h2>";
1655
+ }
1656
+
1657
+ if (!isset($entities_to_restore[$type])) {
1658
+ echo "<p>$type: ".__('This component was not selected for restoration - skipping.', 'updraftplus')."</p>";
1659
+ continue;
1660
+ }
1661
+
1662
+ $fullpath = $updraft_dir.$file;
1663
+
1664
+ echo "Looking for $type archive: file name: ".htmlspecialchars($file)."<br>";
1665
+ if(!is_readable($fullpath)) {
1666
+ echo __("File is not locally present - needs retrieving from remote storage (for large files, it is better to do this in advance from the download console)",'updraftplus')."<br>";
1667
+ $this->download_file($file, $service);
1668
+ }
1669
+ // If a file size is stored in the backup data, then verify correctness of the local file
1670
+ if (isset($backup_history[$timestamp][$type.'-size'])) {
1671
+ $fs = $backup_history[$timestamp][$type.'-size'];
1672
+ echo __("Archive is expected to be size:",'updraftplus')." ".round($fs/1024)." Kb :";
1673
+ $as = @filesize($fullpath);
1674
+ if ($as == $fs) {
1675
+ echo "OK<br>";
1676
+ } else {
1677
+ echo "<strong>".__('ERROR','updraftplus').":</strong> is size: ".round($as/1024)." ($fs, $as)<br>";
1678
+ }
1679
+ } else {
1680
+ echo __("The backup records do not contain information about the proper size of this file.",'updraftplus')."<br>";
1681
+ }
1682
+ # Types: uploads, themes, plugins, others, db
1683
+ if(is_readable($fullpath)) {
1684
+
1685
+ if(!class_exists('WP_Upgrader')) require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
1686
+ require_once(UPDRAFTPLUS_DIR.'/includes/updraft-restorer.php');
1687
+ $restorer = new Updraft_Restorer();
1688
+ $val = $restorer->restore_backup($fullpath, $type, $service, $backupable_entities[$type]);
1689
+
1690
+ if(is_wp_error($val)) {
1691
+ foreach ($val->get_error_messages() as $msg) {
1692
+ echo '<strong>'.__('Error message', 'updraftplus').':</strong> '.htmlspecialchars($msg).'<br>';
1693
+ }
1694
+ echo '</div>'; //close the updraft_restore_progress div even if we error
1695
+ return false;
1696
+ }
1697
+ } else {
1698
+ $updraftplus->error("$file: ".__('Could not find one of the files for restoration', 'updraftplus'));
1699
+ echo __('Could not find one of the files for restoration', 'updraftplus').": ($file)";
1700
+ }
1701
+ }
1702
+ echo '</div>'; //close the updraft_restore_progress div
1703
+ return true;
1704
+ }
1705
+
1706
+
1707
+
1708
+ }
1709
+
1710
+ ?>
backup.php ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (!defined ('ABSPATH')) die ('No direct access allowed');
4
+
5
+ // This file contains functions moved out of updraftplus.php that are only needed when a backup is running (reduce memory usage on other site pages)
6
+
7
+ global $updraftplus_backup;
8
+ $updraftplus_backup = new UpdraftPlus_Backup();
9
+ if (defined('UPDRAFTPLUS_PREFERPCLZIP') && UPDRAFTPLUS_PREFERPCLZIP == true) $updraftplus_backup->zip_preferpcl = true;
10
+
11
+ class UpdraftPlus_Backup {
12
+
13
+ var $zipfiles_added;
14
+ var $zipfiles_existingfiles;
15
+ var $zipfiles_dirbatched;
16
+ var $zipfiles_batched;
17
+
18
+ var $zip_preferpcl = false;
19
+
20
+ // This function recursively packs the zip, dereferencing symlinks but packing into a single-parent tree for universal unpacking
21
+ function makezip_recursive_add($zipfile, $fullpath, $use_path_when_storing, $original_fullpath) {
22
+
23
+ global $updraftplus;
24
+
25
+ // De-reference
26
+ $fullpath = realpath($fullpath);
27
+
28
+ // Is the place we've ended up above the original base? That leads to infinite recursion
29
+ if (($fullpath !== $original_fullpath && strpos($original_fullpath, $fullpath) === 0) || ($original_fullpath == $fullpath && strpos($use_path_when_storing, '/') !== false) ) {
30
+ $updraftplus->log("Infinite recursion: symlink lead us to $fullpath, which is within $original_fullpath");
31
+ $updraftplus->error(__("Infinite recursion: consult your log for more information",'updraftplus'));
32
+ return false;
33
+ }
34
+
35
+ if(is_file($fullpath)) {
36
+ if (is_readable($fullpath)) {
37
+ $key = ($fullpath == $original_fullpath) ? basename($fullpath) : $use_path_when_storing.'/'.basename($fullpath);
38
+ $this->zipfiles_batched[$fullpath] = $key;
39
+ @touch($zipfile);
40
+ } else {
41
+ $updraftplus->log("$fullpath: unreadable file");
42
+ $updraftplus->error("$fullpath: unreadable file");
43
+ }
44
+ } elseif (is_dir($fullpath)) {
45
+ if (!isset($this->existing_files[$use_path_when_storing])) $this->zipfiles_dirbatched[] = $use_path_when_storing;
46
+ if (!$dir_handle = @opendir($fullpath)) {
47
+ $updraftplus->log("Failed to open directory: $fullpath");
48
+ $updraftplus->error("Failed to open directory: $fullpath");
49
+ return;
50
+ }
51
+ while ($e = readdir($dir_handle)) {
52
+ if ($e != '.' && $e != '..') {
53
+ if (is_link($fullpath.'/'.$e)) {
54
+ $deref = realpath($fullpath.'/'.$e);
55
+ if (is_file($deref)) {
56
+ if (is_readable($deref)) {
57
+ $this->zipfiles_batched[$deref] = $use_path_when_storing.'/'.$e;
58
+ @touch($zipfile);
59
+ } else {
60
+ $updraftplus->log("$deref: unreadable file");
61
+ $updraftplus->error("$deref: unreadable file");
62
+ }
63
+ } elseif (is_dir($deref)) {
64
+ $this->makezip_recursive_add($zipfile, $deref, $use_path_when_storing.'/'.$e, $original_fullpath);
65
+ }
66
+ } elseif (is_file($fullpath.'/'.$e)) {
67
+ if (is_readable($fullpath.'/'.$e)) {
68
+ $this->zipfiles_batched[$fullpath.'/'.$e] = $use_path_when_storing.'/'.$e;
69
+ @touch($zipfile);
70
+ } else {
71
+ $updraftplus->log("$fullpath/$e: unreadable file");
72
+ $updraftplus->error("$fullpath/$e: unreadable file");
73
+ }
74
+ } elseif (is_dir($fullpath.'/'.$e)) {
75
+ // no need to addEmptyDir here, as it gets done when we recurse
76
+ $this->makezip_recursive_add($zipfile, $fullpath.'/'.$e, $use_path_when_storing.'/'.$e, $original_fullpath);
77
+ }
78
+ }
79
+ }
80
+ closedir($dir_handle);
81
+ }
82
+
83
+ // We don't want to touch the zip file on every single file, so we batch them up
84
+ // We go every 25 files, because if you wait too much longer, the contents may have changed from under you
85
+ // And for some redundancy (redundant because of the touches going on anyway), we try to touch the file after 20 seconds, to help with the "recently modified" check on resumption (we saw a case where the file went for 155 seconds without being touched and so the other runner was not detected)
86
+ if (count($this->zipfiles_batched) > 25 || (file_exists($zipfile) && ((time()-filemtime($zipfile)) > 20) )) {
87
+ $ret = $this->makezip_addfiles($zipfile);
88
+ } else {
89
+ $ret = true;
90
+ }
91
+
92
+ return $ret;
93
+
94
+ }
95
+
96
+ // Caution: $source is allowed to be an array, not just a filename
97
+ function make_zipfile($source, $destination) {
98
+
99
+ global $updraftplus;
100
+
101
+ // When to prefer PCL:
102
+ // - We were asked to
103
+ // - No zip extension present and no relevant method present
104
+ // The zip extension check is not redundant, because method_exists segfaults some PHP installs, leading to support requests
105
+
106
+ // Fallback to PclZip - which my tests show is 25% slower (and we can't resume)
107
+ if ($this->zip_preferpcl || (!extension_loaded('zip') && !method_exists('ZipArchive', 'AddFile'))) {
108
+ if(!class_exists('PclZip')) require_once(ABSPATH.'/wp-admin/includes/class-pclzip.php');
109
+ $zip_object = new PclZip($destination);
110
+ $zipcode = $zip_object->create($source, PCLZIP_OPT_REMOVE_PATH, WP_CONTENT_DIR);
111
+ if ($zipcode == 0 ) {
112
+ $updraftplus->log("PclZip Error: ".$zip_object->errorName());
113
+ return $zip_object->errorCode();
114
+ } else {
115
+ return true;
116
+ }
117
+ }
118
+
119
+ $this->existing_files = array();
120
+
121
+ // If the file exists, then we should grab its index of files inside, and sizes
122
+ // Then, when we come to write a file, we should check if it's already there, and only add if it is not
123
+ if (file_exists($destination) && is_readable($destination)) {
124
+ $zip = new ZipArchive;
125
+ $zip->open($destination);
126
+ $updraftplus->log(basename($destination).": Zip file already exists, with ".$zip->numFiles." files");
127
+ for ($i=0; $i<$zip->numFiles; $i++) {
128
+ $si = $zip->statIndex($i);
129
+ $name = $si['name'];
130
+ $this->existing_files[$name] = $si['size'];
131
+ }
132
+ } elseif (file_exists($destination)) {
133
+ $updraftplus->log("Zip file already exists, but is not readable; will remove: $destination");
134
+ @unlink($destination);
135
+ }
136
+
137
+ $this->zipfiles_added = 0;
138
+ $this->zipfiles_dirbatched = array();
139
+ $this->zipfiles_batched = array();
140
+
141
+ // Magic value, used later to detect no error occurring
142
+ $last_error = 2349864;
143
+ if (is_array($source)) {
144
+ foreach ($source as $element) {
145
+ $howmany = $this->makezip_recursive_add($destination, $element, basename($element), $element);
146
+ if ($howmany < 0) {
147
+ $last_error = $howmany;
148
+ }
149
+ }
150
+ } else {
151
+ $howmany = $this->makezip_recursive_add($destination, $source, basename($source), $source);
152
+ if ($howmany < 0) {
153
+ $last_error = $howmany;
154
+ }
155
+ }
156
+
157
+ // Any not yet dispatched?
158
+ if (count($this->zipfiles_dirbatched)>0 || count($this->zipfiles_batched)>0) {
159
+ $howmany = $this->makezip_addfiles($destination);
160
+ if ($howmany < 0) {
161
+ $last_error = $howmany;
162
+ }
163
+ }
164
+
165
+ if ($this->zipfiles_added > 0 || $last_error == 2349864) {
166
+ // ZipArchive::addFile sometimes fails
167
+ if (filesize($destination) < 100) {
168
+ // Retry with PclZip
169
+ $updraftplus->log("Zip::addFile apparently failed - retrying with PclZip");
170
+ $this->zip_preferpcl = true;
171
+ return $this->make_zipfile($source, $destination);
172
+ }
173
+ return true;
174
+ } else {
175
+ return $last_error;
176
+ }
177
+
178
+ }
179
+
180
+ // Q. Why don't we only open and close the zip file just once?
181
+ // A. Because apparently PHP doesn't write out until the final close, and it will return an error if anything file has vanished in the meantime. So going directory-by-directory reduces our chances of hitting an error if the filesystem is changing underneath us (which is very possible if dealing with e.g. 1Gb of files)
182
+
183
+ // We batch up the files, rather than do them one at a time. So we are more efficient than open,one-write,close.
184
+ function makezip_addfiles($zipfile) {
185
+
186
+ global $updraftplus;
187
+
188
+ // Short-circuit the null case, because we want to detect later if something useful happenned
189
+ if (count($this->zipfiles_dirbatched) == 0 && count($this->zipfiles_batched) == 0) return true;
190
+
191
+ // 05-Mar-2013 - added a new check on the total data added; it appears that things fall over if too much data is contained in the cumulative total of files that were addFile'd without a close-open cycle; presumably data is being stored in memory. In the case in question, it was a batch of MP3 files of around 100Mb each - 25 of those equals 2.5Gb!
192
+
193
+ $data_added_since_reopen = 0;
194
+
195
+ $zip = new ZipArchive();
196
+ if (file_exists($zipfile)) {
197
+ $opencode = $zip->open($zipfile);
198
+ $original_size = filesize($zipfile);
199
+ clearstatcache($zipfile);
200
+ } else {
201
+ $opencode = $zip->open($zipfile, ZIPARCHIVE::CREATE);
202
+ $original_size = 0;
203
+ }
204
+
205
+ if ($opencode !== true) return array($opencode, 0);
206
+ // Make sure all directories are created before we start creating files
207
+ while ($dir = array_pop($this->zipfiles_dirbatched)) {
208
+ $zip->addEmptyDir($dir);
209
+ }
210
+ foreach ($this->zipfiles_batched as $file => $add_as) {
211
+ $fsize = filesize($file);
212
+ if (!isset($this->existing_files[$add_as]) || $this->existing_files[$add_as] != $fsize) {
213
+
214
+ touch($file);
215
+ $zip->addFile($file, $add_as);
216
+
217
+ $data_added_since_reopen += $fsize;
218
+ # 25Mb - force a write-out and re-open
219
+ if ($data_added_since_reopen > 26214400) {
220
+
221
+ $before_size = filesize($zipfile);
222
+ clearstatcache($zipfile);
223
+
224
+ $updraftplus->log("Adding batch to zip file: over 25Mb added on this batch (".round($data_added_since_reopen/1048576,1)." Mb); re-opening (prior size: ".round($before_size/1024,1).' Kb)');
225
+ if (!$zip->close()) {
226
+ $updraftplus->log("zip::Close returned an error");
227
+ }
228
+ unset($zip);
229
+ $zip = new ZipArchive();
230
+ $opencode = $zip->open($zipfile);
231
+ if ($opencode !== true) return array($opencode, 0);
232
+ $data_added_since_reopen = 0;
233
+ // Call here, in case we've got so many big files that we don't complete the whole routine
234
+ if (filesize($zipfile) > $before_size) $updraftplus->something_useful_happened();
235
+ clearstatcache($zipfile);
236
+ }
237
+ }
238
+ $this->zipfiles_added++;
239
+ if ($this->zipfiles_added % 100 == 0) $updraftplus->log("Zip: ".basename($zipfile).": ".$this->zipfiles_added." files added (on-disk size: ".round(filesize($zipfile)/1024,1)." Kb)");
240
+ }
241
+ // Reset the array
242
+ $this->zipfiles_batched = array();
243
+ $ret = $zip->close();
244
+ if (filesize($zipfile) > $original_size) $updraftplus->something_useful_happened();
245
+ return $ret;
246
+ }
247
+
248
+ function create_zip($create_from_dir, $whichone, $create_in_dir, $backup_file_basename) {
249
+ // Note: $create_from_dir can be an array or a string
250
+ @set_time_limit(900);
251
+
252
+ global $updraftplus;
253
+
254
+ if ($whichone != "others") $updraftplus->log("Beginning creation of dump of $whichone");
255
+
256
+ $full_path = $create_in_dir.'/'.$backup_file_basename.'-'.$whichone.'.zip';
257
+ $time_now = time();
258
+
259
+ if (file_exists($full_path)) {
260
+ $updraftplus->log("$backup_file_basename-$whichone.zip: this file has already been created");
261
+ $time_mod = (int)@filemtime($full_path);
262
+ if ($time_mod>100 && ($time_now-$time_mod)<30) {
263
+ $updraftplus->log("Terminate: the zip $full_path already exists, and was modified within the last 30 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).", size=".filesize($full_path)."). This likely means that another UpdraftPlus run is still at work; so we will exit.");
264
+ $updraftplus->increase_resume_and_reschedule(120);
265
+ die;
266
+ }
267
+ return basename($full_path);
268
+ }
269
+
270
+ // Temporary file, to be able to detect actual completion (upon which, it is renamed)
271
+
272
+ // Firstly, make sure that the temporary file is not already being written to - which can happen if a resumption takes place whilst an old run is still active
273
+ $zip_name = $full_path.'.tmp';
274
+ $time_mod = (int)@filemtime($zip_name);
275
+ if (file_exists($zip_name) && $time_mod>100 && ($time_now-$time_mod)<30) {
276
+ $file_size = filesize($zip_name);
277
+ $updraftplus->log("Terminate: the temporary file $zip_name already exists, and was modified within the last 30 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).", size=$file_size). This likely means that another UpdraftPlus run is still at work; so we will exit.");
278
+ $updraftplus->increase_resume_and_reschedule(120);
279
+ die;
280
+ } elseif (file_exists($zip_name)) {
281
+ $updraftplus->log("File exists ($zip_name), but was apparently not modified within the last 30 seconds, so we assume that any previous run has now terminated (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).")");
282
+ }
283
+
284
+ $microtime_start = microtime(true);
285
+ # The paths in the zip should then begin with '$whichone', having removed WP_CONTENT_DIR from the front
286
+ $zipcode = $this->make_zipfile($create_from_dir, $zip_name);
287
+ if ($zipcode !== true) {
288
+ $updraftplus->log("ERROR: Zip failure: Could not create $whichone zip: code=$zipcode");
289
+ $updraftplus->error(sprintf(__("Could not create %s zip. Consult the log file for more information.",'updraftplus'),$whichone));
290
+ return false;
291
+ } else {
292
+ rename($full_path.'.tmp', $full_path);
293
+ $timetaken = max(microtime(true)-$microtime_start, 0.000001);
294
+ $kbsize = filesize($full_path)/1024;
295
+ $rate = round($kbsize/$timetaken, 1);
296
+ $updraftplus->log("Created $whichone zip - file size is ".round($kbsize,1)." Kb in ".round($timetaken,1)." s ($rate Kb/s)");
297
+ }
298
+
299
+ return basename($full_path);
300
+ }
301
+
302
+
303
+ }
example-decrypt.php CHANGED
@@ -27,13 +27,11 @@ function rijndael_decrypt_file($file, $key) {
27
  require_once(dirname(__FILE__).'/includes/phpseclib/Crypt/Rijndael.php');
28
 
29
  $rijndael = new Crypt_Rijndael();
 
30
  $rijndael->setKey($key);
31
- $in_handle = fopen($file,'r');
32
- $ciphertext = "";
33
- while (!feof ($in_handle)) {
34
- $ciphertext .= fread($in_handle, 16384);
35
- }
36
- fclose ($in_handle);
37
  print $rijndael->decrypt($ciphertext);
38
 
39
  }
27
  require_once(dirname(__FILE__).'/includes/phpseclib/Crypt/Rijndael.php');
28
 
29
  $rijndael = new Crypt_Rijndael();
30
+
31
  $rijndael->setKey($key);
32
+
33
+ $ciphertext = file_get_contents($file);
34
+
 
 
 
35
  print $rijndael->decrypt($ciphertext);
36
 
37
  }
includes/ajax.js DELETED
File without changes
includes/ftp.class.php CHANGED
@@ -51,63 +51,121 @@ class UpdraftPlus_ftp_wrapper
51
  }
52
  }
53
 
54
- public function put($local_file_path, $remote_file_path, $mode = FTP_ASCII)
55
- {
56
- if (ftp_put($this->conn_id, $remote_file_path, $local_file_path, $mode))
57
- {
58
- return true;
 
 
 
 
 
 
 
 
 
 
59
  }
60
- else
61
- {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  return false;
63
  }
 
 
 
64
  }
65
 
66
- public function get($local_file_path, $remote_file_path, $mode = FTP_ASCII)
67
- {
68
- if (ftp_get($this->conn_id, $local_file_path, $remote_file_path, $mode))
69
- {
70
- return true;
 
 
 
 
 
71
  }
72
- else
73
- {
74
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  }
 
 
 
 
 
 
 
 
 
 
 
76
  }
77
-
78
  public function chmod($permissions, $remote_filename)
79
  {
80
- if ($this->is_octal($permissions))
81
- {
82
  $result = ftp_chmod($this->conn_id, $permissions, $remote_filename);
83
- if ($result)
84
- {
85
  return true;
86
- }
87
- else
88
- {
89
  return false;
90
  }
91
- }
92
- else
93
- {
94
  throw new Exception('$permissions must be an octal number');
95
  }
96
  }
97
 
98
- public function chdir($directory)
99
- {
100
  ftp_chdir($this->conn_id, $directory);
101
  }
102
 
103
- public function delete($remote_file_path)
104
- {
105
- if (ftp_delete($this->conn_id, $remote_file_path))
106
- {
107
  return true;
108
- }
109
- else
110
- {
111
  return false;
112
  }
113
  }
51
  }
52
  }
53
 
54
+ public function put($local_file_path, $remote_file_path, $mode = FTP_BINARY, $resume = false, $updraftplus = false) {
55
+
56
+ $file_size = filesize($local_file_path);
57
+
58
+ $existing_size = 0;
59
+ if ($resume) {
60
+ $existing_size = ftp_size($this->conn_id, $remote_file_path);
61
+ if ($existing_size <=0) { $resume = false; $existing_size = 0; }
62
+ elseif ($updraftplus) {
63
+ $updraftplus->log("File already exists at remote site: size $existing_size. Will attempt resumption.");
64
+ if ($existing_size >= $file_size) {
65
+ $updraftplus->log("File is apparently already completely uploaded");
66
+ return true;
67
+ }
68
+ }
69
  }
70
+
71
+ // From here on, $file_size is only used for logging calculations. We want to avoid divsion by zero.
72
+ $file_size = max($file_size, 1);
73
+
74
+ if (!$fh = fopen($local_file_path, 'rb')) return false;
75
+ if ($existing_size) fseek($fh, $existing_size);
76
+
77
+ $ret = ftp_nb_fput($this->conn_id, $remote_file_path, $fh, FTP_BINARY, $existing_size);
78
+
79
+ // $existing_size can now be re-purposed
80
+
81
+ while ($ret == FTP_MOREDATA) {
82
+ if ($updraftplus) {
83
+ $new_size = ftell($fh);
84
+ if ($new_size - $existing_size > 524288) {
85
+ $existing_size = $new_size;
86
+ $percent = round(100*$new_size/$file_size,1);
87
+ $updraftplus->record_uploaded_chunk($percent, '', $local_file_path);
88
+ }
89
+ }
90
+ // Continue upload
91
+ $ret = ftp_nb_continue($this->conn_id);
92
+ }
93
+
94
+ fclose($fh);
95
+
96
+ if ($ret != FTP_FINISHED) {
97
+ if ($updraftplus) $updraftplus->log("FTP upload: error ($ret)");
98
  return false;
99
  }
100
+
101
+ return true;
102
+
103
  }
104
 
105
+ public function get($local_file_path, $remote_file_path, $mode = FTP_BINARY, $resume = false, $updraftplus = false) {
106
+
107
+ $file_last_size = 0;
108
+
109
+ if ($resume) {
110
+ if (!$fh = fopen($local_file_path, 'ab')) return false;
111
+ clearstatcache($local_file_path);
112
+ $file_last_size = filesize($local_file_path);
113
+ } else {
114
+ if (!$fh = fopen($local_file_path, 'wb')) return false;
115
  }
116
+
117
+ $ret = ftp_nb_fget($this->conn_id, $fh, $remote_file_path, $mode, $file_last_size);
118
+
119
+ if (false == $ret) return false;
120
+
121
+ while ($ret == FTP_MOREDATA) {
122
+
123
+ if ($updraftplus) {
124
+ $file_now_size = filesize($local_file_path);
125
+ if ($file_now_size - $file_last_size > 524288) {
126
+ $updraftplus->log("FTP fetch: file size is now: ".sprintf("%0.2f",filesize($local_file_path)/1048576)." Mb");
127
+ $file_last_size = $file_now_size;
128
+ }
129
+ clearstatcache($local_file_path);
130
+ }
131
+
132
+ $ret = ftp_nb_continue($this->conn_id);
133
  }
134
+
135
+ fclose($fh);
136
+
137
+ if ($ret == FTP_FINISHED) {
138
+ if ($updraftplus) $updraftplus->log("FTP fetch: fetch complete");
139
+ return true;
140
+ } else {
141
+ if ($updraftplus) $updraftplus->log("FTP fetch: fetch failed");
142
+ return false;
143
+ }
144
+
145
  }
146
+
147
  public function chmod($permissions, $remote_filename)
148
  {
149
+ if ($this->is_octal($permissions)) {
 
150
  $result = ftp_chmod($this->conn_id, $permissions, $remote_filename);
151
+ if ($result) {
 
152
  return true;
153
+ } else {
 
 
154
  return false;
155
  }
156
+ } else {
 
 
157
  throw new Exception('$permissions must be an octal number');
158
  }
159
  }
160
 
161
+ public function chdir($directory) {
 
162
  ftp_chdir($this->conn_id, $directory);
163
  }
164
 
165
+ public function delete($remote_file_path) {
166
+ if (ftp_delete($this->conn_id, $remote_file_path)) {
 
 
167
  return true;
168
+ } else {
 
 
169
  return false;
170
  }
171
  }
includes/ud-plupload.js ADDED
@@ -0,0 +1,168 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ jQuery(document).ready(function($){
2
+
3
+ // create the uploader and pass the config from above
4
+ var uploader = new plupload.Uploader(updraft_plupload_config);
5
+
6
+ // checks if browser supports drag and drop upload, makes some css adjustments if necessary
7
+ uploader.bind('Init', function(up){
8
+ var uploaddiv = $('#plupload-upload-ui');
9
+
10
+ if(up.features.dragdrop){
11
+ uploaddiv.addClass('drag-drop');
12
+ $('#drag-drop-area')
13
+ .bind('dragover.wp-uploader', function(){ uploaddiv.addClass('drag-over'); })
14
+ .bind('dragleave.wp-uploader, drop.wp-uploader', function(){ uploaddiv.removeClass('drag-over'); });
15
+
16
+ } else {
17
+ uploaddiv.removeClass('drag-drop');
18
+ $('#drag-drop-area').unbind('.wp-uploader');
19
+ }
20
+ });
21
+
22
+ uploader.init();
23
+
24
+ // a file was added in the queue
25
+ uploader.bind('FilesAdded', function(up, files){
26
+ // var hundredmb = 100 * 1024 * 1024, max = parseInt(up.settings.max_file_size, 10);
27
+
28
+ plupload.each(files, function(file){
29
+
30
+ if (! /^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(zip|gz|gz\.crypt)$/i.test(file.name)) {
31
+ alert(file.name+': This file is a zip, but does not appear to be an UpdraftPlus backup archive (such files are .zip files which have a name like: backup_(time)_(site name)_(code)_(type).zip)');
32
+ uploader.removeFile(file);
33
+ return;
34
+ }
35
+
36
+ // a file was added, you may want to update your DOM here...
37
+ $('#filelist').append(
38
+ '<div class="file" id="' + file.id + '"><b>' +
39
+ file.name + '</b> (<span>' + plupload.formatSize(0) + '</span>/' + plupload.formatSize(file.size) + ') ' +
40
+ '<div class="fileprogress"></div></div>');
41
+ });
42
+
43
+ up.refresh();
44
+ up.start();
45
+ });
46
+
47
+ uploader.bind('UploadProgress', function(up, file) {
48
+
49
+ $('#' + file.id + " .fileprogress").width(file.percent + "%");
50
+ $('#' + file.id + " span").html(plupload.formatSize(parseInt(file.size * file.percent / 100)));
51
+ });
52
+
53
+ uploader.bind('Error', function(up, error) {
54
+
55
+ alert('Upload error (code '+error.code+") : "+error.message+" (make sure that you were trying to upload a zip file previously created by UpdraftPlus)");
56
+
57
+ });
58
+
59
+
60
+ // a file was uploaded
61
+ uploader.bind('FileUploaded', function(up, file, response) {
62
+
63
+ if (response.status == '200') {
64
+ // this is your ajax response, update the DOM with it or something...
65
+ if (response.response.substring(0,6) == 'ERROR:') {
66
+ alert("Upload error: "+response.response.substring(6));
67
+ } else if (response.response.substring(0,3) == 'OK:') {
68
+ updraft_updatehistory(1);
69
+ } else {
70
+ alert('Unknown server response: '+response.response);
71
+ }
72
+ } else {
73
+ alert('Unknown server response status: '+response.code);
74
+ }
75
+
76
+ });
77
+
78
+ });
79
+
80
+
81
+
82
+
83
+
84
+
85
+
86
+ // Next: the encrypted database pluploader
87
+
88
+ jQuery(document).ready(function($){
89
+
90
+ // create the uploader and pass the config from above
91
+ var uploader = new plupload.Uploader(updraft_plupload_config2);
92
+
93
+ // checks if browser supports drag and drop upload, makes some css adjustments if necessary
94
+ uploader.bind('Init', function(up){
95
+ var uploaddiv = $('#plupload-upload-ui2');
96
+
97
+ if(up.features.dragdrop){
98
+ uploaddiv.addClass('drag-drop');
99
+ $('#drag-drop-area2')
100
+ .bind('dragover.wp-uploader', function(){ uploaddiv.addClass('drag-over'); })
101
+ .bind('dragleave.wp-uploader, drop.wp-uploader', function(){ uploaddiv.removeClass('drag-over'); });
102
+ } else {
103
+ uploaddiv.removeClass('drag-drop');
104
+ $('#drag-drop-area2').unbind('.wp-uploader');
105
+ }
106
+ });
107
+
108
+ uploader.init();
109
+
110
+ // a file was added in the queue
111
+ uploader.bind('FilesAdded', function(up, files){
112
+ // var hundredmb = 100 * 1024 * 1024, max = parseInt(up.settings.max_file_size, 10);
113
+
114
+ plupload.each(files, function(file){
115
+
116
+ if (! /^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(gz\.crypt)$/i.test(file.name)) {
117
+ alert(file.name+': This file does not appear to be an UpdraftPlus encrypted database archive (such files are .gz.crypt files which have a name like: backup_(time)_(site name)_(code)_db.crypt.gz)');
118
+ uploader.removeFile(file);
119
+ return;
120
+ }
121
+
122
+ // a file was added, you may want to update your DOM here...
123
+ $('#filelist2').append(
124
+ '<div class="file" id="' + file.id + '"><b>' +
125
+ file.name + '</b> (<span>' + plupload.formatSize(0) + '</span>/' + plupload.formatSize(file.size) + ') ' +
126
+ '<div class="fileprogress"></div></div>');
127
+ });
128
+
129
+ up.refresh();
130
+ up.start();
131
+ });
132
+
133
+ uploader.bind('UploadProgress', function(up, file) {
134
+
135
+ $('#' + file.id + " .fileprogress").width(file.percent + "%");
136
+ $('#' + file.id + " span").html(plupload.formatSize(parseInt(file.size * file.percent / 100)));
137
+ });
138
+
139
+ uploader.bind('Error', function(up, error) {
140
+
141
+ alert('Upload error (code '+error.code+") : "+error.message+" (make sure that you were trying to upload a backup file previously created by UpdraftPlus)");
142
+
143
+ });
144
+
145
+ // a file was uploaded
146
+ uploader.bind('FileUploaded', function(up, file, response) {
147
+
148
+ if (response.status == '200') {
149
+ // this is your ajax response, update the DOM with it or something...
150
+ if (response.response.substring(0,6) == 'ERROR:') {
151
+ alert("Upload error: "+response.response.substring(6));
152
+ } else if (response.response.substring(0,3) == 'OK:') {
153
+ bkey = response.response.substring(3);
154
+ // $('#' + file.id + " .fileprogress").width("100%");
155
+ // $('#' + file.id + " span").append('<button type="button" onclick="updraftplus_downloadstage2(\'db\', \'db\'">Download to your computer</button>');
156
+ // $('#' + file.id + " span").append('<form action="admin-ajax.php" onsubmit="return updraft_downloader(\'+bkey+''\', \'db\')" method="post"><input type="hidden" name="_wpnonce" value="'+updraft_downloader_nonce+'"><input type="hidden" name="action" value="updraft_download_backup" /><input type="hidden" name="type" value="db" /><input type="hidden" name="timestamp" value="'+bkey+'" /><input type="submit" value="Download" /></form>');
157
+ $('#' + file.id + " .fileprogress").hide();
158
+ $('#' + file.id).append('The file was uploaded. <a href="?page=updraftplus&action=downloadfile&updraftplus_file='+bkey+'&decrypt_key='+$('#updraftplus_db_decrypt').val()+'">Follow this link to attempt decryption and download the database file to your computer.</a> This decryption key will be attempted: '+$('#updraftplus_db_decrypt').val().replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"));
159
+ } else {
160
+ alert('Unknown server response: '+response.response);
161
+ }
162
+ } else {
163
+ alert('Unknown server response status: '+response.code);
164
+ }
165
+
166
+ });
167
+
168
+ });
includes/updraft-restorer.php CHANGED
@@ -1,11 +1,78 @@
1
  <?php
2
  class Updraft_Restorer extends WP_Upgrader {
3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  function backup_strings() {
5
  $this->strings['no_package'] = __('Backup file not available.','updraftplus');
6
  $this->strings['unpack_package'] = __('Unpacking backup...','updraftplus');
 
 
7
  $this->strings['moving_old'] = __('Moving old directory out of the way...','updraftplus');
8
  $this->strings['moving_backup'] = __('Moving unpacked backup in place...','updraftplus');
 
9
  $this->strings['cleaning_up'] = __('Cleaning up rubbish...','updraftplus');
10
  $this->strings['old_move_failed'] = __('Could not move old directory out of the way. Perhaps you already have -old directories that need deleting first?','updraftplus');
11
  $this->strings['new_move_failed'] = __('Could not move new directory into place. Check your wp-content/upgrade folder.','updraftplus');
@@ -25,9 +92,10 @@ class Updraft_Restorer extends WP_Upgrader {
25
 
26
  $wp_dir = trailingslashit($wp_filesystem->abspath());
27
 
28
- $download = $this->download_package( $backup_file );
29
- if ( is_wp_error($download) )
30
- return $download;
 
31
 
32
  $delete = (UpdraftPlus_Options::get_updraft_option('updraft_delete_local')) ? true : false;
33
  if ('none' == $service) {
@@ -37,7 +105,9 @@ class Updraft_Restorer extends WP_Upgrader {
37
 
38
  $working_dir = $this->unpack_package($download, $delete);
39
  if (is_wp_error($working_dir)) return $working_dir;
40
-
 
 
41
  if ($type == 'others' ) {
42
 
43
  // In this special case, the backup contents are not in a folder, so it is not simply a case of moving the folder around, but rather looping over all that we find
@@ -72,7 +142,105 @@ class Updraft_Restorer extends WP_Upgrader {
72
  }
73
  }
74
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  } else {
77
 
78
  show_message($this->strings['moving_old']);
@@ -87,8 +255,9 @@ class Updraft_Restorer extends WP_Upgrader {
87
 
88
  }
89
 
 
90
  show_message($this->strings['cleaning_up']);
91
- if ( !$wp_filesystem->delete($working_dir) ) {
92
  return new WP_Error('delete_failed', $this->strings['delete_failed']);
93
  }
94
 
@@ -96,10 +265,21 @@ class Updraft_Restorer extends WP_Upgrader {
96
  case 'uploads':
97
  @$wp_filesystem->chmod($wp_dir . "wp-content/$dirname", 0775, true);
98
  break;
 
 
99
  default:
100
  @$wp_filesystem->chmod($wp_dir . "wp-content/$dirname", FS_CHMOD_DIR);
101
  }
102
  }
103
 
 
 
 
 
 
 
 
 
 
104
  }
105
  ?>
1
  <?php
2
  class Updraft_Restorer extends WP_Upgrader {
3
 
4
+ function unpack_package($package, $delete_package = true) {
5
+
6
+ // If not database, then it is a zip - unpack in the usual way
7
+ if (!preg_match('/db\.gz(\.crypt)?$/i', $package)) return parent::unpack_package($package, $delete_package);
8
+
9
+ // Unpack a database. The general shape of the following is copied from class-wp-upgrader.php
10
+
11
+ @set_time_limit(1800);
12
+
13
+ global $wp_filesystem;
14
+
15
+ $this->skin->feedback('unpack_package');
16
+
17
+ $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
18
+
19
+ //Clean up contents of upgrade directory beforehand.
20
+ $upgrade_files = $wp_filesystem->dirlist($upgrade_folder);
21
+ if ( !empty($upgrade_files) ) {
22
+ foreach ( $upgrade_files as $file )
23
+ $wp_filesystem->delete($upgrade_folder . $file['name'], true);
24
+ }
25
+
26
+ //We need a working directory
27
+ $working_dir = $upgrade_folder . basename($package, '.crypt');
28
+
29
+ // Clean up working directory
30
+ if ( $wp_filesystem->is_dir($working_dir) )
31
+ $wp_filesystem->delete($working_dir, true);
32
+
33
+ if (!$wp_filesystem->mkdir($working_dir, 0775)) return new WP_Error('mkdir_failed', __('Failed to create a temporary directory','updraftplus'));
34
+
35
+ // Unpack package to working directory
36
+ if (preg_match('/\.crypt$/i', $package)) {
37
+ $this->skin->feedback('decrypt_database');
38
+ $encryption = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
39
+ if (!$encryption) return new WP_Error('no_encryption_key', __('Decryption failed. The database file is encrypted, but you have no encryption key entered.', 'updraftplus'));
40
+
41
+ // Encrypted - decrypt it
42
+ require_once(UPDRAFTPLUS_DIR.'/includes/phpseclib/Crypt/Rijndael.php');
43
+ $rijndael = new Crypt_Rijndael();
44
+
45
+ // Get decryption key
46
+ $rijndael->setKey($encryption);
47
+ $ciphertext = $rijndael->decrypt($wp_filesystem->get_contents($package));
48
+ if ($ciphertext) {
49
+ $this->skin->feedback('decrypted_database');
50
+ if (!$wp_filesystem->put_contents($working_dir.'/backup.db.gz', $ciphertext)) {
51
+ return new WP_Error('write_failed', __('Failed to write out the decrypted database to the filesystem','updraftplus'));
52
+ }
53
+ } else {
54
+ return new WP_Error('decryption_failed', __('Decryption failed. The most likely cause is that you used the wrong key.','updraftplus'));
55
+ }
56
+ } else {
57
+ $wp_filesystem->copy($package, $working_dir.'/backup.db.gz');
58
+ }
59
+
60
+ // Once extracted, delete the package if required.
61
+ if ( $delete_package )
62
+ unlink($package);
63
+
64
+ return $working_dir;
65
+
66
+ }
67
+
68
  function backup_strings() {
69
  $this->strings['no_package'] = __('Backup file not available.','updraftplus');
70
  $this->strings['unpack_package'] = __('Unpacking backup...','updraftplus');
71
+ $this->strings['decrypt_database'] = __('Decrypting database (can take a while)...','updraftplus');
72
+ $this->strings['decrypted_database'] = __('Database successfully decrypted.','updraftplus');
73
  $this->strings['moving_old'] = __('Moving old directory out of the way...','updraftplus');
74
  $this->strings['moving_backup'] = __('Moving unpacked backup in place...','updraftplus');
75
+ $this->strings['restore_database'] = __('Restoring the database (on a large site this can take a long time - if it times out (which can happen if your web hosting company has configured your hosting to limit resources) then you should use a different method, such as phpMyAdmin)...','updraftplus');
76
  $this->strings['cleaning_up'] = __('Cleaning up rubbish...','updraftplus');
77
  $this->strings['old_move_failed'] = __('Could not move old directory out of the way. Perhaps you already have -old directories that need deleting first?','updraftplus');
78
  $this->strings['new_move_failed'] = __('Could not move new directory into place. Check your wp-content/upgrade folder.','updraftplus');
92
 
93
  $wp_dir = trailingslashit($wp_filesystem->abspath());
94
 
95
+ @set_time_limit(1800);
96
+
97
+ $download = $this->download_package($backup_file);
98
+ if ( is_wp_error($download) ) return $download;
99
 
100
  $delete = (UpdraftPlus_Options::get_updraft_option('updraft_delete_local')) ? true : false;
101
  if ('none' == $service) {
105
 
106
  $working_dir = $this->unpack_package($download, $delete);
107
  if (is_wp_error($working_dir)) return $working_dir;
108
+
109
+ @set_time_limit(1800);
110
+
111
  if ($type == 'others' ) {
112
 
113
  // In this special case, the backup contents are not in a folder, so it is not simply a case of moving the folder around, but rather looping over all that we find
142
  }
143
  }
144
  }
145
+ } elseif ('db' == $type) {
146
+
147
+ // There is a file backup.db.gz inside the working directory
148
+
149
+ # The 'off' check is for badly configured setups - http://wordpress.org/support/topic/plugin-wp-super-cache-warning-php-safe-mode-enabled-but-safe-mode-is-off
150
+ if(@ini_get('safe_mode') && strtolower(@ini_get('safe_mode')) != "off") {
151
+ echo "<p>".__('Warning: PHP safe_mode is active on your server. Timeouts are much more likely. If these happen, then you will need to manually restore the file via phpMyAdmin or another method.', 'updraftplus')."</p><br/>";
152
+ return false;
153
+ }
154
+
155
+
156
+ global $wpdb;
157
+
158
+ if (!is_readable($working_dir.'/backup.db.gz')) return new WP_Error('gzopen_failed',__('Failed to find database file','updraftplus'));
159
+
160
+ $this->skin->feedback('restore_database');
161
+
162
+ // Read-only access: don't need to go through WP_Filesystem
163
+ $dbhandle = gzopen($working_dir.'/backup.db.gz', 'r');
164
+ if (!$dbhandle) return new WP_Error('gzopen_failed',__('Failed to open database file','updraftplus'));
165
+
166
+ $line = 0;
167
+
168
+ // Line up a wpdb-like object to use
169
+ // mysql_query will throw E_DEPRECATED from PHP 5.5, so we expect WordPress to have switched to something else by then
170
+ $use_wpdb = (version_compare(phpversion(), '5.5', '>=') || !function_exists('mysql_query') || !$wpdb->is_mysql || !$wpdb->ready) ? true : false;
171
+
172
+ if (false == $use_wpdb) {
173
+ // We have our own extension which drops lots of the overhead on the query
174
+ $wpdb_obj = new UpdraftPlus_WPDB( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
175
+ // Was that successful?
176
+ if (!$wpdb_obj->is_mysql || !$wpdb_obj->ready) {
177
+ $use_wpdb = true;
178
+ } else {
179
+ $mysql_dbh = $wpdb_obj->updraftplus_getdbh();
180
+ }
181
+ }
182
+
183
+ if (true == $use_wpdb) {
184
+ _e('Database access: Direct MySQL access is not available, so we are falling back to wpdb (this will be considerably slower)','updraftplus');
185
+ } else {
186
+ @mysql_query( 'SET SESSION query_cache_type = OFF;', $mysql_dbh );
187
+ }
188
+
189
+ $errors = 0;
190
+
191
+ $sql_line = "";
192
+
193
+ $start_time = microtime(true);
194
+
195
+ while (!gzeof($dbhandle)) {
196
+ // Up to 1Mb
197
+ $buffer = rtrim(gzgets($dbhandle, 1048576));
198
+ // Discard comments
199
+ if (substr($buffer, 0, 1) == '#' || empty($buffer)) continue;
200
+
201
+ $sql_line .= $buffer;
202
+
203
+ # Do we have a complete line yet?
204
+ if (';' != substr($sql_line, -1, 1)) continue;
205
+
206
+ $line++;
207
 
208
+ # The timed overhead of this is negligible
209
+ if (preg_match('/^\s*create table \`?([^\`]*)`?\s+\(/i', $sql_line, $matches)) {
210
+ echo __('Restoring table','updraftplus').": ".htmlspecialchars($matches[1])."<br>";
211
+ }
212
+
213
+ if ($use_wpdb) {
214
+ $req = $wpdb->query($sql_line);
215
+ if (!$req) $last_error = $wpdb->last_error;
216
+ } else {
217
+ $req = mysql_unbuffered_query( $sql_line, $mysql_dbh );
218
+ if (!$req) $last_error = mysql_error($mysql_dbh);
219
+ }
220
+
221
+ if (!$req) {
222
+ echo sprintf(_x('An error (%s) occured:', 'The user is being told the number of times an error has happened, e.g. An error (27) occurred', 'updraftplus'), $errors).' '.$wpdb_obj->last_error.' - '.__('the database query being run was: ','updraftplus').' '.htmlspecialchars($sql_line).'<br>';
223
+ $errors++;
224
+ if ($errors>49) {
225
+ return new WP_Error('too_many_db_errors', __('Too many database errors have occurred - aborting restoration (you will need to restore manually)','updraftplus'));
226
+ }
227
+ }
228
+
229
+ if ($line%50 == 0) {
230
+ if ($line%250 == 0 || $line<250) {
231
+ $time_taken = microtime(true) - $start_time;
232
+ echo sprintf(__('Database lines processed: %d in %.2f seconds','updraftplus'),$line, $time_taken)."<br>";
233
+ }
234
+ }
235
+
236
+ # Reset
237
+ $sql_line = '';
238
+
239
+ }
240
+ $time_taken = microtime(true) - $start_time;
241
+ echo sprintf(__('Finished: lines processed: %d in %.2f seconds','updraftplus'),$line, $time_taken)."<br>";
242
+ gzclose($dbhandle);
243
+ @unlink($working_dir.'/backup.db.gz');
244
  } else {
245
 
246
  show_message($this->strings['moving_old']);
255
 
256
  }
257
 
258
+ // Non-recursive, so the directory needs to be empty
259
  show_message($this->strings['cleaning_up']);
260
+ if (!$wp_filesystem->delete($working_dir) ) {
261
  return new WP_Error('delete_failed', $this->strings['delete_failed']);
262
  }
263
 
265
  case 'uploads':
266
  @$wp_filesystem->chmod($wp_dir . "wp-content/$dirname", 0775, true);
267
  break;
268
+ case 'db':
269
+ break;
270
  default:
271
  @$wp_filesystem->chmod($wp_dir . "wp-content/$dirname", FS_CHMOD_DIR);
272
  }
273
  }
274
 
275
+ }
276
+
277
+ // Get a protected property
278
+ class UpdraftPlus_WPDB extends wpdb {
279
+
280
+ function updraftplus_getdbh() {
281
+ return $this->dbh;
282
+ }
283
+
284
  }
285
  ?>
languages/updraftplus-de_DE.po CHANGED
@@ -453,8 +453,7 @@ msgid ""
453
  "<em>will</em> be useless.</strong> Presently, only the database file is "
454
  "encrypted. This is also the key used to decrypt backups from this admin "
455
  "interface (so if you change it, then automatic decryption will not work "
456
- "until you change it back). You can also use the file example-decrypt.php "
457
- "from inside the UpdraftPlus plugin directory to decrypt manually."
458
  msgstr ""
459
  "Wenn du einen Text hier eingibst, wird dieser benutzt um die Sicherungen zu "
460
  "verschlüsseln (Rijndael). <strong>Sichere diesen Text an einer sicheren "
@@ -462,9 +461,7 @@ msgstr ""
462
  "<em>nutzlos</em> wenn du den Text vergisst.</strong> Aktuell wird nur die "
463
  "Datenbank-Datei verschlüsselt. Der Text dient außerdem zur Entschlüsselung "
464
  "der Sicherungen aus dieser Oberfläche (daher funktioniert Entschlüsselung "
465
- "älterer Sicherungen nicht, wenn du diesen änderst). Außerdem kannst du das "
466
- "Beispiel example-decrypt.php aus dem UpdraftPlus Plugin-Verzeichnis "
467
- "verwenden, um manuell zu entschlüsseln."
468
 
469
  #: updraftplus.php:2403
470
  msgid "Copying Your Backup To Remote Storage"
@@ -1837,7 +1834,7 @@ msgid "SFTP user setting"
1837
  msgstr "SFTP-Benutzereinstellungen"
1838
 
1839
  #: addons/sftp.php:32
1840
- msgid "SFTP passwrd"
1841
  msgstr "SFTP-Passwort"
1842
 
1843
  #: addons/sftp.php:50 addons/sftp.php:293
453
  "<em>will</em> be useless.</strong> Presently, only the database file is "
454
  "encrypted. This is also the key used to decrypt backups from this admin "
455
  "interface (so if you change it, then automatic decryption will not work "
456
+ "until you change it back)."
 
457
  msgstr ""
458
  "Wenn du einen Text hier eingibst, wird dieser benutzt um die Sicherungen zu "
459
  "verschlüsseln (Rijndael). <strong>Sichere diesen Text an einer sicheren "
461
  "<em>nutzlos</em> wenn du den Text vergisst.</strong> Aktuell wird nur die "
462
  "Datenbank-Datei verschlüsselt. Der Text dient außerdem zur Entschlüsselung "
463
  "der Sicherungen aus dieser Oberfläche (daher funktioniert Entschlüsselung "
464
+ "älterer Sicherungen nicht, wenn du diesen änderst)."
 
 
465
 
466
  #: updraftplus.php:2403
467
  msgid "Copying Your Backup To Remote Storage"
1834
  msgstr "SFTP-Benutzereinstellungen"
1835
 
1836
  #: addons/sftp.php:32
1837
+ msgid "SFTP password"
1838
  msgstr "SFTP-Passwort"
1839
 
1840
  #: addons/sftp.php:50 addons/sftp.php:293
languages/updraftplus-hu_HU.po CHANGED
@@ -452,16 +452,14 @@ msgid ""
452
  "<em>will</em> be useless.</strong> Presently, only the database file is "
453
  "encrypted. This is also the key used to decrypt backups from this admin "
454
  "interface (so if you change it, then automatic decryption will not work "
455
- "until you change it back). You can also use the file example-decrypt.php "
456
- "from inside the UpdraftPlus plugin directory to decrypt manually."
457
  msgstr ""
458
  "Ha ide beír karaktereket, titkosítva lesz a mentés (Rijndael). <strong>Kérem "
459
  "külön jegyezze fel ezt, különben az <em>összes</em> mentése hasztalan lesz.</"
460
  "strong> Jelenleg csak az adatbázis mentések kerülnek titkosításra. Ezzel a "
461
  "kulccsal kerül kinyitásra minden mentés erről a felületről (szóval, ha "
462
  "módosítja, akkor a titkosítás automatikus kinyitása nem fog működni, amíg "
463
- "vissza nem változtatja). Kézi kinyitáshoz használhatja az example-decrypt."
464
- "php program fájlt az UpdraftPlus bővítmény könyvtárban."
465
 
466
  #: updraftplus.php:2403
467
  msgid "Copying Your Backup To Remote Storage"
452
  "<em>will</em> be useless.</strong> Presently, only the database file is "
453
  "encrypted. This is also the key used to decrypt backups from this admin "
454
  "interface (so if you change it, then automatic decryption will not work "
455
+ "until you change it back)."
 
456
  msgstr ""
457
  "Ha ide beír karaktereket, titkosítva lesz a mentés (Rijndael). <strong>Kérem "
458
  "külön jegyezze fel ezt, különben az <em>összes</em> mentése hasztalan lesz.</"
459
  "strong> Jelenleg csak az adatbázis mentések kerülnek titkosításra. Ezzel a "
460
  "kulccsal kerül kinyitásra minden mentés erről a felületről (szóval, ha "
461
  "módosítja, akkor a titkosítás automatikus kinyitása nem fog működni, amíg "
462
+ "vissza nem változtatja)."
 
463
 
464
  #: updraftplus.php:2403
465
  msgid "Copying Your Backup To Remote Storage"
languages/updraftplus.pot CHANGED
@@ -2,15 +2,15 @@ msgid ""
2
  msgstr ""
3
  "Project-Id-Version: UpdraftPlus\n"
4
  "Report-Msgid-Bugs-To: \n"
5
- "POT-Creation-Date: 2013-03-30 17:26+0100\n"
6
- "PO-Revision-Date: 2013-03-30 17:26+0100\n"
7
  "Last-Translator: David Anderson <contact@updraftplus.com>\n"
8
  "Language-Team: <contact@updraftplus.com>\n"
9
  "Language: \n"
10
  "MIME-Version: 1.0\n"
11
  "Content-Type: text/plain; charset=UTF-8\n"
12
  "Content-Transfer-Encoding: 8bit\n"
13
- "X-Poedit-KeywordsList: _;gettext;gettext_noop;__;_x;_e\n"
14
  "X-Poedit-Basepath: /home/david/MissionaryHosting/UpdraftPlus/svn/trunk\n"
15
  "X-Poedit-SearchPath-0: .\n"
16
 
@@ -22,856 +22,903 @@ msgstr ""
22
  msgid "Bad filename format - this does not look like a file created by UpdraftPlus"
23
  msgstr ""
24
 
25
- #: updraftplus.php:295
 
 
 
 
 
26
  msgid "Allowed Files"
27
  msgstr ""
28
 
29
- #: updraftplus.php:372
30
  msgid "Settings"
31
  msgstr ""
32
 
33
- #: updraftplus.php:376
34
  msgid "Add-Ons / Pro Support"
35
  msgstr ""
36
 
37
- #: updraftplus.php:462
38
  msgid "Plugins"
39
  msgstr ""
40
 
41
- #: updraftplus.php:463
42
  msgid "Themes"
43
  msgstr ""
44
 
45
- #: updraftplus.php:464
46
  msgid "Uploads"
47
  msgstr ""
48
 
49
- #: updraftplus.php:478
50
  msgid "Others"
51
  msgstr ""
52
 
53
- #: updraftplus.php:710
54
  msgid "Could not create files in the backup directory. Backup aborted - check your UpdraftPlus settings."
55
  msgstr ""
56
 
57
- #: updraftplus.php:778
58
  msgid "Encryption error occurred when encrypting database. Encryption aborted."
59
  msgstr ""
60
 
61
- #: updraftplus.php:812
62
  msgid "The backup apparently succeeded and is now complete"
63
  msgstr ""
64
 
65
- #: updraftplus.php:815
66
  msgid "The backup attempt has finished, apparently unsuccessfully"
67
  msgstr ""
68
 
69
- #: updraftplus.php:818
70
  msgid "The backup has not finished; a resumption is scheduled within 5 minutes"
71
  msgstr ""
72
 
73
- #: updraftplus.php:869
74
  msgid "Backed up"
75
  msgstr ""
76
 
77
- #: updraftplus.php:869
78
  msgid "WordPress backup is complete"
79
  msgstr ""
80
 
81
- #: updraftplus.php:869
82
  msgid "Backup contains"
83
  msgstr ""
84
 
85
- #: updraftplus.php:869
86
  msgid "Latest status"
87
  msgstr ""
88
 
89
- #: updraftplus.php:1124
90
  #, php-format
91
  msgid "Could not create %s zip. Consult the log file for more information."
92
  msgstr ""
93
 
94
- #: updraftplus.php:1158
95
  #, php-format
96
  msgid "Backup directory (%s) is not writable, or does not exist."
97
  msgstr ""
98
 
99
- #: updraftplus.php:1248
100
  msgid "Could not read the content directory"
101
  msgstr ""
102
 
103
- #: updraftplus.php:1278
104
  msgid "Could not save backup history because we have no backup array. Backup probably failed."
105
  msgstr ""
106
 
107
- #: updraftplus.php:1307
108
  msgid "Could not open the backup file for writing"
109
  msgstr ""
110
 
111
- #: updraftplus.php:1316
112
  #, php-format
113
  msgid "Generated: %s"
114
  msgstr ""
115
 
116
- #: updraftplus.php:1317
117
  #, php-format
118
  msgid "Hostname: %s"
119
  msgstr ""
120
 
121
- #: updraftplus.php:1318
122
  #, php-format
123
  msgid "Database: %s"
124
  msgstr ""
125
 
126
- #: updraftplus.php:1362
127
  msgid "The backup directory is not writable."
128
  msgstr ""
129
 
130
- #: updraftplus.php:1383
131
  #, php-format
132
  msgid "Table: %s"
133
  msgstr ""
134
 
135
- #: updraftplus.php:1388
136
  #, php-format
137
  msgid "Skipping non-WP table: %s"
138
  msgstr ""
139
 
140
- #: updraftplus.php:1479
141
  #, php-format
142
  msgid "Delete any existing table %s"
143
  msgstr ""
144
 
145
- #: updraftplus.php:1488
146
  #, php-format
147
  msgid "Table structure of table %s"
148
  msgstr ""
149
 
150
- #: updraftplus.php:1494
151
  #, php-format
152
  msgid "Error with SHOW CREATE TABLE for %s."
153
  msgstr ""
154
 
155
- #: updraftplus.php:1501
156
  #, php-format
157
  msgid "Error getting table structure of %s"
158
  msgstr ""
159
 
160
- #: updraftplus.php:1507
161
  #, php-format
162
  msgid "Data contents of table %s"
163
  msgstr ""
164
 
165
- #: updraftplus.php:1563
166
  #, php-format
167
  msgid "End of data contents of table %s"
168
  msgstr ""
169
 
170
- #: updraftplus.php:1815
171
  msgid "Nothing yet logged"
172
  msgstr ""
173
 
174
- #: updraftplus.php:1836
175
  msgid "File downloading"
176
  msgstr ""
177
 
178
- #: updraftplus.php:1838
179
  msgid "No local copy present."
180
  msgstr ""
181
 
182
- #: updraftplus.php:2014
 
 
 
 
 
 
 
 
 
 
 
 
183
  msgid "File not found"
184
  msgstr ""
185
 
186
- #: updraftplus.php:2033
187
  #, php-format
188
  msgid "The backup archive for restoring this file could not be found. The remote storage method in use (%s) does not allow us to retrieve files. To proceed with this restoration, you need to obtain a copy of this file and place it inside UpdraftPlus's working folder"
189
  msgstr ""
190
 
191
- #: updraftplus.php:2043
192
  msgid "This backup does not exist in the backup history - restoration aborted. Timestamp:"
193
  msgstr ""
194
 
195
- #: updraftplus.php:2056
196
  msgid "UpdraftPlus Restoration: Progress"
197
  msgstr ""
198
 
199
- #: updraftplus.php:2063
200
  msgid "ABORT: Could not find the information on which entities to restore."
201
  msgstr ""
202
 
203
- #: updraftplus.php:2077
204
- #: updraftplus.php:2820
205
- #: updraftplus.php:3072
206
  msgid "Database"
207
  msgstr ""
208
 
209
- #: updraftplus.php:2083
210
  msgid "This component was not selected for restoration - skipping."
211
  msgstr ""
212
 
213
- #: updraftplus.php:2091
214
  msgid "File is not locally present - needs retrieving from remote storage (for large files, it is better to do this in advance from the download console)"
215
  msgstr ""
216
 
217
- #: updraftplus.php:2097
218
  msgid "Archive is expected to be size:"
219
  msgstr ""
220
 
221
- #: updraftplus.php:2102
222
  msgid "ERROR"
223
  msgstr ""
224
 
225
- #: updraftplus.php:2105
226
  msgid "The backup records do not contain information about the proper size of this file."
227
  msgstr ""
228
 
229
- #: updraftplus.php:2117
230
  msgid "Error message"
231
  msgstr ""
232
 
233
- #: updraftplus.php:2123
234
- #: updraftplus.php:2124
235
  msgid "Could not find one of the files for restoration"
236
  msgstr ""
237
 
238
- #: updraftplus.php:2126
239
  msgid "Databases are not yet restored through this mechanism - use your web host's control panel, phpMyAdmin or a similar tool"
240
  msgstr ""
241
 
242
- #: updraftplus.php:2132
243
  msgid "Database could not be restored because PHP safe_mode is active on your server. You will need to manually restore the file via phpMyAdmin or another method."
244
  msgstr ""
245
 
246
- #: updraftplus.php:2156
247
  msgid "Delete"
248
  msgstr ""
249
 
250
- #: updraftplus.php:2290
 
 
 
 
251
  msgid "Find UpdraftPlus useful?"
252
  msgstr ""
253
 
254
- #: updraftplus.php:2290
255
  msgid "Please make a donation"
256
  msgstr ""
257
 
258
- #: updraftplus.php:2295
259
  msgid "Like UpdraftPlus and can spare one minute?"
260
  msgstr ""
261
 
262
- #: updraftplus.php:2295
263
  msgid "Please help UpdraftPlus by giving a positive review at wordpress.org"
264
  msgstr ""
265
 
266
- #: updraftplus.php:2302
267
  msgid "Need even more features and support? Check out UpdraftPlus Premium"
268
  msgstr ""
269
 
270
- #: updraftplus.php:2311
271
  msgid "Check out UpdraftPlus.Com for help, add-ons and support"
272
  msgstr ""
273
 
274
- #: updraftplus.php:2314
275
  msgid "Want to say thank-you for UpdraftPlus?"
276
  msgstr ""
277
 
278
- #: updraftplus.php:2314
279
  msgid "Please buy our very cheap 'no adverts' add-on."
280
  msgstr ""
281
 
282
- #: updraftplus.php:2325
283
  msgid "File backup intervals"
284
  msgstr ""
285
 
286
- #: updraftplus.php:2328
287
  msgid "Manual"
288
  msgstr ""
289
 
290
- #: updraftplus.php:2328
291
  msgid "Every 4 hours"
292
  msgstr ""
293
 
294
- #: updraftplus.php:2328
295
  msgid "Every 8 hours"
296
  msgstr ""
297
 
298
- #: updraftplus.php:2328
299
  msgid "Every 12 hours"
300
  msgstr ""
301
 
302
- #: updraftplus.php:2328
303
  msgid "Daily"
304
  msgstr ""
305
 
306
- #: updraftplus.php:2328
307
  msgid "Weekly"
308
  msgstr ""
309
 
310
- #: updraftplus.php:2328
311
  msgid "Fortnightly"
312
  msgstr ""
313
 
314
- #: updraftplus.php:2328
315
  msgid "Monthly"
316
  msgstr ""
317
 
318
- #: updraftplus.php:2337
319
- #: updraftplus.php:2355
320
  msgid "and retain this many backups"
321
  msgstr ""
322
 
323
- #: updraftplus.php:2344
324
  msgid "Database backup intervals"
325
  msgstr ""
326
 
327
- #: updraftplus.php:2362
328
  msgid "If you would like to automatically schedule backups, choose schedules from the dropdowns above. Backups will occur at the intervals specified. If the two schedules are the same, then the two backups will take place together. If you choose \"manual\" then you must click the \"Backup Now\" button whenever you wish a backup to occur."
329
  msgstr ""
330
 
331
- #: updraftplus.php:2363
332
  msgid "To fix the time at which a backup should take place,"
333
  msgstr ""
334
 
335
- #: updraftplus.php:2363
336
  msgid "e.g. if your server is busy at day and you want to run overnight"
337
  msgstr ""
338
 
339
- #: updraftplus.php:2363
340
  msgid "use the \"Fix Time\" add-on"
341
  msgstr ""
342
 
343
- #: updraftplus.php:2377
344
  msgid "Any other directories found inside wp-content but exclude these directories:"
345
  msgstr ""
346
 
347
- #: updraftplus.php:2383
348
  msgid "Include all of these, unless you are backing them up outside of UpdraftPlus. The above directories are usually everything (except for WordPress core itself which you can download afresh from WordPress.org). But if you have made customised modifications outside of these directories, you need to back them up another way."
349
  msgstr ""
350
 
351
- #: updraftplus.php:2383
352
  msgid "Use WordShell for automatic backup, version control and patching"
353
  msgstr ""
354
 
355
- #: updraftplus.php:2387
356
  msgid "Email"
357
  msgstr ""
358
 
359
- #: updraftplus.php:2388
360
  msgid "Enter an address here to have a report sent (and the whole backup, if you choose) to it."
361
  msgstr ""
362
 
363
- #: updraftplus.php:2392
364
  msgid "Database encryption phrase"
365
  msgstr ""
366
 
367
- #: updraftplus.php:2399
368
- msgid "If you enter text here, it is used to encrypt backups (Rijndael). <strong>Do make a separate record of it and do not lose it, or all your backups <em>will</em> be useless.</strong> Presently, only the database file is encrypted. This is also the key used to decrypt backups from this admin interface (so if you change it, then automatic decryption will not work until you change it back). You can also use the file example-decrypt.php from inside the UpdraftPlus plugin directory to decrypt manually."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
369
  msgstr ""
370
 
371
- #: updraftplus.php:2403
 
 
 
 
372
  msgid "Copying Your Backup To Remote Storage"
373
  msgstr ""
374
 
375
- #: updraftplus.php:2407
376
  msgid "Choose your remote storage"
377
  msgstr ""
378
 
379
- #: updraftplus.php:2419
380
  msgid "None"
381
  msgstr ""
382
 
383
- #: updraftplus.php:2500
384
- #: updraftplus.php:2838
385
- #: updraftplus.php:3109
386
  msgid "Restore"
387
  msgstr ""
388
 
389
- #: updraftplus.php:2514
390
- #: updraftplus.php:2524
391
  msgid "Cancel"
392
  msgstr ""
393
 
394
- #: updraftplus.php:2521
395
- #: updraftplus.php:2830
396
  msgid "Backup Now"
397
  msgstr ""
398
 
399
- #: updraftplus.php:2548
400
  msgid "Advanced / Debugging Settings"
401
  msgstr ""
402
 
403
- #: updraftplus.php:2551
404
  msgid "Debug mode"
405
  msgstr ""
406
 
407
- #: updraftplus.php:2552
408
  msgid "Check this to receive more information and emails on the backup process - useful if something is going wrong. You <strong>must</strong> send us this log if you are filing a bug report."
409
  msgstr ""
410
 
411
- #: updraftplus.php:2555
412
  msgid "Expert settings"
413
  msgstr ""
414
 
415
- #: updraftplus.php:2556
416
  msgid "Show expert settings"
417
  msgstr ""
418
 
419
- #: updraftplus.php:2556
420
  msgid "click this to show some further options; don't bother with this unless you have a problem or are curious."
421
  msgstr ""
422
 
423
- #: updraftplus.php:2563
424
  msgid "Delete local backup"
425
  msgstr ""
426
 
427
- #: updraftplus.php:2564
428
  msgid "Uncheck this to prevent deletion of any superfluous backup files from your server after the backup run finishes (i.e. any files despatched remotely will also remain locally, and any files being kept locally will not be subject to the retention limits)."
429
  msgstr ""
430
 
431
- #: updraftplus.php:2568
432
  msgid "Backup directory"
433
  msgstr ""
434
 
435
- #: updraftplus.php:2576
436
  msgid "Backup directory specified is writable, which is good."
437
  msgstr ""
438
 
439
- #: updraftplus.php:2578
440
  msgid "Backup directory specified is <b>not</b> writable, or does not exist."
441
  msgstr ""
442
 
443
- #: updraftplus.php:2578
444
  msgid "Click here to attempt to create the directory and set the permissions"
445
  msgstr ""
446
 
447
- #: updraftplus.php:2578
448
  msgid "or, to reset this option"
449
  msgstr ""
450
 
451
- #: updraftplus.php:2578
452
  msgid "click here"
453
  msgstr ""
454
 
455
- #: updraftplus.php:2578
456
  msgid "If that is unsuccessful check the permissions on your server or change it to another directory that is writable by your web server process."
457
  msgstr ""
458
 
459
- #: updraftplus.php:2581
460
  msgid "This is where UpdraftPlus will write the zip files it creates initially. This directory must be writable by your web server. Typically you'll want to have it inside your wp-content folder (this is the default). <b>Do not</b> place it inside your uploads dir, as that will cause recursion issues (backups of backups of backups of...)."
461
  msgstr ""
462
 
463
- #: updraftplus.php:2602
464
  msgid "Save Changes"
465
  msgstr ""
466
 
467
- #: updraftplus.php:2626
468
  msgid "Download log file"
469
  msgstr ""
470
 
471
- #: updraftplus.php:2632
472
  msgid "No backup has been completed."
473
  msgstr ""
474
 
475
- #: updraftplus.php:2652
476
  msgid "Restore successful!"
477
  msgstr ""
478
 
479
- #: updraftplus.php:2653
480
- #: updraftplus.php:2688
481
- #: updraftplus.php:2704
482
  msgid "Actions"
483
  msgstr ""
484
 
485
- #: updraftplus.php:2653
486
- #: updraftplus.php:2668
487
- #: updraftplus.php:2688
488
- #: updraftplus.php:2704
489
  msgid "Return to UpdraftPlus Configuration"
490
  msgstr ""
491
 
492
- #: updraftplus.php:2677
493
  msgid "Remove old directories"
494
  msgstr ""
495
 
496
- #: updraftplus.php:2683
497
  msgid "Old directories successfully removed."
498
  msgstr ""
499
 
500
- #: updraftplus.php:2686
501
  msgid "Old directory removal failed for some reason. You may want to do this manually."
502
  msgstr ""
503
 
504
- #: updraftplus.php:2701
505
  msgid "Backup directory could not be created"
506
  msgstr ""
507
 
508
- #: updraftplus.php:2703
509
  msgid "Backup directory successfully created."
510
  msgstr ""
511
 
512
- #: updraftplus.php:2710
513
  msgid "Schedule backup"
514
  msgstr ""
515
 
516
- #: updraftplus.php:2713
517
  msgid "Failed."
518
  msgstr ""
519
 
520
- #: updraftplus.php:2715
521
  msgid "OK. Now load any page from your site to make sure the schedule can trigger. You should then see activity in the \"Last log message\" field below."
522
  msgstr ""
523
 
524
- #: updraftplus.php:2715
525
  msgid "Nothing happening? Follow this link for help."
526
  msgstr ""
527
 
528
- #: updraftplus.php:2728
529
  msgid "Your settings have been wiped."
530
  msgstr ""
531
 
532
- #: updraftplus.php:2735
533
  msgid "By UpdraftPlus.Com"
534
  msgstr ""
535
 
536
- #: updraftplus.php:2735
537
  msgid "Lead developer's homepage"
538
  msgstr ""
539
 
540
- #: updraftplus.php:2735
541
  msgid "Donate"
542
  msgstr ""
543
 
544
- #: updraftplus.php:2735
545
  msgid "Other WordPress plugins"
546
  msgstr ""
547
 
548
- #: updraftplus.php:2735
549
  msgid "Version"
550
  msgstr ""
551
 
552
- #: updraftplus.php:2739
553
  msgid "Your backup has been restored."
554
  msgstr ""
555
 
556
- #: updraftplus.php:2739
557
  msgid "Your old (themes, uploads, plugins, whatever) directories have been retained with \"-old\" appended to their name. Remove them when you are satisfied that the backup worked properly."
558
  msgstr ""
559
 
560
- #: updraftplus.php:2739
561
  msgid "At this time UpdraftPlus does not automatically restore your database. You will need to use an external tool like phpMyAdmin to perform that task."
562
  msgstr ""
563
 
564
- #: updraftplus.php:2745
565
  msgid "Old directories successfully deleted."
566
  msgstr ""
567
 
568
- #: updraftplus.php:2748
569
- msgid "Your PHP memory limit is quite low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may not work properly with a memory limit of less than 96 Mb (though on the other hand, it has been used successfully with a 32Mb limit - your mileage may vary, but don't blame us!)."
570
  msgstr ""
571
 
572
- #: updraftplus.php:2748
573
  msgid "Current limit is:"
574
  msgstr ""
575
 
576
- #: updraftplus.php:2752
577
  msgid "Your PHP max_execution_time is less than 60 seconds. This possibly means you're running in safe_mode. Either disable safe_mode or modify your php.ini to set max_execution_time to a higher number. If you do not, then longer will be needed to complete a backup (but that is all). Present limit is:"
578
  msgstr ""
579
 
580
- #: updraftplus.php:2752
581
  msgid "seconds"
582
  msgstr ""
583
 
584
- #: updraftplus.php:2757
585
  msgid "You have old directories from a previous backup (technical information: these are found in wp-content, and suffixed with -old). Use this button to delete them (if you have verified that the restoration worked)."
586
  msgstr ""
587
 
588
- #: updraftplus.php:2761
589
  msgid "Delete Old Directories"
590
  msgstr ""
591
 
592
- #: updraftplus.php:2761
593
  msgid "Are you sure you want to delete the old directories? This cannot be undone."
594
  msgstr ""
595
 
596
- #: updraftplus.php:2774
597
  msgid "Existing Schedule And Backups"
598
  msgstr ""
599
 
600
- #: updraftplus.php:2778
601
  msgid "JavaScript warning"
602
  msgstr ""
603
 
604
- #: updraftplus.php:2779
605
  msgid "This admin interface uses JavaScript heavily. You either need to activate it within your browser, or to use a JavaScript-capable browser."
606
  msgstr ""
607
 
608
- #: updraftplus.php:2792
609
- #: updraftplus.php:2805
610
  msgid "Nothing currently scheduled"
611
  msgstr ""
612
 
613
- #: updraftplus.php:2797
614
  msgid "At the same time as the files backup"
615
  msgstr ""
616
 
617
- #: updraftplus.php:2817
618
  msgid "Next scheduled backups"
619
  msgstr ""
620
 
621
- #: updraftplus.php:2819
622
  msgid "Files"
623
  msgstr ""
624
 
625
- #: updraftplus.php:2821
626
  msgid "Time now"
627
  msgstr ""
628
 
629
- #: updraftplus.php:2825
630
  msgid "Last finished backup run"
631
  msgstr ""
632
 
633
- #: updraftplus.php:2845
634
  msgid "Last log message"
635
  msgstr ""
636
 
637
- #: updraftplus.php:2846
638
  msgid "(Nothing yet logged)"
639
  msgstr ""
640
 
641
- #: updraftplus.php:2849
642
  msgid "Backups, logs & restoring"
643
  msgstr ""
644
 
645
- #: updraftplus.php:2850
646
  msgid "Press to see available backups"
647
  msgstr ""
648
 
649
- #: updraftplus.php:2850
650
  #, php-format
651
  msgid "%d set(s) available"
652
  msgstr ""
653
 
654
- #: updraftplus.php:2855
655
  msgid "Downloading"
656
  msgstr ""
657
 
658
- #: updraftplus.php:2855
659
  msgid "Pressing a button for Database/Plugins/Themes/Uploads/Others will make UpdraftPlus try to bring the backup file back from the remote storage (if any - e.g. Amazon S3, Dropbox, Google Drive, FTP) to your webserver. Then you will be allowed to download it to your computer. If the fetch from the remote storage stops progressing (wait 30 seconds to make sure), then press again to resume. Remember that you can also visit the cloud storage vendor's website directly."
660
  msgstr ""
661
 
662
- #: updraftplus.php:2856
663
  msgid "Restoring"
664
  msgstr ""
665
 
666
- #: updraftplus.php:2856
667
  msgid "Press the button for the backup you wish to restore. If your site is large and you are using remote storage, then you should first click on each entity in order to retrieve it back to the webserver. This will prevent time-outs from occuring during the restore process itself."
668
  msgstr ""
669
 
670
- #: updraftplus.php:2856
671
  msgid "More tasks:"
672
  msgstr ""
673
 
674
- #: updraftplus.php:2856
675
  msgid "upload backup files"
676
  msgstr ""
677
 
678
- #: updraftplus.php:2856
679
  msgid "Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below."
680
  msgstr ""
681
 
682
- #: updraftplus.php:2856
683
  msgid "rescan folder for new backup sets"
684
  msgstr ""
685
 
686
- #: updraftplus.php:2857
687
  msgid "Opera web browser"
688
  msgstr ""
689
 
690
- #: updraftplus.php:2857
691
  msgid "If you are using this, then turn Turbo/Road mode off."
692
  msgstr ""
693
 
694
- #: updraftplus.php:2858
695
  msgid "This is a count of the contents of your Updraft directory"
696
  msgstr ""
697
 
698
- #: updraftplus.php:2858
699
  msgid "Web-server disk space in use by UpdraftPlus"
700
  msgstr ""
701
 
702
- #: updraftplus.php:2858
703
  msgid "refresh"
704
  msgstr ""
705
 
706
- #: updraftplus.php:2860
707
  msgid "UpdraftPlus - Upload backup files"
708
  msgstr ""
709
 
710
- #: updraftplus.php:2861
711
  msgid "Upload files into UpdraftPlus. Use this to import backups made on a different WordPress installation."
712
  msgstr ""
713
 
714
- #: updraftplus.php:2865
715
  msgid "Drop backup zips here"
716
  msgstr ""
717
 
718
- #: updraftplus.php:2879
719
  msgid "calculating..."
720
  msgstr ""
721
 
722
- #: updraftplus.php:2948
723
  msgid "Restore backup"
724
  msgstr ""
725
 
726
- #: updraftplus.php:2949
727
  msgid "Restore backup from"
728
  msgstr ""
729
 
730
- #: updraftplus.php:2950
731
  msgid "Restoring will replace this site's themes, plugins, uploads and/or other content directories (according to what is contained in the backup set, and your selection"
732
  msgstr ""
733
 
734
- #: updraftplus.php:2950
735
  msgid "Choose the components to restore"
736
  msgstr ""
737
 
738
- #: updraftplus.php:2961
739
  msgid "Databases cannot yet be restored from here - you must download the database file and take it to your web hosting company's control panel."
740
  msgstr ""
741
 
742
- #: updraftplus.php:2966
743
  msgid "Perform a backup now"
744
  msgstr ""
745
 
746
- #: updraftplus.php:2968
747
  msgid "This will schedule a one-time backup. To proceed, press 'Backup Now', then wait 10 seconds, then visit any page on your site. WordPress should then start the backup running in the background."
748
  msgstr ""
749
 
750
- #: updraftplus.php:2974
751
  msgid "Does nothing happen when you schedule backups?"
752
  msgstr ""
753
 
754
- #: updraftplus.php:2974
755
  msgid "Go here for help."
756
  msgstr ""
757
 
758
- #: updraftplus.php:2981
759
  msgid "Multisite"
760
  msgstr ""
761
 
762
- #: updraftplus.php:2985
763
  msgid "Do you need WordPress Multisite support?"
764
  msgstr ""
765
 
766
- #: updraftplus.php:2985
767
  msgid "Please check out UpdraftPlus Premium, or the stand-alone Multisite add-on."
768
  msgstr ""
769
 
770
- #: updraftplus.php:2990
771
  msgid "Configure Backup Contents And Schedule"
772
  msgstr ""
773
 
774
- #: updraftplus.php:2996
775
  msgid "Debug Information And Expert Options"
776
  msgstr ""
777
 
778
- #: updraftplus.php:3001
779
  msgid "Peak memory usage"
780
  msgstr ""
781
 
782
- #: updraftplus.php:3002
783
  msgid "Current memory usage"
784
  msgstr ""
785
 
786
- #: updraftplus.php:3003
787
  msgid "PHP memory limit"
788
  msgstr ""
789
 
790
- #: updraftplus.php:3006
791
  msgid "The buttons below will immediately execute a backup run, independently of WordPress's scheduler. If these work whilst your scheduled backups and the \"Backup Now\" button do absolutely nothing (i.e. not even produce a log file), then it means that your scheduler is broken. You should then disable all your other plugins, and try the \"Backup Now\" button. If that fails, then contact your web hosting company and ask them if they have disabled wp-cron. If it succeeds, then re-activate your other plugins one-by-one, and find the one that is the problem and report a bug to them."
792
  msgstr ""
793
 
794
- #: updraftplus.php:3010
795
  msgid "Debug Full Backup"
796
  msgstr ""
797
 
798
- #: updraftplus.php:3010
799
  msgid "This will cause an immediate backup. The page will stall loading until it finishes (ie, unscheduled)."
800
  msgstr ""
801
 
802
- #: updraftplus.php:3014
803
  msgid "Debug Database Backup"
804
  msgstr ""
805
 
806
- #: updraftplus.php:3014
807
  msgid "This will cause an immediate DB backup. The page will stall loading until it finishes (ie, unscheduled). The backup may well run out of time; really this button is only helpful for checking that the backup is able to get through the initial stages, or for small WordPress sites.."
808
  msgstr ""
809
 
810
- #: updraftplus.php:3016
811
  msgid "Wipe Settings"
812
  msgstr ""
813
 
814
- #: updraftplus.php:3017
815
  msgid "This button will delete all UpdraftPlus settings (but not any of your existing backups from your cloud storage). You will then need to enter all your settings again. You can also do this before deactivating/deinstalling UpdraftPlus if you wish."
816
  msgstr ""
817
 
818
- #: updraftplus.php:3020
819
  msgid "Wipe All Settings"
820
  msgstr ""
821
 
822
- #: updraftplus.php:3020
823
  msgid "This will delete all your UpdraftPlus settings - are you sure you want to do this?"
824
  msgstr ""
825
 
826
- #: updraftplus.php:3089
827
  msgid "Press here to download"
828
  msgstr ""
829
 
830
- #: updraftplus.php:3091
831
  #, php-format
832
  msgid "(No %s)"
833
  msgstr ""
834
 
835
- #: updraftplus.php:3101
836
  msgid "Backup Log"
837
  msgstr ""
838
 
839
- #: updraftplus.php:3109
840
  msgid "After pressing this button, you will be given the option to choose which components you wish to restore"
841
  msgstr ""
842
 
843
- #: updraftplus.php:3134
844
- #: updraftplus.php:3138
845
  msgid "Warning"
846
  msgstr ""
847
 
848
- #: updraftplus.php:3134
849
  #, php-format
850
  msgid "You have less than %s of free disk space on the disk which UpdraftPlus is configured to use to create backups. UpdraftPlus could well run out of space. Contact your the operator of your server (e.g. your web hosting company) to resolve this issue."
851
  msgstr ""
852
 
853
- #: updraftplus.php:3138
854
  #, php-format
855
  msgid "UpdraftPlus does not officially support versions of WordPress before %s. It may work for you, but if it does not, then please be aware that no support is available until you upgrade WordPress."
856
  msgstr ""
857
 
858
- #: updraftplus.php:3142
859
- #: updraftplus.php:3146
860
- #: updraftplus.php:3150
 
861
  msgid "UpdraftPlus notice:"
862
  msgstr ""
863
 
864
- #: updraftplus.php:3142
865
  msgid "The log file could not be read."
866
  msgstr ""
867
 
868
- #: updraftplus.php:3146
869
- #: updraftplus.php:3150
 
 
 
 
870
  #, php-format
871
  msgid "Click here to authenticate your %s account (you will not be able to back up to %s without it)."
872
  msgstr ""
873
 
874
- #: updraftplus.php:3323
875
  msgid "Infinite recursion: consult your log for more information"
876
  msgstr ""
877
 
@@ -1377,7 +1424,7 @@ msgid "SFTP user setting"
1377
  msgstr ""
1378
 
1379
  #: addons/sftp.php:32
1380
- msgid "SFTP passwrd"
1381
  msgstr ""
1382
 
1383
  #: addons/sftp.php:50
2
  msgstr ""
3
  "Project-Id-Version: UpdraftPlus\n"
4
  "Report-Msgid-Bugs-To: \n"
5
+ "POT-Creation-Date: 2013-04-02 12:11+0100\n"
6
+ "PO-Revision-Date: 2013-04-02 12:12+0100\n"
7
  "Last-Translator: David Anderson <contact@updraftplus.com>\n"
8
  "Language-Team: <contact@updraftplus.com>\n"
9
  "Language: \n"
10
  "MIME-Version: 1.0\n"
11
  "Content-Type: text/plain; charset=UTF-8\n"
12
  "Content-Transfer-Encoding: 8bit\n"
13
+ "X-Poedit-KeywordsList: _;gettext;gettext_noop;_x;__;_e;_ex\n"
14
  "X-Poedit-Basepath: /home/david/MissionaryHosting/UpdraftPlus/svn/trunk\n"
15
  "X-Poedit-SearchPath-0: .\n"
16
 
22
  msgid "Bad filename format - this does not look like a file created by UpdraftPlus"
23
  msgstr ""
24
 
25
+ #: updraftplus.php:335
26
+ msgid "Bad filename format - this does not look like an encrypted database file created by UpdraftPlus"
27
+ msgstr ""
28
+
29
+ #: updraftplus.php:370
30
+ #: updraftplus.php:387
31
  msgid "Allowed Files"
32
  msgstr ""
33
 
34
+ #: updraftplus.php:474
35
  msgid "Settings"
36
  msgstr ""
37
 
38
+ #: updraftplus.php:478
39
  msgid "Add-Ons / Pro Support"
40
  msgstr ""
41
 
42
+ #: updraftplus.php:564
43
  msgid "Plugins"
44
  msgstr ""
45
 
46
+ #: updraftplus.php:565
47
  msgid "Themes"
48
  msgstr ""
49
 
50
+ #: updraftplus.php:566
51
  msgid "Uploads"
52
  msgstr ""
53
 
54
+ #: updraftplus.php:580
55
  msgid "Others"
56
  msgstr ""
57
 
58
+ #: updraftplus.php:812
59
  msgid "Could not create files in the backup directory. Backup aborted - check your UpdraftPlus settings."
60
  msgstr ""
61
 
62
+ #: updraftplus.php:880
63
  msgid "Encryption error occurred when encrypting database. Encryption aborted."
64
  msgstr ""
65
 
66
+ #: updraftplus.php:914
67
  msgid "The backup apparently succeeded and is now complete"
68
  msgstr ""
69
 
70
+ #: updraftplus.php:917
71
  msgid "The backup attempt has finished, apparently unsuccessfully"
72
  msgstr ""
73
 
74
+ #: updraftplus.php:920
75
  msgid "The backup has not finished; a resumption is scheduled within 5 minutes"
76
  msgstr ""
77
 
78
+ #: updraftplus.php:971
79
  msgid "Backed up"
80
  msgstr ""
81
 
82
+ #: updraftplus.php:971
83
  msgid "WordPress backup is complete"
84
  msgstr ""
85
 
86
+ #: updraftplus.php:971
87
  msgid "Backup contains"
88
  msgstr ""
89
 
90
+ #: updraftplus.php:971
91
  msgid "Latest status"
92
  msgstr ""
93
 
94
+ #: updraftplus.php:1226
95
  #, php-format
96
  msgid "Could not create %s zip. Consult the log file for more information."
97
  msgstr ""
98
 
99
+ #: updraftplus.php:1260
100
  #, php-format
101
  msgid "Backup directory (%s) is not writable, or does not exist."
102
  msgstr ""
103
 
104
+ #: updraftplus.php:1350
105
  msgid "Could not read the content directory"
106
  msgstr ""
107
 
108
+ #: updraftplus.php:1380
109
  msgid "Could not save backup history because we have no backup array. Backup probably failed."
110
  msgstr ""
111
 
112
+ #: updraftplus.php:1409
113
  msgid "Could not open the backup file for writing"
114
  msgstr ""
115
 
116
+ #: updraftplus.php:1418
117
  #, php-format
118
  msgid "Generated: %s"
119
  msgstr ""
120
 
121
+ #: updraftplus.php:1419
122
  #, php-format
123
  msgid "Hostname: %s"
124
  msgstr ""
125
 
126
+ #: updraftplus.php:1420
127
  #, php-format
128
  msgid "Database: %s"
129
  msgstr ""
130
 
131
+ #: updraftplus.php:1464
132
  msgid "The backup directory is not writable."
133
  msgstr ""
134
 
135
+ #: updraftplus.php:1485
136
  #, php-format
137
  msgid "Table: %s"
138
  msgstr ""
139
 
140
+ #: updraftplus.php:1490
141
  #, php-format
142
  msgid "Skipping non-WP table: %s"
143
  msgstr ""
144
 
145
+ #: updraftplus.php:1581
146
  #, php-format
147
  msgid "Delete any existing table %s"
148
  msgstr ""
149
 
150
+ #: updraftplus.php:1590
151
  #, php-format
152
  msgid "Table structure of table %s"
153
  msgstr ""
154
 
155
+ #: updraftplus.php:1596
156
  #, php-format
157
  msgid "Error with SHOW CREATE TABLE for %s."
158
  msgstr ""
159
 
160
+ #: updraftplus.php:1603
161
  #, php-format
162
  msgid "Error getting table structure of %s"
163
  msgstr ""
164
 
165
+ #: updraftplus.php:1609
166
  #, php-format
167
  msgid "Data contents of table %s"
168
  msgstr ""
169
 
170
+ #: updraftplus.php:1665
171
  #, php-format
172
  msgid "End of data contents of table %s"
173
  msgstr ""
174
 
175
+ #: updraftplus.php:1917
176
  msgid "Nothing yet logged"
177
  msgstr ""
178
 
179
+ #: updraftplus.php:1938
180
  msgid "File downloading"
181
  msgstr ""
182
 
183
+ #: updraftplus.php:1940
184
  msgid "No local copy present."
185
  msgstr ""
186
 
187
+ #: updraftplus.php:2088
188
+ msgid "Decryption failed. The database file is encrypted, but you have no encryption key entered."
189
+ msgstr ""
190
+
191
+ #: updraftplus.php:2101
192
+ msgid "Decryption failed. The most likely cause is that you used the wrong key."
193
+ msgstr ""
194
+
195
+ #: updraftplus.php:2101
196
+ msgid "The decryption key used:"
197
+ msgstr ""
198
+
199
+ #: updraftplus.php:2116
200
  msgid "File not found"
201
  msgstr ""
202
 
203
+ #: updraftplus.php:2135
204
  #, php-format
205
  msgid "The backup archive for restoring this file could not be found. The remote storage method in use (%s) does not allow us to retrieve files. To proceed with this restoration, you need to obtain a copy of this file and place it inside UpdraftPlus's working folder"
206
  msgstr ""
207
 
208
+ #: updraftplus.php:2145
209
  msgid "This backup does not exist in the backup history - restoration aborted. Timestamp:"
210
  msgstr ""
211
 
212
+ #: updraftplus.php:2158
213
  msgid "UpdraftPlus Restoration: Progress"
214
  msgstr ""
215
 
216
+ #: updraftplus.php:2165
217
  msgid "ABORT: Could not find the information on which entities to restore."
218
  msgstr ""
219
 
220
+ #: updraftplus.php:2179
221
+ #: updraftplus.php:2945
222
+ #: updraftplus.php:3195
223
  msgid "Database"
224
  msgstr ""
225
 
226
+ #: updraftplus.php:2185
227
  msgid "This component was not selected for restoration - skipping."
228
  msgstr ""
229
 
230
+ #: updraftplus.php:2193
231
  msgid "File is not locally present - needs retrieving from remote storage (for large files, it is better to do this in advance from the download console)"
232
  msgstr ""
233
 
234
+ #: updraftplus.php:2199
235
  msgid "Archive is expected to be size:"
236
  msgstr ""
237
 
238
+ #: updraftplus.php:2204
239
  msgid "ERROR"
240
  msgstr ""
241
 
242
+ #: updraftplus.php:2207
243
  msgid "The backup records do not contain information about the proper size of this file."
244
  msgstr ""
245
 
246
+ #: updraftplus.php:2219
247
  msgid "Error message"
248
  msgstr ""
249
 
250
+ #: updraftplus.php:2225
251
+ #: updraftplus.php:2226
252
  msgid "Could not find one of the files for restoration"
253
  msgstr ""
254
 
255
+ #: updraftplus.php:2228
256
  msgid "Databases are not yet restored through this mechanism - use your web host's control panel, phpMyAdmin or a similar tool"
257
  msgstr ""
258
 
259
+ #: updraftplus.php:2234
260
  msgid "Database could not be restored because PHP safe_mode is active on your server. You will need to manually restore the file via phpMyAdmin or another method."
261
  msgstr ""
262
 
263
+ #: updraftplus.php:2258
264
  msgid "Delete"
265
  msgstr ""
266
 
267
+ #: updraftplus.php:2393
268
+ msgid "Can you translate? Want to improve UpdraftPlus for speakers of your language?"
269
+ msgstr ""
270
+
271
+ #: updraftplus.php:2395
272
  msgid "Find UpdraftPlus useful?"
273
  msgstr ""
274
 
275
+ #: updraftplus.php:2395
276
  msgid "Please make a donation"
277
  msgstr ""
278
 
279
+ #: updraftplus.php:2400
280
  msgid "Like UpdraftPlus and can spare one minute?"
281
  msgstr ""
282
 
283
+ #: updraftplus.php:2400
284
  msgid "Please help UpdraftPlus by giving a positive review at wordpress.org"
285
  msgstr ""
286
 
287
+ #: updraftplus.php:2407
288
  msgid "Need even more features and support? Check out UpdraftPlus Premium"
289
  msgstr ""
290
 
291
+ #: updraftplus.php:2416
292
  msgid "Check out UpdraftPlus.Com for help, add-ons and support"
293
  msgstr ""
294
 
295
+ #: updraftplus.php:2419
296
  msgid "Want to say thank-you for UpdraftPlus?"
297
  msgstr ""
298
 
299
+ #: updraftplus.php:2419
300
  msgid "Please buy our very cheap 'no adverts' add-on."
301
  msgstr ""
302
 
303
+ #: updraftplus.php:2430
304
  msgid "File backup intervals"
305
  msgstr ""
306
 
307
+ #: updraftplus.php:2433
308
  msgid "Manual"
309
  msgstr ""
310
 
311
+ #: updraftplus.php:2433
312
  msgid "Every 4 hours"
313
  msgstr ""
314
 
315
+ #: updraftplus.php:2433
316
  msgid "Every 8 hours"
317
  msgstr ""
318
 
319
+ #: updraftplus.php:2433
320
  msgid "Every 12 hours"
321
  msgstr ""
322
 
323
+ #: updraftplus.php:2433
324
  msgid "Daily"
325
  msgstr ""
326
 
327
+ #: updraftplus.php:2433
328
  msgid "Weekly"
329
  msgstr ""
330
 
331
+ #: updraftplus.php:2433
332
  msgid "Fortnightly"
333
  msgstr ""
334
 
335
+ #: updraftplus.php:2433
336
  msgid "Monthly"
337
  msgstr ""
338
 
339
+ #: updraftplus.php:2442
340
+ #: updraftplus.php:2460
341
  msgid "and retain this many backups"
342
  msgstr ""
343
 
344
+ #: updraftplus.php:2449
345
  msgid "Database backup intervals"
346
  msgstr ""
347
 
348
+ #: updraftplus.php:2467
349
  msgid "If you would like to automatically schedule backups, choose schedules from the dropdowns above. Backups will occur at the intervals specified. If the two schedules are the same, then the two backups will take place together. If you choose \"manual\" then you must click the \"Backup Now\" button whenever you wish a backup to occur."
350
  msgstr ""
351
 
352
+ #: updraftplus.php:2468
353
  msgid "To fix the time at which a backup should take place,"
354
  msgstr ""
355
 
356
+ #: updraftplus.php:2468
357
  msgid "e.g. if your server is busy at day and you want to run overnight"
358
  msgstr ""
359
 
360
+ #: updraftplus.php:2468
361
  msgid "use the \"Fix Time\" add-on"
362
  msgstr ""
363
 
364
+ #: updraftplus.php:2482
365
  msgid "Any other directories found inside wp-content but exclude these directories:"
366
  msgstr ""
367
 
368
+ #: updraftplus.php:2488
369
  msgid "Include all of these, unless you are backing them up outside of UpdraftPlus. The above directories are usually everything (except for WordPress core itself which you can download afresh from WordPress.org). But if you have made customised modifications outside of these directories, you need to back them up another way."
370
  msgstr ""
371
 
372
+ #: updraftplus.php:2488
373
  msgid "Use WordShell for automatic backup, version control and patching"
374
  msgstr ""
375
 
376
+ #: updraftplus.php:2492
377
  msgid "Email"
378
  msgstr ""
379
 
380
+ #: updraftplus.php:2493
381
  msgid "Enter an address here to have a report sent (and the whole backup, if you choose) to it."
382
  msgstr ""
383
 
384
+ #: updraftplus.php:2497
385
  msgid "Database encryption phrase"
386
  msgstr ""
387
 
388
+ #: updraftplus.php:2504
389
+ msgid "If you enter text here, it is used to encrypt backups (Rijndael). <strong>Do make a separate record of it and do not lose it, or all your backups <em>will</em> be useless.</strong> Presently, only the database file is encrypted. This is also the key used to decrypt backups from this admin interface (so if you change it, then automatic decryption will not work until you change it back)."
390
+ msgstr ""
391
+
392
+ #: updraftplus.php:2504
393
+ msgid "You can also decrypt a database manually here."
394
+ msgstr ""
395
+
396
+ #: updraftplus.php:2507
397
+ msgid "Manually decrypt a database backup file"
398
+ msgstr ""
399
+
400
+ #: updraftplus.php:2511
401
+ msgid "Drop encrypted database files (db.crypt.gz files) here to upload them for decryption"
402
+ msgstr ""
403
+
404
+ #: updraftplus.php:2512
405
+ #: updraftplus.php:2991
406
+ msgid "or"
407
  msgstr ""
408
 
409
+ #: updraftplus.php:2514
410
+ msgid "Use decryption key"
411
+ msgstr ""
412
+
413
+ #: updraftplus.php:2528
414
  msgid "Copying Your Backup To Remote Storage"
415
  msgstr ""
416
 
417
+ #: updraftplus.php:2532
418
  msgid "Choose your remote storage"
419
  msgstr ""
420
 
421
+ #: updraftplus.php:2544
422
  msgid "None"
423
  msgstr ""
424
 
425
+ #: updraftplus.php:2625
426
+ #: updraftplus.php:2963
427
+ #: updraftplus.php:3232
428
  msgid "Restore"
429
  msgstr ""
430
 
431
+ #: updraftplus.php:2639
432
+ #: updraftplus.php:2649
433
  msgid "Cancel"
434
  msgstr ""
435
 
436
+ #: updraftplus.php:2646
437
+ #: updraftplus.php:2955
438
  msgid "Backup Now"
439
  msgstr ""
440
 
441
+ #: updraftplus.php:2673
442
  msgid "Advanced / Debugging Settings"
443
  msgstr ""
444
 
445
+ #: updraftplus.php:2676
446
  msgid "Debug mode"
447
  msgstr ""
448
 
449
+ #: updraftplus.php:2677
450
  msgid "Check this to receive more information and emails on the backup process - useful if something is going wrong. You <strong>must</strong> send us this log if you are filing a bug report."
451
  msgstr ""
452
 
453
+ #: updraftplus.php:2680
454
  msgid "Expert settings"
455
  msgstr ""
456
 
457
+ #: updraftplus.php:2681
458
  msgid "Show expert settings"
459
  msgstr ""
460
 
461
+ #: updraftplus.php:2681
462
  msgid "click this to show some further options; don't bother with this unless you have a problem or are curious."
463
  msgstr ""
464
 
465
+ #: updraftplus.php:2688
466
  msgid "Delete local backup"
467
  msgstr ""
468
 
469
+ #: updraftplus.php:2689
470
  msgid "Uncheck this to prevent deletion of any superfluous backup files from your server after the backup run finishes (i.e. any files despatched remotely will also remain locally, and any files being kept locally will not be subject to the retention limits)."
471
  msgstr ""
472
 
473
+ #: updraftplus.php:2693
474
  msgid "Backup directory"
475
  msgstr ""
476
 
477
+ #: updraftplus.php:2701
478
  msgid "Backup directory specified is writable, which is good."
479
  msgstr ""
480
 
481
+ #: updraftplus.php:2703
482
  msgid "Backup directory specified is <b>not</b> writable, or does not exist."
483
  msgstr ""
484
 
485
+ #: updraftplus.php:2703
486
  msgid "Click here to attempt to create the directory and set the permissions"
487
  msgstr ""
488
 
489
+ #: updraftplus.php:2703
490
  msgid "or, to reset this option"
491
  msgstr ""
492
 
493
+ #: updraftplus.php:2703
494
  msgid "click here"
495
  msgstr ""
496
 
497
+ #: updraftplus.php:2703
498
  msgid "If that is unsuccessful check the permissions on your server or change it to another directory that is writable by your web server process."
499
  msgstr ""
500
 
501
+ #: updraftplus.php:2706
502
  msgid "This is where UpdraftPlus will write the zip files it creates initially. This directory must be writable by your web server. Typically you'll want to have it inside your wp-content folder (this is the default). <b>Do not</b> place it inside your uploads dir, as that will cause recursion issues (backups of backups of backups of...)."
503
  msgstr ""
504
 
505
+ #: updraftplus.php:2727
506
  msgid "Save Changes"
507
  msgstr ""
508
 
509
+ #: updraftplus.php:2751
510
  msgid "Download log file"
511
  msgstr ""
512
 
513
+ #: updraftplus.php:2757
514
  msgid "No backup has been completed."
515
  msgstr ""
516
 
517
+ #: updraftplus.php:2777
518
  msgid "Restore successful!"
519
  msgstr ""
520
 
521
+ #: updraftplus.php:2778
522
+ #: updraftplus.php:2813
523
+ #: updraftplus.php:2829
524
  msgid "Actions"
525
  msgstr ""
526
 
527
+ #: updraftplus.php:2778
528
+ #: updraftplus.php:2793
529
+ #: updraftplus.php:2813
530
+ #: updraftplus.php:2829
531
  msgid "Return to UpdraftPlus Configuration"
532
  msgstr ""
533
 
534
+ #: updraftplus.php:2802
535
  msgid "Remove old directories"
536
  msgstr ""
537
 
538
+ #: updraftplus.php:2808
539
  msgid "Old directories successfully removed."
540
  msgstr ""
541
 
542
+ #: updraftplus.php:2811
543
  msgid "Old directory removal failed for some reason. You may want to do this manually."
544
  msgstr ""
545
 
546
+ #: updraftplus.php:2826
547
  msgid "Backup directory could not be created"
548
  msgstr ""
549
 
550
+ #: updraftplus.php:2828
551
  msgid "Backup directory successfully created."
552
  msgstr ""
553
 
554
+ #: updraftplus.php:2835
555
  msgid "Schedule backup"
556
  msgstr ""
557
 
558
+ #: updraftplus.php:2838
559
  msgid "Failed."
560
  msgstr ""
561
 
562
+ #: updraftplus.php:2840
563
  msgid "OK. Now load any page from your site to make sure the schedule can trigger. You should then see activity in the \"Last log message\" field below."
564
  msgstr ""
565
 
566
+ #: updraftplus.php:2840
567
  msgid "Nothing happening? Follow this link for help."
568
  msgstr ""
569
 
570
+ #: updraftplus.php:2853
571
  msgid "Your settings have been wiped."
572
  msgstr ""
573
 
574
+ #: updraftplus.php:2860
575
  msgid "By UpdraftPlus.Com"
576
  msgstr ""
577
 
578
+ #: updraftplus.php:2860
579
  msgid "Lead developer's homepage"
580
  msgstr ""
581
 
582
+ #: updraftplus.php:2860
583
  msgid "Donate"
584
  msgstr ""
585
 
586
+ #: updraftplus.php:2860
587
  msgid "Other WordPress plugins"
588
  msgstr ""
589
 
590
+ #: updraftplus.php:2860
591
  msgid "Version"
592
  msgstr ""
593
 
594
+ #: updraftplus.php:2864
595
  msgid "Your backup has been restored."
596
  msgstr ""
597
 
598
+ #: updraftplus.php:2864
599
  msgid "Your old (themes, uploads, plugins, whatever) directories have been retained with \"-old\" appended to their name. Remove them when you are satisfied that the backup worked properly."
600
  msgstr ""
601
 
602
+ #: updraftplus.php:2864
603
  msgid "At this time UpdraftPlus does not automatically restore your database. You will need to use an external tool like phpMyAdmin to perform that task."
604
  msgstr ""
605
 
606
+ #: updraftplus.php:2870
607
  msgid "Old directories successfully deleted."
608
  msgstr ""
609
 
610
+ #: updraftplus.php:2873
611
+ msgid "Your PHP memory limit is quite low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may not work properly with a memory limit of less than 96 Mb (though on the other hand, it has been used successfully with a 32Mb limit - your experience may vary, but don't blame us!)."
612
  msgstr ""
613
 
614
+ #: updraftplus.php:2873
615
  msgid "Current limit is:"
616
  msgstr ""
617
 
618
+ #: updraftplus.php:2877
619
  msgid "Your PHP max_execution_time is less than 60 seconds. This possibly means you're running in safe_mode. Either disable safe_mode or modify your php.ini to set max_execution_time to a higher number. If you do not, then longer will be needed to complete a backup (but that is all). Present limit is:"
620
  msgstr ""
621
 
622
+ #: updraftplus.php:2877
623
  msgid "seconds"
624
  msgstr ""
625
 
626
+ #: updraftplus.php:2882
627
  msgid "You have old directories from a previous backup (technical information: these are found in wp-content, and suffixed with -old). Use this button to delete them (if you have verified that the restoration worked)."
628
  msgstr ""
629
 
630
+ #: updraftplus.php:2886
631
  msgid "Delete Old Directories"
632
  msgstr ""
633
 
634
+ #: updraftplus.php:2886
635
  msgid "Are you sure you want to delete the old directories? This cannot be undone."
636
  msgstr ""
637
 
638
+ #: updraftplus.php:2899
639
  msgid "Existing Schedule And Backups"
640
  msgstr ""
641
 
642
+ #: updraftplus.php:2903
643
  msgid "JavaScript warning"
644
  msgstr ""
645
 
646
+ #: updraftplus.php:2904
647
  msgid "This admin interface uses JavaScript heavily. You either need to activate it within your browser, or to use a JavaScript-capable browser."
648
  msgstr ""
649
 
650
+ #: updraftplus.php:2917
651
+ #: updraftplus.php:2930
652
  msgid "Nothing currently scheduled"
653
  msgstr ""
654
 
655
+ #: updraftplus.php:2922
656
  msgid "At the same time as the files backup"
657
  msgstr ""
658
 
659
+ #: updraftplus.php:2942
660
  msgid "Next scheduled backups"
661
  msgstr ""
662
 
663
+ #: updraftplus.php:2944
664
  msgid "Files"
665
  msgstr ""
666
 
667
+ #: updraftplus.php:2946
668
  msgid "Time now"
669
  msgstr ""
670
 
671
+ #: updraftplus.php:2950
672
  msgid "Last finished backup run"
673
  msgstr ""
674
 
675
+ #: updraftplus.php:2970
676
  msgid "Last log message"
677
  msgstr ""
678
 
679
+ #: updraftplus.php:2971
680
  msgid "(Nothing yet logged)"
681
  msgstr ""
682
 
683
+ #: updraftplus.php:2974
684
  msgid "Backups, logs & restoring"
685
  msgstr ""
686
 
687
+ #: updraftplus.php:2975
688
  msgid "Press to see available backups"
689
  msgstr ""
690
 
691
+ #: updraftplus.php:2975
692
  #, php-format
693
  msgid "%d set(s) available"
694
  msgstr ""
695
 
696
+ #: updraftplus.php:2980
697
  msgid "Downloading"
698
  msgstr ""
699
 
700
+ #: updraftplus.php:2980
701
  msgid "Pressing a button for Database/Plugins/Themes/Uploads/Others will make UpdraftPlus try to bring the backup file back from the remote storage (if any - e.g. Amazon S3, Dropbox, Google Drive, FTP) to your webserver. Then you will be allowed to download it to your computer. If the fetch from the remote storage stops progressing (wait 30 seconds to make sure), then press again to resume. Remember that you can also visit the cloud storage vendor's website directly."
702
  msgstr ""
703
 
704
+ #: updraftplus.php:2981
705
  msgid "Restoring"
706
  msgstr ""
707
 
708
+ #: updraftplus.php:2981
709
  msgid "Press the button for the backup you wish to restore. If your site is large and you are using remote storage, then you should first click on each entity in order to retrieve it back to the webserver. This will prevent time-outs from occuring during the restore process itself."
710
  msgstr ""
711
 
712
+ #: updraftplus.php:2981
713
  msgid "More tasks:"
714
  msgstr ""
715
 
716
+ #: updraftplus.php:2981
717
  msgid "upload backup files"
718
  msgstr ""
719
 
720
+ #: updraftplus.php:2981
721
  msgid "Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below."
722
  msgstr ""
723
 
724
+ #: updraftplus.php:2981
725
  msgid "rescan folder for new backup sets"
726
  msgstr ""
727
 
728
+ #: updraftplus.php:2982
729
  msgid "Opera web browser"
730
  msgstr ""
731
 
732
+ #: updraftplus.php:2982
733
  msgid "If you are using this, then turn Turbo/Road mode off."
734
  msgstr ""
735
 
736
+ #: updraftplus.php:2983
737
  msgid "This is a count of the contents of your Updraft directory"
738
  msgstr ""
739
 
740
+ #: updraftplus.php:2983
741
  msgid "Web-server disk space in use by UpdraftPlus"
742
  msgstr ""
743
 
744
+ #: updraftplus.php:2983
745
  msgid "refresh"
746
  msgstr ""
747
 
748
+ #: updraftplus.php:2985
749
  msgid "UpdraftPlus - Upload backup files"
750
  msgstr ""
751
 
752
+ #: updraftplus.php:2986
753
  msgid "Upload files into UpdraftPlus. Use this to import backups made on a different WordPress installation."
754
  msgstr ""
755
 
756
+ #: updraftplus.php:2990
757
  msgid "Drop backup zips here"
758
  msgstr ""
759
 
760
+ #: updraftplus.php:3004
761
  msgid "calculating..."
762
  msgstr ""
763
 
764
+ #: updraftplus.php:3073
765
  msgid "Restore backup"
766
  msgstr ""
767
 
768
+ #: updraftplus.php:3074
769
  msgid "Restore backup from"
770
  msgstr ""
771
 
772
+ #: updraftplus.php:3075
773
  msgid "Restoring will replace this site's themes, plugins, uploads and/or other content directories (according to what is contained in the backup set, and your selection"
774
  msgstr ""
775
 
776
+ #: updraftplus.php:3075
777
  msgid "Choose the components to restore"
778
  msgstr ""
779
 
780
+ #: updraftplus.php:3086
781
  msgid "Databases cannot yet be restored from here - you must download the database file and take it to your web hosting company's control panel."
782
  msgstr ""
783
 
784
+ #: updraftplus.php:3091
785
  msgid "Perform a backup now"
786
  msgstr ""
787
 
788
+ #: updraftplus.php:3092
789
  msgid "This will schedule a one-time backup. To proceed, press 'Backup Now', then wait 10 seconds, then visit any page on your site. WordPress should then start the backup running in the background."
790
  msgstr ""
791
 
792
+ #: updraftplus.php:3098
793
  msgid "Does nothing happen when you schedule backups?"
794
  msgstr ""
795
 
796
+ #: updraftplus.php:3098
797
  msgid "Go here for help."
798
  msgstr ""
799
 
800
+ #: updraftplus.php:3104
801
  msgid "Multisite"
802
  msgstr ""
803
 
804
+ #: updraftplus.php:3108
805
  msgid "Do you need WordPress Multisite support?"
806
  msgstr ""
807
 
808
+ #: updraftplus.php:3108
809
  msgid "Please check out UpdraftPlus Premium, or the stand-alone Multisite add-on."
810
  msgstr ""
811
 
812
+ #: updraftplus.php:3113
813
  msgid "Configure Backup Contents And Schedule"
814
  msgstr ""
815
 
816
+ #: updraftplus.php:3119
817
  msgid "Debug Information And Expert Options"
818
  msgstr ""
819
 
820
+ #: updraftplus.php:3124
821
  msgid "Peak memory usage"
822
  msgstr ""
823
 
824
+ #: updraftplus.php:3125
825
  msgid "Current memory usage"
826
  msgstr ""
827
 
828
+ #: updraftplus.php:3126
829
  msgid "PHP memory limit"
830
  msgstr ""
831
 
832
+ #: updraftplus.php:3129
833
  msgid "The buttons below will immediately execute a backup run, independently of WordPress's scheduler. If these work whilst your scheduled backups and the \"Backup Now\" button do absolutely nothing (i.e. not even produce a log file), then it means that your scheduler is broken. You should then disable all your other plugins, and try the \"Backup Now\" button. If that fails, then contact your web hosting company and ask them if they have disabled wp-cron. If it succeeds, then re-activate your other plugins one-by-one, and find the one that is the problem and report a bug to them."
834
  msgstr ""
835
 
836
+ #: updraftplus.php:3133
837
  msgid "Debug Full Backup"
838
  msgstr ""
839
 
840
+ #: updraftplus.php:3133
841
  msgid "This will cause an immediate backup. The page will stall loading until it finishes (ie, unscheduled)."
842
  msgstr ""
843
 
844
+ #: updraftplus.php:3137
845
  msgid "Debug Database Backup"
846
  msgstr ""
847
 
848
+ #: updraftplus.php:3137
849
  msgid "This will cause an immediate DB backup. The page will stall loading until it finishes (ie, unscheduled). The backup may well run out of time; really this button is only helpful for checking that the backup is able to get through the initial stages, or for small WordPress sites.."
850
  msgstr ""
851
 
852
+ #: updraftplus.php:3139
853
  msgid "Wipe Settings"
854
  msgstr ""
855
 
856
+ #: updraftplus.php:3140
857
  msgid "This button will delete all UpdraftPlus settings (but not any of your existing backups from your cloud storage). You will then need to enter all your settings again. You can also do this before deactivating/deinstalling UpdraftPlus if you wish."
858
  msgstr ""
859
 
860
+ #: updraftplus.php:3143
861
  msgid "Wipe All Settings"
862
  msgstr ""
863
 
864
+ #: updraftplus.php:3143
865
  msgid "This will delete all your UpdraftPlus settings - are you sure you want to do this?"
866
  msgstr ""
867
 
868
+ #: updraftplus.php:3212
869
  msgid "Press here to download"
870
  msgstr ""
871
 
872
+ #: updraftplus.php:3214
873
  #, php-format
874
  msgid "(No %s)"
875
  msgstr ""
876
 
877
+ #: updraftplus.php:3224
878
  msgid "Backup Log"
879
  msgstr ""
880
 
881
+ #: updraftplus.php:3232
882
  msgid "After pressing this button, you will be given the option to choose which components you wish to restore"
883
  msgstr ""
884
 
885
+ #: updraftplus.php:3257
886
+ #: updraftplus.php:3261
887
  msgid "Warning"
888
  msgstr ""
889
 
890
+ #: updraftplus.php:3257
891
  #, php-format
892
  msgid "You have less than %s of free disk space on the disk which UpdraftPlus is configured to use to create backups. UpdraftPlus could well run out of space. Contact your the operator of your server (e.g. your web hosting company) to resolve this issue."
893
  msgstr ""
894
 
895
+ #: updraftplus.php:3261
896
  #, php-format
897
  msgid "UpdraftPlus does not officially support versions of WordPress before %s. It may work for you, but if it does not, then please be aware that no support is available until you upgrade WordPress."
898
  msgstr ""
899
 
900
+ #: updraftplus.php:3265
901
+ #: updraftplus.php:3269
902
+ #: updraftplus.php:3273
903
+ #: updraftplus.php:3277
904
  msgid "UpdraftPlus notice:"
905
  msgstr ""
906
 
907
+ #: updraftplus.php:3265
908
  msgid "The log file could not be read."
909
  msgstr ""
910
 
911
+ #: updraftplus.php:3269
912
+ msgid "The given file could not be read."
913
+ msgstr ""
914
+
915
+ #: updraftplus.php:3273
916
+ #: updraftplus.php:3277
917
  #, php-format
918
  msgid "Click here to authenticate your %s account (you will not be able to back up to %s without it)."
919
  msgstr ""
920
 
921
+ #: updraftplus.php:3450
922
  msgid "Infinite recursion: consult your log for more information"
923
  msgstr ""
924
 
1424
  msgstr ""
1425
 
1426
  #: addons/sftp.php:32
1427
+ msgid "SFTP password"
1428
  msgstr ""
1429
 
1430
  #: addons/sftp.php:50
methods/dropbox.php CHANGED
@@ -245,7 +245,7 @@ class UpdraftPlus_BackupModule_dropbox {
245
  $curl_version = curl_version();
246
  $curl_ssl_supported= ($curl_version['features'] & CURL_VERSION_SSL);
247
  if (!$curl_ssl_supported) {
248
- ?><p><strong><?php _e('Warning','updraftplus'); ?>:</strong> <?php _e("Your web server's PHP/Curl installation does not support https access. We cannot access Dropbox without this support. Please contact your web hosting provider's support. UpdraftPlus's Dropbox module <strong>requires</strong> Curl+https. Your only options to get this working are 1) Install/enable curl with https or 2) Hire us or someone else to code additional support options into UpdraftPlus. 3) Wait, possibly forever, for someone else to do this.",'updraftplus');?></p><?php
249
  }
250
  }
251
  ?>
245
  $curl_version = curl_version();
246
  $curl_ssl_supported= ($curl_version['features'] & CURL_VERSION_SSL);
247
  if (!$curl_ssl_supported) {
248
+ ?><p><strong><?php _e('Warning','updraftplus'); ?>:</strong> <?php e_("Your web server's PHP/Curl installation does not support https access. We cannot access Dropbox without this support. Please contact your web hosting provider's support. UpdraftPlus's Dropbox module <strong>requires</strong> Curl+https. Your only options to get this working are 1) Install/enable curl with https or 2) Hire us or someone else to code additional support options into UpdraftPlus. 3) Wait, possibly forever, for someone else to do this.",'updraftplus');?></p><?php
249
  }
250
  }
251
  ?>
methods/ftp.php CHANGED
@@ -30,7 +30,7 @@ class UpdraftPlus_BackupModule_ftp {
30
  $updraftplus->log("FTP upload attempt: $file -> ftp://$user@$server/${ftp_remote_path}${file}");
31
  $timer_start = microtime(true);
32
  $size_k = round(filesize($fullpath)/1024,1);
33
- if ($ftp->put($fullpath, $ftp_remote_path.$file, FTP_BINARY)) {
34
  $updraftplus->log("FTP upload attempt successful (".$size_k."Kb in ".(round(microtime(true)-$timer_start,2)).'s)');
35
  $updraftplus->uploaded_file($file);
36
  } else {
@@ -58,7 +58,6 @@ class UpdraftPlus_BackupModule_ftp {
58
 
59
  global $updraftplus;
60
 
61
- //handle errors at some point TODO
62
  $ftp = new UpdraftPlus_ftp_wrapper(UpdraftPlus_Options::get_updraft_option('updraft_server_address'),UpdraftPlus_Options::get_updraft_option('updraft_ftp_login'),UpdraftPlus_Options::get_updraft_option('updraft_ftp_pass'));
63
  $ftp->passive = true;
64
 
@@ -73,7 +72,13 @@ class UpdraftPlus_BackupModule_ftp {
73
  $ftp_remote_path = trailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_ftp_remote_path'));
74
  $fullpath = $updraftplus->backups_dir_location().'/'.$file;
75
 
76
- $ftp->get($fullpath, $ftp_remote_path.$file, FTP_BINARY);
 
 
 
 
 
 
77
  }
78
 
79
  public static function config_print_javascript_onready() {
@@ -99,6 +104,11 @@ class UpdraftPlus_BackupModule_ftp {
99
  public static function config_print() {
100
  ?>
101
 
 
 
 
 
 
102
  <tr class="updraftplusmethod ftp">
103
  <th></th>
104
  <td><em><?php echo apply_filters('updraft_sftp_ftps_notice', '<strong>'.__('Only non-encrypted FTP is supported by regular UpdraftPlus.').'</strong> <a href="http://updraftplus.com/shop/sftp/">'.__('If you want encryption (e.g. you are storing sensitive business data), then an add-on is available.','updraftplus')).'</a>'; ?></em></td>
@@ -165,7 +175,7 @@ class UpdraftPlus_BackupModule_ftp {
165
  _e("Failure: an unexpected internal UpdraftPlus error occurred when testing the credentials - please contact the developer");
166
  return;
167
  }
168
- if ($ftp->put(ABSPATH.'wp-includes/version.php', $fullpath, FTP_BINARY)) {
169
  echo __("Success: we successfully logged in, and confirmed our ability to create a file in the given directory (login type:",'updraftplus')." ".$ftp->login_type.')';
170
  @$ftp->delete($fullpath);
171
  } else {
@@ -176,4 +186,4 @@ class UpdraftPlus_BackupModule_ftp {
176
 
177
  }
178
 
179
- ?>
30
  $updraftplus->log("FTP upload attempt: $file -> ftp://$user@$server/${ftp_remote_path}${file}");
31
  $timer_start = microtime(true);
32
  $size_k = round(filesize($fullpath)/1024,1);
33
+ if ($ftp->put($fullpath, $ftp_remote_path.$file, FTP_BINARY, true, $updraftplus)) {
34
  $updraftplus->log("FTP upload attempt successful (".$size_k."Kb in ".(round(microtime(true)-$timer_start,2)).'s)');
35
  $updraftplus->uploaded_file($file);
36
  } else {
58
 
59
  global $updraftplus;
60
 
 
61
  $ftp = new UpdraftPlus_ftp_wrapper(UpdraftPlus_Options::get_updraft_option('updraft_server_address'),UpdraftPlus_Options::get_updraft_option('updraft_ftp_login'),UpdraftPlus_Options::get_updraft_option('updraft_ftp_pass'));
62
  $ftp->passive = true;
63
 
72
  $ftp_remote_path = trailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_ftp_remote_path'));
73
  $fullpath = $updraftplus->backups_dir_location().'/'.$file;
74
 
75
+ $resume = false;
76
+ if (file_exists($fullpath)) {
77
+ $resume = true;
78
+ $updraftplus->log("File already exists locally; will resume: size: ".filesize($fullpath));
79
+ }
80
+
81
+ $ftp->get($fullpath, $ftp_remote_path.$file, FTP_BINARY, $resume, $updraftplus);
82
  }
83
 
84
  public static function config_print_javascript_onready() {
104
  public static function config_print() {
105
  ?>
106
 
107
+ <tr class="updraftplusmethod ftp">
108
+ <td></td>
109
+ <td><p><em><?php printf(__('%s is a great choice, because UpdraftPlus supports chunked uploads - no matter how big your blog is, UpdraftPlus can upload it a little at a time, and not get thwarted by timeouts.','updraftplus'),'FTP');?></em></p></td>
110
+ </tr>
111
+
112
  <tr class="updraftplusmethod ftp">
113
  <th></th>
114
  <td><em><?php echo apply_filters('updraft_sftp_ftps_notice', '<strong>'.__('Only non-encrypted FTP is supported by regular UpdraftPlus.').'</strong> <a href="http://updraftplus.com/shop/sftp/">'.__('If you want encryption (e.g. you are storing sensitive business data), then an add-on is available.','updraftplus')).'</a>'; ?></em></td>
175
  _e("Failure: an unexpected internal UpdraftPlus error occurred when testing the credentials - please contact the developer");
176
  return;
177
  }
178
+ if ($ftp->put(ABSPATH.'wp-includes/version.php', $fullpath, FTP_BINARY, false)) {
179
  echo __("Success: we successfully logged in, and confirmed our ability to create a file in the given directory (login type:",'updraftplus')." ".$ftp->login_type.')';
180
  @$ftp->delete($fullpath);
181
  } else {
186
 
187
  }
188
 
189
+ ?>
options.php CHANGED
@@ -22,8 +22,8 @@ class UpdraftPlus_Options {
22
  }
23
 
24
  public static function add_admin_pages() {
25
- global $updraftplus;
26
- add_submenu_page('options-general.php', 'UpdraftPlus', __('UpdraftPlus Backups','updraftplus'), "manage_options", "updraftplus", array($updraftplus, "settings_output"));
27
  }
28
 
29
  public static function options_form_begin() {
@@ -33,7 +33,7 @@ class UpdraftPlus_Options {
33
 
34
  public static function admin_init() {
35
 
36
- global $updraftplus;
37
  register_setting('updraft-options-group', 'updraft_interval', array($updraftplus, 'schedule_backup') );
38
  register_setting('updraft-options-group', 'updraft_interval_database', array($updraftplus, 'schedule_backup_database') );
39
  register_setting('updraft-options-group', 'updraft_retain', array($updraftplus, 'retain_range') );
@@ -60,7 +60,7 @@ class UpdraftPlus_Options {
60
  register_setting('updraft-options-group', 'updraft_ftp_pass' );
61
  register_setting('updraft-options-group', 'updraft_ftp_remote_path' );
62
  register_setting('updraft-options-group', 'updraft_server_address' );
63
- register_setting('updraft-options-group', 'updraft_dir', array($updraftplus, 'prune_updraft_dir_prefix') );
64
  register_setting('updraft-options-group', 'updraft_email');
65
  register_setting('updraft-options-group', 'updraft_delete_local', 'absint' );
66
  register_setting('updraft-options-group', 'updraft_debug_mode', 'absint' );
@@ -70,8 +70,10 @@ class UpdraftPlus_Options {
70
  register_setting('updraft-options-group', 'updraft_include_others', 'absint' );
71
  register_setting('updraft-options-group', 'updraft_include_others_exclude' );
72
 
73
- register_setting('updraft-options-group', 'updraft_starttime_files', array($updraftplus, 'hourminute') );
74
- register_setting('updraft-options-group', 'updraft_starttime_db', array($updraftplus, 'hourminute') );
 
 
75
 
76
  global $pagenow;
77
  if (is_multisite() && $pagenow == 'options-general.php' && isset($_REQUEST['page']) && 'updraftplus' == substr($_REQUEST['page'], 0, 11)) {
@@ -80,14 +82,22 @@ class UpdraftPlus_Options {
80
 
81
  }
82
 
83
- public static function show_admin_warning_multisite() {
 
 
84
 
85
- global $updraftplus;
 
 
 
 
86
 
87
- $updraftplus->show_admin_warning('<strong>UpdraftPlus warning:</strong> This is a WordPress multi-site (a.k.a. network) installation. <a href="http://updraftplus.com">WordPress Multisite is supported, with extra features, by UpdraftPlus Premium, or the Multisite add-on</a>. Without upgrading, UpdraftPlus allows <strong>every</strong> blog admin who can modify plugin settings to back up (and hence access the data, including passwords, from) and restore (including with customised modifications, e.g. changed passwords) <strong>the entire network</strong>. (This applies to all WordPress backup plugins unless they have been explicitly coded for multisite compatibility).', "error");
88
 
89
- }
 
90
 
 
91
 
92
  }
93
 
22
  }
23
 
24
  public static function add_admin_pages() {
25
+ global $updraftplus_admin;
26
+ add_submenu_page('options-general.php', 'UpdraftPlus', __('UpdraftPlus Backups','updraftplus'), "manage_options", "updraftplus", array($updraftplus_admin, "settings_output"));
27
  }
28
 
29
  public static function options_form_begin() {
33
 
34
  public static function admin_init() {
35
 
36
+ global $updraftplus, $updraftplus_admin;
37
  register_setting('updraft-options-group', 'updraft_interval', array($updraftplus, 'schedule_backup') );
38
  register_setting('updraft-options-group', 'updraft_interval_database', array($updraftplus, 'schedule_backup_database') );
39
  register_setting('updraft-options-group', 'updraft_retain', array($updraftplus, 'retain_range') );
60
  register_setting('updraft-options-group', 'updraft_ftp_pass' );
61
  register_setting('updraft-options-group', 'updraft_ftp_remote_path' );
62
  register_setting('updraft-options-group', 'updraft_server_address' );
63
+ register_setting('updraft-options-group', 'updraft_dir', array($updraftplus_admin, 'prune_updraft_dir_prefix') );
64
  register_setting('updraft-options-group', 'updraft_email');
65
  register_setting('updraft-options-group', 'updraft_delete_local', 'absint' );
66
  register_setting('updraft-options-group', 'updraft_debug_mode', 'absint' );
70
  register_setting('updraft-options-group', 'updraft_include_others', 'absint' );
71
  register_setting('updraft-options-group', 'updraft_include_others_exclude' );
72
 
73
+ register_setting('updraft-options-group', 'updraft_starttime_files', array('UpdraftPlus_Options', 'hourminute') );
74
+ register_setting('updraft-options-group', 'updraft_starttime_db', array('UpdraftPlus_Options', 'hourminute') );
75
+
76
+ register_setting('updraft-options-group', 'updraft_disable_ping', array('UpdraftPlus_Options', 'pingfilter') );
77
 
78
  global $pagenow;
79
  if (is_multisite() && $pagenow == 'options-general.php' && isset($_REQUEST['page']) && 'updraftplus' == substr($_REQUEST['page'], 0, 11)) {
82
 
83
  }
84
 
85
+ public static function pingfilter($disable) {
86
+ return apply_filters('updraftplus_pingfilter', $disable);
87
+ }
88
 
89
+ public static function hourminute($pot) {
90
+ if (preg_match("/^[0-2][0-9]:[0-5][0-9]$/", $pot)) return $pot;
91
+ if ('' == $pot) return date('H:i', time()+300);
92
+ return '00:00';
93
+ }
94
 
95
+ public static function show_admin_warning_multisite() {
96
 
97
+ global $updraftplus_admin;
98
+ $updraftplus_admin->show_admin_warning('<strong>UpdraftPlus warning:</strong> This is a WordPress multi-site (a.k.a. network) installation. <a href="http://updraftplus.com">WordPress Multisite is supported, with extra features, by UpdraftPlus Premium, or the Multisite add-on</a>. Without upgrading, UpdraftPlus allows <strong>every</strong> blog admin who can modify plugin settings to back up (and hence access the data, including passwords, from) and restore (including with customised modifications, e.g. changed passwords) <strong>the entire network</strong>. (This applies to all WordPress backup plugins unless they have been explicitly coded for multisite compatibility).', "error");
99
 
100
+ }
101
 
102
  }
103
 
readme.txt CHANGED
@@ -16,7 +16,7 @@ New features: selective restoration, importing remote backups; plus many tweaks,
16
  <a href="http://updraftplus.com">UpdraftPlus</a> simplifies backups (and restoration). Backup into the cloud (Amazon S3, Dropbox, Google Drive, FTP, SFTP, WebDAV and email) and restore with a single click. Backups of files and database can have separate schedules.
17
 
18
  * Supports backups to Amazon S3, Dropbox, Google Drive, FTP (including SSL), email, SFTP and WebDAV
19
- * Quick restore
20
  * Backup automatically on a repeating schedule
21
  * Files and databases can have separate schedules
22
  * Failed uploads are automatically resumed/retried
@@ -25,7 +25,7 @@ New features: selective restoration, importing remote backups; plus many tweaks,
25
  * Download backup archives direct from your WordPress dashboard
26
  * Database backups can be encrypted for security
27
  * Debug mode that gives full logging of the backup
28
- * Thousands of users: widely tested and reliable
29
  * Internationalised (translations very welcome - see below)
30
  * Premium version and support available - <a href="http://updraftplus.com">http://updraftplus.com</a>
31
 
@@ -96,7 +96,7 @@ You can check the changelog for changes; but the original Updraft, before I fork
96
 
97
  = Any known bugs ? =
98
 
99
- Not a bug, but one issue to be aware of is that backups of very large sites (lots of uploaded media) are quite complex matters, given the limits of running inside WordPress on a huge variety of different web hosting setups. With large sites, you need to use Amazon S3, which UpdraftPlus supports (since 0.9.20), Google Drive (0.9.21), Dropbox (since 1.2.19) or WebDAV (since 1.4.30), because these support chunked, resumable uploads. Other backup methods have code (since 0.9.0) to retry failed uploads of an archive, but the upload cannot be chunked, so if an archive is enormous (i.e. cannot be completely uploaded in the time that PHP is allowed for running on your web host) it cannot work.
100
 
101
  = My site was hacked, and I have no backups! I thought UpdraftPlus was working! Can I kill you? =
102
 
@@ -112,10 +112,26 @@ Thanks for asking - yes, I have. Check out my profile page - http://profiles.wor
112
 
113
  == Changelog ==
114
 
115
- = 1.5.5 - 2013/03/26 =
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  * Now translatable - .pot file included (translators welcome!)
117
  * When restoring, you can now select only some components to restore
118
- * History of previous backups can re-scan to find backups manually imported (e.g. via FTP) (trunk version has drag-and-drop import)
119
  * Multisite add-on (http://updraftplus.com/shop/) now stores/restores blogs and mu-plugins separately
120
  * Display UpdraftPlus's disk space usage
121
  * Internationalisation hooks in main body of plugin
@@ -129,6 +145,7 @@ Thanks for asking - yes, I have. Check out my profile page - http://profiles.wor
129
  * Clean up temporary files left behind by zipArchive::addFile
130
  * Tweak Dropbox library to work from behind very weird proxies that double-surround the HTTP header
131
  * Improved help for people with broken schedulers
 
132
 
133
  = 1.4.48 - 03/11/2013 =
134
  * Improve batching on zip creation for sites with very large files
@@ -369,7 +386,7 @@ Thanks for asking - yes, I have. Check out my profile page - http://profiles.wor
369
  3. Showing and downloading backup sets
370
 
371
  We recognise and thank the following for code and/or libraries used and/or modified under the terms of their licences:
372
- * UpdraftPlus is based on the original Updraft by Paul Kehrer (Twitter: http://twitter.com/reaperhulk, Blog: http://langui.sh)
373
  * Sorin Iclanzan, http://profiles.wordpress.org/hel.io/
374
  * Ben Tadiar, https://github.com/BenTheDesigner/Dropbox
375
  * Beau Brownlee, http://www.solutionbot.com/2009/01/02/php-ftp-class/
@@ -382,7 +399,7 @@ We recognise and thank the following for code and/or libraries used and/or modif
382
 
383
  This program is free software; you can redistribute it and/or modify
384
  it under the terms of the GNU General Public License as published by
385
- the Free Software Foundation; either version 2 of the License, or
386
  (at your option) any later version.
387
 
388
  This program is distributed in the hope that it will be useful,
16
  <a href="http://updraftplus.com">UpdraftPlus</a> simplifies backups (and restoration). Backup into the cloud (Amazon S3, Dropbox, Google Drive, FTP, SFTP, WebDAV and email) and restore with a single click. Backups of files and database can have separate schedules.
17
 
18
  * Supports backups to Amazon S3, Dropbox, Google Drive, FTP (including SSL), email, SFTP and WebDAV
19
+ * Quick restore (both file and database backups)
20
  * Backup automatically on a repeating schedule
21
  * Files and databases can have separate schedules
22
  * Failed uploads are automatically resumed/retried
25
  * Download backup archives direct from your WordPress dashboard
26
  * Database backups can be encrypted for security
27
  * Debug mode that gives full logging of the backup
28
+ * Thousands of users: widely tested and reliable (over 100,000 downloads)
29
  * Internationalised (translations very welcome - see below)
30
  * Premium version and support available - <a href="http://updraftplus.com">http://updraftplus.com</a>
31
 
96
 
97
  = Any known bugs ? =
98
 
99
+ Not a bug, but one issue to be aware of is that backups of very large sites (lots of uploaded media) are quite complex matters, given the limits of running inside WordPress on a huge variety of different web hosting setups. With large sites, you need to use Amazon S3, which UpdraftPlus supports (since 0.9.20), Google Drive (0.9.21), Dropbox (since 1.2.19), WebDAV (since 1.4.30), or FTP (since 1.5.9) because these support chunked, resumable uploads. Other backup methods have code (since 0.9.0) to retry failed uploads of an archive, but the upload cannot be chunked, so if an archive is enormous (i.e. cannot be completely uploaded in the time that PHP is allowed for running on your web host) it cannot work.
100
 
101
  = My site was hacked, and I have no backups! I thought UpdraftPlus was working! Can I kill you? =
102
 
112
 
113
  == Changelog ==
114
 
115
+ = 1.5.11 - not yet released/supported =
116
+ * Now restores databases (we recommend the MySQL command-line for versions created with previous versions of UpdraftPlus)
117
+ * Batch INSERT commands in database backups, for much faster restoration (typically 95% faster)
118
+ * Built-in multi-uploader, allowing easier restoration of old backup sets
119
+ * FTP and FTPS (not SFTP) are now chunked and resumable (both download and upload), subject to your FTP server responding correctly to SIZE
120
+ * Built in drag-and-drop database decrypter for manual decryption
121
+ * Clear PHP's file stat cache when checking for zip file activity - fixes potential halt on very enormous sites
122
+ * Caught some untranslated strings
123
+ * In fix-time add-on, fade UI when relevant
124
+ * German translation: thanks to Marcel Herrguth - mherrguth@mrgeneration.de
125
+ * Hungarian translation: thanks to Szépe Viktor - http://www.szepe.net
126
+ * Respect WordPress's WP_MAX_MEMORY_LIMIT constant
127
+ * Improved UI of downloader
128
+ * Re-factoring of admin-area and some backup code into separate lazy-loaded files, to reduce memory consumption on sites generally
129
+ * A small typo slipped into 1.5.5 which prevented some Google Drive users from setting up new installations
130
+
131
+ = 1.5.5 - 03/26/2013 =
132
  * Now translatable - .pot file included (translators welcome!)
133
  * When restoring, you can now select only some components to restore
134
+ * History of previous backups can re-scan to find backups manually imported (e.g. via FTP) (trunk has drag-and-drop uploader)
135
  * Multisite add-on (http://updraftplus.com/shop/) now stores/restores blogs and mu-plugins separately
136
  * Display UpdraftPlus's disk space usage
137
  * Internationalisation hooks in main body of plugin
145
  * Clean up temporary files left behind by zipArchive::addFile
146
  * Tweak Dropbox library to work from behind very weird proxies that double-surround the HTTP header
147
  * Improved help for people with broken schedulers
148
+ * Fix FTP download error
149
 
150
  = 1.4.48 - 03/11/2013 =
151
  * Improve batching on zip creation for sites with very large files
386
  3. Showing and downloading backup sets
387
 
388
  We recognise and thank the following for code and/or libraries used and/or modified under the terms of their licences:
389
+ * UpdraftPlus is derived from the original Updraft by Paul Kehrer (Twitter: http://twitter.com/reaperhulk, Blog: http://langui.sh)
390
  * Sorin Iclanzan, http://profiles.wordpress.org/hel.io/
391
  * Ben Tadiar, https://github.com/BenTheDesigner/Dropbox
392
  * Beau Brownlee, http://www.solutionbot.com/2009/01/02/php-ftp-class/
399
 
400
  This program is free software; you can redistribute it and/or modify
401
  it under the terms of the GNU General Public License as published by
402
+ the Free Software Foundation; either version 3 of the License, or
403
  (at your option) any later version.
404
 
405
  This program is distributed in the hope that it will be useful,
updraftplus.php CHANGED
@@ -2,25 +2,35 @@
2
  /*
3
  Plugin Name: UpdraftPlus - Backup/Restore
4
  Plugin URI: http://updraftplus.com
5
- Description: Backup and restore: your site can be backed up locally or to Amazon S3, Dropbox, Google Drive, (S)FTP, WebDAV & email, on automatic schedules.
6
  Author: UpdraftPlus.Com, DavidAnderson
7
- Version: 1.5.6
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
10
  Text Domain: updraftplus
11
  Author URI: http://updraftplus.com
12
  */
13
 
 
14
  /*
15
  TODO - some of these are out of date/done, needs pruning
16
- // Add an appeal for translators to email me
17
- // Separate out all restoration code and admin UI into separate file/classes (optimisation)?
18
  // Search for other TODO-s in the code
 
 
 
 
 
 
 
 
19
  // Make mcrypt warning on dropbox more prominent - one customer missed it
20
  // Store meta-data on which version of UD the backup was made with (will help if we ever introduce quirks that need ironing)
21
  // Test restoration when uploads dir is /assets/ (e.g. with Shoestrap theme)
22
  // Send the user an email upon their first backup with tips on what to do (e.g. support/improve) (include legacy check to not bug existing users)
23
  //Allow use of /usr/bin/zip - since this can escape from PHP's memory limit. Can still batch as we do so, in order to monitor/measure progress
 
 
24
  //Do an automated test periodically for the success of loop-back connections
25
  //When a manual backup is run, use a timer to update the 'Download backups and logs' section, just like 'Last finished backup run'. Beware of over-writing anything that's in there from a resumable downloader.
26
  //Change DB encryption to not require whole gzip in memory (twice)
@@ -33,13 +43,11 @@ TODO - some of these are out of date/done, needs pruning
33
  // Should we resume if the only errors were upon deletion (i.e. the backup itself was fine?) Presently we do, but it displays errors for the user to confuse them. Perhaps better to make pruning a separate scheuled task??
34
  // Warn the user if their zip-file creation is slooowww...
35
  // Create a "Want Support?" button/console, that leads them through what is needed, and performs some basic tests...
36
- // Resuming partial (S)FTP uploads
37
- // Translations
38
  // Add-on to manage all your backups from a single dashboard
39
  // Make disk space check more intelligent (currently hard-coded at 35Mb)
40
  // Provide backup/restoration for UpdraftPlus's settings, to allow 'bootstrap' on a fresh WP install - some kind of single-use code which a remote UpdraftPlus can use to authenticate
41
  // Multiple jobs
42
- // Multisite - a separate 'blogs' zip
43
  // Allow connecting to remote storage, scanning + populating backup history from it
44
  // GoogleDrive in-dashboard download resumption loads the whole archive into memory - should instead either chunk or directly stream fo the file handle
45
  // Multisite add-on should allow restoring of each blog individually
@@ -49,14 +57,12 @@ TODO - some of these are out of date/done, needs pruning
49
  // Remove the recurrence of admin notices when settings are saved due to _wp_referer
50
 
51
  Encrypt filesystem, if memory allows (and have option for abort if not); split up into multiple zips when needed
52
- // Does not delete old custom directories upon a restore?
53
  // New sub-module to verify that the backups are there, independently of backup thread
54
  */
55
 
56
  /* Portions copyright 2010 Paul Kehrer
57
  Portions copyright 2011-13 David Anderson
58
  Other portions copyright as indicated authors in the relevant files
59
- Particular thanks to Sorin Iclanzan, author of the "Backup" plugin, from which much Google Drive code was taken under the GPLv3+
60
 
61
  This program is free software; you can redistribute it and/or modify
62
  it under the terms of the GNU General Public License as published by
@@ -73,9 +79,6 @@ along with this program; if not, write to the Free Software
73
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
74
  */
75
 
76
- // 15 minutes
77
- @set_time_limit(900);
78
-
79
  define('UPDRAFTPLUS_DIR', dirname(__FILE__));
80
  define('UPDRAFTPLUS_URL', plugins_url('', __FILE__));
81
  define('UPDRAFT_DEFAULT_OTHERS_EXCLUDE','upgrade,cache,updraft,index.php,backup,backups');
@@ -85,6 +88,7 @@ define('UPDRAFT_TRANSTIME', 3600*9+5);
85
 
86
  // Load add-ons
87
  if (is_file(UPDRAFTPLUS_DIR.'/premium.php')) require_once(UPDRAFTPLUS_DIR.'/premium.php');
 
88
 
89
  if ($dir_handle = opendir(UPDRAFTPLUS_DIR.'/addons')) {
90
  while ($e = readdir($dir_handle)) {
@@ -99,7 +103,7 @@ if (!isset($updraftplus)) $updraftplus = new UpdraftPlus();
99
 
100
  if (!$updraftplus->memory_check(192)) {
101
  // Experience appears to show that the memory limit is only likely to be hit (unless it is very low) by single files that are larger than available memory (when compressed)
102
- @ini_set('memory_limit', '192M'); //up the memory limit for large backup files
103
  }
104
 
105
  if (!class_exists('UpdraftPlus_Options')) require_once(UPDRAFTPLUS_DIR.'/options.php');
@@ -140,14 +144,6 @@ class UpdraftPlus {
140
  var $current_resumption;
141
  var $newresumption_scheduled = false;
142
 
143
- var $zipfiles_added;
144
- var $zipfiles_existingfiles;
145
- var $zipfiles_dirbatched;
146
- var $zipfiles_batched;
147
- var $zipfiles_lastwritetime;
148
-
149
- var $zip_preferpcl = false;
150
-
151
  function __construct() {
152
 
153
  // Initialisation actions - takes place on plugin load
@@ -161,33 +157,26 @@ class UpdraftPlus {
161
  }
162
 
163
  # Create admin page
164
- add_action('admin_init', array($this, 'admin_init'));
 
165
  add_action('updraft_backup', array($this,'backup_files'));
166
  add_action('updraft_backup_database', array($this,'backup_database'));
167
- # backup_all is used by the manual "Backup Now" button
168
  add_action('updraft_backup_all', array($this,'backup_all'));
169
  # this is our runs-after-backup event, whose purpose is to see if it succeeded or failed, and resume/mom-up etc.
170
  add_action('updraft_backup_resume', array($this,'backup_resume'), 10, 3);
171
- add_action('wp_ajax_updraft_download_backup', array($this, 'updraft_download_backup'));
172
- add_action('wp_ajax_updraft_ajax', array($this, 'updraft_ajax_handler'));
173
  # http://codex.wordpress.org/Plugin_API/Filter_Reference/cron_schedules
174
  add_filter('cron_schedules', array($this,'modify_cron_schedules'));
175
- add_filter('plugin_action_links', array($this, 'plugin_action_links'), 10, 2);
176
- add_action('init', array($this, 'handle_url_actions'));
177
  add_action('plugins_loaded', array($this, 'load_translations'));
178
 
179
- if (defined('UPDRAFTPLUS_PREFERPCLZIP') && UPDRAFTPLUS_PREFERPCLZIP == true) { $this->zip_preferpcl = true; }
180
-
181
- }
182
 
183
- function load_translations() {
184
- // Tell WordPress where to find the translations
185
- load_plugin_textdomain('updraftplus', false, basename(dirname(__FILE__)).'/languages');
186
  }
187
 
188
  // Handle actions passed on to method plugins; e.g. Google OAuth 2.0 - ?page=updraftplus&action=updraftmethod-googledrive-auth
189
  // Also handle action=downloadlog
190
  function handle_url_actions() {
 
191
  // First, basic security check: must be an admin page, with ability to manage options, with the right parameters
192
  if ( UpdraftPlus_Options::user_can_manage() && isset( $_GET['page'] ) && $_GET['page'] == 'updraftplus' && isset($_GET['action']) ) {
193
  if (preg_match("/^updraftmethod-([a-z]+)-([a-z]+)$/", $_GET['action'], $matches) && file_exists(UPDRAFTPLUS_DIR.'/methods/'.$matches[1].'.php')) {
@@ -197,6 +186,7 @@ class UpdraftPlus {
197
  $call_method = "action_".$matches[2];
198
  if (method_exists($call_class, $call_method)) call_user_func(array($call_class,$call_method));
199
  } elseif ($_GET['action'] == 'downloadlog' && isset($_GET['updraftplus_backup_nonce']) && preg_match("/^[0-9a-f]{12}$/",$_GET['updraftplus_backup_nonce'])) {
 
200
  $updraft_dir = $this->backups_dir_location();
201
  $log_file = $updraft_dir.'/log.'.$_GET['updraftplus_backup_nonce'].'.txt';
202
  if (is_readable($log_file)) {
@@ -206,10 +196,35 @@ class UpdraftPlus {
206
  } else {
207
  add_action('admin_notices', array($this,'show_admin_warning_unreadablelog') );
208
  }
 
 
 
 
 
 
 
 
 
 
209
  }
210
  }
211
  }
212
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
213
  // Cleans up temporary files found in the updraft directory
214
  function clean_temporary_files() {
215
  $updraft_dir = $this->backups_dir_location();
@@ -226,19 +241,6 @@ class UpdraftPlus {
226
  }
227
  }
228
 
229
- # Adds the settings link under the plugin on the plugin screen.
230
- function plugin_action_links($links, $file) {
231
- if ($file == plugin_basename(__FILE__)){
232
- $settings_link = '<a href="'.site_url().'/wp-admin/options-general.php?page=updraftplus">'.__("Settings", "updraftplus").'</a>';
233
- array_unshift($links, $settings_link);
234
- // $settings_link = '<a href="http://david.dw-perspective.org.uk/donate">'.__("Donate","UpdraftPlus").'</a>';
235
- // array_unshift($links, $settings_link);
236
- $settings_link = '<a href="http://updraftplus.com">'.__("Add-Ons / Pro Support","updraftplus").'</a>';
237
- array_unshift($links, $settings_link);
238
- }
239
- return $links;
240
- }
241
-
242
  function backup_time_nonce() {
243
  $this->backup_time = time();
244
  $nonce = substr(md5(time().rand()), 20);
@@ -347,6 +349,9 @@ class UpdraftPlus {
347
 
348
  function backup_resume($resumption_no, $bnonce) {
349
 
 
 
 
350
  @ignore_user_abort(true);
351
  // This is scheduled for 5 minutes after a backup job starts
352
 
@@ -386,7 +391,7 @@ class UpdraftPlus {
386
 
387
  // Sanity check
388
  if (empty($this->backup_time)) {
389
- $this->log('Abort this run: the backup_time parameter appears to be empty');
390
  return false;
391
  }
392
 
@@ -560,6 +565,8 @@ class UpdraftPlus {
560
  function boot_backup($backup_files, $backup_database) {
561
 
562
  @ignore_user_abort(true);
 
 
563
 
564
  //generate backup information
565
  $this->backup_time_nonce();
@@ -573,6 +580,7 @@ class UpdraftPlus {
573
 
574
  // Some house-cleaning
575
  $this->clean_temporary_files();
 
576
 
577
  // Log some information that may be helpful
578
  $this->log("Tasks: Backup files: $backup_files (schedule: ".UpdraftPlus_Options::get_updraft_option('updraft_interval', 'unset').") Backup DB: $backup_database (schedule: ".UpdraftPlus_Options::get_updraft_option('updraft_interval_database', 'unset').")");
@@ -669,13 +677,13 @@ class UpdraftPlus {
669
  // Make sure that the final status is shown
670
  if (empty($this->errors)) {
671
  $send_an_email = true;
672
- $final_message = "The backup apparently succeeded and is now complete";
673
  } elseif ($this->newresumption_scheduled == false) {
674
  $send_an_email = true;
675
- $final_message = "The backup attempt has finished, apparently unsuccessfully";
676
  } else {
677
  // There are errors, but a resumption will be attempted
678
- $final_message = "The backup has not finished; a resumption is scheduled within 5 minutes";
679
  }
680
 
681
  // Now over-ride the decision to send an email, if needed
@@ -942,58 +950,6 @@ class UpdraftPlus {
942
  $this->log("To decrease the likelihood of overlaps, increasing resumption interval to: $resume_interval + $howmuch = ".($resume_interval+$howmuch));
943
  }
944
 
945
- function create_zip($create_from_dir, $whichone, $create_in_dir, $backup_file_basename) {
946
- // Note: $create_from_dir can be an array or a string
947
- @set_time_limit(900);
948
-
949
- if ($whichone != "others") $this->log("Beginning creation of dump of $whichone");
950
-
951
- $full_path = $create_in_dir.'/'.$backup_file_basename.'-'.$whichone.'.zip';
952
- $time_now = time();
953
-
954
- if (file_exists($full_path)) {
955
- $this->log("$backup_file_basename-$whichone.zip: this file has already been created");
956
- $time_mod = (int)@filemtime($full_path);
957
- if ($time_mod>100 && ($time_now-$time_mod)<30) {
958
- $this->log("Terminate: the zip $full_path already exists, and was modified within the last 30 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).", size=".filesize($full_path)."). This likely means that another UpdraftPlus run is still at work; so we will exit.");
959
- $this->increase_resume_and_reschedule(120);
960
- die;
961
- }
962
- return basename($full_path);
963
- }
964
-
965
- // Temporary file, to be able to detect actual completion (upon which, it is renamed)
966
-
967
- // Firstly, make sure that the temporary file is not already being written to - which can happen if a resumption takes place whilst an old run is still active
968
- $zip_name = $full_path.'.tmp';
969
- $time_mod = (int)@filemtime($zip_name);
970
- if (file_exists($zip_name) && $time_mod>100 && ($time_now-$time_mod)<30) {
971
- $file_size = filesize($zip_name);
972
- $this->log("Terminate: the temporary file $zip_name already exists, and was modified within the last 30 seconds (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).", size=$file_size). This likely means that another UpdraftPlus run is still at work; so we will exit.");
973
- $this->increase_resume_and_reschedule(120);
974
- die;
975
- } elseif (file_exists($zip_name)) {
976
- $this->log("File exists ($zip_name), but was apparently not modified within the last 30 seconds, so we assume that any previous run has now terminated (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).")");
977
- }
978
-
979
- $microtime_start = microtime(true);
980
- # The paths in the zip should then begin with '$whichone', having removed WP_CONTENT_DIR from the front
981
- $zipcode = $this->make_zipfile($create_from_dir, $zip_name);
982
- if ($zipcode !== true) {
983
- $this->log("ERROR: Zip failure: Could not create $whichone zip: code=$zipcode");
984
- $this->error(sprintf(__("Could not create %s zip. Consult the log file for more information.",'updraftplus'),$whichone));
985
- return false;
986
- } else {
987
- rename($full_path.'.tmp', $full_path);
988
- $timetaken = max(microtime(true)-$microtime_start, 0.000001);
989
- $kbsize = filesize($full_path)/1024;
990
- $rate = round($kbsize/$timetaken, 1);
991
- $this->log("Created $whichone zip - file size is ".round($kbsize,1)." Kb in ".round($timetaken,1)." s ($rate Kb/s)");
992
- }
993
-
994
- return basename($full_path);
995
- }
996
-
997
  // For detecting another run, and aborting if one was found
998
  function check_recent_modification($file) {
999
  if (file_exists($file)) {
@@ -1019,6 +975,10 @@ class UpdraftPlus {
1019
  return array();
1020
  }
1021
 
 
 
 
 
1022
  //get the blog name and rip out all non-alphanumeric chars other than _
1023
  $blog_name = str_replace(' ','_',substr(get_bloginfo(), 0, 96));
1024
  $blog_name = preg_replace('/[^A-Za-z0-9_]/','', $blog_name);
@@ -1043,7 +1003,7 @@ class UpdraftPlus {
1043
  $backup_array[$youwhat] = $backup_file_basename.'-'.$youwhat.'.zip';
1044
  if (file_exists($zip_file)) $backup_array[$youwhat.'-size'] = filesize($zip_file);
1045
  } else {
1046
- $created = $this->create_zip($whichdir, $youwhat, $updraft_dir, $backup_file_basename);
1047
  if ($created) {
1048
  $backup_array[$youwhat] = $created;
1049
  $backup_array[$youwhat.'-size'] = filesize($updraft_dir.'/'.$created);
@@ -1109,7 +1069,7 @@ class UpdraftPlus {
1109
  }
1110
 
1111
  if (count($other_dirlist)>0) {
1112
- $created = $this->create_zip($other_dirlist, 'others', $updraft_dir, $backup_file_basename);
1113
  if ($created) {
1114
  $backup_array['others'] = $created;
1115
  $backup_array['others-size'] = filesize($updraft_dir.'/'.$created);
@@ -1172,6 +1132,7 @@ class UpdraftPlus {
1172
 
1173
  //Begin new backup of MySql
1174
  $this->stow("# " . 'WordPress MySQL database backup' . "\n");
 
1175
  $this->stow("#\n");
1176
  $this->stow("# " . sprintf(__('Generated: %s','wp-db-backup'),date("l j. F Y H:i T")) . "\n");
1177
  $this->stow("# " . sprintf(__('Hostname: %s','wp-db-backup'),DB_HOST) . "\n");
@@ -1358,13 +1319,12 @@ class UpdraftPlus {
1358
  $this->stow($create_table[0][1] . ' ;');
1359
 
1360
  if (false === $table_structure) {
1361
- $err_msg = sprintf(__('Error getting table structure of %s','wp-db-backup'), $table);
1362
- //$this->error($err_msg);
1363
  $this->stow("#\n# $err_msg\n#\n");
1364
  }
1365
 
1366
  // Comment in SQL-file
1367
- $this->stow("\n\n#\n# " . sprintf(__('Data contents of table %s','wp-db-backup'),$this->backquote($table)) . "\n#\n");
1368
  }
1369
 
1370
  // In UpdraftPlus, segment is always 'none'
@@ -1390,12 +1350,14 @@ class UpdraftPlus {
1390
 
1391
  do {
1392
  if ( !@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == "off") @set_time_limit(15*60);
 
1393
  $table_data = $wpdb->get_results("SELECT * FROM $table LIMIT {$row_start}, {$row_inc}", ARRAY_A);
1394
- $entries = 'INSERT INTO ' . $this->backquote($table) . ' VALUES (';
1395
  // \x08\\x09, not required
1396
  $search = array("\x00", "\x0a", "\x0d", "\x1a");
1397
  $replace = array('\0', '\n', '\r', '\Z');
1398
  if($table_data) {
 
1399
  foreach ($table_data as $row) {
1400
  $total_rows++;
1401
  $values = array();
@@ -1409,8 +1371,16 @@ class UpdraftPlus {
1409
  $values[] = "'" . str_replace($search, $replace, str_replace('\'', '\\\'', str_replace('\\', '\\\\', $value))) . "'";
1410
  }
1411
  }
1412
- $this->stow(" \n" . $entries . implode(', ', $values) . ');');
 
 
 
 
 
 
 
1413
  }
 
1414
  $row_start += $row_inc;
1415
  }
1416
  } while((count($table_data) > 0) and ($segment=='none'));
@@ -1476,12 +1446,6 @@ class UpdraftPlus {
1476
 
1477
  /*END OF WP-DB-BACKUP BLOCK */
1478
 
1479
- function hourminute($pot) {
1480
- if (preg_match("/^[0-2][0-9]:[0-5][0-9]$/", $pot)) return $pot;
1481
- if ('' == $pot) return date('H:i', time()+300);
1482
- return '00:00';
1483
- }
1484
-
1485
  /*
1486
  this function is both the backup scheduler and ostensibly a filter callback for saving the option.
1487
  it is called in the register_setting for the updraft_interval, which means when the admin settings
@@ -1506,6 +1470,10 @@ class UpdraftPlus {
1506
  return wp_filter_nohtml_kses($interval);
1507
  }
1508
 
 
 
 
 
1509
  // Acts as a WordPress options filter
1510
  function googledrive_clientid_checkchange($client_id) {
1511
  if (UpdraftPlus_Options::get_updraft_option('fdrive_token') != '' && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_clientid') != $client_id) {
@@ -1543,16 +1511,6 @@ class UpdraftPlus {
1543
  return $schedules;
1544
  }
1545
 
1546
- // This options filter removes ABSPATH off the front of updraft_dir, if it is given absolutely and contained within it
1547
- function prune_updraft_dir_prefix($updraft_dir) {
1548
- if ('/' == substr($updraft_dir, 0, 1) || "\\" == substr($updraft_dir, 0, 1) || preg_match('/^[a-zA-Z]:/', $updraft_dir)) {
1549
- if (strpos($updraft_dir, ABSPATH) === 0) {
1550
- $updraft_dir = substr($updraft_dir, strlen(ABSPATH));
1551
- }
1552
- }
1553
- return $updraft_dir;
1554
- }
1555
-
1556
  function backups_dir_location() {
1557
 
1558
  if (!empty($this->backup_dir)) return $this->backup_dir;
@@ -1580,251 +1538,9 @@ class UpdraftPlus {
1580
  return $updraft_dir;
1581
  }
1582
 
1583
- function recursive_directory_size($directory) {
1584
- $size = 0;
1585
- if(substr($directory,-1) == '/') $directory = substr($directory,0,-1);
1586
-
1587
- if(!file_exists($directory) || !is_dir($directory) || !is_readable($directory)) return -1;
1588
-
1589
- if($handle = opendir($directory)) {
1590
- while(($file = readdir($handle)) !== false) {
1591
- $path = $directory.'/'.$file;
1592
- if($file != '.' && $file != '..') {
1593
- if(is_file($path)) {
1594
- $size += filesize($path);
1595
- } elseif(is_dir($path)) {
1596
- $handlesize = recursive_directory_size($path);
1597
- if($handlesize >= 0) { $size += $handlesize; } else { return -1; }
1598
- }
1599
- }
1600
- }
1601
- closedir($handle);
1602
- }
1603
- if ($size > 1073741824) {
1604
- return round($size / 1048576, 1).' Gb';
1605
- } elseif ($size > 1048576) {
1606
- return round($size / 1048576, 1).' Mb';
1607
- } elseif ($size > 1024) {
1608
- return round($size / 1024, 1).' Kb';
1609
- } else {
1610
- return round($size, 1).' b';
1611
- }
1612
- }
1613
-
1614
- // This function examines inside the updraft directory to see if any new archives have been uploaded. If so, it adds them to the backup set. (No removal of items from the backup set is done)
1615
- function rebuild_backup_history() {
1616
-
1617
- $known_files = array();
1618
- $known_nonces = array();
1619
- $changes = false;
1620
-
1621
- $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1622
- if (!is_array($backup_history)) $backup_history = array();
1623
-
1624
- // Accumulate a list of known files
1625
- foreach ($backup_history as $btime => $bdata) {
1626
- foreach ($bdata as $key => $value) {
1627
- // Record which set this file is found in
1628
- if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(zip|gz)$/i', $value, $matches)) {
1629
- $nonce = $matches[2];
1630
- $known_files[$value] = $nonce;
1631
- $known_nonces[$nonce] = $btime;
1632
- }
1633
- }
1634
- }
1635
-
1636
- $updraft_dir = $this->backups_dir_location();
1637
-
1638
- if (!is_dir($updraft_dir)) return;
1639
-
1640
- if (!$handle = opendir($updraft_dir)) return;
1641
-
1642
- while (false !== ($entry = readdir($handle))) {
1643
- if ($entry != "." && $entry != "..") {
1644
- if (preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-([\-a-z]+)\.(zip|gz)$/i', $entry, $matches)) {
1645
- $btime = strtotime($matches[1]);
1646
- if ($btime > 100) {
1647
- if (!isset($known_files[$entry])) {
1648
- $changes = true;
1649
- $nonce = $matches[2];
1650
- $type = $matches[3];
1651
- // The time from the filename does not include seconds. Need to identify the seconds to get the right time
1652
- if (isset($known_nonces[$nonce])) $btime = $known_nonces[$nonce];
1653
- if (!isset($backup_history[$btime])) $backup_history[$btime] = array();
1654
- $backup_history[$btime][$type] = $entry;
1655
- $backup_history[$btime][$type.'-size'] = filesize($updraft_dir.'/'.$entry);
1656
- $backup_history[$btime]['nonce'] = $nonce;
1657
- }
1658
- }
1659
- }
1660
- }
1661
- }
1662
-
1663
-
1664
- if ($changes) UpdraftPlus_Options::update_updraft_option('updraft_backup_history', $backup_history);
1665
-
1666
- }
1667
-
1668
- // Called via AJAX
1669
- function updraft_ajax_handler() {
1670
- // Test the nonce (probably not needed, since we're presumably admin-authed, but there's no harm)
1671
- $nonce = (empty($_REQUEST['nonce'])) ? "" : $_REQUEST['nonce'];
1672
- if (! wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce') || empty($_REQUEST['subaction'])) die('Security check');
1673
-
1674
- if ('lastlog' == $_GET['subaction']) {
1675
- echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', '('.__('Nothing yet logged', 'updraftplus').')'));
1676
- } elseif ('lastbackup' == $_GET['subaction']) {
1677
- echo $this->last_backup_html();
1678
- } elseif ('diskspaceused' == $_GET['subaction']) {
1679
- echo $this->recursive_directory_size($this->backups_dir_location());
1680
- } elseif ('historystatus' == $_GET['subaction']) {
1681
- $rescan = (isset($_GET['rescan']) && $_GET['rescan'] == 1);
1682
- if ($rescan) $this->rebuild_backup_history();
1683
- echo $this->existing_backup_table();
1684
- } elseif ('downloadstatus' == $_GET['subaction'] && isset($_GET['timestamp']) && isset($_GET['type'])) {
1685
-
1686
- echo get_transient('ud_dlmess_'.$_GET['timestamp'].'_'.$_GET['type']).'<br>';
1687
-
1688
- if ($file = get_transient('ud_dlfile_'.$_GET['timestamp'].'_'.$_GET['type'])) {
1689
- if ('failed' == $file) {
1690
- echo "Download failed";
1691
- } elseif (preg_match('/^downloaded:(.*)$/', $file, $matches) && file_exists($matches[1])) {
1692
- $size = round(filesize($matches[1])/1024, 1);
1693
- echo "File ready: $size Kb: You should: <button type=\"button\" onclick=\"updraftplus_downloadstage2('".$_GET['timestamp']."', '".$_GET['type']."')\">Download to your computer</button> and then, if you wish, <button id=\"uddownloaddelete_".$_GET['timestamp']."_".$_GET['type']."\" type=\"button\" onclick=\"updraftplus_deletefromserver('".$_GET['timestamp']."', '".$_GET['type']."')\">Delete from your web server</button>";
1694
- } elseif (preg_match('/^downloading:(.*)$/', $file, $matches) && file_exists($matches[1])) {
1695
- $size = round(filesize($matches[1])/1024, 1);
1696
- echo __('File downloading', 'updraftplus').": ".basename($matches[1]).": $size Kb";
1697
- } else {
1698
- echo __("No local copy present.", 'updraftplus');
1699
- }
1700
- }
1701
-
1702
- } elseif ($_POST['subaction'] == 'credentials_test') {
1703
- $method = (preg_match("/^[a-z0-9]+$/", $_POST['method'])) ? $_POST['method'] : "";
1704
-
1705
- // Test the credentials, return a code
1706
- require_once(UPDRAFTPLUS_DIR."/methods/$method.php");
1707
-
1708
- $objname = "UpdraftPlus_BackupModule_${method}";
1709
- if (method_exists($objname, "credentials_test")) call_user_func(array('UpdraftPlus_BackupModule_'.$method, 'credentials_test'));
1710
- }
1711
-
1712
- die;
1713
-
1714
- }
1715
-
1716
- function updraft_download_backup() {
1717
-
1718
- if (!isset($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'], 'updraftplus_download')) die;
1719
-
1720
- if (!isset($_REQUEST['timestamp']) || !is_numeric($_REQUEST['timestamp']) || !isset($_REQUEST['type'])) exit;
1721
-
1722
- $backupable_entities = $this->get_backupable_file_entities(true);
1723
- $type_match = false;
1724
- foreach ($backupable_entities as $type => $info) {
1725
- if ($_REQUEST['type'] == $type) $type_match = true;
1726
- }
1727
-
1728
- if (!$type_match && $_REQUEST['type'] != 'db') exit;
1729
 
1730
- // Get the information on what is wanted
1731
- $type = $_REQUEST['type'];
1732
- $timestamp = $_REQUEST['timestamp'];
1733
-
1734
- // You need a nonce before you can set job data. And we certainly don't yet have one.
1735
- $this->backup_time_nonce();
1736
-
1737
- $debug_mode = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
1738
-
1739
- // Set the job type before logging, as there can be different logging destinations
1740
- $this->jobdata_set('job_type', 'download');
1741
-
1742
- // Retrieve the information from our backup history
1743
- $backup_history = $this->get_backup_history();
1744
- // Base name
1745
- $file = $backup_history[$timestamp][$type];
1746
-
1747
- // Where it should end up being downloaded to
1748
- $fullpath = $this->backups_dir_location().'/'.$file;
1749
-
1750
- if (isset($_GET['stage']) && '2' == $_GET['stage']) {
1751
- $this->spool_file($timestamp, $type, $fullpath);
1752
- die;
1753
- }
1754
-
1755
- if (isset($_POST['stage']) && 'delete' == $_POST['stage']) {
1756
- @unlink($fullpath);
1757
- echo 'deleted';
1758
- $this->log('The file has been deleted');
1759
- die;
1760
- }
1761
-
1762
- // TODO: FIXME: Failed downloads may leave log files forever (though they are small)
1763
- // Note that log() assumes that the data is in _POST, not _GET
1764
- if ($debug_mode) $this->logfile_open($this->nonce);
1765
-
1766
- $this->log("Requested to obtain file: timestamp=$timestamp, type=$type");
1767
-
1768
- // The AJAX responder that updates on progress wants to see this
1769
- set_transient('ud_dlfile_'.$timestamp.'_'.$type, 'downloading:'.$fullpath, 3600);
1770
-
1771
- $service = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
1772
- $this->jobdata_set('service', $service);
1773
-
1774
- // Fetch it from the cloud, if we have not already got it
1775
-
1776
- $needs_downloading = false;
1777
- $known_size = isset($backup_history[$timestamp][$type.'-size']) ? $backup_history[$timestamp][$type.'-size'] : false;
1778
-
1779
- if(!file_exists($fullpath)) {
1780
- //if the file doesn't exist and they're using one of the cloud options, fetch it down from the cloud.
1781
- $needs_downloading = true;
1782
- $this->log('File does not yet exist locally - needs downloading');
1783
- } elseif ($known_size>0 && filesize($fullpath) < $known_size) {
1784
- $this->log('The file was found locally but did not match the size in the backup history - will resume downloading');
1785
- $needs_downloading = true;
1786
- } elseif ($known_size>0) {
1787
- $this->log('The file was found locally and matched the recorded size from the backup history ('.round($known_size/1024,1).' Kb)');
1788
- } else {
1789
- $this->log('No file size was found recorded in the backup history. We will assume the local one is complete.');
1790
- }
1791
-
1792
- if ($needs_downloading) {
1793
- // Close browser connection so that it can resume AJAX polling
1794
- header('Connection: close');
1795
- header('Content-Length: 0');
1796
- header('Content-Encoding: none');
1797
- session_write_close();
1798
- echo "\r\n\r\n";
1799
- $this->download_file($file, $service);
1800
- if (is_readable($fullpath)) {
1801
- $this->log('Remote fetch was successful (file size: '.round(filesize($fullpath)/1024,1).' Kb)');
1802
- } else {
1803
- $this->log('Remote fetch failed');
1804
- }
1805
- }
1806
-
1807
- // Now, spool the thing to the browser
1808
- if(is_file($fullpath) && is_readable($fullpath)) {
1809
-
1810
- // That message is then picked up by the AJAX listener
1811
- set_transient('ud_dlfile_'.$timestamp.'_'.$type, 'downloaded:'.$fullpath, 3600);
1812
-
1813
- } else {
1814
-
1815
- set_transient('ud_dlfile_'.$timestamp.'_'.$type, 'failed', 3600);
1816
-
1817
- echo 'Remote fetch failed. File '.$fullpath.' did not exist or was unreadable. If you delete local backups then remote retrieval may have failed.';
1818
- }
1819
-
1820
- @fclose($this->logfile_handle);
1821
- if (!$debug_mode) @unlink($this->logfile_name);
1822
-
1823
- exit;
1824
-
1825
- }
1826
-
1827
- function spool_file($timestamp, $type, $fullpath) {
1828
 
1829
  if (file_exists($fullpath)) {
1830
 
@@ -1835,38 +1551,38 @@ class UpdraftPlus {
1835
  $filearr = explode('.',$file);
1836
  // //we've only got zip and gz...for now
1837
  $file_ext = array_pop($filearr);
1838
- if($file_ext == 'zip') {
1839
- header('Content-type: application/zip');
1840
- } else {
1841
- // This catches both when what was popped was 'crypt' (*-db.gz.crypt) and when it was 'gz' (unencrypted)
1842
- header('Content-type: application/x-gzip');
1843
- }
1844
  header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
1845
  header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
1846
  header("Content-Length: $len;");
 
1847
  if ($file_ext == 'crypt') {
1848
- header("Content-Disposition: attachment; filename=\"".substr($file,0,-6)."\";");
1849
- } else {
1850
- header("Content-Disposition: attachment; filename=\"$file\";");
1851
- }
1852
- ob_end_flush();
1853
- if ($file_ext == 'crypt') {
1854
- $encryption = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
1855
  if ($encryption == "") {
 
 
1856
  $this->error('Decryption of database failed: the database file is encrypted, but you have no encryption key entered.');
1857
  } else {
1858
- require_once(dirname(__FILE__).'/includes/phpseclib/Crypt/Rijndael.php');
1859
  $rijndael = new Crypt_Rijndael();
1860
  $rijndael->setKey($encryption);
1861
- $in_handle = fopen($fullpath,'r');
1862
- $ciphertext = "";
1863
- while (!feof ($in_handle)) {
1864
- $ciphertext .= fread($in_handle, 16384);
 
 
 
 
 
1865
  }
1866
- fclose ($in_handle);
1867
- print $rijndael->decrypt($ciphertext);
1868
  }
1869
  } else {
 
 
 
 
 
 
1870
  readfile($fullpath);
1871
  }
1872
  // $this->delete_local($file);
@@ -1875,193 +1591,9 @@ class UpdraftPlus {
1875
  }
1876
  }
1877
 
1878
- function download_file($file, $service=false) {
1879
-
1880
- if (!$service) $service = UpdraftPlus_Options::get_updraft_option('updraft_service');
1881
-
1882
- $this->log("Requested file from remote service: service=$service, file=$file");
1883
-
1884
- $method_include = UPDRAFTPLUS_DIR.'/methods/'.$service.'.php';
1885
- if (file_exists($method_include)) require_once($method_include);
1886
-
1887
- $objname = "UpdraftPlus_BackupModule_${service}";
1888
- if (method_exists($objname, "download")) {
1889
- $remote_obj = new $objname;
1890
- $remote_obj->download($file);
1891
- } else {
1892
- $this->log("Automatic backup restoration is not available with the method: $service.");
1893
- $this->error("$file: ".sprintf(__("The backup archive for restoring this file could not be found. The remote storage method in use (%s) does not allow us to retrieve files. To proceed with this restoration, you need to obtain a copy of this file and place it inside UpdraftPlus's working folder", 'updraftplus'), $service)." (".$this->prune_updraft_dir_prefix($this->backups_dir_location()).")");
1894
- }
1895
-
1896
- }
1897
-
1898
- function restore_backup($timestamp) {
1899
-
1900
- global $wp_filesystem;
1901
- $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
1902
- if(!is_array($backup_history[$timestamp])) {
1903
- echo '<p>'.__('This backup does not exist in the backup history - restoration aborted. Timestamp:','updraftplus')." $timestamp</p><br/>";
1904
- return false;
1905
- }
1906
-
1907
- $credentials = request_filesystem_credentials("options-general.php?page=updraftplus&action=updraft_restore&backup_timestamp=$timestamp");
1908
- WP_Filesystem($credentials);
1909
- if ( $wp_filesystem->errors->get_error_code() ) {
1910
- foreach ( $wp_filesystem->errors->get_error_messages() as $message )
1911
- show_message($message);
1912
- exit;
1913
- }
1914
-
1915
- //if we make it this far then WP_Filesystem has been instantiated and is functional (tested with ftpext, what about suPHP and other situations where direct may work?)
1916
- echo '<h1>'.__('UpdraftPlus Restoration: Progress', 'updraftplus').'</h1><div id="updraft-restore-progress">';
1917
-
1918
- $updraft_dir = $this->backups_dir_location().'/';
1919
-
1920
- $service = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
1921
-
1922
- if (!isset($_POST['updraft_restore']) || !is_array($_POST['updraft_restore'])) {
1923
- echo '<p>'.__('ABORT: Could not find the information on which entities to restore.', 'updraftplus').'</p>';
1924
- return false;
1925
- }
1926
-
1927
- $entities_to_restore = array_flip($_POST['updraft_restore']);
1928
-
1929
- $backupable_entities = $this->get_backupable_file_entities(true, true);
1930
-
1931
- foreach($backup_history[$timestamp] as $type => $file) {
1932
- // All restorable entities must be given explicitly, as we can store other arbitrary data in the history array
1933
-
1934
- if (!isset($backupable_entities[$type]) && 'db' != $type) continue;
1935
-
1936
- if ($type == 'db') {
1937
- echo "<h2>".__('Database','updraftplus')."</h2>";
1938
- } else {
1939
- echo "<h2>".$backupable_entities[$type]['description']."</h2>";
1940
- }
1941
-
1942
- if (!isset($entities_to_restore[$type])) {
1943
- echo "<p>$type: ".__('This component was not selected for restoration - skipping.', 'updraftplus')."</p>";
1944
- continue;
1945
- }
1946
-
1947
- $fullpath = $updraft_dir.$file;
1948
-
1949
- echo "Looking for $type archive: file name: ".htmlspecialchars($file)."<br>";
1950
- if(!is_readable($fullpath) && $type != 'db') {
1951
- echo __("File is not locally present - needs retrieving from remote storage (for large files, it is better to do this in advance from the download console)",'updraftplus')."<br>";
1952
- $this->download_file($file, $service);
1953
- }
1954
- // If a file size is stored in the backup data, then verify correctness of the local file
1955
- if (isset($backup_history[$timestamp][$type.'-size'])) {
1956
- $fs = $backup_history[$timestamp][$type.'-size'];
1957
- echo __("Archive is expected to be size:",'updraftplus')." ".round($fs/1024)." Kb :";
1958
- $as = @filesize($fullpath);
1959
- if ($as == $fs) {
1960
- echo "OK<br>";
1961
- } else {
1962
- echo "<strong>".__('ERROR','updraftplus').":</strong> is size: ".round($as/1024)." ($fs, $as)<br>";
1963
- }
1964
- } else {
1965
- echo __("The backup records do not contain information about the proper size of this file.",'updraftplus')."<br>";
1966
- }
1967
- # Types: uploads, themes, plugins, others, db
1968
- if(is_readable($fullpath) && $type != 'db') {
1969
-
1970
- if(!class_exists('WP_Upgrader')) require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
1971
- require_once(UPDRAFTPLUS_DIR.'/includes/updraft-restorer.php');
1972
- $restorer = new Updraft_Restorer();
1973
- $val = $restorer->restore_backup($fullpath, $type, $service, $backupable_entities[$type]);
1974
-
1975
- if(is_wp_error($val)) {
1976
- foreach ($val->get_error_messages() as $msg) {
1977
- echo '<strong>'.__('Error message', 'updraftplus').':</strong> '.htmlspecialchars($msg).'<br>';
1978
- }
1979
- echo '</div>'; //close the updraft_restore_progress div even if we error
1980
- return false;
1981
- }
1982
- } elseif ($type != 'db') {
1983
- $this->error("$file: ".__('Could not find one of the files for restoration', 'updraftplus'));
1984
- echo __('Could not find one of the files for restoration', 'updraftplus').": ($file)";
1985
- } else {
1986
- echo __("Databases are not yet restored through this mechanism - use your web host's control panel, phpMyAdmin or a similar tool",'updraftplus')."<br>";
1987
- }
1988
- }
1989
- echo '</div>'; //close the updraft_restore_progress div
1990
- # The 'off' check is for badly configured setups - http://wordpress.org/support/topic/plugin-wp-super-cache-warning-php-safe-mode-enabled-but-safe-mode-is-off
1991
- if(@ini_get('safe_mode') && strtolower(@ini_get('safe_mode')) != "off") {
1992
- echo "<p>".__('Database could not be restored because PHP safe_mode is active on your server. You will need to manually restore the file via phpMyAdmin or another method.', 'updraftplus')."</p><br/>";
1993
- return false;
1994
- }
1995
- return true;
1996
- }
1997
-
1998
- //deletes the -old directories that are created when a backup is restored.
1999
- function delete_old_dirs() {
2000
- global $wp_filesystem;
2001
- $credentials = request_filesystem_credentials(wp_nonce_url("options-general.php?page=updraftplus&action=updraft_delete_old_dirs", 'updraft_delete_old_dirs'));
2002
- WP_Filesystem($credentials);
2003
- if ( $wp_filesystem->errors->get_error_code() ) {
2004
- foreach ( $wp_filesystem->errors->get_error_messages() as $message )
2005
- show_message($message);
2006
- exit;
2007
- }
2008
-
2009
- $list = $wp_filesystem->dirlist(WP_CONTENT_DIR);
2010
-
2011
- $return_code = true;
2012
-
2013
- foreach ($list as $item) {
2014
- if (substr($item['name'], -4, 4) == "-old") {
2015
- //recursively delete
2016
- print "<strong>".__('Delete','updraftplus').": </strong>".htmlspecialchars($item['name']).": ";
2017
- if(!$wp_filesystem->delete(WP_CONTENT_DIR.'/'.$item['name'], true)) {
2018
- $return_code = false;
2019
- print "<strong>Failed</strong><br>";
2020
- } else {
2021
- print "<strong>OK</strong><br>";
2022
- }
2023
- }
2024
- }
2025
-
2026
- return $return_code;
2027
- }
2028
-
2029
- //scans the content dir to see if any -old dirs are present
2030
- function scan_old_dirs() {
2031
- $dirArr = scandir(WP_CONTENT_DIR);
2032
- foreach($dirArr as $dir) {
2033
- if(strpos($dir,'-old') !== false) return true;
2034
- }
2035
- return false;
2036
- }
2037
-
2038
-
2039
  function retain_range($input) {
2040
  $input = (int)$input;
2041
- if($input > 0 && $input < 3650) {
2042
- return $input;
2043
- } else {
2044
- return 1;
2045
- }
2046
- }
2047
-
2048
- function create_backup_dir() {
2049
- global $wp_filesystem;
2050
- $credentials = request_filesystem_credentials("options-general.php?page=updraftplus&action=updraft_create_backup_dir");
2051
- WP_Filesystem($credentials);
2052
- if ( $wp_filesystem->errors->get_error_code() ) {
2053
- foreach ( $wp_filesystem->errors->get_error_messages() as $message ) show_message($message);
2054
- exit;
2055
- }
2056
-
2057
- $updraft_dir = $this->backups_dir_location();
2058
- $default_backup_dir = WP_CONTENT_DIR.'/updraft';
2059
- $updraft_dir = ($updraft_dir)?$updraft_dir:$default_backup_dir;
2060
-
2061
- //chmod the backup dir to 0777. ideally we'd rather chgrp it but i'm not sure if it's possible to detect the group apache is running under (or what if it's not apache...)
2062
- if(!$wp_filesystem->mkdir($updraft_dir, 0777)) return false;
2063
-
2064
- return true;
2065
  }
2066
 
2067
  function memory_check_current() {
@@ -2083,45 +1615,14 @@ class UpdraftPlus {
2083
  return $memory_limit;
2084
  }
2085
 
2086
- function disk_space_check($space) {
2087
- $updraft_dir = $this->backups_dir_location();
2088
- $disk_free_space = @disk_free_space($updraft_dir);
2089
- if ($disk_free_space == false) return -1;
2090
- return ($disk_free_space > $space) ? true : false;
2091
- }
2092
-
2093
  function memory_check($memory) {
2094
  $memory_limit = $this->memory_check_current();
2095
  return ($memory_limit >= $memory)?true:false;
2096
  }
2097
 
2098
- function execution_time_check($time) {
2099
- $setting = ini_get('max_execution_time');
2100
- return ( $setting==0 || $setting >= $time) ? true : false;
2101
- }
2102
-
2103
- function admin_init() {
2104
- if(UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
2105
- @ini_set('display_errors',1);
2106
- @error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
2107
- @ini_set('track_errors',1);
2108
- }
2109
- wp_enqueue_script('jquery');
2110
- wp_enqueue_script('jquery-ui-dialog');
2111
-
2112
- if (UpdraftPlus_Options::user_can_manage() && UpdraftPlus_Options::get_updraft_option('updraft_service') == "googledrive" && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_clientid','') != '' && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_token','') == '') {
2113
- add_action('admin_notices', array($this,'show_admin_warning_googledrive') );
2114
- }
2115
-
2116
- if (UpdraftPlus_Options::user_can_manage() && UpdraftPlus_Options::get_updraft_option('updraft_service') == "dropbox" && UpdraftPlus_Options::get_updraft_option('updraft_dropboxtk_request_token','') == '') {
2117
- add_action('admin_notices', array($this,'show_admin_warning_dropbox') );
2118
- }
2119
-
2120
- if (UpdraftPlus_Options::user_can_manage() && $this->disk_space_check(1024*1024*35) === false) add_action('admin_notices', array($this, 'show_admin_warning_diskspace'));
2121
-
2122
- global $wp_version, $pagenow;
2123
- if ($pagenow == 'options-general.php' && version_compare($wp_version, '3.2', '<')) add_action('admin_notices', array($this, 'show_admin_warning_wordpressversion'));
2124
-
2125
  }
2126
 
2127
  function url_start($urls,$url) {
@@ -2172,1065 +1673,19 @@ class UpdraftPlus {
2172
  }
2173
  }
2174
 
2175
- function settings_formcontents($last_backup_html) {
2176
- $updraft_dir = $this->backups_dir_location();
2177
-
2178
- ?>
2179
- <table class="form-table" style="width:900px;">
2180
- <tr>
2181
- <th><?php _e('File backup intervals','updraftplus'); ?>:</th>
2182
- <td><select name="updraft_interval">
2183
- <?php
2184
- $intervals = array ("manual" => _x("Manual",'i.e. Non-automatic','updraftplus'), 'every4hours' => __("Every 4 hours",'updraftplus'), 'every8hours' => __("Every 8 hours",'updraftplus'), 'twicedaily' => __("Every 12 hours",'updraftplus'), 'daily' => __("Daily",'updraftplus'), 'weekly' => __("Weekly",'updraftplus'), 'fortnightly' => __("Fortnightly",'updraftplus'), 'monthly' => __("Monthly",'updraftplus'));
2185
- foreach ($intervals as $cronsched => $descrip) {
2186
- echo "<option value=\"$cronsched\" ";
2187
- if ($cronsched == UpdraftPlus_Options::get_updraft_option('updraft_interval','manual')) echo 'selected="selected"';
2188
- echo ">$descrip</option>\n";
2189
- }
2190
- ?>
2191
- </select> <?php echo apply_filters('updraftplus_schedule_showfileconfig', '<input type="hidden" name="updraftplus_starttime_files" value="">'); ?>
2192
- <?php
2193
- echo __('and retain this many backups', 'updraftplus').': ';
2194
- $updraft_retain = UpdraftPlus_Options::get_updraft_option('updraft_retain', 1);
2195
- $updraft_retain = ((int)$updraft_retain > 0) ? (int)$updraft_retain : 1;
2196
- ?> <input type="text" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:40px;" />
2197
- </td>
2198
- </tr>
2199
- <tr>
2200
- <th><?php _e('Database backup intervals','updraftplus'); ?>:</th>
2201
- <td><select name="updraft_interval_database">
2202
- <?php
2203
- foreach ($intervals as $cronsched => $descrip) {
2204
- echo "<option value=\"$cronsched\" ";
2205
- if ($cronsched == UpdraftPlus_Options::get_updraft_option('updraft_interval_database', UpdraftPlus_Options::get_updraft_option('updraft_interval'))) echo 'selected="selected"';
2206
- echo ">$descrip</option>\n";
2207
- }
2208
- ?>
2209
- </select> <?php echo apply_filters('updraftplus_schedule_showdbconfig', '<input type="hidden" name="updraftplus_starttime_db" value="">'); ?>
2210
- <?php
2211
- echo __('and retain this many backups', 'updraftplus').': ';
2212
- $updraft_retain_db = UpdraftPlus_Options::get_updraft_option('updraft_retain_db', $updraft_retain);
2213
- $updraft_retain_db = ((int)$updraft_retain_db > 0) ? (int)$updraft_retain_db : 1;
2214
- ?> <input type="text" name="updraft_retain_db" value="<?php echo $updraft_retain_db ?>" style="width:40px" />
2215
- </td>
2216
- </tr>
2217
- <tr class="backup-interval-description">
2218
- <td></td><td><p><?php echo htmlspecialchars(__('If you would like to automatically schedule backups, choose schedules from the dropdowns above. Backups will occur at the intervals specified. If the two schedules are the same, then the two backups will take place together. If you choose "manual" then you must click the "Backup Now" button whenever you wish a backup to occur.', 'updraftplus')); ?></p>
2219
- <?php echo apply_filters('updraftplus_fixtime_advert', '<p><strong>'.__('To fix the time at which a backup should take place,','updraftplus').' </strong> ('.__('e.g. if your server is busy at day and you want to run overnight','updraftplus').'), <a href="http://updraftplus.com/shop/fix-time/">'.htmlspecialchars(__('use the "Fix Time" add-on','updraftplus')).'</a></p>'); ?>
2220
- </td>
2221
- </tr>
2222
- <tr>
2223
- <th>Include in files backup:</th>
2224
- <td>
2225
-
2226
- <?php
2227
- $backupable_entities = $this->get_backupable_file_entities(true, true);
2228
- $include_others_exclude = UpdraftPlus_Options::get_updraft_option('updraft_include_others_exclude',UPDRAFT_DEFAULT_OTHERS_EXCLUDE);
2229
- # The true (default value if non-existent) here has the effect of forcing a default of on.
2230
- foreach ($backupable_entities as $key => $info) {
2231
- $included = (UpdraftPlus_Options::get_updraft_option("updraft_include_$key",true)) ? 'checked="checked"' : "";
2232
- if ('others' == $key) {
2233
- ?><input id="updraft_include_others" type="checkbox" name="updraft_include_others" value="1" <?php echo $included; ?> /> <label for="updraft_include_<?php echo $key ?>"><?php echo __('Any other directories found inside wp-content but exclude these directories:', 'updraftplus');?></label> <input type="text" name="updraft_include_others_exclude" size="44" value="<?php echo htmlspecialchars($include_others_exclude); ?>"/><br><?php
2234
- } else {
2235
- echo "<input id=\"updraft_include_$key\" type=\"checkbox\" name=\"updraft_include_$key\" value=\"1\" $included /><label for=\"updraft_include_$key\">".$info['description']."</label><br>";
2236
- }
2237
- }
2238
- ?>
2239
- <p><?php echo __('Include all of these, unless you are backing them up outside of UpdraftPlus. The above directories are usually everything (except for WordPress core itself which you can download afresh from WordPress.org). But if you have made customised modifications outside of these directories, you need to back them up another way.', 'updraftplus') ?> (<a href="http://wordshell.net"><?php echo __('Use WordShell for automatic backup, version control and patching', 'updraftplus');?></a>).</p></td>
2240
- </td>
2241
- </tr>
2242
- <tr>
2243
- <th><?php _e('Email','updraftplus'); ?>:</th>
2244
- <td><input type="text" style="width:260px" name="updraft_email" value="<?php echo UpdraftPlus_Options::get_updraft_option('updraft_email'); ?>" /> <br><?php _e('Enter an address here to have a report sent (and the whole backup, if you choose) to it.','updraftplus'); ?></td>
2245
- </tr>
2246
-
2247
- <tr>
2248
- <th><?php _e('Database encryption phrase','updraftplus');?>:</th>
2249
- <?php
2250
- $updraft_encryptionphrase = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
2251
- ?>
2252
- <td><input type="text" name="updraft_encryptionphrase" value="<?php echo $updraft_encryptionphrase ?>" style="width:132px" /></td>
2253
- </tr>
2254
- <tr class="backup-crypt-description">
2255
- <td></td><td><?php _e('If you enter text here, it is used to encrypt backups (Rijndael). <strong>Do make a separate record of it and do not lose it, or all your backups <em>will</em> be useless.</strong> Presently, only the database file is encrypted. This is also the key used to decrypt backups from this admin interface (so if you change it, then automatic decryption will not work until you change it back). You can also use the file example-decrypt.php from inside the UpdraftPlus plugin directory to decrypt manually.','updraftplus');?></td>
2256
- </tr>
2257
- </table>
2258
-
2259
- <h2><?php _e('Copying Your Backup To Remote Storage','updraftplus');?></h2>
2260
-
2261
- <table class="form-table" style="width:900px;">
2262
- <tr>
2263
- <th><?php _e('Choose your remote storage','updraftplus');?>:</th>
2264
- <td><select name="updraft_service" id="updraft-service">
2265
- <?php
2266
- $debug_mode = (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) ? 'checked="checked"' : "";
2267
-
2268
- $set = 'selected="selected"';
2269
-
2270
- // Should be one of s3, dropbox, ftp, googledrive, email, or whatever else is added
2271
- $active_service = UpdraftPlus_Options::get_updraft_option('updraft_service');
2272
-
2273
- ?>
2274
- <option value="none" <?php
2275
- if ($active_service == "none") echo $set; ?>>None</option>
2276
- <?php
2277
- foreach ($this->backup_methods as $method => $description) {
2278
- echo "<option value=\"$method\"";
2279
- if ($active_service == $method) echo ' '.$set;
2280
- echo '>'.$description;
2281
- echo "</option>\n";
2282
- }
2283
- ?>
2284
- </select></td>
2285
- </tr>
2286
- <?php
2287
- foreach ($this->backup_methods as $method => $description) {
2288
- require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
2289
- $call_method = "UpdraftPlus_BackupModule_$method";
2290
- call_user_func(array($call_method, 'config_print'));
2291
- }
2292
- ?>
2293
- </table>
2294
- <script type="text/javascript">
2295
- /* <![CDATA[ */
2296
- var lastlog_lastmessage = "";
2297
- var lastlog_sdata = {
2298
- action: 'updraft_ajax',
2299
- subaction: 'lastlog',
2300
- nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
2301
- };
2302
- function updraft_showlastlog(){
2303
- jQuery.get(ajaxurl, lastlog_sdata, function(response) {
2304
- nexttimer = 1500;
2305
- if (lastlog_lastmessage == response) { nexttimer = 4500; }
2306
- setTimeout(function(){updraft_showlastlog()}, nexttimer);
2307
- jQuery('#updraft_lastlogcontainer').html(response);
2308
- lastlog_lastmessage = response;
2309
- });
2310
- }
2311
- var lastbackup_sdata = {
2312
- action: 'updraft_ajax',
2313
- subaction: 'lastbackup',
2314
- nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
2315
- };
2316
- var lastbackup_laststatus = '<?php echo $last_backup_html?>'
2317
- function updraft_showlastbackup(){
2318
- jQuery.get(ajaxurl, lastbackup_sdata, function(response) {
2319
- if (lastbackup_laststatus == response) {
2320
- setTimeout(function(){updraft_showlastbackup()}, 7000);
2321
- } else {
2322
- jQuery('#updraft_last_backup').html(response);
2323
- }
2324
- lastbackup_laststatus = response;
2325
- });
2326
- }
2327
- var updraft_historytimer = 0;
2328
- var calculated_diskspace = 0;
2329
- function updraft_historytimertoggle(forceon) {
2330
- if (!updraft_historytimer || forceon == 1) {
2331
- updraft_updatehistory(0);
2332
- updraft_historytimer = setInterval(function(){updraft_updatehistory(0)}, 30000);
2333
- if (!calculated_diskspace) {
2334
- updraftplus_diskspace();
2335
- calculated_diskspace=1;
2336
- }
2337
- } else {
2338
- clearTimeout(updraft_historytimer);
2339
- updraft_historytimer = 0;
2340
- }
2341
- }
2342
- function updraft_updatehistory(rescan) {
2343
- if (rescan == 1) {
2344
- jQuery('#updraft_existing_backups').html('<p style="text-align:center;"><em>Rescanning (looking for backups that you have uploaded manually into the internal backup store)...</em></p>');
2345
- }
2346
- jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'historystatus', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>', rescan: rescan }, function(response) {
2347
- jQuery('#updraft_existing_backups').html(response);
2348
- });
2349
- }
2350
-
2351
- jQuery(document).ready(function() {
2352
- jQuery( "#updraft-restore-modal" ).dialog({
2353
- autoOpen: false, height: 385, width: 480, modal: true,
2354
- buttons: {
2355
- Restore: function() {
2356
- var anyselected = 0;
2357
- jQuery('input[name="updraft_restore[]"]').each(function(x,y){
2358
- if (jQuery(y).is(':checked')) {
2359
- anyselected = 1;
2360
- //alert(jQuery(y).val());
2361
- }
2362
- });
2363
- if (anyselected == 1) {
2364
- jQuery('#updraft_restore_form').submit();
2365
- } else {
2366
- alert('You did not select any components to restore. Please select at least one, and then try again.');
2367
- }
2368
- },
2369
- <?php _e('Cancel','updraftplus');?>: function() { jQuery(this).dialog("close"); }
2370
- }
2371
- });
2372
-
2373
- jQuery( "#updraft-backupnow-modal" ).dialog({
2374
- autoOpen: false, height: 265, width: 375, modal: true,
2375
- buttons: {
2376
- '<?php _e('Backup Now','updraftplus');?>': function() {
2377
- jQuery('#updraft-backupnow-form').submit();
2378
- },
2379
- <?php _e('Cancel','updraftplus');?>: function() { jQuery(this).dialog("close"); }
2380
- }
2381
- });
2382
-
2383
- jQuery('#enableexpertmode').click(function() {
2384
- jQuery('.expertmode').fadeIn();
2385
- return false;
2386
- });
2387
- <?php if (!@is_writable($updraft_dir)) echo "jQuery('.backupdirrow').show();\n"; ?>
2388
- setTimeout(function(){updraft_showlastlog();}, 1200);
2389
- jQuery('.updraftplusmethod').hide();
2390
- <?php
2391
- if ($active_service) echo "jQuery('.${active_service}').show();";
2392
- foreach ($this->backup_methods as $method => $description) {
2393
- // already done: require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
2394
- $call_method = "UpdraftPlus_BackupModule_$method";
2395
- if (method_exists($call_method, 'config_print_javascript_onready')) call_user_func(array($call_method, 'config_print_javascript_onready'));
2396
- }
2397
- ?>
2398
- });
2399
- /* ]]> */
2400
- </script>
2401
- <table class="form-table" style="width:900px;">
2402
- <tr>
2403
- <td colspan="2"><h2><?php _e('Advanced / Debugging Settings','updraftplus'); ?></h2></td>
2404
- </tr>
2405
- <tr>
2406
- <th><?php _e('Debug mode','updraftplus');?>:</th>
2407
- <td><input type="checkbox" id="updraft_debug_mode" name="updraft_debug_mode" value="1" <?php echo $debug_mode; ?> /> <br><label for="updraft_debug_mode"><?php _e('Check this to receive more information and emails on the backup process - useful if something is going wrong. You <strong>must</strong> send us this log if you are filing a bug report.','updraftplus');?></label></td>
2408
- </tr>
2409
- <tr>
2410
- <th><?php _e('Expert settings','updraftplus');?>:</th>
2411
- <td><a id="enableexpertmode" href="#"><?php _e('Show expert settings','updraftplus');?></a> - <?php _e("click this to show some further options; don't bother with this unless you have a problem or are curious.",'updraftplus');?></td>
2412
- </tr>
2413
- <?php
2414
- $delete_local = UpdraftPlus_Options::get_updraft_option('updraft_delete_local', 1);
2415
- ?>
2416
-
2417
- <tr class="deletelocal expertmode" style="display:none;">
2418
- <th><?php _e('Delete local backup','updraftplus');?>:</th>
2419
- <td><input type="checkbox" id="updraft_delete_local" name="updraft_delete_local" value="1" <?php if ($delete_local) echo 'checked="checked"'; ?>> <br><label for="updraft_delete_local"><?php _e('Uncheck this to prevent deletion of any superfluous backup files from your server after the backup run finishes (i.e. any files despatched remotely will also remain locally, and any files being kept locally will not be subject to the retention limits).','updraftplus');?></label></td>
2420
- </tr>
2421
-
2422
- <tr class="expertmode backupdirrow" style="display:none;">
2423
- <th>Backup directory:</th>
2424
- <td><input type="text" name="updraft_dir" id="updraft_dir" style="width:525px" value="<?php echo htmlspecialchars($this->prune_updraft_dir_prefix($updraft_dir)); ?>" /></td>
2425
- </tr>
2426
- <tr class="expertmode backupdirrow" style="display:none;">
2427
- <td></td><td><?php
2428
-
2429
- // Suppress warnings, since if the user is dumping warnings to screen, then invalid JavaScript results and the screen breaks.
2430
- if(@is_writable($updraft_dir)) {
2431
- $dir_info = '<span style="color:green">'.__('Backup directory specified is writable, which is good.','updraftplus').'</span>';
2432
- } else {
2433
- $dir_info = '<span style="color:red">'.__('Backup directory specified is <b>not</b> writable, or does not exist.','updraftplus').' <span style="font-size:110%;font-weight:bold"><a href="options-general.php?page=updraftplus&action=updraft_create_backup_dir">'.__('Click here to attempt to create the directory and set the permissions','updraftplus').'</a></span>, '.__('or, to reset this option','updraftplus').' <a href="#" onclick="jQuery(\'#updraft_dir\').val(\''.WP_CONTENT_DIR.'/updraft\'); return false;">'.__('click here','updraftplus').'</a>. '.__('If that is unsuccessful check the permissions on your server or change it to another directory that is writable by your web server process.','updraftplus').'</span>';
2434
- }
2435
-
2436
- echo $dir_info.' '.__("This is where UpdraftPlus will write the zip files it creates initially. This directory must be writable by your web server. Typically you'll want to have it inside your wp-content folder (this is the default). <b>Do not</b> place it inside your uploads dir, as that will cause recursion issues (backups of backups of backups of...).",'updraftplus');?></td>
2437
- </tr>
2438
- <tr>
2439
- <td></td>
2440
- <td>
2441
- <?php
2442
- $ws_ad = $this->wordshell_random_advert(1);
2443
- if ($ws_ad) {
2444
- ?>
2445
- <p style="margin: 10px 0; padding: 10px; font-size: 140%; background-color: lightYellow; border-color: #E6DB55; border: 1px solid; border-radius: 4px;">
2446
- <?php echo $ws_ad; ?>
2447
- </p>
2448
- <?php
2449
- }
2450
- ?>
2451
- </td>
2452
- </tr>
2453
- <tr>
2454
- <td></td>
2455
- <td>
2456
- <input type="hidden" name="action" value="update" />
2457
- <input type="submit" class="button-primary" value="<?php _e('Save Changes','updraftplus');?>" />
2458
- </td>
2459
- </tr>
2460
- </table>
2461
- <?php
2462
- }
2463
-
2464
- function last_backup_html() {
2465
-
2466
- $updraft_last_backup = UpdraftPlus_Options::get_updraft_option('updraft_last_backup');
2467
-
2468
- $updraft_dir = $this->backups_dir_location();
2469
-
2470
- if($updraft_last_backup) {
2471
-
2472
- if ($updraft_last_backup['success']) {
2473
- // Convert to GMT, then to blog time
2474
- $last_backup_text = get_date_from_gmt(gmdate('Y-m-d H:i:s', $updraft_last_backup['backup_time']), 'D, F j, Y H:i T');
2475
- } else {
2476
- $last_backup_text = implode("<br>",$updraft_last_backup['errors']);
2477
- }
2478
-
2479
- if (!empty($updraft_last_backup['backup_nonce'])) {
2480
- $potential_log_file = $updraft_dir."/log.".$updraft_last_backup['backup_nonce'].".txt";
2481
- if (is_readable($potential_log_file)) $last_backup_text .= "<br><a href=\"?page=updraftplus&action=downloadlog&updraftplus_backup_nonce=".$updraft_last_backup['backup_nonce']."\">".__('Download log file','updraftplus')."</a>";
2482
- }
2483
-
2484
- $last_backup_color = ($updraft_last_backup['success']) ? 'green' : 'red';
2485
-
2486
- } else {
2487
- $last_backup_text = __('No backup has been completed.','updraftplus');
2488
- $last_backup_color = 'blue';
2489
- }
2490
-
2491
- return "<span style=\"color:${last_backup_color}\">${last_backup_text}</span>";
2492
-
2493
- }
2494
-
2495
- function settings_output() {
2496
-
2497
- wp_enqueue_style('jquery-ui', UPDRAFTPLUS_URL.'/includes/jquery-ui-1.8.22.custom.css');
2498
-
2499
- /*
2500
- we use request here because the initial restore is triggered by a POSTed form. we then may need to obtain credentials
2501
- for the WP_Filesystem. to do this WP outputs a form that we can't insert variables into (apparently). So the values are
2502
- passed back in as GET parameters. REQUEST covers both GET and POST so this weird logic works.
2503
- */
2504
- if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_restore' && isset($_REQUEST['backup_timestamp'])) {
2505
- $backup_success = $this->restore_backup($_REQUEST['backup_timestamp']);
2506
- if(empty($this->errors) && $backup_success == true) {
2507
- echo '<p><strong>'.__('Restore successful!','updraftplus').'</strong></p>';
2508
- echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus&updraft_restore_success=true">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
2509
- return;
2510
- } else {
2511
- echo '<p>Restore failed...</p><ul style="list-style: disc inside;">';
2512
- foreach ($this->errors as $err) {
2513
- if (is_wp_error($err)) {
2514
- foreach ($err->get_error_messages() as $msg) {
2515
- echo '<li>'.htmlspecialchars($msg).'<li>';
2516
- }
2517
- } elseif (is_string($err)) {
2518
- echo "<li>".htmlspecialchars($err)."</li>";
2519
- } else {
2520
- print "<li>".print_r($err,true)."</li>";
2521
- }
2522
- }
2523
- echo '</ul><b>Actions:</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
2524
- return;
2525
- }
2526
- //uncomment the below once i figure out how i want the flow of a restoration to work.
2527
- //echo '<b>'__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">Return to UpdraftPlus Configuration</a>';
2528
- }
2529
- $deleted_old_dirs = false;
2530
- if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_delete_old_dirs') {
2531
-
2532
- echo '<h1>UpdraftPlus - '.__('Remove old directories','updraftplus').'</h1>';
2533
-
2534
- $nonce = (empty($_REQUEST['_wpnonce'])) ? "" : $_REQUEST['_wpnonce'];
2535
- if (!wp_verify_nonce($nonce, 'updraft_delete_old_dirs')) die('Security check');
2536
-
2537
- if($this->delete_old_dirs()) {
2538
- echo '<p>'.__('Old directories successfully removed.','updraftplus').'</p><br/>';
2539
- $deleted_old_dirs = true;
2540
- } else {
2541
- echo '<p>',__('Old directory removal failed for some reason. You may want to do this manually.','updraftplus').'</p><br/>';
2542
- }
2543
- echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
2544
- return;
2545
- }
2546
-
2547
- if(isset($_GET['error'])) {
2548
- $this->show_admin_warning(htmlspecialchars($_GET['error']), 'error');
2549
- }
2550
- if(isset($_GET['message'])) {
2551
- $this->show_admin_warning(htmlspecialchars($_GET['message']));
2552
- }
2553
-
2554
- if(isset($_GET['action']) && $_GET['action'] == 'updraft_create_backup_dir') {
2555
- if(!$this->create_backup_dir()) {
2556
- echo '<p>'.__('Backup directory could not be created','updraftplus').'...</p><br/>';
2557
- }
2558
- echo '<p>'.__('Backup directory successfully created.','updraftplus').'</p><br/>';
2559
- echo '<b>'.__('Actions','updraftplus').':</b> <a href="options-general.php?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
2560
- return;
2561
- }
2562
-
2563
- if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup') {
2564
- // For unknown reasons, the <script> runs twice if put inside the <div>
2565
- echo '<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;"><strong>',__('Schedule backup','updraftplus').':</strong> ';
2566
- if (wp_schedule_single_event(time()+5, 'updraft_backup_all') === false) {
2567
- $this->log("A backup run failed to schedule");
2568
- echo __("Failed.",'updraftplus')."</div>";
2569
- } else {
2570
- echo htmlspecialchars(__('OK. Now load any page from your site to make sure the schedule can trigger. You should then see activity in the "Last log message" field below.','updraftplus'))." <a href=\"http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/\">".__('Nothing happening? Follow this link for help.','updraftplus')."</a></div><script>setTimeout(function(){updraft_showlastbackup();}, 7000);</script>";
2571
- $this->log("A backup run has been scheduled");
2572
- }
2573
- }
2574
-
2575
- // updraft_file_ids is not deleted
2576
- if(isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_all') { $this->boot_backup(true,true); }
2577
- elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_backup_debug_db') { $this->backup_db(); }
2578
- elseif (isset($_POST['action']) && $_POST['action'] == 'updraft_wipesettings') {
2579
- $settings = array('updraft_interval', 'updraft_interval_database', 'updraft_retain', 'updraft_retain_db', 'updraft_encryptionphrase', 'updraft_service', 'updraft_dropbox_appkey', 'updraft_dropbox_secret', 'updraft_googledrive_clientid', 'updraft_googledrive_secret', 'updraft_googledrive_remotepath', 'updraft_ftp_login', 'updraft_ftp_pass', 'updraft_ftp_remote_path', 'updraft_server_address', 'updraft_dir', 'updraft_email', 'updraft_delete_local', 'updraft_debug_mode', 'updraft_include_plugins', 'updraft_include_themes', 'updraft_include_uploads', 'updraft_include_others', 'updraft_include_blogs', 'updraft_include_mu-plugins', 'updraft_include_others_exclude', 'updraft_lastmessage', 'updraft_googledrive_clientid', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder', 'updraft_last_backup', 'updraft_starttime_files', 'updraft_starttime_db', 'updraft_sftp_settings');
2580
- foreach ($settings as $s) {
2581
- UpdraftPlus_Options::delete_updraft_option($s);
2582
- }
2583
- $this->show_admin_warning(__("Your settings have been wiped.",'updraftplus'));
2584
- }
2585
-
2586
- ?>
2587
- <div class="wrap">
2588
- <h1><?php echo $this->plugin_title; ?></h1>
2589
-
2590
- <?php _e('By UpdraftPlus.Com','updraftplus')?> ( <a href="http://updraftplus.com">UpdraftPlus.Com</a> | <a href="http://david.dw-perspective.org.uk"><?php _e("Lead developer's homepage",'updraftplus');?></a> | <?php if (!defined('UPDRAFTPLUS_NOADS')) { ?><a href="http://wordshell.net">WordShell - WordPress command line</a> | <a href="http://david.dw-perspective.org.uk/donate"><?php _e('Donate','updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/frequently-asked-questions/">FAQs</a> | <a href="http://profiles.wordpress.org/davidanderson/"><?php _e('Other WordPress plugins','updraftplus');?></a>). <?php _e('Version','updraftplus');?>: <?php echo $this->version; ?>
2591
- <br>
2592
- <?php
2593
- if(isset($_GET['updraft_restore_success'])) {
2594
- echo "<div class=\"updated fade\" style=\"padding:8px;\"><strong>".__('Your backup has been restored.','updraftplus').'</strong> '.__('Your old (themes, uploads, plugins, whatever) directories have been retained with "-old" appended to their name. Remove them when you are satisfied that the backup worked properly.').' '.__('At this time UpdraftPlus does not automatically restore your database. You will need to use an external tool like phpMyAdmin to perform that task.','updraftplus')."</div>";
2595
- }
2596
-
2597
- $ws_advert = $this->wordshell_random_advert(1);
2598
- if ($ws_advert) { echo '<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;">'.$ws_advert.'</div>'; }
2599
-
2600
- if($deleted_old_dirs) echo '<div style="color:blue" class=\"updated fade\">'.__('Old directories successfully deleted.','updraftplus').'</div>';
2601
-
2602
- if(!$this->memory_check(96)) {?>
2603
- <div style="color:orange"><?php _e("Your PHP memory limit is quite low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may not work properly with a memory limit of less than 96 Mb (though on the other hand, it has been used successfully with a 32Mb limit - your mileage may vary, but don't blame us!).",'updraftplus');?> <?php _e('Current limit is:','updraftplus');?> <?php echo $this->memory_check_current(); ?> Mb</div>
2604
- <?php
2605
- }
2606
- if(1==0 && !$this->execution_time_check(60)) {?>
2607
- <div style="color:orange"><?php _e("Your PHP max_execution_time is less than 60 seconds. This possibly means you're running in safe_mode. Either disable safe_mode or modify your php.ini to set max_execution_time to a higher number. If you do not, then longer will be needed to complete a backup (but that is all). Present limit is:",'updraftplus');?> <?php echo ini_get('max_execution_time').' '.__('seconds','updraftplus')?>.</div>
2608
- <?php
2609
- }
2610
-
2611
- if($this->scan_old_dirs()) {?>
2612
- <div class="updated fade" style="padding:8px;"><?php _e('You have old directories from a previous backup (technical information: these are found in wp-content, and suffixed with -old). Use this button to delete them (if you have verified that the restoration worked).','updraftplus');?>
2613
- <form method="post" action="<?php echo remove_query_arg(array('updraft_restore_success','action')) ?>">
2614
- <?php wp_nonce_field('updraft_delete_old_dirs'); ?>
2615
- <input type="hidden" name="action" value="updraft_delete_old_dirs" />
2616
- <input type="submit" class="button-primary" value="<?php _e('Delete Old Directories','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('Are you sure you want to delete the old directories? This cannot be undone.','updraftplus'));?>'))" />
2617
- </form>
2618
- </div>
2619
- <?php
2620
- }
2621
- if(!empty($this->errors)) {
2622
- foreach($this->errors as $error) {
2623
- // ignoring severity
2624
- echo '<div style="color:red">'.$error['error'].'</div>';
2625
- }
2626
- }
2627
- ?>
2628
-
2629
- <h2 style="clear:left;"><?php _e('Existing Schedule And Backups','updraftplus');?></h2>
2630
- <table class="form-table" style="float:left; clear: both; width:545px;">
2631
- <noscript>
2632
- <tr>
2633
- <th><?php _e('JavaScript warning','updraftplus');?>:</th>
2634
- <td style="color:red"><?php _e('This admin interface uses JavaScript heavily. You either need to activate it within your browser, or to use a JavaScript-capable browser.','updraftplus');?></td>
2635
- </tr>
2636
- </noscript>
2637
- <?php
2638
- $updraft_dir = $this->backups_dir_location();
2639
- // UNIX timestamp
2640
- $next_scheduled_backup = wp_next_scheduled('updraft_backup');
2641
- if ($next_scheduled_backup) {
2642
- // Convert to GMT
2643
- $next_scheduled_backup_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup);
2644
- // Convert to blog time zone
2645
- $next_scheduled_backup = get_date_from_gmt($next_scheduled_backup_gmt, 'D, F j, Y H:i T');
2646
- } else {
2647
- $next_scheduled_backup = __('Nothing currently scheduled','updraftplus');
2648
- }
2649
-
2650
- $next_scheduled_backup_database = wp_next_scheduled('updraft_backup_database');
2651
- if (UpdraftPlus_Options::get_updraft_option('updraft_interval_database',UpdraftPlus_Options::get_updraft_option('updraft_interval')) == UpdraftPlus_Options::get_updraft_option('updraft_interval')) {
2652
- $next_scheduled_backup_database = ('Nothing currently scheduled' == $next_scheduled_backup) ? $next_scheduled_backup : __("At the same time as the files backup", 'updraftplus');
2653
- } else {
2654
- if ($next_scheduled_backup_database) {
2655
- // Convert to GMT
2656
- $next_scheduled_backup_database_gmt = gmdate('Y-m-d H:i:s', $next_scheduled_backup_database);
2657
- // Convert to blog time zone
2658
- $next_scheduled_backup_database = get_date_from_gmt($next_scheduled_backup_database_gmt, 'D, F j, Y H:i T');
2659
- } else {
2660
- $next_scheduled_backup_database = __('Nothing currently scheduled','updraftplus');
2661
- }
2662
- }
2663
- $current_time = get_date_from_gmt(gmdate('Y-m-d H:i:s'), 'D, F j, Y H:i T');
2664
-
2665
- $backup_disabled = (is_writable($updraft_dir)) ? '' : 'disabled="disabled"';
2666
-
2667
- $last_backup_html = $this->last_backup_html();
2668
-
2669
- ?>
2670
-
2671
- <tr>
2672
- <th><?php _e('Next scheduled backups','updraftplus');?>:</th>
2673
- <td>
2674
- <div style="width: 76px; float:left;">Files:</div><div style="color:blue; float:left;"><?php echo $next_scheduled_backup?></div>
2675
- <div style="width: 76px; clear: left; float:left;"><?php _e('Database','updraftplus');?>: </div><div style="color:blue; float:left;"><?php echo $next_scheduled_backup_database?></div>
2676
- <div style="width: 76px; clear: left; float:left;"><?php _e('Time now','updraftplus');?>: </div><div style="color:blue; float:left;"><?php echo $current_time?></div>
2677
- </td>
2678
- </tr>
2679
- <tr>
2680
- <th><?php _e('Last finished backup run','updraftplus');?>:</th>
2681
- <td id="updraft_last_backup"><?php echo $last_backup_html ?></td>
2682
- </tr>
2683
- </table>
2684
- <div style="float:left; width:200px; padding-top: 20px;">
2685
- <p><button type="button" <?php echo $backup_disabled ?> class="button-primary" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px;" onclick="jQuery('#updraft-backupnow-modal').dialog('open');"><?php _e('Backup Now','updraftplus');?></button></p>
2686
- <div style="position:relative">
2687
- <div style="position:absolute;top:0;left:0">
2688
- <?php
2689
- $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
2690
- $backup_history = (is_array($backup_history))?$backup_history:array();
2691
- $backup_history_sets = (count($backup_history) == 1) ? 'set' : 'sets';
2692
- $restore_disabled = (count($backup_history) == 0) ? 'disabled="disabled"' : "";
2693
- ?>
2694
- <input type="button" class="button-primary" <?php echo $restore_disabled ?> value="<?php _e('Restore','updraftplus');?>" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px;" onclick="jQuery('.download-backups').slideDown(); updraft_historytimertoggle(1); jQuery('html,body').animate({scrollTop: jQuery('#updraft_lastlogcontainer').offset().top},'slow');">
2695
- </div>
2696
- </div>
2697
- </div>
2698
- <br style="clear:both" />
2699
- <table class="form-table">
2700
- <tr>
2701
- <th>Last log message:</th>
2702
- <td id="updraft_lastlogcontainer"><?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_lastmessage', '(Nothing yet logged)')); ?></td>
2703
- </tr>
2704
- <tr>
2705
- <th>Backups, logs &amp; restoring:</th>
2706
- <td><a id="updraft_showbackups" href="#" title="<?php _e('Press to see available backups','updraftplus');?>" onclick="jQuery('.download-backups').toggle(); updraft_historytimertoggle(0);"><?php echo count($backup_history).' '.$backup_history_sets; ?> available</a></td>
2707
- </tr>
2708
- <tr>
2709
- <td></td><td class="download-backups" style="display:none; border: 1px dotted;">
2710
- <p style="max-width: 740px;"><ul style="list-style: disc inside;">
2711
- <li><strong><?php _e('Downloading','updraftplus');?>:</strong> <?php _e("Pressing a button for Database/Plugins/Themes/Uploads/Others will make UpdraftPlus try to bring the backup file back from the remote storage (if any - e.g. Amazon S3, Dropbox, Google Drive, FTP) to your webserver. Then you will be allowed to download it to your computer. If the fetch from the remote storage stops progressing (wait 30 seconds to make sure), then press again to resume. Remember that you can also visit the cloud storage vendor's website directly.",'updraftplus');?></li>
2712
- <li><strong><?php _e('Restoring','updraftplus');?>:</strong> <?php _e("Press the button for the backup you wish to restore. If your site is large and you are using remote storage, then you should first click on each entity in order to retrieve it back to the webserver. This will prevent time-outs from occuring during the restore process itself.",'updraftplus');?></li>
2713
- <li><strong><?php _e('Opera web browser','updraftplus');?>:</strong> <?php _e('If you are using this, then turn Turbo/Road mode off.','updraftplus');?></li>
2714
- <li title="<?php _e('This is a count of the contents of your Updraft directory','updraftplus');?>"><strong><?php _e('Web-server disk space in use by UpdraftPlus','updraftplus');?>:</strong> <span id="updraft_diskspaceused"><em>(calculating...)</em></span> <a href="#" onclick="updraftplus_diskspace(); return false;"><?php _e('refresh','updraftplus');?></a> | <a href="#" onclick="updraft_updatehistory(1); return false;" title="<?php _e('Press here to look inside your UpdraftPlus directory (in your web hosting space) for any new backup sets that you have uploaded. The location of this directory is set in the expert settings, below.','updraftplus'); ?>"><?php _e('rescan folder for new backup sets','updraftplus');?></a></li></ul>
2715
- <div id="ud_downloadstatus"></div>
2716
- <script>
2717
- function updraftplus_diskspace() {
2718
- jQuery('#updraft_diskspaceused').html('<em><?php _e('calculating...','updraftplus');?></em>');
2719
- jQuery.get(ajaxurl, { action: 'updraft_ajax', subaction: 'diskspaceused', nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>' }, function(response) {
2720
- jQuery('#updraft_diskspaceused').html(response);
2721
- });
2722
- }
2723
- var lastlog_lastmessage = "";
2724
- function updraftplus_deletefromserver(timestamp, type) {
2725
- var pdata = {
2726
- action: 'updraft_download_backup',
2727
- stage: 'delete',
2728
- timestamp: timestamp,
2729
- type: type,
2730
- _wpnonce: '<?php echo wp_create_nonce("updraftplus_download"); ?>'
2731
- };
2732
- jQuery.post(ajaxurl, pdata, function(response) {
2733
- if (response == 'deleted') {
2734
-
2735
- } else {
2736
- alert('We requested to delete the file, but could not understand the server\'s response '+response);
2737
- }
2738
- });
2739
- }
2740
- function updraftplus_downloadstage2(timestamp, type) {
2741
- location.href=ajaxurl+'?_wpnonce=<?php echo wp_create_nonce("updraftplus_download"); ?>&timestamp='+timestamp+'&type='+type+'&stage=2&action=updraft_download_backup';
2742
- }
2743
- function updraft_downloader(nonce, what) {
2744
- // Create somewhere for the status to be found
2745
- var stid = 'uddlstatus_'+nonce+'_'+what;
2746
- if (!jQuery('#'+stid).length) {
2747
- jQuery('#ud_downloadstatus').append('<div style="clear:left; border: 1px dashed; padding: 8px; margin-top: 4px; max-width:840px;" id="'+stid+'"><button onclick="jQuery(\'#'+stid+'\').fadeOut().remove();" type="button" style="float:right;">X</button><strong>Download '+what+' ('+nonce+')</strong>: <span id="'+stid+'_st">Begun looking for this entity</span></div>');
2748
- setTimeout(function(){updraft_downloader_status(nonce, what)}, 200);
2749
- }
2750
- // Reset, in case this is a re-try
2751
- jQuery('#'+stid+'_st').html('Begun looking for this entity');
2752
- // Now send the actual request to kick it all off
2753
- jQuery.post(ajaxurl, jQuery('#uddownloadform_'+what+'_'+nonce).serialize());
2754
- // We don't want the form to submit as that replaces the document
2755
- return false;
2756
- }
2757
- var dlstatus_sdata = {
2758
- action: 'updraft_ajax',
2759
- subaction: 'downloadstatus',
2760
- nonce: '<?php echo wp_create_nonce('updraftplus-credentialtest-nonce'); ?>'
2761
- };
2762
- dlstatus_lastlog = '';
2763
- function updraft_downloader_status(nonce, what) {
2764
- var stid = 'uddlstatus_'+nonce+'_'+what;
2765
- if (jQuery('#'+stid).length) {
2766
- dlstatus_sdata.timestamp = nonce;
2767
- dlstatus_sdata.type = what;
2768
- jQuery.get(ajaxurl, dlstatus_sdata, function(response) {
2769
- nexttimer = 1250;
2770
- if (dlstatus_lastlog == response) { nexttimer = 3000; }
2771
- setTimeout(function(){updraft_downloader_status(nonce, what)}, nexttimer);
2772
- jQuery('#'+stid+'_st').html(response);
2773
- dlstatus_lastlog = response;
2774
- });
2775
- }
2776
- }
2777
- </script>
2778
- <div id="updraft_existing_backups" style="margin-bottom:12px;">
2779
- <?php
2780
- print $this->existing_backup_table($backup_history);
2781
- ?>
2782
- </div>
2783
- </td>
2784
- </tr>
2785
- </table>
2786
- <div id="updraft-restore-modal" title="UpdraftPlus - <?php _e('Restore backup','updraftplus');?>">
2787
- <p><strong><?php _e('Restore backup from','updraftplus');?>:</strong> <span id="updraft_restore_date"></span></p>
2788
- <p><?php _e("Restoring will replace this site's themes, plugins, uploads and/or other content directories (according to what is contained in the backup set, and your selection",'updraftplus');?>). <?php _e('Choose the components to restore','updraftplus');?>:</p>
2789
- <form id="updraft_restore_form" method="post">
2790
- <fieldset>
2791
- <input type="hidden" name="action" value="updraft_restore">
2792
- <input type="hidden" name="backup_timestamp" value="0" id="updraft_restore_timestamp">
2793
- <?php
2794
- $backupable_entities = $this->get_backupable_file_entities(true, true);
2795
- foreach ($backupable_entities as $type => $info) {
2796
- echo '<div><input id="updraft_restore_'.$type.'" type="checkbox" name="updraft_restore[]" value="'.$type.'"> <label for="updraft_restore_'.$type.'">'.$info['description'].'</label><br></div>';
2797
- }
2798
- ?>
2799
- <p><em><?php _e("Databases cannot yet be restored from here - you must download the database file and take it to your web hosting company's control panel.",'updraftplus');?></em></p>
2800
- </fieldset>
2801
- </form>
2802
- </div>
2803
-
2804
- <div id="updraft-backupnow-modal" title="UpdraftPlus - Perform a backup now">
2805
-
2806
- <p><?php _e("This will schedule a one-time backup. To proceed, press 'Backup Now', then wait 10 seconds, then visit any page on your site. WordPress should then start the backup running in the background.",'updraftplus');?></p>
2807
-
2808
- <form id="updraft-backupnow-form" method="post" action="">
2809
- <input type="hidden" name="action" value="updraft_backup" />
2810
- </form>
2811
-
2812
- <p><?php _e('Does nothing happen when you schedule backups?','updraftplus');?> <a href="http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/"><?php _e('Go here for help.','updraft');?></a></p>
2813
-
2814
- </div>
2815
-
2816
- <?php
2817
- if (is_multisite() && !file_exists(UPDRAFTPLUS_DIR.'/addons/multisite.php')) {
2818
- ?>
2819
- <h2>UpdraftPlus <?php _e('Multisite','updraftplus');?></h2>
2820
- <table>
2821
- <tr>
2822
- <td>
2823
- <p style="max-width:800px;"><?php echo __('Do you need WordPress Multisite support?','updraftplus').' <a href="http://updraftplus.com/">'. __('Please check out UpdraftPlus Premium, or the stand-alone Multisite add-on.','updraftplus');?></a>.</p>
2824
- </td>
2825
- </tr>
2826
- </table>
2827
- <?php } ?>
2828
- <h2><?php _e('Configure Backup Contents And Schedule','updraftplus');?></h2>
2829
- <?php UpdraftPlus_Options::options_form_begin(); ?>
2830
- <?php $this->settings_formcontents($last_backup_html); ?>
2831
- </form>
2832
- <div style="padding-top: 40px; display:none;" class="expertmode">
2833
- <hr>
2834
- <h3><?php _e('Debug Information And Expert Options','updraftplus');?></h3>
2835
- <p>
2836
- <?php
2837
- $peak_memory_usage = memory_get_peak_usage(true)/1024/1024;
2838
- $memory_usage = memory_get_usage(true)/1024/1024;
2839
- echo 'Peak memory usage: '.$peak_memory_usage.' MB<br/>';
2840
- echo 'Current memory usage: '.$memory_usage.' MB<br/>';
2841
- echo 'PHP memory limit: '.ini_get('memory_limit').' <br/>';
2842
- ?>
2843
- </p>
2844
- <p style="max-width: 600px;"><?php _e('The buttons below will immediately execute a backup run, independently of WordPress\'s scheduler. If these work whilst your scheduled backups and the "Backup Now" button do absolutely nothing (i.e. not even produce a log file), then it means that your scheduler is broken. You should then disable all your other plugins, and try the "Backup Now" button. If that fails, then contact your web hosting company and ask them if they have disabled wp-cron. If it succeeds, then re-activate your other plugins one-by-one, and find the one that is the problem and report a bug to them.','updraftplus');?></p>
2845
-
2846
- <form method="post">
2847
- <input type="hidden" name="action" value="updraft_backup_debug_all" />
2848
- <p><input type="submit" class="button-primary" <?php echo $backup_disabled ?> value="<?php _e('Debug Full Backup','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will cause an immediate backup. The page will stall loading until it finishes (ie, unscheduled).','updraftplus'));?>'))" /></p>
2849
- </form>
2850
- <form method="post">
2851
- <input type="hidden" name="action" value="updraft_backup_debug_db" />
2852
- <p><input type="submit" class="button-primary" <?php echo $backup_disabled ?> value="<?php _e('Debug Database Backup','updraftplus');?>" onclick="return(confirm('<?php echo htmlspecialchars(__('This will cause an immediate DB backup. The page will stall loading until it finishes (ie, unscheduled). The backup may well run out of time; really this button is only helpful for checking that the backup is able to get through the initial stages, or for small WordPress sites..','updraftplus'));?>'))" /></p>
2853
- </form>
2854
- <h3><?php _e('Wipe Settings','updraftplus');?></h3>
2855
- <p style="max-width: 600px;"><?php _e('This button will delete all UpdraftPlus settings (but not any of your existing backups from your cloud storage). You will then need to enter all your settings again. You can also do this before deactivating/deinstalling UpdraftPlus if you wish.','updraftplus');?></p>
2856
- <form method="post">
2857
- <input type="hidden" name="action" value="updraft_wipesettings" />
2858
- <p><input type="submit" class="button-primary" value="Wipe All Settings" onclick="return(confirm('<?php echo htmlspecialchars(__('This will delete all your UpdraftPlus settings - are you sure you want to do this?'));?>'))" /></p>
2859
- </form>
2860
- </div>
2861
-
2862
- <script type="text/javascript">
2863
- /* <![CDATA[ */
2864
- jQuery(document).ready(function() {
2865
- jQuery('#updraft-service').change(function() {
2866
- jQuery('.updraftplusmethod').hide();
2867
- var active_class = jQuery(this).val();
2868
- jQuery('.'+active_class).show();
2869
- });
2870
- })
2871
- jQuery(window).load(function() {
2872
- //this is for hiding the restore progress at the top after it is done
2873
- setTimeout('jQuery("#updraft-restore-progress").toggle(1000)',3000)
2874
- jQuery('#updraft-restore-progress-toggle').click(function() {
2875
- jQuery('#updraft-restore-progress').toggle(500)
2876
- })
2877
- })
2878
- /* ]]> */
2879
- </script>
2880
- <?php
2881
- }
2882
-
2883
- function existing_backup_table($backup_history = false) {
2884
-
2885
- // Fetch it if it was not passed
2886
- if ($backup_history === false) $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
2887
- if (!is_array($backup_history)) $backup_history=array();
2888
-
2889
- $updraft_dir = $this->backups_dir_location();
2890
-
2891
- $backupable_entities = $this->get_backupable_file_entities(true, true);
2892
-
2893
- echo '<table>';
2894
-
2895
- krsort($backup_history);
2896
-
2897
- foreach($backup_history as $key=>$value) {
2898
- $pretty_date = date('Y-m-d G:i',$key);
2899
- $entities = '';
2900
- ?>
2901
- <tr>
2902
- <td><b><?php echo $pretty_date?></b></td>
2903
- <td>
2904
- <?php if (isset($value['db'])) { ?>
2905
- <form id="uddownloadform_db_<?php echo $key;?>" action="admin-ajax.php" onsubmit="return updraft_downloader(<?php echo $key;?>, 'db')" method="post">
2906
- <?php wp_nonce_field('updraftplus_download'); ?>
2907
- <input type="hidden" name="action" value="updraft_download_backup" />
2908
- <input type="hidden" name="type" value="db" />
2909
- <input type="hidden" name="timestamp" value="<?php echo $key?>" />
2910
- <input type="submit" value="<?php _e('Database','updraftplus');?>" />
2911
- </form>
2912
- <?php } else { echo "(No&nbsp;database)"; } ?>
2913
- </td>
2914
-
2915
- <?php
2916
- foreach ($backupable_entities as $type => $info) {
2917
- echo '<td>';
2918
- if (isset($value[$type])) {
2919
- $entities .= '/'.$type.'/';
2920
- $sdescrip = preg_replace('/ \(.*\)$/', '', $info['description']);
2921
- ?>
2922
- <form id="uddownloadform_<?php echo $type.'_'.$key;?>" action="admin-ajax.php" onsubmit="return updraft_downloader('<?php echo $key."', '".$type;?>')" method="post">
2923
- <?php wp_nonce_field('updraftplus_download'); ?>
2924
- <input type="hidden" name="action" value="updraft_download_backup" />
2925
- <input type="hidden" name="type" value="<?php echo $type; ?>" />
2926
- <input type="hidden" name="timestamp" value="<?php echo $key?>" />
2927
- <input type="submit" title="<?php echo __('Press here to download','updraftplus').' '.strtolower($info['description']); ?>" value="<?php echo $sdescrip;?>" />
2928
- </form>
2929
- <?php } else { echo "(No&nbsp;".strtolower($info['description']).")"; } ?>
2930
- </td>
2931
- <?php }; ?>
2932
-
2933
- <td>
2934
- <?php if (isset($value['nonce']) && preg_match("/^[0-9a-f]{12}$/",$value['nonce']) && is_readable($updraft_dir.'/log.'.$value['nonce'].'.txt')) { ?>
2935
- <form action="options-general.php" method="get">
2936
- <input type="hidden" name="action" value="downloadlog" />
2937
- <input type="hidden" name="page" value="updraftplus" />
2938
- <input type="hidden" name="updraftplus_backup_nonce" value="<?php echo $value['nonce']; ?>" />
2939
- <input type="submit" value="Backup Log" />
2940
- </form>
2941
- <?php } else { echo "(No&nbsp;backup&nbsp;log)"; } ?>
2942
- </td>
2943
- <td>
2944
- <form method="post" action="">
2945
- <input type="hidden" name="backup_timestamp" value="<?php echo $key;?>">
2946
- <input type="hidden" name="action" value="updraft_restore" />
2947
- <?php if ($entities) { ?><button title="<?php _e('After pressing this button, you will be given the option to choose which components you wish to restore','updraftplus');?>" type="button" <?php echo $restore_disabled ?> class="button-primary" style="padding-top:2px;padding-bottom:2px;font-size:16px !important; min-height:26px;" onclick="updraft_restore_options('<?php echo $entities;?>'); jQuery('#updraft_restore_timestamp').val('<?php echo $key;?>'); jQuery('#updraft_restore_date').html('<?php echo $pretty_date;?>'); jQuery('#updraft-restore-modal').dialog('open');">Restore</button><?php } ?>
2948
- </form>
2949
- </td>
2950
- </tr>
2951
- <script>
2952
- function updraft_restore_options(entities) {
2953
- jQuery('input[name="updraft_restore[]"]').each(function(x,y){
2954
- var entity = jQuery(y).val();
2955
- if (entities.indexOf('/'+entity+'/') != -1) {
2956
- jQuery(y).removeAttr('disabled').parent().show();
2957
- } else {
2958
- jQuery(y).attr('disabled','disabled').parent().hide();
2959
- }
2960
- });
2961
- }
2962
- </script>
2963
- <?php }
2964
- echo '</table>';
2965
- }
2966
-
2967
- function show_admin_warning($message, $class = "updated") {
2968
- echo '<div id="updraftmessage" class="'.$class.' fade">'."<p>$message</p></div>";
2969
- }
2970
-
2971
- function show_admin_warning_diskspace() {
2972
- $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('You have less than %s of free disk space on the disk which UpdraftPlus is configured to use to create backups. UpdraftPlus could well run out of space. Contact your the operator of your server (e.g. your web hosting company) to resolve this issue.','updraftplus'),'35 Mb'));
2973
- }
2974
-
2975
- function show_admin_warning_wordpressversion() {
2976
- $this->show_admin_warning('<strong>'.__('Warning','updraftplus').':</strong> '.sprintf(__('UpdraftPlus does not officially support versions of WordPress before %s. It may work for you, but if it does not, then please be aware that no support is available until you upgrade WordPress.'),'3.2'),'updraftplus');
2977
- }
2978
-
2979
- function show_admin_warning_unreadablelog() {
2980
- $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> '.__('The log file could not be read.','updraftplus'));
2981
- }
2982
-
2983
- function show_admin_warning_dropbox() {
2984
- $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a href="options-general.php?page=updraftplus&action=updraftmethod-dropbox-auth&updraftplus_dropboxauth=doit">.'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'),'Dropbox','Dropbox').'</a>');
2985
- }
2986
-
2987
- function show_admin_warning_googledrive() {
2988
- $this->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').'</strong> <a href="options-general.php?page=updraftplus&action=updraftmethod-googledrive-auth&updraftplus_googleauth=doit">.'.sprintf(__('Click here to authenticate your %s account (you will not be able to back up to %s without it).','updraftplus'),'Google Drive','Google Drive').'</a>');
2989
- }
2990
-
2991
- // Caution: $source is allowed to be an array, not just a filename
2992
- function make_zipfile($source, $destination) {
2993
-
2994
- // When to prefer PCL:
2995
- // - We were asked to
2996
- // - No zip extension present and no relevant method present
2997
- // The zip extension check is not redundant, because method_exists segfaults some PHP installs, leading to support requests
2998
-
2999
- // Fallback to PclZip - which my tests show is 25% slower (and we can't resume)
3000
- if ($this->zip_preferpcl || (!extension_loaded('zip') && !method_exists('ZipArchive', 'AddFile'))) {
3001
- if(!class_exists('PclZip')) require_once(ABSPATH.'/wp-admin/includes/class-pclzip.php');
3002
- $zip_object = new PclZip($destination);
3003
- $zipcode = $zip_object->create($source, PCLZIP_OPT_REMOVE_PATH, WP_CONTENT_DIR);
3004
- if ($zipcode == 0 ) {
3005
- $this->log("PclZip Error: ".$zip_object->errorName());
3006
- return $zip_object->errorCode();
3007
- } else {
3008
- return true;
3009
- }
3010
- }
3011
-
3012
- $this->existing_files = array();
3013
-
3014
- // If the file exists, then we should grab its index of files inside, and sizes
3015
- // Then, when we come to write a file, we should check if it's already there, and only add if it is not
3016
- if (file_exists($destination) && is_readable($destination)) {
3017
- $zip = new ZipArchive;
3018
- $zip->open($destination);
3019
- $this->log(basename($destination).": Zip file already exists, with ".$zip->numFiles." files");
3020
- for ($i=0; $i<$zip->numFiles; $i++) {
3021
- $si = $zip->statIndex($i);
3022
- $name = $si['name'];
3023
- $this->existing_files[$name] = $si['size'];
3024
- }
3025
- } elseif (file_exists($destination)) {
3026
- $this->log("Zip file already exists, but is not readable; will remove: $destination");
3027
- @unlink($destination);
3028
- }
3029
-
3030
- $this->zipfiles_added = 0;
3031
- $this->zipfiles_dirbatched = array();
3032
- $this->zipfiles_batched = array();
3033
- $this->zipfiles_lastwritetime = time();
3034
-
3035
- // Magic value, used later to detect no error occurring
3036
- $last_error = 2349864;
3037
- if (is_array($source)) {
3038
- foreach ($source as $element) {
3039
- $howmany = $this->makezip_recursive_add($destination, $element, basename($element), $element);
3040
- if ($howmany < 0) {
3041
- $last_error = $howmany;
3042
- }
3043
- }
3044
- } else {
3045
- $howmany = $this->makezip_recursive_add($destination, $source, basename($source), $source);
3046
- if ($howmany < 0) {
3047
- $last_error = $howmany;
3048
- }
3049
- }
3050
-
3051
- // Any not yet dispatched?
3052
- if (count($this->zipfiles_dirbatched)>0 || count($this->zipfiles_batched)>0) {
3053
- $howmany = $this->makezip_addfiles($destination);
3054
- if ($howmany < 0) {
3055
- $last_error = $howmany;
3056
- }
3057
- }
3058
-
3059
- if ($this->zipfiles_added > 0 || $last_error == 2349864) {
3060
- // ZipArchive::addFile sometimes fails
3061
- if (filesize($destination) < 100) {
3062
- // Retry with PclZip
3063
- $this->log("Zip::addFile apparently failed - retrying with PclZip");
3064
- $this->zip_preferpcl = true;
3065
- return $this->make_zipfile($source, $destination);
3066
- }
3067
- return true;
3068
- } else {
3069
- return $last_error;
3070
- }
3071
-
3072
- }
3073
-
3074
- // Q. Why don't we only open and close the zip file just once?
3075
- // A. Because apparently PHP doesn't write out until the final close, and it will return an error if anything file has vanished in the meantime. So going directory-by-directory reduces our chances of hitting an error if the filesystem is changing underneath us (which is very possible if dealing with e.g. 1Gb of files)
3076
-
3077
- // We batch up the files, rather than do them one at a time. So we are more efficient than open,one-write,close.
3078
- function makezip_addfiles($zipfile) {
3079
-
3080
- // Short-circuit the null case, because we want to detect later if something useful happenned
3081
- if (count($this->zipfiles_dirbatched) == 0 && count($this->zipfiles_batched) == 0) return true;
3082
-
3083
- // 05-Mar-2013 - added a new check on the total data added; it appears that things fall over if too much data is contained in the cumulative total of files that were addFile'd without a close-open cycle; presumably data is being stored in memory. In the case in question, it was a batch of MP3 files of around 100Mb each - 25 of those equals 2.5Gb!
3084
-
3085
- $data_added_since_reopen = 0;
3086
-
3087
- $zip = new ZipArchive();
3088
- if (file_exists($zipfile)) {
3089
- $opencode = $zip->open($zipfile);
3090
- $original_size = filesize($zipfile);
3091
- clearstatcache($zipfile);
3092
- } else {
3093
- $opencode = $zip->open($zipfile, ZIPARCHIVE::CREATE);
3094
- $original_size = 0;
3095
- }
3096
-
3097
- if ($opencode !== true) return array($opencode, 0);
3098
- // Make sure all directories are created before we start creating files
3099
- while ($dir = array_pop($this->zipfiles_dirbatched)) {
3100
- $zip->addEmptyDir($dir);
3101
- }
3102
- foreach ($this->zipfiles_batched as $file => $add_as) {
3103
- $fsize = filesize($file);
3104
- if (!isset($this->existing_files[$add_as]) || $this->existing_files[$add_as] != $fsize) {
3105
-
3106
- @touch($zipfile);
3107
- $zip->addFile($file, $add_as);
3108
-
3109
- $data_added_since_reopen += $fsize;
3110
- # 25Mb - force a write-out and re-open
3111
- if ($data_added_since_reopen > 26214400 || (time() - $this->zipfiles_lastwritetime) > 2) {
3112
-
3113
- $before_size = filesize($zipfile);
3114
- clearstatcache($zipfile);
3115
-
3116
- if ($data_added_since_reopen > 26214400) {
3117
- $this->log("Adding batch to zip file: over 25Mb added on this batch (".round($data_added_since_reopen/1048576,1)." Mb); re-opening (prior size: ".round($before_size/1024,1).' Kb)');
3118
- } else {
3119
- $this->log("Adding batch to zip file: over 2 seconds have passed since the last write (".round($data_added_since_reopen/1048576,1)." Mb); re-opening (prior size: ".round($before_size/1024,1).' Kb)');
3120
- }
3121
- if (!$zip->close()) {
3122
- $this->log("zip::Close returned an error");
3123
- }
3124
- unset($zip);
3125
- $zip = new ZipArchive();
3126
- $opencode = $zip->open($zipfile);
3127
- if ($opencode !== true) return array($opencode, 0);
3128
- $data_added_since_reopen = 0;
3129
- $zipfiles_lastwritetime = time();
3130
- // Call here, in case we've got so many big files that we don't complete the whole routine
3131
- if (filesize($zipfile) > $before_size) $this->something_useful_happened();
3132
- clearstatcache($zipfile);
3133
- }
3134
- }
3135
- $this->zipfiles_added++;
3136
- // Don't call something_useful_happened() here - nothing necessarily happens until close() is called
3137
- if ($this->zipfiles_added % 100 == 0) $this->log("Zip: ".basename($zipfile).": ".$this->zipfiles_added." files added (on-disk size: ".round(filesize($zipfile)/1024,1)." Kb)");
3138
- }
3139
- // Reset the array
3140
- $this->zipfiles_batched = array();
3141
- $ret = $zip->close();
3142
- $zipfiles_lastwritetime = time();
3143
- if (filesize($zipfile) > $original_size) $this->something_useful_happened();
3144
- clearstatcache($zipfile);
3145
- return $ret;
3146
- }
3147
-
3148
  function something_useful_happened() {
3149
  if ($this->current_resumption >= 9 && $this->newresumption_scheduled == false) {
 
3150
  $resume_interval = $this->jobdata_get('resume_interval');
3151
  if (!is_numeric($resume_interval) || $resume_interval<$this->minimum_resume_interval()) { $resume_interval = $this->minimum_resume_interval(); }
3152
  $schedule_for = time()+$resume_interval;
3153
  $this->newresumption_scheduled = $schedule_for;
3154
- $this->log("This is resumption ".$this->current_resumption.", but meaningful activity is still taking place; so a new one will be scheduled");
3155
  wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($this->current_resumption + 1, $this->nonce));
3156
  } else {
3157
  $this->reschedule_if_needed();
3158
  }
3159
  }
3160
 
3161
- // This function recursively packs the zip, dereferencing symlinks but packing into a single-parent tree for universal unpacking
3162
- function makezip_recursive_add($zipfile, $fullpath, $use_path_when_storing, $original_fullpath) {
3163
-
3164
- // De-reference
3165
- $fullpath = realpath($fullpath);
3166
-
3167
- // Is the place we've ended up above the original base? That leads to infinite recursion
3168
- if (($fullpath !== $original_fullpath && strpos($original_fullpath, $fullpath) === 0) || ($original_fullpath == $fullpath && strpos($use_path_when_storing, '/') !== false) ) {
3169
- $this->log("Infinite recursion: symlink lead us to $fullpath, which is within $original_fullpath");
3170
- $this->error(__("Infinite recursion: consult your log for more information",'updraftplus'));
3171
- return false;
3172
- }
3173
-
3174
- if(is_file($fullpath)) {
3175
- if (is_readable($fullpath)) {
3176
- $key = ($fullpath == $original_fullpath) ? basename($fullpath) : $use_path_when_storing.'/'.basename($fullpath);
3177
- $this->zipfiles_batched[$fullpath] = $key;
3178
- @touch($zipfile);
3179
- } else {
3180
- $this->log("$fullpath: unreadable file");
3181
- $this->error("$fullpath: unreadable file");
3182
- }
3183
- } elseif (is_dir($fullpath)) {
3184
- if (!isset($this->existing_files[$use_path_when_storing])) $this->zipfiles_dirbatched[] = $use_path_when_storing;
3185
- if (!$dir_handle = @opendir($fullpath)) {
3186
- $this->log("Failed to open directory: $fullpath");
3187
- $this->error("Failed to open directory: $fullpath");
3188
- return;
3189
- }
3190
- while ($e = readdir($dir_handle)) {
3191
- if ($e != '.' && $e != '..') {
3192
- if (is_link($fullpath.'/'.$e)) {
3193
- $deref = realpath($fullpath.'/'.$e);
3194
- if (is_file($deref)) {
3195
- if (is_readable($deref)) {
3196
- $this->zipfiles_batched[$deref] = $use_path_when_storing.'/'.$e;
3197
- @touch($zipfile);
3198
- } else {
3199
- $this->log("$deref: unreadable file");
3200
- $this->error("$deref: unreadable file");
3201
- }
3202
- } elseif (is_dir($deref)) {
3203
- $this->makezip_recursive_add($zipfile, $deref, $use_path_when_storing.'/'.$e, $original_fullpath);
3204
- }
3205
- } elseif (is_file($fullpath.'/'.$e)) {
3206
- if (is_readable($fullpath.'/'.$e)) {
3207
- $this->zipfiles_batched[$fullpath.'/'.$e] = $use_path_when_storing.'/'.$e;
3208
- @touch($zipfile);
3209
- } else {
3210
- $this->log("$fullpath/$e: unreadable file");
3211
- $this->error("$fullpath/$e: unreadable file");
3212
- }
3213
- } elseif (is_dir($fullpath.'/'.$e)) {
3214
- // no need to addEmptyDir here, as it gets done when we recurse
3215
- $this->makezip_recursive_add($zipfile, $fullpath.'/'.$e, $use_path_when_storing.'/'.$e, $original_fullpath);
3216
- }
3217
- }
3218
- }
3219
- closedir($dir_handle);
3220
- }
3221
-
3222
- // We don't want to touch the zip file on every single file, so we batch them up
3223
- // We go every 25 files, because if you wait too much longer, the contents may have changed from under you
3224
- // And for some redundancy (redundant because of the touches going on anyway), we try to touch the file after 20 seconds, to help with the "recently modified" check on resumption (we saw a case where the file went for 155 seconds without being touched and so the other runner was not detected)
3225
- if (count($this->zipfiles_batched) > 25 || (file_exists($zipfile) && ((time()-filemtime($zipfile)) > 20) )) {
3226
- $ret = $this->makezip_addfiles($zipfile);
3227
- } else {
3228
- $ret = true;
3229
- }
3230
-
3231
- return $ret;
3232
-
3233
- }
3234
 
3235
  }
3236
 
2
  /*
3
  Plugin Name: UpdraftPlus - Backup/Restore
4
  Plugin URI: http://updraftplus.com
5
+ Description: Backup and restore: your site can take backups locally, or backup to Amazon S3, Dropbox, Google Drive, (S)FTP, WebDAV & email, on automatic schedules.
6
  Author: UpdraftPlus.Com, DavidAnderson
7
+ Version: 1.5.16
8
  Donate link: http://david.dw-perspective.org.uk/donate
9
  License: GPLv3 or later
10
  Text Domain: updraftplus
11
  Author URI: http://updraftplus.com
12
  */
13
 
14
+
15
  /*
16
  TODO - some of these are out of date/done, needs pruning
17
+ // Add an appeal for translators to email me. If it a fails, use Google Translate Tools and appeal for native users to correct it.
 
18
  // Search for other TODO-s in the code
19
+ // Test in PHP 5.4
20
+ // Add in downloading in the 'Restore' modal, and remove the advice to do so manually.
21
+ // Provide an expert option to disable sslverify on WP HTTP requests. Mention in FAQs etc.
22
+ // Save database encryption key inside backup history on per-db basis, so that if it changes we can still decrypt
23
+ // Switch to Google Drive SDK. Google folders. https://developers.google.com/drive/folder
24
+ // GlotPress
25
+ // Ability to re-scan existing cloud storage
26
+ // Migrator - search+replace the database
27
  // Make mcrypt warning on dropbox more prominent - one customer missed it
28
  // Store meta-data on which version of UD the backup was made with (will help if we ever introduce quirks that need ironing)
29
  // Test restoration when uploads dir is /assets/ (e.g. with Shoestrap theme)
30
  // Send the user an email upon their first backup with tips on what to do (e.g. support/improve) (include legacy check to not bug existing users)
31
  //Allow use of /usr/bin/zip - since this can escape from PHP's memory limit. Can still batch as we do so, in order to monitor/measure progress
32
+ // Database decrypter
33
+ // Easier download of 'in progress' backup logs (not just last completed)
34
  //Do an automated test periodically for the success of loop-back connections
35
  //When a manual backup is run, use a timer to update the 'Download backups and logs' section, just like 'Last finished backup run'. Beware of over-writing anything that's in there from a resumable downloader.
36
  //Change DB encryption to not require whole gzip in memory (twice)
43
  // Should we resume if the only errors were upon deletion (i.e. the backup itself was fine?) Presently we do, but it displays errors for the user to confuse them. Perhaps better to make pruning a separate scheuled task??
44
  // Warn the user if their zip-file creation is slooowww...
45
  // Create a "Want Support?" button/console, that leads them through what is needed, and performs some basic tests...
46
+ // Chunking + resuming on SFTP
 
47
  // Add-on to manage all your backups from a single dashboard
48
  // Make disk space check more intelligent (currently hard-coded at 35Mb)
49
  // Provide backup/restoration for UpdraftPlus's settings, to allow 'bootstrap' on a fresh WP install - some kind of single-use code which a remote UpdraftPlus can use to authenticate
50
  // Multiple jobs
 
51
  // Allow connecting to remote storage, scanning + populating backup history from it
52
  // GoogleDrive in-dashboard download resumption loads the whole archive into memory - should instead either chunk or directly stream fo the file handle
53
  // Multisite add-on should allow restoring of each blog individually
57
  // Remove the recurrence of admin notices when settings are saved due to _wp_referer
58
 
59
  Encrypt filesystem, if memory allows (and have option for abort if not); split up into multiple zips when needed
 
60
  // New sub-module to verify that the backups are there, independently of backup thread
61
  */
62
 
63
  /* Portions copyright 2010 Paul Kehrer
64
  Portions copyright 2011-13 David Anderson
65
  Other portions copyright as indicated authors in the relevant files
 
66
 
67
  This program is free software; you can redistribute it and/or modify
68
  it under the terms of the GNU General Public License as published by
79
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
80
  */
81
 
 
 
 
82
  define('UPDRAFTPLUS_DIR', dirname(__FILE__));
83
  define('UPDRAFTPLUS_URL', plugins_url('', __FILE__));
84
  define('UPDRAFT_DEFAULT_OTHERS_EXCLUDE','upgrade,cache,updraft,index.php,backup,backups');
88
 
89
  // Load add-ons
90
  if (is_file(UPDRAFTPLUS_DIR.'/premium.php')) require_once(UPDRAFTPLUS_DIR.'/premium.php');
91
+ if (is_file(UPDRAFTPLUS_DIR.'/autoload.php')) require_once(UPDRAFTPLUS_DIR.'/autoload.php');
92
 
93
  if ($dir_handle = opendir(UPDRAFTPLUS_DIR.'/addons')) {
94
  while ($e = readdir($dir_handle)) {
103
 
104
  if (!$updraftplus->memory_check(192)) {
105
  // Experience appears to show that the memory limit is only likely to be hit (unless it is very low) by single files that are larger than available memory (when compressed)
106
+ @ini_set('memory_limit', WP_MAX_MEMORY_LIMIT); //up the memory limit to the maximum WordPress is allowing for large backup files
107
  }
108
 
109
  if (!class_exists('UpdraftPlus_Options')) require_once(UPDRAFTPLUS_DIR.'/options.php');
144
  var $current_resumption;
145
  var $newresumption_scheduled = false;
146
 
 
 
 
 
 
 
 
 
147
  function __construct() {
148
 
149
  // Initialisation actions - takes place on plugin load
157
  }
158
 
159
  # Create admin page
160
+ add_action('init', array($this, 'handle_url_actions'));
161
+ add_action('wp_loaded', array($this,'wp_loaded'));
162
  add_action('updraft_backup', array($this,'backup_files'));
163
  add_action('updraft_backup_database', array($this,'backup_database'));
164
+ # backup_all is used by the manual "Backup Now" button
165
  add_action('updraft_backup_all', array($this,'backup_all'));
166
  # this is our runs-after-backup event, whose purpose is to see if it succeeded or failed, and resume/mom-up etc.
167
  add_action('updraft_backup_resume', array($this,'backup_resume'), 10, 3);
 
 
168
  # http://codex.wordpress.org/Plugin_API/Filter_Reference/cron_schedules
169
  add_filter('cron_schedules', array($this,'modify_cron_schedules'));
 
 
170
  add_action('plugins_loaded', array($this, 'load_translations'));
171
 
172
+ register_deactivation_hook(__FILE__, array($this, 'deactivation'));
 
 
173
 
 
 
 
174
  }
175
 
176
  // Handle actions passed on to method plugins; e.g. Google OAuth 2.0 - ?page=updraftplus&action=updraftmethod-googledrive-auth
177
  // Also handle action=downloadlog
178
  function handle_url_actions() {
179
+
180
  // First, basic security check: must be an admin page, with ability to manage options, with the right parameters
181
  if ( UpdraftPlus_Options::user_can_manage() && isset( $_GET['page'] ) && $_GET['page'] == 'updraftplus' && isset($_GET['action']) ) {
182
  if (preg_match("/^updraftmethod-([a-z]+)-([a-z]+)$/", $_GET['action'], $matches) && file_exists(UPDRAFTPLUS_DIR.'/methods/'.$matches[1].'.php')) {
186
  $call_method = "action_".$matches[2];
187
  if (method_exists($call_class, $call_method)) call_user_func(array($call_class,$call_method));
188
  } elseif ($_GET['action'] == 'downloadlog' && isset($_GET['updraftplus_backup_nonce']) && preg_match("/^[0-9a-f]{12}$/",$_GET['updraftplus_backup_nonce'])) {
189
+ // No WordPress nonce is needed here or for the next, since the backup is already nonce-based
190
  $updraft_dir = $this->backups_dir_location();
191
  $log_file = $updraft_dir.'/log.'.$_GET['updraftplus_backup_nonce'].'.txt';
192
  if (is_readable($log_file)) {
196
  } else {
197
  add_action('admin_notices', array($this,'show_admin_warning_unreadablelog') );
198
  }
199
+ } elseif ($_GET['action'] == 'downloadfile' && isset($_GET['updraftplus_file']) && preg_match('/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+\.(gz\.crypt)$/i', $_GET['updraftplus_file'])) {
200
+ $updraft_dir = $this->backups_dir_location();
201
+ $spool_file = $updraft_dir.'/'.$_GET['updraftplus_file'];
202
+ if (is_readable($spool_file)) {
203
+ $dkey = (isset($_GET['decrypt_key'])) ? $_GET['decrypt_key'] : "";
204
+ $this->spool_file('db', $spool_file, $dkey);
205
+ exit;
206
+ } else {
207
+ add_action('admin_notices', array($this,'show_admin_warning_unreadablefile') );
208
+ }
209
  }
210
  }
211
  }
212
 
213
+ function show_admin_warning_unreadablelog() {
214
+ global $updraftplus_admin;
215
+ $updraftplus_admin->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').':</strong> '.__('The log file could not be read.','updraftplus'));
216
+ }
217
+
218
+ function show_admin_warning_unreadablefile() {
219
+ global $updraftplus_admin;
220
+ $updraftplus_admin->show_admin_warning('<strong>'.__('UpdraftPlus notice:','updraftplus').':</strong> '.__('The given file could not be read.','updraftplus'));
221
+ }
222
+
223
+ function load_translations() {
224
+ // Tell WordPress where to find the translations
225
+ load_plugin_textdomain('updraftplus', false, basename(dirname(__FILE__)).'/languages');
226
+ }
227
+
228
  // Cleans up temporary files found in the updraft directory
229
  function clean_temporary_files() {
230
  $updraft_dir = $this->backups_dir_location();
241
  }
242
  }
243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  function backup_time_nonce() {
245
  $this->backup_time = time();
246
  $nonce = substr(md5(time().rand()), 20);
349
 
350
  function backup_resume($resumption_no, $bnonce) {
351
 
352
+ // 15 minutes
353
+ @set_time_limit(900);
354
+
355
  @ignore_user_abort(true);
356
  // This is scheduled for 5 minutes after a backup job starts
357
 
391
 
392
  // Sanity check
393
  if (empty($this->backup_time)) {
394
+ $this->log('Abort this run: the backup_time parameter appears to be empty (this is usually caused by resuming an already-complete backup, or by your site having a faulty object cache active (e.g. W3 Total Cache\'s object cache))');
395
  return false;
396
  }
397
 
565
  function boot_backup($backup_files, $backup_database) {
566
 
567
  @ignore_user_abort(true);
568
+ // 15 minutes
569
+ @set_time_limit(900);
570
 
571
  //generate backup information
572
  $this->backup_time_nonce();
580
 
581
  // Some house-cleaning
582
  $this->clean_temporary_files();
583
+ do_action('updraftplus_boot_backup');
584
 
585
  // Log some information that may be helpful
586
  $this->log("Tasks: Backup files: $backup_files (schedule: ".UpdraftPlus_Options::get_updraft_option('updraft_interval', 'unset').") Backup DB: $backup_database (schedule: ".UpdraftPlus_Options::get_updraft_option('updraft_interval_database', 'unset').")");
677
  // Make sure that the final status is shown
678
  if (empty($this->errors)) {
679
  $send_an_email = true;
680
+ $final_message = __("The backup apparently succeeded and is now complete",'updraftplus');
681
  } elseif ($this->newresumption_scheduled == false) {
682
  $send_an_email = true;
683
+ $final_message = __("The backup attempt has finished, apparently unsuccessfully",'updraftplus');
684
  } else {
685
  // There are errors, but a resumption will be attempted
686
+ $final_message = __("The backup has not finished; a resumption is scheduled within 5 minutes",'updraftplus');
687
  }
688
 
689
  // Now over-ride the decision to send an email, if needed
950
  $this->log("To decrease the likelihood of overlaps, increasing resumption interval to: $resume_interval + $howmuch = ".($resume_interval+$howmuch));
951
  }
952
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
953
  // For detecting another run, and aborting if one was found
954
  function check_recent_modification($file) {
955
  if (file_exists($file)) {
975
  return array();
976
  }
977
 
978
+ // Bring in all the zip routines
979
+ require_once(UPDRAFTPLUS_DIR.'/backup.php');
980
+ global $updraftplus_backup;
981
+
982
  //get the blog name and rip out all non-alphanumeric chars other than _
983
  $blog_name = str_replace(' ','_',substr(get_bloginfo(), 0, 96));
984
  $blog_name = preg_replace('/[^A-Za-z0-9_]/','', $blog_name);
1003
  $backup_array[$youwhat] = $backup_file_basename.'-'.$youwhat.'.zip';
1004
  if (file_exists($zip_file)) $backup_array[$youwhat.'-size'] = filesize($zip_file);
1005
  } else {
1006
+ $created = $updraftplus_backup->create_zip($whichdir, $youwhat, $updraft_dir, $backup_file_basename);
1007
  if ($created) {
1008
  $backup_array[$youwhat] = $created;
1009
  $backup_array[$youwhat.'-size'] = filesize($updraft_dir.'/'.$created);
1069
  }
1070
 
1071
  if (count($other_dirlist)>0) {
1072
+ $created = $updraftplus_backup->create_zip($other_dirlist, 'others', $updraft_dir, $backup_file_basename);
1073
  if ($created) {
1074
  $backup_array['others'] = $created;
1075
  $backup_array['others-size'] = filesize($updraft_dir.'/'.$created);
1132
 
1133
  //Begin new backup of MySql
1134
  $this->stow("# " . 'WordPress MySQL database backup' . "\n");
1135
+ $this->stow("# " . 'Created by UpdraftPlus (http://updraftplus.com)' . "\n");
1136
  $this->stow("#\n");
1137
  $this->stow("# " . sprintf(__('Generated: %s','wp-db-backup'),date("l j. F Y H:i T")) . "\n");
1138
  $this->stow("# " . sprintf(__('Hostname: %s','wp-db-backup'),DB_HOST) . "\n");
1319
  $this->stow($create_table[0][1] . ' ;');
1320
 
1321
  if (false === $table_structure) {
1322
+ $err_msg = sprintf('Error getting table structure of %s', $table);
 
1323
  $this->stow("#\n# $err_msg\n#\n");
1324
  }
1325
 
1326
  // Comment in SQL-file
1327
+ $this->stow("\n\n#\n# " . sprintf('Data contents of table %s',$this->backquote($table)) . "\n#\n");
1328
  }
1329
 
1330
  // In UpdraftPlus, segment is always 'none'
1350
 
1351
  do {
1352
  if ( !@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == "off") @set_time_limit(15*60);
1353
+
1354
  $table_data = $wpdb->get_results("SELECT * FROM $table LIMIT {$row_start}, {$row_inc}", ARRAY_A);
1355
+ $entries = 'INSERT INTO ' . $this->backquote($table) . ' VALUES ';
1356
  // \x08\\x09, not required
1357
  $search = array("\x00", "\x0a", "\x0d", "\x1a");
1358
  $replace = array('\0', '\n', '\r', '\Z');
1359
  if($table_data) {
1360
+ $thisentry = "";
1361
  foreach ($table_data as $row) {
1362
  $total_rows++;
1363
  $values = array();
1371
  $values[] = "'" . str_replace($search, $replace, str_replace('\'', '\\\'', str_replace('\\', '\\\\', $value))) . "'";
1372
  }
1373
  }
1374
+ if ($thisentry) $thisentry .= ",\n ";
1375
+ $thisentry .= '('.implode(', ', $values).')';
1376
+ // Flush every 512Kb
1377
+ if (strlen($thisentry) > 524288) {
1378
+ $this->stow(" \n".$entries.$thisentry.';');
1379
+ $thisentry = "";
1380
+ }
1381
+
1382
  }
1383
+ if ($thisentry) $this->stow(" \n".$entries.$thisentry.';');
1384
  $row_start += $row_inc;
1385
  }
1386
  } while((count($table_data) > 0) and ($segment=='none'));
1446
 
1447
  /*END OF WP-DB-BACKUP BLOCK */
1448
 
 
 
 
 
 
 
1449
  /*
1450
  this function is both the backup scheduler and ostensibly a filter callback for saving the option.
1451
  it is called in the register_setting for the updraft_interval, which means when the admin settings
1470
  return wp_filter_nohtml_kses($interval);
1471
  }
1472
 
1473
+ function deactivation () {
1474
+ wp_clear_scheduled_hook('updraftplus_weekly_ping');
1475
+ }
1476
+
1477
  // Acts as a WordPress options filter
1478
  function googledrive_clientid_checkchange($client_id) {
1479
  if (UpdraftPlus_Options::get_updraft_option('fdrive_token') != '' && UpdraftPlus_Options::get_updraft_option('updraft_googledrive_clientid') != $client_id) {
1511
  return $schedules;
1512
  }
1513
 
 
 
 
 
 
 
 
 
 
 
1514
  function backups_dir_location() {
1515
 
1516
  if (!empty($this->backup_dir)) return $this->backup_dir;
1538
  return $updraft_dir;
1539
  }
1540
 
1541
+ function spool_file($type, $fullpath, $encryption = "") {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1542
 
1543
+ @set_time_limit(900);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1544
 
1545
  if (file_exists($fullpath)) {
1546
 
1551
  $filearr = explode('.',$file);
1552
  // //we've only got zip and gz...for now
1553
  $file_ext = array_pop($filearr);
 
 
 
 
 
 
1554
  header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
1555
  header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
1556
  header("Content-Length: $len;");
1557
+
1558
  if ($file_ext == 'crypt') {
1559
+ if ($encryption == "") $encryption = UpdraftPlus_Options::get_updraft_option('updraft_encryptionphrase');
 
 
 
 
 
 
1560
  if ($encryption == "") {
1561
+ header('Content-type: text/plain');
1562
+ _e("Decryption failed. The database file is encrypted, but you have no encryption key entered.",'updraftplus');
1563
  $this->error('Decryption of database failed: the database file is encrypted, but you have no encryption key entered.');
1564
  } else {
1565
+ require_once(UPDRAFTPLUS_DIR.'/includes/phpseclib/Crypt/Rijndael.php');
1566
  $rijndael = new Crypt_Rijndael();
1567
  $rijndael->setKey($encryption);
1568
+ $ciphertext = $rijndael->decrypt(file_get_contents($fullpath));
1569
+ if ($ciphertext) {
1570
+ header('Content-type: application/x-gzip');
1571
+ header("Content-Disposition: attachment; filename=\"".substr($file,0,-6)."\";");
1572
+ print $ciphertext;
1573
+ } else {
1574
+ header('Content-type: text/plain');
1575
+ echo __("Decryption failed. The most likely cause is that you used the wrong key.",'updraftplus')." ".__('The decryption key used:','updraftplus').' '.$encryption;
1576
+
1577
  }
 
 
1578
  }
1579
  } else {
1580
+ if ($file_ext == 'zip') {
1581
+ header('Content-type: application/zip');
1582
+ } else {
1583
+ header('Content-type: application/x-gzip');
1584
+ }
1585
+ header("Content-Disposition: attachment; filename=\"$file\";");
1586
  readfile($fullpath);
1587
  }
1588
  // $this->delete_local($file);
1591
  }
1592
  }
1593
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1594
  function retain_range($input) {
1595
  $input = (int)$input;
1596
+ return ($input > 0 && $input < 3650) ? $input : 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1597
  }
1598
 
1599
  function memory_check_current() {
1615
  return $memory_limit;
1616
  }
1617
 
 
 
 
 
 
 
 
1618
  function memory_check($memory) {
1619
  $memory_limit = $this->memory_check_current();
1620
  return ($memory_limit >= $memory)?true:false;
1621
  }
1622
 
1623
+ function wp_loaded() {
1624
+ // We are in the admin area: now load all that code
1625
+ require_once(UPDRAFTPLUS_DIR.'/admin.php');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1626
  }
1627
 
1628
  function url_start($urls,$url) {
1673
  }
1674
  }
1675
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1676
  function something_useful_happened() {
1677
  if ($this->current_resumption >= 9 && $this->newresumption_scheduled == false) {
1678
+ $this->log("This is resumption ".$this->current_resumption.", but meaningful activity is still taking place; so a new one will be scheduled");
1679
  $resume_interval = $this->jobdata_get('resume_interval');
1680
  if (!is_numeric($resume_interval) || $resume_interval<$this->minimum_resume_interval()) { $resume_interval = $this->minimum_resume_interval(); }
1681
  $schedule_for = time()+$resume_interval;
1682
  $this->newresumption_scheduled = $schedule_for;
 
1683
  wp_schedule_single_event($schedule_for, 'updraft_backup_resume', array($this->current_resumption + 1, $this->nonce));
1684
  } else {
1685
  $this->reschedule_if_needed();
1686
  }
1687
  }
1688
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1689
 
1690
  }
1691