HEX
Server: Apache/2.4.65 (Debian)
System: Linux web6 5.10.0-36-amd64 #1 SMP Debian 5.10.244-1 (2025-09-29) x86_64
User: innocamp (1028)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /home/gdtrain/public_html/wp-content/plugins/backup-wd/includes/buwd-destination-folder.php
<?php

/**
 *
 */
class Buwd_Destination_Folder
{
    protected static $instance = null;

    /**
     *
     */
    public function __construct()
    {
        $this->info['title'] = __('Transferring archive to folder', 'buwd');
        $this->info['sync_title'] = __('Syncing files to folder', 'buwd');
        $this->info['name'] = __('Folder', 'buwd');
        $this->info['desc'] = __('', 'buwd');
        $this->info['sync'] = true;
    }

    public function defaults()
    {
        $wp_upload_dir = Buwd::get_upload_dir();
        $wp_home_path = Buwd::get_plugin_data('home_path');

        $defaults = array(
            'folderpath'       => str_replace($wp_home_path, '', $wp_upload_dir) . Buwd::get_plugin_data('folder_name') . '-{hash_key}/',
            'folderdelete'     => 15,
            'folderdeletesync' => '1'
        );

        return $defaults;
    }

    public function get_options($job_id)
    {
        $wp_upload_dir = Buwd::get_upload_dir();
        $options = array(
            'key'    => 'destination-folder',
            'title'  => '',
            'fields' => array(
                array(
                    'label'  => __('Folder to store', 'buwd'),
                    'header' => __('Folder Options', 'buwd'),
                    'id'     => 'folderpath',
                    'name'   => 'folderpath',
                    'type'   => 'text',
                    'class'  => array(
                        'buwd-large-text',
                    ),
                    'value'  => esc_html(Buwd_Options::get($job_id, 'folderpath')),
                    'hint'   => array(
                        'html' => $wp_upload_dir . '<p class="description">Setup the local folder where the backup files will be stored. You can write any name for the folder, but make sure the path starts with root directory. We recommend keeping <b>{hash_key}</b> component.</p>'
                    ),
                ),
                array(
                    'label'      => __('File deletion', 'buwd'),
                    'id'         => 'folderdelete',
                    'name'       => 'folderdelete',
                    'type'       => 'number', // to number
                    'class'      => array(
                        'buwd-extra-small-text',
                    ),
                    'attr'       => array(
                        'min' => "0"
                    ),
                    'value'      => esc_html(Buwd_Options::get($job_id, 'folderdelete')),
                    'visibility' => Buwd_Options::get($job_id, 'backup_type') == 'archive' ? true : false,
                    'hint'       => array(
                        'html' => '<span>Number of files to keep in folder.</span><p class="description">Specify the maximum number of files in the dedicated folder. When the limit is reached, the oldest backup file will be deleted.</p>',
                    ),
                ),
                array(
                    'label'      => __('File deletion', 'buwd'),
                    'id'         => 'folderdeletesync',
                    'name'       => 'folderdeletesync',
                    'type'       => 'checkbox', // to number
                    'class'      => array(),
                    'choices'    => array(
                        '1' => 'Keep deleted files from previous backup sync.'
                    ),
                    'value'      => Buwd_Options::get($job_id, 'folderdeletesync'),
                    'visibility' => Buwd_Options::get($job_id, 'backup_type') != 'archive' ? true : false,
                    'hint'       => array(
                        'html' => '<p class="description">Uncheck the option to remove the deleted files.</p><span class="buwd-error">Please note that if you uncheck this option, you will loose all previous files in backup storage folder</span>'
                    ),
                ),
            ),
        );

        return $options;
    }

