PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 2.1.7
Backup Migration v2.1.7
2.1.7 2.1.6 2.1.5.2 trunk 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.6.1 1.4.7 1.4.8 1.4.9 1.4.9.1 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.5.1
backup-backup / includes / ajax_offline.php
backup-backup / includes Last commit date
banner 2 weeks ago bodies 2 weeks ago check 2 weeks ago cli 2 weeks ago cron 2 weeks ago dashboard 2 weeks ago database 2 weeks ago external 2 weeks ago extracter 2 weeks ago htaccess 2 weeks ago notices 2 weeks ago progress 2 weeks ago scanner 2 weeks ago services 2 weeks ago staging 2 weeks ago traits 2 weeks ago uploader 2 weeks ago vendor 2 weeks ago zipper 2 weeks ago .htaccess 2 weeks ago activation.php 2 weeks ago ajax.php 2 weeks ago ajax_offline.php 2 weeks ago analyst.php 2 weeks ago backup-process.php 2 weeks ago class-backup-method-mananger.php 2 weeks ago cli-handler.php 2 weeks ago compatibility.php 2 weeks ago config.php 2 weeks ago config_v2.php 2 weeks ago constants.php 2 weeks ago file-explorer.php 2 weeks ago initializer.php 2 weeks ago logger.php 2 weeks ago offline.php 2 weeks ago
ajax_offline.php
891 lines
1 <?php
2
3 // Namespace
4 namespace BMI\Plugin;
5
6 // Uses
7 use BMI\Plugin\Backup_Migration_Plugin as BMP;
8 use BMI\Plugin\BMI_Logger as Logger;
9 use BMI\Plugin\BMI_Pro_Core;
10 use BMI\Plugin\BMProAjax as BMProAjax;
11 use BMI\Plugin\Scanner\BMI_BackupsScanner as Backups;
12 use BMI\Plugin\External\BMI_External_BackupBliss as BackupBliss;
13 use BMI\Plugin\External\BMI_External_Dropbox as Dropbox;
14 use BMI\Plugin\External\BMI_External_GDrive as GDrive;
15 use BMI\Plugin\External\BMI_External_FTP as FTP;
16 use BMI\Plugin\External\BMI_External_S3 as S3;
17 use BMI\Plugin\Dashboard as Dashboard;
18
19 // Exit on direct access
20 if (!defined('ABSPATH')) exit;
21
22 /**
23 * Ajax Offline (unauthorized) Handler for BMI
24 */
25 class BMI_Ajax_Offline
26 {
27
28 public $post;
29 public $backupbliss;
30 public $dropbox;
31 public $gdrive;
32 public $ftp;
33 public $aws;
34 public $wasabi;
35 public $proajax;
36
37
38 public $dropboxStatus = false;
39 public $gdriveStatus = false;
40 public $ftpStatus = false;
41 public $awsStatus = false;
42 public $wasabiStatus = false;
43
44 public function __construct($post)
45 {
46
47 // $POST is sanitized by BMI Basic Version
48 // Do not call this class anywhere else [!]
49 $this->post = $post;
50
51 // Active offline ajax premium side
52 if (defined('BMI_PRO_INC')) {
53 if (BMI_DEBUG)
54 Logger::error("PREMIUM CHECK");
55
56 require_once BMI_PRO_INC . 'ajax_offline.php';
57 $this->proajax = new BMI_Ajax_Offline_Premium($post);
58 }
59
60 $isDropboxEnabled = Dashboard\bmi_get_config('STORAGE::EXTERNAL::DROPBOX');
61 $isGDriveEnabled = Dashboard\bmi_get_config('STORAGE::EXTERNAL::GDRIVE');
62 $isFtpEnabled = Dashboard\bmi_get_config('STORAGE::EXTERNAL::FTP');
63 $isAWSEnabled = Dashboard\bmi_get_config('STORAGE::EXTERNAL::AWS');
64 $isWasabiEnabled = Dashboard\bmi_get_config('STORAGE::EXTERNAL::WASABI');
65
66 $isEnabledDropbox = ($isDropboxEnabled === true || $isDropboxEnabled === 'true') && $this->getDropboxConnectionStatus();
67 $isEnabledGdrive = ($isGDriveEnabled === true || $isGDriveEnabled === 'true') && $this->getGDriveConnectionStatus();
68 $isEnabledFtp = ($isFtpEnabled === true || $isFtpEnabled === 'true') && $this->getFtpConnectionStatus();
69 $isEnabledAWS = ($isAWSEnabled === true || $isAWSEnabled === 'true') && $this->getAWSConnectionStatus();
70 $isEnabledWasabi = ($isWasabiEnabled === true || $isWasabiEnabled === 'true') && $this->getWasabiConnectionStatus();
71
72 if ($isEnabledDropbox) {
73 require_once BMI_INCLUDES . '/external/dropbox.php';
74 $this->dropbox = new Dropbox();
75 }
76
77 if ($isEnabledGdrive) {
78 require_once BMI_INCLUDES . '/external/google-drive.php';
79 $this->gdrive = new GDrive();
80 }
81
82 if ($isEnabledFtp) {
83 require_once BMI_INCLUDES . '/external/ftp.php';
84 $this->ftp = new FTP();
85 }
86
87 if ($isEnabledAWS) {
88 require_once BMI_INCLUDES . '/external/s3.php';
89 $this->aws = new S3('aws');
90 }
91
92 if ($isEnabledWasabi) {
93 require_once BMI_INCLUDES . '/external/s3.php';
94 $this->wasabi = new S3('wasabi');
95 }
96
97 require_once BMI_INCLUDES . '/external/backupbliss.php';
98 $this->backupbliss = new BackupBliss();
99
100 if (is_user_logged_in() && current_user_can('manage_options')) {
101 if (isset($this->post['f']) && $this->post['f'] == 'check-not-uploaded-backups') {
102
103 $this->checkForBackupsToUpload();
104
105 if ($this->proajax)
106 $this->proajax->checkForBackupsToUpload();
107
108 BMP::res(['status' => 'success']);
109 }
110 }
111
112 if (isset($this->post['f']) && $this->post['f'] == 'refresh') {
113 BMP::res($this->keepAliveUnAuthorizedRefresh());
114 }
115
116 }
117
118 public function getWasabiConnectionStatus() {
119 require_once BMI_INCLUDES . '/external/s3.php';
120
121 $s3 = new S3('wasabi');
122 $status = $s3->verifyConnection();
123 if (isset($status['result']) && $status['result'] == 'connected') {
124 $this->wasabiStatus = true;
125 return true;
126 } else {
127 return false;
128 }
129 }
130
131
132 public function getDropboxConnectionStatus() {
133 require_once BMI_INCLUDES . '/external/dropbox.php';
134
135 $dropbox = new Dropbox();
136 $status = $dropbox->verifyConnection();
137 if (isset($status['result']) && $status['result'] == 'connected') {
138 $this->dropboxStatus = true;
139 return true;
140 } else {
141 return false;
142 }
143 }
144
145 /**
146 * getGDriveConnectionStatus - Returns Connection Status for PHP
147 *
148 * @return boolean true on connected | false on disconnected
149 */
150 public function getGDriveConnectionStatus()
151 {
152 require_once BMI_INCLUDES . '/external/google-drive.php';
153
154 $gdrive = new GDrive();
155 $status = $gdrive->verifyConnection();
156 if (isset($status['result']) && $status['result'] == 'connected') {
157 $this->gdriveStatus = true;
158 return true;
159 } else {
160 return false;
161 }
162 }
163
164 public function getAWSConnectionStatus() {
165 require_once BMI_INCLUDES . '/external/s3.php';
166
167 $s3 = new S3('aws');
168 $status = $s3->verifyConnection();
169 if (isset($status['result']) && $status['result'] == 'connected') {
170 $this->awsStatus = true;
171 return true;
172 } else {
173 return false;
174 }
175 }
176
177 public function getFtpConnectionStatus()
178 {
179 require_once BMI_INCLUDES . '/external/ftp.php';
180
181
182 $ftp = new FTP();
183 $status = $ftp->verifyConnection();
184 if (isset($status['result']) && $status['result'] == 'connected') {
185 $this->ftpStatus = true;
186 return true;
187 } else {
188 return false;
189 }
190 }
191
192
193 public function getBackupBlissConnectionStatus()
194 {
195 $status = $this->backupbliss->verifyConnection();
196 return isset($status['result']) && $status['result'] == 'connected';
197 }
198 public function checkForBackupsToUpload() {
199 $toBeUploaded = $this->fetchToBeUploaded();
200
201 $task = $toBeUploaded['current_upload'];
202 $queue = $toBeUploaded['queue'];
203
204 //If there's no task or queue present, then check for backups to upload
205 if (sizeof($task) == 0 && sizeof($queue) == 0) {
206 $this->backupbliss->checkForBackupsToUpload();
207 if ($this->dropbox && $this->dropboxStatus) $this->dropbox->checkForBackupsToUploadToDropbox();
208 if ($this->gdrive && $this->gdriveStatus) $this->gdrive->checkForBackupsToUpload();
209 if ($this->ftp && $this->ftpStatus) $this->ftp->checkForBackupsToUpload();
210 if ($this->aws && $this->awsStatus) $this->aws->checkForBackupsToUpload();
211 if ($this->wasabi && $this->wasabiStatus) $this->wasabi->checkForBackupsToUpload();
212
213 //Check for backups premium
214 if ($this->proajax)
215 $this->proajax->checkForBackupsToUpload();
216 }
217
218 //Remove failed tasks if the local backup is deleted
219 if (isset($toBeUploaded['failed'])) {
220 // Local Backups
221 require_once BMI_INCLUDES . DIRECTORY_SEPARATOR . 'scanner' . DIRECTORY_SEPARATOR . 'backups.php';
222 $backups = Backups::getInstance();
223 $backupsAvailable = $backups->getAvailableBackups("local");
224 $localBackups = $backupsAvailable['local'];
225 $localBackups = array_reverse($localBackups);
226
227 $failed = $toBeUploaded['failed'];
228 foreach($failed as $failed_task => $failed_count) {
229 $data = explode("_", $failed_task);
230
231
232 if (count($data) == 2) {
233 $cloudtype = $data[0];
234 $md5 = $data[1];
235
236 $md5s = array_map(function($backup) { return $backup[7]; }, $localBackups);
237
238 if (!in_array($md5, $md5s)) {
239 unset($toBeUploaded["failed"][$failed_task]);
240 update_option('bmip_to_be_uploaded', $toBeUploaded);
241 }
242 }
243 }
244 }
245 }
246
247 /**
248 * keepAliveUnAuthorizedRefresh - Unauthorized Keep Alive Request
249 * DO NOT RESPONSE WITH ANY SENSITIVE DATA, ONLY SUCCESS OR FAIL
250 * THIS CAN BE ACCESSED BY ANYONE WITHOUT ANY AUTH
251 *
252 * @return string[] success/fail
253 */
254 public function keepAliveUnAuthorizedRefresh()
255 {
256 //Atomic locking to prevent race conditions
257 $lock_file = BMI_CONFIG_DIR . DIRECTORY_SEPARATOR . '.keep_alive.lock';
258
259 // Open the lock file
260 $fp = fopen($lock_file, 'c');
261
262 // Try to acquire an exclusive lock
263 if (flock($fp, LOCK_EX | LOCK_NB)) {
264 if (BMI_DEBUG)
265 Logger::error("Lock acquired.");
266
267 if (isset($this->proajax)) {
268 $ret = $this->proajax->keepAliveDueToBackup();
269 if ($ret === true) {
270 $this->proajax->executeKeepAliveBatch();
271 flock($fp, LOCK_UN);
272 fclose($fp);
273 return ['status' => 'success'];
274 }
275 }
276 $ret = $this->keepAliveUnAuthorizedRefreshExec();
277
278 // Release the lock
279 if (BMI_DEBUG)
280 Logger::error("Lock released.");
281 $this->maybeScheduleKeepAliveCron($ret);
282 flock($fp, LOCK_UN);
283 fclose($fp);
284
285 return $ret;
286 } else {
287 $ret = ['status' => 'success']; // Lock is already held
288 $this->maybeScheduleKeepAliveCron($ret);
289 fclose($fp);
290 return $ret;
291 }
292 }
293
294 private function maybeScheduleKeepAliveCron($res)
295 {
296 if (is_array($res) && isset($res['status']) && $res['status'] === 'success') {
297 $delay = 15;
298
299 if (!wp_next_scheduled('bmip_keepalive_cron')) {
300 wp_schedule_single_event(time() + $delay, 'bmip_keepalive_cron');
301 }
302 } elseif (is_array($res) && isset($res['status']) && $res['status'] === 'no_tasks') {
303 wp_clear_scheduled_hook('bmip_keepalive_cron');
304 }
305 }
306
307 private function removeCurrentTask($toBeUploaded) {
308 $toBeUploaded["current_upload"] = []; //Removes the current ttask
309 update_option("bmip_to_be_uploaded", $toBeUploaded);
310
311 return ['status' => 'no_tasks'];
312 }
313
314 private function fetchToBeUploaded() {
315 //Get the option without any caching when used with get_option which prevvents stale data from being retreived.
316 //This is implemented after observing and debugging the issue that sometimes the same batch is uploaded again causing issues.
317 global $wpdb;
318 $bmip_to_be_uploaded = $wpdb->get_var( $wpdb->prepare( "SELECT option_value FROM $wpdb->options WHERE option_name = %s", 'bmip_to_be_uploaded' ) );
319 if ($bmip_to_be_uploaded !== null) {
320 $toBeUploaded = maybe_unserialize($bmip_to_be_uploaded);
321 if (!isset($toBeUploaded['current_upload']))
322 $toBeUploaded['current_upload'] = [];
323 } else {
324 $toBeUploaded = [
325 'current_upload' => [],
326 'queue' => [],
327 'failed' => []
328 ];
329 }
330
331 return $toBeUploaded;
332 }
333
334 private function checkIfBackupCanBeUploaded($type, $taskname) {
335
336 $backupPath = BMI_BACKUPS . DIRECTORY_SEPARATOR . $taskname;
337 $backupSize = file_exists($backupPath) ? filesize($backupPath) : -1;
338
339 switch($type) {
340
341 case "backupbliss": {
342 $storageInfo = $this->backupbliss->getStorageInfo();
343
344 if ($storageInfo === false) {
345 Logger::error("[BMI] Couldn't fetch storage info from BackupBliss!");
346 return false;
347 }
348
349 if ($storageInfo["used_space_percent"] > 80 && $storageInfo["used_space_percent"] <= 100) {
350 $error_message_notice = 'It seems you already used more than 80% of your space. <a href="'.BMI_AUTHOR_URI . 'pricing'.'">Get more storage now.</a>';
351
352 $this->backupbliss->showNotice("storage_warn", $error_message_notice, 60 * 60);
353 } elseif($storageInfo["used_space_percent"] > 100) {
354 $error_message_notice = 'You’re using more space than allowed. No new backups will be moved to your storage and some of the <b>existing backups will be deleted very soon</b>. ';
355
356 $this->backupbliss->showNotice("upload_issue_space", $error_message_notice, 60 * 60);
357 } else {
358 $this->backupbliss->removeNotice("storage_warn");
359 $this->backupbliss->removeNotice("upload_issue_space");
360 }
361
362 if (!$this->getBackupBlissConnectionStatus()) {
363 return false;
364 }
365
366
367
368 if (!$this->backupbliss->getNotice("upload_issue_space")) {
369
370 if (isset($storageInfo["remaining_space"]))
371 {
372 $remaining = $storageInfo["remaining_space"];
373
374
375 if ($backupSize != -1)
376 {
377 if ($remaining < $backupSize)
378 {
379 $error_message_notice = 'Moving backups to your storage is failing or will fail because you don’t have enough space.';
380
381 add_option("bmip_backupbliss_required_space", $backupPath);
382 $this->backupbliss->showNotice("upload_issue_space", $error_message_notice, 60 * 60);
383 //Triggering the server, so that an alert also get sent
384 $this->backupbliss->initiateUploadSession($backupPath);
385 return false;
386 }
387 }
388
389 }
390 else {
391 Logger::error("[BMI] Couldn't fetch quota from BackupBliss!");
392 }
393 }
394
395 if ($this->backupbliss->getNotice("upload_issue_space")) {
396 return false;
397 }
398
399 break;
400 }
401
402 case "dropbox": {
403 if (!$this->dropbox || !$this->dropboxStatus) return false;
404 if (in_array(get_transient('bmip_dropbox_issue'), ['rate_limit', 'not_enough_memory', 'insufficient_space', 'auth_error_disconnected'])) {
405 $issue = get_transient('bmip_dropbox_issue');
406 switch($issue){
407 case 'auth_error_disconnected':
408 delete_option($this->dropbox->dropboxAuthCodeOption);
409 delete_option($this->dropbox->dropboxId);
410 delete_transient($this->dropbox->dropboxAccessToken);
411 return false;
412 case 'not_enough_memory':
413 if (BMP::getAvailableMemoryInBytes() >= 16 * 1024 * 1024) {
414 delete_transient('bmip_dropbox_issue');
415 return true;
416 }
417 break;
418 case 'insufficient_space':
419 $spaceUsage = $this->dropbox->getSpaceUsage();
420 if ($spaceUsage === false) {
421 return false;
422 }
423
424 $requiredSpace = get_option('bmip_dropbox_required_space', 0);
425 $requiredSpace = intval($requiredSpace);
426 $availableSpace = $spaceUsage['allocation']['allocated'] - $spaceUsage['used'];
427
428 if ($backupSize != -1 && $availableSpace >= $backupSize)
429 return true; //Allow backup to be uploaded if the backup size is within the storage limit
430
431
432 if ($availableSpace >= $requiredSpace) {
433 delete_transient('bmip_dropbox_issue');
434 return true;
435 }
436 break;
437 }
438
439 return false;
440 }
441
442 break;
443 }
444
445 case "gdrive": {
446 if (get_transient('bmip_gd_issue') === 'auth_error_disconnected') {
447 delete_option('bmi_pro_gd_client_id');
448 delete_option('bmi_pro_gd_token');
449 delete_transient('bmi_pro_access_token');
450 return false;
451 }
452 if (!$this->gdrive || !$this->gdriveStatus) return false;
453 if (get_transient('bmip_display_quota_issues')) {
454 $requiredSpace = get_option('bmip_gd_required_space', 0);
455 $gdriveStorage = $this->gdrive->getGoogleDriveAvailableStorage();
456
457 if ($backupSize != -1 && $gdriveStorage >= $backupSize)
458 return true; //Allow backup to be uploaded if the backup size is within the storage limit
459
460 if ($requiredSpace < $gdriveStorage && $requiredSpace != 0) {
461 delete_transient('bmip_display_quota_issues');
462 delete_option('bmip_gd_required_space');
463 delete_option('bmip_to_be_uploaded');
464 } else {
465 return false;
466 }
467 }
468
469 break;
470 }
471
472 case "ftp": {
473 if (!$this->ftp || !$this->ftpStatus) return false;
474
475 break;
476 }
477
478 case "aws": {
479 if (!$this->aws || !$this->awsStatus) return false;
480 $issue = $this->aws->getIssue()['issue'];
481 switch ($issue){
482 case 'rate_limit':
483 return false;
484 case 'disconnected':
485 case 'forbidden':
486 $this->aws->restartUploadProcess();
487 return false;
488 default:
489 return true;
490 }
491 }
492
493 case "wasabi": {
494 if (!$this->wasabi || !$this->wasabiStatus) return false;
495 $issue = $this->wasabi->getIssue()['issue'];
496 switch ($issue){
497 case 'rate_limit':
498 return false;
499 case 'disconnected':
500 case 'forbidden':
501 $this->wasabi->restartUploadProcess();
502 return false;
503 default:
504 return true;
505 }
506 }
507 }
508
509 if ($this->proajax)
510 return $this->proajax->checkIfBackupCanBeUploaded($type, $backupSize);
511
512 return true;
513 }
514
515 private function _removeTasksFromDeactivatedClouds($cltype, $toBeUploaded, $task, $queue, $failed) {
516 if (sizeof($task) > 0 && isset($task['task'])) {
517 $taskname = $task['task'];
518 $type = explode('_', $taskname)[0];
519 if ($type == $cltype)
520 $task = [];
521 }
522
523 if (sizeof($queue) > 0) {
524 $tasks = array_keys($queue);
525 foreach($tasks as $taskname) {
526 $type = explode('_', $taskname)[0];
527 if ($type == $cltype)
528 unset($queue[$taskname]);
529 }
530 }
531
532 if (sizeof($failed) > 0) {
533 $tasks = array_keys($failed);
534 foreach($tasks as $taskname) {
535 $type = explode('_', $taskname)[0];
536 if ($type == $cltype)
537 unset($failed[$taskname]);
538 }
539 }
540
541 $toBeUploaded['current_upload'] = $task;
542 $toBeUploaded['queue'] = $queue;
543 $toBeUploaded['failed'] = $failed;
544 update_option("bmip_to_be_uploaded", $toBeUploaded);
545 }
546
547 public function getDeactivatedClouds() {
548 $deactivatedClouds = [];
549 if (!$this->ftpStatus) $deactivatedClouds[] = "ftp";
550 if (!$this->getBackupBlissConnectionStatus()) $deactivatedClouds[] = "backupbliss";
551 if (!$this->dropboxStatus) $deactivatedClouds[] = "dropbox";
552 if (!$this->gdriveStatus) $deactivatedClouds[] = "gdrive";
553
554 if ($this->proajax)
555 $deactivatedClouds = array_merge($this->proajax->getDeactivatedClouds(), $deactivatedClouds);
556
557 return $deactivatedClouds;
558 }
559
560 public function keepAliveUnAuthorizedRefreshExec() {
561
562 $isOnGoing = get_transient('bmip_upload_ongoing');
563 if ($isOnGoing === '1') return ['status' => 'success']; //Returning success so that the auto pinger will keep on pinging
564
565
566 $toBeUploaded = $this->fetchToBeUploaded();
567
568
569
570 $task = $toBeUploaded['current_upload'];
571 $queue = $toBeUploaded['queue'];
572 $failed = isset($toBeUploaded['failed']) ? $toBeUploaded['failed'] : [];
573
574 foreach ($this->getDeactivatedClouds() as $cloudType)
575 $this->_removeTasksFromDeactivatedClouds($cloudType, $toBeUploaded, $task, $queue, $failed);
576
577
578 //Check for uploads
579 if (get_transient('bmip_check_for_backups_to_upload') !== "wait") {
580 set_transient("bmip_check_for_backups_to_upload", "wait", 10);
581 $this->checkForBackupsToUpload();
582 //Refresh variables after checking for backups to upload
583 $toBeUploaded = $this->fetchToBeUploaded();
584 $task = $toBeUploaded['current_upload'];
585 $queue = $toBeUploaded['queue'];
586 }
587
588 $shouldBeQueued = false;
589
590 if (sizeof($task) > 0 && isset($task['task'])) {
591 $taskname = $task['task'];
592 $type = explode('_', $taskname)[0];
593
594
595 if (!$this->checkIfBackupCanBeUploaded($type, $task['name'])) {
596 $this->removeCurrentTask($toBeUploaded);
597 $type = null; //Set type as null so that no actions will be taken
598 $shouldBeQueued = true; //Set it to queue the next task
599 }
600
601 // BackupBliss
602 if ($type == 'backupbliss') {
603
604 if (!isset($task['uploadSession'])) {
605
606 $backupPath = BMI_BACKUPS . DIRECTORY_SEPARATOR . $task['name'];
607 $manifestPath = BMI_BACKUPS . DIRECTORY_SEPARATOR . $task['json'];
608 $uploadSession = $this->backupbliss->initiateUploadSession($backupPath);
609 if (!$uploadSession)
610 {
611 $this->removeCurrentTask($toBeUploaded);
612 return ['status' => 'success'];
613 }
614
615 $availableMemory = BMP::getAvailableMemoryInBytes();
616 $bytesPerRequest = intval($availableMemory / 4);
617
618 $toBeUploaded['current_upload']['bytesPerRequest'] = $bytesPerRequest;
619 $toBeUploaded['current_upload']['uploadSession'] = $uploadSession;
620 $toBeUploaded['current_upload']['manifestPath'] = $manifestPath;
621 $toBeUploaded['current_upload']['backupPath'] = $backupPath;
622 $toBeUploaded['current_upload']['batch'] = 1;
623
624 update_option('bmip_to_be_uploaded', $toBeUploaded);
625
626 if (!file_exists($backupPath)) delete_option('bmip_to_be_uploaded');
627 return ['status' => 'success'];
628 } else {
629
630 if (!file_exists($task['backupPath'])) {
631 delete_option('bmip_to_be_uploaded');
632 return ['status' => 'success'];
633 }
634
635 $this->backupbliss->uploadFile($task['uploadSession'], $task['backupPath'], $task['manifestPath'], $task['md5'], $task['batch'], $task['bytesPerRequest']);
636 return ['status' => 'success'];
637 }
638 }
639 // Dropbox Process
640 elseif ($type == 'dropbox') {
641
642 $sessionId = isset($task['sessionId']) ? $task['sessionId'] : '';
643 $offset = isset($task['offset']) ? $task['offset'] : 0;
644 $backupName = isset($task['name']) ? $task['name'] : '';
645 $md5 = isset($task['md5']) ? $task['md5'] : '';
646
647 $dropbox = new Dropbox();
648 $result = $dropbox->uploadDropboxBackup($sessionId, $backupName, $offset, $md5);
649 switch ($result['status']) {
650 case 'success':
651 $uploadedBackupStatus = get_option('bmi_uploaded_backups_status', []);
652 if (!isset($uploadedBackupStatus[$md5])) {
653 $uploadedBackupStatus[$md5] = [];
654 }
655 $uploadedBackupStatus[$md5]['dropbox'] = true;
656 update_option('bmi_uploaded_backups_status', $uploadedBackupStatus);
657 $toBeUploaded['current_upload'] = [];
658 if (isset($toBeUploaded['failed']) && isset($toBeUploaded['failed'][$taskname])) unset($toBeUploaded['failed'][$taskname]);
659 do_action('bmi_backup_upload_completed', $md5);
660 break;
661 case 'error':
662 Logger::error('[BMI PRO] Could not upload ' . $backupName . ' to Dropbox as an error occurred: ' . $result['error']);
663
664 if ($result['error'] == 'internal_file_not_found') {
665 return $this->dropbox->restartUploadprocess();
666 }
667
668 if (!isset($toBeUploaded['failed'])) $toBeUploaded['failed'] = [];
669 if (isset($toBeUploaded['failed'][$taskname])) $toBeUploaded['failed'][$taskname]++;
670 else $toBeUploaded['failed'][$taskname] = 1;
671 break;
672 case 'continue':
673 $offset = isset($result['offset']) ? $result['offset'] : 0;
674 $sessionId = isset($result['sessionId']) ? $result['sessionId'] : '';
675 if ($offset != 0 ) $toBeUploaded['current_upload']['offset'] = $offset;
676 if ($sessionId != '') $toBeUploaded['current_upload']['sessionId'] = $sessionId;
677 $fileSize = filesize(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupName);
678 $toBeUploaded['current_upload']['progress'] = round(($offset / $fileSize) * 100) . '%';
679
680 // remove from failed
681 if (isset($toBeUploaded['failed']) && isset($toBeUploaded['failed'][$taskname])) unset($toBeUploaded['failed'][$taskname]);
682 break;
683 }
684
685 delete_transient("bmip_upload_ongoing");
686 update_option('bmip_to_be_uploaded', $toBeUploaded);
687 return ['status' => 'success'];
688 }
689 // Google Drive Process
690 elseif ($type == 'gdrive') {
691
692 if (!isset($task['uploadURL'])) {
693
694 $backupPath = BMI_BACKUPS . DIRECTORY_SEPARATOR . $task['name'];
695 $manifestPath = BMI_BACKUPS . DIRECTORY_SEPARATOR . $task['json'];
696 $uploadURL = $this->gdrive->createUploadGoogleDriveURL($backupPath, $manifestPath);
697
698 $availableMemory = BMP::getAvailableMemoryInBytes();
699 $bytesPerRequest = intval($availableMemory / 4);
700
701 $toBeUploaded['current_upload']['bytesPerRequest'] = $bytesPerRequest;
702 $toBeUploaded['current_upload']['uploadURL'] = $uploadURL['uploadURL'];
703 $toBeUploaded['current_upload']['manifestPath'] = $manifestPath;
704 $toBeUploaded['current_upload']['backupPath'] = $backupPath;
705 $toBeUploaded['current_upload']['batch'] = 1;
706
707 update_option('bmip_to_be_uploaded', $toBeUploaded);
708
709 if (!file_exists($backupPath)) delete_option('bmip_to_be_uploaded');
710 return ['status' => 'success'];
711 } else {
712
713 if (!file_exists($task['backupPath'])) {
714 delete_option('bmip_to_be_uploaded');
715 return ['status' => 'success'];
716 }
717
718 $this->gdrive->uploadGoogleDriveFile($task['uploadURL'], $task['backupPath'], $task['manifestPath'], $task['md5'], $task['batch'], $task['bytesPerRequest']);
719 return ['status' => 'success'];
720 }
721 }
722 // FTP Process
723 elseif ($type == 'ftp') {
724
725 if (!isset($task['uploadURL'])) {
726 $backupPath = BMI_BACKUPS . DIRECTORY_SEPARATOR . $task['name'];
727 $manifestPath = BMI_BACKUPS . DIRECTORY_SEPARATOR . $task['json'];
728 $availableMemory = BMP::getAvailableMemoryInBytes();
729
730 $bytesPerRequest = intval($availableMemory / 4);
731 $toBeUploaded['current_upload']['bytesPerRequest'] = $bytesPerRequest;
732 $toBeUploaded['current_upload']['uploadURL'] = get_option('bmi_pro_ftp_host');
733 $toBeUploaded['current_upload']['manifestPath'] = $manifestPath;
734 $toBeUploaded['current_upload']['backupPath'] = $backupPath;
735 $toBeUploaded['current_upload']['batch'] = 1;
736
737 update_option('bmip_to_be_uploaded', $toBeUploaded);
738
739 if (!file_exists($backupPath)) delete_option('bmip_to_be_uploaded');
740 return ['status' => 'success'];
741 } else {
742
743 if (!file_exists($task['backupPath'])) {
744 delete_option('bmip_to_be_uploaded');
745 return ['status' => 'success'];
746 }
747 $this->ftp->uploadFtpDriveFiles($task['uploadURL'], $task['backupPath'], $task['manifestPath'], $task['md5'], $task['batch'], $task['bytesPerRequest']);
748 return ['status' => 'success'];
749 }
750
751 }
752 // AWS
753 elseif ($type == 'aws') {
754
755 $uploadId = isset($task['uploadId']) ? $task['uploadId'] : '';
756 $offset = isset($task['offset']) ? $task['offset'] : 0;
757 $backupName = isset($task['name']) ? $task['name'] : '';
758 $md5 = isset($task['md5']) ? $task['md5'] : '';
759
760 $s3 = new S3('aws');
761
762 $result = $s3->uploadBackup($uploadId, $backupName, $offset, $md5);
763 switch ($result['status']) {
764 case 'success':
765 $uploadedBackupStatus = get_option('bmi_uploaded_backups_status', []);
766 if (!isset($uploadedBackupStatus[$md5])) {
767 $uploadedBackupStatus[$md5] = [];
768 }
769 $uploadedBackupStatus[$md5]['aws'] = true;
770 update_option('bmi_uploaded_backups_status', $uploadedBackupStatus);
771 $toBeUploaded['current_upload'] = [];
772 if (isset($toBeUploaded['failed']) && isset($toBeUploaded['failed'][$taskname])) unset($toBeUploaded['failed'][$taskname]);
773 do_action('bmi_backup_upload_completed', $md5);
774 break;
775 case 'error':
776 Logger::error('[BMI PRO] Could not upload ' . $backupName . ' to AWS S3 as an error occurred: ' . $result['error']);
777
778 $toBeUploaded['current_upload'] = [];
779 if (!isset($toBeUploaded['failed'])) $toBeUploaded['failed'] = [];
780 if (isset($toBeUploaded['failed'][$taskname])) $toBeUploaded['failed'][$taskname]++;
781 else $toBeUploaded['failed'][$taskname] = 1;
782 break;
783 case 'continue':
784 $offset = isset($result['offset']) ? $result['offset'] : 0;
785 $uploadId = isset($result['uploadId']) ? $result['uploadId'] : '';
786 if ($offset != 0 ) $toBeUploaded['current_upload']['offset'] = $offset;
787 if ($uploadId != '') $toBeUploaded['current_upload']['uploadId'] = $uploadId;
788 $fileSize = filesize(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupName);
789 $toBeUploaded['current_upload']['progress'] = round(($offset / $fileSize) * 100) . '%';
790
791 // remove from failed
792 if (isset($toBeUploaded['failed']) && isset($toBeUploaded['failed'][$taskname])) unset($toBeUploaded['failed'][$taskname]);
793 break;
794 }
795
796 delete_transient("bmip_upload_ongoing");
797 update_option('bmip_to_be_uploaded', $toBeUploaded);
798 return ['status' => 'success'];
799 }
800 //Wasabi
801 elseif ($type == 'wasabi') {
802
803 $uploadId = isset($task['uploadId']) ? $task['uploadId'] : '';
804 $offset = isset($task['offset']) ? $task['offset'] : 0;
805 $backupName = isset($task['name']) ? $task['name'] : '';
806 $md5 = isset($task['md5']) ? $task['md5'] : '';
807
808 $s3 = new S3('wasabi');
809
810 $result = $s3->uploadBackup($uploadId, $backupName, $offset, $md5);
811 switch ($result['status']) {
812 case 'success':
813 $uploadedBackupStatus = get_option('bmi_uploaded_backups_status', []);
814 if (!isset($uploadedBackupStatus[$md5])) {
815 $uploadedBackupStatus[$md5] = [];
816 }
817 $uploadedBackupStatus[$md5]['wasabi'] = true;
818 update_option('bmi_uploaded_backups_status', $uploadedBackupStatus);
819 $toBeUploaded['current_upload'] = [];
820 if (isset($toBeUploaded['failed']) && isset($toBeUploaded['failed'][$taskname])) unset($toBeUploaded['failed'][$taskname]);
821 do_action('bmi_backup_upload_completed', $md5);
822 break;
823 case 'error':
824 Logger::error('[BMI PRO] Could not upload ' . $backupName . ' to Wasabi as an error occurred: ' . $result['error']);
825
826 $toBeUploaded['current_upload'] = [];
827 if (!isset($toBeUploaded['failed'])) $toBeUploaded['failed'] = [];
828 if (isset($toBeUploaded['failed'][$taskname])) $toBeUploaded['failed'][$taskname]++;
829 else $toBeUploaded['failed'][$taskname] = 1;
830 break;
831 case 'continue':
832 $offset = isset($result['offset']) ? $result['offset'] : 0;
833 $uploadId = isset($result['uploadId']) ? $result['uploadId'] : '';
834 if ($offset != 0 ) $toBeUploaded['current_upload']['offset'] = $offset;
835 if ($uploadId != '') $toBeUploaded['current_upload']['uploadId'] = $uploadId;
836 $fileSize = filesize(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupName);
837 $toBeUploaded['current_upload']['progress'] = round(($offset / $fileSize) * 100) . '%';
838
839 // remove from failed
840 if (isset($toBeUploaded['failed']) && isset($toBeUploaded['failed'][$taskname])) unset($toBeUploaded['failed'][$taskname]);
841 break;
842 }
843
844 delete_transient("bmip_upload_ongoing");
845 update_option('bmip_to_be_uploaded', $toBeUploaded);
846 return ['status' => 'success'];
847 }
848 elseif ($this->proajax) {
849 $ret = $this->proajax->processClouds($type, $task, $toBeUploaded, $taskname);
850 if ($ret["status"] !== "no_tasks")
851 return $ret;
852 }
853
854 } else {
855 $shouldBeQueued = true;
856 }
857
858 if ($shouldBeQueued && sizeof($queue) > 0) {
859
860 $tasks = array_keys($queue);
861 if (sizeof($tasks) > 0) {
862
863 $selectedTask = $tasks[0];
864 $cloudType = explode("_", $selectedTask)[0];
865 $toBeProcessed = $queue[$selectedTask];
866
867 if ($this->checkIfBackupCanBeUploaded($cloudType, $toBeProcessed['name'])) {
868 $toBeUploaded['current_upload'] = [
869 'task' => $selectedTask,
870 'name' => $toBeProcessed['name'],
871 'md5' => $toBeProcessed['md5'],
872 'json' => $toBeProcessed['json'],
873 'progress' => '0%'
874 ];
875 } else {
876 if (isset($toBeUploaded['failed']))
877 $toBeUploaded['failed'][$selectedTask] = 1; //Mark the task as failed
878 }
879
880 unset($toBeUploaded['queue'][$selectedTask]);
881 update_option('bmip_to_be_uploaded', $toBeUploaded);
882
883 //Return success if there are more tasks in the queue, so auto pinger can ping rapidly
884 return ['status' => sizeof($queue) > 0 ? 'success' : 'no_tasks'];
885 } else return ['status' => 'no_tasks'];
886 } else return ['status' => 'no_tasks'];
887
888 return ['status' => 'no_tasks'];
889 }
890 }
891