// Copyright (C) 2025, The Duplicati Team // https://duplicati.com, hello@duplicati.com // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. #nullable enable using System; using System.Linq; namespace Duplicati.Library.AutoUpdater; /// /// The different kinds of releases supported /// public enum ReleaseType { /// /// Placeholder for unknown release types /// Unknown, /// /// A stable release /// Stable, /// /// A beta release /// Beta, /// /// An experimental release /// Experimental, /// /// A canary release /// Canary, /// /// A nightly release /// Nightly, /// /// A debug release /// Debug } /// /// The severity of an update /// public enum UpdateSeverity { /// /// No severity specified /// None, /// /// A low severity update /// Low, /// /// A normal severity update /// Normal, /// /// A high severity update /// High, /// /// A critical severity update /// Critical } /// /// Information about an update package /// /// The minimum version required to read this update /// The URL to present to the user for updating, if this client is too old /// Name of the update package /// Version of the update package /// The timestamp when the update was released /// The release update type /// The severity of the update /// The changelog text for this entry /// The version of the package structure /// List of installer packages /// Link to a generic download page public record UpdateInfo( int MinimumCompatibleVersion, string? IncompatibleUpdateUrl, string? Displayname, string? Version, DateTime ReleaseTime, string? ReleaseType, string? UpdateSeverity, string? ChangeInfo, int PackageUpdaterVersion, PackageEntry[]? Packages, string GenericUpdatePageUrl ) { /// /// Finds a package that matches the /// /// The package type id; null uses the currently installed package type id /// The matching package or null public PackageEntry? FindPackage(string? packageTypeId = null) { if (MinimumCompatibleVersion > UpdaterManager.SUPPORTED_PACKAGE_UPDATER_VERSION) return null; packageTypeId ??= UpdaterManager.PackageTypeId; if (string.IsNullOrWhiteSpace(packageTypeId) || Packages == null) return null; return Packages.FirstOrDefault(x => string.Equals(x.PackageTypeId, packageTypeId, StringComparison.OrdinalIgnoreCase)); } /// /// Gets the generic update page url for the /// /// The package type id; null uses the currently installed package type id /// The generic update page url public string GetGenericUpdatePageUrl(string? packageTypeId = null) { var baseurl = GenericUpdatePageUrl ?? string.Empty; if (MinimumCompatibleVersion > UpdaterManager.SUPPORTED_PACKAGE_UPDATER_VERSION && !string.IsNullOrWhiteSpace(IncompatibleUpdateUrl)) baseurl = IncompatibleUpdateUrl; packageTypeId ??= UpdaterManager.PackageTypeId; if (string.IsNullOrWhiteSpace(packageTypeId)) return baseurl; return baseurl + $"{(baseurl.IndexOf('?') > 0 ? "&" : "?")}packagetypeid={Uri.EscapeDataString(packageTypeId ?? "")}"; } /// /// Gets the updated package urls for the /// /// The package type id; null uses the currently installed package type id /// The matching update urls public string[] GetUpdateUrls(string? packageTypeId = null) { packageTypeId ??= UpdaterManager.PackageTypeId; var package = FindPackage(packageTypeId); if (package != null) return package.RemoteUrls; var generic = GetGenericUpdatePageUrl(packageTypeId); if (!string.IsNullOrWhiteSpace(generic)) return [generic]; return []; } }