diff --git a/install.sh b/install.sh index 785ca28..e01e8cb 100644 --- a/install.sh +++ b/install.sh @@ -637,7 +637,15 @@ log "Fail2Ban configured" cat > /etc/sudoers.d/novacpx-firewall </dev/null"); + self::reloadFPM($oldVer); self::createPool($acct['username'], $newVer); @@ -100,10 +101,12 @@ php_value[max_execution_time] = 30 self::reloadFPM($acct['php_version']); $db->execute( - "INSERT INTO php_configs (account_id, php_version, memory_limit, max_execution_time, upload_max_filesize, post_max_size) - VALUES (?,?,?,?,?,?) - ON DUPLICATE KEY UPDATE memory_limit=VALUES(memory_limit), max_execution_time=VALUES(max_execution_time), - upload_max_filesize=VALUES(upload_max_filesize), post_max_size=VALUES(post_max_size), updated_at=NOW()", + "INSERT INTO php_configs (account_id, php_version, memory_limit, max_execution_time, upload_max_filesize, post_max_size, updated_at) + VALUES (?,?,?,?,?,?,datetime('now')) + ON CONFLICT(account_id) DO UPDATE SET php_version=excluded.php_version, + memory_limit=excluded.memory_limit, max_execution_time=excluded.max_execution_time, + upload_max_filesize=excluded.upload_max_filesize, post_max_size=excluded.post_max_size, + updated_at=excluded.updated_at", [$accountId, $acct['php_version'], $cfg['memory_limit'] ?? '256M', $cfg['max_execution_time'] ?? 30, $cfg['upload_max_filesize'] ?? '64M', $cfg['post_max_size'] ?? '64M'] ); diff --git a/panel/lib/WordPressManager.php b/panel/lib/WordPressManager.php index 76ee4e7..ec885d2 100644 --- a/panel/lib/WordPressManager.php +++ b/panel/lib/WordPressManager.php @@ -111,7 +111,7 @@ class WordPressManager { $stagingRoot = dirname($docRoot) . rtrim($stagingPath, '/'); // Copy files - $this->exec("cp -r {$docRoot} {$stagingRoot}"); + $this->exec("cp -r " . escapeshellarg($docRoot) . " " . escapeshellarg($stagingRoot)); // Clone DB $stagingDb = $install['db_name'] . '_staging'; @@ -119,7 +119,7 @@ class WordPressManager { $this->getProvDb()->exec("CREATE DATABASE IF NOT EXISTS `{$stagingDb}`"); $this->getProvDb()->exec("CREATE USER IF NOT EXISTS '{$stagingDb}'@'localhost' IDENTIFIED BY '{$stagingDbPw}'"); $this->getProvDb()->exec("GRANT ALL ON `{$stagingDb}`.* TO '{$stagingDb}'@'localhost'"); - $this->exec("mysqldump {$install['db_name']} | mysql {$stagingDb}"); + $this->exec("mysqldump " . escapeshellarg($install['db_name']) . " | mysql " . escapeshellarg($stagingDb)); // Update staging wp-config $this->wp($stagingRoot, "config set DB_NAME {$stagingDb}", $sysUser); @@ -141,10 +141,11 @@ class WordPressManager { // ── Delete ──────────────────────────────────────────────────────────────── public function delete(int $id): bool { [$install, $sysUser, $docRoot] = $this->resolve($id); - $this->exec("rm -rf {$docRoot}"); + // Remove DB record first so a failed filesystem cleanup doesn't leave a phantom record + $this->db->prepare("DELETE FROM wordpress_installs WHERE id=?")->execute([$id]); + $this->exec("rm -rf " . escapeshellarg($docRoot)); $this->getProvDb()->exec("DROP DATABASE IF EXISTS `{$install['db_name']}`"); $this->getProvDb()->exec("DROP USER IF EXISTS '{$install['db_user']}'@'localhost'"); - $this->db->prepare("DELETE FROM wordpress_installs WHERE id=?")->execute([$id]); return true; } @@ -245,7 +246,12 @@ class WordPressManager { private function ensureWpCli(): void { if (!file_exists($this->wpcli)) { - file_put_contents('/tmp/wp-cli.phar', file_get_contents('https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar')); + $ctx = stream_context_create(['http' => ['timeout' => 30]]); + $data = @file_get_contents('https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar', false, $ctx); + if (!$data || strlen($data) < 100000) { + throw new \RuntimeException("Failed to download WP-CLI (received " . strlen((string)$data) . " bytes)"); + } + file_put_contents('/tmp/wp-cli.phar', $data); rename('/tmp/wp-cli.phar', $this->wpcli); chmod($this->wpcli, 0755); }