ip, $server->ssh_port ?: 22); $this->verifyHostKey($sftp, $server); $login = $this->vault->resolve($server); if (! $sftp->login($login['username'], $login['secret'])) { throw new RuntimeException("SFTP-Login auf {$server->name} fehlgeschlagen."); } $this->sftp = $sftp; return $this; } /** * @return array */ public function list(string $path = '.'): array { $raw = $this->client()->rawlist($path) ?: []; $entries = []; foreach ($raw as $name => $info) { if ($name === '.' || $name === '..') { continue; } $entries[] = [ 'name' => (string) $name, 'type' => ($info['type'] ?? null) === SftpProtocol::TYPE_DIRECTORY ? 'dir' : 'file', 'size' => (int) ($info['size'] ?? 0), 'permissions' => isset($info['permissions']) ? substr(sprintf('%o', $info['permissions']), -4) : '', 'mtime' => (int) ($info['mtime'] ?? 0), ]; } return $entries; } public function get(string $remote): string { return (string) $this->client()->get($remote); } public function put(string $remote, string $contents): bool { return $this->client()->put($remote, $contents); } public function delete(string $remote): bool { return $this->client()->delete($remote); } public function putFromFile(string $remote, string $localPath): bool { return $this->client()->put($remote, $localPath, SftpProtocol::SOURCE_LOCAL_FILE); } public function size(string $remote): int { return (int) ($this->client()->filesize($remote) ?: 0); } public function disconnect(): void { $this->sftp?->disconnect(); $this->sftp = null; } private function client(): SftpProtocol { return $this->sftp ?? throw new RuntimeException('Nicht verbunden — connect() zuerst aufrufen.'); } }