    public function run(Buwd_Job $job_object)
    {
        $job_object->buwd_logger->set_log(sprintf(__('%d. Attempted to send backup file to %s folder.', 'buwd'), $job_object->steps_data[$job_object->current_step]['step'], $job_object->backup_folder));
        $job_object->update_progress();

        $job_object->check_if_stopped();

        if (!is_dir($job_object->backup_folder)) {
            //mkdir( $job_object->backup_folder );
            wp_mkdir_p($job_object->backup_folder);
        }

        $folder_protect = Buwd_Options::getSetting('folder_protect');
        if (!empty($folder_protect)) {
            Buwd_File::protect_folder($job_object->backup_folder);
        }

        $job_object->buwd_logger->set_log(__('Upload to folder has started.', 'buwd'));
        $job_object->update_progress();


        if (copy(Buwd::get_plugin_data('temp_folder_dir') . $job_object->backup_file, $job_object->backup_folder . $job_object->backup_file)) {
            $job_object->buwd_logger->set_log(__('Backup was transferred to folder.', 'buwd'));

            @unlink(Buwd::get_plugin_data('temp_folder_dir') . $job_object->backup_file);
        } else {
            $job_object->buwd_logger->set_log(__('An error occurred while trying to transfer backup to folder.', 'buwd'), E_USER_ERROR);
        }
        $job_object->update_progress();

        $last_file = array();
        $last_file['file'] = $job_object->backup_file;
        $last_file['folder'] = substr($job_object->backup_folder, strlen(get_home_path()), strlen($job_object->backup_folder));
        $last_file['folder_path'] = $job_object->backup_folder;
        $last_file['time'] = filemtime($job_object->backup_folder . $job_object->backup_file);
        $last_file['size'] = filesize($job_object->backup_folder . $job_object->backup_file);
        $last_file['jid'] = $job_object->job_id;
        $last_file['dest'] = 'folder';
        $last_file['logfile'] = basename($job_object->buwd_logger->logfile);

        $dest_files = get_site_option('buwd-dest-folder-' . $job_object->job_id, array());
        $dest_files[] = $last_file;

        update_site_option('buwd-dest-folder-' . $job_object->job_id, $dest_files);

        $backup_files = array();
        if (is_writable($job_object->backup_folder)) {
            if ($handle = opendir($job_object->backup_folder)) {
                while (false !== ($file = readdir($handle))) {
                    $job_object->check_if_stopped();
                    if (in_array($file, array('.', '..'), true)) {
                        continue;
                    }
                    if (!is_dir($job_object->backup_folder . $file) && !is_link($job_object->backup_folder . $file)) {
                        $backup_files[filemtime($job_object->backup_folder . $file)] = $file;
                    }
                }
                closedir($handle);
            }

            $deleted = 0;
            $files_to_delete = array();
            if (!empty($job_object->job['folderdelete']) && $job_object->job['folderdelete'] > 0 && count($backup_files) > $job_object->job['folderdelete']) {
                ksort($backup_files);
                while (count($backup_files) > $job_object->job['folderdelete']) {
                    $file = array_shift($backup_files);
                    unlink($job_object->backup_folder . $file);
                    $deleted++;
                    $files_to_delete[] = $file;
                }
            }

            if (!empty($files_to_delete)) {
                Buwd_Options::backup_bulk_delete('buwd-dest-folder-' . $job_object->job_id, $files_to_delete);
            }

            if ($deleted > 0) {
                $job_object->buwd_logger->set_log(sprintf(__('%d files were deleted from folder.', 'buwd'), $deleted));
                $job_object->update_progress();
            }
        }

        return true;
    }

