Plugin Directory

source: backuply/trunk/functions.php

Last change on this file was 3267947, checked in by softaculous, 13 days ago

New version 1.4.4

File size: 47.6 KB
Line 
1<?php
2
3/*
4* BACKUPLY
5* https://backuply.com
6* (c) Backuply Team
7*/
8
9if(!defined('ABSPATH')) {
10        die('HACKING ATTEMPT!');
11}
12
13function backuply_get_protocols(){
14       
15        $protocols['ftp'] = 'FTP';
16        $protocols['gdrive'] = 'Google Drive';
17        $protocols['bcloud'] = 'Backuply Cloud';
18       
19        if(defined('BACKUPLY_PRO')) {
20               
21                if(!function_exists('backuply_get_pro_backups') && defined('BACKUPLY_PRO_DIR')) {
22                        include_once(BACKUPLY_PRO_DIR . '/functions.php');
23                }
24               
25                $protocols += backuply_get_pro_backups();
26        }
27       
28        return $protocols;
29       
30}
31
32function backuply_create_backup_folders(){
33       
34        // Creating Backuply Folder
35        if(!file_exists(BACKUPLY_BACKUP_DIR)) {
36                @mkdir(BACKUPLY_BACKUP_DIR, 0755, true);
37        }
38       
39        $random_string = wp_generate_password(6, false);
40       
41        // Creating backups_info folder
42        if(file_exists(BACKUPLY_BACKUP_DIR . 'backups_info')){
43                @rename(BACKUPLY_BACKUP_DIR . 'backups_info', BACKUPLY_BACKUP_DIR . 'backups_info-'. $random_string);
44        }
45       
46        // Creating backups folder
47        if(file_exists(BACKUPLY_BACKUP_DIR . 'backups')){
48                @rename(BACKUPLY_BACKUP_DIR . 'backups', BACKUPLY_BACKUP_DIR . 'backups-'. $random_string);
49        }
50
51        $backup_info = backuply_glob('backups_info');
52        $backups = backuply_glob('backups');
53       
54        if(empty($backup_info)){
55                @mkdir(BACKUPLY_BACKUP_DIR . 'backups_info-' . $random_string, 0755, true);
56        }
57       
58        if(empty($backups)){
59                @mkdir(BACKUPLY_BACKUP_DIR . 'backups-' . $random_string, 0755, true);
60        }
61}
62
63
64// Add the htaccess file to protect us !
65function backuply_add_htaccess(){
66       
67        if(!file_exists(BACKUPLY_BACKUP_DIR)) {
68                @mkdir(BACKUPLY_BACKUP_DIR, 0755, true);
69        }
70       
71        $htaccess = @fopen(BACKUPLY_BACKUP_DIR . '.htaccess', 'w');
72        if(!$htaccess) {
73                return false;
74        }
75       
76        @fwrite($htaccess, 'deny from all');
77        @fclose($htaccess);
78       
79        return true;
80}
81
82// Add the webconfig file to protect us !
83function backuply_add_web_config(){
84       
85        if(file_exists(BACKUPLY_BACKUP_DIR . 'web.config')){
86                return true;
87        }
88       
89        $web_config = @fopen(BACKUPLY_BACKUP_DIR . 'web.config', 'w');
90        if(!$web_config) {
91                return false;
92        }
93       
94        $web_conf = '<configuration>
95<system.webServer>
96<authorization>
97<deny users="*" />
98</authorization>
99</system.webServer>
100</configuration>';
101       
102        @fwrite($web_config, $web_conf);
103        @fclose($web_config);
104       
105        return true;
106}
107
108// Add the htaccess folder to protect us !
109function backuply_add_index_files(){
110       
111        if(!file_exists(BACKUPLY_BACKUP_DIR)) {
112                @mkdir(BACKUPLY_BACKUP_DIR, 0755, true);
113        }
114       
115        $php_protection = '<?php //Backuply';
116        $html_protection = '<html><body><a href="https://backuply.com" target="_blank">WordPress backups by Backuply</a></body></html>';
117
118        @file_put_contents(BACKUPLY_BACKUP_DIR . 'index.html', $html_protection);
119        @file_put_contents(BACKUPLY_BACKUP_DIR . 'index.php', $php_protection);
120       
121        $backups = backuply_glob('backups');
122       
123        if(!empty($backups)){
124                if(!file_exists($backups . '/index.html')){
125                        @file_put_contents($backups . '/index.html', $html_protection);
126                }
127               
128                if(!file_exists($backups . '/index.php')){
129                        @file_put_contents($backups . '/index.php', $php_protection);
130                }
131               
132                // Protecting backups-*/tmp folder
133                if(!file_exists($backups . '/tmp/index.html')){
134                        @mkdir($backups . '/tmp');
135                        @file_put_contents($backups . '/tmp/index.html', $html_protection);
136                }
137               
138                if(!file_exists($backups . '/tmp/index.php')){
139                        @file_put_contents($backups . '/tmp/index.php', $php_protection);
140                }
141        }
142
143        // Protecting backups_info folder
144        $backups_info = backuply_glob('backups_info');
145       
146        if(!empty($backups_info)){
147                if(!file_exists($backups_info . '/index.html')){
148                        @file_put_contents($backups_info . '/index.html', $html_protection);
149                }
150
151                if(!file_exists($backups_info . '/index.php')){
152                        @file_put_contents($backups_info . '/index.php', $php_protection);
153                }
154        }
155}
156
157function backuply_glob($relative_path){
158        $glob = glob(BACKUPLY_BACKUP_DIR . $relative_path . '-*', GLOB_ONLYDIR);
159       
160        if(!empty($glob[0])){
161                return $glob[0];
162        }
163
164        return false;
165}
166
167
168function backuply_kill_process($is_restore = false) {
169        delete_option('backuply_status');
170        update_option('backuply_backup_stopped', true);
171       
172        if(!empty($is_restore)){
173                backuply_clean_restoration_file();
174        }
175
176        die();
177}
178
179function backuply_clean_restoration_file(){
180
181        // Restore is complete now we dont need this
182        if(file_exists(BACKUPLY_BACKUP_DIR.'/restoration/restoration.php')) {
183                @unlink(BACKUPLY_BACKUP_DIR.'/restoration/restoration.php');
184        }
185       
186        if(is_dir(BACKUPLY_BACKUP_DIR.'/restoration')) {
187                @rmdir(BACKUPLY_BACKUP_DIR.'/restoration');
188        }
189       
190        // Deleting restore index file
191        if(file_exists(ABSPATH . '/backuply-restore.php')){
192                unlink(ABSPATH . '/backuply-restore.php');
193        }
194}
195
196// If there is a restore or backup task running
197function backuply_active(){
198        global $backuply;
199       
200        $backuply['status'] = get_option('backuply_status');
201       
202        // Nothing there
203        if(empty($backuply['status']['last_time'])){
204                return false;
205        }
206       
207        // No updates since 5 min
208        if((time() - BACKUPLY_TIMEOUT_TIME) > $backuply['status']['last_time']){
209                return false;
210        }
211       
212        return true;
213       
214}
215
216// Verifies the backuply key
217function backuply_verify_self($key, $restore_key = false) {
218       
219        if(empty($key)) {
220                return false;
221        }
222       
223        $config = backuply_get_config();
224       
225        if(!empty($restore_key)){
226                if(!empty($config['RESTORE_KEY']) && urldecode($key) == $config['RESTORE_KEY']) {
227                        return true;
228                }
229               
230                return false;
231        }
232
233        if(urldecode($key) == $config['BACKUPLY_KEY']) {
234                return true;
235        }
236
237        return false;
238}
239
240// Wp-Cron handle for timeout check i.e. clean dead processes
241// Terminates process if no update for 30 min
242function backuply_timeout_check($is_restore) { 
243       
244        global $backuply;
245       
246        // Is it a restore check ?
247        if(!empty($is_restore)) {
248               
249                $file = BACKUPLY_BACKUP_DIR . '/restoration/restoration.php';
250               
251                if(!file_exists($file)) {
252                        die();
253                }
254               
255                $fm_time = filemtime($file);
256               
257                if((time() - $fm_time) >= BACKUPLY_TIMEOUT_TIME) {
258                        backuply_kill_process(true);
259                }
260       
261        // Its a backup process
262        } else {
263               
264                if(empty($backuply['status']['last_update'])){
265                        backuply_kill_process();
266                }
267               
268                if((time() - $backuply['status']['last_update']) >= BACKUPLY_TIMEOUT_TIME) {
269                        backuply_kill_process();
270                }
271               
272        }
273       
274        // To check after 5 minutes again
275        wp_schedule_single_event(time() + BACKUPLY_TIMEOUT_TIME, 'backuply_timeout_check', array('is_restore' => $is_restore));
276       
277}
278
279// Create a config file and set it with a key
280function backuply_set_config() {
281       
282        $write['BACKUPLY_KEY'] = backuply_csrf_get_token();
283        // $write['RESTORE_KEY'] = backuply_csrf_get_token();
284       
285        update_option('backuply_config_keys', $write);
286}
287
288function backuply_set_config_file(){
289
290        $write = get_option('backuply_config_keys', []);
291
292        if(empty($write)){
293                return false;
294        }
295
296        $config_file = BACKUPLY_BACKUP_DIR . 'backuply_config.php';
297       
298        $fp = @fopen($config_file, 'w');
299       
300        if(!is_resource($fp)){
301                return;
302        }
303
304        @fwrite($fp, "<?php exit();?>\n" . json_encode($write, JSON_PRETTY_PRINT));
305        @fclose($fp);
306       
307        @chmod($config_file, 0600);
308
309        return true;
310}
311
312function backuply_update_restore_key(){
313       
314        $config = get_option('backuply_config_keys');
315
316        if(empty($config)) {
317                backuply_set_config();
318                return;
319        }
320
321        $restore_key = backuply_csrf_get_token();
322        $config['RESTORE_KEY'] = $restore_key;
323       
324        update_option('backuply_config_keys', $config);
325}
326
327// Sets Backup Location details in Restoration File
328function backuply_set_restoration_file($loc) {
329        $write['protocol'] = $loc['protocol'];
330        $write['name'] = $loc['name'];
331       
332        $restoration_file = BACKUPLY_BACKUP_DIR . 'restoration/restoration.php';
333       
334        $fp = @fopen($restoration_file, 'w');
335       
336        if(!is_resource($fp)){
337                return;
338        }
339
340        if (0 == filesize($restoration_file)){
341                // file is empty
342                @fwrite($fp, "<?php exit();?>\n");
343        }
344       
345        @fwrite($fp, json_encode($write, JSON_PRETTY_PRINT));
346        @fclose($fp);
347       
348        @chmod($restoration_file, 0600);
349}
350
351// Sets Backup Location details in Restoration File
352function backuply_get_restoration_data() {
353        $restoration_file = BACKUPLY_BACKUP_DIR . 'restoration/restoration.php';
354       
355        $fp = @fopen($restoration_file, 'r');
356        @fseek($fp, 16);
357       
358        if(filesize($restoration_file) == 0){
359                return;
360        }
361       
362        $content = @fread($fp, filesize($restoration_file));
363        @fclose($fp);
364       
365        if(empty($content)) {
366                return [];
367        }
368       
369        $restro = json_decode($content, true);
370
371        return $restro;
372}
373
374// Get Config Array
375function backuply_get_config() {
376       
377        $config_file = BACKUPLY_BACKUP_DIR . 'backuply_config.php';
378       
379        // Fetch keys saved in DB
380        if(!file_exists($config_file)){
381                $db_keys = get_option('backuply_config_keys', []);
382
383                if(empty($db_keys)){
384                        return [];
385                }
386
387                return $db_keys;
388        }
389       
390        if(empty(filesize($config_file))) {
391                return [];
392                //backuply_get_config();
393        }
394
395        $fp = @fopen($config_file, 'r');
396       
397        if(!is_resource($fp)){
398                return [];
399        }
400       
401        @fseek($fp, 16);
402       
403        $file_size = filesize($config_file);
404        if(empty($file_size)){
405                return [];
406        }
407       
408        $content = @fread($fp, $file_size);
409        @fclose($fp);
410       
411        if(empty($content)) {
412                return [];
413        }
414       
415        $config = json_decode($content, true);
416
417        return $config;
418}
419
420// Create or updates the log file
421function backuply_status_log($log, $status = 'working', $percentage = 0){
422        $log_file = BACKUPLY_BACKUP_DIR . 'backuply_log.php';
423       
424        if(!file_exists($log_file) || 0 == filesize($log_file)) {
425                $log = "<?php exit();?>\n" . $log; //Prepend php exit
426        }
427
428        $this_log = $log . '|' . $status . '|' . $percentage . "\n";
429       
430        file_put_contents($log_file, $this_log, FILE_APPEND);
431}
432
433// Returns array of logs
434function backuply_get_status($last_log = 0){
435        $log_file = BACKUPLY_BACKUP_DIR. 'backuply_log.php';
436        $logs = [];
437       
438        if(!file_exists($log_file)){
439                $logs[] = 'Something went wrong!|error';
440                delete_option('backuply_status');
441                update_option('backuply_backup_stopped', 1, false);
442                return $logs;
443        }
444       
445        $fh = fopen($log_file, 'r');
446       
447        $seek_to = $last_log;
448        @fseek($fh, $seek_to);
449       
450        $lines = fread($fh, fstat($fh)['size']);
451        fclose($fh);
452        $fh = null;
453        return $lines;
454}
455
456// A compulsory POST which issues a error if the POST[$name] is not there
457function backuply_POST($name, $e){
458
459        global $error;
460
461        //Check the POSTED NAME was posted
462        if(!isset($_POST[$name]) || strlen(trim($_POST[$name])) < 1){
463       
464                $error[] = $e;
465               
466        }else{
467                return backuply_inputsec(backuply_htmlizer(trim($_POST[$name])));
468        }
469}
470
471// Used for the checkboxes which have the same names (i.e. name=SOMENAME[])
472function backuply_POSTmulticheck($name, $value, $default = array()){
473       
474        if(isset($_POST[$name]) && is_array($_POST[$name])){
475                if(in_array($value, $_POST[$name])){
476                        return 'checked="checked"';
477                }
478        }else{
479                if(in_array($value, $default)){
480                        return 'checked="checked"';
481                }
482        }
483       
484        return true;
485}
486
487// A compulsory REQUEST which issues a error if the REQUEST[$name] is not there
488function backuply_REQUEST($name, $e){
489
490        global $error;
491
492        //Check the POSTED NAME was posted
493        if(!isset($_REQUEST[$name]) || strlen(trim($_REQUEST[$name])) < 1){
494       
495                $error[$name] = $e;
496               
497        }else{
498                return backuply_inputsec(backuply_htmlizer(trim($_REQUEST[$name])));
499        }
500}
501
502// Check if a field is posted via POST else return default value
503function backuply_optpost($name, $default = ''){
504       
505        if(!empty($_POST[$name])){
506                return backuply_inputsec(backuply_htmlizer(trim($_POST[$name])));
507        }
508       
509        return $default;       
510}
511
512// Check if a field is posted via GET else return default value
513function backuply_optget($name, $default = ''){
514       
515        if(!empty($_GET[$name])){
516                return backuply_inputsec(backuply_htmlizer(trim($_GET[$name])));
517        }
518       
519        return $default;       
520}
521
522// Check if a field is posted via GET or POST else return default value
523function backuply_optreq($name, $default = ''){
524       
525        if(!empty($_REQUEST[$name])){
526                return backuply_inputsec(backuply_htmlizer(trim($_REQUEST[$name])));
527        }
528       
529        return $default;       
530}
531
532function backuply_POSTchecked($name, $default = false, $submit_name = ''){
533       
534        if(!empty($submit_name)){
535                $post_to_check = isset($_POST[$submit_name]) ? backuply_optpost($submit_name) : '';
536        }else{
537                $post_to_check = $_POST;
538        }
539       
540        return (!empty($post_to_check) ? (isset($_POST[$name]) ? 'checked="checked"' : '') : (!empty($default) ? 'checked="checked"' : ''));
541
542}
543
544function backuply_POSTselect($name, $value, $default = false){
545       
546        if(empty($_POST)){
547                if(!empty($default)){
548                        return 'selected="selected"';
549                }
550        }else{
551                if(isset($_POST[$name])){
552                        if(trim($_POST[$name]) == $value){
553                                return 'selected="selected"';
554                        }
555                }
556        }
557}
558
559///TODO:: Not being used
560function backuply_POSTradio($name, $val, $default = null){
561       
562        return (!empty($_POST) ? (@$_POST[$name] == $val ? 'checked="checked"' : '') : (!is_null($default) && $default == $val ? 'checked="checked"' : ''));
563
564}
565
566function backuply_inputsec($string){
567
568        $string = addslashes($string);
569       
570        // This is to replace ` which can cause the command to be executed in exec()
571        $string = str_replace('`', '\`', $string);
572       
573        return $string;
574
575}
576
577function backuply_htmlizer($string){
578
579        $string = htmlentities($string, ENT_QUOTES, 'UTF-8');
580       
581        preg_match_all('/(&amp;#(\d{1,7}|x[0-9a-fA-F]{1,6});)/', $string, $matches);//backuply_print($matches);
582       
583        foreach($matches[1] as $mk => $mv){             
584                $tmp_m = backuply_entity_check($matches[2][$mk]);
585                $string = str_replace($matches[1][$mk], $tmp_m, $string);
586        }
587       
588        return $string;
589       
590}
591
592function backuply_entity_check($string){
593       
594        //Convert Hexadecimal to Decimal
595        $num = ((substr($string, 0, 1) === 'x') ? hexdec(substr($string, 1)) : (int) $string);
596       
597        //Squares and Spaces - return nothing
598        $string = (($num > 0x10FFFF || ($num >= 0xD800 && $num <= 0xDFFF) || $num < 0x20) ? '' : '&#'.$num.';');
599       
600        return $string;
601}
602
603// Check if a checkbox is selected
604function backuply_is_checked($post){
605
606        if(!empty($_POST[$post])){
607                return true;
608        }       
609        return false;
610}
611
612// A Function that lists files and folders in a folder.
613function backuply_sfilelist($startdir='./', $searchSubdirs=1, $directoriesonly=0, $maxlevel='all', $level=1){   
614        return backuply_filelist_fn($startdir, $searchSubdirs, $directoriesonly, $maxlevel, $level);
615}
616
617// The below function will list all folders and files within a directory. It is a recursive function that uses a global array.
618function backuply_filelist_fn($startdir='./', $searchSubdirs=1, $directoriesonly=0, $maxlevel='all', $level=1, $reset = 1){
619       
620   //list the directory/file names that you want to ignore
621   $ignoredDirectory = array();
622   $ignoredDirectory[] = '.';
623   $ignoredDirectory[] = '..';
624   $ignoredDirectory[] = '_vti_cnf';
625   global $directorylist;       //initialize global array
626   
627        if(substr($startdir, -1) != '/'){
628                $startdir = $startdir.'/';
629        }
630   
631        if (is_dir($startdir)) {
632                if ($dh = opendir($startdir)) {
633                        while (($file = readdir($dh)) !== false) {
634                                if (!(array_search($file,$ignoredDirectory) > -1)) {
635                                        if (@filetype($startdir . $file) == 'dir') {
636
637                                                //build your directory array however you choose;
638                                                //add other file details that you want.
639
640                                                $directorylist[$startdir . $file]['level'] = $level;
641                                                $directorylist[$startdir . $file]['dir'] = 1;
642                                                $directorylist[$startdir . $file]['name'] = $file;
643                                                $directorylist[$startdir . $file]['path'] = $startdir;
644                                                if ($searchSubdirs) {
645                                                        if ((($maxlevel) == 'all') or ($maxlevel > $level)) {
646                                                           backuply_filelist_fn($startdir . $file . "/", $searchSubdirs, $directoriesonly, $maxlevel, ($level + 1), 0);
647                                                        }
648                                                }
649                                        } else {
650                                                if (!$directoriesonly) {
651                                                        //if you want to include files; build your file array
652                                                        //however you choose; add other file details that you want.
653                                                        $directorylist[$startdir . $file]['level'] = $level;
654                                                        $directorylist[$startdir . $file]['dir'] = 0;
655                                                        $directorylist[$startdir . $file]['name'] = $file;
656                                                        $directorylist[$startdir . $file]['path'] = $startdir;
657                                                }
658                                        }
659                                }
660                        }
661                        closedir($dh);
662                }
663        }
664
665        if(!empty($reset)){
666                $r = $directorylist;
667                $directorylist = array();
668                return($r);
669        }
670}
671
672// Report an error
673function backuply_report_error($error = array()){
674
675        if(empty($error)){
676                return true;
677        }
678       
679        $error_string = '<b>Please fix the below error(s) :</b> <br />';
680
681        foreach($error as $ek => $ev){
682                $error_string .= '* '.$ev.'<br />';
683        }
684       
685        echo '<div id="message" class="error"><p>'. wp_kses_post($error_string). '</p></div><br>';
686       
687}
688
689// Report a success
690function backuply_report_success($msg){
691
692        if(empty($msg)){
693                return true;
694        }
695       
696        echo '<div id="message" class="notice updated is-dismissible"><p>'. wp_kses_post($msg) . '</p></div><br />';
697}
698
699// Generate a random string
700function backuply_random_string($length = 10){
701        $characters = '0123456789abcdefghijklmnopqrstuvwxyz';
702        $charactersLength = strlen($characters);
703        $randomString = '';
704        for($i = 0; $i < $length; $i++){
705                $randomString .= $characters[rand(0, $charactersLength - 1)];
706        }
707        return $randomString;
708}
709
710function backuply_print($array){
711
712        echo '<pre>';
713        print_r($array);
714        echo '</pre>';
715
716}
717
718function backuply_cleanpath($path){
719        $path = str_replace('\\\\', '/', $path);
720        $path = str_replace('\\', '/', $path);
721        $path = str_replace('//', '/', $path);
722        return rtrim($path, '/');
723}
724
725//TODO:: Not being used
726// Returns the Numeric Value of results Per Page
727function backuply_get_page($get = 'page', $resperpage = 50){
728
729        $resperpage = (!empty($_REQUEST['reslen']) && is_numeric($_REQUEST['reslen']) ? (int) backuply_optreq('reslen') : $resperpage);
730       
731        if(backuply_optget($get)){
732                $pg = (int) backuply_optget($get);
733                $pg = $pg - 1;         
734                $page = ($pg * $resperpage);
735                $page = ($page <= 0 ? 0 : $page);
736        }else{ 
737                $page = 0;             
738        }       
739        return $page;
740}
741
742// This function just redirects to the Location specified and dies
743function backuply_redirect($location, $header = true){
744        //$prefix = (empty($raw) ? $globals['index'] : '');
745       
746        if($header){
747       
748                //Redirect
749                header('Location: '.$location);
750               
751        }else{
752                echo '<meta http-equiv="Refresh" content="0;url='.esc_url($location).'">';
753        }
754}
755
756// Returns the CSRF Token, generates one if it does not exist
757function backuply_csrf_get_token(){
758        $csrf_token = bin2hex(openssl_random_pseudo_bytes(32));
759        return $csrf_token;
760}
761
762// Update Backuply logs as per action
763function backuply_log($data){
764        global $backuply;
765       
766        if(empty($backuply['debug_mode'])){
767                return;
768        }
769
770        $write = '';
771        $write .= '['.date('Y-m-d H:i:s', time()).'] ';
772
773        $write .= $data."\n\n";
774       
775        $backups_info = backuply_glob('backups_info');
776       
777        $log_file = $backups_info .'/debug.php';
778       
779        $fp = @fopen($log_file, 'ab');
780       
781        if (0 == @filesize($log_file)){
782                // file is empty
783                @fwrite($fp, "<?php exit();?>\n");
784        }
785       
786        @fwrite($fp, $write);
787        @fclose($fp);
788       
789        @chmod($log_file, 0600);
790}
791
792/**
793 * This function will preg_match the pattern and return the respective values in $var
794 * @package       Backuply
795 * @param                $pattern This should be the pattern to be matched
796 * @param                $file This should have the data to search from
797 * @param                $var This will be the variable which will have the preg matched data
798 * @param                $valuenum This should be the no of regular expression to be returned in $var
799 * @param                $stripslashes 0 or 1 depending upon whether the stripslashes function is to be applied (1) or not (0)
800 * @return         string Will pass value by reference in $var
801 * @since                4.5.4
802 */
803function backuply_preg_replace($pattern, $file, &$var, $valuenum, $stripslashes = ''){ 
804        preg_match($pattern, $file, $matches);
805
806        if(!empty($matches) && !empty($matches[$valuenum])){
807                if(empty($stripslashes)){
808                        $var = trim($matches[$valuenum]);
809                }else{
810                        $var = stripslashes(trim($matches[$valuenum]));
811                }
812        }
813}
814
815//Function to return a file's size with their appropriate formats.
816function backuply_format_size($size){
817        $sizes = array(' Bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB');
818        if ($size == 0) { return('n/a'); } else {
819        return (round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . $sizes[$i]); }
820}
821
822// Prevent pro activate text for installer
823function backuply_install_plugin_complete_actions($install_actions, $api, $plugin_file){
824       
825        if($plugin_file == BACKUPLY_PRO_BASE){
826                return array();
827        }
828       
829        return $install_actions;
830}
831
832function backuply_get_backups_info(){
833       
834        // Get all Backups Information from the "backups_info" folder.
835        $all_backup_info_files = backuply_glob('backups_info');
836        $backup_files_location = backuply_glob('backups');
837       
838        $backup_infos = array();
839
840        if(empty($all_backup_info_files)){
841                return [];
842        }
843
844        $info_files = @scandir($all_backup_info_files);
845       
846        if(empty($info_files)){
847                return $backup_infos;
848        }
849       
850        foreach($info_files as $files){
851
852                if($files != '.' && $files != '..'){
853                       
854                        $i = 0;
855                        $check_for_file = basename($files, '.php');
856
857                        $file = file($all_backup_info_files."/".$files);
858                        unset($file[0]);
859                        $all_info = json_decode(implode('', $file));
860
861                        $backup_file_location = $backup_files_location.'/'.$check_for_file.'.tar.gz';
862                        if(file_exists($backup_file_location) || isset($all_info->backup_location)){
863
864                                //Store all the files information in an array
865                                $backup_infos[] = $all_info;
866                        }
867                }
868        }
869
870        return $backup_infos;
871}
872
873// Deletes backups
874function backuply_delete_backup($tar_file) {
875       
876        global $error;
877       
878        $_file = $tar_file;
879        $bkey = basename(basename($_file, '.tar.gz'), '.tar');
880        $backup_info_dir = backuply_glob('backups_info');
881        $deleted = false;
882       
883        // Load Backuply's remote backup locations.
884        $backuply_remote_backup_locs = get_option('backuply_remote_backup_locs');
885       
886        $files_exists = 0;
887        $backup_infos = backuply_get_backups_info();
888        $is_bcloud = false; // We are using this so we know we need to update the quota too.
889
890        foreach($backup_infos as $backup_info){
891                // Is the backup on a remote location ?
892                if(!empty($backup_info->backup_location) && $backup_info->name == $bkey && array_key_exists($backup_info->backup_location, $backuply_remote_backup_locs)){
893
894                        $backup_dir = $backuply_remote_backup_locs[$backup_info->backup_location]['full_backup_loc'];
895                        $remote_stream_wrappers = array('dropbox', 'gdrive', 'softftpes', 'softsftp', 'webdav', 'aws', 'caws', 'onedrive', 'bcloud');
896
897                        if(in_array($backuply_remote_backup_locs[$backup_info->backup_location]['protocol'], $remote_stream_wrappers)){
898
899                                if($backuply_remote_backup_locs[$backup_info->backup_location]['protocol'] === 'bcloud'){
900                                        $is_bcloud = true;
901                                }
902                               
903                                if(!defined('BACKUPLY_PRO') && $backuply_remote_backup_locs[$backup_info->backup_location]['protocol'] !== 'gdrive' && $backuply_remote_backup_locs[$backup_info->backup_location]['protocol'] !== 'bcloud') {
904                                        $error[] = esc_html__('You are trying to access a PRO feature through FREE version', 'backuply');
905                                        return false;
906                                } else if(defined('BACKUPLY_PRO')){
907                                        include_once BACKUPLY_PRO_DIR . '/functions.php';
908                                }
909
910                                backuply_stream_wrapper_register($backuply_remote_backup_locs[$backup_info->backup_location]['protocol'], $backuply_remote_backup_locs[$backup_info->backup_location]['protocol']);
911                        }
912                       
913                        //echo "<br> checked for file existance : ".$backup_dir.'/'.$_file;
914                       
915                        if(file_exists($backup_dir.'/'.$_file)){
916                                //echo "<br> checked for file existance : ".$backup_dir.'/'.$_file;
917                                $files_exists = 1;
918                                break;
919                        }
920                }else{
921                        $backup_dir = backuply_glob('backups');
922               
923                        if(file_exists($backup_dir.'/'.$_file)){
924                                //echo "local file : ".$backup_dir.'/'.$_file;
925                                $files_exists = 1;
926                                break;
927                        }
928                }
929        }
930
931        if(!empty($files_exists)){
932                // Delete the backup
933                @unlink($backup_dir.'/'.$_file);
934
935                // Delete the backup_info file
936                @unlink($backup_info_dir.'/'.$bkey.'.php');
937               
938                // If the Location is remote
939                if(strpos($backup_dir, '://') !== FALSE){
940                        @unlink($backup_dir.'/'.$bkey.'.info'); // Changed to info file since 1.0.2
941                        @unlink($backup_dir.'/'.$bkey.'.log');
942                }
943
944                // Deleting log files from local
945                if(file_exists(BACKUPLY_BACKUP_DIR . $bkey.'_log.php')){
946                        @unlink(BACKUPLY_BACKUP_DIR . $bkey.'_log.php');
947                }
948
949                $deleted = true;
950        }else{
951
952                // Delete the backup_info file
953                @unlink($backup_info_dir.'/'.$bkey.'.php');
954               
955                // If the Location is remote
956                @unlink($backup_dir.'/'.$bkey.'.php');
957                if(strpos($backup_dir, '://') !== FALSE){
958                        @unlink($backup_dir.'/'.$bkey.'.info'); // Changed to info file since 1.0.2
959                        @unlink($backup_dir.'/'.$bkey.'.log');
960                }
961               
962                // Deleting log files from remote and local
963                if(file_exists(BACKUPLY_BACKUP_DIR . $bkey.'_log.php')){
964                        @unlink(BACKUPLY_BACKUP_DIR . $bkey.'_log.php');
965                }
966               
967                $deleted = true;
968        }
969
970        // Updating the storage usage of Backuply Cloud.
971        if(!empty($deleted) && !empty($is_bcloud)){
972                $args = ['bcloud'];
973                $schedule_time = wp_next_scheduled('backuply_update_quota', $args);
974
975                // We are scheduling this because it makes a remote call and can take time
976                // So we are pushing it on another request so, deletion can happen smoothly.
977                // We have added a delay of some time so that if there is consecutive deletion
978                // then we only make a single quota updation request.
979                if(empty($schedule_time)){
980                        wp_schedule_single_event(time() + 10, 'backuply_update_quota', $args);
981                }
982        }
983       
984        if(file_exists($backup_dir.'/'.$_file)) {
985                $deleted = false;
986                $error[] = __('Unable to delete ', 'backuply') . esc_html($_file);
987        }
988
989        return $deleted;
990}
991
992// Creates log file
993function backuply_create_log_file() {
994        @unlink(BACKUPLY_BACKUP_DIR.'backuply_log.php');
995        @touch(BACKUPLY_BACKUP_DIR.'backuply_log.php');
996}
997
998/**
999 * Connect to the ftp server
1000 *
1001 * @param       string $host The hostname of the ftp server
1002 * @param       string $username The username Login detail
1003 * @param       string $pass The Login password
1004 * @param       string $cd The path of the file or directory to be changed
1005 * @returns     bool
1006 */
1007function backuply_sftp_connect($host, $username, $pass, $protocol = 'ftp', $port = 21, $cd = false, $pri = '', $passphrase = ''){
1008       
1009        $port = (int) $port; // Converting to INT as FTP class requires an integer
1010
1011        backuply_include_lib($protocol);
1012       
1013        if($protocol == 'ftp'){
1014                $ftp = new ftp(FALSE, FALSE);
1015               
1016                if(!$ftp->SetServer($host, $port)) {
1017                        $ftp->quit();
1018                        return 0;
1019                }
1020               
1021                if (!$ftp->connect()) {
1022                        return -1;
1023                }
1024               
1025                if (!$ftp->login($username, $pass)) {
1026                        $ftp->quit();
1027                        return -2;
1028                }
1029               
1030                if(!empty($cd)){
1031                        if(!$ftp->chdir($cd)){
1032                                if(!$ftp->chdir(trim($cd, '/'))){
1033                                        return -3;
1034                                }
1035                                //return -3;
1036                        }
1037                }
1038               
1039                if(!$ftp->SetType(BACKUPLY_FTP_AUTOASCII)){
1040                }
1041               
1042                if(!$ftp->Passive(TRUE)){
1043                }
1044        }
1045
1046        // Class other than FTP
1047        if(empty($ftp)){
1048       
1049                // Initialize a Class
1050                $ftp = new $protocol();
1051               
1052                // Return if Class not found
1053                if(!is_object($ftp)){
1054                        return -1;
1055                }
1056               
1057                // For SFTP authentication with keys or password
1058                if($protocol == 'softftpes' && !empty($pri)){
1059                        $ftp->auth_pass = 0;
1060                }else{
1061                        $ftp->auth_pass = 1;
1062                }
1063
1064                // Can connect ?
1065                $ret = $ftp->connect($host, $port, $username, $pass, $pri, $passphrase);
1066               
1067                if(!$ret){
1068                        return -2;
1069                }
1070               
1071                // Is directory present
1072                if(!empty($cd)){
1073                        if(!$ftp->is_dir($cd)){
1074                                return -3;
1075                        }
1076                }
1077        }
1078
1079        return $ftp;
1080}
1081
1082// Creates stream wrapper and includes the associated class
1083function backuply_stream_wrapper_register($protocol, $classname){
1084       
1085        $protocols = array('dropbox', 'aws', 'caws', 'gdrive', 'softftpes', 'softsftp', 'webdav', 'onedrive', 'bcloud');
1086       
1087        if(!in_array($protocol, $protocols)){
1088                return true;
1089        }
1090
1091        backuply_include_lib($protocol);
1092       
1093        $existing = stream_get_wrappers();
1094        if(in_array($protocol, $existing)){
1095                return true;
1096        }
1097
1098        if(!stream_wrapper_register($protocol, $classname)){
1099                return false;
1100        }
1101
1102        return true;
1103}
1104
1105// Includes Lib Files
1106function backuply_include_lib($protocol) {
1107
1108        if(!class_exists($protocol)){
1109                if(file_exists(BACKUPLY_DIR.'/lib/'.$protocol.'.php')) {
1110                        include_once(BACKUPLY_DIR.'/lib/'.$protocol.'.php');
1111                        return true;
1112                }
1113
1114                if(defined('BACKUPLY_PRO') && defined('BACKUPLY_PRO_DIR') && file_exists(BACKUPLY_PRO_DIR . '/lib/' .$protocol . '.php')) {
1115                        include_once(BACKUPLY_PRO_DIR . '/lib/' .$protocol . '.php');
1116                        return true;
1117                }
1118
1119                return false;
1120        }
1121
1122        return true;
1123}
1124
1125// Load Remote Backup class and initialize the class object
1126function backuply_load_remote_backup($backup_proto){
1127       
1128        if(!array_key_exists($backup_proto, backuply_get_protocols())){
1129                return false;
1130        }
1131
1132        backuply_include_lib($backup_proto);
1133       
1134        $init_obj = new $backup_proto([]);
1135       
1136        return $init_obj;
1137}
1138
1139// Gets data and path of the backup location
1140function backuply_load_remote_backup_info($protocol) {
1141        $remote = get_option('backuply_remote_backup_locs');
1142       
1143        foreach($remote as $k => $r) {
1144                if($r['protocol'] == $protocol) {
1145                        return $r;
1146                }
1147        }
1148}
1149
1150// Returns Remote loc details by id
1151function backuply_get_loc_by_id($id, $filter = array()){
1152        $remote = get_option('backuply_remote_backup_locs');
1153
1154        foreach($remote as $k => $r) {
1155                if($k == $id) {
1156                        // Removes the indexes that matches the filter
1157                        foreach($r as $i => $k){
1158                                if(in_array($i, $filter)) {
1159                                        unset($r[$i]);
1160                                }
1161                        }
1162
1163                        return $r;
1164                }
1165        }
1166       
1167        return false;
1168}
1169
1170// Syncs available backup infos on a remote backup location to your site
1171function backuply_sync_remote_backup_infos($location_id){
1172       
1173        if($location_id === 'loc'){
1174                $synced_local = backuply_sync_local_backups();
1175                return true;
1176        }
1177       
1178        $locs = get_option('backuply_remote_backup_locs');
1179       
1180        if(empty($locs[$location_id])){
1181                return false;
1182        }
1183       
1184        $loc = $locs[$location_id];
1185        //backuply_print($loc);
1186       
1187        backuply_stream_wrapper_register($loc['protocol'], $loc['protocol']);
1188
1189        $list = @scandir($loc['full_backup_loc']);
1190       
1191        if(empty($list)){
1192                return false;
1193        }
1194       
1195        foreach($list as $k => $v){
1196               
1197                $ext = pathinfo($v, PATHINFO_EXTENSION);
1198               
1199                $allowed_ext = array('php', 'info');
1200                $fexists = $v;
1201
1202                if(strpos($v, '.info') !== FALSE){
1203                        $fexists = basename($v, '.info') . '.php';
1204                }
1205               
1206                if(!in_array($ext, $allowed_ext) || file_exists(backuply_glob('backups_info') . '/'. $fexists)){
1207                        //echo 'Continuing : '.$v.'<br>';
1208                        continue;
1209                }
1210                //echo $v.'<br>';
1211               
1212                // Get the contents
1213                $fh = fopen($loc['full_backup_loc']. '/' . trim($v, '/'), 'rb');
1214               
1215                if(empty($fh)){
1216                        continue;
1217                }
1218               
1219                $file = fread($fh, 8192);
1220                @fclose($fh);
1221                //backuply_print($file);
1222               
1223                if(empty($file)){
1224                        continue;
1225                }
1226               
1227                $lines = explode("\n", $file);
1228                unset($lines[0]);
1229               
1230                $info = json_decode(implode("\n", $lines), true);
1231                //backuply_print($info);
1232               
1233                if(empty($info)){
1234                        continue;
1235                }
1236               
1237                // Set the backup location ID
1238                $info['backup_location'] = $location_id;
1239                //backuply_print($info);
1240               
1241                $v = str_replace('.info', '.php', $v);
1242               
1243                // Write the file
1244                file_put_contents(backuply_glob('backups_info') .'/'.$v, "<?php exit();?>\n".json_encode($info, JSON_PRETTY_PRINT));
1245               
1246        }
1247       
1248        return true;
1249       
1250}
1251
1252function backuply_untar_archive($tarname, $untar_path, $file_list = array(), $handle_remote = false){
1253        global $globals, $can_write, $ftp;
1254
1255        // Create directory if not there
1256        if(!is_dir($untar_path)){
1257                @mkdir($untar_path);
1258        }
1259        $tar_archive = new backuply_tar($tarname, '', $handle_remote);
1260       
1261        if(empty($file_list)){
1262                $res = $tar_archive->extractModify($untar_path, '');
1263        }else{
1264                $res = $tar_archive->extractList($file_list, $untar_path);
1265        }
1266       
1267        if(!$res){
1268                return false;   
1269        }
1270       
1271        return true;   
1272}
1273
1274function backuply_sync_local_backups(){
1275       
1276        $backups_dir = backuply_glob('backups');
1277        $backups_info_dir = backuply_glob('backups_info');
1278       
1279        if(!file_exists($backups_dir) || !file_exists($backups_info_dir)){
1280                return false;
1281        }
1282
1283        $backups = @scandir($backups_dir);
1284
1285        $backup_info_name = '';
1286        $backup_file_name = '';
1287       
1288        foreach($backups as $backup){
1289                if(in_array($backup, ['.', '..', 'index.html', 'index.php', 'tmp'])){
1290                        continue;
1291                }
1292               
1293                $info_file_name = str_replace('.tar.gz', '.php', $backup);
1294               
1295                if(!file_exists($backups_info_dir . '/' . $info_file_name)){
1296                        backuply_create_info_file($info_file_name, $backup);
1297                }
1298        }
1299
1300}
1301
1302// Creates new info file, from the info file in that backup tar.gz
1303function backuply_create_info_file($backup_info_name, $backup_file_name){
1304
1305        $backups_dir = backuply_glob('backups');
1306        $backups_info_dir = backuply_glob('backups_info');
1307
1308        if(empty($backup_info_name) || empty($backup_file_name)){
1309                return true;
1310        }
1311
1312        include_once BACKUPLY_DIR . '/backuplytar.php'; // Including the Backuply TAR class.
1313
1314        $backup_path = $backups_dir . '/' .$backup_file_name;
1315        backuply_untar_archive($backup_path, $backups_dir .'/tmp/', array($backup_info_name));
1316       
1317        $archived_info = $backups_dir .'/tmp/' .$backup_info_name;
1318       
1319        if(!file_exists($archived_info)){
1320                return true;
1321        }
1322       
1323        $content = file_get_contents($archived_info);
1324
1325        if(!preg_match('/{.*}/s', $content, $json_info) || empty($json_info[0])){
1326                return true;
1327        }
1328
1329        $info_arr = json_decode($json_info[0], true);
1330
1331        if(empty($info_arr['size'])){
1332                $info_arr['size'] = filesize($backup_path);
1333        }
1334
1335        file_put_contents($backups_info_dir . '/'. $backup_info_name, "<?php exit();?>\n".json_encode($info_arr, JSON_PRETTY_PRINT));
1336       
1337        @unlink($archived_info);
1338
1339        return true;
1340}
1341
1342// Syncs available backup logs on a remote backup location to your site
1343function backuply_sync_remote_backup_logs($location_id, $fname){
1344       
1345        if(empty($location_id)){
1346                return false;
1347        }
1348       
1349        $locs = get_option('backuply_remote_backup_locs');
1350       
1351        if(empty($locs[$location_id])){
1352                return false;
1353        }
1354       
1355        $loc = $locs[$location_id];
1356       
1357        backuply_stream_wrapper_register($loc['protocol'], $loc['protocol']);
1358
1359        $list = @scandir($loc['full_backup_loc']);
1360       
1361        if(empty($list)){
1362                return false;
1363        }
1364       
1365        foreach($list as $k => $v){
1366               
1367                // Changing log name to log file for remote loc
1368                $fname = str_replace('_log.php', '.log', $fname);
1369                $ext = pathinfo($v, PATHINFO_EXTENSION);
1370
1371                if($ext != 'log' || $fname != trim($v, '/') || file_exists(BACKUPLY_BACKUP_DIR . $v)){
1372                        continue;
1373                }
1374               
1375                // Get the contents
1376                $fh = fopen($loc['full_backup_loc'].'/'.trim($v, '/'), 'rb');
1377               
1378                if(empty($fh)){
1379                        return false;
1380                }
1381               
1382                $file = '';
1383
1384                while(!feof($fh)){
1385                        $file .= fread($fh, 8192);
1386                }
1387               
1388                @fclose($fh);
1389
1390                if(empty($file)){
1391                        return false;
1392                }
1393
1394                // Changing log to php file for local
1395                $v = str_replace('.log', '_log.php', $v);
1396               
1397                // Write the file
1398                file_put_contents(BACKUPLY_BACKUP_DIR . $v, $file);
1399       
1400        }
1401       
1402        return true;
1403       
1404}
1405
1406//Fix the serialization in Cloned DB Tables
1407function backuply_wp_clone_sql($table, $field_prefix, $keepalive, $i = null){
1408
1409        global $wpdb;
1410
1411        if(empty($wpdb)){
1412                backuply_log('Fix Serialization failed: unable to connect to the database');
1413                return false;
1414        }
1415       
1416        if(empty($table) || empty($field_prefix)){
1417                return false;
1418        }
1419       
1420        $possible_tables = ['options', 'postmeta', 'commentmeta'];
1421        $possible_fields = ['option', 'meta'];
1422
1423        // We make sure here that we do not process any unwanted data.
1424        if(!in_array($table, $possible_tables, true) || !in_array($field_prefix, $possible_fields, true)){
1425                return false;
1426        }
1427
1428        if($wpdb->has_cap('identifier_placeholders')){
1429                $cnt_qry = $wpdb->prepare("SELECT count(%i) as %i FROM %i", [$field_prefix.'_id', 'count_'.$field_prefix, $wpdb->prefix.$table]);
1430        } else {
1431                $cnt_qry = $wpdb->prepare("SELECT count(%s) as %s FROM `".$wpdb->prefix.$table . "`", [$field_prefix.'_id', 'count_'.$field_prefix]);
1432        }
1433        $result = $wpdb->get_results($cnt_qry);
1434        $result = json_decode(json_encode($result[0]), true);
1435        $cnt_res = $result['count_'.$field_prefix];
1436       
1437        $count = 10000;
1438        $limit = 0;
1439
1440        if(is_null($i)){
1441                $i = $cnt_res;
1442                backuply_status_log('Repairing '. $wpdb->prefix.$table, 'repairing', 80);
1443        }
1444       
1445        backuply_status_log($i . ' Rows left to repair in ' . $wpdb->prefix.$table, 'working', 89);
1446       
1447        while($i >= 0){
1448               
1449                if(time() > $keepalive){
1450                        return (int) $i;
1451                }
1452
1453                if($wpdb->has_cap('identifier_placeholders')){
1454                        $query = $wpdb->prepare("SELECT %i, %i FROM %i ORDER BY %i LIMIT %d, %d", [$field_prefix.'_id', $field_prefix.'_value', $wpdb->prefix.$table, $field_prefix.'_id', $limit, $count]);
1455                } else {
1456                        $query = $wpdb->prepare("SELECT `".$field_prefix."_id`, `".$field_prefix."_value` FROM `".$wpdb->prefix.$table."` ORDER BY %s LIMIT %d, %d", [$field_prefix.'_id', $limit, $count]);
1457                }
1458
1459                $result = $wpdb->get_results($query);
1460               
1461                // If there are no more rows we need to break the loop
1462                if(empty($result[0])){
1463                        break;
1464                }
1465               
1466                foreach($result as $rk => $rv){
1467                        $rv = json_decode(json_encode($rv), true);
1468                       
1469                        $update_query = '';
1470                        $sresult = '';
1471                        // This data should be serialized
1472                        if(preg_match('/^a:(.*?):{/is', $rv[$field_prefix.'_value']) || preg_match('/^O:(.*?):{/is', $rv[$field_prefix.'_value'])){
1473                               
1474                                if(preg_match('/^utf8(.*?)/is', $wpdb->charset) && empty($conn)){
1475                                        $encoding = mb_detect_encoding($rv[$field_prefix.'_value']);
1476                                        if(empty($encoding)){
1477                                                $encoding = 'ISO-8859-1';
1478                                        }
1479
1480                                        $_unserialize = backuply_unserialize(mb_convert_encoding($rv[$field_prefix.'_value'], 'UTF-8', 'auto'));
1481                                        $updated_data = (!function_exists('get_magic_quotes_gpc') || !get_magic_quotes_gpc()) ? addslashes(mb_convert_encoding(serialize($_unserialize), $encoding, 'UTF-8')) : mb_convert_encoding(serialize($_unserialize), $encoding, 'UTF-8');
1482                                }else{
1483                                        $_unserialize = backuply_unserialize($rv[$field_prefix.'_value']);
1484                                        $updated_data = (!function_exists('get_magic_quotes_gpc') || !get_magic_quotes_gpc()) ? addslashes(serialize($_unserialize)) : serialize($_unserialize);
1485                                }
1486                               
1487                                $update_query = "UPDATE `".$wpdb->prefix.$table."` SET `".$field_prefix."_value` = '".$updated_data."' WHERE `".$field_prefix."_id` = '".$rv[$field_prefix.'_id']."';";
1488                               
1489                                $sresult = $wpdb->query($update_query);
1490                        }
1491
1492                        $i--;
1493                        $limit++;
1494                }
1495        }
1496       
1497        return true;
1498}
1499
1500/**
1501 * Callback for fixing any broken serialized string
1502 *
1503 * @package      string
1504 * @author       Brijesh Kothari
1505 * @param        array $matches
1506 * @return       string Returns the fixed serialize content
1507 * @since        5.3.1
1508 * NOTE : Any changes in this function will affect anywhere this function is used as a callback
1509 */
1510function backuply_fix_serialize_callback($matches){
1511       
1512        //r_print($matches);
1513       
1514        // We are not using soft_is_serialized_str() because that checks for ; or } at the end and our data can be a:2:{s:3:"three
1515        if(preg_match('/^a:(.*?):{/is', $matches[2]) || preg_match('/^O:(.*?):/is', $matches[2])){
1516                return $matches[0];
1517        }
1518       
1519        return 's:'.strlen($matches[2]).':"'.$matches[2].'";';
1520}
1521
1522/**
1523 * Unserialize a string and also fixes any broken serialized string before unserializing
1524 *
1525 * @package      string
1526 * @author       Pulkit Gupta
1527 * @param        string $str
1528 * @return       array Returns an array if successful otherwise false
1529 * @since        1.0
1530 */
1531// Note : This will not work for a serialized string in an array key
1532function backuply_unserialize($str){
1533
1534        $var = @unserialize($str);
1535       
1536        if(empty($var)){
1537               
1538                // NOTE : Any changes in this pattern will need to be handled in callback function as well
1539                $str = preg_replace_callback('/s:(\d+):"(.*?)";(?=([:]|(?<=;)\}(?!\.)|a:|s:|S:|b:|d:|i:|o:|O:|C:|r:|R:|N;))/s', 'backuply_fix_serialize_callback', $str);
1540               
1541                $var = @unserialize($str);
1542       
1543        }
1544       
1545        //If it is still empty false
1546        if($var === false){
1547       
1548                return false;
1549       
1550        }else{
1551       
1552                return $var;
1553       
1554        }
1555
1556}
1557
1558// Renames backuply_log file to show last logs.
1559function backuply_copy_log_file($is_restore = false, $file_name = ''){
1560       
1561        if(empty($file_name)){
1562                $file_name = 'backuply_backup';
1563        }
1564       
1565        $copy_to = empty($is_restore) ? $file_name . '_log.php' : 'backuply_restore_log.php';
1566        copy(BACKUPLY_BACKUP_DIR . 'backuply_log.php', BACKUPLY_BACKUP_DIR . $copy_to);
1567
1568}
1569
1570function backuply_pattern_type_text($type) {
1571               
1572        if(empty($type)){
1573                return esc_html__('No type found!', 'backuply');
1574        }
1575               
1576        $types = array(
1577                'extension' => esc_html__('With specific extension', 'backuply'),
1578                'beginning' => esc_html__('At beginning', 'backuply'),
1579                'end' => esc_html__('At end', 'backuply'),
1580                'anywhere' => esc_html__('Anywhere', 'backuply')
1581        );
1582               
1583        return $types[$type];
1584}
1585
1586function backuply_init_restore($info){
1587       
1588        global $wpdb;
1589       
1590        $backuply_backup_dir = backuply_cleanpath(BACKUPLY_BACKUP_DIR);
1591       
1592        if(!is_dir($backuply_backup_dir.'/restoration')) {
1593                mkdir($backuply_backup_dir.'/restoration', 0755, true);
1594        }
1595       
1596        $myfile = fopen($backuply_backup_dir.'/restoration/restoration.php', 'w') or die('Unable to open restoaration.php file !');
1597        $txt = time();
1598        fwrite($myfile, $txt);
1599        fclose($myfile);
1600
1601        $info['plugin_dir'] = backuply_cleanpath(BACKUPLY_DIR);
1602        $info['backuly_backup_dir'] = $backuply_backup_dir;
1603        $info['softdb'] = $wpdb->dbname;
1604        $info['softdbhost'] = $wpdb->dbhost;
1605        $info['softdbuser'] = $wpdb->dbuser;
1606        $info['softdbpass'] = $wpdb->dbpassword;
1607        $info['tbl_prefix'] = $wpdb->prefix;
1608        $info['backuply_version'] = BACKUPLY_VERSION;
1609
1610        backuply_create_log_file(); // Create a log file.
1611        backuply_status_log('Starting Restoring your backup', 'info', 10);
1612        wp_schedule_single_event(time() + BACKUPLY_TIMEOUT_TIME, 'backuply_timeout_check', array('is_restore' => true));
1613        backuply_restore_curl($info);
1614
1615}
1616
1617function backuply_restore_curl($info = array()) {
1618        global $wpdb, $backuply;
1619
1620        $backup_file_loc = $info['backup_file_loc'];
1621        $info['site_url'] = site_url();
1622        $info['to_email'] = get_option('backuply_notify_email_address');
1623        $info['admin_email'] = get_option('admin_email');
1624        $info['ajax_url'] = admin_url('admin-ajax.php');
1625        $info['debug_mode'] = $backuply['debug_mode'];
1626        $info['user_id'] = get_current_user_id();
1627        $info['exclude_db'] = !empty($backuply['excludes']['db']) ? $backuply['excludes']['db'] : array();
1628
1629        $config = backuply_get_config();
1630       
1631        if(empty($config['RESTORE_KEY'])) {
1632                return;
1633        }
1634       
1635        $info['backup_dir'] = backuply_glob('backups');
1636
1637        // Setting backup_dir if its remote location
1638        if(!empty($info['loc_id'])){
1639                $backuply_remote_backup_locs = get_option('backuply_remote_backup_locs');
1640                $loc_id = $info['loc_id'];
1641                $info['backup_dir'] = $backuply_remote_backup_locs[$loc_id]['full_backup_loc'];
1642                backuply_set_restoration_file($backuply_remote_backup_locs[$loc_id]);
1643        }
1644
1645        $info['restore_key'] = urlencode($config['RESTORE_KEY']);
1646        $tmp_restore_file = ABSPATH . '/backuply-restore.php';
1647        $tmp_restore_include = "<?php\ndefine('BACKUPLY_DIR_FOR_RESTORE', '".BACKUPLY_DIR."');\ninclude_once '".BACKUPLY_DIR."/restore_ins.php';";
1648
1649        if(file_put_contents($tmp_restore_file, $tmp_restore_include)){
1650                $restore_url = site_url() . '/backuply-restore.php';
1651        } else {
1652                $restore_url = BACKUPLY_URL . '/restore_ins.php';
1653        }
1654
1655        $info['restore_curl_url'] = $restore_url;
1656       
1657        $args = array(
1658                'body' => $info,
1659                'timeout' => 0.01,
1660                'blocking' => false,
1661                'sslverify' => false,
1662                'headers' => [
1663                        'Referer' => (!empty($_SERVER['REQUEST_SCHEME']) ? $_SERVER['REQUEST_SCHEME'] : 'http') .'://'. $_SERVER['SERVER_NAME'],
1664                ],
1665                'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
1666        );
1667
1668        wp_remote_post($info['restore_curl_url'], $args);
1669}
1670
1671// Shifts the Config keys from file to db for user below 1.2.0.
1672function backuply_keys_to_db(){
1673        $config = backuply_get_config();
1674        if(isset($config['RESTORE_KEY'])){
1675                unset($config['RESTORE_KEY']); // Restore Key gets generated every time a restore is created.
1676        }
1677
1678        update_option('backuply_config_keys', $config);
1679        unlink(BACKUPLY_BACKUP_DIR . '/backuply_config.php');
1680}
1681
1682// Create a status lock key
1683function backuply_set_status_key(){
1684       
1685        $key = wp_generate_password(32, false);
1686
1687        file_put_contents(BACKUPLY_BACKUP_DIR . '/status_key.php', "<?php exit();?>\n". $key);
1688       
1689        @chmod(BACKUPLY_BACKUP_DIR . '/status_key.php', 0600);
1690}
1691
1692function backuply_get_status_key(){
1693
1694        $status_file = BACKUPLY_BACKUP_DIR . 'status_key.php';
1695
1696        if(!file_exists($status_file)){
1697                return false;
1698        }
1699
1700        $content = file_get_contents($status_file);
1701        $content = str_replace("<?php exit();?>\n", '', $content);
1702       
1703        return $content;
1704}
1705
1706function backuply_get_quota($protocol){
1707
1708        backuply_stream_wrapper_register($protocol, $protocol);
1709       
1710        if(class_exists($protocol) && method_exists($protocol, 'get_quota')){
1711                $class = new $protocol();
1712               
1713                $info = backuply_load_remote_backup_info($protocol);
1714                $quota = $class->get_quota($info['full_backup_loc']);
1715
1716                if(empty($quota)){
1717                        return false;
1718                }
1719               
1720                return $quota;
1721        }
1722       
1723        return false;
1724}
1725
1726function backuply_schedule_quota_updation($location){
1727
1728        $storage_loc = sanitize_text_field($location);
1729       
1730        if(empty($storage_loc)){
1731                backuply_log(__('No Storage location provided', 'backuply'));
1732                return;
1733        }
1734
1735        $quota = backuply_get_quota($storage_loc);
1736       
1737        if(empty($quota)){
1738                backuply_log('Scheduled Quota Update: Nothing returned in quota fetch!');
1739                return;
1740        }
1741       
1742        $info = get_option('backuply_remote_backup_locs', []);
1743       
1744        if(!empty($info)){
1745                foreach($info as $key => $locs){
1746                        if($locs['protocol'] === $storage_loc){
1747                                $info[$key]['backup_quota'] = (int) $quota['used'];
1748                                $info[$key]['allocated_storage'] = (int) $quota['total'];
1749                        }
1750                }
1751               
1752                update_option('backuply_remote_backup_locs', $info, false);
1753        }
1754
1755        backuply_log('Scheduled Quota Update: Fetched Quota updated successfully!');
1756}
1757
1758// Checks every day if there is any file inside tmp or a backup with dot(.) at start
1759// and have not been updated since last 24 hours, then delete them.
1760// And also deletes any softperms, softsql residue left
1761function backuply_delete_tmp(){
1762
1763        $backup_folder = backuply_glob('backups');
1764
1765        // Deleting files with dot(.) at start
1766        $files = glob($backup_folder .'/.*.tar.gz');
1767
1768        if(!empty($files)){
1769                foreach($files as $file){
1770                        if(!file_exists($file) || is_dir($file)){
1771                                continue;
1772                        }
1773
1774                        if(filemtime($file) < (time() - 86400)){
1775                                try{
1776                                        unlink($file);
1777                                        backuply_log('Deletion unsuccessful: '.$file);
1778                                }catch(Exception $e){
1779                                        backuply_log('Deletion Error: ' . $e->getMessage());
1780                                }
1781                        }
1782                }
1783        }
1784
1785        // Deleting folders in tmp
1786        $folders = glob($backup_folder .'/tmp/*/');
1787
1788        if(!empty($folders)){
1789                foreach($folders as $folder){
1790                        // We dont need to delete any file in this folder.
1791                        if(!is_dir($folder)){
1792                                continue;       
1793                        }
1794
1795                        if(filemtime($folder) < (time() - 86400)){
1796                                try{
1797                                        global $wp_filesystem;
1798
1799                                        include_once ABSPATH . 'wp-admin/includes/file.php';
1800                                        WP_Filesystem();
1801
1802                                        $wp_filesystem->rmdir($folder, true);
1803                                } catch(Exception $e){
1804                                        backuply_log('Deletion Error: '. $e->getMessage());
1805                                }
1806                        }
1807                }
1808        }
1809       
1810        // Deletes any restore residue
1811        if(!file_exists(BACKUPLY_BACKUP_DIR .'/restoration/restoration.php')){
1812                if(file_exists(ABSPATH .'/softperms.txt')){
1813                        unlink(ABSPATH .'/softperms.txt');
1814                }
1815
1816                if(file_exists(ABSPATH .'/softsql.sql')){
1817                        unlink(ABSPATH .'/softsql.sql');
1818                }
1819
1820                if(file_exists(ABSPATH .'/softver.txt')){
1821                        unlink(ABSPATH .'/softver.txt');
1822                }
1823        }
1824}
1825
1826function backuply_add_mime_types($mimes) {
1827
1828    if(!array_key_exists('tar', $mimes)){
1829        $mimes['tar'] =  'application/x-tar';
1830    }
1831
1832    if(!array_key_exists('gz|gzip', $mimes) && !array_key_exists('gz', $mimes)){
1833        $mimes['gz|gzip'] = 'application/x-gzip';
1834    }
1835
1836    return $mimes;
1837}
1838
1839function backuply_sanitize_filename($filename){
1840        $filename = sanitize_file_name($filename);
1841        // We need to remove "_" as sanitize_file_name adds it if the file
1842        // have more than 2 extensions, which in our case happens sometimes, if the
1843        // URL of the website, has a sub domain or has TLD as .co.in or similar.
1844        $filename = str_replace('_.', '.', $filename);
1845
1846        return $filename;
1847}
1848
1849function backuply_direct_download_file(){
1850        check_admin_referer('backuply_download_security', 'security');
1851
1852        if(!current_user_can('manage_options')){
1853                wp_die('You do not have required privilege to download the file');
1854        }
1855       
1856        @set_time_limit(0);
1857
1858        $filename = backuply_optget('backup_name');
1859        $filename = backuply_sanitize_filename($filename);
1860        $backups_dir = backuply_glob('backups');
1861       
1862        $file_path = $backups_dir . '/'. $filename;
1863
1864        if(!file_exists($file_path)){
1865                wp_die('File does not exists');
1866        }
1867       
1868        if(ob_get_level()){
1869                $ob_levels = min(5, (int) ob_get_level());
1870                for($i = 1; $i<= $ob_levels; $i++){
1871                        @ob_end_clean();
1872                }
1873        }
1874
1875        if(ob_get_level()){
1876                @ob_end_clean();
1877        }
1878
1879        // Get the file size
1880        $file_size = filesize($file_path);
1881
1882        // Handle range requests
1883        header('Content-Type: application/octet-stream');
1884        header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
1885        header('Content-Transfer-Encoding: binary');
1886        header('Content-Length: ' . $file_size);
1887        header('Last-Modified: ' . gmdate('D, d M Y H:i:s T', filemtime($file_path)));
1888        header('Expires: 0');
1889        header('Cache-Control: public, must-revalidate, max-age=0');
1890        header('Pragma: no-cache');
1891
1892        readfile($file_path);
1893        die();
1894}
1895
1896// Returns the Security key
1897function backuply_status_config(){
1898
1899        $config_file = BACKUPLY_BACKUP_DIR . '/status_key.php';
1900       
1901        if(!file_exists($config_file) || 0 == filesize($config_file)) {
1902                return false;
1903        }
1904
1905        $fp = file($config_file);
1906
1907        if(empty($fp[1])){
1908                return '';
1909        }
1910
1911        $status_key = $fp[1];
1912
1913        return $status_key;
1914}
1915
1916// Verifies the backuply key
1917function backuply_verify_status_log(){
1918       
1919        if(empty($_REQUEST['status_key'])) {
1920                return false;
1921        }
1922       
1923        $status_lock = BACKUPLY_BACKUP_DIR. '/status.lock';
1924       
1925        if(!file_exists($status_lock) || (time() - filemtime($status_lock) > 1800)){
1926                return false;
1927        }
1928
1929        $status_key = backuply_status_config();
1930       
1931        if(!$status_key) {
1932                return false;
1933        }
1934       
1935        $request_key = sanitize_text_field(wp_unslash($_REQUEST['status_key']));
1936
1937        if(urldecode($request_key) == $status_key) {
1938                return true;
1939        }
1940
1941        return false;
1942}
Note: See TracBrowser for help on using the repository browser.