$_SESSION['user_id'], 'username' => $_SESSION['username'], 'role' => $_SESSION['role'], ]; } function isAdmin() { $user = getCurrentUser(); return $user && $user['role'] === 'admin'; } function requireLogin($action) { $publicActions = ['login']; if (!in_array($action, $publicActions, true) && !isset($_SESSION['user_id'])) { header('Location: ?action=login'); exit; } } // ---------- Misc helpers ---------- function generatePassword($length = 16) { $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*'; $pass = ''; $max = strlen($chars) - 1; for ($i = 0; $i < $length; $i++) { $pass .= $chars[random_int(0, $max)]; } return $pass; } // ---------- CLI Helpers ---------- function stripAnsi($str) { // Remove ANSI escape sequences like \e[94m ... \e[0m return preg_replace('/\x1B\[[0-9;]*[A-Za-z]/', '', $str); } function runCommand($cmd, &$output = null, &$status = null) { $output = []; exec($cmd . ' 2>&1', $output, $status); // Strip ANSI codes from each line foreach ($output as &$line) { $line = stripAnsi($line); } return $status === 0; } function runCommandStreaming($cmd, callable $onLine) { $descriptorspec = [ 0 => ['pipe', 'r'], // stdin 1 => ['pipe', 'w'], // stdout 2 => ['pipe', 'w'], // stderr ]; $process = proc_open($cmd . ' 2>&1', $descriptorspec, $pipes); if (!is_resource($process)) { return [false, ['Failed to start process']]; } // We don't need stdin fclose($pipes[0]); stream_set_blocking($pipes[1], false); stream_set_blocking($pipes[2], false); $allLines = []; while (true) { $status = proc_get_status($process); $out = fgets($pipes[1]); $err = fgets($pipes[2]); foreach ([$out, $err] as $chunk) { if ($chunk !== false && $chunk !== '') { $chunk = stripAnsi($chunk); $lines = preg_split("/\r\n|\n|\r/", $chunk); foreach ($lines as $line) { if ($line === '') { continue; } $allLines[] = $line; $onLine($line); } @ob_flush(); @flush(); } } if (!$status['running']) { break; } usleep(50000); // 50ms } fclose($pipes[1]); fclose($pipes[2]); $exitCode = proc_close($process); return [$exitCode === 0, $allLines]; } function sanitizeDomain($domain) { $domain = trim($domain); if ($domain === '') { return null; } // Allow letters, numbers, dots, and dashes if (!preg_match('/^[a-zA-Z0-9.-]+$/', $domain)) { return null; } return $domain; }