    public function run_sync(Buwd_Job $job_object)
    {
        $job_object->check_if_stopped();

        $job_object->buwd_logger->set_log(sprintf(__('%d. Attempted to sync files to folder.', 'buwd'), $job_object->steps_data[$job_object->current_step]['step']));
        $job_object->update_progress();

        $files_folders = array();
        $files_folders_dir = Buwd::get_plugin_data('temp_folder_dir') . 'job_files_folders.php';
        if (file_exists($files_folders_dir)) {
            $files_folders = unserialize(file_get_contents($files_folders_dir));
        }

        if (!isset($files_folders['files'])) {
            $files_folders['files'] = array();
        }

        $sync_folder = Buwd_File::get_absolute_path(str_replace('{hash_key}', Buwd::get_plugin_data('hash'), $job_object->job['folderpath']));

        if (!is_dir($sync_folder)) {
            wp_mkdir_p($sync_folder);
        }

        $folder_protect = Buwd_Options::getSetting('folder_protect');
        if (!empty($folder_protect)) {
            Buwd_File::protect_folder($sync_folder);
        }

        if (!isset($job_object->steps_data[$job_object->current_step]['file_key'])) {
            $job_object->steps_data[$job_object->current_step]['file_key'] = -1;
            $job_object->steps_data[$job_object->current_step]['sub_step'] = 'folder_files';
            $job_object->steps_data[$job_object->current_step]['files_count'] = 0;
            $job_object->steps_data[$job_object->current_step]['folder_size'] = 0;
            $job_object->steps_data[$job_object->current_step]['sync_files'] = array();
        }


        if ($job_object->steps_data[$job_object->current_step]['sub_step'] == 'folder_files') {
            $this->get_sync_files($sync_folder, $job_object->steps_data[$job_object->current_step]['sync_files']);

            $job_object->buwd_logger->set_log(__('File list from folder was retrieved.', 'buwd'));
            $job_object->update_progress();

            $job_object->steps_data[$job_object->current_step]['sub_step'] = 'sync_files';
        }


        if ($job_object->steps_data[$job_object->current_step]['sub_step'] == 'sync_files') {
            if (!empty($files_folders['files'])) {
                $job_object->buwd_logger->set_log(__('Modified files were copied to folder.', 'buwd'));
                $job_object->update_progress();
                $files = array_reduce($files_folders['files'], 'array_merge', array());
                foreach ($files as $file_key => $file) {
                    if ($job_object->steps_data[$job_object->current_step]['file_key'] >= $file_key) {
                        continue;
                    }

                    $job_object->check_if_stopped();
                    $job_object->restart_if_needed();

                    if (strpos($file, $job_object->job['abs_path']) !== false) {
                        $file_dirname = $sync_folder . substr($file, strlen($job_object->job['abs_path']));
                    } else {
                        $file_dirname = $sync_folder . substr($file, strlen(dirname($job_object->job['abs_path'])));
                    }

                    if (isset($job_object->steps_data[$job_object->current_step]['sync_files'][$file_dirname]) && $job_object->steps_data[$job_object->current_step]['sync_files'][$file_dirname] == md5_file($file)) {
                        unset($job_object->steps_data[$job_object->current_step]['sync_files'][$file_dirname]);
                        continue;
                    }

                    if (!is_dir(dirname($file_dirname))) {
                        wp_mkdir_p(dirname($file_dirname));
                    }
                    copy($file, $file_dirname);
                    $job_object->steps_data[$job_object->current_step]['folder_size'] += filesize($file);

                    $job_object->buwd_logger->set_log(sprintf(__('%s file was copied.', 'buwd'), $file));
                    $job_object->update_progress();

                    if (isset($job_object->steps_data[$job_object->current_step]['sync_files'][$file_dirname])) {
                        unset($job_object->steps_data[$job_object->current_step]['sync_files'][$file_dirname]);
                    }

                    $job_object->steps_data[$job_object->current_step]['file_key'] = $file_key;
                }
                foreach ($files_folders['folders'] as $folder) {
                    $folder_name = $sync_folder . substr($folder, strlen($job_object->job['abs_path']));

                    if (!is_dir($folder_name)) {
                        wp_mkdir_p($folder_name);
                    }
                }
            }

            $job_object->steps_data[$job_object->current_step]['sub_step'] = 'sync_extra_files';
        }

        if ($job_object->steps_data[$job_object->current_step]['sub_step'] == 'sync_extra_files') {
            if ($job_object->extra_files) {
                $job_object->buwd_logger->set_log(__('Modified extra files were copied to folder.', 'buwd'));
                $job_object->update_progress();

                foreach ($job_object->extra_files as $extra_file) {
                    $job_object->check_if_stopped();
                    $job_object->restart_if_needed();
                    $base_file = $sync_folder . basename($extra_file);
                    if (isset($job_object->steps_data[$job_object->current_step]['sync_files'][$base_file]) && $job_object->steps_data[$job_object->current_step]['sync_files'][$base_file] == md5_file($extra_file)) {
                        unset($job_object->steps_data[$job_object->current_step]['sync_files'][$base_file]);
                        continue;
                    }
                    copy($extra_file, $base_file);
                    $job_object->steps_data[$job_object->current_step]['folder_size'] += filesize($extra_file);
                    $job_object->buwd_logger->set_log(sprintf(__('%s extra file was copied.', 'buwd'), $extra_file));
                    $job_object->update_progress();
                    if (isset($job_object->steps_data[$job_object->current_step]['sync_files'][$base_file])) {
                        unset($job_object->steps_data[$job_object->current_step]['sync_files'][$base_file]);
                    }
                }
            }
            $job_object->steps_data[$job_object->current_step]['sub_step'] = 'delete_files';
        }

        $sync_file = get_site_option('buwd-dest-folder-sync-' . $job_object->job_id, array());
        $sync_file['file'] = 'Synchronized';
        $sync_file['folder'] = substr($sync_folder, strlen(get_home_path()), strlen($sync_folder));
        $last_file['folder_path'] = $sync_folder;
        $sync_file['time'] = current_time('timestamp', true);
        $sync_file['size'] = $job_object->steps_data[$job_object->current_step]['folder_size'];
        $sync_file['jid'] = $job_object->job_id;
        $sync_file['dest'] = 'folder';
        $sync_file['logfile'] = basename($job_object->buwd_logger->logfile);
        $sync_file['sync'] = 1;

        update_site_option('buwd-dest-folder-sync-' . $job_object->job_id, $sync_file);

        if ($job_object->steps_data[$job_object->current_step]['sub_step'] == 'delete_files') {
            if (!$job_object->job['folderdeletesync'] && !empty($job_object->steps_data[$job_object->current_step]['sync_files'])) {
                $job_object->buwd_logger->set_log(__('Non-existent files were deleted from folder.', 'buwd'));
                $folders_to_check = array();
                foreach ($job_object->steps_data[$job_object->current_step]['sync_files'] as $sync_file => $sync_file_hash) {

                    $job_object->check_if_stopped();
                    $job_object->restart_if_needed();
                    if (file_exists($sync_file)) {
                        unlink($sync_file);
                        $job_object->buwd_logger->set_log(sprintf(__('%s file was deleted from folder.', 'buwd'), $sync_file));
                        $job_object->update_progress();
                    }

                    unset($job_object->steps_data[$job_object->current_step]['sync_files'][$sync_file]);
                    $folders_to_check[] = dirname($sync_file);
                }

                Buwd_File::delete_if_empty(array_unique($folders_to_check));
            }
        }

        return true;
    }

