module_fn('pi_control', 'table', $name); $assets = app()->assets(); if ($assets) { $assets->addStyle('/module/pi_control/asset?file=pi_control.css'); $assets->addScript('/module/pi_control/asset?file=hosts.js', 'footer', true); } $notice = null; $error = null; if ($_SERVER['REQUEST_METHOD'] === 'POST') { require_admin(); $deleteId = (int)($_POST['delete_id'] ?? 0); $editId = (int)($_POST['id'] ?? 0); $name = trim((string)($_POST['name'] ?? '')); $host = trim((string)($_POST['host'] ?? '')); $port = (int)($_POST['port'] ?? 22); $username = trim((string)($_POST['username'] ?? '')); $authType = trim((string)($_POST['auth_type'] ?? 'key')); $keyPath = trim((string)($_POST['key_path'] ?? '')); $password = trim((string)($_POST['password'] ?? '')); $imageUrl = trim((string)($_POST['image_url'] ?? '')); if ($deleteId > 0) { $stmt = $pdo->prepare('DELETE FROM ' . $table('hosts') . ' WHERE id = :id'); $stmt->execute(['id' => $deleteId]); $notice = 'Host gelöscht.'; } else { if ($name === '' || $host === '' || $username === '') { $error = 'Bitte Name, Host und Benutzer angeben.'; } else { if ($editId > 0) { $stmt = $pdo->prepare('SELECT * FROM ' . $table('hosts') . ' WHERE id = :id LIMIT 1'); $stmt->execute(['id' => $editId]); $existing = $stmt->fetch(PDO::FETCH_ASSOC) ?: []; $passwordToStore = $password !== '' ? $password : ($existing['password'] ?? null); $stmt = $pdo->prepare( 'UPDATE ' . $table('hosts') . ' SET name = :name, host = :host, port = :port, username = :username, auth_type = :auth_type, key_path = :key_path, password = :password, image_url = :image_url WHERE id = :id' ); $stmt->execute([ 'id' => $editId, 'name' => $name, 'host' => $host, 'port' => $port > 0 ? $port : 22, 'username' => $username, 'auth_type' => $authType !== '' ? $authType : 'key', 'key_path' => $keyPath !== '' ? $keyPath : null, 'password' => $passwordToStore, 'image_url' => $imageUrl !== '' ? $imageUrl : null, ]); $notice = 'Host aktualisiert.'; } else { $stmt = $pdo->prepare( 'INSERT INTO ' . $table('hosts') . ' (name, host, port, username, auth_type, key_path, password, image_url) VALUES (:name, :host, :port, :username, :auth_type, :key_path, :password, :image_url)' ); $stmt->execute([ 'name' => $name, 'host' => $host, 'port' => $port > 0 ? $port : 22, 'username' => $username, 'auth_type' => $authType !== '' ? $authType : 'key', 'key_path' => $keyPath !== '' ? $keyPath : null, 'password' => $password !== '' ? $password : null, 'image_url' => $imageUrl !== '' ? $imageUrl : null, ]); $notice = 'Host gespeichert.'; } } } } $hosts = $pdo->query('SELECT * FROM ' . $table('hosts') . ' ORDER BY id DESC')->fetchAll(PDO::FETCH_ASSOC); $settings = modules()->settings('pi_control'); $strictHostKey = !empty($settings['terminal_strict_hostkey']); function hostReachable(string $host, int $port): bool { $errno = 0; $errstr = ''; $fp = @fsockopen($host, $port, $errno, $errstr, 1.2); if ($fp) { fclose($fp); return true; } return false; } function runSshCommand(string $cmd, int $timeoutSec): int { $descriptors = [ 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ]; $process = proc_open($cmd, $descriptors, $pipes); if (!is_resource($process)) { return 255; } stream_set_blocking($pipes[1], false); stream_set_blocking($pipes[2], false); $start = time(); while (true) { $status = proc_get_status($process); if (!$status['running']) { $code = (int)$status['exitcode']; proc_close($process); return $code; } if (time() - $start > $timeoutSec) { proc_terminate($process, 9); proc_close($process); return 124; } usleep(100000); } } function hostAuthOk(array $host, bool $strictHostKey): bool { $hostAddr = (string)($host['host'] ?? ''); $user = (string)($host['username'] ?? ''); $port = (int)($host['port'] ?? 22); $authType = (string)($host['auth_type'] ?? 'key'); $keyPath = (string)($host['key_path'] ?? ''); $password = (string)($host['password'] ?? ''); if ($hostAddr === '' || $user === '') { return false; } $opts = $strictHostKey ? '-o StrictHostKeyChecking=accept-new -o UserKnownHostsFile=/root/.ssh/known_hosts' : '-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'; $opts .= ' -o ConnectTimeout=2 -o NumberOfPasswordPrompts=1'; $target = escapeshellarg($user . '@' . $hostAddr); $cmd = 'ssh ' . $opts . ' -p ' . (int)$port . ' '; if ($authType === 'key' && $keyPath !== '') { $cmd .= '-i ' . escapeshellarg($keyPath) . ' -o BatchMode=yes '; } elseif ($authType === 'key') { $cmd .= '-o BatchMode=yes '; } $cmd .= $target . ' -- true'; if ($authType === 'pass') { if ($password === '') { return false; } $cmd = 'sshpass -p ' . escapeshellarg($password) . ' ' . $cmd; } $exitCode = runSshCommand($cmd, 3); return $exitCode === 0; } ?>
Pi Control

Hosts

Verwalte die Raspberry Pis, die du steuern möchtest.

Neuer Host
Registrierte Hosts
Keine Hosts vorhanden.
>
:
·