<?php

require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skin.php';
require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader-skin.php';
require_once ABSPATH . 'wp-admin/includes/class-theme-upgrader-skin.php';
require_once ABSPATH . 'wp-admin/includes/class-bulk-upgrader-skin.php';
require_once ABSPATH . 'wp-admin/includes/class-bulk-plugin-upgrader-skin.php';
require_once ABSPATH . 'wp-admin/includes/class-bulk-theme-upgrader-skin.php';
require_once ABSPATH . 'wp-admin/includes/class-plugin-installer-skin.php';
require_once ABSPATH . 'wp-admin/includes/class-theme-installer-skin.php';
require_once ABSPATH . 'wp-admin/includes/class-language-pack-upgrader-skin.php';
require_once ABSPATH . 'wp-admin/includes/class-automatic-upgrader-skin.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-ajax-upgrader-skin.php';
class WP_Upgrader
{
    public $strings = array();
    public $skin = null;
    public $result = array();
    public $update_count = 0;
    public $update_current = 0;
    public function __construct($skin = null)
    {
        if (null == $skin) {
            $this->skin = new WP_Upgrader_Skin();
        } else {
            $this->skin = $skin;
        }
    }
    public function init()
    {
        $this->skin->set_upgrader($this);
        $this->generic_strings();
    }
    public function generic_strings()
    {
        $this->strings['bad_request'] = __('Invalid data provided.');
        $this->strings['fs_unavailable'] = __('Could not access filesystem.');
        $this->strings['fs_error'] = __('Filesystem error.');
        $this->strings['fs_no_root_dir'] = __('Unable to locate WordPress root directory.');
        $this->strings['fs_no_content_dir'] = __('Unable to locate WordPress content directory (wp-content).');
        $this->strings['fs_no_plugins_dir'] = __('Unable to locate WordPress plugin directory.');
        $this->strings['fs_no_themes_dir'] = __('Unable to locate WordPress theme directory.');
        $this->strings['fs_no_folder'] = __('Unable to locate needed folder (%s).');
        $this->strings['download_failed'] = __('Download failed.');
        $this->strings['installing_package'] = __('Installing the latest version&#8230;');
        $this->strings['no_files'] = __('The package contains no files.');
        $this->strings['folder_exists'] = __('Destination folder already exists.');
        $this->strings['mkdir_failed'] = __('Could not create directory.');
        $this->strings['incompatible_archive'] = __('The package could not be installed.');
        $this->strings['files_not_writable'] = __('The update cannot be installed because we will be unable to copy some files. This is usually due to inconsistent file permissions.');
        $this->strings['maintenance_start'] = __('Enabling Maintenance mode&#8230;');
        $this->strings['maintenance_end'] = __('Disabling Maintenance mode&#8230;');
    }
    public function fs_connect($directories = array(), $allow_relaxed_file_ownership = false)
    {
        global $wp_filesystem;
        $credentials = $this->skin->request_filesystem_credentials(false, $directories[0], $allow_relaxed_file_ownership);
        if (false === $credentials) {
            return false;
        }
        if (!WP_Filesystem($credentials, $directories[0], $allow_relaxed_file_ownership)) {
            $error = true;
            if (is_object($wp_filesystem) && $wp_filesystem->errors->has_errors()) {
                $error = $wp_filesystem->errors;
            }
            $this->skin->request_filesystem_credentials($error, $directories[0], $allow_relaxed_file_ownership);
            return false;
        }
        if (!is_object($wp_filesystem)) {
            return new WP_Error('fs_unavailable', $this->strings['fs_unavailable']);
        }
        if (is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->has_errors()) {
            return new WP_Error('fs_error', $this->strings['fs_error'], $wp_filesystem->errors);
        }
        foreach ((array) $directories as $dir) {
            switch ($dir) {
                case ABSPATH:
                    if (!$wp_filesystem->abspath()) {
                        return new WP_Error('fs_no_root_dir', $this->strings['fs_no_root_dir']);
                    }
                    break;
                case WP_CONTENT_DIR:
                    if (!$wp_filesystem->wp_content_dir()) {
                        return new WP_Error('fs_no_content_dir', $this->strings['fs_no_content_dir']);
                    }
                    break;
                case WP_PLUGIN_DIR:
                    if (!$wp_filesystem->wp_plugins_dir()) {
                        return new WP_Error('fs_no_plugins_dir', $this->strings['fs_no_plugins_dir']);
                    }
                    break;
                case get_theme_root():
                    if (!$wp_filesystem->wp_themes_dir()) {
                        return new WP_Error('fs_no_themes_dir', $this->strings['fs_no_themes_dir']);
                    }
                    break;
                default:
                    if (!$wp_filesystem->find_folder($dir)) {
                        return new WP_Error('fs_no_folder', sprintf($this->strings['fs_no_folder'], esc_html(basename($dir))));
                    }
                    break;
            }
        }
        return true;
    }
    public function download_package($package, $check_signatures = false, $hook_extra = array())
    {
        $reply = apply_filters('upgrader_pre_download', false, $package, $this, $hook_extra);
        if (false !== $reply) {
            return $reply;
        }
        if (!preg_match('!^(http|https|ftp)://!i', $package) && file_exists($package)) {
            return $package;
        }
        if (empty($package)) {
            return new WP_Error('no_package', $this->strings['no_package']);
        }
        $this->skin->feedback('downloading_package', $package);
        $download_file = download_url($package, 300, $check_signatures);
        if (is_wp_error($download_file) && !$download_file->get_error_data('softfail-filename')) {
            return new WP_Error('download_failed', $this->strings['download_failed'], $download_file->get_error_message());
        }
        return $download_file;
    }
    public function unpack_package($package, $delete_package = true)
    {
        global $wp_filesystem;
        $this->skin->feedback('unpack_package');
        $upgrade_folder = $wp_filesystem->wp_content_dir() . 'upgrade/';
        $upgrade_files = $wp_filesystem->dirlist($upgrade_folder);
        if (!empty($upgrade_files)) {
            foreach ($upgrade_files as $file) {
                $wp_filesystem->delete($upgrade_folder . $file['name'], true);
            }
        }
        $working_dir = $upgrade_folder . basename(basename($package, '.tmp'), '.zip');
        if ($wp_filesystem->is_dir($working_dir)) {
            $wp_filesystem->delete($working_dir, true);
        }
        $result = unzip_file($package, $working_dir);
        if ($delete_package) {
            unlink($package);
        }
        if (is_wp_error($result)) {
            $wp_filesystem->delete($working_dir, true);
            if ('incompatible_archive' === $result->get_error_code()) {
                return new WP_Error('incompatible_archive', $this->strings['incompatible_archive'], $result->get_error_data());
            }
            return $result;
        }
        return $working_dir;
    }
    protected function flatten_dirlist($nested_files, $path = '')
    {
        $files = array();
        foreach ($nested_files as $name => $details) {
            $files[$path . $name] = $details;
            if (!empty($details['files'])) {
                $children = $this->flatten_dirlist($details['files'], $path . $name . '/');
                $files = $files + $children;
            }
        }
        return $files;
    }
    public function clear_destination($remote_destination)
    {
        global $wp_filesystem;
        $files = $wp_filesystem->dirlist($remote_destination, true, true);
        if (false === $files) {
            return true;
        }
        $files = $this->flatten_dirlist($files);
        $unwritable_files = array();
        foreach ($files as $filename => $file_details) {
            if (!$wp_filesystem->is_writable($remote_destination . $filename)) {
                $wp_filesystem->chmod($remote_destination . $filename, 'd' === $file_details['type'] ? FS_CHMOD_DIR : FS_CHMOD_FILE);
                if (!$wp_filesystem->is_writable($remote_destination . $filename)) {
                    $unwritable_files[] = $filename;
                }
            }
        }
        if (!empty($unwritable_files)) {
            return new WP_Error('files_not_writable', $this->strings['files_not_writable'], implode(', ', $unwritable_files));
        }
        if (!$wp_filesystem->delete($remote_destination, true)) {
            return new WP_Error('remove_old_failed', $this->strings['remove_old_failed']);
        }
        return true;
    }
    public function install_package($args = array())
    {
        global $wp_filesystem, $wp_theme_directories;
        $defaults = array('source' => '', 'destination' => '', 'clear_destination' => false, 'clear_working' => false, 'abort_if_destination_exists' => true, 'hook_extra' => array());
        $args = wp_parse_args($args, $defaults);
        $source = $args['source'];
        $destination = $args['destination'];
        $clear_destination = $args['clear_destination'];
        set_time_limit(300);
        if (empty($source) || empty($destination)) {
            return new WP_Error('bad_request', $this->strings['bad_request']);
        }
        $this->skin->feedback('installing_package');
        $res = apply_filters('upgrader_pre_install', true, $args['hook_extra']);
        if (is_wp_error($res)) {
            return $res;
        }
        $remote_source = $args['source'];
        $local_destination = $destination;
        $source_files = array_keys($wp_filesystem->dirlist($remote_source));
        $remote_destination = $wp_filesystem->find_folder($local_destination);
        if (1 === count($source_files) && $wp_filesystem->is_dir(trailingslashit($args['source']) . $source_files[0] . '/')) {
            $source = trailingslashit($args['source']) . trailingslashit($source_files[0]);
        } elseif (count($source_files) == 0) {
            return new WP_Error('incompatible_archive_empty', $this->strings['incompatible_archive'], $this->strings['no_files']);
        } else {
            $source = trailingslashit($args['source']);
        }
        $source = apply_filters('upgrader_source_selection', $source, $remote_source, $this, $args['hook_extra']);
        if (is_wp_error($source)) {
            return $source;
        }
        if ($source !== $remote_source) {
            $source_files = array_keys($wp_filesystem->dirlist($source));
        }
        $protected_directories = array(ABSPATH, WP_CONTENT_DIR, WP_PLUGIN_DIR, WP_CONTENT_DIR . '/themes');
        if (is_array($wp_theme_directories)) {
            $protected_directories = array_merge($protected_directories, $wp_theme_directories);
        }
        if (in_array($destination, $protected_directories, true)) {
            $remote_destination = trailingslashit($remote_destination) . trailingslashit(basename($source));
            $destination = trailingslashit($destination) . trailingslashit(basename($source));
        }
        if ($clear_destination) {
            $this->skin->feedback('remove_old');
            $removed = $this->clear_destination($remote_destination);
            $removed = apply_filters('upgrader_clear_destination', $removed, $local_destination, $remote_destination, $args['hook_extra']);
            if (is_wp_error($removed)) {
                return $removed;
            }
        } elseif ($args['abort_if_destination_exists'] && $wp_filesystem->exists($remote_destination)) {
            $_files = $wp_filesystem->dirlist($remote_destination);
            if (!empty($_files)) {
                $wp_filesystem->delete($remote_source, true);
                return new WP_Error('folder_exists', $this->strings['folder_exists'], $remote_destination);
            }
        }
        if (!$wp_filesystem->exists($remote_destination)) {
            if (!$wp_filesystem->mkdir($remote_destination, FS_CHMOD_DIR)) {
                return new WP_Error('mkdir_failed_destination', $this->strings['mkdir_failed'], $remote_destination);
            }
        }
        $result = copy_dir($source, $remote_destination);
        if (is_wp_error($result)) {
            if ($args['clear_working']) {
                $wp_filesystem->delete($remote_source, true);
            }
            return $result;
        }
        if ($args['clear_working']) {
            $wp_filesystem->delete($remote_source, true);
        }
        $destination_name = basename(str_replace($local_destination, '', $destination));
        if ('.' === $destination_name) {
            $destination_name = '';
        }
        $this->result = compact('source', 'source_files', 'destination', 'destination_name', 'local_destination', 'remote_destination', 'clear_destination');
        $res = apply_filters('upgrader_post_install', true, $args['hook_extra'], $this->result);
        if (is_wp_error($res)) {
            $this->result = $res;
            return $res;
        }
        return $this->result;
    }
    public function run($options)
    {
        $defaults = array('package' => '', 'destination' => '', 'clear_destination' => false, 'abort_if_destination_exists' => true, 'clear_working' => true, 'is_multi' => false, 'hook_extra' => array());
        $options = wp_parse_args($options, $defaults);
        $options = apply_filters('upgrader_package_options', $options);
        if (!$options['is_multi']) {
            $this->skin->header();
        }
        $res = $this->fs_connect(array(WP_CONTENT_DIR, $options['destination']));
        if (!$res) {
            if (!$options['is_multi']) {
                $this->skin->footer();
            }
            return false;
        }
        $this->skin->before();
        if (is_wp_error($res)) {
            $this->skin->error($res);
            $this->skin->after();
            if (!$options['is_multi']) {
                $this->skin->footer();
            }
            return $res;
        }
        $download = $this->download_package($options['package'], true, $options['hook_extra']);
        if (is_wp_error($download) && $download->get_error_data('softfail-filename')) {
            if ('signature_verification_no_signature' !== $download->get_error_code() || WP_DEBUG) {
                $this->skin->feedback($download->get_error_message());
                wp_version_check(array('signature_failure_code' => $download->get_error_code(), 'signature_failure_data' => $download->get_error_data()));
            }
            $download = $download->get_error_data('softfail-filename');
        }
        if (is_wp_error($download)) {
            $this->skin->error($download);
            $this->skin->after();
            if (!$options['is_multi']) {
                $this->skin->footer();
            }
            return $download;
        }
        $delete_package = $download != $options['package'];
        $working_dir = $this->unpack_package($download, $delete_package);
        if (is_wp_error($working_dir)) {
            $this->skin->error($working_dir);
            $this->skin->after();
            if (!$options['is_multi']) {
                $this->skin->footer();
            }
            return $working_dir;
        }
        $result = $this->install_package(array('source' => $working_dir, 'destination' => $options['destination'], 'clear_destination' => $options['clear_destination'], 'abort_if_destination_exists' => $options['abort_if_destination_exists'], 'clear_working' => $options['clear_working'], 'hook_extra' => $options['hook_extra']));
        $result = apply_filters('upgrader_install_package_result', $result, $options['hook_extra']);
        $this->skin->set_result($result);
        if (is_wp_error($result)) {
            $this->skin->error($result);
            if (!method_exists($this->skin, 'hide_process_failed') || !$this->skin->hide_process_failed($result)) {
                $this->skin->feedback('process_failed');
            }
        } else {
            $this->skin->feedback('process_success');
        }
        $this->skin->after();
        if (!$options['is_multi']) {
            do_action('upgrader_process_complete', $this, $options['hook_extra']);
            $this->skin->footer();
        }
        return $result;
    }
    public function maintenance_mode($enable = false)
    {
        global $wp_filesystem;
        $file = $wp_filesystem->abspath() . '.maintenance';
        if ($enable) {
            $this->skin->feedback('maintenance_start');
            $maintenance_string = '<?php $upgrading = ' . time() . '; ?>';
            $wp_filesystem->delete($file);
            $wp_filesystem->put_contents($file, $maintenance_string, FS_CHMOD_FILE);
        } elseif (!$enable && $wp_filesystem->exists($file)) {
            $this->skin->feedback('maintenance_end');
            $wp_filesystem->delete($file);
        }
    }
    public static function create_lock($lock_name, $release_timeout = null)
    {
        global $wpdb;
        if (!$release_timeout) {
            $release_timeout = HOUR_IN_SECONDS;
        }
        $lock_option = $lock_name . '.lock';
        $lock_result = $wpdb->query($wpdb->prepare("INSERT IGNORE INTO `{$wpdb->options}` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'no') /* LOCK */", $lock_option, time()));
        if (!$lock_result) {
            $lock_result = get_option($lock_option);
            if (!$lock_result) {
                return false;
            }
            if ($lock_result > time() - $release_timeout) {
                return false;
            }
            WP_Upgrader::release_lock($lock_name);
            return WP_Upgrader::create_lock($lock_name, $release_timeout);
        }
        update_option($lock_option, time());
        return true;
    }
    public static function release_lock($lock_name)
    {
        return delete_option($lock_name . '.lock');
    }
}
require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
require_once ABSPATH . 'wp-admin/includes/class-theme-upgrader.php';
require_once ABSPATH . 'wp-admin/includes/class-language-pack-upgrader.php';
require_once ABSPATH . 'wp-admin/includes/class-core-upgrader.php';
require_once ABSPATH . 'wp-admin/includes/class-file-upload-upgrader.php';
require_once ABSPATH . 'wp-admin/includes/class-wp-automatic-updater.php';