    private function get_sync_files($folder, &$job_obj_sync_files)
    {
        if ($dir = opendir($folder)) {
            while (false !== ($file = readdir($dir))) {
                if (in_array($file, array('.', '..'), true)) {
                    continue;
                }

                if (is_dir($folder . $file)) {
                    $this->get_sync_files(trailingslashit($folder . $file), $job_obj_sync_files);
                } else if (is_readable($folder . $file) && !is_link($folder . $file)) {
                    $job_obj_sync_files[$folder . $file] = md5_file($folder . $file);
                }
            }
            closedir($dir);
        }
    }

    public static function display_messages()
    {

    }

    public function save_form($job_id, $field_names)
    {
        foreach ($field_names as $field_name) {
            $field_value = Buwd_Helper::get($field_name) ? Buwd_Helper::get($field_name) : '';

            if ($field_name == 'folderpath') {
                $field_value = trailingslashit(str_replace('//', '/', str_replace('\\', '/', trim(sanitize_text_field($field_value)))));
            }

            if ($field_name == 'folderdelete') {
                $field_value = (int)$field_value;
            }
            Buwd_Options::update_job_option($job_id, $field_name, $field_value);
        }
    }

    public function delete_file($backup)
    {
        $file = $backup['file'];
        $folder = $backup['folder_path'];

        //delete from folder
        if (file_exists($folder . $file)) {
            if (!unlink($folder . $file)) {
                return false;
            }
        }

        return true;
    }

    public function download_file($backup)
    {
        $file = $backup['file'];
        $folder_path = $backup['folder_path'];
        $size = $backup['size'];
        $file_url = $folder_path . $file;

        if (isset($file_url) && is_readable($file_url) && !is_link($file_url)) {
            @set_time_limit(3000);
            nocache_headers();
            while (ob_get_level() > 0) {
                @ob_end_clean();
            }

            header("Content-Description: File Transfer");
            header("Content-Type:  application/octet-stream");
            header("Content-disposition: attachment; filename=\"" . basename($file) . "\"");
            header("Content-Transfer-Encoding: Binary");
            header("Connection: Keep-Alive");
            header("Expires: 0");
            header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
            header("Pragma: public");
            header("Content-Length: " . $size);
            readfile($file_url);
            die();
        } else {
            set_site_transient('buwd_backups_error', __('File not found.', 'buwd'));
            Buwd_Helper::redirect(array('page' => 'buwd_backups'));
        }

    }

    public function is_valid($job_options)
    {
        if (empty($job_options['folderpath'])) {
            return false;
        }

        return true;
    }

    /**
     * Return an instance of this class.
     */
    public static function get_instance()
    {
        if (null == self::$instance) {
            self::$instance = new self;
        }

        return self::$instance;
    }
}