.zip und deskhub-.zip.sig */ /** Wird für Updates eine Herausgeber-Signatur verlangt? Ja, sobald ein Herausgeber-Schlüssel eingebaut ist. */ function update_signature_required(): bool { return function_exists('plugin_publisher_key') && plugin_publisher_key() !== ''; } /** Zu signierende Nachricht: bindet Signatur an Version und Dateiinhalt. */ function update_signature_message(string $tag, string $sha256): string { return "deskhub-update\n" . ltrim(trim($tag), 'vV') . "\n" . strtolower($sha256); } /** Prüft die Signatur eines heruntergeladenen Pakets. Gibt null bei Erfolg zurück, sonst eine Fehlermeldung. */ function update_verify_package(string $tag, string $zipPath, string $signature): ?string { $signature = trim($signature); if ($signature === '') return 'Dem Release fehlt die Signatur des Herausgebers.'; $key = plugin_publisher_key(); if ($key === '') return 'Es ist kein Herausgeber-Schlüssel hinterlegt, die Signatur kann nicht geprüft werden.'; $sha = hash_file('sha256', $zipPath); if ($sha === false) return 'Das Paket konnte nicht gelesen werden.'; if (!plugin_verify_signature(update_signature_message($tag, $sha), $signature, $key)) { return 'Die Signatur ist ungültig. Das Paket wurde verändert oder stammt nicht vom Herausgeber. Es wird nicht installiert.'; } return null; } /** * Sucht in den Anhängen eines Releases (Gitea-API) das Paket und die Signatur. * * @return array{zip: ?string, sig: ?string} Download-Adressen oder null */ function update_find_assets(array $release, string $tag): array { $version = ltrim(trim($tag), 'vV'); $names = ['zip' => "deskhub-{$version}.zip", 'sig' => "deskhub-{$version}.zip.sig"]; $out = ['zip' => null, 'sig' => null]; foreach ((array) ($release['assets'] ?? []) as $asset) { $name = (string) ($asset['name'] ?? ''); $url = (string) ($asset['browser_download_url'] ?? ''); foreach ($names as $kind => $expected) { if ($name === $expected && str_starts_with($url, 'https://')) $out[$kind] = $url; } } return $out; } /** * Zugangstoken für den Update-Server (nur nötig, wenn das Repository privat ist; Gitea antwortet sonst mit "404"). * Quelle: config/config.php ('update' => ['token' => '…']) hat Vorrang, sonst das in den Einstellungen der Update-Seite * gespeicherte (verschlüsselt). Gibt [Token, Quelle] zurück, Quelle 'config', 'einstellungen' oder ''. * * @return array{0: string, 1: string} */ function update_token_info(): array { $fromConfig = trim((string) (config()['update']['token'] ?? '')); if ($fromConfig !== '') return [$fromConfig, 'config']; $stored = (string) get_setting('update_token', ''); $fromSettings = $stored !== '' ? trim(decrypt_secret($stored)) : ''; return $fromSettings !== '' ? [$fromSettings, 'einstellungen'] : ['', '']; } /** Kopfzeilen für Abrufe beim Update-Server; ein Zugangstoken ist nur nötig, wenn das Repository nicht öffentlich ist. */ function update_http_headers(): array { [$token] = update_token_info(); return $token !== '' ? ['Authorization: token ' . $token] : []; }