PluginProbe ʕ •ᴥ•ʔ
UpdraftPlus: WP Backup & Migration Plugin / 1.16.22
UpdraftPlus: WP Backup & Migration Plugin v1.16.22
1.26.4 1.26.3 1.9.19 1.9.25 1.9.26 1.9.30 1.9.31 1.9.32 1.9.4 1.9.40 1.9.41 1.9.42 1.9.43 1.9.44 1.9.45 1.9.46 1.9.5 1.9.50 1.9.51 1.9.60 1.9.62 1.9.63 1.9.64 1.11.12 1.4.8 1.11.15 1.4.9 1.11.17 1.5.16 1.11.18 1.5.20 1.11.2 1.5.21 1.11.20 1.5.22 1.11.23 1.5.5 1.11.24 1.5.6 1.11.25 1.5.7 1.11.26 1.5.8 1.11.27 1.5.9 1.11.28 1.6.1 1.11.3 1.6.17 1.11.4 1.6.2 1.11.5 1.6.46 1.11.8 1.7.0 1.11.9 1.7.1 1.12.0 1.7.18 1.12.1 1.7.20 1.12.12 1.7.3 1.12.13 1.7.34 1.12.15 1.7.35 1.12.17 1.7.39 1.12.2 1.7.40 1.12.20 1.7.41 1.12.23 1.8.1 1.12.24 1.8.11 1.12.25 1.8.12 1.12.28 1.8.13 1.12.29 1.8.2 1.12.30 1.8.5 1.12.32 1.8.8 1.12.34 1.9.0 1.12.35 1.9.13 1.12.37 1.9.15 1.12.39 1.9.17 1.12.4 1.12.40 1.12.6 1.13.1 1.13.11 1.13.12 1.13.15 1.13.16 1.13.2 1.13.3 1.13.4 1.13.5 1.13.6 1.13.7 1.13.8 1.13.9 1.14.10 1.14.11 1.14.12 1.14.13 1.14.2 1.14.3 1.14.4 1.14.5 1.14.7 1.14.9 1.15.0 1.15.2 1.15.3 1.15.5 1.15.6 1.15.7 1.16.0 1.16.10 1.16.11 1.16.12 1.16.13 1.16.14 1.16.15 1.16.16 1.16.17 1.16.20 1.16.21 1.16.22 1.16.23 1.16.24 1.16.25 1.16.26 1.16.28 1.16.29 1.16.32 1.16.34 1.16.35 1.16.36 1.16.37 1.16.4 1.16.40 1.16.41 1.16.42 1.16.43 1.16.44 1.16.45 1.16.46 1.16.47 1.16.48 1.16.49 1.16.5 1.16.50 1.16.51 1.16.53 1.16.55 1.16.56 1.16.59 1.16.6 1.16.60 1.16.61 1.16.62 1.16.63 1.16.64 1.16.65 1.16.66 1.16.67 1.16.68 1.16.69 1.16.7 1.16.8 1.16.9 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.14 1.2.15 1.2.16 1.2.17 1.2.19 1.2.2 1.2.20 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.33 1.2.35 1.2.36 1.2.38 1.2.39 1.2.4 1.2.40 1.2.41 1.2.42 1.2.43 1.2.44 1.2.45 1.2.46 1.2.5 1.2.7 1.2.8 1.2.9 1.22.1 1.22.10 1.22.11 1.22.12 1.22.14 1.22.15 1.22.16 1.22.17 1.22.18 1.22.19 1.22.20 1.22.21 1.22.22 1.22.23 1.22.24 1.22.3 1.22.4 1.22.5 1.22.6 1.22.7 1.22.8 1.22.9 1.23.1 1.23.10 1.23.11 1.23.12 1.23.13 1.23.15 1.23.16 1.23.2 1.23.3 1.23.4 1.23.5 1.23.6 1.23.7 1.23.8 1.23.9 1.24.1 1.24.10 1.24.11 1.24.12 1.24.2 trunk 1.24.3 0.7.4 1.24.4 0.7.7 1.24.5 0.8.28 1.24.6 0.8.29 1.24.7 0.8.30 1.24.8 0.8.31 1.24.9 0.8.32 1.25.1 0.8.33 1.25.2 0.8.36 1.25.3 0.8.37 1.25.5 0.8.50 1.25.6 0.8.51 1.25.7 0.9.1 1.25.8 0.9.10 1.25.9 0.9.11 1.26.1 0.9.12 1.26.2 0.9.2 1.3.10 0.9.20 1.3.12 0.9.21 1.3.14 0.9.22 1.3.15 1.0.10 1.3.17 1.0.11 1.3.18 1.0.12 1.3.19 1.0.15 1.3.2 1.0.16 1.3.20 1.0.18 1.3.22 1.0.20 1.3.23 1.0.3 1.3.24 1.0.4 1.3.25 1.0.5 1.3.3 1.0.6 1.3.4 1.0.7 1.3.6 1.0.8 1.3.7 1.0.9 1.3.8 1.1.0 1.3.9 1.1.10 1.4.0 1.1.11 1.4.10 1.1.12 1.4.11 1.1.13 1.4.12 1.1.14 1.4.13 1.1.15 1.4.14 1.1.16 1.4.15 1.1.17 1.4.2 1.1.2 1.4.27 1.1.3 1.4.28 1.1.5 1.4.29 1.1.6 1.4.30 1.1.8 1.4.4 1.1.9 1.4.48 1.10.1 1.4.5 1.10.3 1.4.6 1.11.1 1.4.7
updraftplus / methods / addon-base-v2.php
updraftplus / methods Last commit date
addon-base-v2.php 6 years ago addon-not-yet-present.php 6 years ago azure.php 8 years ago backblaze.php 8 years ago backup-module.php 6 years ago cloudfiles-new.php 6 years ago cloudfiles.php 6 years ago dreamobjects.php 7 years ago dropbox.php 6 years ago email.php 6 years ago ftp.php 6 years ago googlecloud.php 8 years ago googledrive.php 6 years ago insufficient.php 6 years ago onedrive.php 8 years ago openstack-base.php 6 years ago openstack.php 8 years ago openstack2.php 6 years ago remotesend.php 6 years ago s3.php 6 years ago s3generic.php 7 years ago sftp.php 8 years ago template.php 6 years ago updraftvault.php 6 years ago webdav.php 8 years ago
addon-base-v2.php
372 lines
1 <?php
2
3 if (!defined('UPDRAFTPLUS_DIR')) die('No direct access allowed');
4
5 /*
6 Methods to define when extending this class (can use $this->storage and $this->options where relevant):
7 do_bootstrap($possible_options_array) # Return a WP_Error object if something goes wrong
8 do_upload($file, $sourcefile) # Return true/false
9 do_listfiles($match)
10 do_delete($file) - return true/false
11 do_download($file, $fullpath, $start_offset) - return true/false
12 do_config_print()
13 get_credentials_test_required_parameters() - return an array: keys = required _POST parameters; values = description of each
14 do_credentials_test($testfile, $posted_settings) - return true/false; or alternatively an array with keys 'result' (true/false) and 'data' (arbitrary debug data)
15 do_credentials_test_deletefile($testfile, $posted_settings)
16 */
17
18 // Uses job options: Yes
19 // Uses single-array storage: Yes
20
21 if (!class_exists('UpdraftPlus_BackupModule')) require_once(UPDRAFTPLUS_DIR.'/methods/backup-module.php');
22
23 /**
24 * Note that the naming of this class is historical. There is nothing inherent which restricts it to add-ons, or requires add-ons to use it. It is just an abstraction layer that results in needing to write less code for the storage module.
25 */
26 abstract class UpdraftPlus_RemoteStorage_Addons_Base_v2 extends UpdraftPlus_BackupModule {
27
28 protected $method;
29
30 protected $description;
31
32 protected $options;
33
34 private $chunked;
35
36 public function __construct($method, $description, $chunked = true, $test_button = true) {
37
38 $this->method = $method;
39 $this->description = $description;
40 $this->chunked = $chunked;
41 $this->test_button = $test_button;
42
43 }
44
45 /**
46 * download method: takes a file name (base name), and removes it from the cloud storage
47 *
48 * @param string $file specific file for being removed from cloud storage
49 * @return array
50 */
51 public function download($file) {
52 return $this->download_file(false, $file);
53 }
54
55 public function backup($backup_array) {
56 return $this->upload_files(null, $backup_array);
57 }
58
59 public function delete($files, $method_obj = false, $sizeinfo = array()) {
60 return $this->delete_files(false, $files, $method_obj, $sizeinfo);
61 }
62
63 protected function required_configuration_keys() {
64 }
65
66 public function upload_files($ret, $backup_array) {// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
67
68 global $updraftplus;
69
70 $this->options = $this->get_options();
71
72 if (!$this->options_exist($this->options)) {
73 $this->log('No settings were found');
74 $this->log(sprintf(__('No %s settings were found', 'updraftplus'), $this->description), 'error');
75 return false;
76 }
77
78 $storage = $this->bootstrap();
79 if (is_wp_error($storage)) return $updraftplus->log_wp_error($storage, false, true);
80
81 $this->set_storage($storage);
82
83 $updraft_dir = trailingslashit($updraftplus->backups_dir_location());
84
85 foreach ($backup_array as $file) {
86 $this->log("upload ".((!empty($this->options['ownername'])) ? '(account owner: '.$this->options['ownername'].')' : '').": attempt: $file");
87 try {
88 if ($this->do_upload($file, $updraft_dir.$file)) {
89 $updraftplus->uploaded_file($file);
90 } else {
91 $any_failures = true;
92 $this->log('ERROR: Failed to upload file: '.$file);
93 $this->log(__('Error', 'updraftplus').': '.$this->description.': '.sprintf(__('Failed to upload %s', 'updraftplus'), $file), 'error');
94 }
95 } catch (Exception $e) {
96 $any_failures = true;
97 $this->log('ERROR ('.get_class($e).'): '.$file.': Failed to upload file: '.$e->getMessage().' (code: '.$e->getCode().', line: '.$e->getLine().', file: '.$e->getFile().')');
98 $this->log(__('Error', 'updraftplus').': '.$this->description.': '.sprintf(__('Failed to upload %s', 'updraftplus'), $file), 'error');
99 }
100 }
101
102 return (!empty($any_failures)) ? null : true;
103
104 }
105
106 public function listfiles($match = 'backup_') {
107
108 try {
109
110 if (!method_exists($this, 'do_listfiles')) {
111 return new WP_Error('no_listing', 'This remote storage method does not support file listing');
112 }
113
114 $this->options = $this->get_options();
115 if (!$this->options_exist($this->options)) return new WP_Error('no_settings', sprintf(__('No %s settings were found', 'updraftplus'), $this->description));
116
117 $storage = $this->bootstrap();
118 if (is_wp_error($storage)) return $storage;
119
120 return $this->do_listfiles($match);
121
122 } catch (Exception $e) {
123 $this->log('ERROR: Failed to list files: '.$e->getMessage().' (code: '.$e->getCode().', line: '.$e->getLine().', file: '.$e->getFile().')');
124 return new WP_Error('list_failed', $this->description.': '.__('failed to list files', 'updraftplus'));
125 }
126
127 }
128
129 /**
130 * This function handles bootstrapping and calling the remote methods delete function
131 *
132 * @param boolean $ret - A boolean value
133 * @param array $files - An array of files to delete.
134 * @param boolean $ignore_it - unused parameter
135 *
136 * @return - On success returns true, false or WordPress Error on failure
137 */
138 public function delete_files($ret, $files, $ignore_it = false) {// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
139
140 global $updraftplus;
141
142 if (is_string($files)) $files = array($files);
143
144 if (empty($files)) return true;
145 if (!method_exists($this, 'do_delete')) {
146 $this->log("Delete failed: this storage method does not allow deletions");
147 return false;
148 }
149
150 $storage = $this->get_storage();
151
152 if (empty($storage)) {
153
154 $this->options = $this->get_options();
155 if (!$this->options_exist($this->options)) {
156 $this->log('No settings were found');
157 $this->log(sprintf(__('No %s settings were found', 'updraftplus'), $this->description), 'error');
158 return false;
159 }
160
161 $storage = $this->bootstrap();
162 if (is_wp_error($storage)) return $storage;
163
164 }
165
166 $ret = true;
167
168 if ($this->supports_feature('multi_delete')) {
169 $updraftplus->log("Delete remote files: ".implode($files));
170 try {
171 $responses = $this->do_delete($files);
172
173 if (is_array($responses)) {
174 foreach ($responses as $key => $response) {
175 if ('success' == $response) {
176 $updraftplus->log("$files[$key]: Delete succeeded");
177 } elseif (is_array($response)) {
178 $ret = false;
179 if (isset($response['error']) && isset($response['error']['code']) && isset($response['error']['message'])) {
180 $updraftplus->log("Delete failed for file: $files[$key] with error code: ".$response['error']['code']." message: ".$response['error']['message']);
181 } else {
182 $updraftplus->log("Delete failed for file: $files[$key]");
183 }
184 }
185 }
186 } elseif (!$responses) {
187 $ret = false;
188 $updraftplus->log("Delete failed for files: ".implode($files));
189 }
190 } catch (Exception $e) {
191 $updraftplus->log('ERROR:'.implode($files).': Failed to delete files: '.$e->getMessage().' (code: '.$e->getCode().', line: '.$e->getLine().', file: '.$e->getFile().')');
192 $ret = false;
193 }
194
195 return $ret;
196 }
197
198 foreach ($files as $file) {
199 $this->log("Delete remote: $file");
200 try {
201 if (!$this->do_delete($file)) {
202 $ret = false;
203 $this->log("Delete failed");
204 } else {
205 $this->log("$file: Delete succeeded");
206 }
207 } catch (Exception $e) {
208 $this->log('ERROR: '.$file.': Failed to delete file: '.$e->getMessage().' (code: '.$e->getCode().', line: '.$e->getLine().', file: '.$e->getFile().')');
209 $ret = false;
210 }
211 }
212
213 return $ret;
214
215 }
216
217 public function download_file($ret, $files) {
218
219 global $updraftplus;
220
221 if (is_string($files)) $files = array($files);
222
223 if (empty($files)) return true;
224 if (!method_exists($this, 'do_download')) {
225 $this->log("Download failed: this storage method does not allow downloading");
226 $this->log(__('This storage method does not allow downloading', 'updraftplus'), 'error');
227 return false;
228 }
229
230 $this->options = $this->get_options();
231 if (!$this->options_exist($this->options)) {
232 $this->log('No settings were found');
233 $this->log(sprintf(__('No %s settings were found', 'updraftplus'), $this->description), 'error');
234 return false;
235 }
236
237 try {
238 $storage = $this->bootstrap();
239 if (is_wp_error($storage)) return $updraftplus->log_wp_error($storage, false, true);
240 } catch (Exception $e) {
241 $ret = false;
242 $this->log('ERROR: '.$files[0].': Failed to download file: '.$e->getMessage().' (code: '.$e->getCode().', line: '.$e->getLine().', file: '.$e->getFile().')');
243 $this->log(__('Error', 'updraftplus').': '.$this->description.': '.sprintf(__('Failed to download %s', 'updraftplus'), $files[0]), 'error');
244 }
245
246 $ret = true;
247 $updraft_dir = untrailingslashit($updraftplus->backups_dir_location());
248
249 foreach ($files as $file) {
250 try {
251 $fullpath = $updraft_dir.'/'.$file;
252 $start_offset = file_exists($fullpath) ? filesize($fullpath) : 0;
253
254 if (false == $this->do_download($file, $fullpath, $start_offset)) {
255 $ret = false;
256 $this->log("error: failed to download: $file");
257 $this->log("$file: ".sprintf(__("%s Error", 'updraftplus'), $this->description).": ".__('Failed to download', 'updraftplus'), 'error');
258 }
259
260 } catch (Exception $e) {
261 $ret = false;
262 $this->log('ERROR: '.$file.': Failed to download file: '.$e->getMessage().' (code: '.$e->getCode().', line: '.$e->getLine().', file: '.$e->getFile().')');
263 $this->log(__('Error', 'updraftplus').': '.$this->description.': '.sprintf(__('Failed to download %s', 'updraftplus'), $file), 'error');
264 }
265 }
266
267 return $ret;
268 }
269
270 /**
271 * Get the configuration template
272 *
273 * @return String - the template, ready for substitutions to be carried out
274 */
275 public function get_configuration_template() {
276 $template_str = '';
277
278 if (method_exists($this, 'do_get_configuration_template')) {
279 $template_str .= $this->do_get_configuration_template();
280 }
281 if (!$this->test_button || (method_exists($this, 'should_print_test_button') && !$this->should_print_test_button())) return $template_str;
282 $template_str .= $this->get_test_button_html($this->description);
283 return $template_str;
284 }
285
286 /**
287 * Modifies handerbar template options
288 *
289 * @param array $opts
290 * @return array - Modified handerbar template options
291 */
292 public function transform_options_for_template($opts) {
293 if (method_exists($this, 'do_transform_options_for_template')) {
294 $opts = $this->do_transform_options_for_template($opts);
295 }
296 return $opts;
297 }
298
299 public function config_print_javascript_onready() {
300 $this->do_config_javascript();
301 }
302
303 protected function do_config_javascript() {
304 }
305
306 /**
307 * Analyse the passed-in options to indicate whether something is configured or not.
308 *
309 * @param Array $opts - options to examine
310 *
311 * @return Boolean
312 */
313 public function options_exist($opts) {
314 if (is_array($opts) && !empty($opts)) return true;
315 return false;
316 }
317
318 public function bootstrap($opts = false, $connect = true) {
319 if (false === $opts) $opts = $this->options;
320 $storage = $this->get_storage();
321 // Be careful of checking empty($opts) here - some storage methods may have no options until the OAuth token has been obtained
322 if ($connect && !$this->options_exist($opts)) return new WP_Error('no_settings', sprintf(__('No %s settings were found', 'updraftplus'), $this->description));
323 if (!empty($storage) && !is_wp_error($storage)) return $storage;
324 return $this->do_bootstrap($opts, $connect);
325 }
326
327 /**
328 * Run a credentials test. Output can be echoed.
329 *
330 * @param Array $posted_settings - settings to use
331 *
332 * @return Mixed - any data to return (gets logged in the browser eventually)
333 */
334 public function credentials_test($posted_settings) {
335
336 $required_test_parameters = $this->get_credentials_test_required_parameters();
337
338 foreach ($required_test_parameters as $param => $descrip) {
339 if (empty($posted_settings[$param])) {
340 printf(__("Failure: No %s was given.", 'updraftplus'), $descrip)."\n";
341 return;
342 }
343 }
344
345 $storage = $this->bootstrap($posted_settings);
346
347 if (is_wp_error($storage)) {
348 echo __("Failed", 'updraftplus').": ";
349 foreach ($storage->get_error_messages() as $key => $msg) {
350 echo "$msg\n";
351 }
352 return;
353 }
354
355 $testfile = md5(time().rand()).'.txt';
356
357 $test_results = $this->do_credentials_test($testfile, $posted_settings);
358
359 $data = (is_array($test_results) && isset($test_results['data'])) ? $test_results['data'] : null;
360
361 if ((is_array($test_results) && $test_results['result']) || (!is_array($test_results) && $test_results)) {
362 _e('Success', 'updraftplus');
363 $this->do_credentials_test_deletefile($testfile, $posted_settings);
364 } else {
365 _e("Failed: We were not able to place a file in that directory - please check your credentials.", 'updraftplus');
366 }
367
368 return $data;
369
370 }
371 }
372