PluginProbe
UpdraftPlus: WP Backup & Migration Plugin / 1.8.13
UpdraftPlus: WP Backup & Migration Plugin v1.8.13
1.26.7 1.26.6 1.26.5 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 All 371 releases
updraftplus / methods / dropbox.php

dropbox.php in UpdraftPlus: WP Backup & Migration Plugin 1.8.13, at methods/dropbox.php

432 lines 17.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // https://www.dropbox.com/developers/apply?cont=/developers/apps
4
5 class UpdraftPlus_BackupModule_dropbox {
6
7 private $current_file_hash;
8 private $current_file_size;
9
10 public function chunked_callback($offset, $uploadid, $fullpath = false) {
11 global $updraftplus;
12
13 // Update upload ID
14 $updraftplus->jobdata_set('updraf_dbid_'.$this->current_file_hash, $uploadid);
15 $updraftplus->jobdata_set('updraf_dbof_'.$this->current_file_hash, $offset);
16
17 if ($this->current_file_size > 0) {
18 $percent = round(100*($offset/$this->current_file_size),1);
19 $updraftplus->record_uploaded_chunk($percent, "$uploadid, $offset", $fullpath);
20 } else {
21 $updraftplus->log("Dropbox: Chunked Upload: $offset bytes uploaded");
22 // This act is done by record_uploaded_chunk, and helps prevent overlapping runs
23 touch($fullpath);
24 }
25 }
26
27 public function backup($backup_array) {
28
29 global $updraftplus, $updraftplus_backup;
30 $updraftplus->log("Dropbox: begin cloud upload");
31
32 if (!function_exists('mcrypt_encrypt')) {
33 $updraftplus->log('The required mcrypt PHP module is not installed');
34 $updraftplus->log(sprintf(__('The required %s PHP module is not installed - ask your web hosting company to enable it', 'updraftplus'), 'mcrypt'), 'error');
35 return false;
36 }
37
38 if (UpdraftPlus_Options::get_updraft_option('updraft_dropboxtk_request_token', '') == '') {
39 $updraftplus->log('You do not appear to be authenticated with Dropbox');
40 $updraftplus->log(__('You do not appear to be authenticated with Dropbox','updraftplus'), 'error');
41 return false;
42 }
43
44 try {
45 $dropbox = $this->bootstrap();
46 if (false === $dropbox) throw new Exception(__('You do not appear to be authenticated with Dropbox', 'updraftplus'));
47 $updraftplus->log("Dropbox: access gained");
48 $dropbox->setChunkSize(524288); // 512Kb
49 } catch (Exception $e) {
50 $updraftplus->log('Dropbox error when trying to gain access: '.$e->getMessage().' (line: '.$e->getLine().', file: '.$e->getFile().')');
51 $updraftplus->log(sprintf(__('Dropbox error: %s (see log file for more)','updraftplus'), $e->getMessage()), 'error');
52 return false;
53 }
54
55 $updraft_dir = $updraftplus->backups_dir_location();
56 $dropbox_folder = trailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_dropbox_folder'));
57
58 foreach ($backup_array as $file) {
59
60 $available_quota = -1;
61
62 // If we experience any failures collecting account info, then carry on anyway
63 try {
64
65 $accountInfo = $dropbox->accountInfo();
66
67 if ($accountInfo['code'] != "200") {
68 $message = "Dropbox account/info did not return HTTP 200; returned: ". $accountInfo['code'];
69 } elseif (!isset($accountInfo['body'])) {
70 $message = "Dropbox account/info did not return the expected data";
71 } else {
72 $body = $accountInfo['body'];
73 if (!isset($body->quota_info)) {
74 $message = "Dropbox account/info did not return the expected data";
75 } else {
76 $quota_info = $body->quota_info;
77 $total_quota = $quota_info->quota;
78 $normal_quota = $quota_info->normal;
79 $shared_quota = $quota_info->shared;
80 $available_quota = $total_quota - ($normal_quota + $shared_quota);
81 $message = "Dropbox quota usage: normal=".round($normal_quota/1048576,1)." Mb, shared=".round($shared_quota/1048576,1)." Mb, total=".round($total_quota/1048576,1)." Mb, available=".round($available_quota/1048576,1)." Mb";
82 }
83 }
84 $updraftplus->log($message);
85 } catch (Exception $e) {
86 $updraftplus->log("Dropbox error: exception occurred whilst getting account info: ".$e->getMessage());
87 }
88
89 $file_success = 1;
90
91 $hash = md5($file);
92 $this->current_file_hash = $hash;
93
94 $filesize = filesize($updraft_dir.'/'.$file);
95 $this->current_file_size = $filesize;
96
97 // Into Kb
98 $filesize = $filesize/1024;
99 $microtime = microtime(true);
100
101 if ($upload_id = $updraftplus->jobdata_get('updraf_dbid_'.$hash)) {
102 # Resume
103 $offset = $updraftplus->jobdata_get('updraf_dbof_'.$hash);
104 $updraftplus->log("This is a resumption: $offset bytes had already been uploaded");
105 } else {
106 $offset = 0;
107 $upload_id = null;
108 }
109
110 // We don't actually abort now - there's no harm in letting it try and then fail
111 if ($available_quota != -1 && $available_quota < ($filesize-$offset)) {
112 $updraftplus->log("File upload expected to fail: file data remaining to upload ($file) size is ".($filesize-$offset)." b (overall file size; $filesize b), whereas available quota is only $available_quota b");
113 $updraftplus->log(sprintf(__("Account full: your %s account has only %d bytes left, but the file to be uploaded has %d bytes remaining (total size: %d bytes)",'updraftplus'),'Dropbox', $available_quota, $filesize-$offset, $filesize), 'error');
114 }
115
116 // Old-style, single file put: $put = $dropbox->putFile($updraft_dir.'/'.$file, $dropbox_folder.$file);
117
118 $ourself = $this;
119
120 $ufile = apply_filters('updraftplus_dropbox_modpath', $file);
121
122 $updraftplus->log("Dropbox: Attempt to upload: $file to: $ufile");
123
124 try {
125 $response = $dropbox->chunkedUpload($updraft_dir.'/'.$file, '', $ufile, true, $offset, $upload_id, array($ourself, 'chunked_callback'));
126 if (empty($response['code']) || "200" != $response['code']) {
127 $updraftplus->log('Unexpected HTTP code returned from Dropbox: '.$response['code']." (".serialize($response).")");
128 $updraftplus->log(sprintf(__('%s did not return the expected response - check your log file for more details', 'updraftplus'), 'Dropbox'), 'warning');
129 }
130
131 } catch (Exception $e) {
132 $updraftplus->log("Dropbox chunked upload exception: ".$e->getMessage());
133 if (preg_match("/Submitted input out of alignment: got \[(\d+)\] expected \[(\d+)\]/i", $e->getMessage(), $matches)) {
134 // Try the indicated offset
135 $we_tried = $matches[1];
136 $dropbox_wanted = $matches[2];
137 $updraftplus->log("Dropbox not yet aligned: tried=$we_tried, wanted=$dropbox_wanted; will attempt recovery");
138 try {
139 $dropbox->chunkedUpload($updraft_dir.'/'.$file, '', $ufile, true, $dropbox_wanted, $upload_id, array($ourself, 'chunked_callback'));
140 } catch (Exception $e) {
141 $updraftplus->log('Dropbox error: '.$e->getMessage().' (line: '.$e->getLine().', file: '.$e->getFile().')');
142 $updraftplus->log('Dropbox '.sprintf(__('error: failed to upload file to %s (see log file for more)','updraftplus'), $ufile), 'error');
143 $file_success = 0;
144 }
145 } else {
146 $updraftplus->log('Dropbox error: '.$e->getMessage());
147 $updraftplus->log('Dropbox '.sprintf(__('error: failed to upload file to %s (see log file for more)','updraftplus'), $ufile), 'error');
148 $file_success = 0;
149 }
150 }
151 if ($file_success) {
152 $updraftplus->uploaded_file($file);
153 $microtime_elapsed = microtime(true)-$microtime;
154 $speedps = $filesize/$microtime_elapsed;
155 $speed = sprintf("%.2d",$filesize)." Kb in ".sprintf("%.2d",$microtime_elapsed)."s (".sprintf("%.2d", $speedps)." Kb/s)";
156 $updraftplus->log("Dropbox: File upload success (".$file."): $speed");
157 $updraftplus->jobdata_delete('updraft_duido_'.$hash);
158 $updraftplus->jobdata_delete('updraft_duidi_'.$hash);
159 }
160
161 }
162
163 return null;
164
165 }
166
167 public function defaults() {
168 return array('Z3Q3ZmkwbnplNHA0Zzlx', 'bTY0bm9iNmY4eWhjODRt');
169 }
170
171 public function delete($files) {
172
173 global $updraftplus;
174 if (is_string($files)) $files=array($files);
175
176 if (UpdraftPlus_Options::get_updraft_option('updraft_dropboxtk_request_token', 'xyz') == 'xyz') {
177 $updraftplus->log('You do not appear to be authenticated with Dropbox');
178 $updraftplus->log(sprintf(__('You do not appear to be authenticated with %s (whilst deleting)', 'updraftplus'), 'Dropbox'), 'warning');
179 return false;
180 }
181
182 try {
183 $dropbox = $this->bootstrap();
184 } catch (Exception $e) {
185 $updraftplus->log('Dropbox error: '.$e->getMessage().' (line: '.$e->getLine().', file: '.$e->getFile().')');
186 $updraftplus->log(sprintf(__('Failed to access %s when deleting (see log file for more)', 'updraftplus'), 'Dropbox'), 'warning');
187 return false;
188 }
189 if (false === $dropbox) return false;
190
191 foreach ($files as $file) {
192 $ufile = apply_filters('updraftplus_dropbox_modpath', $file);
193 $updraftplus->log("Dropbox: request deletion: $ufile");
194
195 try {
196 $dropbox->delete($ufile);
197 $file_success = 1;
198 } catch (Exception $e) {
199 $updraftplus->log('Dropbox error: '.$e->getMessage().' (line: '.$e->getLine().', file: '.$e->getFile().')');
200 }
201
202 if (isset($file_success)) {
203 $updraftplus->log('Dropbox: delete succeeded');
204 } else {
205 return false;
206 }
207 }
208
209 }
210
211 public function download($file) {
212
213 global $updraftplus;
214
215 if (UpdraftPlus_Options::get_updraft_option('updraft_dropboxtk_request_token', 'xyz') == 'xyz') {
216 $updraftplus->log('You do not appear to be authenticated with Dropbox');
217 $updraftplus->log(sprintf(__('You do not appear to be authenticated with %s','updraftplus'), 'Dropbox'), 'error');
218 return false;
219 }
220
221 try {
222 $dropbox = $this->bootstrap();
223 } catch (Exception $e) {
224 $updraftplus->log('Dropbox error: '.$e->getMessage().' (line: '.$e->getLine().', file: '.$e->getFile().')');
225 $updraftplus->log('Dropbox error: '.$e->getMessage().' (line: '.$e->getLine().', file: '.$e->getFile().')', 'error');
226 return false;
227 }
228 if (false === $dropbox) return false;
229
230 $updraft_dir = $updraftplus->backups_dir_location();
231 $microtime = microtime(true);
232
233 $try_the_other_one = false;
234
235 $ufile = apply_filters('updraftplus_dropbox_modpath', $file);
236
237 try {
238 $get = $dropbox->getFile($ufile, $updraft_dir.'/'.$file, null, true);
239 } catch (Exception $e) {
240 // TODO: Remove this October 2013 (we stored in the wrong place for a while...)
241 $try_the_other_one = true;
242 $possible_error = $e->getMessage();
243 $updraftplus->log('Dropbox error: '.$e);
244 $get = false;
245 }
246
247 // TODO: Remove this October 2013 (we stored files in the wrong place for a while...)
248 if ($try_the_other_one) {
249 $dropbox_folder = trailingslashit(UpdraftPlus_Options::get_updraft_option('updraft_dropbox_folder'));
250 try {
251 $get = $dropbox->getFile($dropbox_folder.'/'.$file, $updraft_dir.'/'.$file, null, true);
252 if (isset($get['response']['body'])) {
253 $updraftplus->log("Dropbox: downloaded ".round(strlen($get['response']['body'])/1024,1).' Kb');
254 }
255 } catch (Exception $e) {
256 $updraftplus->log($possible_error, 'error');
257 $updraftplus->log($e->getMessage(), 'error');
258 $get = false;
259 }
260 }
261
262 return $get;
263
264 }
265
266 public function config_print() {
267 ?>
268 <tr class="updraftplusmethod dropbox">
269 <td></td>
270 <td>
271 <img alt="<?php _e(sprintf(__('%s logo', 'updraftplus'), 'Dropbox')); ?>" src="<?php echo UPDRAFTPLUS_URL.'/images/dropbox-logo.png' ?>">
272 <p><em><?php printf(__('%s is a great choice, because UpdraftPlus supports chunked uploads - no matter how big your site is, UpdraftPlus can upload it a little at a time, and not get thwarted by timeouts.','updraftplus'),'Dropbox');?></em></p>
273 </td>
274 </tr>
275
276 <tr class="updraftplusmethod dropbox">
277 <th></th>
278 <td>
279 <?php
280 // Check requirements.
281 global $updraftplus_admin;
282 if (!function_exists('mcrypt_encrypt')) {
283 $updraftplus_admin->show_double_warning('<strong>'.__('Warning','updraftplus').':</strong> '. sprintf(__('Your web server\'s PHP installation does not included a required module (%s). Please contact your web hosting provider\'s support and ask for them to enable it.', 'updraftplus'), 'mcrypt'));
284 /*
285 .' '.sprintf(__("UpdraftPlus's %s module <strong>requires</strong> %s. Please do not file any support requests; there is no alternative.",'updraftplus'),'Dropbox', 'mcrypt'), 'dropbox')
286 */
287 }
288 $updraftplus_admin->curl_check('Dropbox', false, 'dropbox');
289 ?>
290 </td>
291 </tr>
292
293 <?php
294
295 $defmsg = '<tr class="updraftplusmethod dropbox"><td></td><td><strong>'.__('Need to use sub-folders?','updraftplus').'</strong> '.__('Backups are saved in','updraftplus').' apps/UpdraftPlus. '.__('If you back up several sites into the same Dropbox and want to organise with sub-folders, then ','updraftplus').'<a href="http://updraftplus.com/shop/">'.__("there's an add-on for that.",'updraftplus').'</a></td></tr>';
296
297 echo apply_filters('updraftplus_dropbox_extra_config', $defmsg); ?>
298
299 <tr class="updraftplusmethod dropbox">
300 <th><?php _e('Authenticate with Dropbox','updraftplus');?>:</th>
301 <td><p><?php if (UpdraftPlus_Options::get_updraft_option('updraft_dropboxtk_request_token','') != '') echo "<strong>".__('(You appear to be already authenticated)','updraftplus').".</strong>"; ?> <a href="?page=updraftplus&action=updraftmethod-dropbox-auth&updraftplus_dropboxauth=doit"><?php echo __('<strong>After</strong> you have saved your settings (by clicking \'Save Changes\' below), then come back here once and click this link to complete authentication with Dropbox.','updraftplus');?></a>
302 </p>
303 </td>
304 </tr>
305
306 <?php
307 // Legacy: only show this next setting to old users who had a setting stored
308 if (UpdraftPlus_Options::get_updraft_option('updraft_dropbox_appkey')) {
309 ?>
310
311 <tr class="updraftplusmethod dropbox">
312 <th>Your Dropbox App Key:</th>
313 <td><input type="text" autocomplete="off" style="width:332px" id="updraft_dropbox_appkey" name="updraft_dropbox_appkey" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_dropbox_appkey')) ?>" /></td>
314 </tr>
315 <tr class="updraftplusmethod dropbox">
316 <th>Your Dropbox App Secret:</th>
317 <td><input type="text" style="width:332px" id="updraft_dropbox_secret" name="updraft_dropbox_secret" value="<?php echo htmlspecialchars(UpdraftPlus_Options::get_updraft_option('updraft_dropbox_secret')); ?>" /></td>
318 </tr>
319
320 <?php } ?>
321
322 <?php
323 }
324
325 public function action_auth() {
326 if ( isset( $_GET['oauth_token'] ) ) {
327 $this->auth_token();
328 } elseif (isset($_GET['updraftplus_dropboxauth'])) {
329 // Clear out the existing credentials
330 if ('doit' == $_GET['updraftplus_dropboxauth']) {
331 UpdraftPlus_Options::update_updraft_option('updraft_dropboxtk_request_token', '');
332 UpdraftPlus_Options::update_updraft_option('updraft_dropboxtk_access_token', '');
333 }
334 try {
335 $this->auth_request();
336 } catch (Exception $e) {
337 global $updraftplus;
338 $updraftplus->log(sprintf(__("%s error: %s", 'updraftplus'), sprintf(__("%s authentication", 'updraftplus'), 'Dropbox'), $e->getMessage()), 'error');
339 }
340 }
341 }
342
343 public function show_authed_admin_warning() {
344 global $updraftplus_admin;
345
346 $dropbox = $this->bootstrap();
347 if (false === $dropbox) return false;
348 $accountInfo = $dropbox->accountInfo();
349
350 $message = "<strong>".__('Success','updraftplus').'</strong>: '.sprintf(__('you have authenticated your %s account','updraftplus'),'Dropbox');
351
352 if (empty($accountInfo['code']) || "200" != $accountInfo['code']) {
353 $message .= " (".__('though part of the returned information was not as expected - your mileage may vary','updraftplus').")". $accountInfo['code'];
354 } else {
355 $body = $accountInfo['body'];
356 $message .= ". <br>".sprintf(__('Your %s account name: %s','updraftplus'),'Dropbox', htmlspecialchars($body->display_name));
357
358 try {
359 $quota_info = $body->quota_info;
360 $total_quota = max($quota_info->quota, 1);
361 $normal_quota = $quota_info->normal;
362 $shared_quota = $quota_info->shared;
363 $available_quota =$total_quota - ($normal_quota + $shared_quota);
364 $used_perc = round(($normal_quota + $shared_quota)*100/$total_quota, 1);
365 $message .= ' <br>'.sprintf(__('Your %s quota usage: %s %% used, %s available','updraftplus'), 'Dropbox', $used_perc, round($available_quota/1048576, 1).' Mb');
366 } catch (Exception $e) {
367 }
368
369 }
370 $updraftplus_admin->show_admin_warning($message);
371
372 }
373
374 public function auth_token() {
375 $previous_token = UpdraftPlus_Options::get_updraft_option('updraft_dropboxtk_request_token', '');
376 $this->bootstrap();
377 $new_token = UpdraftPlus_Options::get_updraft_option("updraft_dropboxtk_request_token", '');
378 if ($new_token) {
379 add_action('all_admin_notices', array($this, 'show_authed_admin_warning') );
380 }
381 }
382
383 // Acquire single-use authorization code
384 public function auth_request() {
385 $this->bootstrap();
386 }
387
388 // This basically reproduces the relevant bits of bootstrap.php from the SDK
389 public function bootstrap() {
390
391 require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/API.php' );
392 require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/Exception.php');
393 require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/API.php');
394 require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/OAuth/Consumer/ConsumerAbstract.php');
395 require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/OAuth/Storage/StorageInterface.php');
396 require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/OAuth/Storage/Encrypter.php');
397 require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/OAuth/Storage/WordPress.php');
398 require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/OAuth/Consumer/Curl.php');
399 // require_once(UPDRAFTPLUS_DIR.'/includes/Dropbox/OAuth/Consumer/WordPress.php');
400
401 $key = UpdraftPlus_Options::get_updraft_option('updraft_dropbox_secret');
402 $sec = UpdraftPlus_Options::get_updraft_option('updraft_dropbox_appkey');
403
404 // Set the callback URL
405 $callback = UpdraftPlus_Options::admin_page_url().'?page=updraftplus&action=updraftmethod-dropbox-auth';
406
407 // Instantiate the Encrypter and storage objects
408 $encrypter = new Dropbox_Encrypter('ThisOneDoesNotMatterBeyondLength');
409
410 // Instantiate the storage
411 $storage = new Dropbox_WordPress($encrypter, "updraft_dropboxtk_");
412
413 // WordPress consumer does not yet work
414 // $OAuth = new Dropbox_ConsumerWordPress($sec, $key, $storage, $callback);
415
416 // Get the DropBox API access details
417 list($d2, $d1) = $this->defaults();
418 if (empty($sec)) { $sec = base64_decode($d1); }; if (empty($key)) { $key = base64_decode($d2); }
419
420 try {
421 $OAuth = new Dropbox_Curl($sec, $key, $storage, $callback);
422 } catch (Exception $e) {
423 global $updraftplus;
424 $updraftplus->log("Dropbox Curl error: ".$e->getMessage());
425 $updraftplus->log(sprintf(__("%s error: %s", 'updraftplus'), "Dropbox/Curl", $e->getMessage()), 'error');
426 return false;
427 }
428 return new Dropbox_API($OAuth);
429 }
430
431 }
432