diff --git a/.nuget/NuGet.Config b/.nuget/NuGet.Config index 67f8ea04..3343d682 100644 --- a/.nuget/NuGet.Config +++ b/.nuget/NuGet.Config @@ -1,4 +1,5 @@  + diff --git a/.nuget/NuGet.targets b/.nuget/NuGet.targets index 3f8c37b2..6aba4a93 100644 --- a/.nuget/NuGet.targets +++ b/.nuget/NuGet.targets @@ -1,129 +1,134 @@ - + + - - $(MSBuildProjectDirectory)\..\ + + $(MSBuildProjectDirectory)\..\ - - false + + false - - false + + false - - true + + true - - false - + + false + - - - - + + - - - - - $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) - - - - - $(SolutionDir).nuget - - - - $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config - $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config - - - - $(MSBuildProjectDirectory)\packages.config - $(PackagesProjectConfig) - - - - - $(NuGetToolsPath)\NuGet.exe - @(PackageSource) - - "$(NuGetExePath)" - mono --runtime=v4.0.30319 "$(NuGetExePath)" - - $(TargetDir.Trim('\\')) - - -RequireConsent - -NonInteractive - - "$(SolutionDir) " - "$(SolutionDir)" - - - $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) - $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols - - - - RestorePackages; - $(BuildDependsOn); - - - - - $(BuildDependsOn); - BuildPackage; - - - - - - - + $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) + + + + + $(SolutionDir).nuget + + + + $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config + $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config + + + + $(MSBuildProjectDirectory)\packages.config + $(PackagesProjectConfig) + + + + + $(NuGetToolsPath)\NuGet.exe + @(PackageSource) + + "$(NuGetExePath)" + mono --runtime=v4.0.30319 "$(NuGetExePath)" + + $(TargetDir.Trim('\\')) + + -RequireConsent + -NonInteractive + + "$(SolutionDir) " + "$(SolutionDir)" + + + $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir) + $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols + + + + RestorePackages; + $(BuildDependsOn); + + + + + $(BuildDependsOn); + BuildPackage; + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + \ No newline at end of file diff --git a/nUpdate.Administration.TransferInterface/App.config b/nUpdate.Administration.TransferInterface/App.config index 74ade9db..0ac2de8f 100644 --- a/nUpdate.Administration.TransferInterface/App.config +++ b/nUpdate.Administration.TransferInterface/App.config @@ -1,6 +1,7 @@ - + + - - - - + + + + \ No newline at end of file diff --git a/nUpdate.Administration.TransferInterface/ITransferProvider.cs b/nUpdate.Administration.TransferInterface/ITransferProvider.cs index 8be0f277..e71f4435 100644 --- a/nUpdate.Administration.TransferInterface/ITransferProvider.cs +++ b/nUpdate.Administration.TransferInterface/ITransferProvider.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// ITransferProvider.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration.TransferInterface/Properties/AssemblyInfo.cs b/nUpdate.Administration.TransferInterface/Properties/AssemblyInfo.cs index db75b8e1..29cfc55b 100644 --- a/nUpdate.Administration.TransferInterface/Properties/AssemblyInfo.cs +++ b/nUpdate.Administration.TransferInterface/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// AssemblyInfo.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System.Reflection; using System.Runtime.InteropServices; diff --git a/nUpdate.Administration.TransferInterface/Properties/Settings.settings b/nUpdate.Administration.TransferInterface/Properties/Settings.settings index 39645652..e04fc631 100644 --- a/nUpdate.Administration.TransferInterface/Properties/Settings.settings +++ b/nUpdate.Administration.TransferInterface/Properties/Settings.settings @@ -1,7 +1,8 @@  + - + \ No newline at end of file diff --git a/nUpdate.Administration.TransferInterface/ServerItem.cs b/nUpdate.Administration.TransferInterface/ServerItem.cs index 77477789..6037af1d 100644 --- a/nUpdate.Administration.TransferInterface/ServerItem.cs +++ b/nUpdate.Administration.TransferInterface/ServerItem.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// ServerItem.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Administration.TransferInterface/ServerItemType.cs b/nUpdate.Administration.TransferInterface/ServerItemType.cs index 05e102a3..9c6130e6 100644 --- a/nUpdate.Administration.TransferInterface/ServerItemType.cs +++ b/nUpdate.Administration.TransferInterface/ServerItemType.cs @@ -1,4 +1,6 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// ServerItemType.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 + namespace nUpdate.Administration.TransferInterface { public enum ServerItemType diff --git a/nUpdate.Administration.TransferInterface/ServiceProviderAttribute.cs b/nUpdate.Administration.TransferInterface/ServiceProviderAttribute.cs index 983ddd85..c580121f 100644 --- a/nUpdate.Administration.TransferInterface/ServiceProviderAttribute.cs +++ b/nUpdate.Administration.TransferInterface/ServiceProviderAttribute.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// ServiceProviderAttribute.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System; @@ -17,7 +18,7 @@ public ServiceProviderAttribute(Type serviceType) { if (serviceType == null) throw new ArgumentNullException(nameof(serviceType)); - if (!typeof (IServiceProvider).IsAssignableFrom(serviceType)) + if (!typeof(IServiceProvider).IsAssignableFrom(serviceType)) throw new ArgumentException("Implementation of IServiceProvider is missing.", nameof(serviceType)); ServiceType = serviceType; } diff --git a/nUpdate.Administration.TransferInterface/TransferProgressEventArgs.cs b/nUpdate.Administration.TransferInterface/TransferProgressEventArgs.cs index f04369fb..be16e85a 100644 --- a/nUpdate.Administration.TransferInterface/TransferProgressEventArgs.cs +++ b/nUpdate.Administration.TransferInterface/TransferProgressEventArgs.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// TransferProgressEventArgs.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; @@ -6,7 +7,9 @@ namespace nUpdate.Administration.TransferInterface { public class TransferProgressEventArgs : EventArgs { - public TransferProgressEventArgs(int bytesTransferred, long totalBytesTransferred, int bytesPerSecond, int kilobytesPerSecond, int megabytesPerSecond, int gigabytesPerSecond, TimeSpan elapsedTime, int percentComplete, long transferSize, long bytesRemaining, TimeSpan timeRemaining) + public TransferProgressEventArgs(int bytesTransferred, long totalBytesTransferred, int bytesPerSecond, + int kilobytesPerSecond, int megabytesPerSecond, int gigabytesPerSecond, TimeSpan elapsedTime, + int percentComplete, long transferSize, long bytesRemaining, TimeSpan timeRemaining) { BytesTransferred = bytesTransferred; TotalBytesTransferred = totalBytesTransferred; diff --git a/nUpdate.Administration/App.config b/nUpdate.Administration/App.config index 4170727f..0a43f629 100644 --- a/nUpdate.Administration/App.config +++ b/nUpdate.Administration/App.config @@ -1,4 +1,5 @@  + @@ -60,10 +61,11 @@ - - + + - \ No newline at end of file + + \ No newline at end of file diff --git a/nUpdate.Administration/Core/AesManager.cs b/nUpdate.Administration/Core/AesManager.cs index 763eb213..9c1bb02f 100644 --- a/nUpdate.Administration/Core/AesManager.cs +++ b/nUpdate.Administration/Core/AesManager.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// AesManager.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.IO; diff --git a/nUpdate.Administration/Core/Application/Extension/AssociationManager.cs b/nUpdate.Administration/Core/Application/Extension/AssociationManager.cs index bca364e2..54d6793d 100644 --- a/nUpdate.Administration/Core/Application/Extension/AssociationManager.cs +++ b/nUpdate.Administration/Core/Application/Extension/AssociationManager.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// AssociationManager.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Collections.Generic; diff --git a/nUpdate.Administration/Core/Application/Extension/FileAssociationInfo.cs b/nUpdate.Administration/Core/Application/Extension/FileAssociationInfo.cs index d633aa71..446ee84e 100644 --- a/nUpdate.Administration/Core/Application/Extension/FileAssociationInfo.cs +++ b/nUpdate.Administration/Core/Application/Extension/FileAssociationInfo.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// FileAssociationInfo.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Linq; diff --git a/nUpdate.Administration/Core/Application/Extension/ProgramAssociationInfo.cs b/nUpdate.Administration/Core/Application/Extension/ProgramAssociationInfo.cs index 37d13ef6..92982b57 100644 --- a/nUpdate.Administration/Core/Application/Extension/ProgramAssociationInfo.cs +++ b/nUpdate.Administration/Core/Application/Extension/ProgramAssociationInfo.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ProgramAssociationInfo.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/Core/Application/Extension/ProgramIcon.cs b/nUpdate.Administration/Core/Application/Extension/ProgramIcon.cs index 2e478bab..64add893 100644 --- a/nUpdate.Administration/Core/Application/Extension/ProgramIcon.cs +++ b/nUpdate.Administration/Core/Application/Extension/ProgramIcon.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ProgramIcon.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Administration/Core/Application/Extension/ProgramVerb.cs b/nUpdate.Administration/Core/Application/Extension/ProgramVerb.cs index 6debb711..a44fb471 100644 --- a/nUpdate.Administration/Core/Application/Extension/ProgramVerb.cs +++ b/nUpdate.Administration/Core/Application/Extension/ProgramVerb.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ProgramVerb.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Administration.Core.Application.Extension { diff --git a/nUpdate.Administration/Core/Application/Extension/RegistryException.cs b/nUpdate.Administration/Core/Application/Extension/RegistryException.cs index 599bdd5f..dd634c45 100644 --- a/nUpdate.Administration/Core/Application/Extension/RegistryException.cs +++ b/nUpdate.Administration/Core/Application/Extension/RegistryException.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// RegistryException.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Administration/Core/Application/Extension/RegistryWrapper.cs b/nUpdate.Administration/Core/Application/Extension/RegistryWrapper.cs index fd8030b8..0335cdc1 100644 --- a/nUpdate.Administration/Core/Application/Extension/RegistryWrapper.cs +++ b/nUpdate.Administration/Core/Application/Extension/RegistryWrapper.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// RegistryWrapper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using Microsoft.Win32; diff --git a/nUpdate.Administration/Core/Application/Extension/ShellNotification.cs b/nUpdate.Administration/Core/Application/Extension/ShellNotification.cs index d00b1f43..735c7d44 100644 --- a/nUpdate.Administration/Core/Application/Extension/ShellNotification.cs +++ b/nUpdate.Administration/Core/Application/Extension/ShellNotification.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ShellNotification.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using nUpdate.Administration.Core.Win32; diff --git a/nUpdate.Administration/Core/Application/UpdatePackage.cs b/nUpdate.Administration/Core/Application/UpdatePackage.cs index 1d1f92d7..b8d53359 100644 --- a/nUpdate.Administration/Core/Application/UpdatePackage.cs +++ b/nUpdate.Administration/Core/Application/UpdatePackage.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdatePackage.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Administration/Core/Application/UpdateProject.cs b/nUpdate.Administration/Core/Application/UpdateProject.cs index 1d751468..97782d42 100644 --- a/nUpdate.Administration/Core/Application/UpdateProject.cs +++ b/nUpdate.Administration/Core/Application/UpdateProject.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdateProject.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -26,7 +27,7 @@ public class UpdateProject /// public string AssemblyVersionPath { get; set; } - public string ConfigVersion => "1b2"; + public string ConfigVersion { get; set; } = "v3"; /// /// The FTP-directory of the project. diff --git a/nUpdate.Administration/Core/CodeDomHelper.cs b/nUpdate.Administration/Core/CodeDomHelper.cs index 5c6f5939..91f0bc5d 100644 --- a/nUpdate.Administration/Core/CodeDomHelper.cs +++ b/nUpdate.Administration/Core/CodeDomHelper.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// CodeDomHelper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.CodeDom.Compiler; diff --git a/nUpdate.Administration/Core/Extensions.cs b/nUpdate.Administration/Core/Extensions.cs index 43fec12a..34dcb40d 100644 --- a/nUpdate.Administration/Core/Extensions.cs +++ b/nUpdate.Administration/Core/Extensions.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// Extensions.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/Core/Ftp/Service/FtpTransferService.cs b/nUpdate.Administration/Core/Ftp/Service/FtpTransferService.cs index 6f779e62..8d39ee18 100644 --- a/nUpdate.Administration/Core/Ftp/Service/FtpTransferService.cs +++ b/nUpdate.Administration/Core/Ftp/Service/FtpTransferService.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// FtpTransferService.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -55,6 +56,7 @@ public void DeleteDirectory(string directoryPath) DeleteFile(directoryPath, item.Name); break; } + ftp.DeleteDirectory(directoryPath); } } @@ -219,7 +221,8 @@ public void UploadPackage(string packagePath, string packageVersion) _packageFtpsClient.PutFileAsyncCompleted += UploadPackageFinished; _packageFtpsClient.Open(Username, Password.ConvertToInsecureString()); _packageFtpsClient.ChangeDirectoryMultiPath(Directory); - _packageFtpsClient.MakeDirectory(packageVersion); + if (!_packageFtpsClient.Exists(packageVersion)) + _packageFtpsClient.MakeDirectory(packageVersion); _packageFtpsClient.ChangeDirectory(packageVersion); _packageFtpsClient.PutFileAsync(packagePath, FileAction.Create); _uploadPackageResetEvent.WaitOne(); diff --git a/nUpdate.Administration/Core/Ftp/Service/TransferServiceProvider.cs b/nUpdate.Administration/Core/Ftp/Service/TransferServiceProvider.cs index 8b1a865e..4d04f7c1 100644 --- a/nUpdate.Administration/Core/Ftp/Service/TransferServiceProvider.cs +++ b/nUpdate.Administration/Core/Ftp/Service/TransferServiceProvider.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// TransferServiceProvider.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/Core/FtpManager.cs b/nUpdate.Administration/Core/FtpManager.cs index 0f46055a..edec1d81 100644 --- a/nUpdate.Administration/Core/FtpManager.cs +++ b/nUpdate.Administration/Core/FtpManager.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// FtpManager.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/Core/History/Log.cs b/nUpdate.Administration/Core/History/Log.cs index fc2e1540..ef205d3d 100644 --- a/nUpdate.Administration/Core/History/Log.cs +++ b/nUpdate.Administration/Core/History/Log.cs @@ -1,8 +1,12 @@ -// Copyright © Dominic Beger 2018 +// Log.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; +using System.Drawing; +using System.Globalization; using nUpdate.Administration.Core.Application; +using nUpdate.Administration.UI.Popups; namespace nUpdate.Administration.Core.History { @@ -28,6 +32,11 @@ public class Log /// public UpdateProject Project { get; set; } + /// + /// Gets or Set the Username that contains in the entry. + /// + public string Username { get; set; } + /// /// Writes an entry to the log. /// @@ -36,10 +45,30 @@ public class Log public void Write(LogEntry entry, string packageVersionString) { var log = new Log(); - log.EntryTime = DateTime.Now.ToString(); + log.EntryTime = DateTime.Now.ToString(CultureInfo.CurrentCulture); log.Entry = entry; log.PackageVersion = packageVersionString; + string userDomainName; + + try + { + userDomainName = Environment.UserDomainName; + } + catch (NotSupportedException e1) + { + userDomainName = null; + Console.WriteLine(e1); + } + catch (Exception ex) + { + userDomainName = null; + Popup.ShowPopup(null, SystemIcons.Error, "Error while get the current domainname.", ex, + PopupButtons.Ok); + } + + log.Username = userDomainName == null ? Environment.UserName : $"{userDomainName}\\{Environment.UserName}"; + if (Project.Log == null) Project.Log = new List(); Project.Log.Add(log); diff --git a/nUpdate.Administration/Core/History/LogEntry.cs b/nUpdate.Administration/Core/History/LogEntry.cs index 08604926..a74f6a91 100644 --- a/nUpdate.Administration/Core/History/LogEntry.cs +++ b/nUpdate.Administration/Core/History/LogEntry.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// LogEntry.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Administration.Core.History { @@ -6,6 +7,7 @@ public enum LogEntry { Create, Delete, - Upload + Upload, + Edit } } \ No newline at end of file diff --git a/nUpdate.Administration/Core/IAsyncSupportable.cs b/nUpdate.Administration/Core/IAsyncSupportable.cs index 32067781..73338889 100644 --- a/nUpdate.Administration/Core/IAsyncSupportable.cs +++ b/nUpdate.Administration/Core/IAsyncSupportable.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// IAsyncSupportable.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Administration.Core { diff --git a/nUpdate.Administration/Core/IResettable.cs b/nUpdate.Administration/Core/IResettable.cs index ede5a122..eeeded6c 100644 --- a/nUpdate.Administration/Core/IResettable.cs +++ b/nUpdate.Administration/Core/IResettable.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// IResettable.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Administration.Core { diff --git a/nUpdate.Administration/Core/JsonHelper.cs b/nUpdate.Administration/Core/JsonHelper.cs index a79c7719..2a4c1d55 100644 --- a/nUpdate.Administration/Core/JsonHelper.cs +++ b/nUpdate.Administration/Core/JsonHelper.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// JsonHelper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Linq; using System.Text; diff --git a/nUpdate.Administration/Core/ListingItem.cs b/nUpdate.Administration/Core/ListingItem.cs index 8c4c53b4..e98abfce 100644 --- a/nUpdate.Administration/Core/ListingItem.cs +++ b/nUpdate.Administration/Core/ListingItem.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ListingItem.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Collections.Generic; diff --git a/nUpdate.Administration/Core/Localization/LocalizationProperties.cs b/nUpdate.Administration/Core/Localization/LocalizationProperties.cs index cac6b065..870c5f37 100644 --- a/nUpdate.Administration/Core/Localization/LocalizationProperties.cs +++ b/nUpdate.Administration/Core/Localization/LocalizationProperties.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// LocalizationProperties.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Administration/Core/Navigator.cs b/nUpdate.Administration/Core/Navigator.cs index 6f920362..859d274d 100644 --- a/nUpdate.Administration/Core/Navigator.cs +++ b/nUpdate.Administration/Core/Navigator.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// Navigator.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Collections.Generic; using System.Linq; diff --git a/nUpdate.Administration/Core/Operations/Panels/FileDeleteOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/FileDeleteOperationPanel.cs index ad2b6d19..9d69b5dc 100644 --- a/nUpdate.Administration/Core/Operations/Panels/FileDeleteOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/FileDeleteOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// FileDeleteOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.ComponentModel; diff --git a/nUpdate.Administration/Core/Operations/Panels/FileRenameOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/FileRenameOperationPanel.cs index 447ccdf9..b75e0e4f 100644 --- a/nUpdate.Administration/Core/Operations/Panels/FileRenameOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/FileRenameOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// FileRenameOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/Core/Operations/Panels/IOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/IOperationPanel.cs index 91bc861c..9795077b 100644 --- a/nUpdate.Administration/Core/Operations/Panels/IOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/IOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// IOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using nUpdate.Internal.Core.Operations; diff --git a/nUpdate.Administration/Core/Operations/Panels/ProcessStartOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/ProcessStartOperationPanel.cs index 75659a3a..fd3c421b 100644 --- a/nUpdate.Administration/Core/Operations/Panels/ProcessStartOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/ProcessStartOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ProcessStartOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/Core/Operations/Panels/ProcessStopOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/ProcessStopOperationPanel.cs index d3b15a9b..978c2af5 100644 --- a/nUpdate.Administration/Core/Operations/Panels/ProcessStopOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/ProcessStopOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ProcessStopOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/Core/Operations/Panels/RegistryDeleteValueOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/RegistryDeleteValueOperationPanel.cs index a828c3e7..8c9d3331 100644 --- a/nUpdate.Administration/Core/Operations/Panels/RegistryDeleteValueOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/RegistryDeleteValueOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// RegistryDeleteValueOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.ComponentModel; diff --git a/nUpdate.Administration/Core/Operations/Panels/RegistrySetValueOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/RegistrySetValueOperationPanel.cs index e52f2976..76aa8080 100644 --- a/nUpdate.Administration/Core/Operations/Panels/RegistrySetValueOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/RegistrySetValueOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// RegistrySetValueOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/Core/Operations/Panels/RegistrySubKeyCreateOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/RegistrySubKeyCreateOperationPanel.cs index 330b08cc..b8b95833 100644 --- a/nUpdate.Administration/Core/Operations/Panels/RegistrySubKeyCreateOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/RegistrySubKeyCreateOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// RegistrySubKeyCreateOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.ComponentModel; diff --git a/nUpdate.Administration/Core/Operations/Panels/RegistrySubKeyDeleteOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/RegistrySubKeyDeleteOperationPanel.cs index 8098540c..8d0730b4 100644 --- a/nUpdate.Administration/Core/Operations/Panels/RegistrySubKeyDeleteOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/RegistrySubKeyDeleteOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// RegistrySubKeyDeleteOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.ComponentModel; diff --git a/nUpdate.Administration/Core/Operations/Panels/ScriptExecuteOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/ScriptExecuteOperationPanel.cs index 0d723567..b858552e 100644 --- a/nUpdate.Administration/Core/Operations/Panels/ScriptExecuteOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/ScriptExecuteOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ScriptExecuteOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.CodeDom.Compiler; diff --git a/nUpdate.Administration/Core/Operations/Panels/ServiceStartOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/ServiceStartOperationPanel.cs index 532fd5dc..9cf6098a 100644 --- a/nUpdate.Administration/Core/Operations/Panels/ServiceStartOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/ServiceStartOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ServiceStartOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Collections.Generic; using System.Linq; diff --git a/nUpdate.Administration/Core/Operations/Panels/ServiceStopOperationPanel.cs b/nUpdate.Administration/Core/Operations/Panels/ServiceStopOperationPanel.cs index 19205c14..9efbdf8e 100644 --- a/nUpdate.Administration/Core/Operations/Panels/ServiceStopOperationPanel.cs +++ b/nUpdate.Administration/Core/Operations/Panels/ServiceStopOperationPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ServiceStopOperationPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Windows.Forms; using nUpdate.Internal.Core.Operations; diff --git a/nUpdate.Administration/Core/ProjectConfiguration.cs b/nUpdate.Administration/Core/ProjectConfiguration.cs index e65941a8..b2e273aa 100644 --- a/nUpdate.Administration/Core/ProjectConfiguration.cs +++ b/nUpdate.Administration/Core/ProjectConfiguration.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ProjectConfiguration.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/Core/ServiceProviderHelper.cs b/nUpdate.Administration/Core/ServiceProviderHelper.cs index 51ce90ad..cca9d4a5 100644 --- a/nUpdate.Administration/Core/ServiceProviderHelper.cs +++ b/nUpdate.Administration/Core/ServiceProviderHelper.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ServiceProviderHelper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Linq; diff --git a/nUpdate.Administration/Core/StatisticsServer.cs b/nUpdate.Administration/Core/StatisticsServer.cs index 48ebc6f3..286f1de7 100644 --- a/nUpdate.Administration/Core/StatisticsServer.cs +++ b/nUpdate.Administration/Core/StatisticsServer.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// StatisticsServer.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Administration/Core/ValidationManager.cs b/nUpdate.Administration/Core/ValidationManager.cs index 025162cc..a9681980 100644 --- a/nUpdate.Administration/Core/ValidationManager.cs +++ b/nUpdate.Administration/Core/ValidationManager.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ValidationManager.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Collections.Generic; using System.Linq; diff --git a/nUpdate.Administration/Core/Win32/IconReader.cs b/nUpdate.Administration/Core/Win32/IconReader.cs index bb3d5207..d47df99a 100644 --- a/nUpdate.Administration/Core/Win32/IconReader.cs +++ b/nUpdate.Administration/Core/Win32/IconReader.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// IconReader.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/Core/Win32/Margins.cs b/nUpdate.Administration/Core/Win32/Margins.cs index bed39e24..5830e3eb 100644 --- a/nUpdate.Administration/Core/Win32/Margins.cs +++ b/nUpdate.Administration/Core/Win32/Margins.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// Margins.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Runtime.InteropServices; diff --git a/nUpdate.Administration/Core/Win32/NativeMethods.cs b/nUpdate.Administration/Core/Win32/NativeMethods.cs index 597d9508..c05ae7d8 100644 --- a/nUpdate.Administration/Core/Win32/NativeMethods.cs +++ b/nUpdate.Administration/Core/Win32/NativeMethods.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// NativeMethods.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Runtime.InteropServices; diff --git a/nUpdate.Administration/Core/Win32/PaintStruct.cs b/nUpdate.Administration/Core/Win32/PaintStruct.cs index f6567b27..9e9683bf 100644 --- a/nUpdate.Administration/Core/Win32/PaintStruct.cs +++ b/nUpdate.Administration/Core/Win32/PaintStruct.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// PaintStruct.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Runtime.InteropServices; diff --git a/nUpdate.Administration/GlobalSuppressions.cs b/nUpdate.Administration/GlobalSuppressions.cs index 775495e8..75f9a620 100644 Binary files a/nUpdate.Administration/GlobalSuppressions.cs and b/nUpdate.Administration/GlobalSuppressions.cs differ diff --git a/nUpdate.Administration/Program.cs b/nUpdate.Administration/Program.cs index d1fd2e89..fc72424e 100644 --- a/nUpdate.Administration/Program.cs +++ b/nUpdate.Administration/Program.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// Program.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.IO; @@ -57,7 +58,7 @@ public static class Program /// /// The version string shown in all dialog titles. /// - public static string VersionString => "nUpdate Administration v3.3.1"; + public static string VersionString => "nUpdate Administration v3.4.1"; private static void Exit(object sender, EventArgs e) { diff --git a/nUpdate.Administration/Properties/AssemblyInfo.cs b/nUpdate.Administration/Properties/AssemblyInfo.cs index 1747d16b..27d70989 100644 --- a/nUpdate.Administration/Properties/AssemblyInfo.cs +++ b/nUpdate.Administration/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// AssemblyInfo.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System.Reflection; using System.Resources; @@ -38,6 +39,6 @@ // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.3.1.0")] -[assembly: AssemblyFileVersion("3.3.1.0")] +[assembly: AssemblyVersion("3.4.1.0")] +[assembly: AssemblyFileVersion("3.4.1.0")] [assembly: NeutralResourcesLanguage("")] \ No newline at end of file diff --git a/nUpdate.Administration/Properties/Resources.Designer.cs b/nUpdate.Administration/Properties/Resources.Designer.cs index 82134517..fc0f7ae1 100644 --- a/nUpdate.Administration/Properties/Resources.Designer.cs +++ b/nUpdate.Administration/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.34014 +// Laufzeitversion:4.0.30319.42000 // // Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn // der Code erneut generiert wird. @@ -19,7 +19,7 @@ namespace nUpdate.Administration.Properties { // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -90,6 +90,16 @@ internal static System.Drawing.Bitmap Changelog { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Conditions { + get { + object obj = ResourceManager.GetObject("Conditions", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// diff --git a/nUpdate.Administration/Properties/Resources.resx b/nUpdate.Administration/Properties/Resources.resx index 8ad0e8c6..19114c8d 100644 --- a/nUpdate.Administration/Properties/Resources.resx +++ b/nUpdate.Administration/Properties/Resources.resx @@ -193,4 +193,7 @@ ..\Resources\statistics.php;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\conditions.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/nUpdate.Administration/Properties/Settings.Designer.cs b/nUpdate.Administration/Properties/Settings.Designer.cs index 4fa19eae..06768c79 100644 --- a/nUpdate.Administration/Properties/Settings.Designer.cs +++ b/nUpdate.Administration/Properties/Settings.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. // //------------------------------------------------------------------------------ @@ -12,7 +12,7 @@ namespace nUpdate.Administration.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/nUpdate.Administration/Properties/Settings.settings b/nUpdate.Administration/Properties/Settings.settings index 51eb688b..3e24110d 100644 --- a/nUpdate.Administration/Properties/Settings.settings +++ b/nUpdate.Administration/Properties/Settings.settings @@ -1,5 +1,7 @@  - + + diff --git a/nUpdate.Administration/Resources/conditions.png b/nUpdate.Administration/Resources/conditions.png new file mode 100644 index 00000000..4869ed24 Binary files /dev/null and b/nUpdate.Administration/Resources/conditions.png differ diff --git a/nUpdate.Administration/Resources/en.json b/nUpdate.Administration/Resources/en.json index b664d889..7e9ada9a 100644 --- a/nUpdate.Administration/Resources/en.json +++ b/nUpdate.Administration/Resources/en.json @@ -1,183 +1,193 @@ { - "ProductTitle": "nUpdate Administration 1.1.0.0", - "CancelButtonText": "Cancel", - "ContinueButtonText": "Continue", - "SaveButtonText": "Save", - "DoneButtonText": "Done", - "CreatePackageButtonText": "Create package", - "EditPackageButtonText": "Edit package", - "SendButtonText": "Send", - "SaveLanguageButtonText": "Save language", - "InvalidArgumentErrorCaption": "Invalid argument found.", - "InvalidArgumentErrorText": "The entry for {0} can\u0027t be parsed to {1}.", - "CredentialsDialogTitle": "Enter your credentials", - "CredentialsDialogHeaderText": "Credentials", - "CredentialsDialogUsernameLabelText": "Username:", - "CredentialsDialogPasswordLabelext": "Password:", - "DirectorySearchDialogTitle": "Set the directory - {0} - {1}", - "DirectorySearchDialogDirectoryLabelText": "Directory:", - "DirectorySearchDialogInfoLabelText": "Select the directory that should be used for the update files.", - "DirectorySearchDialogServerNodeText": "Server", - "FeedbackDialogTitle": "Feedback - {0}", - "FeedbackDialogHeaderLabelText": "Feedback", - "FeedbackDialogEmailAdressWatermarkText": "Your e-mail address", - "FeedbackDialogNameWatermarkText": "Name", - "FeedBackDialogPrivacyTermsLinkLabelText": "How will my data be used?", - "HistoryDialogTitle": "History - {0} - {1}", - "HistoryDialogClearButtonText": "Clear history", - "HistoryDialogOrderDescendingEntryText": "Order descending", - "HistoryDialogOrderAscendingEntryText": "Order ascending", - "HistoryDialogSaveToFileButtonText": "Save to file.", - "HistoryDialogNoHistoryLabelText": "No history available.", - "HistoryDialogCreatedPackageEntryText": "Created package", - "HistoryDialogEditedPackageEntryText": "Edited package", - "HistoryDialogUploadedPackageEntryText": "Uploaded package", - "HistoryDialogDeletedPackageEntryText": "Deleted package", - "InfoDialogTitle": "Information - {0}", - "InfoDialogLicenseInfoLabelText": "nUpdate\u0027s solution contains 7 projects which are all licensed under the CC-ND-license.", - "InfoDialogIconsLabelText": "Icons:", - "InfoDialogIconPackageByLabelText": "Fugue Icon Package by", - "InfoDialogSpecialThanksToLabelText": "Special thanks to ", - "InfoDialogAsRsaContributorLabelText": "as a contributor to the RsaSignature-class and", - "InfoDialogENBLabelText": "for tips and the great \"ExplorerNavigationButton\"-control.", - "InfoDialogFollowProjectLabelText": "Follow this project on ", - "InfoDialogOrHaveALookLabelText": "or have a look at", - "JsonEditorDialogTitle": "Edit language file - {0} - {1}", - "MainDialogHeader": null, - "MainDialogInfoText": "Welcome, here you can create and manage your updates for nUpdate.", - "MainDialogProjectsGroupText": "Projects", - "MainDialogPreferencesGroupText": "Preferences", - "MainDialogInformationGroupText": "Information", - "MainDialogNewProjectText": "New project", - "MainDialogNewProjectDescriptionText": "Creates a new project.", - "MainDialogOpenProjectText": "Open project", - "MainDialogOpenProjectDescriptionText": "Opens an existing project.", - "MainDialogInformationText": "Information", - "MainDialogInformationDescriptionText": "Shows the information.", - "MainDialogPreferencesText": "Preferences", - "MainDialogPreferencesDescriptionText": null, - "MainDialogProxyText": "Proxy", - "MainDialogProxyDescriptionText": "Configurate your proxies here.", - "MainDialogFeedbackText": "Feedback", - "MainDialogFeedbackDescriptionText": "Send your feedback here.", - "NewProjectDialogTitle": "New project - {0}", - "PanelSignatureHeader": "Key pair generation", - "PanelSignatureInfoText": "nUpdate uses a 4096-bit RSA-Signature to serve for the security of your update packages.\nThe generation of these keys may take a different amount of time,\ndepending on your PC. Please be patient.", - "PanelSignatureWaitText": "Please wait while the key pair is being generated...", - "PanelGeneralHeader": "General", - "PanelGeneralNameText": "Name:", - "PanelGeneralNameWatermarkText": "The name of the project", - "PanelGeneralLanguageText": "Language:", - "PanelFtpHeader": "FTP-Data", - "PanelFtpServerText": "Adress:", - "PanelFtpUserText": "User:", - "PanelFtpUserWatermarkText": "The username", - "PanelFtpPasswordText": "Password:", - "PanelFtpDirectoryText": "Directory:", - "PanelFtpPortText": "Port:", - "PanelFtpPortWatermarkText": "The port", - "PanelFtpPassiveConnectionText": "Passive (rated)", - "PanelFtpActiveConnectionText": "Active", - "ProjectDialogTitle": "{0} - {1}", - "ProjectDialogOverviewTabText": "Overview", - "ProjectDialogPackagesTabText": "Packages", - "ProjectDialogOverviewText": "Project-overview", - "ProjectDialogNameLabelText": "Name:", - "ProjectDialogUpdateUrlLabelText": "Update-URL:", - "ProjectDialogFtpHostLabelText": "FTP-Host:", - "ProjectDialogFtpDirectoryLabelText": "FTP-directory:", - "ProjectDialogPackagesAmountLabelText": "Amount of packages released:", - "ProjectDialogNewestPackageLabelText": "Newest package released:", - "ProjectDialogInfoFileloadingLabelText": "Status of the update-info file:", - "ProjectDialogCheckInfoFileStatusLinkLabelText": "Check status", - "ProjectDialogProjectDataText": "Project-data", - "ProjectDialogPublicKeyLabelText": "Public key:", - "ProjectDialogProjectIdLabelText": "Project-ID:", - "ProjectDialogAddButtonText": "Add", - "ProjectDialogEditButtonText": "Edit", - "ProjectDialogDeleteButtonText": "Delete", - "ProjectDialogUploadButtonText": "Upload", - "ProjectDialogHistoryButtonText": "History", - "ProjectDialogVersionText": "Version", - "ProjectDialogReleasedText": "Released", - "ProjectDialogSizeText": "Size", - "ProjectDialogDescriptionText": "Description", - "ProjectDialogSearchText": "Search...", - "ProjectEditDialogTitle": "Edit project", - "ProjectEditDialogRenameText": "The new name of the project", - "ProjectEditDialogNewNameText": "New name:", - "ProjectEditDialogLanguageText": "Language:", - "PackageAddDialogTitle": "Add new package - {0} - {1}", - "PackageAddDialogGeneralItemText": "General", - "PackageAddDialogChangelogItemText": "Changelog", - "PackageAddDialogFilesItemText": "Files", - "PackageAddDialogAvailabilityItemText": "Availability", - "PackageAddDialogOperationsItemText": null, - "PackageAddDialogProxyItemText": null, - "PackageAddDialogDevelopmentalStageLabelText": "Developmental stage:", - "PackageAddDialogVersionLabelText": "Version:", - "PackageAddDialogDescriptionLabelText": "Description:", - "PackageAddDialogPublishCheckBoxText": "Publish this update", - "PackageAddDialogPublishInfoLabelText": "Sets if the package should be uploaded yet. You can upload it later, if you disable this\r\noption. The update package will be saved locally on your PC then.", - "PackageAddDialogEnvironmentLabelText": "Architecture settings:", - "PackageAddDialogEnvironmentInfoLabelText": "Sets if the update package should only run on special architectures. To set any type\r\nof architecture, choose \"AnyCPU\" as entry.", - "PackageAddDialogLoadButtonText": "Load from file...", - "PackageAddDialogClearButtonText": "Clear", - "PackageAddDialogAddFileButtonText": "Add files...", - "PackageAddDialogRemoveFileButtonText": "Remove files...", - "PackageAddDialogNameHeaderText": "Name", - "PackageAddDialogSizeHeaderText": "Size", - "PackageAddDialogAvailableForAllRadioButtonText": "Available for all older versions", - "PackageAddDialogAvailableForAllInfoText": "This package is available and can be downloaded for all older versions.", - "PackageAddDialogAvailableForSomeRadioButtonText": "Not available for some older versions", - "PackageAddDialogAvailableForSomeInfoText": "This package is not available for the following versions.", - "PackageAddDialogAddButtonText": "Add", - "PackageAddDialogRemoveButtonText": "Remove", - "PackageAddDialogUseProxyCheckBoxText": null, - "PackageAddDialogProxyHostLabelText": null, - "PackageAddDialogProxyPortLabelText": null, - "PackageAddDialogProxyUsernameLabelText": null, - "PackageAddDialogProxyPasswordLabelText": null, - "PackageAddDialogProxyInfoLabelText": null, - "PackageAddDialogUseOperationsCheckBoxText": null, - "PackageAddDialogOperationAddButtonText": null, - "PackageAddDialogArchiveInitializerInfoText": "Initializing archive...", - "PackageAddDialogPrepareInfoText": "Preparing update...", - "PackageAddDialogSigningInfoText": "Signing package...", - "PackageAddDialogConfigInitializerInfoText": "Initializing config...", - "PackageAddDialogUploadingPackageInfoText": "Uploading package - {0}", - "PackageAddDialogUploadingConfigInfoText": "Uploading configuration...", - "PackageAddDialogPackageDataCreationErrorCaption": "Creating package data failed.", - "PackageAddDialogProjectDataLoadingErrorCaption": "Failed to load project data.", - "PackageAddDialogGettingUrlErrorCaption": "Error while getting url.", - "PackageAddDialogReadingPackageBytesErrorCaption": "Reading package bytes failed.", - "PackageAddDialogInvalidServerDirectoryErrorCaption": "Invalid server directory.", - "PackageAddDialogInvalidServerDirectoryErrorText": "The directory for the update files on the server is not valid. Please edit it.", - "PackageAddDialogLoadingFtpDataErrorCaption": "Failed to load FTP-data.", - "PackageAddDialogConfigurationDownloadErrorCaption": "Configuration download failed.", - "PackageAddDialogSerializingDataErrorCaption": "Error on serializing data.", - "PackageAddDialogRelativeUriErrorText": "The server-directory can\u0027t be set as a relative uri.", - "PackageAddDialogPackageInformationSavingErrorCaption": "Saving package information failed.", - "PackageAddDialogUploadFailedErrorCaption": "Upload failed.", - "PackageAddDialogNoInternetWarningText": "nUpdate Administration could not verify a network connection. Some functions are disabled for now and you can only save the package on your PC. An upload is possible as soon as a network connections is given.", - "PackageAddDialogNoInternetWarningCaption": "No network connection available.", - "PackageAddDialogNoFilesSpecifiedWarningText": "There were no files specified for the update package. Please make sure you added an archive or some files to pack automatically.", - "PackageAddDialogNoFilesSpecifiedWarningCaption": "No files for the package set.", - "PackageAddDialogUnsupportedArchiveWarningText": "You added an unsupported archive type to the list. nUpdate is only able to unpack \".ZIP\"-files at the moment.", - "PackageAddDialogUnsupportedArchiveWarningCaption": "Unsupported archive type.", - "PackageAddDialogVersionInvalidWarningText": "The given version is invalid. You cannot use \"0.0.x.x\" as product-version. Please make sure to select a minimum Minor-version of \"1\".", - "PackageAddDialogVersionExistingWarningText": "Version \"{0}\" is already existing.", - "PackageAddDialogVersionInvalidWarningCaption": "Invalid package version.", - "PackageAddDialogNoChangelogWarningText": "There was no changelog set for the update package.", - "PackageAddDialogNoChangelogWarningCaption": "No changelog set.", - "PackageAddDialogAlreadyImportedWarningText": "The file \" {0} \" is already imported. Should it be replaced by the new one?", - "PackageAddDialogAlreadyImportedWarningCaption": "File already imported", - "InputsMissingErrorCaption": null, - "InputsMissingErrorText": null, - "ProjectReadingErrorCaption": "Error while reading the project.", - "OperatingSystemNotSupportedWarn": "Your system is not supported. Windows Vista or higher necessary...", - "MissingRightsWarnCaption": "Missing rights.", - "MissingRightsWarnText": "You do not own the admin rights to create the extension\u0027s registry entry.", - "AlreadyExistingWarnText": "The project {0} already exists.", - "ListingServerDataErrorCaption": "Error while listing the server-data." + "ProductTitle": "nUpdate Administration 1.1.0.0", + "CancelButtonText": "Cancel", + "ContinueButtonText": "Continue", + "SaveButtonText": "Save", + "DoneButtonText": "Done", + "CreatePackageButtonText": "Create package", + "EditPackageButtonText": "Edit package", + "SendButtonText": "Send", + "SaveLanguageButtonText": "Save language", + "InvalidArgumentErrorCaption": "Invalid argument found.", + "InvalidArgumentErrorText": "The entry for {0} can\u0027t be parsed to {1}.", + "CredentialsDialogTitle": "Enter your credentials", + "CredentialsDialogHeaderText": "Credentials", + "CredentialsDialogUsernameLabelText": "Username:", + "CredentialsDialogPasswordLabelext": "Password:", + "DirectorySearchDialogTitle": "Set the directory - {0} - {1}", + "DirectorySearchDialogDirectoryLabelText": "Directory:", + "DirectorySearchDialogInfoLabelText": "Select the directory that should be used for the update files.", + "DirectorySearchDialogServerNodeText": "Server", + "FeedbackDialogTitle": "Feedback - {0}", + "FeedbackDialogHeaderLabelText": "Feedback", + "FeedbackDialogEmailAdressWatermarkText": "Your e-mail address", + "FeedbackDialogNameWatermarkText": "Name", + "FeedBackDialogPrivacyTermsLinkLabelText": "How will my data be used?", + "HistoryDialogTitle": "History - {0} - {1}", + "HistoryDialogClearButtonText": "Clear history", + "HistoryDialogOrderDescendingEntryText": "Order descending", + "HistoryDialogOrderAscendingEntryText": "Order ascending", + "HistoryDialogSaveToFileButtonText": "Save to file.", + "HistoryDialogNoHistoryLabelText": "No history available.", + "HistoryDialogCreatedPackageEntryText": "Created package", + "HistoryDialogEditedPackageEntryText": "Edited package", + "HistoryDialogUploadedPackageEntryText": "Uploaded package", + "HistoryDialogDeletedPackageEntryText": "Deleted package", + "InfoDialogTitle": "Information - {0}", + "InfoDialogLicenseInfoLabelText": + "nUpdate\u0027s solution contains 7 projects which are all licensed under the CC-ND-license.", + "InfoDialogIconsLabelText": "Icons:", + "InfoDialogIconPackageByLabelText": "Fugue Icon Package by", + "InfoDialogSpecialThanksToLabelText": "Special thanks to ", + "InfoDialogAsRsaContributorLabelText": "as a contributor to the RsaSignature-class and", + "InfoDialogENBLabelText": "for tips and the great \"ExplorerNavigationButton\"-control.", + "InfoDialogFollowProjectLabelText": "Follow this project on ", + "InfoDialogOrHaveALookLabelText": "or have a look at", + "JsonEditorDialogTitle": "Edit language file - {0} - {1}", + "MainDialogHeader": null, + "MainDialogInfoText": "Welcome, here you can create and manage your updates for nUpdate.", + "MainDialogProjectsGroupText": "Projects", + "MainDialogPreferencesGroupText": "Preferences", + "MainDialogInformationGroupText": "Information", + "MainDialogNewProjectText": "New project", + "MainDialogNewProjectDescriptionText": "Creates a new project.", + "MainDialogOpenProjectText": "Open project", + "MainDialogOpenProjectDescriptionText": "Opens an existing project.", + "MainDialogInformationText": "Information", + "MainDialogInformationDescriptionText": "Shows the information.", + "MainDialogPreferencesText": "Preferences", + "MainDialogPreferencesDescriptionText": null, + "MainDialogProxyText": "Proxy", + "MainDialogProxyDescriptionText": "Configurate your proxies here.", + "MainDialogFeedbackText": "Feedback", + "MainDialogFeedbackDescriptionText": "Send your feedback here.", + "NewProjectDialogTitle": "New project - {0}", + "PanelSignatureHeader": "Key pair generation", + "PanelSignatureInfoText": + "nUpdate uses a 4096-bit RSA-Signature to serve for the security of your update packages.\nThe generation of these keys may take a different amount of time,\ndepending on your PC. Please be patient.", + "PanelSignatureWaitText": "Please wait while the key pair is being generated...", + "PanelGeneralHeader": "General", + "PanelGeneralNameText": "Name:", + "PanelGeneralNameWatermarkText": "The name of the project", + "PanelGeneralLanguageText": "Language:", + "PanelFtpHeader": "FTP-Data", + "PanelFtpServerText": "Adress:", + "PanelFtpUserText": "User:", + "PanelFtpUserWatermarkText": "The username", + "PanelFtpPasswordText": "Password:", + "PanelFtpDirectoryText": "Directory:", + "PanelFtpPortText": "Port:", + "PanelFtpPortWatermarkText": "The port", + "PanelFtpPassiveConnectionText": "Passive (rated)", + "PanelFtpActiveConnectionText": "Active", + "ProjectDialogTitle": "{0} - {1}", + "ProjectDialogOverviewTabText": "Overview", + "ProjectDialogPackagesTabText": "Packages", + "ProjectDialogOverviewText": "Project-overview", + "ProjectDialogNameLabelText": "Name:", + "ProjectDialogUpdateUrlLabelText": "Update-URL:", + "ProjectDialogFtpHostLabelText": "FTP-Host:", + "ProjectDialogFtpDirectoryLabelText": "FTP-directory:", + "ProjectDialogPackagesAmountLabelText": "Amount of packages released:", + "ProjectDialogNewestPackageLabelText": "Newest package released:", + "ProjectDialogInfoFileloadingLabelText": "Status of the update-info file:", + "ProjectDialogCheckInfoFileStatusLinkLabelText": "Check status", + "ProjectDialogProjectDataText": "Project-data", + "ProjectDialogPublicKeyLabelText": "Public key:", + "ProjectDialogProjectIdLabelText": "Project-ID:", + "ProjectDialogAddButtonText": "Add", + "ProjectDialogEditButtonText": "Edit", + "ProjectDialogDeleteButtonText": "Delete", + "ProjectDialogUploadButtonText": "Upload", + "ProjectDialogHistoryButtonText": "History", + "ProjectDialogVersionText": "Version", + "ProjectDialogReleasedText": "Released", + "ProjectDialogSizeText": "Size", + "ProjectDialogDescriptionText": "Description", + "ProjectDialogSearchText": "Search...", + "ProjectEditDialogTitle": "Edit project", + "ProjectEditDialogRenameText": "The new name of the project", + "ProjectEditDialogNewNameText": "New name:", + "ProjectEditDialogLanguageText": "Language:", + "PackageAddDialogTitle": "Add new package - {0} - {1}", + "PackageAddDialogGeneralItemText": "General", + "PackageAddDialogChangelogItemText": "Changelog", + "PackageAddDialogFilesItemText": "Files", + "PackageAddDialogAvailabilityItemText": "Availability", + "PackageAddDialogOperationsItemText": null, + "PackageAddDialogProxyItemText": null, + "PackageAddDialogDevelopmentalStageLabelText": "Developmental stage:", + "PackageAddDialogVersionLabelText": "Version:", + "PackageAddDialogDescriptionLabelText": "Description:", + "PackageAddDialogPublishCheckBoxText": "Publish this update", + "PackageAddDialogPublishInfoLabelText": + "Sets if the package should be uploaded yet. You can upload it later, if you disable this\r\noption. The update package will be saved locally on your PC then.", + "PackageAddDialogEnvironmentLabelText": "Architecture settings:", + "PackageAddDialogEnvironmentInfoLabelText": + "Sets if the update package should only run on special architectures. To set any type\r\nof architecture, choose \"AnyCPU\" as entry.", + "PackageAddDialogLoadButtonText": "Load from file...", + "PackageAddDialogClearButtonText": "Clear", + "PackageAddDialogAddFileButtonText": "Add files...", + "PackageAddDialogRemoveFileButtonText": "Remove files...", + "PackageAddDialogNameHeaderText": "Name", + "PackageAddDialogSizeHeaderText": "Size", + "PackageAddDialogAvailableForAllRadioButtonText": "Available for all older versions", + "PackageAddDialogAvailableForAllInfoText": "This package is available and can be downloaded for all older versions.", + "PackageAddDialogAvailableForSomeRadioButtonText": "Not available for some older versions", + "PackageAddDialogAvailableForSomeInfoText": "This package is not available for the following versions.", + "PackageAddDialogAddButtonText": "Add", + "PackageAddDialogRemoveButtonText": "Remove", + "PackageAddDialogUseProxyCheckBoxText": null, + "PackageAddDialogProxyHostLabelText": null, + "PackageAddDialogProxyPortLabelText": null, + "PackageAddDialogProxyUsernameLabelText": null, + "PackageAddDialogProxyPasswordLabelText": null, + "PackageAddDialogProxyInfoLabelText": null, + "PackageAddDialogUseOperationsCheckBoxText": null, + "PackageAddDialogOperationAddButtonText": null, + "PackageAddDialogArchiveInitializerInfoText": "Initializing archive...", + "PackageAddDialogPrepareInfoText": "Preparing update...", + "PackageAddDialogSigningInfoText": "Signing package...", + "PackageAddDialogConfigInitializerInfoText": "Initializing config...", + "PackageAddDialogUploadingPackageInfoText": "Uploading package - {0}", + "PackageAddDialogUploadingConfigInfoText": "Uploading configuration...", + "PackageAddDialogPackageDataCreationErrorCaption": "Creating package data failed.", + "PackageAddDialogProjectDataLoadingErrorCaption": "Failed to load project data.", + "PackageAddDialogGettingUrlErrorCaption": "Error while getting url.", + "PackageAddDialogReadingPackageBytesErrorCaption": "Reading package bytes failed.", + "PackageAddDialogInvalidServerDirectoryErrorCaption": "Invalid server directory.", + "PackageAddDialogInvalidServerDirectoryErrorText": + "The directory for the update files on the server is not valid. Please edit it.", + "PackageAddDialogLoadingFtpDataErrorCaption": "Failed to load FTP-data.", + "PackageAddDialogConfigurationDownloadErrorCaption": "Configuration download failed.", + "PackageAddDialogSerializingDataErrorCaption": "Error on serializing data.", + "PackageAddDialogRelativeUriErrorText": "The server-directory can\u0027t be set as a relative uri.", + "PackageAddDialogPackageInformationSavingErrorCaption": "Saving package information failed.", + "PackageAddDialogUploadFailedErrorCaption": "Upload failed.", + "PackageAddDialogNoInternetWarningText": + "nUpdate Administration could not verify a network connection. Some functions are disabled for now and you can only save the package on your PC. An upload is possible as soon as a network connections is given.", + "PackageAddDialogNoInternetWarningCaption": "No network connection available.", + "PackageAddDialogNoFilesSpecifiedWarningText": + "There were no files specified for the update package. Please make sure you added an archive or some files to pack automatically.", + "PackageAddDialogNoFilesSpecifiedWarningCaption": "No files for the package set.", + "PackageAddDialogUnsupportedArchiveWarningText": + "You added an unsupported archive type to the list. nUpdate is only able to unpack \".ZIP\"-files at the moment.", + "PackageAddDialogUnsupportedArchiveWarningCaption": "Unsupported archive type.", + "PackageAddDialogVersionInvalidWarningText": + "The given version is invalid. You cannot use \"0.0.x.x\" as product-version. Please make sure to select a minimum Minor-version of \"1\".", + "PackageAddDialogVersionExistingWarningText": "Version \"{0}\" is already existing.", + "PackageAddDialogVersionInvalidWarningCaption": "Invalid package version.", + "PackageAddDialogNoChangelogWarningText": "There was no changelog set for the update package.", + "PackageAddDialogNoChangelogWarningCaption": "No changelog set.", + "PackageAddDialogAlreadyImportedWarningText": + "The file \" {0} \" is already imported. Should it be replaced by the new one?", + "PackageAddDialogAlreadyImportedWarningCaption": "File already imported", + "InputsMissingErrorCaption": null, + "InputsMissingErrorText": null, + "ProjectReadingErrorCaption": "Error while reading the project.", + "OperatingSystemNotSupportedWarn": "Your system is not supported. Windows Vista or higher necessary...", + "MissingRightsWarnCaption": "Missing rights.", + "MissingRightsWarnText": "You do not own the admin rights to create the extension\u0027s registry entry.", + "AlreadyExistingWarnText": "The project {0} already exists.", + "ListingServerDataErrorCaption": "Error while listing the server-data." } \ No newline at end of file diff --git a/nUpdate.Administration/UI/Controls/ActionList.cs b/nUpdate.Administration/UI/Controls/ActionList.cs index e0c61f93..73569d17 100644 --- a/nUpdate.Administration/UI/Controls/ActionList.cs +++ b/nUpdate.Administration/UI/Controls/ActionList.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ActionList.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Drawing; using System.Drawing.Text; diff --git a/nUpdate.Administration/UI/Controls/ButtonTextBox.cs b/nUpdate.Administration/UI/Controls/ButtonTextBox.cs index 7311733b..2acece47 100644 --- a/nUpdate.Administration/UI/Controls/ButtonTextBox.cs +++ b/nUpdate.Administration/UI/Controls/ButtonTextBox.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ButtonTextBox.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/UI/Controls/ChangelogPanel.cs b/nUpdate.Administration/UI/Controls/ChangelogPanel.cs index 677ce4c4..034a8b9e 100644 --- a/nUpdate.Administration/UI/Controls/ChangelogPanel.cs +++ b/nUpdate.Administration/UI/Controls/ChangelogPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ChangelogPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Windows.Forms; diff --git a/nUpdate.Administration/UI/Controls/CommandLink.cs b/nUpdate.Administration/UI/Controls/CommandLink.cs index 4928609c..9af0ee27 100644 --- a/nUpdate.Administration/UI/Controls/CommandLink.cs +++ b/nUpdate.Administration/UI/Controls/CommandLink.cs @@ -1,4 +1,5 @@ -// Copyright � Dominic Beger 2018 +// CommandLink.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.ComponentModel; diff --git a/nUpdate.Administration/UI/Controls/CueTextBox.cs b/nUpdate.Administration/UI/Controls/CueTextBox.cs index c613c436..8af9dad2 100644 --- a/nUpdate.Administration/UI/Controls/CueTextBox.cs +++ b/nUpdate.Administration/UI/Controls/CueTextBox.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// CueTextBox.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.ComponentModel; diff --git a/nUpdate.Administration/UI/Controls/ExpandButton.cs b/nUpdate.Administration/UI/Controls/ExpandButton.cs index aa7b878a..db308036 100644 --- a/nUpdate.Administration/UI/Controls/ExpandButton.cs +++ b/nUpdate.Administration/UI/Controls/ExpandButton.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ExpandButton.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.ComponentModel; diff --git a/nUpdate.Administration/UI/Controls/ExplorerListView.cs b/nUpdate.Administration/UI/Controls/ExplorerListView.cs index a8d89809..c47d9409 100644 --- a/nUpdate.Administration/UI/Controls/ExplorerListView.cs +++ b/nUpdate.Administration/UI/Controls/ExplorerListView.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ExplorerListView.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Reflection; diff --git a/nUpdate.Administration/UI/Controls/ExplorerListViewGroup.cs b/nUpdate.Administration/UI/Controls/ExplorerListViewGroup.cs index 6d467816..f5a8a1df 100644 --- a/nUpdate.Administration/UI/Controls/ExplorerListViewGroup.cs +++ b/nUpdate.Administration/UI/Controls/ExplorerListViewGroup.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ExplorerListViewGroup.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Runtime.InteropServices; diff --git a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/AeroTemplate.cs b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/AeroTemplate.cs index a4efedb9..69ec661a 100644 --- a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/AeroTemplate.cs +++ b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/AeroTemplate.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// AeroTemplate.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Drawing; using System.Drawing.Drawing2D; diff --git a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ArrowDirection.cs b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ArrowDirection.cs index 79d08d6b..b4aa305b 100644 --- a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ArrowDirection.cs +++ b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ArrowDirection.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ArrowDirection.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace ExplorerNavigationButton { diff --git a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ButtonState.cs b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ButtonState.cs index a89d5c84..204f6e84 100644 --- a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ButtonState.cs +++ b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ButtonState.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ButtonState.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace ExplorerNavigationButton { diff --git a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ButtonTheme.cs b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ButtonTheme.cs index 148306fa..a3593817 100644 --- a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ButtonTheme.cs +++ b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ButtonTheme.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ButtonTheme.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace ExplorerNavigationButton { diff --git a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ExplorerNavigationButton.cs b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ExplorerNavigationButton.cs index 93e61ffe..e82ec70e 100644 --- a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ExplorerNavigationButton.cs +++ b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/ExplorerNavigationButton.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ExplorerNavigationButton.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.ComponentModel; diff --git a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/MetroTemplate.cs b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/MetroTemplate.cs index f4368ad5..7b97870e 100644 --- a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/MetroTemplate.cs +++ b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/MetroTemplate.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// MetroTemplate.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Drawing; using System.Drawing.Drawing2D; diff --git a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/Template.cs b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/Template.cs index a57be11a..35d3921d 100644 --- a/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/Template.cs +++ b/nUpdate.Administration/UI/Controls/ExplorerNavigationButton/Template.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// Template.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/UI/Controls/ExplorerTreeNode.cs b/nUpdate.Administration/UI/Controls/ExplorerTreeNode.cs index 2d4c21c9..b38441c9 100644 --- a/nUpdate.Administration/UI/Controls/ExplorerTreeNode.cs +++ b/nUpdate.Administration/UI/Controls/ExplorerTreeNode.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ExplorerTreeNode.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Runtime.InteropServices; diff --git a/nUpdate.Administration/UI/Controls/ExplorerTreeView.cs b/nUpdate.Administration/UI/Controls/ExplorerTreeView.cs index e8178ffd..af0bf373 100644 --- a/nUpdate.Administration/UI/Controls/ExplorerTreeView.cs +++ b/nUpdate.Administration/UI/Controls/ExplorerTreeView.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ExplorerTreeView.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; @@ -150,6 +151,7 @@ protected override void WndProc(ref Message message) message.Result = IntPtr.Zero; return; } + case 20: message.Result = (IntPtr) 1; return; diff --git a/nUpdate.Administration/UI/Controls/ServerList.cs b/nUpdate.Administration/UI/Controls/ServerList.cs index 92e9c6c7..f8d4aa20 100644 --- a/nUpdate.Administration/UI/Controls/ServerList.cs +++ b/nUpdate.Administration/UI/Controls/ServerList.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ServerList.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Drawing; using System.Drawing.Text; diff --git a/nUpdate.Administration/UI/Controls/StatisticsChart.cs b/nUpdate.Administration/UI/Controls/StatisticsChart.cs index af8aaed0..ce352b82 100644 --- a/nUpdate.Administration/UI/Controls/StatisticsChart.cs +++ b/nUpdate.Administration/UI/Controls/StatisticsChart.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// StatisticsChart.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/UI/Controls/TablessTabControl.cs b/nUpdate.Administration/UI/Controls/TablessTabControl.cs index 6b86f7e8..88b29614 100644 --- a/nUpdate.Administration/UI/Controls/TablessTabControl.cs +++ b/nUpdate.Administration/UI/Controls/TablessTabControl.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// TablessTabControl.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Windows.Forms; diff --git a/nUpdate.Administration/UI/Dialogs/BaseDialog.cs b/nUpdate.Administration/UI/Dialogs/BaseDialog.cs index 0babd00e..23938a28 100644 --- a/nUpdate.Administration/UI/Dialogs/BaseDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/BaseDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// BaseDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Drawing; using System.Windows.Forms; diff --git a/nUpdate.Administration/UI/Dialogs/CredentialsDialog.cs b/nUpdate.Administration/UI/Dialogs/CredentialsDialog.cs index 3435ef99..2a00674a 100644 --- a/nUpdate.Administration/UI/Dialogs/CredentialsDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/CredentialsDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// CredentialsDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/UI/Dialogs/DirectorySearchDialog.cs b/nUpdate.Administration/UI/Dialogs/DirectorySearchDialog.cs index 06cebc77..73f5c6ef 100644 --- a/nUpdate.Administration/UI/Dialogs/DirectorySearchDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/DirectorySearchDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// DirectorySearchDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/UI/Dialogs/FeedbackDialog.cs b/nUpdate.Administration/UI/Dialogs/FeedbackDialog.cs index b040cabe..8cd97763 100644 --- a/nUpdate.Administration/UI/Dialogs/FeedbackDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/FeedbackDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// FeedbackDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/UI/Dialogs/FtpAssemblyInputDialog.cs b/nUpdate.Administration/UI/Dialogs/FtpAssemblyInputDialog.cs index 7624cf24..addf13c6 100644 --- a/nUpdate.Administration/UI/Dialogs/FtpAssemblyInputDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/FtpAssemblyInputDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// FtpAssemblyInputDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/UI/Dialogs/HistoryDialog.cs b/nUpdate.Administration/UI/Dialogs/HistoryDialog.cs index 6e6d3e93..1f45bea4 100644 --- a/nUpdate.Administration/UI/Dialogs/HistoryDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/HistoryDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// HistoryDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -58,7 +59,8 @@ private void InitializeLog() { var item = new ActionListItem { - ItemText = $"{logEntry.PackageVersion} - {logEntry.EntryTime}" + ItemText = $"{logEntry.PackageVersion} - {logEntry.EntryTime}" + + (logEntry.Username == null ? string.Empty : $" by {logEntry.Username}") }; switch (logEntry.Entry) @@ -75,6 +77,10 @@ private void InitializeLog() item.HeaderText = "Uploaded package"; item.ItemImage = Resources.Upload; break; + case LogEntry.Edit: + item.HeaderText = "Edit package"; + item.ItemImage = Resources.Edit; + break; } _logItemsStack.Push(item); @@ -126,7 +132,8 @@ private void saveToFileButton_Click(object sender, EventArgs e) var logEntryList = Project.Log.Select( logEntry => - $"{logEntry.PackageVersion}-{logEntry.Entry}-{logEntry.EntryTime}") + $"{logEntry.PackageVersion}-{logEntry.Entry}-{logEntry.EntryTime}" + + (logEntry.Username == null ? "" : $" by {logEntry.Username}")) .ToList(); File.WriteAllLines(sfd.FileName, logEntryList); } diff --git a/nUpdate.Administration/UI/Dialogs/InfoDialog.Designer.cs b/nUpdate.Administration/UI/Dialogs/InfoDialog.Designer.cs index cb8fe3f2..948b0400 100644 --- a/nUpdate.Administration/UI/Dialogs/InfoDialog.Designer.cs +++ b/nUpdate.Administration/UI/Dialogs/InfoDialog.Designer.cs @@ -107,7 +107,7 @@ private void InitializeComponent() this.label13.Name = "label13"; this.label13.Size = new System.Drawing.Size(75, 13); this.label13.TabIndex = 20; - this.label13.Text = "v3.3.1"; + this.label13.Text = "v3.4.1"; // // controlPanel1 // diff --git a/nUpdate.Administration/UI/Dialogs/InfoDialog.cs b/nUpdate.Administration/UI/Dialogs/InfoDialog.cs index 397dc77c..f4e6332f 100644 --- a/nUpdate.Administration/UI/Dialogs/InfoDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/InfoDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// InfoDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Diagnostics; diff --git a/nUpdate.Administration/UI/Dialogs/JsonEditorDialog.cs b/nUpdate.Administration/UI/Dialogs/JsonEditorDialog.cs index 09143c14..cf22a268 100644 --- a/nUpdate.Administration/UI/Dialogs/JsonEditorDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/JsonEditorDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// JsonEditorDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/UI/Dialogs/MainDialog.cs b/nUpdate.Administration/UI/Dialogs/MainDialog.cs index 64a51c3a..8f969e01 100644 --- a/nUpdate.Administration/UI/Dialogs/MainDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/MainDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// MainDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/UI/Dialogs/NewProjectDialog.cs b/nUpdate.Administration/UI/Dialogs/NewProjectDialog.cs index ac9836a4..8344b5f4 100644 --- a/nUpdate.Administration/UI/Dialogs/NewProjectDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/NewProjectDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// NewProjectDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/UI/Dialogs/PackageAddDialog.Designer.cs b/nUpdate.Administration/UI/Dialogs/PackageAddDialog.Designer.cs index 81e74a6c..09bae675 100644 --- a/nUpdate.Administration/UI/Dialogs/PackageAddDialog.Designer.cs +++ b/nUpdate.Administration/UI/Dialogs/PackageAddDialog.Designer.cs @@ -82,7 +82,8 @@ private void InitializeComponent() System.Windows.Forms.TreeNode treeNode5 = new System.Windows.Forms.TreeNode("General", 2, 2); System.Windows.Forms.TreeNode treeNode6 = new System.Windows.Forms.TreeNode("Changelog", 3, 3); System.Windows.Forms.TreeNode treeNode7 = new System.Windows.Forms.TreeNode("Availability", 0, 0); - System.Windows.Forms.TreeNode treeNode8 = new System.Windows.Forms.TreeNode("Operations", 4, 4); + System.Windows.Forms.TreeNode treeNode8 = new System.Windows.Forms.TreeNode("Conditions", 4, 4); + System.Windows.Forms.TreeNode treeNode9 = new System.Windows.Forms.TreeNode("Operations", 17, 17); this.filesImageList = new System.Windows.Forms.ImageList(this.components); this.categoryImageList = new System.Windows.Forms.ImageList(this.components); this.cancelToolTip = new System.Windows.Forms.ToolTip(this.components); @@ -92,18 +93,18 @@ private void InitializeComponent() this.loadingLabel = new System.Windows.Forms.Label(); this.createButton = new System.Windows.Forms.Button(); this.cancelButton = new System.Windows.Forms.Button(); - this.controlPanel1 = new BottomPanel(); + this.controlPanel1 = new nUpdate.Internal.UI.Controls.BottomPanel(); this.categoryTabControl = new nUpdate.Administration.UI.Controls.TablessTabControl(); this.generalTabPage = new System.Windows.Forms.TabPage(); this.generalPanel = new System.Windows.Forms.Panel(); this.includeIntoStatisticsInfoLabel = new System.Windows.Forms.Label(); this.includeIntoStatisticsCheckBox = new System.Windows.Forms.CheckBox(); - this.line2 = new Line(); + this.line2 = new nUpdate.Internal.UI.Controls.Line(); this.developmentBuildNumericUpDown = new System.Windows.Forms.NumericUpDown(); this.necessaryUpdateInfoLabel = new System.Windows.Forms.Label(); this.necessaryUpdateCheckBox = new System.Windows.Forms.CheckBox(); - this.line3 = new Line(); - this.line1 = new Line(); + this.line3 = new nUpdate.Internal.UI.Controls.Line(); + this.line1 = new nUpdate.Internal.UI.Controls.Line(); this.architectureInfoLabel = new System.Windows.Forms.Label(); this.buildNumericUpDown = new System.Windows.Forms.NumericUpDown(); this.descriptionLabel = new System.Windows.Forms.Label(); @@ -164,7 +165,6 @@ private void InitializeComponent() this.Description = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.replaceFilesTabPage = new System.Windows.Forms.TabPage(); this.filesPanel = new System.Windows.Forms.Panel(); - this.differentialUpdateCheckBox = new System.Windows.Forms.CheckBox(); this.filesDataTreeView = new nUpdate.Administration.UI.Controls.ExplorerTreeView(); this.replaceFilesToolStrip = new System.Windows.Forms.ToolStrip(); this.addFolderButton = new System.Windows.Forms.ToolStripSplitButton(); @@ -181,6 +181,15 @@ private void InitializeComponent() this.filesList = new System.Windows.Forms.ListView(); this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.conditionsTabPage = new System.Windows.Forms.TabPage(); + this.conditionHelpLinkLabel = new System.Windows.Forms.LinkLabel(); + this.line4 = new nUpdate.Internal.UI.Controls.Line(); + this.rolloutConditionModeComboBox = new System.Windows.Forms.ComboBox(); + this.rolloutConditionModeLabel = new System.Windows.Forms.Label(); + this.conditionsDataGridView = new System.Windows.Forms.DataGridView(); + this.Key = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.Value = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.Negative = new System.Windows.Forms.DataGridViewCheckBoxColumn(); this.categoryTreeView = new nUpdate.Administration.UI.Controls.ExplorerTreeView(); this.loadingPanel.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); @@ -210,6 +219,8 @@ private void InitializeComponent() this.replaceFilesTabPage.SuspendLayout(); this.filesPanel.SuspendLayout(); this.replaceFilesToolStrip.SuspendLayout(); + this.conditionsTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.conditionsDataGridView)).BeginInit(); this.SuspendLayout(); // // filesImageList @@ -227,7 +238,7 @@ private void InitializeComponent() this.categoryImageList.Images.SetKeyName(1, "blue-documents-stack.png"); this.categoryImageList.Images.SetKeyName(2, "property.png"); this.categoryImageList.Images.SetKeyName(3, "document--pencil.png"); - this.categoryImageList.Images.SetKeyName(4, "node-delete-previous.png"); + this.categoryImageList.Images.SetKeyName(4, "node-select.png"); this.categoryImageList.Images.SetKeyName(5, "sofa--arrow.png"); this.categoryImageList.Images.SetKeyName(6, "sofa--minus.png"); this.categoryImageList.Images.SetKeyName(7, "system-monitor--minus.png"); @@ -240,6 +251,7 @@ private void InitializeComponent() this.categoryImageList.Images.SetKeyName(14, "wall--plus.png"); this.categoryImageList.Images.SetKeyName(15, "application--arrow.png"); this.categoryImageList.Images.SetKeyName(16, "script-code.png"); + this.categoryImageList.Images.SetKeyName(17, "toolbox.png"); // // cancelToolTip // @@ -330,10 +342,11 @@ private void InitializeComponent() this.categoryTabControl.Controls.Add(this.availabilityTabPage); this.categoryTabControl.Controls.Add(this.operationsTabPage); this.categoryTabControl.Controls.Add(this.replaceFilesTabPage); + this.categoryTabControl.Controls.Add(this.conditionsTabPage); this.categoryTabControl.Location = new System.Drawing.Point(151, 24); this.categoryTabControl.Name = "categoryTabControl"; this.categoryTabControl.SelectedIndex = 0; - this.categoryTabControl.Size = new System.Drawing.Size(481, 262); + this.categoryTabControl.Size = new System.Drawing.Size(481, 257); this.categoryTabControl.TabIndex = 44; // // generalTabPage @@ -342,7 +355,7 @@ private void InitializeComponent() this.generalTabPage.Location = new System.Drawing.Point(4, 22); this.generalTabPage.Name = "generalTabPage"; this.generalTabPage.Padding = new System.Windows.Forms.Padding(3); - this.generalTabPage.Size = new System.Drawing.Size(473, 236); + this.generalTabPage.Size = new System.Drawing.Size(473, 231); this.generalTabPage.TabIndex = 0; this.generalTabPage.Text = "General"; this.generalTabPage.UseVisualStyleBackColor = true; @@ -404,7 +417,7 @@ private void InitializeComponent() // line2 // this.line2.BackColor = System.Drawing.SystemColors.Window; - this.line2.LineAlignment = Line.Alignment.Horizontal; + this.line2.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line2.Location = new System.Drawing.Point(9, 323); this.line2.Name = "line2"; this.line2.Size = new System.Drawing.Size(437, 10); @@ -444,7 +457,7 @@ private void InitializeComponent() // line3 // this.line3.BackColor = System.Drawing.SystemColors.Window; - this.line3.LineAlignment = Line.Alignment.Horizontal; + this.line3.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line3.Location = new System.Drawing.Point(10, 231); this.line3.Name = "line3"; this.line3.Size = new System.Drawing.Size(437, 10); @@ -454,7 +467,7 @@ private void InitializeComponent() // line1 // this.line1.BackColor = System.Drawing.SystemColors.Window; - this.line1.LineAlignment = Line.Alignment.Horizontal; + this.line1.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line1.Location = new System.Drawing.Point(7, 153); this.line1.Name = "line1"; this.line1.Size = new System.Drawing.Size(437, 14); @@ -467,7 +480,7 @@ private void InitializeComponent() this.architectureInfoLabel.ForeColor = System.Drawing.SystemColors.ControlDarkDark; this.architectureInfoLabel.Location = new System.Drawing.Point(9, 198); this.architectureInfoLabel.Name = "architectureInfoLabel"; - this.architectureInfoLabel.Size = new System.Drawing.Size(438, 26); + this.architectureInfoLabel.Size = new System.Drawing.Size(437, 26); this.architectureInfoLabel.TabIndex = 20; this.architectureInfoLabel.Text = "Sets if the update package should only run on special architectures. To set any t" + "ype \r\nof architecture, choose \"AnyCPU\" as entry."; @@ -543,7 +556,7 @@ private void InitializeComponent() this.publishInfoLabel.ForeColor = System.Drawing.SystemColors.ControlDarkDark; this.publishInfoLabel.Location = new System.Drawing.Point(8, 120); this.publishInfoLabel.Name = "publishInfoLabel"; - this.publishInfoLabel.Size = new System.Drawing.Size(449, 26); + this.publishInfoLabel.Size = new System.Drawing.Size(448, 26); this.publishInfoLabel.TabIndex = 16; this.publishInfoLabel.Text = "Sets if the package should be uploaded yet. You can upload it later, if you disab" + "le this\r\noption. The update package will be saved locally on your PC then."; @@ -566,7 +579,7 @@ private void InitializeComponent() this.versionLabel.AutoSize = true; this.versionLabel.Location = new System.Drawing.Point(8, 39); this.versionLabel.Name = "versionLabel"; - this.versionLabel.Size = new System.Drawing.Size(49, 13); + this.versionLabel.Size = new System.Drawing.Size(48, 13); this.versionLabel.TabIndex = 2; this.versionLabel.Text = "Version:"; // @@ -622,7 +635,7 @@ private void InitializeComponent() this.changelogTabPage.Location = new System.Drawing.Point(4, 22); this.changelogTabPage.Name = "changelogTabPage"; this.changelogTabPage.Padding = new System.Windows.Forms.Padding(3); - this.changelogTabPage.Size = new System.Drawing.Size(473, 236); + this.changelogTabPage.Size = new System.Drawing.Size(473, 231); this.changelogTabPage.TabIndex = 1; this.changelogTabPage.Text = "Changelog"; this.changelogTabPage.UseVisualStyleBackColor = true; @@ -836,7 +849,7 @@ private void InitializeComponent() this.availabilityTabPage.Location = new System.Drawing.Point(4, 22); this.availabilityTabPage.Name = "availabilityTabPage"; this.availabilityTabPage.Padding = new System.Windows.Forms.Padding(3); - this.availabilityTabPage.Size = new System.Drawing.Size(473, 236); + this.availabilityTabPage.Size = new System.Drawing.Size(473, 231); this.availabilityTabPage.TabIndex = 2; this.availabilityTabPage.Text = "Availability"; this.availabilityTabPage.UseVisualStyleBackColor = true; @@ -973,7 +986,7 @@ private void InitializeComponent() this.operationsTabPage.Location = new System.Drawing.Point(4, 22); this.operationsTabPage.Name = "operationsTabPage"; this.operationsTabPage.Padding = new System.Windows.Forms.Padding(3); - this.operationsTabPage.Size = new System.Drawing.Size(473, 236); + this.operationsTabPage.Size = new System.Drawing.Size(473, 231); this.operationsTabPage.TabIndex = 3; this.operationsTabPage.Text = "Operations"; this.operationsTabPage.UseVisualStyleBackColor = true; @@ -1075,14 +1088,13 @@ private void InitializeComponent() this.replaceFilesTabPage.Location = new System.Drawing.Point(4, 22); this.replaceFilesTabPage.Name = "replaceFilesTabPage"; this.replaceFilesTabPage.Padding = new System.Windows.Forms.Padding(3); - this.replaceFilesTabPage.Size = new System.Drawing.Size(473, 236); + this.replaceFilesTabPage.Size = new System.Drawing.Size(473, 231); this.replaceFilesTabPage.TabIndex = 4; this.replaceFilesTabPage.Text = "ReplaceFiles"; this.replaceFilesTabPage.UseVisualStyleBackColor = true; // // filesPanel // - this.filesPanel.Controls.Add(this.differentialUpdateCheckBox); this.filesPanel.Controls.Add(this.filesDataTreeView); this.filesPanel.Controls.Add(this.replaceFilesToolStrip); this.filesPanel.Controls.Add(this.filesList); @@ -1091,17 +1103,6 @@ private void InitializeComponent() this.filesPanel.Size = new System.Drawing.Size(474, 235); this.filesPanel.TabIndex = 41; // - // differentialUpdateCheckBox - // - this.differentialUpdateCheckBox.AutoSize = true; - this.differentialUpdateCheckBox.Location = new System.Drawing.Point(388, 7); - this.differentialUpdateCheckBox.Name = "differentialUpdateCheckBox"; - this.differentialUpdateCheckBox.Size = new System.Drawing.Size(84, 17); - this.differentialUpdateCheckBox.TabIndex = 6; - this.differentialUpdateCheckBox.Text = "Differential"; - this.differentialUpdateCheckBox.UseVisualStyleBackColor = true; - this.differentialUpdateCheckBox.Visible = false; - // // filesDataTreeView // this.filesDataTreeView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; @@ -1268,6 +1269,101 @@ private void InitializeComponent() this.columnHeader2.Text = "Size"; this.columnHeader2.Width = 147; // + // conditionsTabPage + // + this.conditionsTabPage.Controls.Add(this.conditionHelpLinkLabel); + this.conditionsTabPage.Controls.Add(this.line4); + this.conditionsTabPage.Controls.Add(this.rolloutConditionModeComboBox); + this.conditionsTabPage.Controls.Add(this.rolloutConditionModeLabel); + this.conditionsTabPage.Controls.Add(this.conditionsDataGridView); + this.conditionsTabPage.Location = new System.Drawing.Point(4, 22); + this.conditionsTabPage.Name = "conditionsTabPage"; + this.conditionsTabPage.Padding = new System.Windows.Forms.Padding(3); + this.conditionsTabPage.Size = new System.Drawing.Size(473, 231); + this.conditionsTabPage.TabIndex = 5; + this.conditionsTabPage.Text = "Rollout conditions"; + this.conditionsTabPage.UseVisualStyleBackColor = true; + // + // conditionHelpLinkLabel + // + this.conditionHelpLinkLabel.ActiveLinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(153)))), ((int)(((byte)(255))))); + this.conditionHelpLinkLabel.AutoSize = true; + this.conditionHelpLinkLabel.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(204))))); + this.conditionHelpLinkLabel.Location = new System.Drawing.Point(433, 14); + this.conditionHelpLinkLabel.Name = "conditionHelpLinkLabel"; + this.conditionHelpLinkLabel.Size = new System.Drawing.Size(31, 13); + this.conditionHelpLinkLabel.TabIndex = 6; + this.conditionHelpLinkLabel.TabStop = true; + this.conditionHelpLinkLabel.Text = "Help"; + this.conditionHelpLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.conditionHelpLinkLabel_LinkClicked); + // + // line4 + // + this.line4.BackColor = System.Drawing.SystemColors.Window; + this.line4.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Vertical; + this.line4.Location = new System.Drawing.Point(420, 7); + this.line4.Name = "line4"; + this.line4.Size = new System.Drawing.Size(10, 23); + this.line4.TabIndex = 3; + this.line4.Text = "line4"; + // + // rolloutConditionModeComboBox + // + this.rolloutConditionModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.rolloutConditionModeComboBox.FormattingEnabled = true; + this.rolloutConditionModeComboBox.Items.AddRange(new object[] { + "One positive condition must be met for different keys", + "All positive conditions must be met for different keys"}); + this.rolloutConditionModeComboBox.Location = new System.Drawing.Point(106, 11); + this.rolloutConditionModeComboBox.Name = "rolloutConditionModeComboBox"; + this.rolloutConditionModeComboBox.Size = new System.Drawing.Size(305, 21); + this.rolloutConditionModeComboBox.TabIndex = 2; + // + // rolloutConditionModeLabel + // + this.rolloutConditionModeLabel.AutoSize = true; + this.rolloutConditionModeLabel.Location = new System.Drawing.Point(6, 14); + this.rolloutConditionModeLabel.Name = "rolloutConditionModeLabel"; + this.rolloutConditionModeLabel.Size = new System.Drawing.Size(94, 13); + this.rolloutConditionModeLabel.TabIndex = 1; + this.rolloutConditionModeLabel.Text = "Condition mode:"; + // + // conditionsDataGridView + // + this.conditionsDataGridView.BackgroundColor = System.Drawing.SystemColors.Window; + this.conditionsDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.conditionsDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.Key, + this.Value, + this.Negative}); + this.conditionsDataGridView.Location = new System.Drawing.Point(9, 40); + this.conditionsDataGridView.Name = "conditionsDataGridView"; + this.conditionsDataGridView.RowHeadersVisible = false; + this.conditionsDataGridView.Size = new System.Drawing.Size(455, 178); + this.conditionsDataGridView.TabIndex = 0; + // + // Key + // + this.Key.DataPropertyName = "Key"; + this.Key.HeaderText = "Key"; + this.Key.Name = "Key"; + this.Key.Width = 152; + // + // Value + // + this.Value.DataPropertyName = "Value"; + this.Value.HeaderText = "Value"; + this.Value.Name = "Value"; + this.Value.Width = 152; + // + // Negative + // + this.Negative.DataPropertyName = "IsNegativeCondition"; + this.Negative.HeaderText = "Negative"; + this.Negative.Name = "Negative"; + this.Negative.ToolTipText = "When checked, this conditions must not be met."; + this.Negative.Width = 152; + // // categoryTreeView // this.categoryTreeView.AllowDrop = true; @@ -1294,14 +1390,19 @@ private void InitializeComponent() treeNode7.SelectedImageIndex = 0; treeNode7.Text = "Availability"; treeNode8.ImageIndex = 4; - treeNode8.Name = "operationsNode"; + treeNode8.Name = "conditionNode"; treeNode8.SelectedImageIndex = 4; - treeNode8.Text = "Operations"; + treeNode8.Text = "Conditions"; + treeNode9.ImageIndex = 17; + treeNode9.Name = "operationsNode"; + treeNode9.SelectedImageIndex = 17; + treeNode9.Text = "Operations"; this.categoryTreeView.Nodes.AddRange(new System.Windows.Forms.TreeNode[] { treeNode5, treeNode6, treeNode7, - treeNode8}); + treeNode8, + treeNode9}); this.categoryTreeView.SelectedImageIndex = 0; this.categoryTreeView.ShowLines = false; this.categoryTreeView.Size = new System.Drawing.Size(129, 231); @@ -1366,9 +1467,11 @@ private void InitializeComponent() this.operationsPanel.ResumeLayout(false); this.replaceFilesTabPage.ResumeLayout(false); this.filesPanel.ResumeLayout(false); - this.filesPanel.PerformLayout(); this.replaceFilesToolStrip.ResumeLayout(false); this.replaceFilesToolStrip.PerformLayout(); + this.conditionsTabPage.ResumeLayout(false); + this.conditionsTabPage.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.conditionsDataGridView)).EndInit(); this.ResumeLayout(false); } @@ -1472,8 +1575,15 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripSeparator toolStripSeparator9; private System.Windows.Forms.ToolStripButton infoButton; private System.Windows.Forms.ToolStripMenuItem addFolderContentToolStripMenuItem; - private System.Windows.Forms.CheckBox differentialUpdateCheckBox; private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; - + private System.Windows.Forms.TabPage conditionsTabPage; + private System.Windows.Forms.DataGridView conditionsDataGridView; + private System.Windows.Forms.ComboBox rolloutConditionModeComboBox; + private System.Windows.Forms.Label rolloutConditionModeLabel; + private System.Windows.Forms.DataGridViewTextBoxColumn Key; + private System.Windows.Forms.DataGridViewTextBoxColumn Value; + private System.Windows.Forms.DataGridViewCheckBoxColumn Negative; + private Line line4; + private System.Windows.Forms.LinkLabel conditionHelpLinkLabel; } } \ No newline at end of file diff --git a/nUpdate.Administration/UI/Dialogs/PackageAddDialog.cs b/nUpdate.Administration/UI/Dialogs/PackageAddDialog.cs index 97b68003..522c4d88 100644 --- a/nUpdate.Administration/UI/Dialogs/PackageAddDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/PackageAddDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// PackageAddDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -90,6 +91,11 @@ public partial class PackageAddDialog : BaseDialog, IAsyncSupportable, IResettab private bool _uploadCancelled; + /// + /// Gets or sets the rollout conditions. + /// + public List Conditions = new List(); + public PackageAddDialog() { InitializeComponent(); @@ -115,6 +121,28 @@ public PackageAddDialog() /// public SecureString SqlPassword { get; set; } + /// + /// Enables or disables the UI controls. + /// + /// Sets the activation state. + public void SetUiState(bool enabled) + { + _allowCancel = enabled; + try + { + Invoke(new Action(() => + { + foreach (var c in from Control c in Controls where c.Visible select c) c.Enabled = enabled; + + loadingPanel.Visible = !enabled; + })); + } + catch (InvalidOperationException) + { + // Doesn't interest us anymore as the dialog has been closed + } + } + /// /// Resets the data set. /// @@ -144,7 +172,7 @@ public void Reset() $"UID='{Project.SqlUsername}';" + $"PASSWORD='{SqlPassword.ConvertToInsecureString()}';"; - bool connectingFailed = false; + var connectingFailed = false; MySqlConnection deleteConnection = null; try { @@ -211,28 +239,6 @@ public void Reset() DialogResult = DialogResult.OK; } - /// - /// Enables or disables the UI controls. - /// - /// Sets the activation state. - public void SetUiState(bool enabled) - { - _allowCancel = enabled; - try - { - Invoke(new Action(() => - { - foreach (var c in from Control c in Controls where c.Visible select c) c.Enabled = enabled; - - loadingPanel.Visible = !enabled; - })); - } - catch (InvalidOperationException) - { - // Doesn't interest us anymore as the dialog has been closed - } - } - private void addFilesButton_Click(object sender, EventArgs e) { if (filesDataTreeView.SelectedNode == null) @@ -409,6 +415,9 @@ private void categoryTreeView_AfterSelect(object sender, TreeViewEventArgs e) categoryTabControl.SelectedTab = availabilityTabPage; break; case 3: + categoryTabControl.SelectedTab = conditionsTabPage; + break; + case 4: categoryTabControl.SelectedTab = operationsTabPage; break; } @@ -420,7 +429,7 @@ private void categoryTreeView_AfterSelect(object sender, TreeViewEventArgs e) break; default: categoryTabControl.SelectedTab = - categoryTabControl.TabPages[4 + categoryTreeView.SelectedNode.Index]; + categoryTabControl.TabPages[(int) categoryTreeView.SelectedNode.Tag]; break; } } @@ -428,33 +437,40 @@ private void categoryTreeView_AfterSelect(object sender, TreeViewEventArgs e) private void categoryTreeView_DragDrop(object sender, DragEventArgs e) { var nodeToDropIn = categoryTreeView.GetNodeAt(categoryTreeView.PointToClient(new Point(e.X, e.Y))); - if (nodeToDropIn == null || nodeToDropIn.Index != 3) // Operations-node + if (nodeToDropIn == null || nodeToDropIn.Index != 4) // Operations-node return; var data = e.Data.GetData(typeof(string)); if (data == null) return; + TreeNode node; switch (data.ToString()) { case "DeleteFile": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _deleteNode.Clone()); + node = (TreeNode) _deleteNode.Clone(); var deletePage = new TabPage("Delete file") {BackColor = SystemColors.Window}; deletePage.Controls.Add(new FileDeleteOperationPanel()); categoryTabControl.TabPages.Add(deletePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(deletePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "RenameFile": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _renameNode.Clone()); + node = (TreeNode) _renameNode.Clone(); var renamePage = new TabPage("Rename file") {BackColor = SystemColors.Window}; renamePage.Controls.Add(new FileRenameOperationPanel()); categoryTabControl.TabPages.Add(renamePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(renamePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "CreateRegistrySubKey": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _createRegistrySubKeyNode.Clone()); + node = (TreeNode) _createRegistrySubKeyNode.Clone(); var createRegistrySubKeyPage = new TabPage("Create registry subkey") { @@ -462,10 +478,13 @@ private void categoryTreeView_DragDrop(object sender, DragEventArgs e) }; createRegistrySubKeyPage.Controls.Add(new RegistrySubKeyCreateOperationPanel()); categoryTabControl.TabPages.Add(createRegistrySubKeyPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(createRegistrySubKeyPage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "DeleteRegistrySubKey": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _deleteRegistrySubKeyNode.Clone()); + node = (TreeNode) _deleteRegistrySubKeyNode.Clone(); var deleteRegistrySubKeyPage = new TabPage("Delete registry subkey") { @@ -473,59 +492,83 @@ private void categoryTreeView_DragDrop(object sender, DragEventArgs e) }; deleteRegistrySubKeyPage.Controls.Add(new RegistrySubKeyDeleteOperationPanel()); categoryTabControl.TabPages.Add(deleteRegistrySubKeyPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(deleteRegistrySubKeyPage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "SetRegistryValue": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _setRegistryValueNode.Clone()); + node = (TreeNode) _setRegistryValueNode.Clone(); var setRegistryValuePage = new TabPage("Set registry value") {BackColor = SystemColors.Window}; setRegistryValuePage.Controls.Add(new RegistrySetValueOperationPanel()); categoryTabControl.TabPages.Add(setRegistryValuePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(setRegistryValuePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "DeleteRegistryValue": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _deleteRegistryValueNode.Clone()); + node = (TreeNode) _deleteRegistryValueNode.Clone(); var deleteRegistryValuePage = new TabPage("Delete registry value") {BackColor = SystemColors.Window}; deleteRegistryValuePage.Controls.Add(new RegistryDeleteValueOperationPanel()); categoryTabControl.TabPages.Add(deleteRegistryValuePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(deleteRegistryValuePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "StartProcess": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _startProcessNode.Clone()); + node = (TreeNode) _startProcessNode.Clone(); var startProcessPage = new TabPage("Start process") {BackColor = SystemColors.Window}; startProcessPage.Controls.Add(new ProcessStartOperationPanel()); categoryTabControl.TabPages.Add(startProcessPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(startProcessPage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "TerminateProcess": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _terminateProcessNode.Clone()); + node = (TreeNode) _terminateProcessNode.Clone(); var terminateProcessPage = new TabPage("Terminate process") {BackColor = SystemColors.Window}; terminateProcessPage.Controls.Add(new ProcessStopOperationPanel()); categoryTabControl.TabPages.Add(terminateProcessPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(terminateProcessPage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "StartService": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _startServiceNode.Clone()); + node = (TreeNode) _startServiceNode.Clone(); var startServicePage = new TabPage("Start service") {BackColor = SystemColors.Window}; startServicePage.Controls.Add(new ServiceStartOperationPanel()); categoryTabControl.TabPages.Add(startServicePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(startServicePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "StopService": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _stopServiceNode.Clone()); + node = (TreeNode) _stopServiceNode.Clone(); var stopServicePage = new TabPage("Stop service") {BackColor = SystemColors.Window}; stopServicePage.Controls.Add(new ServiceStopOperationPanel()); categoryTabControl.TabPages.Add(stopServicePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(stopServicePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "ExecuteScript": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _executeScriptNode.Clone()); + node = (TreeNode) _executeScriptNode.Clone(); var executeScriptPage = new TabPage("Stop service") {BackColor = SystemColors.Window}; executeScriptPage.Controls.Add(new ScriptExecuteOperationPanel()); categoryTabControl.TabPages.Add(executeScriptPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(executeScriptPage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; } } @@ -540,24 +583,32 @@ private void categoryTreeView_KeyDown(object sender, KeyEventArgs e) if (categoryTreeView.SelectedNode?.Parent == null) return; + TreeNode selectedNode = categoryTreeView.SelectedNode; if (e.Control && e.KeyCode == Keys.Up) { - if (categoryTreeView.SelectedNode.Text != "Replace file/folder" && - categoryTreeView.SelectedNode.Index != 1) - categoryTreeView.SelectedNode.MoveUp(); + selectedNode.MoveUp(); + categoryTreeView.SelectedNode = selectedNode; + return; } else if (e.Control && e.KeyCode == Keys.Down) { - if (categoryTreeView.SelectedNode.Text != "Replace file/folder") - categoryTreeView.SelectedNode.MoveDown(); + selectedNode.MoveDown(); + categoryTreeView.SelectedNode = selectedNode; + return; } - if (e.KeyCode != Keys.Delete && e.KeyCode != Keys.Back || categoryTreeView.SelectedNode.Parent == null || - categoryTreeView.SelectedNode.Text == "Replace file/folder") + if (e.KeyCode != Keys.Delete && e.KeyCode != Keys.Back || + categoryTreeView.SelectedNode.Equals(_replaceNode)) return; - categoryTabControl.TabPages.Remove( - categoryTabControl.TabPages[4 + categoryTreeView.SelectedNode.Index]); + + int index = (int) categoryTreeView.SelectedNode.Tag; + foreach (var node in categoryTreeView.Nodes[4].Nodes.Cast() + .Where(n => !n.Equals(_replaceNode) && (int) n.Tag > index)) + node.Tag = (int) node.Tag - 1; + categoryTreeView.SelectedNode.Remove(); + categoryTabControl.TabPages.Remove( + categoryTabControl.TabPages[index]); } private void changelogClearButton_Click(object sender, EventArgs e) @@ -770,19 +821,19 @@ private void createPackageButton_Click(object sender, EventArgs e) } if (!filesDataTreeView.Nodes.Cast().Any(node => node.Nodes.Count > 0) && - categoryTreeView.Nodes[3].Nodes.Count <= 1) + categoryTreeView.Nodes[4].Nodes.Count <= 1) { Popup.ShowPopup(this, SystemIcons.Error, "No files and/or folders or operations set.", "Please specify some files and/or folders that should be included or operations into the package.", PopupButtons.Ok); filesPanel.BringToFront(); - categoryTreeView.SelectedNode = categoryTreeView.Nodes[3].Nodes[0]; + categoryTreeView.SelectedNode = _replaceNode; return; } foreach ( var tabPage in - from tabPage in categoryTabControl.TabPages.Cast().Where(item => item.TabIndex > 4) + from tabPage in categoryTabControl.TabPages.Cast().Where(item => item.TabIndex > 5) let operationPanel = tabPage.Controls[0] as IOperationPanel where operationPanel != null && !operationPanel.IsValid select tabPage) @@ -791,8 +842,8 @@ from tabPage in categoryTabControl.TabPages.Cast().Where(item => item.T "Please make sure to fill out all required fields correctly.", PopupButtons.Ok); categoryTreeView.SelectedNode = - categoryTreeView.Nodes[3].Nodes.Cast() - .First(item => item.Index == tabPage.TabIndex - 4); + categoryTreeView.Nodes[4].Nodes.Cast() + .First(item => (int) item.Tag == categoryTabControl.TabPages.IndexOf(tabPage)); return; } @@ -957,6 +1008,27 @@ await Task.Factory.StartNew(() => InitializeArchiveContents(filesDataTreeView.Nodes[2], "Temp"); InitializeArchiveContents(filesDataTreeView.Nodes[3], "Desktop"); + string operationFile = Path.Combine(_packageFolder, "operations.json"); + var operations = new List(); + + Invoke(new Action(() => + { + foreach (TreeNode node in categoryTreeView.Nodes[4].Nodes) + { + if (node.Equals(_replaceNode)) + continue; + + bool execBefore = categoryTreeView.Nodes[4].Nodes.IndexOf(_replaceNode) > node.Index; + var panel = (IOperationPanel) categoryTabControl.TabPages[(int) node.Tag].Controls[0]; + Operation op = panel.Operation; + op.ExecuteBeforeReplacingFiles = execBefore; + operations.Add(op); + } + })); + + File.WriteAllText(operationFile, Serializer.Serialize(operations)); + _zip.AddFile(operationFile, string.Empty); + //Invoke(new Action(() => loadingLabel.Text = "Initializing hash file...")); //try @@ -1019,15 +1091,6 @@ var tabPage in _configuration.NecessaryUpdate = _necessaryUpdate; _configuration.Architecture = (Architecture) _architectureIndex; - _configuration.Operations = new List(); - Invoke(new Action(() => - { - foreach (var operationPanel in from TreeNode node in categoryTreeView.Nodes[3].Nodes - where node.Index != 0 - select (IOperationPanel) categoryTabControl.TabPages[4 + node.Index].Controls[0]) - _configuration.Operations.Add(operationPanel.Operation); - })); - Invoke(new Action(() => loadingLabel.Text = "Signing package...")); try @@ -1086,8 +1149,18 @@ var tabPage in return; } + + Invoke(new Action(() => _configuration.RolloutConditionMode = + (RolloutConditionMode) rolloutConditionModeComboBox.SelectedIndex)); + _configuration.RolloutConditions = new List(); + foreach (var conditionItem in Conditions) + if (!string.IsNullOrEmpty(conditionItem.Key) && !string.IsNullOrEmpty(conditionItem.Value)) + _configuration.RolloutConditions.Add(new RolloutCondition(conditionItem.Key, + conditionItem.Value, conditionItem.IsNegativeCondition)); + configurationList.Add(_configuration); + try { File.WriteAllText(_updateConfigFile, Serializer.Serialize(configurationList)); @@ -1378,8 +1451,8 @@ private void PackageAddDialog_Load(object sender, EventArgs e) _zip.UseZip64WhenSaving = Zip64Option.AsNecessary; _updateLog.Project = Project; - categoryTreeView.Nodes[3].Nodes.Add(_replaceNode); - categoryTreeView.Nodes[3].Toggle(); + categoryTreeView.Nodes[4].Nodes.Add(_replaceNode); + categoryTreeView.Nodes[4].Toggle(); unsupportedVersionsListBox.DataSource = _unsupportedVersionLiteralsBindingList; var devStages = Enum.GetValues(typeof(DevelopmentalStage)); @@ -1398,6 +1471,7 @@ private void PackageAddDialog_Load(object sender, EventArgs e) architectureComboBox.SelectedIndex = 2; categoryTreeView.SelectedNode = categoryTreeView.Nodes[0]; developmentalStageComboBox.SelectedIndex = 3; + rolloutConditionModeComboBox.SelectedIndex = 0; unsupportedVersionsPanel.Enabled = false; _publishUpdate = publishCheckBox.Checked; @@ -1409,6 +1483,10 @@ private void PackageAddDialog_Load(object sender, EventArgs e) buildNumericUpDown.Maximum = decimal.MaxValue; revisionNumericUpDown.Maximum = decimal.MaxValue; + conditionsDataGridView.AutoGenerateColumns = false; + var source = new BindingSource(new BindingList(Conditions) {AllowNew = true}, null); + conditionsDataGridView.DataSource = source; + try { if (!string.IsNullOrEmpty(Project.AssemblyVersionPath)) @@ -1450,7 +1528,7 @@ private void ProgressChanged(object sender, TransferProgressEventArgs e) new Action( () => loadingLabel.Text = - $"Uploading package... {e.PercentComplete}% | {e.BytesPerSecond / 1024}KB/s")); + $"Uploading package... {e.PercentComplete}% | {e.BytesPerSecond / 1024}KiB/s")); if (_uploadCancelled) Invoke(new Action(() => { loadingLabel.Text = "Cancelling upload..."; })); } @@ -1517,6 +1595,11 @@ private void unregisteredTrademarkToolStripMenuItem_Click(object sender, EventAr } } + private void conditionHelpLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + // TODO: Implement + } + #region "Localization" //private string configDownloadErrorCaption; diff --git a/nUpdate.Administration/UI/Dialogs/PackageAddDialog.resx b/nUpdate.Administration/UI/Dialogs/PackageAddDialog.resx index 64d5f1b9..c5391d5b 100644 --- a/nUpdate.Administration/UI/Dialogs/PackageAddDialog.resx +++ b/nUpdate.Administration/UI/Dialogs/PackageAddDialog.resx @@ -125,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAm - CAAAAk1TRnQBSQFMAgEBAgEAAWgBDgFoAQ4BEAEAARABAAT/AREBAAj/AUIBTQE2BwABNgMAASgDAAFA + CAAAAk1TRnQBSQFMAgEBAgEAAagBDgGoAQ4BEAEAARABAAT/AREBAAj/AUIBTQE2BwABNgMAASgDAAFA AwABEAMAAQEBAAEQBgABCBIAAf8BfwHeAXsBsgFeAW0BWgFtAVoBbQFaAW0BWgFtAVoBbQFaAW0BWgFt AVoBbQFaAW0BWgGyAV4B3gF7Af8BfwIAAd4BewG9AXcBvQF3Ab0BdwG9AXcBvQF3Ab0BdwG9AXcBvQF3 Ab0BdwG9AXcBvQF3Ab0BdwHeAXtCAAH/AX8B/wF/Aa4BYgEwAXsBMAF3ATABdwEwAXcBMAF3ATABdwEw @@ -169,344 +169,364 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADy - TgAAAk1TRnQBSQFMAgEBEQEAAbABCAGwAQgBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA - AwABUAMAAQEBAAEgBgABUBIAAyABLgJIAUcBhwJIAUcBhwJIAUcBhwJIAUcBhwJIAUcBhwJIAUcBhwJI - AUcBhwJIAUcBhwJIAUcBhwJIAUcBhwJIAUcBhwM4AV4DHQEpAxQBGwMLAQ/AAAMeASsDSwGQAr4BuwHv - A/4B/wP+Af8D/gH/A/4B/wP+Af8D/gH/A/4B/wP+A/8B/gH/AmgBZQHBAzMBUwMKAQ4DBgEIxAADHgEr - AlcBVAGrAs0BvAH/AtABwQH/AtUBxwH/AtoBzgH/AuAB1QH/AuYB3QH/AuwB5QH/AvEB7AH/AvYB8gH/ - AvwB+QH/A0MBedAAA0ABcQLxAeoB/wLvAegB/wLwAeoB/wLxAesB/wLzAe0B/wL0Ae8B/wL1AfEB/wL3 - AfIB/wL4AfQB/wL8AfgB/wNAAXHQAAI+AT0BawL7AfUB/wL2AfEB/wLPAcsB/wNXAf8C4gHeAf8C4gHe - Af8DVwH/As8BywH/AvYB8QH/AvsB9QH/Aj4BPQFr0AADPAFnAvoB8gH/AuIB2wH/A2AB/wK9AbgB/wLz - AewB/wLzAewB/wK9AbgB/wNgAf8C4gHbAf8C+gHyAf8DPAFn0AADPAFmAvgB7gH/Aq8BqgH/AqABnAH/ - AvAB5gH/AvAB5gH/AvAB5gH/AvAB5gH/AqABnAH/Aq8BqgH/AvgB7gH/AzwBZtAAAzwBZgL2AesB/wLe - AdQB/wN3Af8CwgG7Af8C7QHhAf8C7QHhAf8CwgG7Af8DdwH/At4B1AH/AvYB6wH/AzwBZtAAAzwBZgL1 - AecB/wLqAdwB/wLRAccB/wOGAf8C3gHSAf8C3gHSAf8DhgH/AtEBxwH/AuoB3AH/AvUB5wH/AzwBZtAA - AzwBZgL0AeQB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wL0 - AeQB/wM8AWbQAAM8AWYC8wHjAf8C5gHWAf8C5gHWAf8C5gHWAf8C5gHWAf8C5gHWAf8C5gHWAf8C5gHW - Af8C5gHWAf8C8wHjAf8DPAFm0AADPAFmAvIB4QH/AuUB1AH/AuUB1AH/AuUB1AH/AuUB1AH/AuUB1AH/ - AuUB1AH/AuUB1AH/AuUB1AH/AvIB4QH/AzwBZtAAAzwBZgL0AeUB/wLoAdkB/wLoAdkB/wLoAdkB/wLo - AdkB/wLoAdkB/wLoAdkB/wLoAdkB/wLoAdkB/wL0AeUB/wM8AWbQAAM8AWYC/AHzAf8C8wHrAf8C8wHr - Af8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C+gHxAf8CVwFVAaADGgEkzAADJgE5 - A2MBswL+Af0B/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wK/ - Ab0B7AJFAUQBegMWAR/MAAMmATkDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFm - AzwBZgMTARr/ACAAAf8CVAFWAasDKAE9RAADTgGZAVkBXAFZAcwDTgGZOAADTgGZAzgBXGQAAUUCRgF/ - AdkB9AL/AVYCWQG+AywBREAAAVkBXAFZAcwBAAHfAQAB/wFZAVwBWQHMCAADBwEJAxABFgMTARoDEwEa - AxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoBYAFcAVcB0QFgAVwBVwHRAzsBZQMHAQkDSgGM - A1YBuwNWAbsDVgG7A1YBuwNWAbkDVgG2A1YBtgNWAbYDWAHjAlMBZAHxAlMBZAHxAlMBZAHxAlMBZAHx - AlMBZAHxA1UBtQNKAYwDVgG7A1YBuwNWAbsDVgG7A1YBuQNWAbYDVgHBAVUCXAHqATkB5gH3Af8DXQHt - A1gBywNWAbYDVgG2A1YBtgNIAYgDSgGMA1YBuwNWAbsDVgG7A1YBuwNWAbkDVgG2A1YBtgNWAbYBWAFd - AVgB4wFTAWQBUwHxAVMBZAFTAfEBAAHiAQAB/wFTAWQBUwHxAVMBZAFTAfEDVQG1AzwBZwNIAYUDSAGF - A0gBhQNIAYUDSAGFA0gBhQNIAYUBXwFZAVgBzwFyAVwBTQHnAXIBXAFNAecBcgFcAU0B5wFyAVwBTQHn - Af8BxQExAf8BcgFcAU0B5wNOAZQDVQG3ApMBpAH/AooBmwH/AooBmwH/AooBmwH/ASwBKAExAf8BmwKT - Af8BkgKKAf8BkgKKAf8CAAGVAf8CHgH3Af8CHgH3Af8CHgH3Af8CHgH3Af8CHgH3Af8CVAFhAe4DVQG3 - ApMBpAH/AooBmwH/AooBmwH/AooBmwH/ASwBKAExAf8BmwKTAf8BkgKKAf8BLwGPAZUB/wEAAZMBpQH/ - ATkB5gH3Af8BAAGDAZQB/wErAYQBigH/AZICigH/AZICigH/A1IBqANVAbcCkwGkAf8CigGbAf8CigGb - Af8CigGbAf8BLAEoATEB/wGbApMB/wGSAooB/wGSAooB/wEAAZMBAAH/ARIB5wEBAf8BEgHnAQEB/wES - AecBAQH/ARIB5wEBAf8BEgHnAQEB/wFUAWEBVAHuA0QBewPrAf8D5wH/A+cB/wPnAf8D5wH/A+cB/wPn - Af8BywGPAUMC/wHjAZIC/wHVAWMC/wHRAVYC/wHRAVYC/wHRAVYC/wHYAWwB/wF2AWUBUwHlA1UBsgKd - Aa4B/wKVAaYB/wKVAaYB/wKVAaYB/wE+AToBggH/AaUCnQH/AZ0ClQH/AZ0ClQH/AQEBAAGhAf8CAAGe - Af8CAAGlAf8CAAGkAf8CAAGkAf8CAAGkAf8CWQFdAdcDVQGyAp0BrgH/ApUBpgH/ApUBpgH/ApUBpgH/ - AT4BOgGCAf8BpQKdAf8BnQKVAf8BnQKVAf8BOQGZAZ8B/wEAAY8BoAH/ATkB5gH3Af8BAAGEAZUB/wE0 - AYkBjgH/AZ0ClQH/A08BmwNVAbICnQGuAf8ClQGmAf8ClQGmAf8ClQGmAf8BPgE6AYIB/wGlAp0B/wGd - ApUB/wGdApUB/wELAZwBAAH/AQABlgEAAf8BAAGdAQAB/wEmAesBFQH/AQABnAEAAf8BAAGcAQAB/wFZ - AV0BWQHXA0IBdgPqAf8D4gH/A+IB/wPiAf8D4gH/A+IB/wPiAf8B2AGrAW8B/wHVAZkBSwH/AdUBmQFL - Af8B1QGZAUsB/wHVAZkBSwL/AeUBlwH/AdcBmwFNAf8CUwFSAagDRAF6ATMBLwE4Af8BMwEvATgB/wEz - AS8BOAH/ATMBLwE4Af8BIwEeASMB/wE3Ai8B/wE1ATQBLwH/ATMBOAEvAf8BMwE4AS8B/wEiASQBHgH/ - ATMBOAEvAf8BNQE0AS8B/wE3Ai8B/wE3Ai8B/wNAAXEDRAF6ATMBLwE4Af8BMwEvATgB/wEzAS8BOAH/ - ATMBLwE4Af8BIwEeASMB/wE3Ai8B/wE1ATQBLwH/ATMBOAEvAf8BMwE4AS8B/wEHATEBMgH/AQABjgGd - Af8BOQHmAfcB/wEOAgoB/wEmAh8B/wNAAXEDRAF6ATMBLwE4Af8BMwEvATgB/wEzAS8BOAH/ATMBLwE4 - Af8BIwEeASMB/wE3Ai8B/wE1ATQBLwH/ATMBOAEvAf8BMwE4AS8B/wEiASQBHgH/AQABmwEAAf8BNQHu - ASQB/wEAAZkBAAH/ATcCLwH/A0ABcQNBAXMD7QH/A+YB/wPmAf8D5gH/A+YB/wPmAf8D5gH/A+YB/wPm - Af8D5gH/A+YB/wHhAaUBVAH/AeEBpQFUAf8B6QHOAawB/wNBAXMDTAGSAaMCmwH/AZoCkgH/ATwCNAH/ - AaMCmwH/AZoCkgH/AZoCkgH/ATgBPQE0Af8BmwGsAZsB/wGSAaMBkgH/AZIBowGSAf8BkgGjAZIB/wE4 - AT0BNAH/AaMCmwH/AZoCkgH/A0wBkgNMAZIBowKbAf8BmgKSAf8BPAI0Af8BowKbAf8BmgKSAf8BmgKS - Af8BOAE9ATQB/wGbAawBmwH/AZIBowGSAf8BkgGjAZIB/wEvAaMBnAH/ASQBJwEiAf8D9wH/ARIBDgEw - Af8DUwGwA0wBkgGjApsB/wGaApIB/wE8AjQB/wGjApsB/wGaApIB/wGaApIB/wE4AT0BNAH/AZsBrAGb - Af8BkgGjAZIB/wGSAaMBkgH/AQcBpwEAAf8BAAGgAQAB/wEMAaIBAAH/AZoCkgH/A0wBkgNAAXED8AH/ - A+sB/wPrAf8D6wH/A+sB/wPrAf8D6wH/A+sB/wPrAf8D6wH/A+sB/wHpAbwBgwH/AeoBzwGtAf8D8AH/ - A0ABcQNLAY4BrwKnAf8BpwKfAf8BjQKGAf8BrwKnAf8BpwKfAf8BpwKfAf8BiQGOAYYB/wGnAbgBpwH/ - AZ8BsAGfAf8BnwGwAZ8B/wGfAbABnwH/AYkBjgGGAf8BrwKnAf8BpwKfAf8DSwGOA0sBjgGvAqcB/wGn - Ap8B/wGNAoYB/wGvAqcB/wGnAp8B/wGnAp8B/wGJAY4BhgH/AacBuAGnAf8BnwGwAZ8B/wGfAbABnwH/ - AZ8BsAGfAf8BgwGHAYAB/wEyAS4BkwH/AoAC/wJaAWEB5ANLAY4BrwKnAf8BpwKfAf8BjQKGAf8BrwKn - Af8BpwKfAf8BpwKfAf8BiQGOAYYB/wGnAbgBpwH/AZ8BsAGfAf8BnwGwAZ8B/wGfAbABnwH/AYkBjgGG - Af8BrwKnAf8BpwKfAf8DSwGOA0ABbgPzAf8D7wH/A+8B/wPvAf8D7wH/A+8B/wPvAf8D7wH/A+8B/wPv - Af8D7wH/A+8B/wPvAf8D8wH/A0ABbgM/AW4BgQGGAT0B/wGBAYYBPQH/AS4BMAEqAf8BgQGGAT0B/wGD - AYIBPQH/AYUCPQH/Ai8BKgH/AYEBhgE9Af8BgQGGAT0B/wE/AYYBggH/AT0ChgH/ASwBLwEwAf8BgQE9 - AYYB/wGBAT0BhgH/Az8BbgM/AW4BgQGGAT0B/wGBAYYBPQH/AS4BMAEqAf8BgQGGAT0B/wGDAYIBPQH/ - AYUCPQH/Ai8BKgH/AYEBhgE9Af8BgQGGAT0B/wE/AYYBggH/AT0ChgH/ASwBLwEwAf8BJgEkAZoB/wIA - AcIB/wNKAY0DPwFuAYEBhgE9Af8BgQGGAT0B/wEuATABKgH/AYEBhgE9Af8BgwGCAT0B/wGFAj0B/wIv - ASoB/wGBAYYBPQH/AYEBhgE9Af8BPwGGAYIB/wE9AoYB/wEsAS8BMAH/AYEBPQGGAf8BgQE9AYYB/wM/ - AW4DPwFsA/cB/wP0Af8D9AH/A/QB/wP0Af8D9AH/A/QB/wP0Af8D9AH/A/QB/wP0Af8D9AH/A/QB/wP3 - Af8DPwFsA0wBkwGnAbgBpwH/AZ4BrwGeAf8BngGvAZ4B/wGeAa8BngH/AYUBigGBAf8BrwKnAf8BpgKe - Af8BpgKeAf8BpgKeAf8BhQGBAYoB/wKnAbgB/wKeAa8B/wKeAa8B/wKeAa8B/wNMAZMDTAGTAacBuAGn - Af8BngGvAZ4B/wGeAa8BngH/AZ4BrwGeAf8BhQGKAYEB/wGvAqcB/wGmAp4B/wGmAp4B/wGmAp4B/wGF - AYEBigH/AqcBuAH/Ap4BrwH/Ap4BrwH/Ap4BrwH/A0wBkwNMAZMBpwG4AacB/wGeAa8BngH/AZ4BrwGe - Af8BngGvAZ4B/wGFAYoBgQH/Aa8CpwH/AaYCngH/AaYCngH/AaYCngH/AYUBgQGKAf8CpwG4Af8CngGv - Af8CngGvAf8CngGvAf8DTAGTAz4BagP6Af8D+AH/A/gB/wP4Af8D+AH/A/gB/wP4Af8D+AH/A/gB/wP4 - Af8D+AH/A/gB/wP4Af8D+gH/Az4BagNKAYwBswHEAbMB/wGqAbsBqgH/AaoBuwGqAf8BqgG7AaoB/wGV - AZkBkQH/AbsCswH/AbICqgH/AbICqgH/AbICqgH/AZUBkQGZAf8CswHEAf8CqgG7Af8CqgG7Af8CqgG7 - Af8DSgGMA0oBjAGzAcQBswH/AaoBuwGqAf8BqgG7AaoB/wGqAbsBqgH/AZUBmQGRAf8BuwKzAf8BsgKq - Af8BsgKqAf8BsgKqAf8BlQGRAZkB/wKzAcQB/wKqAbsB/wKqAbsB/wKqAbsB/wNKAYwDSgGMAbMBxAGz - Af8BqgG7AaoB/wGqAbsBqgH/AaoBuwGqAf8BlQGZAZEB/wG7ArMB/wGyAqoB/wGyAqoB/wGyAqoB/wGV - AZEBmQH/ArMBxAH/AqoBuwH/AqoBuwH/AqoBuwH/A0oBjAM9AWgD/QH/A/wB/wP8Af8D/AH/A/wB/wP8 - Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/A/0B/wM9AWgDOwFjAYwBkAGIAf8BjAGQAYgB/wNH - AYMDSAGGA00BlgNGAYABkAKIAf8BkAKIAf8DRgGAA00BlgNIAYYDRwGDAYwBiAGQAf8BjAGIAZAB/wM7 - AWMDOwFjAYwBkAGIAf8BjAGQAYgB/wNHAYMDSAGGA00BlgNGAYABkAKIAf8BkAKIAf8DRgGAA00BlgNI - AYYDRwGDAYwBiAGQAf8BjAGIAZAB/wM7AWMDOwFjAYwBkAGIAf8BjAGQAYgB/wNHAYMDSAGGA00BlgNG - AYABkAKIAf8BkAKIAf8DRgGAA00BlgNIAYYDRwGDAYwBiAGQAf8BjAGIAZAB/wM7AWMDPQFnOP8DPQFn - A0UBfQG5ArEB/wGwAqgB/wNFAX0IAANFAX0BuQKxAf8BsAKoAf8DRQF9CAADRQF9AbkCsQH/AbACqAH/ - A0UBfQNFAX0BuQKxAf8BsAKoAf8DRQF9CAADRQF9AbkCsQH/AbACqAH/A0UBfQgAA0UBfQG5ArEB/wGw - AqgB/wNFAX0DRQF9AbkCsQH/AbACqAH/A0UBfQgAA0UBfQG5ArEB/wGwAqgB/wNFAX0IAANFAX0BuQKx - Af8BsAKoAf8DRQF9Az0BaQO7Af8DugH/A7gB/wO2Af8DswH/A7AB/wOuAf8DqwH/A6gB/wOmAf8DowH/ - A6AB/wOeAf8DnAH/AzwBZgNEAXsBwwK7Af8BugKyAf8DRAF7CAADRAF7AcMCuwH/AboCsgH/A0QBewgA - A0QBewHDArsB/wG6ArIB/wNEAXsDRAF7AcMCuwH/AboCsgH/A0QBewgAA0QBewHDArsB/wG6ArIB/wNE - AXsIAANEAXsBwwK7Af8BugKyAf8DRAF7A0QBewHDArsB/wG6ArIB/wNEAXsIAANEAXsBwwK7Af8BugKy - Af8DRAF7CAADRAF7AcMCuwH/AboCsgH/A0QBewM3AVsDZQHUA9wB/wHYAtkB/wPVAf8B0ALRAf8DzAH/ - A8gB/wPGAf8BxgLFAf8ByQLFAf8BzQLGAf8B0QLHAf8B1wLLAf8DZQHUAzcBWwM3AVsDRAF5A0QBeQM3 - AVsIAAM3AVsDRAF5A0QBeQM3AVsIAAM3AVsDRAF5A0QBeQM3AVsDNwFbA0QBeQNEAXkDNwFbCAADNwFb - A0QBeQNEAXkDNwFbCAADNwFbA0QBeQNEAXkDNwFbAzcBWwNEAXkDRAF5AzcBWwgAAzcBWwNEAXkDRAF5 - AzcBWwgAAzcBWwNEAXkDRAF5AzcBWwMYASIDNgFZAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8 - AWYDPAFmAzwBZgM8AWYDPAFmAzYBWQMYASL/AC0AA04BmQFZAVwBWQHMA04BmQgAAw0BEgMfASwDQQFy - A0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNBAXIDHwEsAw0BEggAAw0BEgMf - ASwDQQFyA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNBAXIDDQESAx8BLANB - AXIDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcBXgJbAdADUAGeAx8BLAMNARIDBAEG - AxABFgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgFYAVwBWAHRAQAB3wEAAf8BWAFc - AVgB0QMQARYDBAEGAwcBCQMQARYDRwGCDv8B/gH/Av4B/QH/Av4B/AH/Av0B+wH/Av0B+gH/AvwB+AH/ - Av4B+QH/A0cBggMQARYDBwEJCAADBwEJAxABFgNHAYIO/wH+Af8C/gH9Af8C/gH8Af8C/QH7Af8C/QH6 - Af8C/AH4Af8C/gH5Af8DRwGCAwcBCQMQARYDRwGCDv8B/gH/Av4B/QH/Av4B/AH/Av0B+wH/Av0B+gH/ - AvwB+AH/AbgCAAH/AWEBWQFYAeYBQAI/AW4DBwEJAzwBaANIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNI - AYcDSAGHAVsBXgFbAdABXAFkAVwB5wFcAWQBXAHnAQAB4gEAAf8BXAFkAVwB5wFcAWQBXAHnAVUBVgFV - AbEIAANEAXsI/wP+Af8C/QH8Af8C/QH7Af8C/AH5Af8CAAGyAf8CAAGXAf8CAAGXAf8CAAGYAf8CXgFl - AeUCWQFcAcwDTgGZEAADRAF7CP8D/gH/Av0B/AH/Av0B+wH/AvwB+QH/AvsB+AH/AvoB9gH/AvgB9AH/ - AvsB9gH/A0QBewgAA0QBewj/A/4B/wL9AfwB/wL9AfsB/wHSAaUBAAH/AcMBhwEAAf8BwwGHAQAB/wHC - AYYBAAH/AcMBhwEAAv8BxQEAAf8CXAFZAcwDOAFcA0UBfwPKAf8DxQH/A8UB/wPFAf8DxQH/A8UB/wPF - Af8DxQH/AQABnwEAAf8BAAHnAQAB/wEAAecBAAH/AQAB5wEAAf8BAAHnAQAB/wEAAecBAAH/AVgBYQFY - AeYIAANDAXcE/wP+Af8C/QH8Af8C/QH7Af8C/AH5Af8C+wH4Af8CAAGrAf8CAAH3Af8CAAH3Af8CAAH3 - Af8CAAH3Af8CAAH3Af8CWQFcAcwQAANDAXcE/wOrAf8DQwH/AqsBqQH/AkMBQgH/AqkBpgH/AvoB9gH/ - AvgB9AH/AvcB8gH/AvsB9QH/A0MBdwgAA0MBdwT/A/4B/wL9AfwB/wL9AfsB/wL8AfkB/wHOAZMBAAL/ - AeMBkgL/AdUBAAL/AdEBAAL/AdEBAAL/AdEBAAL/AdgBAAH/AlwBWQHMA0MBeAPIAf8DAAH/AwAB/wMA - Af8DAAH/AwAB/wMAAf8DAAH/AQABgwEAAf8BAAGPAQAB/wEAAY8BAAH/AQAB6wEAAf8BAAGRAQAB/wEA - AaYBAAH/AVkBXAFZAckIAANCAXYC/wH+Af8C/QH8Af8C/QH7Af8C/AH5Af8C+wH4Af8C+gH2Af8CAAHF - Af8CAAG2Af8CAAG2Af8CAAG3Af8CWgFhAeQCWQFcAcwDTgGZEAADQgF2Av8B/gH/Av0B/AH/Av0B+wH/ - AkgBRwH/AvsB+AH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvoB8wH/A0IBdggAA0IBdgL/Af4B/wL9 - AfwB/wL9AfsB/wL8AfkB/wL7AfgB/wHhAbQBAAH/AdkBnQEAAf8B2QGdAQAB/wHZAZ0BAAH/AdoBngEA - Av8B5QGXAf8CXAFZAcwDOAFcA0IBdgPLAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8BAAGXAQAB/wEAAe4BAAH/AQABlAEAAf8DywH/A0IBdggAA0IBdAL+Af0B/wL9AfsB/wL8AfkB/wL7 - AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1Ae4B/wL6AfIB/wNCAXQIAAMxAU4DPQFnAz0BZwM9 - AWcDSgGKA8kB/wLJAcgB/wPIAf8DUAH/AsgBxwH/AtMB0QH/AvcB8gH/AvYB8AH/AvUB7gH/AvoB8gH/ - A0IBdAgAA0IBdAL+Af0B/wL9AfsB/wL8AfkB/wL7AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1 - Ae4B/wHlAakBAAH/Al8BWAHjAzgBXAQAA0IBdAPOAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wG7Ad0BAAH/ - AwAB/wMAAf8DAAH/AQABiQEAAf8BAAGaAQAB/wEAAYQBAAH/A84B/wNCAXQIAANBAXIC/gH8Af8C/AH5 - Af8C+wH4Af8C+gH2Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C+QHvAf8DQQFyCAADPQFp - A/oB/wP6Af8D+gH/A/oB/wP6Af8D+gH/A/oB/wNZAf8D+gH/AsIBwAH/AvYB8AH/AvUB7gH/AvQB7AH/ - AvkB7wH/A0EBcggAA0EBcgL+AfwB/wL8AfkB/wL7AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1 - Ae4B/wL0AewB/wHtAcABhAH/AlMBTwGlCAADQQFyA9IB/wEAAYQBAAH/AaABuQEAAf8BhAGVAQAB/wG7 - Ad0BAAH/AbsB3QEAAf8DAAH/AbsB3QEAAf8DAAH/AaMBugEAAf8BzAHmAYAB/wHuAfcBswH/AwAB/wPS - Af8DQQFyCAADQAFxAv0B+wH/AvsB+AH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/ - AvEB5wH/AvcB6gH/A0ABcQgAAz4BawPxAf8B6QGDAU0B/wHIAVABLgH/Aa0BNAESAf8BuAE1ARMB/wHa - AUcBJQH/A/EB/wNhAf8D8QH/ArsBuQH/AvUB7gH/AvQB7AH/AvEB5wH/AvcB6gH/A0ABcQgAA0ABcQL9 - AfsB/wL7AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wL3AeoB/wNA - AXEIAANAAXAD1gH/AwAB/wMAAf8BjgGfAQAB/wMAAf8BuwHdAQAB/wMAAf8DAAH/AbsB3QEAAf8BkQGc - AQAB/wMAAf8DAAH/AwAB/wPWAf8DQAFwCAADQAFvAv0B+gH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/ - AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AvQB5QH/A0ABbwgAAz8BbQPnAf8B6QGDAU0B/wHIAVABLgH/ - Aa0BNAESAf8BuAE1ARMB/wHaAUcBJQH/A+cB/wNpAf8D5wH/ArIBsAH/AvQB7AH/AvEB5wH/AuwB3wH/ - AvQB5QH/A0ABbwgAA0ABbwL9AfoB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLx - AecB/wLsAd8B/wL0AeUB/wNAAW8IAANAAW4D2gH/AwAB/wMAAf8DAAH/AwAB/wG7Ad0BAAH/AwAB/wMA - Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wPaAf8DQAFuCAADPwFtAvwB+AH/AvgB9AH/AvcB8gH/AvYB8AH/ - AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/AvMB4gH/Az8BbQgAA0ABcAPfAf8D3wH/A98B/wPf - Af8D3wH/A98B/wPfAf8DhgH/A98B/wKnAaUB/wLxAecB/wLsAd8B/wLoAdkB/wLzAeIB/wM/AW0IAAM/ - AW0C/AH4Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZAf8C8wHi - Af8DPwFtCAADPwFsA94B/wMAAf8DAAH/AwAB/wMAAf8BpgG/AQAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ - AwAB/wMAAf8D3gH/Az8BbAgAAz8BbAL8AfcB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wLs - Ad8B/wLoAdkB/wLmAdUB/wLyAeEB/wM/AWwIAAM2AVkDQwF3A0MBdwNDAXcDTAGTAo0BjAH/AowBiwH/ - AowBigH/AooBiAH/AosBiQH/AqUBnwH/AuwB3wH/AugB2QH/AuYB1QH/AvIB4QH/Az8BbAgAAz8BbAL8 - AfcB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLmAdUB/wLyAeEB/wM/ - AWwIAAM+AWoD4QH/AwAB/wMAAf8DAAH/AwAB/wGTAaQBAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ - AwAB/wPhAf8DPgFqCAADPgFrAvsB9gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/ - AuYB1QH/AuUB1AH/AvIB4QH/Az4BaxgAAz4BawL7AfYB/wL2AfAB/wL1Ae4B/wKNAYgB/wLxAecB/wLs - Ad8B/wLoAdkB/wLmAdUB/wLlAdQB/wLyAeEB/wM+AWsIAAM+AWsC+wH2Af8C9gHwAf8C9QHuAf8C9AHs - Af8C8QHnAf8C7AHfAf8C6AHZAf8C5gHVAf8C5QHUAf8C8gHhAf8DPgFrCAADPQFpA+QB/wMAAf8DAAH/ - AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wPkAf8DPQFpCAADPQFpAvoB9AH/ - AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/AuYB1QH/AqQBkwH/AqQBkwH/AqQBkwH/AkUBRAF8 - GAADPQFpAvoB9AH/AsMBvgH/ApEBjQH/AsABuAH/Ao0BhQH/ArkBrQH/AuYB1QH/AqQBkwH/AqQBkwH/ - AqQBkwH/AkUBRAF8CAADPQFpAvoB9AH/AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/AuYB1QH/ - AqQBkwH/AqQBkwH/AqQBkwH/AkUBRAF8CAADPQFoA+oB/wPlAf8D5QH/A+UB/wPlAf8D5QH/A+UB/wPl - Af8D5QH/A+UB/wPlAf8D5QH/A+UB/wPqAf8DPQFoCAADPQFoAvoB8wH/AvQB7AH/AvEB5wH/AuwB3wH/ - AugB2QH/AuYB1QH/AuUB1AH/ArYBpQX/Az0BaAMaASUYAAM9AWgC+gHzAf8C9AHsAf8C8QHnAf8C7AHf - Af8C6AHZAf8C5gHVAf8C5QHUAf8CtgGlBf8DPQFoAxoBJQgAAz0BaAL6AfMB/wL0AewB/wLxAecB/wLs - Ad8B/wLoAdkB/wLmAdUB/wLlAdQB/wK2AaUF/wM9AWgDGgElCAADMQFNAzwBZgM8AWYDPAFmAzwBZgM8 - AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDMQFNCAADPQFnAvwB9QH/AvkB7wH/ - AvYB6gH/AvQB5QH/AvMB4gH/AvIB4QH/AvIB4QH/AsIBsQH/Az0BZwMaASUcAAM9AWcC/AH1Af8C+QHv - Af8C9gHqAf8C9AHlAf8C8wHiAf8C8gHhAf8C8gHhAf8CwgGxAf8DPQFnAxoBJQwAAz0BZwL8AfUB/wL5 - Ae8B/wL2AeoB/wL0AeUB/wLzAeIB/wLyAeEB/wLyAeEB/wLCAbEB/wM9AWcDGgElVAADMQFNAzwBZgM8 - AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDGgEkIAADMQFNAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFm - AzwBZgM8AWYDGgEkEAADMQFNAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDGgEkUAADCwEP - AxIBGAMSARkDEgEYAxABFQMNARIDCwEPAwoBDgMKAQ4DDAEQAw0BEgMQARUDEgEYAxMBGgMSARgDCwEP - AwsBDwMSARgDEgEZAxIBGAMQARUDDQESAwsBDwMKAQ4DCgEOAwwBEAMNARIDEAEVAxIBGAMTARoDEgEY - AwsBD0cAAQEDAgEDAwQBBgMHAQkDCgQNAREDEAEVAxEBFwMSARkDEgEYAwkBDBAAAxYBHgMhATADSgGN - A08BpQMdASkDGQEjAxUBHQMUARsDFAEbAxYBHwMaASQDHQEqA0oBjANSAaYDIQEwAxYBHgMWAR4DIQEw - A0oBjQNPAaUDHQEpAxkBIwMVAR0DFAEbAxQBGwMWAR8DGgEkAx0BKgNKAYwDUgGmAyEBMAMWAR4DBAEG - AxABFgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMQARYDBAEG - BwABAQMEAQYDCQEMAw0BEgMTARoDIAEuAzwBZgNDAXgDPAFnAyYBOQMRARcQAAMGAQgDCQEMA1QBqwNZ - AcwDCAELAwcBCQMGAQgDBQEHAwUBBwMGAQgDBwEJAwgBCwNUAasDWQHMAwkBDAMGAQgDBgEIAwkBDANU - AasDWQHMAwgBCwMHAQkDBgEIAwUBBwMFAQcDBgEIAwcBCQMIAQsDVAGrA1kBzAMJAQwDBgEIAzwBaANI - AYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA1sB0AJcAWQB5wJcAWQB5wJcAWQB5wJcAWQB5wJc - AWQB5wJVAVYBsRgAAzkBYANZAb8D5AH/A1kBvwM5AWAYAANKAYsDVgGzA1kByQJZAVwByQJZAV0B0gFb - Al4B2QFYAl4B3QFcAmEB3AFaAV0BXgHYAlgBXAHRA1sByANWAbkDWQHEA0oBiwgAA0oBiwNWAbMDWQHJ - AlkBXAHJAlkBXQHSAVsCXgHZAVgCXgHdAVwCYQHcAVoBXQFeAdgCWAFcAdEDWwHIA1YBuQNZAcQDSgGL - BAADRQF/A8oB/wPFAf8DxQH/A8UB/wPFAf8DxQH/A8UB/wPFAf8CAAGhAf8CAAH3Af8CAAH3Af8CAAH3 - Af8CAAH3Af8CAAH3Af8CWAFhAeYMAAMwAU0DPAFmAzwBZgNBAXMD8gH/A/IB/wPyAf8DQQFzGAADVgGz - AYwBpAG/Af8BjwGnAcIB/wGVAawByAH/AZoBsQHNAf8BnwG1AdIB/wGiAbcB1QH/AaIBtwHVAf8BngG0 - AdEB/wGaAbABzQH/AZQBrAHHAf8BjwGnAcIB/wGMAaUBvwH/A1YBswgAA1YBswGMAaQBvwH/AY8BpwHC - Af8BlQGsAcgB/wGaAbEBzQH/AZ8BtQHSAf8BogG3AdUB/wGiAbcB1QH/AZ4BtAHRAf8BmgGwAc0B/wGU - AawBxwH/AY8BpwHCAf8BjAGlAb8B/wNWAbMEAANDAXgDyAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ - AwAB/wIAAYkB/wIAAZcB/wIAAZcB/wIAAZcB/wIAAZgB/wIAAa4B/wJZAVwByQwAAzwBZggAAzgBXANY - AbwD/QH/A1gBvAM4AVwYAAJUAVYBqwGTAasBxgH/AQABigGkAf8BAAGDAZ0B/wEAAYgBogH/AQABjQGn - Af8BAAGQAaoB/wEAAZABqgH/AQABjQGnAf8BAAGJAaMB/wEAAYQBngH/AQABigGkAf8BkwGrAcYB/wJU - AVYBqwgAAlQBVgGrAZMBqwHGAf8BAAGKAaQB/wEAAYMBnQH/AQABiAGiAf8BAAGNAacB/wEAAZABqgH/ - AQABkAGqAf8BAAGNAacB/wEAAYkBowH/AQABhAGeAf8BAAGKAaQB/wGTAasBxgH/AlQBVgGrBAADQgF2 - A8sB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wPLAf8DQgF2 - DAADPAFmCAADDQESAzcBWgNAAW4DNwFaAw0BEhgAA1EBogGcAbMBzwH/AQABgAGaAf8BlAGtAccB/wGU - Aa0BxwH/AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/AQABgAGa - Af8BnAGzAc8B/wNRAaIIAANRAaIBnAGzAc8B/wEAAYABmgH/AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/ - AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/AZQBrQHHAf8BlAGtAccB/wEAAYABmgH/AZwBswHPAf8DUQGi - BAADQgF0A84B/wMAAf8DAAH/AwAB/wMAAf8DAAH/AbsB3QEAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8DzgH/A0IBdAwAAzwBZjAAAxQBGwJUAVYBqwGkAbsB1wH/AQABgAGaAf8BpwHAAdoB/wGqAcEB3QH/ - Aa0BwwHgAf8BrwHEAeIB/wGvAcQB4gH/Aa0BwwHgAf8BqgHCAd0B/wGoAcAB2wH/AQABgAGaAf8BpAG7 - AdcB/wJUAVYBqwMUARsDFAEbAlQBVgGrAaQBuwHXAf8BAAGAAZoB/wGnAcAB2gH/AaoBwQHdAf8BrQHD - AeAB/wGvAcQB4gH/Aa8BxAHiAf8BrQHDAeAB/wGqAcIB3QH/AagBwAHbAf8BAAGAAZoB/wGkAbsB1wH/ - AlQBVgGrAxQBGwNBAXID0gH/AQABhAEAAf8BoAG5AQAB/wGEAZUBAAH/AbsB3QEAAf8BuwHdAQAB/wMA - Af8BuwHdAQAB/wMAAf8BowG6AQAB/wHMAeYBgAH/Ae4B9wGzAf8DAAH/A9IB/wNBAXIMAAM8AWYwAAMz - AVIDXgHQAasBwQHeAf8DAAH/AQABhgGgAf8BAAGGAaAB/wEAAYYBoAH/AgABjwH/AgABjwH/AQABhgGg - Af8BAAGGAaAB/wEAAYYBoAH/AwAB/wGrAcEB3gH/A14B0AMzAVIDMwFSA14B0AGrAcEB3gH/AwAB/wEA - AYYBoAH/AQABhgGgAf8BAAGGAaAB/wIAAY8B/wIAAY8B/wEAAYYBoAH/AQABhgGgAf8BAAGGAaAB/wMA - Af8BqwHBAd4B/wNeAdADMwFSA0ABcAPWAf8DAAH/AwAB/wGOAZ8BAAH/AwAB/wG7Ad0BAAH/AwAB/wMA - Af8BuwHdAQAB/wGRAZwBAAH/AwAB/wMAAf8DAAH/A9YB/wNAAXAMAAM8AWYUAAMYASECUgFUAaYCWQFc - AcwCUgFUAaYDGAEhCAADSAGGAasBwgHeAf8BsAHFAeMB/wIAAYwB/wEAAZQBrgH/AQABlAGuAf8BAAGU - Aa4B/wEAAYMBnQH/AQABgwGdAf8BAAGUAa4B/wEAAZQBrgH/AQABlAGuAf8BgAIAAf8BqgGcAZUB/wGr - AcIB3gH/A0gBhgNIAYYBqwHCAd4B/wGwAcUB4wH/AgABjAH/AQABlAGuAf8BAAGUAa4B/wEAAZQBrgH/ - AQABgwGdAf8BAAGDAZ0B/wEAAZQBrgH/AQABlAGuAf8BAAGUAa4B/wIAAYwB/wGwAcUB4wH/AasBwgHe - Af8DSAGGA0ABbgPaAf8DAAH/AwAB/wMAAf8DAAH/AbsB3QEAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8DAAH/A9oB/wNAAW4MAAM8AWYIAAJZAVwBzAMjATMEAAJRAVIBpwJXAV8B6AIAAesB/wJXAV8B6AJR - AVIBpwgAAkUBRgF/Aa4BxQHhAf8BjwGmAcIB/wEAAYMBnQH/AY0BpgG/Af8BjQGmAb8B/wGNAaYBvwH/ - AQABlQGuAf8BAAGVAa4B/wGNAaYBvwH/AY0BpgG/Af8BjQGmAb8B/wGbAgAB/wGiAgAB/wGsAaABlgH/ - AkUBRgF/AkUBRgF/Aa4BxQHhAf8BjwGmAcIB/wEAAYMBnQH/AY0BpgG/Af8BjQGmAb8B/wGNAaYBvwH/ - AQABlQGuAf8BAAGVAa4B/wGNAaYBvwH/AY0BpgG/Af8BjQGmAb8B/wEAAYMBnQH/AY8BpgHCAf8BrgHF - AeEB/wJFAUYBfwM/AWwD3gH/AwAB/wMAAf8DAAH/AwAB/wGmAb8BAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8DAAH/AwAB/wPeAf8DPwFsBAADPAFmAzwBZgM8AWYDPAFmBAADVgGzAlkBXAHMBAACWQFcAcwCAAH1 - Af8CAAH1Af8CAAH1Af8CWQFcAcwIAAMoAT0DRAF5Ak0BTgGWAQABlQGvAf8BngG3AdEB/wGeAbcB0QH/ - AZ4BtwHRAf8BjQGmAcAB/wGiAgAB/wGwAgAB/wGwAgAB/wGwAgAB/wGpAgAC/wHFAQAB/wJhAVoB5AJI - AUcBgwMoAT0DRAF5Ak0BTgGWAQABlQGvAf8BngG3AdEB/wGeAbcB0QH/AZ4BtwHRAf8BjQGmAcAB/wGN - AaYBwAH/AgABoQH/AgABkAH/AgABkAH/AgABiQH/AlUBXAHqAloBYQHkA1UBsgM+AWoD4QH/AwAB/wMA - Af8DAAH/AwAB/wGTAaQBAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wPhAf8DPgFqGAACWQFc - AcwDIwEzBAACUQFSAacCVwFfAegCAAH+Af8CVwFfAegCUQFSAacQAAJLAUwBjwGNAaYBwAH/Aa4BxwHh - Af8BrgHHAeEB/wGuAccB4QH/AZ4BtwHRAf8BvAGGAQAC/wHjAZIC/wHVAQAC/wHRAQAC/wHRAQAC/wHR - AQAC/wHYAQAB/wJcAVkBzAgAAksBTAGPAY0BpgHAAf8BrgHHAeEB/wGuAccB4QH/Aa4BxwHhAf8BngG3 - AdEB/wGeAbcB0QH/AgABpgH/AgAB9wH/AgAB9wH/AgAB9wH/AgAB9wH/AgAB9wH/AlkBXAHMAz0BaQPk - Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8D5AH/Az0BaSQA - AxgBIQJSAVQBpgJZAVwBzAJSAVQBpgMYASEQAANEAXsDXQHwAawBxQHfAf8BuQHSAewB/wG5AdIB7AH/ - AasBxAHeAf8BvwGcAQAB/wHNAZYBAAH/Ac0BlgEAAf8BygGTAQAB/wMrAfwB/wHlAZcB/wJcAVkBzAM4 - AVwIAANEAXsDXQHwAawBxQHfAf8BuQHSAewB/wG5AdIB7AH/AasBxAHeAf8BqwHEAd4B/wIAAcMB/wIA - AbUB/wIAAbMB/wMrAfwCXgFlAeUCWQFcAcwDTgGZAz0BaAPqAf8D5QH/A+UB/wPlAf8D5QH/A+UB/wPl - Af8D5QH/A+UB/wPlAf8D5QH/A+UB/wPlAf8D6gH/Az0BaEgAAy4BSANSAakDYQHuAagBwQHbAf8BqAHB - AdsB/wGoAcEB2wH/AagBwQHbAf8BqAHBAdsB/wGoAcEB2wH/A2EB7gJhAVQB7gJfAVoB2wM4AVwMAAMu - AUgDUgGpA2EB7gGoAcEB2wH/AagBwQHbAf8BqAHBAdsB/wGoAcEB2wH/AagBwQHbAf8BqAHBAdsB/wNh - Ae4DUgGpAy4BSAgAAzEBTQM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFm - AzwBZgM8AWYDPAFmAzEBTUgAAwUBBwMtAUUCPwFAAW4DRAF5A0QBeQNEAXkDRAF5A0QBeQNEAXkCPwFA - AW4DVQGyAzgBXhAAAwUBBwMtAUUCPwFAAW4DRAF5A0QBeQNEAXkDRAF5A0QBeQNEAXkCPwFAAW4DLQFF - AwUBB0sAAQEDAgEDAwQBBgMHBAoBDgMNARIDEAEWAxIBGAMTARoDEwEaAxMBGgMSARgDDgETAwkBDAME - AQYDAAEBAxYBHwJRAU8BnAJYAVYBwQJYAVYBwQJYAVYBwQJYAVYBwQJYAVYBwQJYAVYBwQJYAVYBwQJY - AVYBwQJRAU8BnAMYASIQAAM9AWoDSAGFA0gBhQNIAYUDSAGFA0gBhQNIAYUDSAGFA0gBhQNIAYUDSAGF - A0gBhQNIAYUDQAFwAx0BKgMSARgDDQESAx8BLANBAXIDSAGHA0gBhwNIAYcDSAGHAwAB/wNaAdgDUAGk - A0gBhwNIAYcDSAGHA0EBcgMfASwDDQESAwABAQMEAQYDCQEMAw8EFAEcAxkBIwMeASsDIQEwAyMBMwMj - ATMDIwEzA0MBeAMzAVIDEgEYAwgBCwMBAQIDDAEQA1MBqgH9AfQB4QH/AfsB8gHcAf8B+gHxAdwB/wH6 - AfAB2wH/AfkB8AHaAf8B+QHvAdkB/wH5Ae4B2AH/AfwB8gHfAf8DVgGzAx4BKwMTARoDDQERCAADRAF7 - A+sB/wPnAf8D5wH/A+cB/wPnAf8D5wH/A+cB/wPnAf8D5wH/A+cB/wPnAf8D6wH/A0QBewMQARUDCQEM - AwcBCQMQARYDRwGCDv8B/gH/AYABtgHHAf8B2QH0Av8BAAGfAa8B/wG7AdkB3QH/AvwB+AH/Av4B+QH/ - A0cBggMQARYDBwEJLAACTAFLAY8CTAFLAY8DKgFBDAACTwFOAZcB+wHyAdwB/wH1AewB0gH/AfUB6wHR - Af8B9AHqAdAB/wHzAegBzgH/AfIB5gHMAf8B8QHkAcoB/wH4Ae0B1wH/AmEBWAHmAlgBVgHBAlEBTwGc - AxgBIggAA0IBdgPqAf8D4gH/A+IB/wPiAf8D4gH/A+IB/wPiAf8D4gH/A+IB/wPiAf8D4gH/A+oB/wNC - AXYQAANEAXsI/wP+Af8C/QH8Af8B1wHpAe4B/wEAAbUBxQH/AQAB5gH3Af8BAAGdAa0B/wG2AdYB2AH/ - AvsB9gH/A0QBewgAA04BmQFcAlkByQFWAlUBtANIAYYDIwEzCAADGgEkAzgBXQJGAUUBfgNKAY0CTAFL - AY8DVgGzAkwBSwGPAyoBQQgAAkwBSwGQAfoB8QHcAf8B9QHrAdEB/wH0AeoB0AH/AfMB6AHOAf8B8gHm - AcwB/wHxAeQBygH/AfAB4gHIAf8B9wHrAdYB/wHOAasBggH/AfwB8gHfAf8DVgGzAxMBGgMTARoDDQER - A0EBcwPtAv8BmQEAAf8D5gH/A70B/wOsAf8DvQH/A70B/wOsAf8DvQH/A8kB/wPmAf8D7QH/A0EBcxAA - A0MBdwT/A/4B/wL9AfwB/wL9AfsB/wL8AfkB/wG+AeQB6AH/AQABtAHEAf8BAAHmAfcB/wEAAZ0BrAH/ - AboB2QHaAf8DQwF3CAABXAJZAcwDKwH8AlkBQgH1AmUBXgHlAVwBWgFZAc8CQAE/AW8DMQFPA0wBkgJS - AVEBoQJWAVQBqwJWAVUBsQNWAbMDVgGzA1YBswJMAUsBjwMjATMEAANKAYoB+gHwAdsB/wH0AeoB0AH/ - AfMB6AHOAf8B8gHmAcwB/wHxAeQBygH/AfAB4gHIAf8B7wHgAcYB/wH3AeoB1QH/Ac0BqgEAAf8B+AHt - AdcB/wJhAVgB5gJYAVYBwQJRAU8BnAMYASIDQAFxA/AB/wPrAf8D6wH/A+sB/wPrAf8D6wH/A+sB/wPr - Af8D6wH/A+sB/wPrAf8D8AH/A0ABcRAAA0IBdgL/Af4B/wL9AfwB/wL9AfsB/wL8AfkB/wL7AfgB/wL6 - AfYB/wG8AeIB5QH/AQABtAHDAf8BAAHmAfcB/wEAAZ4BrAH/A04BmQgAAVwCWQHMAfkBwgEAAv8BtAEA - Av8BswEAAf8CTQEpAfoCYQFdAeICWQFXAcIDVAGvA1YBswNWAbMDVgGzA1YBswNWAbMDVgGzAkwBSwGP - AyMBMwQAA0gBhAH5AfAB2gH/AfMB6AHOAf8B8gHmAcwB/wHxAeQBygH/AfAB4gHIAf8B7wHgAcYB/wHu - Ad0BwwH/AfYB5wHSAf8B0AGsAYIB/wH3AesB1gH/Ac4BqwGCAf8B/AHyAd8B/wNTAaoEAANAAW4D8wH/ - AgABwgH/A+8B/wO8Af8DxQH/A8UB/wPFAf8DvAH/A8UB/wO8Af8DxQH/A/MB/wNAAW4QAANCAXQC/gH9 - Af8C/QH7Af8C/AH5Af8C+wH4Af8C+gH2Af8C+AH0Af8C9wHyAf8BuwHhAeIB/wEAAbMBwgH/AQAB5gH3 - Af8DVgG4AyABLgQAA04BmQJdAVkB0gJfAVgB4wKoAUAB/QH8AbABAAH/AysB/AJiAVgB7wJbAVkBwwNV - AbICUQFQAZ8DTAGTAkwBSwGPA1YBswJMAUsBjwMqAUEIAAJGAUUBfgH5Ae8B2QH/AfIB5gHMAf8B8QHk - AcoB/wHwAeIByAH/Ae8B4AHGAf8B7gHdAcMB/wHqAdcBvQH/AfQB5AHOAf8B0gGuAYQB/wH3AeoB1QH/ - Ac0BqgEAAf8B+AHtAdcB/wJPAU4BlwQAAz8BbAP3Af8D9AH/A/QB/wP0Af8D9AH/A/QB/wP0Af8D9AH/ - A/QB/wP0Af8D9AH/A/cB/wM/AWwQAANBAXIC/gH8Af8C/AH5Af8C+wH4Af8C+gH2Af8C+AH0Af8C9wHy - Af8C9gHwAf8C9QHuAf8BuQLfAf8CrwGqAf8D9wH/A0sBjgMtAUYDBAEGAyIBMgJOAU0BlgJeAVoB2AJ/ - ATAB/gHuAagBAAH/AmoBQQH5AmQBXAHnA1ABmgM9AWkDGAEhAkwBSwGPAkwBSwGPAyoBQQwAA0MBeAH5 - Ae4B2AH/AfEB5AHKAf8B8AHiAcgB/wHvAeABxgH/Ae4B3QHDAf8B6gHXAb0B/wHnAdABtgH/AfIB4gHM - Af8B1AGwAYUB/wH2AecB0gH/AdABrAGCAf8B9wHrAdYB/wJMAUsBkAQAAz4BagP6Af8BAAGqAQAB/wP4 - Af8DuwH/A8wB/wPUAf8D2gH/A/gB/wP4Af8D+AH/A/gB/wP6Af8DPgFqEAADQAFxAv0B+wH/AvsB+AH/ - AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/At4B1AH/A1YBtgKAAv8CVgFY - AcEIAAMCAQMDVQG1AmQBUwHxAecBrgEAAf8B4QGlAQAB/wJkAVMB8QNVAbUDAgEDBAADNQFXA0QBehAA - AkIBQQFzAfgB7QHYAf8B8AHiAcgB/wHvAeABxgH/Ae4B3QHDAf8B6gHXAb0B/wHCAaQBhQH/AcIBpAGF - Af8BwgGkAYUB/wG/AZcBAAH/AfQB5AHOAf8B0gGuAYQB/wH3AeoB1QH/A0oBigQAAz0BaAP9Af8D/AH/ - A/wB/wP8Af8D/AH/A/wB/wP8Af8BqwHAAdQB/wIAAZkB/wGRAaYBugH/A8oB/wPLAf8DPQFoEAADQAFv - Av0B+gH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AvQB5QH/ - A0wBjwNUAa8DKgFAAwMBBAMZASMDPQFpAlABTwGbAl8BVwHoAmoBYQH5Ae0BtgEAAf8CfwFlAf4CXgFa - AdgCTgFNAZYDIAEvAlwBWQHMAlwBWQHMAzgBXAwAAkABPwFuAfgB7AHXAf8B7wHgAcYB/wHuAd0BwwH/ - AeoB1wG9Af8B5wHQAbYB/wHSAbYBmgL/AfYB5QH/AdYBsQGHAf8B4AHDAaQB/wHyAeIBzAH/AdQBsAGF - Af8B9gHnAdIB/wNIAYQEAAM9AWcI/wGwAcUB2gH/AgABoAH/AbABxQHaBf8BrQHCAdYB/wIAAZkB/wGB - AbQB5gH/AgABqgH/AZMBpwG8Af8DzAH/Az0BZxAAAz8BbQL8AfgB/wL4AfQB/wL3AfIB/wL2AfAB/wL1 - Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLzAeIB/wM/AW0IAAI/AT4BbANMAZMDUQGfA1UBsgNb - AcMCXQFOAfADKwH8AfQBvwEAAf8CqAFAAf0CXwFYAeMCXAFYAdECXAFZAcwB9AHCAQAB/wJcAVkBzAM4 - AVwIAAM+AWoB+wHxAd0B/wH3AeoB1QH/AfUB5wHSAf8B9AHkAc4B/wHyAeIBzAH/AdwBwgGnAf8B1wGy - AYkB/wHCAaABAAH/AcIBpAGFAf8BwgGkAYUB/wG/AZcBAAH/AfQB5AHOAf8CRgFFAX4EAAM9AWkDuwH/ - A7kB/wIAAZgB/wGPAcIB8QH/AgABpAH/AgABlgH/AgABiQH/AYQBtwHoAf8CAAGqAf8BhAG3AegB/wIA - Aa4B/wIAAZIB/wNTAaoDEwEaDAADPwFsAvwB9wH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/ - AuwB3wH/AugB2QH/AuYB1QH/AvIB4QH/Az8BbAgAAkwBSwGPA1YBswNWAbMDVgGzA1QBrwJZAVcBwgJh - AV0B4gNNAfoB9wHFAQAB/wH2AcQBAAH/AfgBygEAAf8B+AHLAQAB/wHyAbsBAAH/AfYBxgEAAf8CXAFZ - AcwDLgFIBAADMQFNAz0BZwJTAVIBqAHgAcABmgH/AdsBuQGPAf8B2gG4AY4B/wHYAbMBigH/AeEBxAGl - Af8B0gG2AZoC/wH2AeUB/wHWAbEBhwH/AeABwwGkAf8B8gHiAcwB/wNDAXgEAAM3AVsDYAHUA9sB/wGb - AbEBxgH/AQABigG9Af8BlQHIAfUB/wIAAZ8B/wGJAbwB6wH/AgABqgH/AYkBvAHrAf8BAAGIAbsB/wGJ - AbwB6wH/AXMCfwH+A10B7QJWAVkBvgM4AV4IAAM+AWsC+wH2Af8C9gHwAf8C9QHuAf8C9AHsAf8C8QHn - Af8C7AHfAf8C6AHZAf8C5gHVAf8C5QHUAf8C8gHhAf8DPgFrCAACTAFLAY8DVgGxA1QBrANSAaEDTAGS - AzEBTwJAAT8BbwJcAVkBzwJlAWQB5QNlAfQDKwH8AfoB0AGEAf8B9gHBAQAB/wH4Ac0BgQH/AlwBWQHM - Ay4BSAwAAz4BagH7AfEB3QH/AfcB6gHVAf8B9QHnAdIB/wH0AeQBzgH/AfIB4gHMAf8B3AHCAacB/wHX - AbIBiQH/AcIBoAEAAf8BwgGkAYUB/wHCAaQBhQH/AlIBUAGjBAADGAEiAzYBWQM8AWYDPAFmAUsCTAGP - AVoCXgHYAZ0B0AH4Af8BAAGIAbsB/wGSAcUB8AH/AQABiAG7Af8BnQHQAfgB/wGHAboB5wH/AQABqQHa - Af8BAAGwAeAB/wNcAeoBUgJTAagIAAM9AWkC+gH0Af8C9QHuAf8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZ - Af8C5gHVAf8CpAGTAf8CpAGTAf8CpAGTAf8CRQFEAXwIAAM/AWwDSgGNAkYBRQF/AzgBXgMaASQIAAMj - ATMDSAGFA1YBswJcAVkByQJcAVkBzAH8AdUBiQH/AlwBWQHMAzgBXBAAAzEBTQM9AWcCUwFSAagB4AHA - AZoB/wHbAbkBjwH/AdoBuAGOAf8B2AGzAYoB/wHhAcQBpQH/AdIBtgGaAv8B9gHlAf8CQAE/AW4DHAEn - FAADMQFOA1ABnQEAAZwBywH/AaQB1wH8Af8BAAGIAbsB/wGkAdcB/AH/AYwBvwHrAf8BAAGkAdUB/wEA - Aa0B3QH/AYQBtwHlAf8BjAG/AewB/wNQAZ0IAAM9AWgC+gHzAf8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZ - Af8C5gHVAf8C5QHUAf8CtgGlBf8DPQFoAxoBJTQAAlwBWQHMAlwBWQHMAzgBXBwAAz4BagH7AfEB3QH/ - AfcB6gHVAf8B9QHnAdIB/wH0AeQBzgH/AfIB4gHMAf8B3AHCAacB/wM+AWoDGwEmGAADTAGTAaUB2AH8 - Af8BAAGvAd0B/wEAAZ0BzAH/AakB3AL/AaUB2AH8Af8BigG9AecB/wGOAcEB6gH/AZMBxgHvAf8BmQHM - AfQB/wNMAZMDMAFLCAADPQFnAvwB9QH/AvkB7wH/AvYB6gH/AvQB5QH/AvMB4gH/AvIB4QH/AvIB4QH/ - AsIBsQH/Az0BZwMaASU4AANOAZkDOAFcIAADMQFNAz0BZwM9AWcDPQFnAz0BZwM9AWcDPQFnAxoBJBwA - Ay4BRwNKAYwDSgGMA0oBjANKAYwDSgGMA0oBjANKAYwDSgGMA0oBjAMuAUcMAAMxAU0DPAFmAzwBZgM8 - AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgMaASQQAAFCAU0BPgcAAT4DAAEoAwABQAMAAVADAAEBAQABAQUA - AYABAhYAA/8RAAGAAQMGAAHAAQMGAAHAAQMGAAHAAQMGAAHAAQMGAAHAAQMGAAHAAQMGAAHAAQMGAAHA - AQMGAAHAAQMGAAHAAQMGAAHAAQEGAAHABwAB4AcAAv8B/gE/Af8B4wH/AfMC/wH+AR8B/wHjUgABDAEw - AQwBMAEMATACAAEMATABDAEwAQwBMAIAAQwBMAEMATABDAEwAgAJ/wHjAgABwAcAAcAFAAHAAQAB8AEA - AcADAAHAAQAB8AEAAcADAAHAAQAB8AEAAcADAAHAAQMCAAHAAQECAAHAAQMCAAHAAQMCAAHAAQMCAAHA - AQMCAAHAAQMCAAHAAQMCAAHAAQMCAAHAAQMCAAHAAQMCAAHAAQMCAAHAAQMB8AEAAcABAwIAAcABAwHw - AQABwAEDAgABwAEDAfABAAHAAQMCAAHAAQcB8AEBAcABBwL/AcABDwHwAQMBwAEPAv8EAAL/AYABDwYA - AYABDwYAAfwBHwGAAQEBgAEBAgAB4AEfAYABAQGAAQECAAHsAR8BgAEBAYABAQIAAewBHwGAAQEBgAEB - AgAB7wH/BgAB7wH/BgAB7wGDBgAB7AGDBgABhAGDBgAB/AGDAcABAAHAAwAB/wGDAcABAAHAAwAC/wHA - AQEBwAEDAgAC/wHAAQMBwAEDAv8DAAEPBwABAwQAAf8B4wGAAQMBAAEDAcABAwEGAQEBgAIAAQMBwAED - AgABgAIAAQMBwAEDAgABgAEBAQABAwHAAQEBAAEBAYABAQEAAQMBwAIAAQMBgAEBAQABAwHAAQABwAEn - AYABAQEAAQMBwAIAAQMBgAEBAQABAwHAAQMBAAEBAYABAQEAAQEBwAEDAgABgAEBAgABwAEDAgAB4AEB - AgABwAEDAQYBAQHgAQEB8AEAAcABAwH/AeMB+AEDAfABAAHAAQcB/wHnAfgBBwHwAQEBwAEPCw== + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAB0 + UwAAAk1TRnQBSQFMAgEBEgEAAfABCAHwAQgBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + AwABUAMAAQEBAAEgBgABUBIAAyABLgNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNI + AYcDSAGHAzgBXgMdASkDFAEbAwsBD8AAAx4BKwNLAZACggF/Ae8D/gH/A/4B/wP+Af8D/gH/A/4B/wP+ + Af8D/gH/A/4D/wH+Af8DWAHBAzMBUwMKAQ4DBgEIAwsBDwMRARcDEwEaAxMBGgMTARoDEwEaAxMBGgMT + ARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEQEXAwsBD4QAAx4BKwJWAVQBqwLNAbwB/wLQAcEB/wLV + AccB/wLaAc4B/wLgAdUB/wLmAd0B/wLsAeUB/wLxAewB/wL2AfIB/wL8AfkB/wNEAXkIAANRAaACVQFc + AcwCVQFcAcwCVQFcAcwCVQFcAcwCVQFcAcwCVQFcAcwCVQFcAcwCVQFcAcwCVQFcAcwCVQFcAcwCVQFc + AcwCVQFcAcwCVQFcAcwCVQFcAcwDUQGgiAADQAFxAvEB6gH/Au8B6AH/AvAB6gH/AvEB6wH/AvMB7QH/ + AvQB7wH/AvUB8QH/AvcB8gH/AvgB9AH/AvwB+AH/A0ABcQgAAlUBXgHMAikB4AH/Ah8B2wH/Ah0B2gH/ + AhsB2gH/AhkB2QH/AhgB2AH/AhYB2AH/AhUB1wH/AhQB1wH/AhMB1gH/AhIB1gH/AhIB1gH/AhIB1gH/ + AhIB1gH/AlUBXgHMiAADPgFrAvsB9QH/AvYB8QH/As8BywH/A08B/wLiAd4B/wLiAd4B/wNPAf8CzwHL + Af8C9gHxAf8C+wH1Af8DPgFrCAACVQFeAcwCMwHWAf8CIAHJAf8CIAHJAf8CIAHJAf8CIAHJAf8CIAHJ + Af8CCwGZAf8CCwGZAf8CFgGxAf8CIAHJAf8CIAHJAf8CIAHJAf8CIAHJAf8CIAHJAf8CVQFeAcyIAAM8 + AWcC+gHyAf8C4gHbAf8DWAH/Ar0BuAH/AvMB7AH/AvMB7AH/Ar0BuAH/A1gB/wLiAdsB/wL6AfIB/wM8 + AWcIAAJVAV8BzAJBAdIB/wIrAb0B/wIrAb0B/wIrAb0B/wIrAb0B/wIrAb0B/wPCAf8DwgH/AhsBqwH/ + AisBvQH/AisBvQH/AisBvQH/AisBvQH/Ai4BwAH/AlUBXwHMiAADPAFmAvgB7gH/Aq8BqgH/AqABnAH/ + AvAB5gH/AvAB5gH/AvAB5gH/AvAB5gH/AqABnAH/Aq8BqgH/AvgB7gH/AzwBZggAAlUBXwHMAgsBmQH/ + AgsBmQH/AgsBmQH/AgsBmQH/AgsBmQH/AgsBmQH/A6wB/wOIAf8CAwGIAf8CCwGZAf8CCwGZAf8CCwGZ + Af8CCwGZAf8CCwGZAf8CVQFfAcyIAAM8AWYC9gHrAf8C3gHUAf8DbwH/AsIBuwH/Au0B4QH/Au0B4QH/ + AsIBuwH/A28B/wLeAdQB/wL2AesB/wM8AWYIAAJVAV8BzAJPAd0B/wI0AcIB/wI0AcIB/wI0AcIB/wI0 + AcIB/wI0AcIB/wPbAf8D2wH/AiABrgH/AjQBwgH/AjQBwgH/AjQBwgH/AjQBwgH/Aj4BzAH/AlUBXwHM + iAADPAFmAvUB5wH/AuoB3AH/AtEBxwH/A4YB/wLeAdIB/wLeAdIB/wOGAf8C0QHHAf8C6gHcAf8C9QHn + Af8DPAFmCAACVQFfAcwCcQL/AnEC/wJxAv8CcQL/AnEC/wJxAv8CcQL/AnEC/wJxAv8CcQL/AnEC/wJx + Av8CcQL/AnEC/wJVAV8BzIgAAzwBZgL0AeQB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wLo + AdgB/wLoAdgB/wLoAdgB/wL0AeQB/wM8AWYIAAJVAWEBzAJiAfAB/wJSAeAB/wJSAeAB/wJSAeAB/wJS + AeAB/wJSAeAB/wJSAeAB/wJSAeAB/wJSAeAB/wJSAeAB/wJSAeAB/wJSAeAB/wJSAeAB/wJcAeoB/wJV + AWEBzIgAAzwBZgLzAeMB/wLmAdYB/wLmAdYB/wLmAdYB/wLmAdYB/wLmAdYB/wLmAdYB/wLmAdYB/wLm + AdYB/wLzAeMB/wM8AWYIAAJVAWEBzAJsAfoB/wJnAfUB/wJnAfUB/wJWAcIB/wJFAY8B/wJWAcIB/wJn + AfUB/wJmAfQB/wJWAcIB/wJFAY8B/wJVAcEB/wJlAfMB/wJlAfMB/wJpAfcB/wJVAWEBzIgAAzwBZgLy + AeEB/wLlAdQB/wLlAdQB/wLlAdQB/wLlAdQB/wLlAdQB/wLlAdQB/wLlAdQB/wLlAdQB/wLyAeEB/wM8 + AWYIAANOAZkCVQFhAcwCVQFhAcwCVQFhAcwCVgFaAcoDmQH/AlYBWgHKAlUBYQHMAlUBYQHMAlYBWgHK + A5kB/wJWAVoBygJVAWEBzAJVAWEBzAJVAWEBzANOAZmIAAM8AWYC9AHlAf8C6AHZAf8C6AHZAf8C6AHZ + Af8C6AHZAf8C6AHZAf8C6AHZAf8C6AHZAf8C6AHZAf8C9AHlAf8DPAFmGAADIQEwA1YBvhAAA1YBvgMh + ATCYAAM8AWYC/AHzAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHr + Af8C+gHxAf8DUQGgAxoBJBQAAxEBFwNUAbQDSAGHAzYBWQM2AVkDSAGHA1QBtAMRAReYAAMmATkDVgGz + Av4B/QH/Av0B/AH/Av0B/AH/Av0B/AH/Av0B/AH/Av0B/AH/Av0B/AH/Av0B/AH/Av0B/AH/A30B7ANE + AXoDFgEfFAADNQFXA1MBrQNTAa0DUwGtA1MBrQM1AVegAAMmATkDPAFmAzwBZgM8AWYDPAFmAzwBZgM8 + AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgMTARr/ACAAAf8CVAFWAasDKAE9RAADTgGZAVkBXAFZAcwDTgGZ + OAADTgGZAzgBXGQAAUUCRgF/AdkB9AL/AVYCWQG+AywBREAAAVkBXAFZAcwBAAHfAQAB/wFZAVwBWQHM + CAADBwEJAxABFgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoCXAFYAdECXAFY + AdEDOwFlAwcBCQNKAYwDVgG7A1YBuwNWAbsDVgG7A1YBuQNWAbYDVgG2A1YBtgNYAeMCUwFkAfECUwFk + AfECUwFkAfECUwFkAfECUwFkAfEDVQG1A0oBjANWAbsDVgG7A1YBuwNWAbsDVgG5A1YBtgNWAcEBVQJc + AeoBMQHmAfcB/wNdAe0DWAHLA1YBtgNWAbYDVgG2A0gBiANKAYwDVgG7A1YBuwNWAbsDVgG7A1YBuQNW + AbYDVgG2A1YBtgFYAV0BWAHjAVMBZAFTAfEBUwFkAVMB8QEAAeIBAAH/AVMBZAFTAfEBUwFkAVMB8QNV + AbUDPAFnA0gBhQNIAYUDSAGFA0gBhQNIAYUDSAGFA0gBhQFcAlkBzwFkAlwB5wFkAlwB5wFkAlwB5wFk + AlwB5wH/AcUBKQH/AWQCXAHnA04BlANVAbcCkwGkAf8CigGbAf8CigGbAf8CigGbAf8BJAEgASkB/wGb + ApMB/wGSAooB/wGSAooB/wIAAZUB/wIWAfcB/wIWAfcB/wIWAfcB/wIWAfcB/wIWAfcB/wJUAWEB7gNV + AbcCkwGkAf8CigGbAf8CigGbAf8CigGbAf8BJAEgASkB/wGbApMB/wGSAooB/wEnAY8BlQH/AQABkwGl + Af8BMQHmAfcB/wEAAYMBlAH/ASMBhAGKAf8BkgKKAf8BkgKKAf8DUgGoA1UBtwKTAaQB/wKKAZsB/wKK + AZsB/wKKAZsB/wEkASABKQH/AZsCkwH/AZICigH/AZICigH/AQABkwEAAf8BCgHnAQAB/wEKAecBAAH/ + AQoB5wEAAf8BCgHnAQAB/wEKAecBAAH/AVQBYQFUAe4DRAF7A+sB/wPnAf8D5wH/A+cB/wPnAf8D5wH/ + A+cB/wHLAY8BOwL/AeMBkgL/AdUBWwL/AdEBTgL/AdEBTgL/AdEBTgL/AdgBZAH/AmUBXgHlA1UBsgKd + Aa4B/wKVAaYB/wKVAaYB/wKVAaYB/wE2ATIBggH/AaUCnQH/AZ0ClQH/AZ0ClQH/AgABoQH/AgABngH/ + AgABpQH/AgABpAH/AgABpAH/AgABpAH/AlkBXQHXA1UBsgKdAa4B/wKVAaYB/wKVAaYB/wKVAaYB/wE2 + ATIBggH/AaUCnQH/AZ0ClQH/AZ0ClQH/ATEBmQGfAf8BAAGPAaAB/wExAeYB9wH/AQABhAGVAf8BLAGJ + AY4B/wGdApUB/wNPAZsDVQGyAp0BrgH/ApUBpgH/ApUBpgH/ApUBpgH/ATYBMgGCAf8BpQKdAf8BnQKV + Af8BnQKVAf8BAwGcAQAB/wEAAZYBAAH/AQABnQEAAf8BHgHrAQ0B/wEAAZwBAAH/AQABnAEAAf8BWQFd + AVkB1wNCAXYD6gH/A+IB/wPiAf8D4gH/A+IB/wPiAf8D4gH/AdgBqwFnAf8B1QGZAUMB/wHVAZkBQwH/ + AdUBmQFDAf8B1QGZAUMC/wHlAZcB/wHXAZsBRQH/AlMBUgGoA0QBegErAScBMAH/ASsBJwEwAf8BKwEn + ATAB/wErAScBMAH/ARsBFgEbAf8BLwInAf8BLQEsAScB/wErATABJwH/ASsBMAEnAf8BGgEcARYB/wEr + ATABJwH/AS0BLAEnAf8BLwInAf8BLwInAf8DQAFxA0QBegErAScBMAH/ASsBJwEwAf8BKwEnATAB/wEr + AScBMAH/ARsBFgEbAf8BLwInAf8BLQEsAScB/wErATABJwH/ASsBMAEnAf8BAAEpASoB/wEAAY4BnQH/ + ATEB5gH3Af8BBgICAf8BHgIXAf8DQAFxA0QBegErAScBMAH/ASsBJwEwAf8BKwEnATAB/wErAScBMAH/ + ARsBFgEbAf8BLwInAf8BLQEsAScB/wErATABJwH/ASsBMAEnAf8BGgEcARYB/wEAAZsBAAH/AS0B7gEc + Af8BAAGZAQAB/wEvAicB/wNAAXEDQQFzA+0B/wPmAf8D5gH/A+YB/wPmAf8D5gH/A+YB/wPmAf8D5gH/ + A+YB/wPmAf8B4QGlAUwB/wHhAaUBTAH/AekBzgGsAf8DQQFzA0wBkgGjApsB/wGaApIB/wE0AiwB/wGj + ApsB/wGaApIB/wGaApIB/wEwATUBLAH/AZsBrAGbAf8BkgGjAZIB/wGSAaMBkgH/AZIBowGSAf8BMAE1 + ASwB/wGjApsB/wGaApIB/wNMAZIDTAGSAaMCmwH/AZoCkgH/ATQCLAH/AaMCmwH/AZoCkgH/AZoCkgH/ + ATABNQEsAf8BmwGsAZsB/wGSAaMBkgH/AZIBowGSAf8BJwGjAZwB/wEcAR8BGgH/A/cB/wEKAQYBKAH/ + A1MBsANMAZIBowKbAf8BmgKSAf8BNAIsAf8BowKbAf8BmgKSAf8BmgKSAf8BMAE1ASwB/wGbAawBmwH/ + AZIBowGSAf8BkgGjAZIB/wEAAacBAAH/AQABoAEAAf8BBAGiAQAB/wGaApIB/wNMAZIDQAFxA/AB/wPr + Af8D6wH/A+sB/wPrAf8D6wH/A+sB/wPrAf8D6wH/A+sB/wPrAf8B6QG8AYMB/wHqAc8BrQH/A/AB/wNA + AXEDSwGOAa8CpwH/AacCnwH/AY0ChgH/Aa8CpwH/AacCnwH/AacCnwH/AYkBjgGGAf8BpwG4AacB/wGf + AbABnwH/AZ8BsAGfAf8BnwGwAZ8B/wGJAY4BhgH/Aa8CpwH/AacCnwH/A0sBjgNLAY4BrwKnAf8BpwKf + Af8BjQKGAf8BrwKnAf8BpwKfAf8BpwKfAf8BiQGOAYYB/wGnAbgBpwH/AZ8BsAGfAf8BnwGwAZ8B/wGf + AbABnwH/AYMBhwGAAf8BKgEmAZMB/wKAAv8CWgFhAeQDSwGOAa8CpwH/AacCnwH/AY0ChgH/Aa8CpwH/ + AacCnwH/AacCnwH/AYkBjgGGAf8BpwG4AacB/wGfAbABnwH/AZ8BsAGfAf8BnwGwAZ8B/wGJAY4BhgH/ + Aa8CpwH/AacCnwH/A0sBjgNAAW4D8wH/A+8B/wPvAf8D7wH/A+8B/wPvAf8D7wH/A+8B/wPvAf8D7wH/ + A+8B/wPvAf8D7wH/A/MB/wNAAW4DPwFuAYEBhgE1Af8BgQGGATUB/wEmASgBIgH/AYEBhgE1Af8BgwGC + ATUB/wGFAjUB/wInASIB/wGBAYYBNQH/AYEBhgE1Af8BNwGGAYIB/wE1AoYB/wEkAScBKAH/AYEBNQGG + Af8BgQE1AYYB/wM/AW4DPwFuAYEBhgE1Af8BgQGGATUB/wEmASgBIgH/AYEBhgE1Af8BgwGCATUB/wGF + AjUB/wInASIB/wGBAYYBNQH/AYEBhgE1Af8BNwGGAYIB/wE1AoYB/wEkAScBKAH/AR4BHAGaAf8CAAHC + Af8DSgGNAz8BbgGBAYYBNQH/AYEBhgE1Af8BJgEoASIB/wGBAYYBNQH/AYMBggE1Af8BhQI1Af8CJwEi + Af8BgQGGATUB/wGBAYYBNQH/ATcBhgGCAf8BNQKGAf8BJAEnASgB/wGBATUBhgH/AYEBNQGGAf8DPwFu + Az8BbAP3Af8D9AH/A/QB/wP0Af8D9AH/A/QB/wP0Af8D9AH/A/QB/wP0Af8D9AH/A/QB/wP0Af8D9wH/ + Az8BbANMAZMBpwG4AacB/wGeAa8BngH/AZ4BrwGeAf8BngGvAZ4B/wGFAYoBgQH/Aa8CpwH/AaYCngH/ + AaYCngH/AaYCngH/AYUBgQGKAf8CpwG4Af8CngGvAf8CngGvAf8CngGvAf8DTAGTA0wBkwGnAbgBpwH/ + AZ4BrwGeAf8BngGvAZ4B/wGeAa8BngH/AYUBigGBAf8BrwKnAf8BpgKeAf8BpgKeAf8BpgKeAf8BhQGB + AYoB/wKnAbgB/wKeAa8B/wKeAa8B/wKeAa8B/wNMAZMDTAGTAacBuAGnAf8BngGvAZ4B/wGeAa8BngH/ + AZ4BrwGeAf8BhQGKAYEB/wGvAqcB/wGmAp4B/wGmAp4B/wGmAp4B/wGFAYEBigH/AqcBuAH/Ap4BrwH/ + Ap4BrwH/Ap4BrwH/A0wBkwM+AWoD+gH/A/gB/wP4Af8D+AH/A/gB/wP4Af8D+AH/A/gB/wP4Af8D+AH/ + A/gB/wP4Af8D+AH/A/oB/wM+AWoDSgGMAbMBxAGzAf8BqgG7AaoB/wGqAbsBqgH/AaoBuwGqAf8BlQGZ + AZEB/wG7ArMB/wGyAqoB/wGyAqoB/wGyAqoB/wGVAZEBmQH/ArMBxAH/AqoBuwH/AqoBuwH/AqoBuwH/ + A0oBjANKAYwBswHEAbMB/wGqAbsBqgH/AaoBuwGqAf8BqgG7AaoB/wGVAZkBkQH/AbsCswH/AbICqgH/ + AbICqgH/AbICqgH/AZUBkQGZAf8CswHEAf8CqgG7Af8CqgG7Af8CqgG7Af8DSgGMA0oBjAGzAcQBswH/ + AaoBuwGqAf8BqgG7AaoB/wGqAbsBqgH/AZUBmQGRAf8BuwKzAf8BsgKqAf8BsgKqAf8BsgKqAf8BlQGR + AZkB/wKzAcQB/wKqAbsB/wKqAbsB/wKqAbsB/wNKAYwDPQFoA/0B/wP8Af8D/AH/A/wB/wP8Af8D/AH/ + A/wB/wP8Af8D/AH/A/wB/wP8Af8D/AH/A/wB/wP9Af8DPQFoAzsBYwGMAZABiAH/AYwBkAGIAf8DRwGD + A0gBhgNNAZYDRgGAAZACiAH/AZACiAH/A0YBgANNAZYDSAGGA0cBgwGMAYgBkAH/AYwBiAGQAf8DOwFj + AzsBYwGMAZABiAH/AYwBkAGIAf8DRwGDA0gBhgNNAZYDRgGAAZACiAH/AZACiAH/A0YBgANNAZYDSAGG + A0cBgwGMAYgBkAH/AYwBiAGQAf8DOwFjAzsBYwGMAZABiAH/AYwBkAGIAf8DRwGDA0gBhgNNAZYDRgGA + AZACiAH/AZACiAH/A0YBgANNAZYDSAGGA0cBgwGMAYgBkAH/AYwBiAGQAf8DOwFjAz0BZzj/Az0BZwNF + AX0BuQKxAf8BsAKoAf8DRQF9CAADRQF9AbkCsQH/AbACqAH/A0UBfQgAA0UBfQG5ArEB/wGwAqgB/wNF + AX0DRQF9AbkCsQH/AbACqAH/A0UBfQgAA0UBfQG5ArEB/wGwAqgB/wNFAX0IAANFAX0BuQKxAf8BsAKo + Af8DRQF9A0UBfQG5ArEB/wGwAqgB/wNFAX0IAANFAX0BuQKxAf8BsAKoAf8DRQF9CAADRQF9AbkCsQH/ + AbACqAH/A0UBfQM9AWkDuwH/A7oB/wO4Af8DtgH/A7MB/wOwAf8DrgH/A6sB/wOoAf8DpgH/A6MB/wOg + Af8DngH/A5wB/wM8AWYDRAF7AcMCuwH/AboCsgH/A0QBewgAA0QBewHDArsB/wG6ArIB/wNEAXsIAANE + AXsBwwK7Af8BugKyAf8DRAF7A0QBewHDArsB/wG6ArIB/wNEAXsIAANEAXsBwwK7Af8BugKyAf8DRAF7 + CAADRAF7AcMCuwH/AboCsgH/A0QBewNEAXsBwwK7Af8BugKyAf8DRAF7CAADRAF7AcMCuwH/AboCsgH/ + A0QBewgAA0QBewHDArsB/wG6ArIB/wNEAXsDNwFbA2AB1APcAf8B2ALZAf8D1QH/AdAC0QH/A8wB/wPI + Af8DxgH/AcYCxQH/AckCxQH/Ac0CxgH/AdECxwH/AdcCywH/A2AB1AM3AVsDNwFbA0QBeQNEAXkDNwFb + CAADNwFbA0QBeQNEAXkDNwFbCAADNwFbA0QBeQNEAXkDNwFbAzcBWwNEAXkDRAF5AzcBWwgAAzcBWwNE + AXkDRAF5AzcBWwgAAzcBWwNEAXkDRAF5AzcBWwM3AVsDRAF5A0QBeQM3AVsIAAM3AVsDRAF5A0QBeQM3 + AVsIAAM3AVsDRAF5A0QBeQM3AVsDGAEiAzYBWQM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFm + AzwBZgM8AWYDPAFmAzwBZgM2AVkDGAEi/wAtAANOAZkBWQFcAVkBzANOAZkIAAMNARIDHwEsA0EBcgNI + AYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDQQFyAx8BLAMNARIIAAMNARIDHwEs + A0EBcgNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDQQFyAw0BEgMfASwDQQFy + A0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHAV4CWwHQA1ABngMfASwDDQESAwQBBgMQ + ARYDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoBWAFcAVgB0QEAAd8BAAH/AVgBXAFY + AdEDEAEWAwQBBgMHAQkDEAEWA0cBgg7/Af4B/wL+Af0B/wL+AfwB/wL9AfsB/wL9AfoB/wL8AfgB/wL+ + AfkB/wNHAYIDEAEWAwcBCQgAAwcBCQMQARYDRwGCDv8B/gH/Av4B/QH/Av4B/AH/Av0B+wH/Av0B+gH/ + AvwB+AH/Av4B+QH/A0cBggMHAQkDEAEWA0cBgg7/Af4B/wL+Af0B/wL+AfwB/wL9AfsB/wL9AfoB/wL8 + AfgB/wG4AgAB/wFhAVkBWAHmAUACPwFuAwcBCQM8AWgDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGH + A0gBhwFbAV4BWwHQAVwBZAFcAecBXAFkAVwB5wEAAeIBAAH/AVwBZAFcAecBXAFkAVwB5wFVAVYBVQGx + CAADRAF7CP8D/gH/Av0B/AH/Av0B+wH/AvwB+QH/AgABsgH/AgABlwH/AgABlwH/AgABmAH/Al4BZQHl + AlkBXAHMA04BmRAAA0QBewj/A/4B/wL9AfwB/wL9AfsB/wL8AfkB/wL7AfgB/wL6AfYB/wL4AfQB/wL7 + AfYB/wNEAXsIAANEAXsI/wP+Af8C/QH8Af8C/QH7Af8B0gGlAQAB/wHDAYcBAAH/AcMBhwEAAf8BwgGG + AQAB/wHDAYcBAAL/AcUBAAH/AlwBWQHMAzgBXANFAX8DygH/A8UB/wPFAf8DxQH/A8UB/wPFAf8DxQH/ + A8UB/wEAAZ8BAAH/AQAB5wEAAf8BAAHnAQAB/wEAAecBAAH/AQAB5wEAAf8BAAHnAQAB/wFYAWEBWAHm + CAADQwF3BP8D/gH/Av0B/AH/Av0B+wH/AvwB+QH/AvsB+AH/AgABqwH/AgAB9wH/AgAB9wH/AgAB9wH/ + AgAB9wH/AgAB9wH/AlkBXAHMEAADQwF3BP8DqwH/AzsB/wKrAakB/wI7AToB/wKpAaYB/wL6AfYB/wL4 + AfQB/wL3AfIB/wL7AfUB/wNDAXcIAANDAXcE/wP+Af8C/QH8Af8C/QH7Af8C/AH5Af8BzgGTAQAC/wHj + AZIC/wHVAQAC/wHRAQAC/wHRAQAC/wHRAQAC/wHYAQAB/wJcAVkBzANDAXgDyAH/AwAB/wMAAf8DAAH/ + AwAB/wMAAf8DAAH/AwAB/wEAAYMBAAH/AQABjwEAAf8BAAGPAQAB/wEAAesBAAH/AQABkQEAAf8BAAGm + AQAB/wFZAVwBWQHJCAADQgF2Av8B/gH/Av0B/AH/Av0B+wH/AvwB+QH/AvsB+AH/AvoB9gH/AgABxQH/ + AgABtgH/AgABtgH/AgABtwH/AloBYQHkAlkBXAHMA04BmRAAA0IBdgL/Af4B/wL9AfwB/wL9AfsB/wJA + AT8B/wL7AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL6AfMB/wNCAXYIAANCAXYC/wH+Af8C/QH8 + Af8C/QH7Af8C/AH5Af8C+wH4Af8B4QG0AQAB/wHZAZ0BAAH/AdkBnQEAAf8B2QGdAQAB/wHaAZ4BAAL/ + AeUBlwH/AlwBWQHMAzgBXANCAXYDywH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ + AQABlwEAAf8BAAHuAQAB/wEAAZQBAAH/A8sB/wNCAXYIAANCAXQC/gH9Af8C/QH7Af8C/AH5Af8C+wH4 + Af8C+gH2Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHuAf8C+gHyAf8DQgF0CAADMQFOAz0BZwM9AWcDPQFn + A0oBigPJAf8CyQHIAf8DyAH/A0gB/wLIAccB/wLTAdEB/wL3AfIB/wL2AfAB/wL1Ae4B/wL6AfIB/wNC + AXQIAANCAXQC/gH9Af8C/QH7Af8C/AH5Af8C+wH4Af8C+gH2Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHu + Af8B5QGpAQAB/wJfAVgB4wM4AVwEAANCAXQDzgH/AwAB/wMAAf8DAAH/AwAB/wMAAf8BuwHdAQAB/wMA + Af8DAAH/AwAB/wEAAYkBAAH/AQABmgEAAf8BAAGEAQAB/wPOAf8DQgF0CAADQQFyAv4B/AH/AvwB+QH/ + AvsB+AH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvkB7wH/A0EBcggAAz0BaQP6 + Af8D+gH/A/oB/wP6Af8D+gH/A/oB/wP6Af8DUQH/A/oB/wLCAcAB/wL2AfAB/wL1Ae4B/wL0AewB/wL5 + Ae8B/wNBAXIIAANBAXIC/gH8Af8C/AH5Af8C+wH4Af8C+gH2Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHu + Af8C9AHsAf8B7QHAAYQB/wJTAU8BpQgAA0EBcgPSAf8BAAGEAQAB/wGgAbkBAAH/AYQBlQEAAf8BuwHd + AQAB/wG7Ad0BAAH/AwAB/wG7Ad0BAAH/AwAB/wGjAboBAAH/AcwB5gGAAf8B7gH3AbMB/wMAAf8D0gH/ + A0EBcggAA0ABcQL9AfsB/wL7AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLx + AecB/wL3AeoB/wNAAXEIAAM+AWsD8QH/AekBgwFFAf8ByAFIASYB/wGtASwBCgH/AbgBLQELAf8B2gE/ + AR0B/wPxAf8DWQH/A/EB/wK7AbkB/wL1Ae4B/wL0AewB/wLxAecB/wL3AeoB/wNAAXEIAANAAXEC/QH7 + Af8C+wH4Af8C+gH2Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C8QHnAf8C9wHqAf8DQAFx + CAADQAFwA9YB/wMAAf8DAAH/AY4BnwEAAf8DAAH/AbsB3QEAAf8DAAH/AwAB/wG7Ad0BAAH/AZEBnAEA + Af8DAAH/AwAB/wMAAf8D1gH/A0ABcAgAA0ABbwL9AfoB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1 + Ae4B/wL0AewB/wLxAecB/wLsAd8B/wL0AeUB/wNAAW8IAAM/AW0D5wH/AekBgwFFAf8ByAFIASYB/wGt + ASwBCgH/AbgBLQELAf8B2gE/AR0B/wPnAf8DYQH/A+cB/wKyAbAB/wL0AewB/wLxAecB/wLsAd8B/wL0 + AeUB/wNAAW8IAANAAW8C/QH6Af8C+gH2Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C8QHn + Af8C7AHfAf8C9AHlAf8DQAFvCAADQAFuA9oB/wMAAf8DAAH/AwAB/wMAAf8BuwHdAQAB/wMAAf8DAAH/ + AwAB/wMAAf8DAAH/AwAB/wMAAf8D2gH/A0ABbggAAz8BbQL8AfgB/wL4AfQB/wL3AfIB/wL2AfAB/wL1 + Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLzAeIB/wM/AW0IAANAAXAD3wH/A98B/wPfAf8D3wH/ + A98B/wPfAf8D3wH/A4YB/wPfAf8CpwGlAf8C8QHnAf8C7AHfAf8C6AHZAf8C8wHiAf8DPwFtCAADPwFt + AvwB+AH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/AvMB4gH/ + Az8BbQgAAz8BbAPeAf8DAAH/AwAB/wMAAf8DAAH/AaYBvwEAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA + Af8DAAH/A94B/wM/AWwIAAM/AWwC/AH3Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C8QHnAf8C7AHf + Af8C6AHZAf8C5gHVAf8C8gHhAf8DPwFsCAADNgFZA0MBdwNDAXcDQwF3A0wBkwKNAYwB/wKMAYsB/wKM + AYoB/wKKAYgB/wKLAYkB/wKlAZ8B/wLsAd8B/wLoAdkB/wLmAdUB/wLyAeEB/wM/AWwIAAM/AWwC/AH3 + Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZAf8C5gHVAf8C8gHhAf8DPwFs + CAADPgFqA+EB/wMAAf8DAAH/AwAB/wMAAf8BkwGkAQAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA + Af8D4QH/Az4BaggAAz4BawL7AfYB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLm + AdUB/wLlAdQB/wLyAeEB/wM+AWsYAAM+AWsC+wH2Af8C9gHwAf8C9QHuAf8CjQGIAf8C8QHnAf8C7AHf + Af8C6AHZAf8C5gHVAf8C5QHUAf8C8gHhAf8DPgFrCAADPgFrAvsB9gH/AvYB8AH/AvUB7gH/AvQB7AH/ + AvEB5wH/AuwB3wH/AugB2QH/AuYB1QH/AuUB1AH/AvIB4QH/Az4BawgAAz0BaQPkAf8DAAH/AwAB/wMA + Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8D5AH/Az0BaQgAAz0BaQL6AfQB/wL1 + Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLmAdUB/wKkAZMB/wKkAZMB/wKkAZMB/wJFAUQBfBgA + Az0BaQL6AfQB/wLDAb4B/wKRAY0B/wLAAbgB/wKNAYUB/wK5Aa0B/wLmAdUB/wKkAZMB/wKkAZMB/wKk + AZMB/wJFAUQBfAgAAz0BaQL6AfQB/wL1Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLmAdUB/wKk + AZMB/wKkAZMB/wKkAZMB/wJFAUQBfAgAAz0BaAPqAf8D5QH/A+UB/wPlAf8D5QH/A+UB/wPlAf8D5QH/ + A+UB/wPlAf8D5QH/A+UB/wPlAf8D6gH/Az0BaAgAAz0BaAL6AfMB/wL0AewB/wLxAecB/wLsAd8B/wLo + AdkB/wLmAdUB/wLlAdQB/wK2AaUF/wM9AWgDGgElGAADPQFoAvoB8wH/AvQB7AH/AvEB5wH/AuwB3wH/ + AugB2QH/AuYB1QH/AuUB1AH/ArYBpQX/Az0BaAMaASUIAAM9AWgC+gHzAf8C9AHsAf8C8QHnAf8C7AHf + Af8C6AHZAf8C5gHVAf8C5QHUAf8CtgGlBf8DPQFoAxoBJQgAAzEBTQM8AWYDPAFmAzwBZgM8AWYDPAFm + AzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzEBTQgAAz0BZwL8AfUB/wL5Ae8B/wL2 + AeoB/wL0AeUB/wLzAeIB/wLyAeEB/wLyAeEB/wLCAbEB/wM9AWcDGgElHAADPQFnAvwB9QH/AvkB7wH/ + AvYB6gH/AvQB5QH/AvMB4gH/AvIB4QH/AvIB4QH/AsIBsQH/Az0BZwMaASUMAAM9AWcC/AH1Af8C+QHv + Af8C9gHqAf8C9AHlAf8C8wHiAf8C8gHhAf8C8gHhAf8CwgGxAf8DPQFnAxoBJVQAAzEBTQM8AWYDPAFm + AzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAxoBJCAAAzEBTQM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8 + AWYDPAFmAxoBJBAAAzEBTQM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAxoBJFAAAwsBDwMS + ARgDEgEZAxIBGAMQARUDDQESAwsBDwMKAQ4DCgEOAwwBEAMNARIDEAEVAxIBGAMTARoDEgEYAwsBDwML + AQ8DEgEYAxIBGQMSARgDEAEVAw0BEgMLAQ8DCgEOAwoBDgMMARADDQESAxABFQMSARgDEwEaAxIBGAML + AQ9LAAQBAQIDAwEEAwUEBwQKAQ0DDAEQAw4BEwMQARUDEQEXAxIBGQMTARoDEAEVAwcBCgMWAR4DIQEw + A0oBjQNPAaUDHQEpAxkBIwMVAR0DFAEbAxQBGwMWAR8DGgEkAx0BKgNKAYwDUgGmAyEBMAMWAR4DFgEe + AyEBMANKAY0DTwGlAx0BKQMZASMDFQEdAxQBGwMUARsDFgEfAxoBJAMdASoDSgGMA1IBpgMhATADFgEe + AwQBBgMQARYDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEAEW + AwQBBgsAAQEDAwEEAwYBCAMKBA4BEwMSARkDFgEfAxoBJQMkATUDPAFoA0MBeAM8AWgDJAE1Aw4BEwMG + AQgDCQEMA1QBqwNZAcwDCAELAwcBCQMGAQgDBQEHAwUBBwMGAQgDBwEJAwgBCwNUAasDWQHMAwkBDAMG + AQgDBgEIAwkBDANUAasDWQHMAwgBCwMHAQkDBgEIAwUBBwMFAQcDBgEIAwcBCQMIAQsDVAGrA1kBzAMJ + AQwDBgEIAzwBaANIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA1sB0AJcAWQB5wJcAWQB5wJc + AWQB5wJcAWQB5wJcAWQB5wJVAVYBsSgAAzkBYANbAb8D5AH/A1sBvwM5AWAIAANKAYsDVgGzA1kByQJZ + AVwByQJZAV0B0gFbAl4B2QFYAl4B3QFcAmEB3AFaAV0BXgHYAlgBXAHRA1sByANWAbkDWQHEA0oBiwgA + A0oBiwNWAbMDWQHJAlkBXAHJAlkBXQHSAVsCXgHZAVgCXgHdAVwCYQHcAVoBXQFeAdgCWAFcAdEDWwHI + A1YBuQNZAcQDSgGLBAADRQF/A8oB/wPFAf8DxQH/A8UB/wPFAf8DxQH/A8UB/wPFAf8CAAGhAf8CAAH3 + Af8CAAH3Af8CAAH3Af8CAAH3Af8CAAH3Af8CWAFhAeYcAAMwAU0DPAFmAzwBZgNBAXMD8gH/A/IB/wPy + Af8DQQFzCAADVgGzAYwBpAG/Af8BjwGnAcIB/wGVAawByAH/AZoBsQHNAf8BnwG1AdIB/wGiAbcB1QH/ + AaIBtwHVAf8BngG0AdEB/wGaAbABzQH/AZQBrAHHAf8BjwGnAcIB/wGMAaUBvwH/A1YBswgAA1YBswGM + AaQBvwH/AY8BpwHCAf8BlQGsAcgB/wGaAbEBzQH/AZ8BtQHSAf8BogG3AdUB/wGiAbcB1QH/AZ4BtAHR + Af8BmgGwAc0B/wGUAawBxwH/AY8BpwHCAf8BjAGlAb8B/wNWAbMEAANDAXgDyAH/AwAB/wMAAf8DAAH/ + AwAB/wMAAf8DAAH/AwAB/wIAAYkB/wIAAZcB/wIAAZcB/wIAAZcB/wIAAZgB/wIAAa4B/wJZAVwByRwA + AzwBZggAAzgBXANbAbwD/QH/A1sBvAM4AVwIAAJUAVYBqwGTAasBxgH/AQABigGkAf8BAAGDAZ0B/wEA + AYgBogH/AQABjQGnAf8BAAGQAaoB/wEAAZABqgH/AQABjQGnAf8BAAGJAaMB/wEAAYQBngH/AQABigGk + Af8BkwGrAcYB/wJUAVYBqwgAAlQBVgGrAZMBqwHGAf8BAAGKAaQB/wEAAYMBnQH/AQABiAGiAf8BAAGN + AacB/wEAAZABqgH/AQABkAGqAf8BAAGNAacB/wEAAYkBowH/AQABhAGeAf8BAAGKAaQB/wGTAasBxgH/ + AlQBVgGrBAADQgF2A8sB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ + AwAB/wPLAf8DQgF2HAADPAFmCAADDQESAzcBWgNAAW4DNwFaAw0BEggAA1EBogGcAbMBzwH/AQABgAGa + Af8BlAGtAccB/wGUAa0BxwH/AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/AZQBrQHHAf8BlAGtAccB/wGU + Aa0BxwH/AQABgAGaAf8BnAGzAc8B/wNRAaIIAANRAaIBnAGzAc8B/wEAAYABmgH/AZQBrQHHAf8BlAGt + AccB/wGUAa0BxwH/AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/AZQBrQHHAf8BlAGtAccB/wEAAYABmgH/ + AZwBswHPAf8DUQGiBAADQgF0A84B/wMAAf8DAAH/AwAB/wMAAf8DAAH/AbsB3QEAAf8DAAH/AwAB/wMA + Af8DAAH/AwAB/wMAAf8DzgH/A0IBdBwAAzwBZiAAAxQBGwJUAVYBqwGkAbsB1wH/AQABgAGaAf8BpwHA + AdoB/wGqAcEB3QH/Aa0BwwHgAf8BrwHEAeIB/wGvAcQB4gH/Aa0BwwHgAf8BqgHCAd0B/wGoAcAB2wH/ + AQABgAGaAf8BpAG7AdcB/wJUAVYBqwMUARsDFAEbAlQBVgGrAaQBuwHXAf8BAAGAAZoB/wGnAcAB2gH/ + AaoBwQHdAf8BrQHDAeAB/wGvAcQB4gH/Aa8BxAHiAf8BrQHDAeAB/wGqAcIB3QH/AagBwAHbAf8BAAGA + AZoB/wGkAbsB1wH/AlQBVgGrAxQBGwNBAXID0gH/AQABhAEAAf8BoAG5AQAB/wGEAZUBAAH/AbsB3QEA + Af8BuwHdAQAB/wMAAf8BuwHdAQAB/wMAAf8BowG6AQAB/wHMAeYBgAH/Ae4B9wGzAf8DAAH/A9IB/wNB + AXIcAAM8AWYgAAMzAVIDXgHQAasBwQHeAf8DAAH/AQABhgGgAf8BAAGGAaAB/wEAAYYBoAH/AgABjwH/ + AgABjwH/AQABhgGgAf8BAAGGAaAB/wEAAYYBoAH/AwAB/wGrAcEB3gH/A14B0AMzAVIDMwFSA14B0AGr + AcEB3gH/AwAB/wEAAYYBoAH/AQABhgGgAf8BAAGGAaAB/wIAAY8B/wIAAY8B/wEAAYYBoAH/AQABhgGg + Af8BAAGGAaAB/wMAAf8BqwHBAd4B/wNeAdADMwFSA0ABcAPWAf8DAAH/AwAB/wGOAZ8BAAH/AwAB/wG7 + Ad0BAAH/AwAB/wMAAf8BuwHdAQAB/wGRAZwBAAH/AwAB/wMAAf8DAAH/A9YB/wNAAXADHQEpAWkBWwFZ + AdAB2gFVATMB/wFpAVsBWQHQAx0BKQgAAzwBZggAAw8BFAM6AWEDQwF3AzoBYQMPARQEAANIAYYBqwHC + Ad4B/wGwAcUB4wH/AgABjAH/AQABlAGuAf8BAAGUAa4B/wEAAZQBrgH/AQABgwGdAf8BAAGDAZ0B/wEA + AZQBrgH/AQABlAGuAf8BAAGUAa4B/wGAAgAB/wGqAZwBlQH/AasBwgHeAf8DSAGGA0gBhgGrAcIB3gH/ + AbABxQHjAf8CAAGMAf8BAAGUAa4B/wEAAZQBrgH/AQABlAGuAf8BAAGDAZ0B/wEAAYMBnQH/AQABlAGu + Af8BAAGUAa4B/wEAAZQBrgH/AgABjAH/AbABxQHjAf8BqwHCAd4B/wNIAYYDQAFuA9oB/wMAAf8DAAH/ + AwAB/wMAAf8BuwHdAQAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8D2gH/A0ABbgFlAVsBVwHQ + AdQBiQFrAf8B6AG/AbIB/wHUAYkBawH/AWUBWwFXAdAIAAM8AWYIAAM4AV4DWgG9A+QB/wNaAb0DOAFe + BAACRQFGAX8BrgHFAeEB/wGPAaYBwgH/AQABgwGdAf8BjQGmAb8B/wGNAaYBvwH/AY0BpgG/Af8BAAGV + Aa4B/wEAAZUBrgH/AY0BpgG/Af8BjQGmAb8B/wGNAaYBvwH/AZsCAAH/AaICAAH/AawBoAGWAf8CRQFG + AX8CRQFGAX8BrgHFAeEB/wGPAaYBwgH/AQABgwGdAf8BjQGmAb8B/wGNAaYBvwH/AY0BpgG/Af8BAAGV + Aa4B/wEAAZUBrgH/AY0BpgG/Af8BjQGmAb8B/wGNAaYBvwH/AQABgwGdAf8BjwGmAcIB/wGuAcUB4QH/ + AkUBRgF/Az8BbAPeAf8DAAH/AwAB/wMAAf8DAAH/AaYBvwEAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA + Af8DAAH/A94B/wM/AWwBrQFCASAB/wHwAccBugH/AfABxwG6Af8B8AHHAboB/wGtAUIBIAH/AzwBZgM8 + AWYDPAFmAzwBZgM8AWYDQAFvA/IB/wPyAf8D8gH/A0ABbwQAAygBPQNEAXkCTQFOAZYBAAGVAa8B/wGe + AbcB0QH/AZ4BtwHRAf8BngG3AdEB/wGNAaYBwAH/AaICAAH/AbACAAH/AbACAAH/AbACAAH/AakCAAL/ + AcUBAAH/AmEBWgHkAkgBRwGDAygBPQNEAXkCTQFOAZYBAAGVAa8B/wGeAbcB0QH/AZ4BtwHRAf8BngG3 + AdEB/wGNAaYBwAH/AY0BpgHAAf8CAAGhAf8CAAGQAf8CAAGQAf8CAAGJAf8CVQFcAeoCWgFhAeQDVQGy + Az4BagPhAf8DAAH/AwAB/wMAAf8DAAH/AZMBpAEAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ + A+EB/wM+AWoBZgFeAVkB0AHjAZ4BhwH/AfcBzgHBAf8B4wGeAYcB/wFmAV4BWQHQFAADNQFXA1kBuAP9 + Af8DWQG4AzUBVwwAAksBTAGPAY0BpgHAAf8BrgHHAeEB/wGuAccB4QH/Aa4BxwHhAf8BngG3AdEB/wG8 + AYYBAAL/AeMBkgL/AdUBAAL/AdEBAAL/AdEBAAL/AdEBAAL/AdgBAAH/AlwBWQHMCAACSwFMAY8BjQGm + AcAB/wGuAccB4QH/Aa4BxwHhAf8BrgHHAeEB/wGeAbcB0QH/AZ4BtwHRAf8CAAGmAf8CAAH3Af8CAAH3 + Af8CAAH3Af8CAAH3Af8CAAH3Af8CWQFcAcwDPQFpA+QB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA + Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wPkAf8DPQFpAx0BKQFqAWABXgHQAekBgwFbAf8BagFgAV4B0AMd + ASkUAAMNAREDNAFUAz0BZwM0AVQDDQERDAADRAF7A10B8AGsAcUB3wH/AbkB0gHsAf8BuQHSAewB/wGr + AcQB3gH/Ab8BnAEAAf8BzQGWAQAB/wHNAZYBAAH/AcoBkwEAAf8DKwH8Af8B5QGXAf8CXAFZAcwDOAFc + CAADRAF7A10B8AGsAcUB3wH/AbkB0gHsAf8BuQHSAewB/wGrAcQB3gH/AasBxAHeAf8CAAHDAf8CAAG1 + Af8CAAGzAf8DKwH8Al4BZQHlAlkBXAHMA04BmQM9AWgD6gH/A+UB/wPlAf8D5QH/A+UB/wPlAf8D5QH/ + A+UB/wPlAf8D5QH/A+UB/wPlAf8D5QH/A+oB/wM9AWhIAAMuAUgDUgGpA2EB7gGoAcEB2wH/AagBwQHb + Af8BqAHBAdsB/wGoAcEB2wH/AagBwQHbAf8BqAHBAdsB/wNhAe4CYQFUAe4CXwFaAdsDOAFcDAADLgFI + A1IBqQNhAe4BqAHBAdsB/wGoAcEB2wH/AagBwQHbAf8BqAHBAdsB/wGoAcEB2wH/AagBwQHbAf8DYQHu + A1IBqQMuAUgIAAMxAU0DPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8 + AWYDPAFmAzwBZgMxAU1IAAMFAQcDLQFFAj8BQAFuA0QBeQNEAXkDRAF5A0QBeQNEAXkDRAF5Aj8BQAFu + A1UBsgM4AV4QAAMFAQcDLQFFAj8BQAFuA0QBeQNEAXkDRAF5A0QBeQNEAXkDRAF5Aj8BQAFuAy0BRQMF + AQdLAAEBAwIBAwMEAQYDBwQKAQ4DDQESAxABFgMSARgDEwEaAxMBGgMTARoDEgEYAw4BEwMJAQwDBAEG + AwABAQMWAR8CUQFPAZwCWAFWAcECWAFWAcECWAFWAcECWAFWAcECWAFWAcECWAFWAcECWAFWAcECWAFW + AcECUQFPAZwDGAEiEAADPQFqA0gBhQNIAYUDSAGFA0gBhQNIAYUDSAGFA0gBhQNIAYUDSAGFA0gBhQNI + AYUDSAGFA0ABcAMdASoDEgEYAw0BEgMfASwDQQFyA0gBhwNIAYcDSAGHA0gBhwMAAf8DWgHYA1ABpANI + AYcDSAGHA0gBhwNBAXIDHwEsAw0BEgMAAQEDBAEGAwkBDAMPBBQBHAMZASMDHgErAyEBMAMjATMDIwEz + AyMBMwNDAXgDMwFSAxIBGAMIAQsDAQECAwwBEANTAaoB/QH0AeEB/wH7AfIB3AH/AfoB8QHcAf8B+gHw + AdsB/wH5AfAB2gH/AfkB7wHZAf8B+QHuAdgB/wH8AfIB3wH/A1YBswMeASsDEwEaAw0BEQgAA0QBewPr + Af8D5wH/A+cB/wPnAf8D5wH/A+cB/wPnAf8D5wH/A+cB/wPnAf8D5wH/A+sB/wNEAXsDEAEVAwkBDAMH + AQkDEAEWA0cBgg7/Af4B/wGAAbYBxwH/AdkB9AL/AQABnwGvAf8BuwHZAd0B/wL8AfgB/wL+AfkB/wNH + AYIDEAEWAwcBCSwAAkwBSwGPAkwBSwGPAyoBQQwAAk8BTgGXAfsB8gHcAf8B9QHsAdIB/wH1AesB0QH/ + AfQB6gHQAf8B8wHoAc4B/wHyAeYBzAH/AfEB5AHKAf8B+AHtAdcB/wJhAVgB5gJYAVYBwQJRAU8BnAMY + ASIIAANCAXYD6gH/A+IB/wPiAf8D4gH/A+IB/wPiAf8D4gH/A+IB/wPiAf8D4gH/A+IB/wPqAf8DQgF2 + EAADRAF7CP8D/gH/Av0B/AH/AdcB6QHuAf8BAAG1AcUB/wEAAeYB9wH/AQABnQGtAf8BtgHWAdgB/wL7 + AfYB/wNEAXsIAANOAZkBXAJZAckBVgJVAbQDSAGGAyMBMwgAAxoBJAM4AV0CRgFFAX4DSgGNAkwBSwGP + A1YBswJMAUsBjwMqAUEIAAJMAUsBkAH6AfEB3AH/AfUB6wHRAf8B9AHqAdAB/wHzAegBzgH/AfIB5gHM + Af8B8QHkAcoB/wHwAeIByAH/AfcB6wHWAf8BzgGrAYIB/wH8AfIB3wH/A1YBswMTARoDEwEaAw0BEQNB + AXMD7QL/AZkBAAH/A+YB/wO9Af8DrAH/A70B/wO9Af8DrAH/A70B/wPJAf8D5gH/A+0B/wNBAXMQAAND + AXcE/wP+Af8C/QH8Af8C/QH7Af8C/AH5Af8BvgHkAegB/wEAAbQBxAH/AQAB5gH3Af8BAAGdAawB/wG6 + AdkB2gH/A0MBdwgAAVwCWQHMAysB/AJZAUIB9QJlAV4B5QFcAVoBWQHPAkABPwFvAzEBTwNMAZICUgFR + AaECVgFUAasCVgFVAbEDVgGzA1YBswNWAbMCTAFLAY8DIwEzBAADSgGKAfoB8AHbAf8B9AHqAdAB/wHz + AegBzgH/AfIB5gHMAf8B8QHkAcoB/wHwAeIByAH/Ae8B4AHGAf8B9wHqAdUB/wHNAaoBAAH/AfgB7QHX + Af8CYQFYAeYCWAFWAcECUQFPAZwDGAEiA0ABcQPwAf8D6wH/A+sB/wPrAf8D6wH/A+sB/wPrAf8D6wH/ + A+sB/wPrAf8D6wH/A/AB/wNAAXEQAANCAXYC/wH+Af8C/QH8Af8C/QH7Af8C/AH5Af8C+wH4Af8C+gH2 + Af8BvAHiAeUB/wEAAbQBwwH/AQAB5gH3Af8BAAGeAawB/wNOAZkIAAFcAlkBzAH5AcIBAAL/AbQBAAL/ + AbMBAAH/Ak0BKQH6AmEBXQHiAlkBVwHCA1QBrwNWAbMDVgGzA1YBswNWAbMDVgGzA1YBswJMAUsBjwMj + ATMEAANIAYQB+QHwAdoB/wHzAegBzgH/AfIB5gHMAf8B8QHkAcoB/wHwAeIByAH/Ae8B4AHGAf8B7gHd + AcMB/wH2AecB0gH/AdABrAGCAf8B9wHrAdYB/wHOAasBggH/AfwB8gHfAf8DUwGqBAADQAFuA/MB/wIA + AcIB/wPvAf8DvAH/A8UB/wPFAf8DxQH/A7wB/wPFAf8DvAH/A8UB/wPzAf8DQAFuEAADQgF0Av4B/QH/ + Av0B+wH/AvwB+QH/AvsB+AH/AvoB9gH/AvgB9AH/AvcB8gH/AbsB4QHiAf8BAAGzAcIB/wEAAeYB9wH/ + A1YBuAMgAS4EAANOAZkCXQFZAdICXwFYAeMCqAFAAf0B/AGwAQAB/wMrAfwCYgFYAe8CWwFZAcMDVQGy + AlEBUAGfA0wBkwJMAUsBjwNWAbMCTAFLAY8DKgFBCAACRgFFAX4B+QHvAdkB/wHyAeYBzAH/AfEB5AHK + Af8B8AHiAcgB/wHvAeABxgH/Ae4B3QHDAf8B6gHXAb0B/wH0AeQBzgH/AdIBrgGEAf8B9wHqAdUB/wHN + AaoBAAH/AfgB7QHXAf8CTwFOAZcEAAM/AWwD9wH/A/QB/wP0Af8D9AH/A/QB/wP0Af8D9AH/A/QB/wP0 + Af8D9AH/A/QB/wP3Af8DPwFsEAADQQFyAv4B/AH/AvwB+QH/AvsB+AH/AvoB9gH/AvgB9AH/AvcB8gH/ + AvYB8AH/AvUB7gH/AbkC3wH/Aq8BqgH/A/cB/wNLAY4DLQFGAwQBBgMiATICTgFNAZYCXgFaAdgCfwEw + Af4B7gGoAQAB/wJqAUEB+QJkAVwB5wNQAZoDPQFpAxgBIQJMAUsBjwJMAUsBjwMqAUEMAANDAXgB+QHu + AdgB/wHxAeQBygH/AfAB4gHIAf8B7wHgAcYB/wHuAd0BwwH/AeoB1wG9Af8B5wHQAbYB/wHyAeIBzAH/ + AdQBsAGFAf8B9gHnAdIB/wHQAawBggH/AfcB6wHWAf8CTAFLAZAEAAM+AWoD+gH/AQABqgEAAf8D+AH/ + A7sB/wPMAf8D1AH/A9oB/wP4Af8D+AH/A/gB/wP4Af8D+gH/Az4BahAAA0ABcQL9AfsB/wL7AfgB/wL6 + AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wLeAdQB/wNWAbYCgAL/AlYBWAHB + CAADAgEDA1UBtQJkAVMB8QHnAa4BAAH/AeEBpQEAAf8CZAFTAfEDVQG1AwIBAwQAAzUBVwNEAXoQAAJC + AUEBcwH4Ae0B2AH/AfAB4gHIAf8B7wHgAcYB/wHuAd0BwwH/AeoB1wG9Af8BwgGkAYUB/wHCAaQBhQH/ + AcIBpAGFAf8BvwGXAQAB/wH0AeQBzgH/AdIBrgGEAf8B9wHqAdUB/wNKAYoEAAM9AWgD/QH/A/wB/wP8 + Af8D/AH/A/wB/wP8Af8D/AH/AasBwAHUAf8CAAGZAf8BkQGmAboB/wPKAf8DywH/Az0BaBAAA0ABbwL9 + AfoB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wLsAd8B/wL0AeUB/wNM + AY8DVAGvAyoBQAMDAQQDGQEjAz0BaQJQAU8BmwJfAVcB6AJqAWEB+QHtAbYBAAH/An8BZQH+Al4BWgHY + Ak4BTQGWAyABLwJcAVkBzAJcAVkBzAM4AVwMAAJAAT8BbgH4AewB1wH/Ae8B4AHGAf8B7gHdAcMB/wHq + AdcBvQH/AecB0AG2Af8B0gG2AZoC/wH2AeUB/wHWAbEBhwH/AeABwwGkAf8B8gHiAcwB/wHUAbABhQH/ + AfYB5wHSAf8DSAGEBAADPQFnCP8BsAHFAdoB/wIAAaAB/wGwAcUB2gX/Aa0BwgHWAf8CAAGZAf8BgQG0 + AeYB/wIAAaoB/wGTAacBvAH/A8wB/wM9AWcQAAM/AW0C/AH4Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHu + Af8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZAf8C8wHiAf8DPwFtCAACPwE+AWwDTAGTA1EBnwNVAbIDWwHD + Al0BTgHwAysB/AH0Ab8BAAH/AqgBQAH9Al8BWAHjAlwBWAHRAlwBWQHMAfQBwgEAAf8CXAFZAcwDOAFc + CAADPgFqAfsB8QHdAf8B9wHqAdUB/wH1AecB0gH/AfQB5AHOAf8B8gHiAcwB/wHcAcIBpwH/AdcBsgGJ + Af8BwgGgAQAB/wHCAaQBhQH/AcIBpAGFAf8BvwGXAQAB/wH0AeQBzgH/AkYBRQF+BAADPQFpA7sB/wO5 + Af8CAAGYAf8BjwHCAfEB/wIAAaQB/wIAAZYB/wIAAYkB/wGEAbcB6AH/AgABqgH/AYQBtwHoAf8CAAGu + Af8CAAGSAf8DUwGqAxMBGgwAAz8BbAL8AfcB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wLs + Ad8B/wLoAdkB/wLmAdUB/wLyAeEB/wM/AWwIAAJMAUsBjwNWAbMDVgGzA1YBswNUAa8CWQFXAcICYQFd + AeIDTQH6AfcBxQEAAf8B9gHEAQAB/wH4AcoBAAH/AfgBywEAAf8B8gG7AQAB/wH2AcYBAAH/AlwBWQHM + Ay4BSAQAAzEBTQM9AWcCUwFSAagB4AHAAZoB/wHbAbkBjwH/AdoBuAGOAf8B2AGzAYoB/wHhAcQBpQH/ + AdIBtgGaAv8B9gHlAf8B1gGxAYcB/wHgAcMBpAH/AfIB4gHMAf8DQwF4BAADNwFbA2AB1APbAf8BmwGx + AcYB/wEAAYoBvQH/AZUByAH1Af8CAAGfAf8BiQG8AesB/wIAAaoB/wGJAbwB6wH/AQABiAG7Af8BiQG8 + AesB/wFzAn8B/gNdAe0CVgFZAb4DOAFeCAADPgFrAvsB9gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/ + AuwB3wH/AugB2QH/AuYB1QH/AuUB1AH/AvIB4QH/Az4BawgAAkwBSwGPA1YBsQNUAawDUgGhA0wBkgMx + AU8CQAE/AW8CXAFZAc8CZQFkAeUDZQH0AysB/AH6AdABhAH/AfYBwQEAAf8B+AHNAYEB/wJcAVkBzAMu + AUgMAAM+AWoB+wHxAd0B/wH3AeoB1QH/AfUB5wHSAf8B9AHkAc4B/wHyAeIBzAH/AdwBwgGnAf8B1wGy + AYkB/wHCAaABAAH/AcIBpAGFAf8BwgGkAYUB/wJSAVABowQAAxgBIgM2AVkDPAFmAzwBZgFLAkwBjwFa + Al4B2AGdAdAB+AH/AQABiAG7Af8BkgHFAfAB/wEAAYgBuwH/AZ0B0AH4Af8BhwG6AecB/wEAAakB2gH/ + AQABsAHgAf8DXAHqAVICUwGoCAADPQFpAvoB9AH/AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/ + AuYB1QH/AqQBkwH/AqQBkwH/AqQBkwH/AkUBRAF8CAADPwFsA0oBjQJGAUUBfwM4AV4DGgEkCAADIwEz + A0gBhQNWAbMCXAFZAckCXAFZAcwB/AHVAYkB/wJcAVkBzAM4AVwQAAMxAU0DPQFnAlMBUgGoAeABwAGa + Af8B2wG5AY8B/wHaAbgBjgH/AdgBswGKAf8B4QHEAaUB/wHSAbYBmgL/AfYB5QH/AkABPwFuAxwBJxQA + AzEBTgNQAZ0BAAGcAcsB/wGkAdcB/AH/AQABiAG7Af8BpAHXAfwB/wGMAb8B6wH/AQABpAHVAf8BAAGt + Ad0B/wGEAbcB5QH/AYwBvwHsAf8DUAGdCAADPQFoAvoB8wH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/ + AuYB1QH/AuUB1AH/ArYBpQX/Az0BaAMaASU0AAJcAVkBzAJcAVkBzAM4AVwcAAM+AWoB+wHxAd0B/wH3 + AeoB1QH/AfUB5wHSAf8B9AHkAc4B/wHyAeIBzAH/AdwBwgGnAf8DPgFqAxsBJhgAA0wBkwGlAdgB/AH/ + AQABrwHdAf8BAAGdAcwB/wGpAdwC/wGlAdgB/AH/AYoBvQHnAf8BjgHBAeoB/wGTAcYB7wH/AZkBzAH0 + Af8DTAGTAzABSwgAAz0BZwL8AfUB/wL5Ae8B/wL2AeoB/wL0AeUB/wLzAeIB/wLyAeEB/wLyAeEB/wLC + AbEB/wM9AWcDGgElOAADTgGZAzgBXCAAAzEBTQM9AWcDPQFnAz0BZwM9AWcDPQFnAz0BZwMaASQcAAMu + AUcDSgGMA0oBjANKAYwDSgGMA0oBjANKAYwDSgGMA0oBjANKAYwDLgFHDAADMQFNAzwBZgM8AWYDPAFm + AzwBZgM8AWYDPAFmAzwBZgM8AWYDGgEkEAABQgFNAT4HAAE+AwABKAMAAUADAAFQAwABAQEAAQEFAAGA + AQIWAAP/AwAC/wwAAYABAwYAAcABAwYAAcABAwYAAcABAwYAAcABAwYAAcABAwYAAcABAwYAAcABAwYA + AcABAwYAAcABAwYAAcABAwHzAc8EAAHAAQEB8AEPBAABwAEAAfgBHwQAAeABAAL/BAAC/wH+AT8B/wHj + Af8B8wL/Af4BHwH/AeNSAAEMATABDAEwAQwBMAIAAQwBMAEMATABDAEwAgABDAEwAQwBMAEMATACAAn/ + AeMCAAHABwABwAUAAcABAAHwAQABwAMAAcABAAHwAQABwAMAAcABAAHwAQABwAMAAcABAwIAAcABAQIA + AcABAwIAAcABAwIAAcABAwIAAcABAwIAAcABAwIAAcABAwIAAcABAwIAAcABAwIAAcABAwIAAcABAwIA + AcABAwHwAQABwAEDAgABwAEDAfABAAHAAQMCAAHAAQMB8AEAAcABAwIAAcABBwHwAQEBwAEHAv8BwAEP + AfABAwHAAQ8C/wQAAv8BwAcAAcAHAAH/AcEBgAEBAYABAQIAAf4BAQGAAQEBgAEBAgAB/gHBAYABAQGA + AQECAAH+AcEBgAEBAYABAQIAAf4B/wYAAf4B/wYAAQYBwQYAAQYBwQcAAQEGAAEHAcEBwAEAAcADAAEH + AcEBwAEAAcADAAL/AcABAQHAAQMCAAL/AcABAwHAAQMC/wMAAQ8HAAEDBAAB/wHjAYABAwEAAQMBwAED + AQYBAQGAAgABAwHAAQMCAAGAAgABAwHAAQMCAAGAAQEBAAEDAcABAQEAAQEBgAEBAQABAwHAAgABAwGA + AQEBAAEDAcABAAHAAScBgAEBAQABAwHAAgABAwGAAQEBAAEDAcABAwEAAQEBgAEBAQABAQHAAQMCAAGA + AQECAAHAAQMCAAHgAQECAAHAAQMBBgEBAeABAQHwAQABwAEDAf8B4wH4AQMB8AEAAcABBwH/AecB+AEH + AfABAQHAAQ8L @@ -944,20 +964,29 @@ that have the "Necessary update" status and the newest one. iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJxSURBVDhPrZNrSFNhGMdf3YRwfYouKrjS7it1i2Wm1rpY - ygIzC50SnG1qrSgaZtCSkD6kZQQFESLTCClIMYKmzNHWjVBRtoqDzG3eGF1YKOgZ0Qfl6X1eXwdG0Jf+ - 8IP3PO//9xw4cMj/j8qRFK92VcvUfa1xWa5eBM84wzve+ntkmc4ixR73y4OW0UD1renZyw2h+VoKnnVV - /gDeYYfXl0eW6Shak+95JzRPSzVNP0C48Q0M1yahpNbPqGmKgNAYkVbRDna5xrOtO1mhdTqExgmpon4S - ym0TjLq7AcCMjP8C/YXPgHeVdROSQtvjQIfbhMSrntfkCx+DZVdDUGwdiWG9PcIWiKGfUHBmmM1OXgnA - rvLBIDpcJyRuc2dbmW1srvCcD5bQmfoh43gvpB/pYmw62s3Yqn8BGoNrDh2u44InfRX14jy+5YB5EDSn - 3GBr9oDX6wVRFOFhxxBs0TtiqPLd8+hwnS7Y2OHSCW8X8oQB2Fn6BlQlHthe7IIHjwcgGAyCzuhhsyWy - dK8X0OE6XbDhUfshYVBSVwxBlmGRAsswk+3PPsVmS6zXf5DQ4Tr9iKmtlrRC91hO1SjsNvoZN1t8EA6H - Qbguwv2nU7E5krK3ZxwdrtMoW5JXpNmdOaZANNfyFXLPfoHTNh9EIhGYmZmBO+0imyGaE/5ogtLuRIfb - i5El3dMr0tv6s82hqO7SLOynaCp9jLzz39mz1hiKJtIOdrn2RxLNxxJWN71K3dc7lW2iiwxjCwiecYZ3 - 2OHtZZFT1lF2EJnyMJGXNhD5xU6SYH3PwDPO8I6QDAr+VOjEEk9ZSVlLSfkH+CLsUoeQ32lWd+HlE+lB - AAAAAElFTkSuQmCC + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJySURBVDhPrZNtSFNRGMePTiFcn6IXFVxp7ytfFstMrduL + pSywZeGcBFen1oqiYQYtCelDWkZQECGiRkhBhhE0xxxtRhEqiqu4ydymU0YvLBR0I/qw8XSe43FgBH3p + Dz849zn/33PhwiX/P0pLcnyOvVaW098el223InjGGd7x1t8jy7KVyPc4Xh00Tnhqb83OX26SIvUUPAs1 + bg/eYYfXl0eWZSlZU+h8K7bOhupafoB44xtUXJsGbb2bUdcSBLE5GFpFO9jlGs+23hS52mYRm/0hfeM0 + 6Mx+RsNdD2DGp36B5sInwLvKBn9Iru6zoMNtQuKVL+oKxQ/e8qs+KDWNxzDdHmcLJN9PKDozymYnr3hg + l27Yiw7XCYnb3NNZbp5cKD7ngiWE6kHIPG6FjCPPGZuO9jK2al6CqsK+gA7XccGTfn2jFMG3HDAMg+qU + A8ytThgbGwNJkuBh9whs0VhiKNWOCDpcpws2dtsF3UC0QByCnWVvQKl1wvZSOzx4PARerxeEKiebLZEt + DETR4TpdsOFR1yFxOJSjH4HsikWKjKNM7nj2MTZbYr3mfQgdrtOPmNZuTC92TObVTMDuKjfjZpsLAoEA + iNcluP90JjZHUvf2TaHDdRpFW8qK9A5bXrUnnG/8Cvlnv8BpswuCwSDMzc3BnS6JzRDVCXc4UdFhQ4fb + i5El39PIMzoHcw2+sHBpHvZTVJUuRsH57+xZXeULJ9EOdrn2R5IMxxJXt7xO22edya2mi7SfowiecYZ3 + 2OHtZUmgrKPsIDLFYZJQ1kQSLvaQRNM7Bp5xhneEZFLwp0InlnjKSspaSuo/wBdhlzqE/Ab5pXefUwEq + nwAAAABJRU5ErkJggg== + + True + + + True + + + True + AAABAAkAICAQAAEABADoAgAAlgAAABAQEAABAAQAKAEAAH4DAAAwMAAAAQAIAKgOAACmBAAAICAAAAEA diff --git a/nUpdate.Administration/UI/Dialogs/PackageEditDialog.Designer.cs b/nUpdate.Administration/UI/Dialogs/PackageEditDialog.Designer.cs index 8c3630b4..1793919a 100644 --- a/nUpdate.Administration/UI/Dialogs/PackageEditDialog.Designer.cs +++ b/nUpdate.Administration/UI/Dialogs/PackageEditDialog.Designer.cs @@ -39,7 +39,8 @@ private void InitializeComponent() System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("General", 2, 2); System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("Changelog", 3, 3); System.Windows.Forms.TreeNode treeNode3 = new System.Windows.Forms.TreeNode("Availability", 0, 0); - System.Windows.Forms.TreeNode treeNode4 = new System.Windows.Forms.TreeNode("Operations", 4, 4); + System.Windows.Forms.TreeNode treeNode4 = new System.Windows.Forms.TreeNode("Conditions", 16, 16); + System.Windows.Forms.TreeNode treeNode13 = new System.Windows.Forms.TreeNode("Operations", 4, 4); System.Windows.Forms.ListViewGroup listViewGroup1 = new System.Windows.Forms.ListViewGroup("Files", System.Windows.Forms.HorizontalAlignment.Left); System.Windows.Forms.ListViewGroup listViewGroup2 = new System.Windows.Forms.ListViewGroup("Registry", System.Windows.Forms.HorizontalAlignment.Left); System.Windows.Forms.ListViewGroup listViewGroup3 = new System.Windows.Forms.ListViewGroup("Processes", System.Windows.Forms.HorizontalAlignment.Left); @@ -78,6 +79,10 @@ private void InitializeComponent() System.Windows.Forms.ListViewItem listViewItem11 = new System.Windows.Forms.ListViewItem(new string[] { "Execute script", "Executes a C#-script."}, 15); + System.Windows.Forms.TreeNode treeNode5 = new System.Windows.Forms.TreeNode("Program directory", 0, 0); + System.Windows.Forms.TreeNode treeNode6 = new System.Windows.Forms.TreeNode("AppData", 0, 0); + System.Windows.Forms.TreeNode treeNode7 = new System.Windows.Forms.TreeNode("Temp directory", 0, 0); + System.Windows.Forms.TreeNode treeNode8 = new System.Windows.Forms.TreeNode("Desktop", 0, 0); this.categoryImageList = new System.Windows.Forms.ImageList(this.components); this.cancelToolTip = new System.Windows.Forms.ToolTip(this.components); this.saveButton = new System.Windows.Forms.Button(); @@ -87,18 +92,18 @@ private void InitializeComponent() this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.loadingLabel = new System.Windows.Forms.Label(); this.categoryTreeView = new nUpdate.Administration.UI.Controls.ExplorerTreeView(); - this.controlPanel1 = new BottomPanel(); + this.controlPanel1 = new nUpdate.Internal.UI.Controls.BottomPanel(); this.categoryTabControl = new nUpdate.Administration.UI.Controls.TablessTabControl(); this.generalTabPage = new System.Windows.Forms.TabPage(); this.generalPanel = new System.Windows.Forms.Panel(); this.includeIntoStatisticsInfoLabel = new System.Windows.Forms.Label(); this.includeIntoStatisticsCheckBox = new System.Windows.Forms.CheckBox(); - this.line2 = new Line(); + this.line2 = new nUpdate.Internal.UI.Controls.Line(); this.developmentBuildNumericUpDown = new System.Windows.Forms.NumericUpDown(); this.necessaryUpdateInfoLabel = new System.Windows.Forms.Label(); this.necessaryUpdateCheckBox = new System.Windows.Forms.CheckBox(); - this.line3 = new Line(); - this.line1 = new Line(); + this.line3 = new nUpdate.Internal.UI.Controls.Line(); + this.line1 = new nUpdate.Internal.UI.Controls.Line(); this.architectureInfoLabel = new System.Windows.Forms.Label(); this.buildNumericUpDown = new System.Windows.Forms.NumericUpDown(); this.descriptionLabel = new System.Windows.Forms.Label(); @@ -155,6 +160,34 @@ private void InitializeComponent() this.operationsListView = new nUpdate.Administration.UI.Controls.ExplorerListView(); this.itemName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.Description = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.conditionsTabPage = new System.Windows.Forms.TabPage(); + this.conditionHelpLinkLabel = new System.Windows.Forms.LinkLabel(); + this.line4 = new nUpdate.Internal.UI.Controls.Line(); + this.rolloutConditionModeComboBox = new System.Windows.Forms.ComboBox(); + this.rolloutConditionModeLabel = new System.Windows.Forms.Label(); + this.conditionsDataGridView = new System.Windows.Forms.DataGridView(); + this.Key = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.Value = new System.Windows.Forms.DataGridViewTextBoxColumn(); + this.Negative = new System.Windows.Forms.DataGridViewCheckBoxColumn(); + this.replaceFilesTabPage = new System.Windows.Forms.TabPage(); + this.filesPanel = new System.Windows.Forms.Panel(); + this.filesDataTreeView = new nUpdate.Administration.UI.Controls.ExplorerTreeView(); + this.replaceFilesToolStrip = new System.Windows.Forms.ToolStrip(); + this.addFolderButton = new System.Windows.Forms.ToolStripSplitButton(); + this.addExistingFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.addFolderContentToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.addVirtualFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.addFilesButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.removeEntryButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator9 = new System.Windows.Forms.ToolStripSeparator(); + this.infoButton = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.filesList = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.filesImageList = new System.Windows.Forms.ImageList(this.components); this.loadingPanel.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); this.controlPanel1.SuspendLayout(); @@ -180,6 +213,11 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.unsupportedBuildNumericUpDown)).BeginInit(); this.operationsTabPage.SuspendLayout(); this.operationsPanel.SuspendLayout(); + this.conditionsTabPage.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.conditionsDataGridView)).BeginInit(); + this.replaceFilesTabPage.SuspendLayout(); + this.filesPanel.SuspendLayout(); + this.replaceFilesToolStrip.SuspendLayout(); this.SuspendLayout(); // // categoryImageList @@ -190,7 +228,7 @@ private void InitializeComponent() this.categoryImageList.Images.SetKeyName(1, "blue-documents-stack.png"); this.categoryImageList.Images.SetKeyName(2, "property.png"); this.categoryImageList.Images.SetKeyName(3, "document--pencil.png"); - this.categoryImageList.Images.SetKeyName(4, "node-delete-previous.png"); + this.categoryImageList.Images.SetKeyName(4, "node-select.png"); this.categoryImageList.Images.SetKeyName(5, "sofa--arrow.png"); this.categoryImageList.Images.SetKeyName(6, "sofa--minus.png"); this.categoryImageList.Images.SetKeyName(7, "system-monitor--minus.png"); @@ -202,6 +240,7 @@ private void InitializeComponent() this.categoryImageList.Images.SetKeyName(13, "wall--pencil.png"); this.categoryImageList.Images.SetKeyName(14, "wall--plus.png"); this.categoryImageList.Images.SetKeyName(15, "script-code.png"); + this.categoryImageList.Images.SetKeyName(16, "toolbox.png"); // // cancelToolTip // @@ -299,15 +338,20 @@ private void InitializeComponent() treeNode3.Name = "availabilityNode"; treeNode3.SelectedImageIndex = 0; treeNode3.Text = "Availability"; - treeNode4.ImageIndex = 4; - treeNode4.Name = "operationsNode"; - treeNode4.SelectedImageIndex = 4; - treeNode4.Text = "Operations"; + treeNode4.ImageIndex = 16; + treeNode4.Name = "conditionsNode"; + treeNode4.SelectedImageIndex = 16; + treeNode4.Text = "Conditions"; + treeNode13.ImageIndex = 4; + treeNode13.Name = "operationsNode"; + treeNode13.SelectedImageIndex = 4; + treeNode13.Text = "Operations"; this.categoryTreeView.Nodes.AddRange(new System.Windows.Forms.TreeNode[] { treeNode1, treeNode2, treeNode3, - treeNode4}); + treeNode4, + treeNode13}); this.categoryTreeView.SelectedImageIndex = 0; this.categoryTreeView.ShowLines = false; this.categoryTreeView.Size = new System.Drawing.Size(129, 231); @@ -333,6 +377,8 @@ private void InitializeComponent() this.categoryTabControl.Controls.Add(this.changelogTabPage); this.categoryTabControl.Controls.Add(this.availabilityTabPage); this.categoryTabControl.Controls.Add(this.operationsTabPage); + this.categoryTabControl.Controls.Add(this.replaceFilesTabPage); + this.categoryTabControl.Controls.Add(this.conditionsTabPage); this.categoryTabControl.Location = new System.Drawing.Point(151, 24); this.categoryTabControl.Name = "categoryTabControl"; this.categoryTabControl.SelectedIndex = 0; @@ -404,7 +450,7 @@ private void InitializeComponent() // line2 // this.line2.BackColor = System.Drawing.SystemColors.Window; - this.line2.LineAlignment = Line.Alignment.Horizontal; + this.line2.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line2.Location = new System.Drawing.Point(9, 262); this.line2.Name = "line2"; this.line2.Size = new System.Drawing.Size(437, 10); @@ -443,7 +489,7 @@ private void InitializeComponent() // line3 // this.line3.BackColor = System.Drawing.SystemColors.Window; - this.line3.LineAlignment = Line.Alignment.Horizontal; + this.line3.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line3.Location = new System.Drawing.Point(10, 170); this.line3.Name = "line3"; this.line3.Size = new System.Drawing.Size(437, 10); @@ -453,7 +499,7 @@ private void InitializeComponent() // line1 // this.line1.BackColor = System.Drawing.SystemColors.Window; - this.line1.LineAlignment = Line.Alignment.Horizontal; + this.line1.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line1.Location = new System.Drawing.Point(7, 92); this.line1.Name = "line1"; this.line1.Size = new System.Drawing.Size(437, 14); @@ -466,7 +512,7 @@ private void InitializeComponent() this.architectureInfoLabel.ForeColor = System.Drawing.SystemColors.ControlDarkDark; this.architectureInfoLabel.Location = new System.Drawing.Point(9, 137); this.architectureInfoLabel.Name = "architectureInfoLabel"; - this.architectureInfoLabel.Size = new System.Drawing.Size(438, 26); + this.architectureInfoLabel.Size = new System.Drawing.Size(437, 26); this.architectureInfoLabel.TabIndex = 20; this.architectureInfoLabel.Text = "Sets if the update package should only run on special architectures. To set any t" + "ype \r\nof architecture, choose \"AnyCPU\" as entry."; @@ -553,7 +599,7 @@ private void InitializeComponent() this.versionLabel.AutoSize = true; this.versionLabel.Location = new System.Drawing.Point(8, 39); this.versionLabel.Name = "versionLabel"; - this.versionLabel.Size = new System.Drawing.Size(49, 13); + this.versionLabel.Size = new System.Drawing.Size(48, 13); this.versionLabel.TabIndex = 2; this.versionLabel.Text = "Version:"; // @@ -1043,6 +1089,292 @@ private void InitializeComponent() // this.Description.Width = 300; // + // conditionsTabPage + // + this.conditionsTabPage.Controls.Add(this.conditionHelpLinkLabel); + this.conditionsTabPage.Controls.Add(this.line4); + this.conditionsTabPage.Controls.Add(this.rolloutConditionModeComboBox); + this.conditionsTabPage.Controls.Add(this.rolloutConditionModeLabel); + this.conditionsTabPage.Controls.Add(this.conditionsDataGridView); + this.conditionsTabPage.Location = new System.Drawing.Point(4, 22); + this.conditionsTabPage.Name = "conditionsTabPage"; + this.conditionsTabPage.Padding = new System.Windows.Forms.Padding(3); + this.conditionsTabPage.Size = new System.Drawing.Size(473, 236); + this.conditionsTabPage.TabIndex = 6; + this.conditionsTabPage.Text = "Rollout conditions"; + this.conditionsTabPage.UseVisualStyleBackColor = true; + // + // conditionHelpLinkLabel + // + this.conditionHelpLinkLabel.ActiveLinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(153)))), ((int)(((byte)(255))))); + this.conditionHelpLinkLabel.AutoSize = true; + this.conditionHelpLinkLabel.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(102)))), ((int)(((byte)(204))))); + this.conditionHelpLinkLabel.Location = new System.Drawing.Point(433, 14); + this.conditionHelpLinkLabel.Name = "conditionHelpLinkLabel"; + this.conditionHelpLinkLabel.Size = new System.Drawing.Size(31, 13); + this.conditionHelpLinkLabel.TabIndex = 6; + this.conditionHelpLinkLabel.TabStop = true; + this.conditionHelpLinkLabel.Text = "Help"; + // + // line4 + // + this.line4.BackColor = System.Drawing.SystemColors.Window; + this.line4.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Vertical; + this.line4.Location = new System.Drawing.Point(420, 7); + this.line4.Name = "line4"; + this.line4.Size = new System.Drawing.Size(10, 23); + this.line4.TabIndex = 3; + this.line4.Text = "line4"; + // + // rolloutConditionModeComboBox + // + this.rolloutConditionModeComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.rolloutConditionModeComboBox.FormattingEnabled = true; + this.rolloutConditionModeComboBox.Items.AddRange(new object[] { + "One positive condition must be met for different keys", + "All positive conditions must be met for different keys"}); + this.rolloutConditionModeComboBox.Location = new System.Drawing.Point(106, 11); + this.rolloutConditionModeComboBox.Name = "rolloutConditionModeComboBox"; + this.rolloutConditionModeComboBox.Size = new System.Drawing.Size(305, 21); + this.rolloutConditionModeComboBox.TabIndex = 2; + // + // rolloutConditionModeLabel + // + this.rolloutConditionModeLabel.AutoSize = true; + this.rolloutConditionModeLabel.Location = new System.Drawing.Point(6, 14); + this.rolloutConditionModeLabel.Name = "rolloutConditionModeLabel"; + this.rolloutConditionModeLabel.Size = new System.Drawing.Size(94, 13); + this.rolloutConditionModeLabel.TabIndex = 1; + this.rolloutConditionModeLabel.Text = "Condition mode:"; + // + // conditionsDataGridView + // + this.conditionsDataGridView.BackgroundColor = System.Drawing.SystemColors.Window; + this.conditionsDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.conditionsDataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { + this.Key, + this.Value, + this.Negative}); + this.conditionsDataGridView.Location = new System.Drawing.Point(9, 40); + this.conditionsDataGridView.Name = "conditionsDataGridView"; + this.conditionsDataGridView.RowHeadersVisible = false; + this.conditionsDataGridView.Size = new System.Drawing.Size(455, 178); + this.conditionsDataGridView.TabIndex = 0; + // + // Key + // + this.Key.DataPropertyName = "Key"; + this.Key.HeaderText = "Key"; + this.Key.Name = "Key"; + this.Key.Width = 152; + // + // Value + // + this.Value.DataPropertyName = "Value"; + this.Value.HeaderText = "Value"; + this.Value.Name = "Value"; + this.Value.Width = 152; + // + // Negative + // + this.Negative.DataPropertyName = "IsNegativeCondition"; + this.Negative.HeaderText = "Negative"; + this.Negative.Name = "Negative"; + this.Negative.ToolTipText = "When checked, this conditions must not be met."; + this.Negative.Width = 152; + // + // replaceFilesTabPage + // + this.replaceFilesTabPage.Controls.Add(this.filesPanel); + this.replaceFilesTabPage.Location = new System.Drawing.Point(4, 22); + this.replaceFilesTabPage.Name = "replaceFilesTabPage"; + this.replaceFilesTabPage.Padding = new System.Windows.Forms.Padding(3); + this.replaceFilesTabPage.Size = new System.Drawing.Size(473, 236); + this.replaceFilesTabPage.TabIndex = 7; + this.replaceFilesTabPage.Text = "ReplaceFiles"; + this.replaceFilesTabPage.UseVisualStyleBackColor = true; + // + // filesPanel + // + this.filesPanel.Controls.Add(this.filesDataTreeView); + this.filesPanel.Controls.Add(this.replaceFilesToolStrip); + this.filesPanel.Controls.Add(this.filesList); + this.filesPanel.Location = new System.Drawing.Point(0, 0); + this.filesPanel.Name = "filesPanel"; + this.filesPanel.Size = new System.Drawing.Size(474, 235); + this.filesPanel.TabIndex = 41; + // + // filesDataTreeView + // + this.filesDataTreeView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.filesDataTreeView.HotTracking = true; + this.filesDataTreeView.ImageIndex = 0; + this.filesDataTreeView.ImageList = this.filesImageList; + this.filesDataTreeView.ItemHeight = 23; + this.filesDataTreeView.LabelEdit = true; + this.filesDataTreeView.Location = new System.Drawing.Point(3, 30); + this.filesDataTreeView.Name = "filesDataTreeView"; + treeNode5.ImageIndex = 0; + treeNode5.Name = "Knoten0"; + treeNode5.SelectedImageIndex = 0; + treeNode5.Text = "Program directory"; + treeNode6.ImageIndex = 0; + treeNode6.Name = "Knoten1"; + treeNode6.SelectedImageIndex = 0; + treeNode6.Text = "AppData"; + treeNode7.ImageIndex = 0; + treeNode7.Name = "Knoten2"; + treeNode7.SelectedImageIndex = 0; + treeNode7.Text = "Temp directory"; + treeNode8.ImageIndex = 0; + treeNode8.Name = "Knoten3"; + treeNode8.SelectedImageIndex = 0; + treeNode8.Text = "Desktop"; + this.filesDataTreeView.Nodes.AddRange(new System.Windows.Forms.TreeNode[] { + treeNode5, + treeNode6, + treeNode7, + treeNode8}); + this.filesDataTreeView.SelectedImageIndex = 0; + this.filesDataTreeView.ShowLines = false; + this.filesDataTreeView.Size = new System.Drawing.Size(469, 198); + this.filesDataTreeView.TabIndex = 5; + this.filesDataTreeView.BeforeLabelEdit += new System.Windows.Forms.NodeLabelEditEventHandler(this.FilesDataTreeView_BeforeLabelEdit); + // + // replaceFilesToolStrip + // + this.replaceFilesToolStrip.AutoSize = false; + this.replaceFilesToolStrip.BackColor = System.Drawing.Color.Transparent; + this.replaceFilesToolStrip.Dock = System.Windows.Forms.DockStyle.None; + this.replaceFilesToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + this.replaceFilesToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.addFolderButton, + this.toolStripSeparator1, + this.addFilesButton, + this.toolStripSeparator4, + this.removeEntryButton, + this.toolStripSeparator9, + this.infoButton, + this.toolStripSeparator2}); + this.replaceFilesToolStrip.Location = new System.Drawing.Point(3, 2); + this.replaceFilesToolStrip.Name = "replaceFilesToolStrip"; + this.replaceFilesToolStrip.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; + this.replaceFilesToolStrip.Size = new System.Drawing.Size(468, 25); + this.replaceFilesToolStrip.TabIndex = 4; + this.replaceFilesToolStrip.Text = "toolStrip4"; + // + // addFolderButton + // + this.addFolderButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.addExistingFolderToolStripMenuItem, + this.addFolderContentToolStripMenuItem, + this.addVirtualFolderToolStripMenuItem}); + this.addFolderButton.Image = ((System.Drawing.Image)(resources.GetObject("addFolderButton.Image"))); + this.addFolderButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.addFolderButton.Name = "addFolderButton"; + this.addFolderButton.Size = new System.Drawing.Size(95, 22); + this.addFolderButton.Text = "Add folder"; + this.addFolderButton.Click += new System.EventHandler(this.AddFolderButton_Click); + // + // addExistingFolderToolStripMenuItem + // + this.addExistingFolderToolStripMenuItem.Name = "addExistingFolderToolStripMenuItem"; + this.addExistingFolderToolStripMenuItem.Size = new System.Drawing.Size(174, 22); + this.addExistingFolderToolStripMenuItem.Text = "Add folder"; + // + // addFolderContentToolStripMenuItem + // + this.addFolderContentToolStripMenuItem.Name = "addFolderContentToolStripMenuItem"; + this.addFolderContentToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.addFolderContentToolStripMenuItem.Text = "Add folder content"; + this.addFolderContentToolStripMenuItem.Click += new System.EventHandler(this.AddFolderContentToolStripMenuItem_Click); + // + // addVirtualFolderToolStripMenuItem + // + this.addVirtualFolderToolStripMenuItem.Name = "addVirtualFolderToolStripMenuItem"; + this.addVirtualFolderToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.addVirtualFolderToolStripMenuItem.Text = "Add virtual folder"; + this.addVirtualFolderToolStripMenuItem.Click += new System.EventHandler(this.AddVirtualFolderToolStripMenuItem_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25); + // + // addFilesButton + // + this.addFilesButton.Image = ((System.Drawing.Image)(resources.GetObject("addFilesButton.Image"))); + this.addFilesButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.addFilesButton.Name = "addFilesButton"; + this.addFilesButton.Size = new System.Drawing.Size(73, 22); + this.addFilesButton.Text = "Add files"; + this.addFilesButton.Click += new System.EventHandler(this.AddFilesButton_Click); + // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(6, 25); + // + // removeEntryButton + // + this.removeEntryButton.Image = ((System.Drawing.Image)(resources.GetObject("removeEntryButton.Image"))); + this.removeEntryButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.removeEntryButton.Name = "removeEntryButton"; + this.removeEntryButton.Size = new System.Drawing.Size(100, 22); + this.removeEntryButton.Text = "Remove entry"; + this.removeEntryButton.Click += new System.EventHandler(this.RemoveEntryButton_Click); + // + // toolStripSeparator9 + // + this.toolStripSeparator9.Name = "toolStripSeparator9"; + this.toolStripSeparator9.Size = new System.Drawing.Size(6, 25); + // + // infoButton + // + this.infoButton.Image = ((System.Drawing.Image)(resources.GetObject("infoButton.Image"))); + this.infoButton.ImageTransparentColor = System.Drawing.Color.Magenta; + this.infoButton.Name = "infoButton"; + this.infoButton.Size = new System.Drawing.Size(90, 22); + this.infoButton.Text = "Information"; + this.infoButton.Click += new System.EventHandler(this.InfoButton_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(6, 25); + // + // filesList + // + this.filesList.BackColor = System.Drawing.SystemColors.Window; + this.filesList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.filesList.FullRowSelect = true; + this.filesList.GridLines = true; + this.filesList.Location = new System.Drawing.Point(4, 30); + this.filesList.Name = "filesList"; + this.filesList.Size = new System.Drawing.Size(467, 198); + this.filesList.TabIndex = 3; + this.filesList.UseCompatibleStateImageBehavior = false; + this.filesList.View = System.Windows.Forms.View.Details; + // + // columnHeader1 + // + this.columnHeader1.Text = "Name"; + this.columnHeader1.Width = 316; + // + // columnHeader2 + // + this.columnHeader2.Text = "Size"; + this.columnHeader2.Width = 147; + // + // filesImageList + // + this.filesImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("filesImageList.ImageStream"))); + this.filesImageList.TransparentColor = System.Drawing.Color.Transparent; + this.filesImageList.Images.SetKeyName(0, "folder.png"); + this.filesImageList.Images.SetKeyName(1, "page_white.png"); + // // PackageEditDialog // this.AcceptButton = this.saveButton; @@ -1096,6 +1428,13 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.unsupportedBuildNumericUpDown)).EndInit(); this.operationsTabPage.ResumeLayout(false); this.operationsPanel.ResumeLayout(false); + this.conditionsTabPage.ResumeLayout(false); + this.conditionsTabPage.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.conditionsDataGridView)).EndInit(); + this.replaceFilesTabPage.ResumeLayout(false); + this.filesPanel.ResumeLayout(false); + this.replaceFilesToolStrip.ResumeLayout(false); + this.replaceFilesToolStrip.PerformLayout(); this.ResumeLayout(false); } @@ -1179,8 +1518,33 @@ private void InitializeComponent() private System.Windows.Forms.ListBox unsupportedVersionsListBox; private System.Windows.Forms.NumericUpDown unsupportedMinorNumericUpDown; private System.Windows.Forms.NumericUpDown unsupportedBuildNumericUpDown; - - - + private System.Windows.Forms.TabPage conditionsTabPage; + private System.Windows.Forms.LinkLabel conditionHelpLinkLabel; + private Line line4; + private System.Windows.Forms.ComboBox rolloutConditionModeComboBox; + private System.Windows.Forms.Label rolloutConditionModeLabel; + private System.Windows.Forms.DataGridView conditionsDataGridView; + private System.Windows.Forms.DataGridViewTextBoxColumn Key; + private System.Windows.Forms.DataGridViewTextBoxColumn Value; + private System.Windows.Forms.DataGridViewCheckBoxColumn Negative; + private System.Windows.Forms.TabPage replaceFilesTabPage; + private System.Windows.Forms.Panel filesPanel; + private Controls.ExplorerTreeView filesDataTreeView; + private System.Windows.Forms.ToolStrip replaceFilesToolStrip; + private System.Windows.Forms.ToolStripSplitButton addFolderButton; + private System.Windows.Forms.ToolStripMenuItem addExistingFolderToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem addFolderContentToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem addVirtualFolderToolStripMenuItem; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.ToolStripButton addFilesButton; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; + private System.Windows.Forms.ToolStripButton removeEntryButton; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator9; + private System.Windows.Forms.ToolStripButton infoButton; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ListView filesList; + private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader2; + private System.Windows.Forms.ImageList filesImageList; } } \ No newline at end of file diff --git a/nUpdate.Administration/UI/Dialogs/PackageEditDialog.cs b/nUpdate.Administration/UI/Dialogs/PackageEditDialog.cs index 4fea018f..542aa6ca 100644 --- a/nUpdate.Administration/UI/Dialogs/PackageEditDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/PackageEditDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// PackageEditDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -15,6 +16,7 @@ using MySql.Data.MySqlClient; using nUpdate.Administration.Core; using nUpdate.Administration.Core.Application; +using nUpdate.Administration.Core.History; using nUpdate.Administration.Core.Operations.Panels; using nUpdate.Administration.UI.Controls; using nUpdate.Administration.UI.Popups; @@ -24,6 +26,10 @@ using Newtonsoft.Json.Linq; using Starksoft.Aspen.Ftps; using OpenFileDialog = System.Windows.Forms.OpenFileDialog; +using nUpdate.Administration.Core.Win32; +using Ionic.Zip; +using System.Threading; +using nUpdate.Administration.TransferInterface; namespace nUpdate.Administration.UI.Dialogs { @@ -49,6 +55,7 @@ public partial class PackageEditDialog : BaseDialog, IAsyncSupportable, IResetta private readonly TreeNode _executeScriptNode = new TreeNode("Execute Script", 15, 15) {Tag = "ExecuteScript"}; private readonly TreeNode _renameNode = new TreeNode("Rename file", 10, 10) {Tag = "RenameFile"}; + private readonly TreeNode _replaceNode = new TreeNode("Replace file/folder", 11, 11) {Tag = "ReplaceFile"}; private readonly TreeNode _setRegistryValueNode = new TreeNode("Set registry value", 13, 13) { @@ -63,15 +70,20 @@ public partial class PackageEditDialog : BaseDialog, IAsyncSupportable, IResetta {Tag = "StopProcess"}; private readonly BindingList _unsupportedVersionLiteralsBindingList = new BindingList(); + private bool _nodeInitializingFailed; private bool _allowCancel = true; private bool _commandsExecuted; private bool _configurationUploaded; private string _existingVersionString; + private ZipFile _zip; private FtpManager _ftp; private string _newPackageDirectory; private UpdateVersion _newVersion; private string _oldPackageDirectoryPath; private UpdateConfiguration _packageConfiguration; + private readonly Log _updateLog = new Log(); + private String _packagePath; + private String _extractedPackagePath; /// /// The FTP-password. Set as SecureString for deleting it out of the memory after runtime. @@ -88,6 +100,9 @@ public partial class PackageEditDialog : BaseDialog, IAsyncSupportable, IResetta /// public SecureString SqlPassword = new SecureString(); + private bool _uploadCancelled; + private bool _packageUploaded; + public PackageEditDialog() { InitializeComponent(); @@ -108,6 +123,11 @@ public PackageEditDialog() /// public UpdateVersion PackageVersion { get; set; } + /// + /// Gets or sets the rollout conditions. + /// + public List Conditions { get; set; } + /// /// The configurations available in the file. /// @@ -115,6 +135,23 @@ public PackageEditDialog() public void Reset() { + if (_packageUploaded) + try + { + Invoke(new Action(() => loadingLabel.Text = "Undoing package upload...")); + _ftp.DeleteDirectory($"{_ftp.Directory}/{_packageConfiguration.LiteralVersion}"); + } + catch (Exception ex) + { + if (!ex.Message.Contains("No such file or directory")) + Invoke( + new Action( + () => + Popup.ShowPopup(this, SystemIcons.Error, "Error while undoing the package upload.", + ex, + PopupButtons.Ok))); + } + if (_existingVersionString != _newVersion.ToString()) try { @@ -312,118 +349,162 @@ private void categoryTreeView_AfterSelect(object sender, TreeViewEventArgs e) categoryTabControl.SelectedTab = availabilityTabPage; break; case 3: + categoryTabControl.SelectedTab = conditionsTabPage; + break; + case 4: categoryTabControl.SelectedTab = operationsTabPage; break; } else - categoryTabControl.SelectedTab = - categoryTabControl.TabPages[4 + categoryTreeView.SelectedNode.Index]; + switch (categoryTreeView.SelectedNode.Tag.ToString()) + { + case "ReplaceFile": + categoryTabControl.SelectedTab = replaceFilesTabPage; + break; + default: + categoryTabControl.SelectedTab = + categoryTabControl.TabPages[(int) categoryTreeView.SelectedNode.Tag]; + break; + } } private void categoryTreeView_DragDrop(object sender, DragEventArgs e) { var nodeToDropIn = categoryTreeView.GetNodeAt(categoryTreeView.PointToClient(new Point(e.X, e.Y))); - if (nodeToDropIn == null || nodeToDropIn.Index != 3) // Operations-node + if (nodeToDropIn == null || nodeToDropIn.Index != 4) // Operations-node return; var data = e.Data.GetData(typeof(string)); if (data == null) return; + TreeNode node; switch (data.ToString()) { case "DeleteFile": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _deleteNode.Clone()); + node = (TreeNode) _deleteNode.Clone(); var deletePage = new TabPage("Delete file") {BackColor = SystemColors.Window}; deletePage.Controls.Add(new FileDeleteOperationPanel()); categoryTabControl.TabPages.Add(deletePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(deletePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "RenameFile": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _renameNode.Clone()); + node = (TreeNode) _renameNode.Clone(); var renamePage = new TabPage("Rename file") {BackColor = SystemColors.Window}; renamePage.Controls.Add(new FileRenameOperationPanel()); categoryTabControl.TabPages.Add(renamePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(renamePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "CreateRegistrySubKey": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _createRegistrySubKeyNode.Clone()); + node = (TreeNode) _createRegistrySubKeyNode.Clone(); + + var createRegistrySubKeyPage = new TabPage("Create registry subkey") + { + BackColor = SystemColors.Window + }; + createRegistrySubKeyPage.Controls.Add(new RegistrySubKeyCreateOperationPanel()); + categoryTabControl.TabPages.Add(createRegistrySubKeyPage); - var createRegistryEntryPage = - new TabPage("Create registry entry") {BackColor = SystemColors.Window}; - createRegistryEntryPage.Controls.Add(new RegistrySubKeyCreateOperationPanel()); - categoryTabControl.TabPages.Add(createRegistryEntryPage); + node.Tag = categoryTabControl.TabPages.IndexOf(createRegistrySubKeyPage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "DeleteRegistrySubKey": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _deleteRegistrySubKeyNode.Clone()); + node = (TreeNode) _deleteRegistrySubKeyNode.Clone(); - var deleteRegistryEntryPage = - new TabPage("Delete registry entry") {BackColor = SystemColors.Window}; - deleteRegistryEntryPage.Controls.Add(new RegistrySubKeyDeleteOperationPanel()); - categoryTabControl.TabPages.Add(deleteRegistryEntryPage); + var deleteRegistrySubKeyPage = new TabPage("Delete registry subkey") + { + BackColor = SystemColors.Window + }; + deleteRegistrySubKeyPage.Controls.Add(new RegistrySubKeyDeleteOperationPanel()); + categoryTabControl.TabPages.Add(deleteRegistrySubKeyPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(deleteRegistrySubKeyPage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "SetRegistryValue": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _setRegistryValueNode.Clone()); + node = (TreeNode) _setRegistryValueNode.Clone(); - var setRegistryEntryValuePage = new TabPage("Set registry entry value") - { - BackColor = SystemColors.Window - }; - setRegistryEntryValuePage.Controls.Add(new RegistrySetValueOperationPanel()); - categoryTabControl.TabPages.Add(setRegistryEntryValuePage); + var setRegistryValuePage = new TabPage("Set registry value") {BackColor = SystemColors.Window}; + setRegistryValuePage.Controls.Add(new RegistrySetValueOperationPanel()); + categoryTabControl.TabPages.Add(setRegistryValuePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(setRegistryValuePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; + case "DeleteRegistryValue": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _deleteRegistryValueNode.Clone()); + node = (TreeNode) _deleteRegistryValueNode.Clone(); - var deleteRegistryEntryValuePage = new TabPage("Delete registry entry value") - { - BackColor = SystemColors.Window - }; - deleteRegistryEntryValuePage.Controls.Add(new RegistryDeleteValueOperationPanel()); - categoryTabControl.TabPages.Add(deleteRegistryEntryValuePage); + var deleteRegistryValuePage = + new TabPage("Delete registry value") {BackColor = SystemColors.Window}; + deleteRegistryValuePage.Controls.Add(new RegistryDeleteValueOperationPanel()); + categoryTabControl.TabPages.Add(deleteRegistryValuePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(deleteRegistryValuePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; + case "StartProcess": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _startProcessNode.Clone()); + node = (TreeNode) _startProcessNode.Clone(); var startProcessPage = new TabPage("Start process") {BackColor = SystemColors.Window}; startProcessPage.Controls.Add(new ProcessStartOperationPanel()); categoryTabControl.TabPages.Add(startProcessPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(startProcessPage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "TerminateProcess": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _terminateProcessNode.Clone()); + node = (TreeNode) _terminateProcessNode.Clone(); var terminateProcessPage = new TabPage("Terminate process") {BackColor = SystemColors.Window}; terminateProcessPage.Controls.Add(new ProcessStopOperationPanel()); categoryTabControl.TabPages.Add(terminateProcessPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(terminateProcessPage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "StartService": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _startServiceNode.Clone()); + node = (TreeNode) _startServiceNode.Clone(); var startServicePage = new TabPage("Start service") {BackColor = SystemColors.Window}; startServicePage.Controls.Add(new ServiceStartOperationPanel()); categoryTabControl.TabPages.Add(startServicePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(startServicePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "StopService": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _stopServiceNode.Clone()); + node = (TreeNode) _stopServiceNode.Clone(); var stopServicePage = new TabPage("Stop service") {BackColor = SystemColors.Window}; stopServicePage.Controls.Add(new ServiceStopOperationPanel()); categoryTabControl.TabPages.Add(stopServicePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(stopServicePage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; case "ExecuteScript": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _executeScriptNode.Clone()); + node = (TreeNode) _executeScriptNode.Clone(); - var executeScriptPage = new TabPage("Execute script") {BackColor = SystemColors.Window}; + var executeScriptPage = new TabPage("Stop service") {BackColor = SystemColors.Window}; executeScriptPage.Controls.Add(new ScriptExecuteOperationPanel()); categoryTabControl.TabPages.Add(executeScriptPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(executeScriptPage); + categoryTreeView.Nodes[4].Nodes.Add(node); break; } - - categoryTreeView.Nodes[0].Toggle(); } private void categoryTreeView_DragEnter(object sender, DragEventArgs e) @@ -436,17 +517,32 @@ private void categoryTreeView_KeyDown(object sender, KeyEventArgs e) if (categoryTreeView.SelectedNode?.Parent == null) return; + TreeNode selectedNode = categoryTreeView.SelectedNode; if (e.Control && e.KeyCode == Keys.Up) - categoryTreeView.SelectedNode.MoveUp(); + { + selectedNode.MoveUp(); + categoryTreeView.SelectedNode = selectedNode; + return; + } else if (e.Control && e.KeyCode == Keys.Down) - categoryTreeView.SelectedNode.MoveDown(); + { + selectedNode.MoveDown(); + categoryTreeView.SelectedNode = selectedNode; + return; + } - if (e.KeyCode != Keys.Delete && e.KeyCode != Keys.Back || categoryTreeView.SelectedNode.Parent == null) + if (e.KeyCode != Keys.Delete && e.KeyCode != Keys.Back || + categoryTreeView.SelectedNode.Equals(_replaceNode)) return; - categoryTabControl.TabPages.Remove( - categoryTabControl.TabPages[4 + categoryTreeView.SelectedNode.Index]); + int index = (int) categoryTreeView.SelectedNode.Tag; + foreach (var node in categoryTreeView.Nodes[4].Nodes.Cast() + .Where(n => !n.Equals(_replaceNode) && (int) n.Tag > index)) + node.Tag = (int) node.Tag - 1; + categoryTreeView.SelectedNode.Remove(); + categoryTabControl.TabPages.Remove( + categoryTabControl.TabPages[index]); } private void changelogClearButton_Click(object sender, EventArgs e) @@ -616,11 +712,129 @@ await Task.Factory.StartNew(() => } } + Invoke(new Action(() => loadingLabel.Text = "Saving package archive...")); + try + { + _zip.Dispose(); + File.Delete(_packagePath); + + _zip = new ZipFile(); + _zip.AddDirectoryByName("Program"); + _zip.AddDirectoryByName("AppData"); + _zip.AddDirectoryByName("Temp"); + _zip.AddDirectoryByName("Desktop"); + _zip.AddFile(Path.Combine(_extractedPackagePath, "operations.json"), string.Empty); + + InitializeArchiveContents(filesDataTreeView.Nodes[0], "Program"); + InitializeArchiveContents(filesDataTreeView.Nodes[1], "AppData"); + InitializeArchiveContents(filesDataTreeView.Nodes[2], "Temp"); + InitializeArchiveContents(filesDataTreeView.Nodes[3], "Desktop"); + _zip.Save(_packagePath); + } + catch (Exception ex) + { + Invoke( + new Action( + () => + Popup.ShowPopup(this, SystemIcons.Error, "Error while saving the package archive.", ex, + PopupButtons.Ok))); + Reset(); + return; + } + + Invoke(new Action(() => loadingLabel.Text = "Signing package...")); + + try + { + using (var stream = File.Open(_packagePath, + FileMode.Open)) + { + _packageConfiguration.Signature = + Convert.ToBase64String(new RsaManager(Project.PrivateKey).SignData(stream)); + } + } + catch (Exception ex) + { + Invoke( + new Action( + () => + Popup.ShowPopup(this, SystemIcons.Error, "Error while signing the package.", ex, + PopupButtons.Ok))); + Reset(); + return; + } + + /* -------------- Package upload -----------------*/ + Invoke(new Action(() => + { + loadingLabel.Text = "Uploading package... 0%"; + cancelLabel.Visible = true; + })); + + try + { + _ftp.UploadPackage(_packagePath, _packageConfiguration.LiteralVersion); + } + catch (Exception ex) // Upload-method is async, it's true, but directory creation can fail. + { + Invoke( + new Action( + () => + Popup.ShowPopup(this, SystemIcons.Error, + "Error while creating the package directory.", + ex, PopupButtons.Ok))); + Reset(); + return; + } + + if (_uploadCancelled) + { + Reset(); + return; + } + + _packageUploaded = true; + + if (_ftp.PackageUploadException != null) + { + if (_ftp.PackageUploadException.InnerException != null) + Invoke( + new Action( + () => + Popup.ShowPopup(this, SystemIcons.Error, "Error while uploading the package.", + _ftp.PackageUploadException.InnerException, PopupButtons.Ok))); + else + Invoke( + new Action( + () => + Popup.ShowPopup(this, SystemIcons.Error, "Error while uploading the package.", + _ftp.PackageUploadException, PopupButtons.Ok))); + + Reset(); + return; + } + Invoke(new Action(() => loadingLabel.Text = "Uploading new configuration...")); + UpdateConfiguration[ + UpdateConfiguration.IndexOf( + UpdateConfiguration.First(item => item.LiteralVersion == PackageVersion.ToString()))] = + _packageConfiguration; + var configurationFilePath = Path.Combine(_newPackageDirectory, "updates.json"); try { - _ftp.UploadFile(Path.Combine(_newPackageDirectory, "updates.json")); + File.WriteAllText(configurationFilePath, Serializer.Serialize(UpdateConfiguration)); + } + catch (Exception ex) + { + Popup.ShowPopup(this, SystemIcons.Error, "Error while saving the new configuration.", ex, + PopupButtons.Ok); + return; + } + + try + { + _ftp.UploadFile(configurationFilePath); if (_newVersion != new UpdateVersion(_existingVersionString)) _ftp.RenameDirectory(_existingVersionString, _packageConfiguration.LiteralVersion); _configurationUploaded = true; @@ -654,6 +868,8 @@ await Task.Factory.StartNew(() => .Version = _packageConfiguration.LiteralVersion; } + _updateLog.Write(LogEntry.Edit, _newVersion.FullText); + UpdateProject.SaveProject(Project.Path, Project); } catch (Exception ex) @@ -672,6 +888,27 @@ await Task.Factory.StartNew(() => }); } + private void cancelLabel_Click(object sender, EventArgs e) + { + _uploadCancelled = true; + + Invoke(new Action(() => + { + loadingLabel.Text = "Cancelling upload..."; + cancelLabel.Visible = false; + })); + + _ftp.CancelPackageUpload(); + } + + private void CancellationFinished(object sender, EventArgs e) + { + if (!_packageUploaded) + _packageUploaded = true; + + Reset(); + } + private void insideQuotationMarkToolStripMenuItem_Click(object sender, EventArgs e) { var page = changelogContentTabControl.SelectedTab; @@ -717,7 +954,7 @@ private void PackageEditDialog_FormClosing(object sender, FormClosingEventArgs e e.Cancel = true; } - private void PackageEditDialog_Load(object sender, EventArgs e) + private async void PackageEditDialog_Load(object sender, EventArgs e) { Text = string.Format(Text, PackageVersion.FullText, Program.VersionString); @@ -728,6 +965,9 @@ private void PackageEditDialog_Load(object sender, EventArgs e) FtpPassword, Project.Proxy, Project.FtpUsePassiveMode, Project.FtpTransferAssemblyFilePath, Project.FtpProtocol, Project.FtpNetworkVersion); + + _ftp.ProgressChanged += ProgressChanged; + _ftp.CancellationFinished += CancellationFinished; if (!string.IsNullOrWhiteSpace(Project.FtpTransferAssemblyFilePath)) _ftp.TransferAssemblyPath = Project.FtpTransferAssemblyFilePath; else @@ -752,7 +992,7 @@ private void PackageEditDialog_Load(object sender, EventArgs e) try { _packageConfiguration = - UpdateConfiguration.First(item => item.LiteralVersion == PackageVersion.ToString()).DeepCopy(); + UpdateConfiguration.First(item => item.LiteralVersion == PackageVersion.ToString()); } catch (InvalidOperationException) { @@ -835,154 +1075,318 @@ private void PackageEditDialog_Load(object sender, EventArgs e) unsupportedVersionsPanel.Enabled = false; } - foreach (var operation in _packageConfiguration.Operations) - switch (Operation.GetOperationTag(operation)) + if (_packageConfiguration.RolloutConditions == null) + _packageConfiguration.RolloutConditions = new List(); + + Conditions = _packageConfiguration.RolloutConditions; + conditionsDataGridView.AutoGenerateColumns = false; + var source = new BindingSource(new BindingList(Conditions) {AllowNew = true}, null); + conditionsDataGridView.DataSource = source; + rolloutConditionModeComboBox.SelectedIndex = (int) _packageConfiguration.RolloutConditionMode; + + _updateLog.Project = Project; + + var packageFolder = Path.Combine(Program.Path, "Projects", Project.Name, + _packageConfiguration.LiteralVersion); + var packageFile = $"{Project.Guid}.zip"; + _packagePath = Path.Combine(packageFolder, packageFile); + _extractedPackagePath = Path.Combine(packageFolder, Project.Guid); + if (Directory.Exists(_extractedPackagePath)) + Directory.Delete(_extractedPackagePath, true); + + if (!File.Exists(_packagePath)) + { + Invoke(new Action(() => { - case "DeleteFile": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _deleteNode.Clone()); + Popup.ShowPopup(this, SystemIcons.Warning, "Package archive not found locally.", + "The archive of the package file does not exist in your local project data. It will be downloaded now.", + PopupButtons.Ok); + })); - var deletePage = new TabPage("Delete file") {BackColor = SystemColors.Window}; - deletePage.Controls.Add(new FileDeleteOperationPanel - { - Path = operation.Value, - ItemList = - ((JArray) operation.Value2).ToObject>() - }); - categoryTabControl.TabPages.Add(deletePage); - break; + using (var wc = new WebClientWrapper()) + { + wc.DownloadProgressChanged += (o, ev) => + { + Invoke(new Action(() => + loadingLabel.Text = + $"Downloading {_packageConfiguration.LiteralVersion} ({ev.ProgressPercentage}%)")); + }; + await wc.DownloadFileTaskAsync(_packageConfiguration.UpdatePackageUri, _packagePath); + } + } - case "RenameFile": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _renameNode.Clone()); + using (var stream = File.OpenRead(_packagePath)) + { + using (_zip = ZipFile.Read(stream)) + { + _zip.ParallelDeflateThreshold = -1; + _zip.UseZip64WhenSaving = Zip64Option.AsNecessary; + _zip.ExtractAll(_extractedPackagePath); + } + } - var renamePage = new TabPage("Rename file") {BackColor = SystemColors.Window}; - renamePage.Controls.Add(new FileRenameOperationPanel - { - Path = operation.Value, - NewName = operation.Value2.ToString() - }); - categoryTabControl.TabPages.Add(renamePage); - break; + var operations = + Serializer.Deserialize>( + File.ReadAllText(Path.Combine(_extractedPackagePath, "operations.json"))) ?? Enumerable.Empty(); + foreach (var operation in operations.Where(o => o.ExecuteBeforeReplacingFiles)) + AddOperation(operation); + categoryTreeView.Nodes[4].Nodes.Add(_replaceNode); + foreach (var operation in operations.Where(o => !o.ExecuteBeforeReplacingFiles)) + AddOperation(operation); - case "CreateRegistrySubKey": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _createRegistrySubKeyNode.Clone()); + await LoadPackageContent(_extractedPackagePath); + } - var createRegistrySubKeyPage = new TabPage("Create registry subkey") - { - BackColor = SystemColors.Window - }; - createRegistrySubKeyPage.Controls.Add(new RegistrySubKeyCreateOperationPanel - { - KeyPath = operation.Value, - ItemList = - ((JArray) operation.Value2).ToObject>() - }); - categoryTabControl.TabPages.Add(createRegistrySubKeyPage); - break; + private void ProgressChanged(object sender, TransferInterface.TransferProgressEventArgs e) + { + Invoke( + new Action( + () => + loadingLabel.Text = + $"Uploading package... {e.PercentComplete}% | {e.BytesPerSecond / 1024}KiB/s")); + if (_uploadCancelled) Invoke(new Action(() => { loadingLabel.Text = "Cancelling upload..."; })); + } - case "DeleteRegistrySubKey": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _deleteRegistrySubKeyNode.Clone()); + private void AddOperation(Operation operation) + { + TreeNode node; + switch (Operation.GetOperationTag(operation)) + { + case "DeleteFile": + node = (TreeNode) _deleteNode.Clone(); - var deleteRegistrySubKeyPage = new TabPage("Delete registry subkey") - { - BackColor = SystemColors.Window - }; - deleteRegistrySubKeyPage.Controls.Add(new RegistrySubKeyDeleteOperationPanel - { - KeyPath = operation.Value, - ItemList = - ((JArray) operation.Value2).ToObject>() - }); - categoryTabControl.TabPages.Add(deleteRegistrySubKeyPage); - break; + var deletePage = new TabPage("Delete file") {BackColor = SystemColors.Window}; + deletePage.Controls.Add(new FileDeleteOperationPanel + { + Path = operation.Value, + ItemList = + ((JArray) operation.Value2).ToObject>() + }); + categoryTabControl.TabPages.Add(deletePage); - case "SetRegistryValue": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _setRegistryValueNode.Clone()); + node.Tag = categoryTabControl.TabPages.IndexOf(deletePage); + categoryTreeView.Nodes[4].Nodes.Add(node); + break; - var setRegistryValuePage = new TabPage("Set registry value") - { - BackColor = SystemColors.Window - }; - setRegistryValuePage.Controls.Add(new RegistrySetValueOperationPanel - { - KeyPath = operation.Value, - NameValuePairs = - ((JArray) operation.Value2).ToObject>>() - }); - categoryTabControl.TabPages.Add(setRegistryValuePage); - break; + case "RenameFile": + node = (TreeNode) _renameNode.Clone(); - case "DeleteRegistryValue": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _deleteRegistryValueNode.Clone()); + var renamePage = new TabPage("Rename file") {BackColor = SystemColors.Window}; + renamePage.Controls.Add(new FileRenameOperationPanel + { + Path = operation.Value, + NewName = operation.Value2.ToString() + }); + categoryTabControl.TabPages.Add(renamePage); - var deleteRegistryValuePage = new TabPage("Delete registry value") - { - BackColor = SystemColors.Window - }; - deleteRegistryValuePage.Controls.Add(new RegistryDeleteValueOperationPanel - { - KeyPath = operation.Value, - ItemList = ((JArray) operation.Value2).ToObject>() - }); - categoryTabControl.TabPages.Add(deleteRegistryValuePage); - break; + node.Tag = categoryTabControl.TabPages.IndexOf(renamePage); + categoryTreeView.Nodes[4].Nodes.Add(node); + break; - case "StartProcess": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _startProcessNode.Clone()); + case "CreateRegistrySubKey": + node = (TreeNode) _createRegistrySubKeyNode.Clone(); - var startProcessPage = new TabPage("Start process") {BackColor = SystemColors.Window}; - startProcessPage.Controls.Add(new ProcessStartOperationPanel - { - Path = operation.Value, - Arguments = operation.Value2.ToString() - }); - categoryTabControl.TabPages.Add(startProcessPage); - break; + var createRegistrySubKeyPage = new TabPage("Create registry subkey") + { + BackColor = SystemColors.Window + }; + createRegistrySubKeyPage.Controls.Add(new RegistrySubKeyCreateOperationPanel + { + KeyPath = operation.Value, + ItemList = + ((JArray) operation.Value2).ToObject>() + }); + categoryTabControl.TabPages.Add(createRegistrySubKeyPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(createRegistrySubKeyPage); + categoryTreeView.Nodes[4].Nodes.Add(node); + break; - case "TerminateProcess": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _terminateProcessNode.Clone()); + case "DeleteRegistrySubKey": + node = (TreeNode) _deleteRegistrySubKeyNode.Clone(); - var terminateProcessPage = new TabPage("Terminate process") {BackColor = SystemColors.Window}; - terminateProcessPage.Controls.Add(new ProcessStopOperationPanel - { - ProcessName = operation.Value - }); - categoryTabControl.TabPages.Add(terminateProcessPage); - break; + var deleteRegistrySubKeyPage = new TabPage("Delete registry subkey") + { + BackColor = SystemColors.Window + }; + deleteRegistrySubKeyPage.Controls.Add(new RegistrySubKeyDeleteOperationPanel + { + KeyPath = operation.Value, + ItemList = + ((JArray) operation.Value2).ToObject>() + }); + categoryTabControl.TabPages.Add(deleteRegistrySubKeyPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(deleteRegistrySubKeyPage); + categoryTreeView.Nodes[4].Nodes.Add(node); + break; - case "StartService": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _startServiceNode.Clone()); + case "SetRegistryValue": + node = (TreeNode) _setRegistryValueNode.Clone(); - var startServicePage = new TabPage("Start service") {BackColor = SystemColors.Window}; - startServicePage.Controls.Add(new ServiceStartOperationPanel - { - ServiceName = operation.Value, - Arguments = ((JArray) operation.Value2).ToObject>() - }); - categoryTabControl.TabPages.Add(startServicePage); - break; + var setRegistryValuePage = new TabPage("Set registry value") {BackColor = SystemColors.Window}; + setRegistryValuePage.Controls.Add(new RegistrySetValueOperationPanel + { + KeyPath = operation.Value, + NameValuePairs = + ((JArray) operation.Value2).ToObject>>() + }); + categoryTabControl.TabPages.Add(setRegistryValuePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(setRegistryValuePage); + categoryTreeView.Nodes[4].Nodes.Add(node); + break; - case "StopService": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _stopServiceNode.Clone()); + case "DeleteRegistryValue": + node = (TreeNode) _deleteRegistryValueNode.Clone(); - var stopServicePage = new TabPage("Stop service") {BackColor = SystemColors.Window}; - stopServicePage.Controls.Add(new ServiceStopOperationPanel - { - ServiceName = operation.Value - }); - categoryTabControl.TabPages.Add(stopServicePage); - break; + var deleteRegistryValuePage = + new TabPage("Delete registry value") {BackColor = SystemColors.Window}; + deleteRegistryValuePage.Controls.Add(new RegistryDeleteValueOperationPanel + { + KeyPath = operation.Value, + ItemList = ((JArray) operation.Value2).ToObject>() + }); + categoryTabControl.TabPages.Add(deleteRegistryValuePage); - case "ExecuteScript": - categoryTreeView.Nodes[3].Nodes.Add((TreeNode) _executeScriptNode.Clone()); + node.Tag = categoryTabControl.TabPages.IndexOf(deleteRegistryValuePage); + categoryTreeView.Nodes[4].Nodes.Add(node); + break; - var executeScriptPage = new TabPage("Execute script") {BackColor = SystemColors.Window}; - executeScriptPage.Controls.Add(new ScriptExecuteOperationPanel - { - Code = operation.Value - }); - categoryTabControl.TabPages.Add(executeScriptPage); - break; + case "StartProcess": + node = (TreeNode) _startProcessNode.Clone(); + + var startProcessPage = new TabPage("Start process") {BackColor = SystemColors.Window}; + startProcessPage.Controls.Add(new ProcessStartOperationPanel + { + Path = operation.Value, + Arguments = operation.Value2.ToString() + }); + categoryTabControl.TabPages.Add(startProcessPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(startProcessPage); + categoryTreeView.Nodes[4].Nodes.Add(node); + break; + case "TerminateProcess": + node = (TreeNode) _terminateProcessNode.Clone(); + + var terminateProcessPage = new TabPage("Terminate process") {BackColor = SystemColors.Window}; + terminateProcessPage.Controls.Add(new ProcessStopOperationPanel + { + ProcessName = operation.Value + }); + categoryTabControl.TabPages.Add(terminateProcessPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(terminateProcessPage); + categoryTreeView.Nodes[4].Nodes.Add(node); + break; + case "StartService": + node = (TreeNode) _startServiceNode.Clone(); + + var startServicePage = new TabPage("Start service") {BackColor = SystemColors.Window}; + startServicePage.Controls.Add(new ServiceStartOperationPanel + { + ServiceName = operation.Value, + Arguments = ((JArray) operation.Value2).ToObject>() + }); + categoryTabControl.TabPages.Add(startServicePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(startServicePage); + categoryTreeView.Nodes[4].Nodes.Add(node); + break; + case "StopService": + node = (TreeNode) _stopServiceNode.Clone(); + + var stopServicePage = new TabPage("Stop service") {BackColor = SystemColors.Window}; + stopServicePage.Controls.Add(new ServiceStopOperationPanel + { + ServiceName = operation.Value + }); + categoryTabControl.TabPages.Add(stopServicePage); + + node.Tag = categoryTabControl.TabPages.IndexOf(stopServicePage); + categoryTreeView.Nodes[4].Nodes.Add(node); + break; + case "ExecuteScript": + node = (TreeNode) _executeScriptNode.Clone(); + + var executeScriptPage = new TabPage("Stop service") {BackColor = SystemColors.Window}; + executeScriptPage.Controls.Add(new ScriptExecuteOperationPanel + { + Code = operation.Value + }); + categoryTabControl.TabPages.Add(executeScriptPage); + + node.Tag = categoryTabControl.TabPages.IndexOf(executeScriptPage); + categoryTreeView.Nodes[4].Nodes.Add(node); + break; + } + } + + private Task LoadPackageContent(string packagePath) + { + return Task.Factory.StartNew(() => + { + ListDirectoryContent(Path.Combine(packagePath, "Program"), filesDataTreeView.Nodes[0], true); + ListDirectoryContent(Path.Combine(packagePath, "AppData"), filesDataTreeView.Nodes[1], true); + ListDirectoryContent(Path.Combine(packagePath, "Temp"), filesDataTreeView.Nodes[2], true); + ListDirectoryContent(Path.Combine(packagePath, "Desktop"), filesDataTreeView.Nodes[3], true); + }); + } + + private void InitializeArchiveContents(TreeNode treeNode, string currentDirectory) + { + foreach (TreeNode node in treeNode.Nodes) + { + var isDirectory = false; + if (node.Tag != null) + { + var attributes = File.GetAttributes(node.Tag.ToString()); + if ((attributes & FileAttributes.Directory) == FileAttributes.Directory) + isDirectory = true; + } + else + { + isDirectory = true; + } + + if (isDirectory) + { + var tmpDir = $"{currentDirectory}/{node.Text}"; + try + { + _zip.AddDirectoryByName(tmpDir); + InitializeArchiveContents(node, tmpDir); + } + catch (ArgumentException) + { + var nodePlaceHolder = node; + Invoke( + new Action( + () => + Popup.ShowPopup(this, SystemIcons.Information, "The element was removed.", + $"The file/folder \"{nodePlaceHolder.Text}\" was removed from the collection because it is already existing in the current directory.", + PopupButtons.Ok))); + } } + else + { + try + { + _zip.AddFile(node.Tag.ToString(), currentDirectory); + } + catch (ArgumentException) + { + var nodePlaceHolder = node; + Invoke( + new Action( + () => + Popup.ShowPopup(this, SystemIcons.Information, "The element was removed.", + $"The file/folder \"{nodePlaceHolder.Text}\" was removed from the collection because it is already existing in the current directory.", + PopupButtons.Ok))); + } + } + } } private void removeVersionButton_Click(object sender, EventArgs e) @@ -1027,9 +1431,20 @@ private void saveButton_Click(object sender, EventArgs e) return; } + if (!filesDataTreeView.Nodes.Cast().Any(node => node.Nodes.Count > 0) && + categoryTreeView.Nodes[4].Nodes.Count <= 1) + { + Popup.ShowPopup(this, SystemIcons.Error, "No files and/or folders or operations set.", + "Please specify some files and/or folders that should be included or operations into the package.", + PopupButtons.Ok); + filesPanel.BringToFront(); + categoryTreeView.SelectedNode = _replaceNode; + return; + } + foreach ( var tabPage in - from tabPage in categoryTabControl.TabPages.Cast().Where(item => item.TabIndex > 3) + from tabPage in categoryTabControl.TabPages.Cast() let operationPanel = tabPage.Controls[0] as IOperationPanel where operationPanel != null && !operationPanel.IsValid select tabPage) @@ -1038,8 +1453,8 @@ from tabPage in categoryTabControl.TabPages.Cast().Where(item => item.T "Please make sure to fill out all required fields correctly.", PopupButtons.Ok); categoryTreeView.SelectedNode = - categoryTreeView.Nodes[3].Nodes.Cast() - .First(item => item.Index == tabPage.TabIndex - 4); + categoryTreeView.Nodes[4].Nodes.Cast() + .First(item => (int) item.Tag == categoryTabControl.TabPages.IndexOf(tabPage)); return; } @@ -1059,6 +1474,8 @@ var tabPage in _packageConfiguration.NecessaryUpdate = necessaryUpdateCheckBox.Checked; _packageConfiguration.Architecture = (Architecture) architectureComboBox.SelectedIndex; _packageConfiguration.Changelog = changelog; + _packageConfiguration.RolloutConditionMode = + (RolloutConditionMode) rolloutConditionModeComboBox.SelectedIndex; if (unsupportedVersionsListBox.Items.Count == 0) allVersionsRadioButton.Checked = true; @@ -1066,10 +1483,20 @@ var tabPage in _packageConfiguration.UnsupportedVersions = unsupportedVersionsListBox.Items.Cast().ToArray(); - _packageConfiguration.Operations.Clear(); - foreach (var operationPanel in from TreeNode node in categoryTreeView.Nodes[3].Nodes - select (IOperationPanel) categoryTabControl.TabPages[4 + node.Index].Controls[0]) - _packageConfiguration.Operations.Add(operationPanel.Operation); + var operations = new List(); + foreach (TreeNode node in categoryTreeView.Nodes[4].Nodes) + { + if (node.Equals(_replaceNode)) + continue; + + bool execBefore = categoryTreeView.Nodes[4].Nodes.IndexOf(_replaceNode) > node.Index; + var panel = (IOperationPanel) categoryTabControl.TabPages[(int) node.Tag].Controls[0]; + Operation op = panel.Operation; + op.ExecuteBeforeReplacingFiles = execBefore; + operations.Add(op); + } + + File.WriteAllText(Path.Combine(_extractedPackagePath, "operations.json"), Serializer.Serialize(operations)); _packageConfiguration.UseStatistics = includeIntoStatisticsCheckBox.Checked; @@ -1105,22 +1532,6 @@ var tabPage in } } - UpdateConfiguration[ - UpdateConfiguration.IndexOf( - UpdateConfiguration.First(item => item.LiteralVersion == PackageVersion.ToString()))] = - _packageConfiguration; - var configurationFilePath = Path.Combine(_newPackageDirectory, "updates.json"); - try - { - File.WriteAllText(configurationFilePath, Serializer.Serialize(UpdateConfiguration)); - } - catch (Exception ex) - { - Popup.ShowPopup(this, SystemIcons.Error, "Error while saving the new configuration.", ex, - PopupButtons.Ok); - return; - } - loadingPanel.Location = new Point(180, 91); loadingPanel.BringToFront(); @@ -1176,5 +1587,224 @@ private void unregisteredTrademarkToolStripMenuItem_Click(object sender, EventAr englishChangelogTextBox.Paste("™"); } } + + private void FilesDataTreeView_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e) + { + if (e.Node.Parent == null || e.Node.ImageIndex != 0) + e.Node.EndEdit(true); + } + + private void AddFolderButton_Click(object sender, EventArgs e) + { + InitializeDirectoryListing(false); + } + + private void AddFolderContentToolStripMenuItem_Click(object sender, EventArgs e) + { + InitializeDirectoryListing(true); + } + + private void InitializeDirectoryListing(bool onlyContent) + { + if (filesDataTreeView.SelectedNode == null) + return; + + string selectedPath; + using (var folderDialog = new FolderBrowserDialog()) + { + if (folderDialog.ShowDialog() != DialogResult.OK) + return; + + selectedPath = folderDialog.SelectedPath; + } + + TaskEx.Run(() => ListDirectoryContent(selectedPath, onlyContent)); + } + + private void ListDirectoryContent(string path, bool onlyContent) + { + ListDirectoryContent(path, filesDataTreeView.SelectedNode, onlyContent); + } + + private void ListDirectoryContent(string path, TreeNode selectedNode, bool onlyContent) + { + BeginInvoke(new Action(() => + { + if (!onlyContent) + { + var folderNode = new TreeNode(new DirectoryInfo(path).Name, 0, 0); + selectedNode.Nodes.Add(folderNode); + selectedNode = folderNode; + } + + var rootDirectoryInfo = new DirectoryInfo(path); + CreateFilesNode(rootDirectoryInfo, selectedNode); + foreach ( + var node in + rootDirectoryInfo.GetDirectories().Select(CreateDirectoryNode).Where(node => node != null)) + selectedNode.Nodes.Add(node); + + if (!selectedNode.IsExpanded) + selectedNode.Toggle(); + })); + } + + private void CreateFilesNode(DirectoryInfo directoryInfo, TreeNode directoryNode) + { + foreach (var file in directoryInfo.GetFiles()) + { + if (_nodeInitializingFailed) + { + _nodeInitializingFailed = false; + break; + } + + TreeNode fileNode; + if (string.IsNullOrWhiteSpace(file.Extension)) + { + fileNode = new TreeNode(file.Name, 1, 1) {Tag = file.FullName}; + } + else + { + if (string.IsNullOrEmpty(file.Extension)) + { + fileNode = new TreeNode(file.Name, 1, 1) {Tag = file.FullName}; + } + else if (filesImageList.Images.ContainsKey(file.Extension)) + { + var index = filesImageList.Images.IndexOfKey(file.Extension); + fileNode = new TreeNode(file.Name, index, index) {Tag = file.FullName}; + } + else + { + var icon = IconReader.GetFileIcon(file.Extension); + if (icon != null) + { + var index = 0; + var file1 = file; + Invoke(new Action(() => + { + filesImageList.Images.Add(file1.Extension, icon.ToBitmap()); + index = filesImageList.Images.IndexOfKey(file1.Extension); + })); + fileNode = new TreeNode(file.Name, index, index) {Tag = file.FullName}; + } + else + { + fileNode = new TreeNode(file.Name, 1, 1) {Tag = file.FullName}; + } + } + } + + var node = directoryNode; + Invoke(new Action(() => node.Nodes.Add(fileNode))); + } + } + + private TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo) + { + var directoryNode = new TreeNode(directoryInfo.Name, 0, 0) {Tag = directoryInfo.FullName}; + try + { + foreach (var directory in directoryInfo.GetDirectories()) + { + if (_nodeInitializingFailed) + { + _nodeInitializingFailed = false; + break; + } + + var node = CreateDirectoryNode(directory); + if (node != null) + directoryNode.Nodes.Add(node); + } + + CreateFilesNode(directoryInfo, directoryNode); + } + catch (Exception ex) + { + Invoke( + new Action( + () => + Popup.ShowPopup(this, SystemIcons.Error, "Error while adding a directory recursively.", ex, + PopupButtons.Ok))); + _nodeInitializingFailed = true; + directoryNode = null; + } + + return directoryNode; + } + + private void AddVirtualFolderToolStripMenuItem_Click(object sender, EventArgs e) + { + if (filesDataTreeView.SelectedNode == null) + return; + + var folderNode = new TreeNode("Folder name", 0, 0); + filesDataTreeView.SelectedNode.Nodes.Add(folderNode); + if (!filesDataTreeView.SelectedNode.IsExpanded) + filesDataTreeView.SelectedNode.Toggle(); + + folderNode.BeginEdit(); + } + + private void AddFilesButton_Click(object sender, EventArgs e) + { + if (filesDataTreeView.SelectedNode == null) + return; + + using (var fileDialog = new OpenFileDialog()) + { + fileDialog.SupportMultiDottedExtensions = true; + fileDialog.Multiselect = true; + fileDialog.Filter = "All Files (*.*)| *.*"; + + if (fileDialog.ShowDialog() != DialogResult.OK) return; + foreach (var fileName in fileDialog.FileNames) + { + TreeNode fileNode; + var fileInfo = new FileInfo(fileName); + if (string.IsNullOrEmpty(fileInfo.Extension)) + { + fileNode = new TreeNode(fileInfo.Name, 1, 1) {Tag = fileInfo.FullName}; + } + else if (filesImageList.Images.ContainsKey(fileInfo.Extension)) + { + var index = filesImageList.Images.IndexOfKey(fileInfo.Extension); + fileNode = new TreeNode(fileInfo.Name, index, index) {Tag = fileInfo.FullName}; + } + else + { + var icon = IconReader.GetFileIcon(fileInfo.Extension); + if (icon != null) + { + filesImageList.Images.Add(fileInfo.Extension, icon.ToBitmap()); + var index = filesImageList.Images.IndexOfKey(fileInfo.Extension); + fileNode = new TreeNode(fileInfo.Name, index, index) {Tag = fileInfo.FullName}; + } + else + { + fileNode = new TreeNode(fileInfo.Name, 1, 1) {Tag = fileInfo.FullName}; + } + } + + filesDataTreeView.SelectedNode.Nodes.Add(fileNode); + if (!filesDataTreeView.SelectedNode.IsExpanded) + filesDataTreeView.SelectedNode.Toggle(); + } + } + } + + private void RemoveEntryButton_Click(object sender, EventArgs e) + { + if (filesDataTreeView.SelectedNode?.Parent != null) + filesDataTreeView.SelectedNode.Remove(); + } + + private void InfoButton_Click(object sender, EventArgs e) + { + var updatingInfoDialog = new UpdatingInfoDialog(); + updatingInfoDialog.ShowDialog(); + } } } \ No newline at end of file diff --git a/nUpdate.Administration/UI/Dialogs/PackageEditDialog.resx b/nUpdate.Administration/UI/Dialogs/PackageEditDialog.resx index 4ab56ecc..cc3f23da 100644 --- a/nUpdate.Administration/UI/Dialogs/PackageEditDialog.resx +++ b/nUpdate.Administration/UI/Dialogs/PackageEditDialog.resx @@ -124,330 +124,348 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACe - SwAAAk1TRnQBSQFMAgEBEAEAAVABCAFQAQgBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA - AwABUAMAAQEBAAEgBgABUP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8AgQAB/wJUAVYBqwMo - AT1EAANOAZkBWQFcAVkBzANOAZkIAAMfAS4CPgE1AYcCPgE1AYcCPgE1AYcCPgE1AYcCPgE1AYcCPgE1 - AYcCPgE1AYcCPgE1AYcCPgE1AYcCPgE1AYcCPgE1AYcCNAExAV4DHAEpAxQBGwMLAQ9cAAFFAkYBfwHZ - AfQC/wFWAlkBvgMsAURAAAFZAVwBWQHMAQAB3wEAAf8BWQFcAVkBzAgAAh4BHQErAksBQQGQAtwB2QHv - A/4B/wP+Af8D/gH/A/4B/wP+Af8D/gH/A/4B/wP+A/8B/gH/AoQBfAHBAjABLgFTAwoBDgMGAQgDSgGM - A1YBuwNWAbsDVgG7A1YBuwNWAbkDVgG2A1YBtgNWAbYDWAHjAlMBZAHxAlMBZAHxAlMBZAHxAlMBZAHx - AlMBZAHxA1UBtQNKAYwDVgG7A1YBuwNWAbsDVgG7A1YBuQNWAbYDVgHBAVUCXAHqAUUB5gH3Af8DXQHt - A1gBywNWAbYDVgG2A1YBtgNIAYgDSgGMA1YBuwNWAbsDVgG7A1YBuwNWAbkDVgG2A1YBtgNWAbYBWAFd - AVgB4wFTAWQBUwHxAVMBZAFTAfEBCQHiAQAB/wFTAWQBUwHxAVMBZAFTAfEDVQG1BAACHgEdASsCXwFS - AasCzQG8Af8C0AHBAf8C1QHHAf8C2gHOAf8C4AHVAf8C5gHdAf8C7AHlAf8C8QHsAf8C9gHyAf8C/AH5 - Af8CPAE0AXkIAANVAbcCkwGkAf8CigGbAf8CigGbAf8CigGbAf8BOAE0AT0B/wGbApMB/wGSAooB/wGS - AooB/wIAAZUB/wIqAfcB/wIqAfcB/wIqAfcB/wIqAfcB/wIqAfcB/wJUAWEB7gNVAbcCkwGkAf8CigGb - Af8CigGbAf8CigGbAf8BOAE0AT0B/wGbApMB/wGSAooB/wE7AY8BlQH/AQABkwGlAf8BRQHmAfcB/wEA - AYMBlAH/ATcBhAGKAf8BkgKKAf8BkgKKAf8DUgGoA1UBtwKTAaQB/wKKAZsB/wKKAZsB/wKKAZsB/wE4 - ATQBPQH/AZsCkwH/AZICigH/AZICigH/AQABkwEAAf8BHgHnAQ0B/wEeAecBDQH/AR4B5wENAf8BHgHn - AQ0B/wEeAecBDQH/AVQBYQFUAe4IAAI7ATMBcQLxAeoB/wLvAegB/wLwAeoB/wLxAesB/wLzAe0B/wL0 - Ae8B/wL1AfEB/wL3AfIB/wL4AfQB/wL8AfgB/wI7ATMBcQgAA1UBsgKdAa4B/wKVAaYB/wKVAaYB/wKV - AaYB/wFKAUYBggH/AaUCnQH/AZ0ClQH/AZ0ClQH/AQ0BCgGhAf8CAAGeAf8CAAGlAf8CAAGkAf8CAAGk - Af8CAAGkAf8CWQFdAdcDVQGyAp0BrgH/ApUBpgH/ApUBpgH/ApUBpgH/AUoBRgGCAf8BpQKdAf8BnQKV - Af8BnQKVAf8BRQGZAZ8B/wEAAY8BoAH/AUUB5gH3Af8BAAGEAZUB/wFAAYkBjgH/AZ0ClQH/A08BmwNV - AbICnQGuAf8ClQGmAf8ClQGmAf8ClQGmAf8BSgFGAYIB/wGlAp0B/wGdApUB/wGdApUB/wEXAZwBCgH/ - AQABlgEAAf8BAAGdAQAB/wEyAesBIQH/AQABnAEAAf8BAAGcAQAB/wFZAV0BWQHXCAACOgEyAWsC+wH1 - Af8C9gHxAf8CzwHLAf8DWQH/AuIB3gH/AuIB3gH/A1kB/wLPAcsB/wL2AfEB/wL7AfUB/wI6ATIBawgA - A0QBegE/ATsBRAH/AT8BOwFEAf8BPwE7AUQB/wE/ATsBRAH/AS8BKgEvAf8BQwI7Af8BQQFAATsB/wE/ - AUQBOwH/AT8BRAE7Af8BLgEwASoB/wE/AUQBOwH/AUEBQAE7Af8BQwI7Af8BQwI7Af8DQAFxA0QBegE/ - ATsBRAH/AT8BOwFEAf8BPwE7AUQB/wE/ATsBRAH/AS8BKgEvAf8BQwI7Af8BQQFAATsB/wE/AUQBOwH/ - AT8BRAE7Af8BEwE9AT4B/wEAAY4BnQH/AUUB5gH3Af8BGgIWAf8BMgIrAf8DQAFxA0QBegE/ATsBRAH/ - AT8BOwFEAf8BPwE7AUQB/wE/ATsBRAH/AS8BKgEvAf8BQwI7Af8BQQFAATsB/wE/AUQBOwH/AT8BRAE7 - Af8BLgEwASoB/wEAAZsBAAH/AUEB7gEwAf8BAAGZAQAB/wFDAjsB/wNAAXEIAAI6ATIBZwL6AfIB/wLi - AdsB/wNiAf8CvQG4Af8C8wHsAf8C8wHsAf8CvQG4Af8DYgH/AuIB2wH/AvoB8gH/AjoBMgFnCAADTAGS - AaMCmwH/AZoCkgH/AUgCQAH/AaMCmwH/AZoCkgH/AZoCkgH/AUQBSQFAAf8BmwGsAZsB/wGSAaMBkgH/ - AZIBowGSAf8BkgGjAZIB/wFEAUkBQAH/AaMCmwH/AZoCkgH/A0wBkgNMAZIBowKbAf8BmgKSAf8BSAJA - Af8BowKbAf8BmgKSAf8BmgKSAf8BRAFJAUAB/wGbAawBmwH/AZIBowGSAf8BkgGjAZIB/wE7AaMBnAH/ - ATABMwEuAf8D9wH/AR4BGgE8Af8DUwGwA0wBkgGjApsB/wGaApIB/wFIAkAB/wGjApsB/wGaApIB/wGa - ApIB/wFEAUkBQAH/AZsBrAGbAf8BkgGjAZIB/wGSAaMBkgH/ARMBpwEHAf8BAAGgAQAB/wEYAaIBCQH/ - AZoCkgH/A0wBkggAAjoBMwFmAvgB7gH/Aq8BqgH/AqABnAH/AvAB5gH/AvAB5gH/AvAB5gH/AvAB5gH/ - AqABnAH/Aq8BqgH/AvgB7gH/AjoBMwFmCAADSwGOAa8CpwH/AacCnwH/AY0ChgH/Aa8CpwH/AacCnwH/ - AacCnwH/AYkBjgGGAf8BpwG4AacB/wGfAbABnwH/AZ8BsAGfAf8BnwGwAZ8B/wGJAY4BhgH/Aa8CpwH/ - AacCnwH/A0sBjgNLAY4BrwKnAf8BpwKfAf8BjQKGAf8BrwKnAf8BpwKfAf8BpwKfAf8BiQGOAYYB/wGn - AbgBpwH/AZ8BsAGfAf8BnwGwAZ8B/wGfAbABnwH/AYMBhwGAAf8BPgE6AZMB/wKAAv8CWgFhAeQDSwGO - Aa8CpwH/AacCnwH/AY0ChgH/Aa8CpwH/AacCnwH/AacCnwH/AYkBjgGGAf8BpwG4AacB/wGfAbABnwH/ - AZ8BsAGfAf8BnwGwAZ8B/wGJAY4BhgH/Aa8CpwH/AacCnwH/A0sBjggAAjwBNAFmAvYB6wH/At4B1AH/ - A3kB/wLCAbsB/wLtAeEB/wLtAeEB/wLCAbsB/wN5Af8C3gHUAf8C9gHrAf8CPAE0AWYIAAM/AW4BgQGG - AUkB/wGBAYYBSQH/AToBPAE2Af8BgQGGAUkB/wGDAYIBSQH/AYUCSQH/AjsBNgH/AYEBhgFJAf8BgQGG - AUkB/wFLAYYBggH/AUkChgH/ATgBOwE8Af8BgQFJAYYB/wGBAUkBhgH/Az8BbgM/AW4BgQGGAUkB/wGB - AYYBSQH/AToBPAE2Af8BgQGGAUkB/wGDAYIBSQH/AYUCSQH/AjsBNgH/AYEBhgFJAf8BgQGGAUkB/wFL - AYYBggH/AUkChgH/ATgBOwE8Af8BMgEwAZoB/wIAAcIB/wNKAY0DPwFuAYEBhgFJAf8BgQGGAUkB/wE6 - ATwBNgH/AYEBhgFJAf8BgwGCAUkB/wGFAkkB/wI7ATYB/wGBAYYBSQH/AYEBhgFJAf8BSwGGAYIB/wFJ - AoYB/wE4ATsBPAH/AYEBSQGGAf8BgQFJAYYB/wM/AW4IAAI9ATYBZgL1AecB/wLqAdwB/wLRAccB/wOG - Af8C3gHSAf8C3gHSAf8DhgH/AtEBxwH/AuoB3AH/AvUB5wH/Aj0BNgFmCAADTAGTAacBuAGnAf8BngGv - AZ4B/wGeAa8BngH/AZ4BrwGeAf8BhQGKAYEB/wGvAqcB/wGmAp4B/wGmAp4B/wGmAp4B/wGFAYEBigH/ - AqcBuAH/Ap4BrwH/Ap4BrwH/Ap4BrwH/A0wBkwNMAZMBpwG4AacB/wGeAa8BngH/AZ4BrwGeAf8BngGv - AZ4B/wGFAYoBgQH/Aa8CpwH/AaYCngH/AaYCngH/AaYCngH/AYUBgQGKAf8CpwG4Af8CngGvAf8CngGv - Af8CngGvAf8DTAGTA0wBkwGnAbgBpwH/AZ4BrwGeAf8BngGvAZ4B/wGeAa8BngH/AYUBigGBAf8BrwKn - Af8BpgKeAf8BpgKeAf8BpgKeAf8BhQGBAYoB/wKnAbgB/wKeAa8B/wKeAa8B/wKeAa8B/wNMAZMIAAI+ - ATgBZgL0AeQB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wLoAdgB/wL0 - AeQB/wI+ATgBZggAA0oBjAGzAcQBswH/AaoBuwGqAf8BqgG7AaoB/wGqAbsBqgH/AZUBmQGRAf8BuwKz - Af8BsgKqAf8BsgKqAf8BsgKqAf8BlQGRAZkB/wKzAcQB/wKqAbsB/wKqAbsB/wKqAbsB/wNKAYwDSgGM - AbMBxAGzAf8BqgG7AaoB/wGqAbsBqgH/AaoBuwGqAf8BlQGZAZEB/wG7ArMB/wGyAqoB/wGyAqoB/wGy - AqoB/wGVAZEBmQH/ArMBxAH/AqoBuwH/AqoBuwH/AqoBuwH/A0oBjANKAYwBswHEAbMB/wGqAbsBqgH/ - AaoBuwGqAf8BqgG7AaoB/wGVAZkBkQH/AbsCswH/AbICqgH/AbICqgH/AbICqgH/AZUBkQGZAf8CswHE - Af8CqgG7Af8CqgG7Af8CqgG7Af8DSgGMCAACQAE5AWYC8wHjAf8C5gHWAf8C5gHWAf8C5gHWAf8C5gHW - Af8C5gHWAf8C5gHWAf8C5gHWAf8C5gHWAf8C8wHjAf8CQAE5AWYIAAM7AWMBjAGQAYgB/wGMAZABiAH/ - A0cBgwNIAYYDTQGWA0YBgAGQAogB/wGQAogB/wNGAYADTQGWA0gBhgNHAYMBjAGIAZAB/wGMAYgBkAH/ - AzsBYwM7AWMBjAGQAYgB/wGMAZABiAH/A0cBgwNIAYYDTQGWA0YBgAGQAogB/wGQAogB/wNGAYADTQGW - A0gBhgNHAYMBjAGIAZAB/wGMAYgBkAH/AzsBYwM7AWMBjAGQAYgB/wGMAZABiAH/A0cBgwNIAYYDTQGW - A0YBgAGQAogB/wGQAogB/wNGAYADTQGWA0gBhgNHAYMBjAGIAZAB/wGMAYgBkAH/AzsBYwgAAkIBOwFm - AvIB4QH/AuUB1AH/AuUB1AH/AuUB1AH/AuUB1AH/AuUB1AH/AuUB1AH/AuUB1AH/AuUB1AH/AvIB4QH/ - AkIBOwFmCAADRQF9AbkCsQH/AbACqAH/A0UBfQgAA0UBfQG5ArEB/wGwAqgB/wNFAX0IAANFAX0BuQKx - Af8BsAKoAf8DRQF9A0UBfQG5ArEB/wGwAqgB/wNFAX0IAANFAX0BuQKxAf8BsAKoAf8DRQF9CAADRQF9 - AbkCsQH/AbACqAH/A0UBfQNFAX0BuQKxAf8BsAKoAf8DRQF9CAADRQF9AbkCsQH/AbACqAH/A0UBfQgA - A0UBfQG5ArEB/wGwAqgB/wNFAX0IAAJDATwBZgL0AeUB/wLoAdkB/wLoAdkB/wLoAdkB/wLoAdkB/wLo - AdkB/wLoAdkB/wLoAdkB/wLoAdkB/wL0AeUB/wJDATwBZggAA0QBewHDArsB/wG6ArIB/wNEAXsIAANE - AXsBwwK7Af8BugKyAf8DRAF7CAADRAF7AcMCuwH/AboCsgH/A0QBewNEAXsBwwK7Af8BugKyAf8DRAF7 - CAADRAF7AcMCuwH/AboCsgH/A0QBewgAA0QBewHDArsB/wG6ArIB/wNEAXsDRAF7AcMCuwH/AboCsgH/ - A0QBewgAA0QBewHDArsB/wG6ArIB/wNEAXsIAANEAXsBwwK7Af8BugKyAf8DRAF7CAACRAE+AWYC/AHz - Af8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C+gHxAf8CdgFr - AaADGwEkBAADNwFbA0QBeQNEAXkDNwFbCAADNwFbA0QBeQNEAXkDNwFbCAADNwFbA0QBeQNEAXkDNwFb - AzcBWwNEAXkDRAF5AzcBWwgAAzcBWwNEAXkDRAF5AzcBWwgAAzcBWwNEAXkDRAF5AzcBWwM3AVsDRAF5 - A0QBeQM3AVsIAAM3AVsDRAF5A0QBeQM3AVsIAAM3AVsDRAF5A0QBeQM3AVsIAAIqASgBOQKQAYgBswL+ - Af0B/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wLhAd4B7AJV - AU4BegIYARcBH8wAAioBKAE5AkYBQAFmAkYBQAFmAkYBQAFmAkYBQAFmAkYBQAFmAkYBQAFmAkYBQAFm - AkYBQAFmAkYBQAFmAkYBQAFmAkYBQAFmAxQBGiwAA04BmQFZAVwBWQHMA04BmQgAAw0BEgMfASwDQQFy - A0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNBAXIDHwEsAw0BEggAAw0BEgMf - ASwDQQFyA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNBAXIDDQESAx8BLANB - AXIDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcBXgJbAdADUAGeAx8BLAMNARIDBAEG - AxABFgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgFYAVwBWAHRAQAB3wEAAf8BWAFc - AVgB0QMQARYDBAEGAwcBCQMQARYDRwGCDv8B/gH/Av4B/QH/Av4B/AH/Av0B+wH/Av0B+gH/AvwB+AH/ - Av4B+QH/A0cBggMQARYDBwEJCAADBwEJAxABFgNHAYIO/wH+Af8C/gH9Af8C/gH8Af8C/QH7Af8C/QH6 - Af8C/AH4Af8C/gH5Af8DRwGCAwcBCQMQARYDRwGCDv8B/gH/Av4B/QH/Av4B/AH/Av0B+wH/Av0B+gH/ - AvwB+AH/AbgCAAH/AWEBWQFYAeYBQAI/AW4DBwEJAzwBaANIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNI - AYcDSAGHAVsBXgFbAdABXAFkAVwB5wFcAWQBXAHnAQAB4gEAAf8BXAFkAVwB5wFcAWQBXAHnAVUBVgFV - AbEIAANEAXsI/wP+Af8C/QH8Af8C/QH7Af8C/AH5Af8CAAGyAf8CAAGXAf8CAAGXAf8CAAGYAf8CXgFl - AeUCWQFcAcwDTgGZEAADRAF7CP8D/gH/Av0B/AH/Av0B+wH/AvwB+QH/AvsB+AH/AvoB9gH/AvgB9AH/ - AvsB9gH/A0QBewgAA0QBewj/A/4B/wL9AfwB/wL9AfsB/wHSAaUBAAH/AcMBhwEAAf8BwwGHAQAB/wHC - AYYBAAH/AcMBhwEAAv8BxQEAAf8CXAFZAcwDOAFcA0UBfwPKAf8DxQH/A8UB/wPFAf8DxQH/A8UB/wPF - Af8DxQH/AQABnwEAAf8BAAHnAQAB/wEAAecBAAH/AQAB5wEAAf8BAAHnAQAB/wEAAecBAAH/AVgBYQFY - AeYIAANDAXcE/wP+Af8C/QH8Af8C/QH7Af8C/AH5Af8C+wH4Af8CAAGrAf8CAAH3Af8CAAH3Af8CAAH3 - Af8CAAH3Af8CAAH3Af8CWQFcAcwQAANDAXcE/wOrAf8DSwH/AqsBqQH/AksBSgH/AqkBpgH/AvoB9gH/ - AvgB9AH/AvcB8gH/AvsB9QH/A0MBdwgAA0MBdwT/A/4B/wL9AfwB/wL9AfsB/wL8AfkB/wHOAZMBAAL/ - AeMBkgL/AdUBAAL/AdEBAAL/AdEBAAL/AdEBAAL/AdgBAAH/AlwBWQHMA0MBeAPIAf8DAAH/AwAB/wMA - Af8DAAH/AwAB/wMAAf8DAAH/AQABgwEAAf8BAAGPAQAB/wEAAY8BAAH/AQAB6wEAAf8BAAGRAQAB/wEA - AaYBAAH/AVkBXAFZAckIAANCAXYC/wH+Af8C/QH8Af8C/QH7Af8C/AH5Af8C+wH4Af8C+gH2Af8CAAHF - Af8CAAG2Af8CAAG2Af8CAAG3Af8CWgFhAeQCWQFcAcwDTgGZEAADQgF2Av8B/gH/Av0B/AH/Av0B+wH/ - AlABTwH/AvsB+AH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvoB8wH/A0IBdggAA0IBdgL/Af4B/wL9 - AfwB/wL9AfsB/wL8AfkB/wL7AfgB/wHhAbQBAAH/AdkBnQEAAf8B2QGdAQAB/wHZAZ0BAAH/AdoBngEA - Av8B5QGXAf8CXAFZAcwDOAFcA0IBdgPLAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8BAAGXAQAB/wEAAe4BAAH/AQABlAEAAf8DywH/A0IBdggAA0IBdAL+Af0B/wL9AfsB/wL8AfkB/wL7 - AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1Ae4B/wL6AfIB/wNCAXQIAAMxAU4DPQFnAz0BZwM9 - AWcDSgGKA8kB/wLJAcgB/wPIAf8DWAH/AsgBxwH/AtMB0QH/AvcB8gH/AvYB8AH/AvUB7gH/AvoB8gH/ - A0IBdAgAA0IBdAL+Af0B/wL9AfsB/wL8AfkB/wL7AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1 - Ae4B/wHlAakBAAH/Al8BWAHjAzgBXAQAA0IBdAPOAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wG7Ad0BAAH/ - AwAB/wMAAf8DAAH/AQABiQEAAf8BAAGaAQAB/wEAAYQBAAH/A84B/wNCAXQIAANBAXIC/gH8Af8C/AH5 - Af8C+wH4Af8C+gH2Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C+QHvAf8DQQFyCAADPQFp - A/oB/wP6Af8D+gH/A/oB/wP6Af8D+gH/A/oB/wNhAf8D+gH/AsIBwAH/AvYB8AH/AvUB7gH/AvQB7AH/ - AvkB7wH/A0EBcggAA0EBcgL+AfwB/wL8AfkB/wL7AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1 - Ae4B/wL0AewB/wHtAcABhAH/AlMBTwGlCAADQQFyA9IB/wEAAYQBAAH/AaABuQEAAf8BhAGVAQAB/wG7 - Ad0BAAH/AbsB3QEAAf8DAAH/AbsB3QEAAf8DAAH/AaMBugEAAf8BzAHmAYAB/wHuAfcBswH/AwAB/wPS - Af8DQQFyCAADQAFxAv0B+wH/AvsB+AH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/ - AvEB5wH/AvcB6gH/A0ABcQgAAz4BawPxAf8B6QGDAVUB/wHIAVgBNgH/Aa0BPAEaAf8BuAE9ARsB/wHa - AU8BLQH/A/EB/wNpAf8D8QH/ArsBuQH/AvUB7gH/AvQB7AH/AvEB5wH/AvcB6gH/A0ABcQgAA0ABcQL9 - AfsB/wL7AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wL3AeoB/wNA - AXEIAANAAXAD1gH/AwAB/wMAAf8BjgGfAQAB/wMAAf8BuwHdAQAB/wMAAf8DAAH/AbsB3QEAAf8BkQGc - AQAB/wMAAf8DAAH/AwAB/wPWAf8DQAFwCAADQAFvAv0B+gH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/ - AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AvQB5QH/A0ABbwgAAz8BbQPnAf8B6QGDAVUB/wHIAVgBNgH/ - Aa0BPAEaAf8BuAE9ARsB/wHaAU8BLQH/A+cB/wNxAf8D5wH/ArIBsAH/AvQB7AH/AvEB5wH/AuwB3wH/ - AvQB5QH/A0ABbwgAA0ABbwL9AfoB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLx - AecB/wLsAd8B/wL0AeUB/wNAAW8IAANAAW4D2gH/AwAB/wMAAf8DAAH/AwAB/wG7Ad0BAAH/AwAB/wMA - Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wPaAf8DQAFuCAADPwFtAvwB+AH/AvgB9AH/AvcB8gH/AvYB8AH/ - AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/AvMB4gH/Az8BbQgAA0ABcAPfAf8D3wH/A98B/wPf - Af8D3wH/A98B/wPfAf8DhgH/A98B/wKnAaUB/wLxAecB/wLsAd8B/wLoAdkB/wLzAeIB/wM/AW0IAAM/ - AW0C/AH4Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZAf8C8wHi - Af8DPwFtCAADPwFsA94B/wMAAf8DAAH/AwAB/wMAAf8BpgG/AQAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ - AwAB/wMAAf8D3gH/Az8BbAgAAz8BbAL8AfcB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wLs - Ad8B/wLoAdkB/wLmAdUB/wLyAeEB/wM/AWwIAAM2AVkDQwF3A0MBdwNDAXcDTAGTAo0BjAH/AowBiwH/ - AowBigH/AooBiAH/AosBiQH/AqUBnwH/AuwB3wH/AugB2QH/AuYB1QH/AvIB4QH/Az8BbAgAAz8BbAL8 - AfcB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLmAdUB/wLyAeEB/wM/ - AWwIAAM+AWoD4QH/AwAB/wMAAf8DAAH/AwAB/wGTAaQBAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ - AwAB/wPhAf8DPgFqCAADPgFrAvsB9gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/ - AuYB1QH/AuUB1AH/AvIB4QH/Az4BaxgAAz4BawL7AfYB/wL2AfAB/wL1Ae4B/wKNAYgB/wLxAecB/wLs - Ad8B/wLoAdkB/wLmAdUB/wLlAdQB/wLyAeEB/wM+AWsIAAM+AWsC+wH2Af8C9gHwAf8C9QHuAf8C9AHs - Af8C8QHnAf8C7AHfAf8C6AHZAf8C5gHVAf8C5QHUAf8C8gHhAf8DPgFrCAADPQFpA+QB/wMAAf8DAAH/ - AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wPkAf8DPQFpCAADPQFpAvoB9AH/ - AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/AuYB1QH/AqQBkwH/AqQBkwH/AqQBkwH/AkUBRAF8 - GAADPQFpAvoB9AH/AsMBvgH/ApEBjQH/AsABuAH/Ao0BhQH/ArkBrQH/AuYB1QH/AqQBkwH/AqQBkwH/ - AqQBkwH/AkUBRAF8CAADPQFpAvoB9AH/AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/AuYB1QH/ - AqQBkwH/AqQBkwH/AqQBkwH/AkUBRAF8CAADPQFoA+oB/wPlAf8D5QH/A+UB/wPlAf8D5QH/A+UB/wPl - Af8D5QH/A+UB/wPlAf8D5QH/A+UB/wPqAf8DPQFoCAADPQFoAvoB8wH/AvQB7AH/AvEB5wH/AuwB3wH/ - AugB2QH/AuYB1QH/AuUB1AH/ArYBpQX/Az0BaAMaASUYAAM9AWgC+gHzAf8C9AHsAf8C8QHnAf8C7AHf - Af8C6AHZAf8C5gHVAf8C5QHUAf8CtgGlBf8DPQFoAxoBJQgAAz0BaAL6AfMB/wL0AewB/wLxAecB/wLs - Ad8B/wLoAdkB/wLmAdUB/wLlAdQB/wK2AaUF/wM9AWgDGgElCAADMQFNAzwBZgM8AWYDPAFmAzwBZgM8 - AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDMQFNCAADPQFnAvwB9QH/AvkB7wH/ - AvYB6gH/AvQB5QH/AvMB4gH/AvIB4QH/AvIB4QH/AsIBsQH/Az0BZwMaASUcAAM9AWcC/AH1Af8C+QHv - Af8C9gHqAf8C9AHlAf8C8wHiAf8C8gHhAf8C8gHhAf8CwgGxAf8DPQFnAxoBJQwAAz0BZwL8AfUB/wL5 - Ae8B/wL2AeoB/wL0AeUB/wLzAeIB/wLyAeEB/wLyAeEB/wLCAbEB/wM9AWcDGgElVAADMQFNAzwBZgM8 - AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDGgEkIAADMQFNAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFm - AzwBZgM8AWYDGgEkEAADMQFNAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDGgEkUAADCwEP - AxIBGAMSARkDEgEYAxABFQMNARIDCwEPAwoBDgMKAQ4DDAEQAw0BEgMQARUDEgEYAxMBGgMSARgDCwEP - AwsBDwMSARgDEgEZAxIBGAMQARUDDQESAwsBDwMKAQ4DCgEOAwwBEAMNARIDEAEVAxIBGAMTARoDEgEY - AwsBD0cAAQEDAgEDAwQBBgMHAQkDCgQNAREDEAEVAxEBFwMSARkDEgEYAwkBDBAAAxYBHgMhATADSgGN - A08BpQMdASkDGQEjAxUBHQMUARsDFAEbAxYBHwMaASQDHQEqA0oBjANSAaYDIQEwAxYBHgMWAR4DIQEw - A0oBjQNPAaUDHQEpAxkBIwMVAR0DFAEbAxQBGwMWAR8DGgEkAx0BKgNKAYwDUgGmAyEBMAMWAR4DBAEG - AxABFgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMQARYDBAEG - BwABAQMEAQYDCQEMAw0BEgMTARoDIAEuAzwBZgNDAXgDPAFnAyYBOQMRARcQAAMGAQgDCQEMA1QBqwNZ - AcwDCAELAwcBCQMGAQgDBQEHAwUBBwMGAQgDBwEJAwgBCwNUAasDWQHMAwkBDAMGAQgDBgEIAwkBDANU - AasDWQHMAwgBCwMHAQkDBgEIAwUBBwMFAQcDBgEIAwcBCQMIAQsDVAGrA1kBzAMJAQwDBgEIAzwBaANI - AYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA1sB0AJcAWQB5wJcAWQB5wJcAWQB5wJcAWQB5wJc - AWQB5wJVAVYBsRgAAzkBYANZAb8D5AH/A1kBvwM5AWAYAANKAYsDVgGzA1kByQJZAVwByQJZAV0B0gFb - Al4B2QFYAl4B3QFcAmEB3AFaAV0BXgHYAlgBXAHRA1sByANWAbkDWQHEA0oBiwgAA0oBiwNWAbMDWQHJ - AlkBXAHJAlkBXQHSAVsCXgHZAVgCXgHdAVwCYQHcAVoBXQFeAdgCWAFcAdEDWwHIA1YBuQNZAcQDSgGL - BAADRQF/A8oB/wPFAf8DxQH/A8UB/wPFAf8DxQH/A8UB/wPFAf8CAAGhAf8CAAH3Af8CAAH3Af8CAAH3 - Af8CAAH3Af8CAAH3Af8CWAFhAeYMAAMwAU0DPAFmAzwBZgNBAXMD8gH/A/IB/wPyAf8DQQFzGAADVgGz - AYwBpAG/Af8BjwGnAcIB/wGVAawByAH/AZoBsQHNAf8BnwG1AdIB/wGiAbcB1QH/AaIBtwHVAf8BngG0 - AdEB/wGaAbABzQH/AZQBrAHHAf8BjwGnAcIB/wGMAaUBvwH/A1YBswgAA1YBswGMAaQBvwH/AY8BpwHC - Af8BlQGsAcgB/wGaAbEBzQH/AZ8BtQHSAf8BogG3AdUB/wGiAbcB1QH/AZ4BtAHRAf8BmgGwAc0B/wGU - AawBxwH/AY8BpwHCAf8BjAGlAb8B/wNWAbMEAANDAXgDyAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ - AwAB/wIAAYkB/wIAAZcB/wIAAZcB/wIAAZcB/wIAAZgB/wIAAa4B/wJZAVwByQwAAzwBZggAAzgBXANY - AbwD/QH/A1gBvAM4AVwYAAJUAVYBqwGTAasBxgH/AQABigGkAf8BAAGDAZ0B/wEAAYgBogH/AQABjQGn - Af8BAAGQAaoB/wEAAZABqgH/AQABjQGnAf8BAAGJAaMB/wEAAYQBngH/AQABigGkAf8BkwGrAcYB/wJU - AVYBqwgAAlQBVgGrAZMBqwHGAf8BAAGKAaQB/wEAAYMBnQH/AQABiAGiAf8BAAGNAacB/wEAAZABqgH/ - AQABkAGqAf8BAAGNAacB/wEAAYkBowH/AQABhAGeAf8BAAGKAaQB/wGTAasBxgH/AlQBVgGrBAADQgF2 - A8sB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wPLAf8DQgF2 - DAADPAFmCAADDQESAzcBWgNAAW4DNwFaAw0BEhgAA1EBogGcAbMBzwH/AQABgAGaAf8BlAGtAccB/wGU - Aa0BxwH/AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/AQABgAGa - Af8BnAGzAc8B/wNRAaIIAANRAaIBnAGzAc8B/wEAAYABmgH/AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/ - AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/AZQBrQHHAf8BlAGtAccB/wEAAYABmgH/AZwBswHPAf8DUQGi - BAADQgF0A84B/wMAAf8DAAH/AwAB/wMAAf8DAAH/AbsB3QEAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8DzgH/A0IBdAwAAzwBZjAAAxQBGwJUAVYBqwGkAbsB1wH/AQABgAGaAf8BpwHAAdoB/wGqAcEB3QH/ - Aa0BwwHgAf8BrwHEAeIB/wGvAcQB4gH/Aa0BwwHgAf8BqgHCAd0B/wGoAcAB2wH/AQABgAGaAf8BpAG7 - AdcB/wJUAVYBqwMUARsDFAEbAlQBVgGrAaQBuwHXAf8BAAGAAZoB/wGnAcAB2gH/AaoBwQHdAf8BrQHD - AeAB/wGvAcQB4gH/Aa8BxAHiAf8BrQHDAeAB/wGqAcIB3QH/AagBwAHbAf8BAAGAAZoB/wGkAbsB1wH/ - AlQBVgGrAxQBGwNBAXID0gH/AQABhAEAAf8BoAG5AQAB/wGEAZUBAAH/AbsB3QEAAf8BuwHdAQAB/wMA - Af8BuwHdAQAB/wMAAf8BowG6AQAB/wHMAeYBgAH/Ae4B9wGzAf8DAAH/A9IB/wNBAXIMAAM8AWYwAAMz - AVIDXgHQAasBwQHeAf8DAAH/AQABhgGgAf8BAAGGAaAB/wEAAYYBoAH/AgABjwH/AgABjwH/AQABhgGg - Af8BAAGGAaAB/wEAAYYBoAH/AwAB/wGrAcEB3gH/A14B0AMzAVIDMwFSA14B0AGrAcEB3gH/AwAB/wEA - AYYBoAH/AQABhgGgAf8BAAGGAaAB/wIAAY8B/wIAAY8B/wEAAYYBoAH/AQABhgGgAf8BAAGGAaAB/wMA - Af8BqwHBAd4B/wNeAdADMwFSA0ABcAPWAf8DAAH/AwAB/wGOAZ8BAAH/AwAB/wG7Ad0BAAH/AwAB/wMA - Af8BuwHdAQAB/wGRAZwBAAH/AwAB/wMAAf8DAAH/A9YB/wNAAXAMAAM8AWYUAAMYASECUgFUAaYCWQFc - AcwCUgFUAaYDGAEhCAADSAGGAasBwgHeAf8BsAHFAeMB/wIAAYwB/wEAAZQBrgH/AQABlAGuAf8BAAGU - Aa4B/wEAAYMBnQH/AQABgwGdAf8BAAGUAa4B/wEAAZQBrgH/AQABlAGuAf8BgAIAAf8BqgGcAZUB/wGr - AcIB3gH/A0gBhgNIAYYBqwHCAd4B/wGwAcUB4wH/AgABjAH/AQABlAGuAf8BAAGUAa4B/wEAAZQBrgH/ - AQABgwGdAf8BAAGDAZ0B/wEAAZQBrgH/AQABlAGuAf8BAAGUAa4B/wIAAYwB/wGwAcUB4wH/AasBwgHe - Af8DSAGGA0ABbgPaAf8DAAH/AwAB/wMAAf8DAAH/AbsB3QEAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8DAAH/A9oB/wNAAW4MAAM8AWYIAAJZAVwBzAMjATMEAAJRAVIBpwJXAV8B6AIAAesB/wJXAV8B6AJR - AVIBpwgAAkUBRgF/Aa4BxQHhAf8BjwGmAcIB/wEAAYMBnQH/AY0BpgG/Af8BjQGmAb8B/wGNAaYBvwH/ - AQABlQGuAf8BAAGVAa4B/wGNAaYBvwH/AY0BpgG/Af8BjQGmAb8B/wGbAgAB/wGiAgAB/wGsAaABlgH/ - AkUBRgF/AkUBRgF/Aa4BxQHhAf8BjwGmAcIB/wEAAYMBnQH/AY0BpgG/Af8BjQGmAb8B/wGNAaYBvwH/ - AQABlQGuAf8BAAGVAa4B/wGNAaYBvwH/AY0BpgG/Af8BjQGmAb8B/wEAAYMBnQH/AY8BpgHCAf8BrgHF - AeEB/wJFAUYBfwM/AWwD3gH/AwAB/wMAAf8DAAH/AwAB/wGmAb8BAAH/AwAB/wMAAf8DAAH/AwAB/wMA - Af8DAAH/AwAB/wPeAf8DPwFsBAADPAFmAzwBZgM8AWYDPAFmBAADVgGzAlkBXAHMBAACWQFcAcwCAAH1 - Af8CAAH1Af8CAAH1Af8CWQFcAcwIAAMoAT0DRAF5Ak0BTgGWAQABlQGvAf8BngG3AdEB/wGeAbcB0QH/ + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADa + TwAAAk1TRnQBSQFMAgEBEQEAAXgBCAF4AQgBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + AwABUAMAAQEBAAEgBgABUP8AEwADCwEPAxEBFwMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEa + AxMBGgMTARoDEwEaAxMBGgMRARcDCwEPwAACTAFRAaACQgFcAcwCQgFcAcwCQgFcAcwCQgFcAcwCQgFc + AcwCQgFcAcwCQgFcAcwCQgFcAcwCQgFcAcwCQgFcAcwCQgFcAcwCQgFcAcwCQgFcAcwCQgFcAcwCTAFR + AaDAAAJCAWQBzAIsAeAB/wIiAdsB/wIgAdoB/wIeAdoB/wIcAdkB/wIbAdgB/wIZAdgB/wIYAdcB/wIX + AdcB/wIWAdYB/wIVAdYB/wIVAdYB/wIVAdYB/wIVAdYB/wJCAWQBzMAAAkIBZgHMAjYB1gH/AiMByQH/ + AiMByQH/AiMByQH/AiMByQH/AiMByQH/Ag4BmQH/Ag4BmQH/AhkBsQH/AiMByQH/AiMByQH/AiMByQH/ + AiMByQH/AiMByQH/AkIBZgHMwAACQgFpAcwCRAHSAf8CLgG9Af8CLgG9Af8CLgG9Af8CLgG9Af8CLgG9 + Af8DwgH/A8IB/wIeAasB/wIuAb0B/wIuAb0B/wIuAb0B/wIuAb0B/wIxAcAB/wJCAWkBzMAAAkIBawHM + Ag4BmQH/Ag4BmQH/Ag4BmQH/Ag4BmQH/Ag4BmQH/Ag4BmQH/A6wB/wOIAf8CBgGIAf8CDgGZAf8CDgGZ + Af8CDgGZAf8CDgGZAf8CDgGZAf8CQgFrAczAAAJCAW0BzAJSAd0B/wI3AcIB/wI3AcIB/wI3AcIB/wI3 + AcIB/wI3AcIB/wPbAf8D2wH/AiMBrgH/AjcBwgH/AjcBwgH/AjcBwgH/AjcBwgH/AkEBzAH/AkIBbQHM + wAACQgFtAcwCdAL/AnQC/wJ0Av8CdAL/AnQC/wJ0Av8CdAL/AnQC/wJ0Av8CdAL/AnQC/wJ0Av8CdAL/ + AnQC/wJCAW0BzMAAAkIBbwHMAmUB8AH/AlUB4AH/AlUB4AH/AlUB4AH/AlUB4AH/AlUB4AH/AlUB4AH/ + AlUB4AH/AlUB4AH/AlUB4AH/AlUB4AH/AlUB4AH/AlUB4AH/Al8B6gH/AkIBbwHMwAACQgFwAcwCbwH6 + Af8CagH1Af8CagH1Af8CWQHCAf8CSAGPAf8CWQHCAf8CagH1Af8CaQH0Af8CWQHCAf8CSAGPAf8CWAHB + Af8CaAHzAf8CaAHzAf8CbAH3Af8CQgFwAczAAAJKAVIBmQJCAXEBzAJCAXEBzAJCAXEBzAJFAVoBygOZ + Af8CRQFaAcoCQgFxAcwCQgFxAcwCRQFaAcoDmQH/AkUBWgHKAkIBcQHMAkIBcQHMAkIBcQHMAkoBUgGZ + 0AADIQEwA0kBvhAAA0kBvgMhATDgAAMRARcDSgG0A0cBhwM2AVkDNgFZA0cBhwNKAbQDEQEX5AADNQFX + A0wBrQNMAa0DTAGtA0wBrQM1AVf/AP8ANQAB/wJUAVYBqwMoAT1EAANOAZkBWQFcAVkBzANOAZkIAAMg + AS4DSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwM4AV4DHQEpAxQBGwML + AQ9cAAFFAkYBfwHZAfQC/wFWAlkBvgMsAURAAAFZAVwBWQHMAQAB3wEAAf8BWQFcAVkBzAgAAx4BKwNL + AZACnwGdAe8D/gH/A/4B/wP+Af8D/gH/A/4B/wP+Af8D/gH/A/4D/wH+Af8DWwHBAzMBUwMKAQ4DBgEI + A0oBjANWAbsDVgG7A1YBuwNWAbsDVgG5A1YBtgNWAbYDVgG2A1gB4wJTAWQB8QJTAWQB8QJTAWQB8QJT + AWQB8QJTAWQB8QNVAbUDSgGMA1YBuwNWAbsDVgG7A1YBuwNWAbkDVgG2A1YBwQFVAlwB6gFAAeYB9wH/ + A10B7QNYAcsDVgG2A1YBtgNWAbYDSAGIA0oBjANWAbsDVgG7A1YBuwNWAbsDVgG5A1YBtgNWAbYDVgG2 + AVgBXQFYAeMBUwFkAVMB8QFTAWQBUwHxAQQB4gEAAf8BUwFkAVMB8QFTAWQBUwHxA1UBtQQAAx4BKwJW + AVQBqwLNAbwB/wLQAcEB/wLVAccB/wLaAc4B/wLgAdUB/wLmAd0B/wLsAeUB/wLxAewB/wL2AfIB/wL8 + AfkB/wNEAXkIAANVAbcCkwGkAf8CigGbAf8CigGbAf8CigGbAf8BMwEvATgB/wGbApMB/wGSAooB/wGS + AooB/wIAAZUB/wIlAfcB/wIlAfcB/wIlAfcB/wIlAfcB/wIlAfcB/wJUAWEB7gNVAbcCkwGkAf8CigGb + Af8CigGbAf8CigGbAf8BMwEvATgB/wGbApMB/wGSAooB/wE2AY8BlQH/AQABkwGlAf8BQAHmAfcB/wEA + AYMBlAH/ATIBhAGKAf8BkgKKAf8BkgKKAf8DUgGoA1UBtwKTAaQB/wKKAZsB/wKKAZsB/wKKAZsB/wEz + AS8BOAH/AZsCkwH/AZICigH/AZICigH/AQABkwEAAf8BGQHnAQgB/wEZAecBCAH/ARkB5wEIAf8BGQHn + AQgB/wEZAecBCAH/AVQBYQFUAe4IAANAAXEC8QHqAf8C7wHoAf8C8AHqAf8C8QHrAf8C8wHtAf8C9AHv + Af8C9QHxAf8C9wHyAf8C+AH0Af8C/AH4Af8DQAFxCAADVQGyAp0BrgH/ApUBpgH/ApUBpgH/ApUBpgH/ + AUUBQQGCAf8BpQKdAf8BnQKVAf8BnQKVAf8BCAEFAaEB/wIAAZ4B/wIAAaUB/wIAAaQB/wIAAaQB/wIA + AaQB/wJZAV0B1wNVAbICnQGuAf8ClQGmAf8ClQGmAf8ClQGmAf8BRQFBAYIB/wGlAp0B/wGdApUB/wGd + ApUB/wFAAZkBnwH/AQABjwGgAf8BQAHmAfcB/wEAAYQBlQH/ATsBiQGOAf8BnQKVAf8DTwGbA1UBsgKd + Aa4B/wKVAaYB/wKVAaYB/wKVAaYB/wFFAUEBggH/AaUCnQH/AZ0ClQH/AZ0ClQH/ARIBnAEFAf8BAAGW + AQAB/wEAAZ0BAAH/AS0B6wEcAf8BAAGcAQAB/wEAAZwBAAH/AVkBXQFZAdcIAAM+AWsC+wH1Af8C9gHx + Af8CzwHLAf8DVAH/AuIB3gH/AuIB3gH/A1QB/wLPAcsB/wL2AfEB/wL7AfUB/wM+AWsIAANEAXoBOgE2 + AT8B/wE6ATYBPwH/AToBNgE/Af8BOgE2AT8B/wEqASUBKgH/AT4CNgH/ATwBOwE2Af8BOgE/ATYB/wE6 + AT8BNgH/ASkBKwElAf8BOgE/ATYB/wE8ATsBNgH/AT4CNgH/AT4CNgH/A0ABcQNEAXoBOgE2AT8B/wE6 + ATYBPwH/AToBNgE/Af8BOgE2AT8B/wEqASUBKgH/AT4CNgH/ATwBOwE2Af8BOgE/ATYB/wE6AT8BNgH/ + AQ4BOAE5Af8BAAGOAZ0B/wFAAeYB9wH/ARUCEQH/AS0CJgH/A0ABcQNEAXoBOgE2AT8B/wE6ATYBPwH/ + AToBNgE/Af8BOgE2AT8B/wEqASUBKgH/AT4CNgH/ATwBOwE2Af8BOgE/ATYB/wE6AT8BNgH/ASkBKwEl + Af8BAAGbAQAB/wE8Ae4BKwH/AQABmQEAAf8BPgI2Af8DQAFxCAADPAFnAvoB8gH/AuIB2wH/A10B/wK9 + AbgB/wLzAewB/wLzAewB/wK9AbgB/wNdAf8C4gHbAf8C+gHyAf8DPAFnCAADTAGSAaMCmwH/AZoCkgH/ + AUMCOwH/AaMCmwH/AZoCkgH/AZoCkgH/AT8BRAE7Af8BmwGsAZsB/wGSAaMBkgH/AZIBowGSAf8BkgGj + AZIB/wE/AUQBOwH/AaMCmwH/AZoCkgH/A0wBkgNMAZIBowKbAf8BmgKSAf8BQwI7Af8BowKbAf8BmgKS + Af8BmgKSAf8BPwFEATsB/wGbAawBmwH/AZIBowGSAf8BkgGjAZIB/wE2AaMBnAH/ASsBLgEpAf8D9wH/ + ARkBFQE3Af8DUwGwA0wBkgGjApsB/wGaApIB/wFDAjsB/wGjApsB/wGaApIB/wGaApIB/wE/AUQBOwH/ + AZsBrAGbAf8BkgGjAZIB/wGSAaMBkgH/AQ4BpwECAf8BAAGgAQAB/wETAaIBBAH/AZoCkgH/A0wBkggA + AzwBZgL4Ae4B/wKvAaoB/wKgAZwB/wLwAeYB/wLwAeYB/wLwAeYB/wLwAeYB/wKgAZwB/wKvAaoB/wL4 + Ae4B/wM8AWYIAANLAY4BrwKnAf8BpwKfAf8BjQKGAf8BrwKnAf8BpwKfAf8BpwKfAf8BiQGOAYYB/wGn + AbgBpwH/AZ8BsAGfAf8BnwGwAZ8B/wGfAbABnwH/AYkBjgGGAf8BrwKnAf8BpwKfAf8DSwGOA0sBjgGv + AqcB/wGnAp8B/wGNAoYB/wGvAqcB/wGnAp8B/wGnAp8B/wGJAY4BhgH/AacBuAGnAf8BnwGwAZ8B/wGf + AbABnwH/AZ8BsAGfAf8BgwGHAYAB/wE5ATUBkwH/AoAC/wJaAWEB5ANLAY4BrwKnAf8BpwKfAf8BjQKG + Af8BrwKnAf8BpwKfAf8BpwKfAf8BiQGOAYYB/wGnAbgBpwH/AZ8BsAGfAf8BnwGwAZ8B/wGfAbABnwH/ + AYkBjgGGAf8BrwKnAf8BpwKfAf8DSwGOCAADPAFmAvYB6wH/At4B1AH/A3QB/wLCAbsB/wLtAeEB/wLt + AeEB/wLCAbsB/wN0Af8C3gHUAf8C9gHrAf8DPAFmCAADPwFuAYEBhgFEAf8BgQGGAUQB/wE1ATcBMQH/ + AYEBhgFEAf8BgwGCAUQB/wGFAkQB/wI2ATEB/wGBAYYBRAH/AYEBhgFEAf8BRgGGAYIB/wFEAoYB/wEz + ATYBNwH/AYEBRAGGAf8BgQFEAYYB/wM/AW4DPwFuAYEBhgFEAf8BgQGGAUQB/wE1ATcBMQH/AYEBhgFE + Af8BgwGCAUQB/wGFAkQB/wI2ATEB/wGBAYYBRAH/AYEBhgFEAf8BRgGGAYIB/wFEAoYB/wEzATYBNwH/ + AS0BKwGaAf8CAAHCAf8DSgGNAz8BbgGBAYYBRAH/AYEBhgFEAf8BNQE3ATEB/wGBAYYBRAH/AYMBggFE + Af8BhQJEAf8CNgExAf8BgQGGAUQB/wGBAYYBRAH/AUYBhgGCAf8BRAKGAf8BMwE2ATcB/wGBAUQBhgH/ + AYEBRAGGAf8DPwFuCAADPAFmAvUB5wH/AuoB3AH/AtEBxwH/A4YB/wLeAdIB/wLeAdIB/wOGAf8C0QHH + Af8C6gHcAf8C9QHnAf8DPAFmCAADTAGTAacBuAGnAf8BngGvAZ4B/wGeAa8BngH/AZ4BrwGeAf8BhQGK + AYEB/wGvAqcB/wGmAp4B/wGmAp4B/wGmAp4B/wGFAYEBigH/AqcBuAH/Ap4BrwH/Ap4BrwH/Ap4BrwH/ + A0wBkwNMAZMBpwG4AacB/wGeAa8BngH/AZ4BrwGeAf8BngGvAZ4B/wGFAYoBgQH/Aa8CpwH/AaYCngH/ + AaYCngH/AaYCngH/AYUBgQGKAf8CpwG4Af8CngGvAf8CngGvAf8CngGvAf8DTAGTA0wBkwGnAbgBpwH/ + AZ4BrwGeAf8BngGvAZ4B/wGeAa8BngH/AYUBigGBAf8BrwKnAf8BpgKeAf8BpgKeAf8BpgKeAf8BhQGB + AYoB/wKnAbgB/wKeAa8B/wKeAa8B/wKeAa8B/wNMAZMIAAM8AWYC9AHkAf8C6AHYAf8C6AHYAf8C6AHY + Af8C6AHYAf8C6AHYAf8C6AHYAf8C6AHYAf8C6AHYAf8C9AHkAf8DPAFmCAADSgGMAbMBxAGzAf8BqgG7 + AaoB/wGqAbsBqgH/AaoBuwGqAf8BlQGZAZEB/wG7ArMB/wGyAqoB/wGyAqoB/wGyAqoB/wGVAZEBmQH/ + ArMBxAH/AqoBuwH/AqoBuwH/AqoBuwH/A0oBjANKAYwBswHEAbMB/wGqAbsBqgH/AaoBuwGqAf8BqgG7 + AaoB/wGVAZkBkQH/AbsCswH/AbICqgH/AbICqgH/AbICqgH/AZUBkQGZAf8CswHEAf8CqgG7Af8CqgG7 + Af8CqgG7Af8DSgGMA0oBjAGzAcQBswH/AaoBuwGqAf8BqgG7AaoB/wGqAbsBqgH/AZUBmQGRAf8BuwKz + Af8BsgKqAf8BsgKqAf8BsgKqAf8BlQGRAZkB/wKzAcQB/wKqAbsB/wKqAbsB/wKqAbsB/wNKAYwIAAM8 + AWYC8wHjAf8C5gHWAf8C5gHWAf8C5gHWAf8C5gHWAf8C5gHWAf8C5gHWAf8C5gHWAf8C5gHWAf8C8wHj + Af8DPAFmCAADOwFjAYwBkAGIAf8BjAGQAYgB/wNHAYMDSAGGA00BlgNGAYABkAKIAf8BkAKIAf8DRgGA + A00BlgNIAYYDRwGDAYwBiAGQAf8BjAGIAZAB/wM7AWMDOwFjAYwBkAGIAf8BjAGQAYgB/wNHAYMDSAGG + A00BlgNGAYABkAKIAf8BkAKIAf8DRgGAA00BlgNIAYYDRwGDAYwBiAGQAf8BjAGIAZAB/wM7AWMDOwFj + AYwBkAGIAf8BjAGQAYgB/wNHAYMDSAGGA00BlgNGAYABkAKIAf8BkAKIAf8DRgGAA00BlgNIAYYDRwGD + AYwBiAGQAf8BjAGIAZAB/wM7AWMIAAM8AWYC8gHhAf8C5QHUAf8C5QHUAf8C5QHUAf8C5QHUAf8C5QHU + Af8C5QHUAf8C5QHUAf8C5QHUAf8C8gHhAf8DPAFmCAADRQF9AbkCsQH/AbACqAH/A0UBfQgAA0UBfQG5 + ArEB/wGwAqgB/wNFAX0IAANFAX0BuQKxAf8BsAKoAf8DRQF9A0UBfQG5ArEB/wGwAqgB/wNFAX0IAANF + AX0BuQKxAf8BsAKoAf8DRQF9CAADRQF9AbkCsQH/AbACqAH/A0UBfQNFAX0BuQKxAf8BsAKoAf8DRQF9 + CAADRQF9AbkCsQH/AbACqAH/A0UBfQgAA0UBfQG5ArEB/wGwAqgB/wNFAX0IAAM8AWYC9AHlAf8C6AHZ + Af8C6AHZAf8C6AHZAf8C6AHZAf8C6AHZAf8C6AHZAf8C6AHZAf8C6AHZAf8C9AHlAf8DPAFmCAADRAF7 + AcMCuwH/AboCsgH/A0QBewgAA0QBewHDArsB/wG6ArIB/wNEAXsIAANEAXsBwwK7Af8BugKyAf8DRAF7 + A0QBewHDArsB/wG6ArIB/wNEAXsIAANEAXsBwwK7Af8BugKyAf8DRAF7CAADRAF7AcMCuwH/AboCsgH/ + A0QBewNEAXsBwwK7Af8BugKyAf8DRAF7CAADRAF7AcMCuwH/AboCsgH/A0QBewgAA0QBewHDArsB/wG6 + ArIB/wNEAXsIAAM8AWYC/AHzAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHrAf8C8wHr + Af8C8wHrAf8C+gHxAf8DUQGgAxoBJAQAAzcBWwNEAXkDRAF5AzcBWwgAAzcBWwNEAXkDRAF5AzcBWwgA + AzcBWwNEAXkDRAF5AzcBWwM3AVsDRAF5A0QBeQM3AVsIAAM3AVsDRAF5A0QBeQM3AVsIAAM3AVsDRAF5 + A0QBeQM3AVsDNwFbA0QBeQNEAXkDNwFbCAADNwFbA0QBeQNEAXkDNwFbCAADNwFbA0QBeQNEAXkDNwFb + CAADJgE5A1cBswL+Af0B/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9AfwB/wL9 + AfwB/wKeAZ0B7ANEAXoDFgEfzAADJgE5AzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFm + AzwBZgM8AWYDEwEaLAADTgGZAVkBXAFZAcwDTgGZCAADDQESAx8BLANBAXIDSAGHA0gBhwNIAYcDSAGH + A0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0EBcgMfASwDDQESCAADDQESAx8BLANBAXIDSAGHA0gBhwNI + AYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0EBcgMNARIDHwEsA0EBcgNIAYcDSAGHA0gBhwNI + AYcDSAGHA0gBhwNIAYcDSAGHA0gBhwFeAlsB0ANQAZ4DHwEsAw0BEgMEAQYDEAEWAxMBGgMTARoDEwEa + AxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAVgBXAFYAdEBAAHfAQAB/wFYAVwBWAHRAxABFgMEAQYDBwEJ + AxABFgNHAYIO/wH+Af8C/gH9Af8C/gH8Af8C/QH7Af8C/QH6Af8C/AH4Af8C/gH5Af8DRwGCAxABFgMH + AQkIAAMHAQkDEAEWA0cBgg7/Af4B/wL+Af0B/wL+AfwB/wL9AfsB/wL9AfoB/wL8AfgB/wL+AfkB/wNH + AYIDBwEJAxABFgNHAYIO/wH+Af8C/gH9Af8C/gH8Af8C/QH7Af8C/QH6Af8C/AH4Af8BuAIAAf8BYQFZ + AVgB5gFAAj8BbgMHAQkDPAFoA0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNIAYcBWwFeAVsB0AFc + AWQBXAHnAVwBZAFcAecBAAHiAQAB/wFcAWQBXAHnAVwBZAFcAecBVQFWAVUBsQgAA0QBewj/A/4B/wL9 + AfwB/wL9AfsB/wL8AfkB/wIAAbIB/wIAAZcB/wIAAZcB/wIAAZgB/wJeAWUB5QJZAVwBzANOAZkQAANE + AXsI/wP+Af8C/QH8Af8C/QH7Af8C/AH5Af8C+wH4Af8C+gH2Af8C+AH0Af8C+wH2Af8DRAF7CAADRAF7 + CP8D/gH/Av0B/AH/Av0B+wH/AdIBpQEAAf8BwwGHAQAB/wHDAYcBAAH/AcIBhgEAAf8BwwGHAQAC/wHF + AQAB/wJcAVkBzAM4AVwDRQF/A8oB/wPFAf8DxQH/A8UB/wPFAf8DxQH/A8UB/wPFAf8BAAGfAQAB/wEA + AecBAAH/AQAB5wEAAf8BAAHnAQAB/wEAAecBAAH/AQAB5wEAAf8BWAFhAVgB5ggAA0MBdwT/A/4B/wL9 + AfwB/wL9AfsB/wL8AfkB/wL7AfgB/wIAAasB/wIAAfcB/wIAAfcB/wIAAfcB/wIAAfcB/wIAAfcB/wJZ + AVwBzBAAA0MBdwT/A6sB/wNGAf8CqwGpAf8CRgFFAf8CqQGmAf8C+gH2Af8C+AH0Af8C9wHyAf8C+wH1 + Af8DQwF3CAADQwF3BP8D/gH/Av0B/AH/Av0B+wH/AvwB+QH/Ac4BkwEAAv8B4wGSAv8B1QEAAv8B0QEA + Av8B0QEAAv8B0QEAAv8B2AEAAf8CXAFZAcwDQwF4A8gB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA + Af8BAAGDAQAB/wEAAY8BAAH/AQABjwEAAf8BAAHrAQAB/wEAAZEBAAH/AQABpgEAAf8BWQFcAVkByQgA + A0IBdgL/Af4B/wL9AfwB/wL9AfsB/wL8AfkB/wL7AfgB/wL6AfYB/wIAAcUB/wIAAbYB/wIAAbYB/wIA + AbcB/wJaAWEB5AJZAVwBzANOAZkQAANCAXYC/wH+Af8C/QH8Af8C/QH7Af8CSwFKAf8C+wH4Af8C+gH2 + Af8C+AH0Af8C9wHyAf8C9gHwAf8C+gHzAf8DQgF2CAADQgF2Av8B/gH/Av0B/AH/Av0B+wH/AvwB+QH/ + AvsB+AH/AeEBtAEAAf8B2QGdAQAB/wHZAZ0BAAH/AdkBnQEAAf8B2gGeAQAC/wHlAZcB/wJcAVkBzAM4 + AVwDQgF2A8sB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wEAAZcBAAH/AQAB7gEA + Af8BAAGUAQAB/wPLAf8DQgF2CAADQgF0Av4B/QH/Av0B+wH/AvwB+QH/AvsB+AH/AvoB9gH/AvgB9AH/ + AvcB8gH/AvYB8AH/AvUB7gH/AvoB8gH/A0IBdAgAAzEBTgM9AWcDPQFnAz0BZwNKAYoDyQH/AskByAH/ + A8gB/wNTAf8CyAHHAf8C0wHRAf8C9wHyAf8C9gHwAf8C9QHuAf8C+gHyAf8DQgF0CAADQgF0Av4B/QH/ + Av0B+wH/AvwB+QH/AvsB+AH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AeUBqQEAAf8CXwFY + AeMDOAFcBAADQgF0A84B/wMAAf8DAAH/AwAB/wMAAf8DAAH/AbsB3QEAAf8DAAH/AwAB/wMAAf8BAAGJ + AQAB/wEAAZoBAAH/AQABhAEAAf8DzgH/A0IBdAgAA0EBcgL+AfwB/wL8AfkB/wL7AfgB/wL6AfYB/wL4 + AfQB/wL3AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wL5Ae8B/wNBAXIIAAM9AWkD+gH/A/oB/wP6Af8D+gH/ + A/oB/wP6Af8D+gH/A1wB/wP6Af8CwgHAAf8C9gHwAf8C9QHuAf8C9AHsAf8C+QHvAf8DQQFyCAADQQFy + Av4B/AH/AvwB+QH/AvsB+AH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/Ae0BwAGE + Af8CUwFPAaUIAANBAXID0gH/AQABhAEAAf8BoAG5AQAB/wGEAZUBAAH/AbsB3QEAAf8BuwHdAQAB/wMA + Af8BuwHdAQAB/wMAAf8BowG6AQAB/wHMAeYBgAH/Ae4B9wGzAf8DAAH/A9IB/wNBAXIIAANAAXEC/QH7 + Af8C+wH4Af8C+gH2Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C8QHnAf8C9wHqAf8DQAFx + CAADPgFrA/EB/wHpAYMBUAH/AcgBUwExAf8BrQE3ARUB/wG4ATgBFgH/AdoBSgEoAf8D8QH/A2QB/wPx + Af8CuwG5Af8C9QHuAf8C9AHsAf8C8QHnAf8C9wHqAf8DQAFxCAADQAFxAv0B+wH/AvsB+AH/AvoB9gH/ + AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/AvcB6gH/A0ABcQgAA0ABcAPWAf8DAAH/ + AwAB/wGOAZ8BAAH/AwAB/wG7Ad0BAAH/AwAB/wMAAf8BuwHdAQAB/wGRAZwBAAH/AwAB/wMAAf8DAAH/ + A9YB/wNAAXAIAANAAW8C/QH6Af8C+gH2Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C8QHn + Af8C7AHfAf8C9AHlAf8DQAFvCAADPwFtA+cB/wHpAYMBUAH/AcgBUwExAf8BrQE3ARUB/wG4ATgBFgH/ + AdoBSgEoAf8D5wH/A2wB/wPnAf8CsgGwAf8C9AHsAf8C8QHnAf8C7AHfAf8C9AHlAf8DQAFvCAADQAFv + Av0B+gH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AvQB5QH/ + A0ABbwgAA0ABbgPaAf8DAAH/AwAB/wMAAf8DAAH/AbsB3QEAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA + Af8DAAH/A9oB/wNAAW4IAAM/AW0C/AH4Af8C+AH0Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C8QHn + Af8C7AHfAf8C6AHZAf8C8wHiAf8DPwFtCAADQAFwA98B/wPfAf8D3wH/A98B/wPfAf8D3wH/A98B/wOG + Af8D3wH/AqcBpQH/AvEB5wH/AuwB3wH/AugB2QH/AvMB4gH/Az8BbQgAAz8BbQL8AfgB/wL4AfQB/wL3 + AfIB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLzAeIB/wM/AW0IAAM/AWwD3gH/ + AwAB/wMAAf8DAAH/AwAB/wGmAb8BAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wPeAf8DPwFs + CAADPwFsAvwB9wH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/AuYB1QH/ + AvIB4QH/Az8BbAgAAzYBWQNDAXcDQwF3A0MBdwNMAZMCjQGMAf8CjAGLAf8CjAGKAf8CigGIAf8CiwGJ + Af8CpQGfAf8C7AHfAf8C6AHZAf8C5gHVAf8C8gHhAf8DPwFsCAADPwFsAvwB9wH/AvcB8gH/AvYB8AH/ + AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/AuYB1QH/AvIB4QH/Az8BbAgAAz4BagPhAf8DAAH/ + AwAB/wMAAf8DAAH/AZMBpAEAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/A+EB/wM+AWoIAAM+ + AWsC+wH2Af8C9gHwAf8C9QHuAf8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZAf8C5gHVAf8C5QHUAf8C8gHh + Af8DPgFrGAADPgFrAvsB9gH/AvYB8AH/AvUB7gH/Ao0BiAH/AvEB5wH/AuwB3wH/AugB2QH/AuYB1QH/ + AuUB1AH/AvIB4QH/Az4BawgAAz4BawL7AfYB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLo + AdkB/wLmAdUB/wLlAdQB/wLyAeEB/wM+AWsIAAM9AWkD5AH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ + AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/A+QB/wM9AWkIAAM9AWkC+gH0Af8C9QHuAf8C9AHsAf8C8QHn + Af8C7AHfAf8C6AHZAf8C5gHVAf8CpAGTAf8CpAGTAf8CpAGTAf8CRQFEAXwYAAM9AWkC+gH0Af8CwwG+ + Af8CkQGNAf8CwAG4Af8CjQGFAf8CuQGtAf8C5gHVAf8CpAGTAf8CpAGTAf8CpAGTAf8CRQFEAXwIAAM9 + AWkC+gH0Af8C9QHuAf8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZAf8C5gHVAf8CpAGTAf8CpAGTAf8CpAGT + Af8CRQFEAXwIAAM9AWgD6gH/A+UB/wPlAf8D5QH/A+UB/wPlAf8D5QH/A+UB/wPlAf8D5QH/A+UB/wPl + Af8D5QH/A+oB/wM9AWgIAAM9AWgC+gHzAf8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZAf8C5gHVAf8C5QHU + Af8CtgGlBf8DPQFoAxoBJRgAAz0BaAL6AfMB/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLmAdUB/wLl + AdQB/wK2AaUF/wM9AWgDGgElCAADPQFoAvoB8wH/AvQB7AH/AvEB5wH/AuwB3wH/AugB2QH/AuYB1QH/ + AuUB1AH/ArYBpQX/Az0BaAMaASUIAAMxAU0DPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8 + AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgMxAU0IAAM9AWcC/AH1Af8C+QHvAf8C9gHqAf8C9AHlAf8C8wHi + Af8C8gHhAf8C8gHhAf8CwgGxAf8DPQFnAxoBJRwAAz0BZwL8AfUB/wL5Ae8B/wL2AeoB/wL0AeUB/wLz + AeIB/wLyAeEB/wLyAeEB/wLCAbEB/wM9AWcDGgElDAADPQFnAvwB9QH/AvkB7wH/AvYB6gH/AvQB5QH/ + AvMB4gH/AvIB4QH/AvIB4QH/AsIBsQH/Az0BZwMaASVUAAMxAU0DPAFmAzwBZgM8AWYDPAFmAzwBZgM8 + AWYDPAFmAzwBZgMaASQgAAMxAU0DPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgMaASQQAAMx + AU0DPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgMaASRQAAMLAQ8DEgEYAxIBGQMSARgDEAEV + Aw0BEgMLAQ8DCgEOAwoBDgMMARADDQESAxABFQMSARgDEwEaAxIBGAMLAQ8DCwEPAxIBGAMSARkDEgEY + AxABFQMNARIDCwEPAwoBDgMKAQ4DDAEQAw0BEgMQARUDEgEYAxMBGgMSARgDCwEPSwAEAQECAwMBBAMF + BAcECgENAwwBEAMOARMDEAEVAxEBFwMSARkDEwEaAxABFQMHAQoDFgEeAyEBMANKAY0DTwGlAx0BKQMZ + ASMDFQEdAxQBGwMUARsDFgEfAxoBJAMdASoDSgGMA1IBpgMhATADFgEeAxYBHgMhATADSgGNA08BpQMd + ASkDGQEjAxUBHQMUARsDFAEbAxYBHwMaASQDHQEqA0oBjANSAaYDIQEwAxYBHgMEAQYDEAEWAxMBGgMT + ARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxMBGgMTARoDEwEaAxABFgMEAQYLAAEBAwMBBAMG + AQgDCgQOARMDEgEZAxYBHwMaASUDJAE1AzwBaANDAXgDPAFoAyQBNQMOARMDBgEIAwkBDANUAasDWQHM + AwgBCwMHAQkDBgEIAwUBBwMFAQcDBgEIAwcBCQMIAQsDVAGrA1kBzAMJAQwDBgEIAwYBCAMJAQwDVAGr + A1kBzAMIAQsDBwEJAwYBCAMFAQcDBQEHAwYBCAMHAQkDCAELA1QBqwNZAcwDCQEMAwYBCAM8AWgDSAGH + A0gBhwNIAYcDSAGHA0gBhwNIAYcDSAGHA0gBhwNbAdACXAFkAecCXAFkAecCXAFkAecCXAFkAecCXAFk + AecCVQFWAbEoAAM5AWADZQG/A+QB/wNlAb8DOQFgCAADSgGLA1YBswNZAckCWQFcAckCWQFdAdIBWwJe + AdkBWAJeAd0BXAJhAdwBWgFdAV4B2AJYAVwB0QNbAcgDVgG5A1kBxANKAYsIAANKAYsDVgGzA1kByQJZ + AVwByQJZAV0B0gFbAl4B2QFYAl4B3QFcAmEB3AFaAV0BXgHYAlgBXAHRA1sByANWAbkDWQHEA0oBiwQA + A0UBfwPKAf8DxQH/A8UB/wPFAf8DxQH/A8UB/wPFAf8DxQH/AgABoQH/AgAB9wH/AgAB9wH/AgAB9wH/ + AgAB9wH/AgAB9wH/AlgBYQHmHAADMAFNAzwBZgM8AWYDQQFzA/IB/wPyAf8D8gH/A0EBcwgAA1YBswGM + AaQBvwH/AY8BpwHCAf8BlQGsAcgB/wGaAbEBzQH/AZ8BtQHSAf8BogG3AdUB/wGiAbcB1QH/AZ4BtAHR + Af8BmgGwAc0B/wGUAawBxwH/AY8BpwHCAf8BjAGlAb8B/wNWAbMIAANWAbMBjAGkAb8B/wGPAacBwgH/ + AZUBrAHIAf8BmgGxAc0B/wGfAbUB0gH/AaIBtwHVAf8BogG3AdUB/wGeAbQB0QH/AZoBsAHNAf8BlAGs + AccB/wGPAacBwgH/AYwBpQG/Af8DVgGzBAADQwF4A8gB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMA + Af8CAAGJAf8CAAGXAf8CAAGXAf8CAAGXAf8CAAGYAf8CAAGuAf8CWQFcAckcAAM8AWYIAAM4AVwDaAG8 + A/0B/wNoAbwDOAFcCAACVAFWAasBkwGrAcYB/wEAAYoBpAH/AQABgwGdAf8BAAGIAaIB/wEAAY0BpwH/ + AQABkAGqAf8BAAGQAaoB/wEAAY0BpwH/AQABiQGjAf8BAAGEAZ4B/wEAAYoBpAH/AZMBqwHGAf8CVAFW + AasIAAJUAVYBqwGTAasBxgH/AQABigGkAf8BAAGDAZ0B/wEAAYgBogH/AQABjQGnAf8BAAGQAaoB/wEA + AZABqgH/AQABjQGnAf8BAAGJAaMB/wEAAYQBngH/AQABigGkAf8BkwGrAcYB/wJUAVYBqwQAA0IBdgPL + Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DywH/A0IBdhwA + AzwBZggAAw0BEgM3AVoDQAFuAzcBWgMNARIIAANRAaIBnAGzAc8B/wEAAYABmgH/AZQBrQHHAf8BlAGt + AccB/wGUAa0BxwH/AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/AZQBrQHHAf8BlAGtAccB/wEAAYABmgH/ + AZwBswHPAf8DUQGiCAADUQGiAZwBswHPAf8BAAGAAZoB/wGUAa0BxwH/AZQBrQHHAf8BlAGtAccB/wGU + Aa0BxwH/AZQBrQHHAf8BlAGtAccB/wGUAa0BxwH/AZQBrQHHAf8BAAGAAZoB/wGcAbMBzwH/A1EBogQA + A0IBdAPOAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wG7Ad0BAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ + A84B/wNCAXQcAAM8AWYgAAMUARsCVAFWAasBpAG7AdcB/wEAAYABmgH/AacBwAHaAf8BqgHBAd0B/wGt + AcMB4AH/Aa8BxAHiAf8BrwHEAeIB/wGtAcMB4AH/AaoBwgHdAf8BqAHAAdsB/wEAAYABmgH/AaQBuwHX + Af8CVAFWAasDFAEbAxQBGwJUAVYBqwGkAbsB1wH/AQABgAGaAf8BpwHAAdoB/wGqAcEB3QH/Aa0BwwHg + Af8BrwHEAeIB/wGvAcQB4gH/Aa0BwwHgAf8BqgHCAd0B/wGoAcAB2wH/AQABgAGaAf8BpAG7AdcB/wJU + AVYBqwMUARsDQQFyA9IB/wEAAYQBAAH/AaABuQEAAf8BhAGVAQAB/wG7Ad0BAAH/AbsB3QEAAf8DAAH/ + AbsB3QEAAf8DAAH/AaMBugEAAf8BzAHmAYAB/wHuAfcBswH/AwAB/wPSAf8DQQFyHAADPAFmIAADMwFS + A14B0AGrAcEB3gH/AwAB/wEAAYYBoAH/AQABhgGgAf8BAAGGAaAB/wIAAY8B/wIAAY8B/wEAAYYBoAH/ + AQABhgGgAf8BAAGGAaAB/wMAAf8BqwHBAd4B/wNeAdADMwFSAzMBUgNeAdABqwHBAd4B/wMAAf8BAAGG + AaAB/wEAAYYBoAH/AQABhgGgAf8CAAGPAf8CAAGPAf8BAAGGAaAB/wEAAYYBoAH/AQABhgGgAf8DAAH/ + AasBwQHeAf8DXgHQAzMBUgNAAXAD1gH/AwAB/wMAAf8BjgGfAQAB/wMAAf8BuwHdAQAB/wMAAf8DAAH/ + AbsB3QEAAf8BkQGcAQAB/wMAAf8DAAH/AwAB/wPWAf8DQAFwAx0BKQGDAVsBUgHQAdoBWAE2Af8BgwFb + AVIB0AMdASkIAAM8AWYIAAMPARQDOgFhA0IBdwM6AWEDDwEUBAADSAGGAasBwgHeAf8BsAHFAeMB/wIA + AYwB/wEAAZQBrgH/AQABlAGuAf8BAAGUAa4B/wEAAYMBnQH/AQABgwGdAf8BAAGUAa4B/wEAAZQBrgH/ + AQABlAGuAf8BgAIAAf8BqgGcAZUB/wGrAcIB3gH/A0gBhgNIAYYBqwHCAd4B/wGwAcUB4wH/AgABjAH/ + AQABlAGuAf8BAAGUAa4B/wEAAZQBrgH/AQABgwGdAf8BAAGDAZ0B/wEAAZQBrgH/AQABlAGuAf8BAAGU + Aa4B/wIAAYwB/wGwAcUB4wH/AasBwgHeAf8DSAGGA0ABbgPaAf8DAAH/AwAB/wMAAf8DAAH/AbsB3QEA + Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/A9oB/wNAAW4BeAFWAUwB0AHUAYkBbgH/AegBvwGy + Af8B1AGJAW4B/wF4AVYBTAHQCAADPAFmCAADOAFeA2UBvQPkAf8DZQG9AzgBXgQAAkUBRgF/Aa4BxQHh + Af8BjwGmAcIB/wEAAYMBnQH/AY0BpgG/Af8BjQGmAb8B/wGNAaYBvwH/AQABlQGuAf8BAAGVAa4B/wGN + AaYBvwH/AY0BpgG/Af8BjQGmAb8B/wGbAgAB/wGiAgAB/wGsAaABlgH/AkUBRgF/AkUBRgF/Aa4BxQHh + Af8BjwGmAcIB/wEAAYMBnQH/AY0BpgG/Af8BjQGmAb8B/wGNAaYBvwH/AQABlQGuAf8BAAGVAa4B/wGN + AaYBvwH/AY0BpgG/Af8BjQGmAb8B/wEAAYMBnQH/AY8BpgHCAf8BrgHFAeEB/wJFAUYBfwM/AWwD3gH/ + AwAB/wMAAf8DAAH/AwAB/wGmAb8BAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wPeAf8DPwFs + Aa0BRQEjAf8B8AHHAboB/wHwAccBugH/AfABxwG6Af8BrQFFASMB/wM8AWYDPAFmAzwBZgM8AWYDPAFm + A0ABbwPyAf8D8gH/A/IB/wNAAW8EAAMoAT0DRAF5Ak0BTgGWAQABlQGvAf8BngG3AdEB/wGeAbcB0QH/ AZ4BtwHRAf8BjQGmAcAB/wGiAgAB/wGwAgAB/wGwAgAB/wGwAgAB/wGpAgAC/wHFAQAB/wJhAVoB5AJI AUcBgwMoAT0DRAF5Ak0BTgGWAQABlQGvAf8BngG3AdEB/wGeAbcB0QH/AZ4BtwHRAf8BjQGmAcAB/wGN AaYBwAH/AgABoQH/AgABkAH/AgABkAH/AgABiQH/AlUBXAHqAloBYQHkA1UBsgM+AWoD4QH/AwAB/wMA - Af8DAAH/AwAB/wGTAaQBAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wPhAf8DPgFqGAACWQFc - AcwDIwEzBAACUQFSAacCVwFfAegCAAH+Af8CVwFfAegCUQFSAacQAAJLAUwBjwGNAaYBwAH/Aa4BxwHh - Af8BrgHHAeEB/wGuAccB4QH/AZ4BtwHRAf8BvAGGAQAC/wHjAZIC/wHVAQAC/wHRAQAC/wHRAQAC/wHR - AQAC/wHYAQAB/wJcAVkBzAgAAksBTAGPAY0BpgHAAf8BrgHHAeEB/wGuAccB4QH/Aa4BxwHhAf8BngG3 - AdEB/wGeAbcB0QH/AgABpgH/AgAB9wH/AgAB9wH/AgAB9wH/AgAB9wH/AgAB9wH/AlkBXAHMAz0BaQPk - Af8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8D5AH/Az0BaSQA - AxgBIQJSAVQBpgJZAVwBzAJSAVQBpgMYASEQAANEAXsDXQHwAawBxQHfAf8BuQHSAewB/wG5AdIB7AH/ - AasBxAHeAf8BvwGcAQAB/wHNAZYBAAH/Ac0BlgEAAf8BygGTAQAB/wMrAfwB/wHlAZcB/wJcAVkBzAM4 - AVwIAANEAXsDXQHwAawBxQHfAf8BuQHSAewB/wG5AdIB7AH/AasBxAHeAf8BqwHEAd4B/wIAAcMB/wIA - AbUB/wIAAbMB/wMrAfwCXgFlAeUCWQFcAcwDTgGZAz0BaAPqAf8D5QH/A+UB/wPlAf8D5QH/A+UB/wPl - Af8D5QH/A+UB/wPlAf8D5QH/A+UB/wPlAf8D6gH/Az0BaEgAAy4BSANSAakDYQHuAagBwQHbAf8BqAHB - AdsB/wGoAcEB2wH/AagBwQHbAf8BqAHBAdsB/wGoAcEB2wH/A2EB7gJhAVQB7gJfAVoB2wM4AVwMAAMu - AUgDUgGpA2EB7gGoAcEB2wH/AagBwQHbAf8BqAHBAdsB/wGoAcEB2wH/AagBwQHbAf8BqAHBAdsB/wNh - Ae4DUgGpAy4BSAgAAzEBTQM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFm - AzwBZgM8AWYDPAFmAzEBTUgAAwUBBwMtAUUCPwFAAW4DRAF5A0QBeQNEAXkDRAF5A0QBeQNEAXkCPwFA - AW4DVQGyAzgBXhAAAwUBBwMtAUUCPwFAAW4DRAF5A0QBeQNEAXkDRAF5A0QBeQNEAXkCPwFAAW4DLQFF - AwUBB0sAAQEDAgEDAwQBBgMHBAoBDgMNARIDEAEWAxIBGAMTARoDEwEaAxMBGgMSARgDDgETAwkBDAME - AQYDAAEBAxYBHwJRAU8BnAJYAVYBwQJYAVYBwQJYAVYBwQJYAVYBwQJYAVYBwQJYAVYBwQJYAVYBwQJY - AVYBwQJRAU8BnAMYASIQAAM9AWoDSAGFA0gBhQNIAYUDSAGFA0gBhQNIAYUDSAGFA0gBhQNIAYUDSAGF - A0gBhQNIAYUDQAFwAx0BKgMSARgDDQESAx8BLANBAXIDSAGHA0gBhwNIAYcDSAGHAwAB/wNaAdgDUAGk - A0gBhwNIAYcDSAGHA0EBcgMfASwDDQESAwABAQMEAQYDCQEMAw8EFAEcAxkBIwMeASsDIQEwAyMBMwMj - ATMDIwEzA0MBeAMzAVIDEgEYAwgBCwMBAQIDDAEQA1MBqgH9AfQB4QH/AfsB8gHcAf8B+gHxAdwB/wH6 - AfAB2wH/AfkB8AHaAf8B+QHvAdkB/wH5Ae4B2AH/AfwB8gHfAf8DVgGzAx4BKwMTARoDDQERCAADRAF7 - A+sB/wPnAf8D5wH/A+cB/wPnAf8D5wH/A+cB/wPnAf8D5wH/A+cB/wPnAf8D6wH/A0QBewMQARUDCQEM - AwcBCQMQARYDRwGCDv8B/gH/AYABtgHHAf8B2QH0Av8BAAGfAa8B/wG7AdkB3QH/AvwB+AH/Av4B+QH/ - A0cBggMQARYDBwEJLAACTAFLAY8CTAFLAY8DKgFBDAACTwFOAZcB+wHyAdwB/wH1AewB0gH/AfUB6wHR - Af8B9AHqAdAB/wHzAegBzgH/AfIB5gHMAf8B8QHkAcoB/wH4Ae0B1wH/AmEBWAHmAlgBVgHBAlEBTwGc - AxgBIggAA0IBdgPqAf8D4gH/A+IB/wPiAf8D4gH/A+IB/wPiAf8D4gH/A+IB/wPiAf8D4gH/A+oB/wNC - AXYQAANEAXsI/wP+Af8C/QH8Af8B1wHpAe4B/wEAAbUBxQH/AQAB5gH3Af8BAAGdAa0B/wG2AdYB2AH/ - AvsB9gH/A0QBewgAA04BmQFcAlkByQFWAlUBtANIAYYDIwEzCAADGgEkAzgBXQJGAUUBfgNKAY0CTAFL - AY8DVgGzAkwBSwGPAyoBQQgAAkwBSwGQAfoB8QHcAf8B9QHrAdEB/wH0AeoB0AH/AfMB6AHOAf8B8gHm - AcwB/wHxAeQBygH/AfAB4gHIAf8B9wHrAdYB/wHOAasBggH/AfwB8gHfAf8DVgGzAxMBGgMTARoDDQER - A0EBcwPtAv8BmQEAAf8D5gH/A70B/wOsAf8DvQH/A70B/wOsAf8DvQH/A8kB/wPmAf8D7QH/A0EBcxAA - A0MBdwT/A/4B/wL9AfwB/wL9AfsB/wL8AfkB/wG+AeQB6AH/AQABtAHEAf8BAAHmAfcB/wEAAZ0BrAH/ - AboB2QHaAf8DQwF3CAABXAJZAcwDKwH8AlkBQgH1AmUBXgHlAVwBWgFZAc8CQAE/AW8DMQFPA0wBkgJS - AVEBoQJWAVQBqwJWAVUBsQNWAbMDVgGzA1YBswJMAUsBjwMjATMEAANKAYoB+gHwAdsB/wH0AeoB0AH/ - AfMB6AHOAf8B8gHmAcwB/wHxAeQBygH/AfAB4gHIAf8B7wHgAcYB/wH3AeoB1QH/Ac0BqgEAAf8B+AHt - AdcB/wJhAVgB5gJYAVYBwQJRAU8BnAMYASIDQAFxA/AB/wPrAf8D6wH/A+sB/wPrAf8D6wH/A+sB/wPr - Af8D6wH/A+sB/wPrAf8D8AH/A0ABcRAAA0IBdgL/Af4B/wL9AfwB/wL9AfsB/wL8AfkB/wL7AfgB/wL6 - AfYB/wG8AeIB5QH/AQABtAHDAf8BAAHmAfcB/wEAAZ4BrAH/A04BmQgAAVwCWQHMAfkBwgEAAv8BtAEA - Av8BswEAAf8CTQEpAfoCYQFdAeICWQFXAcIDVAGvA1YBswNWAbMDVgGzA1YBswNWAbMDVgGzAkwBSwGP - AyMBMwQAA0gBhAH5AfAB2gH/AfMB6AHOAf8B8gHmAcwB/wHxAeQBygH/AfAB4gHIAf8B7wHgAcYB/wHu - Ad0BwwH/AfYB5wHSAf8B0AGsAYIB/wH3AesB1gH/Ac4BqwGCAf8B/AHyAd8B/wNTAaoEAANAAW4D8wH/ - AgABwgH/A+8B/wO8Af8DxQH/A8UB/wPFAf8DvAH/A8UB/wO8Af8DxQH/A/MB/wNAAW4QAANCAXQC/gH9 - Af8C/QH7Af8C/AH5Af8C+wH4Af8C+gH2Af8C+AH0Af8C9wHyAf8BuwHhAeIB/wEAAbMBwgH/AQAB5gH3 - Af8DVgG4AyABLgQAA04BmQJdAVkB0gJfAVgB4wKoAUAB/QH8AbABAAH/AysB/AJiAVgB7wJbAVkBwwNV - AbICUQFQAZ8DTAGTAkwBSwGPA1YBswJMAUsBjwMqAUEIAAJGAUUBfgH5Ae8B2QH/AfIB5gHMAf8B8QHk - AcoB/wHwAeIByAH/Ae8B4AHGAf8B7gHdAcMB/wHqAdcBvQH/AfQB5AHOAf8B0gGuAYQB/wH3AeoB1QH/ - Ac0BqgEAAf8B+AHtAdcB/wJPAU4BlwQAAz8BbAP3Af8D9AH/A/QB/wP0Af8D9AH/A/QB/wP0Af8D9AH/ - A/QB/wP0Af8D9AH/A/cB/wM/AWwQAANBAXIC/gH8Af8C/AH5Af8C+wH4Af8C+gH2Af8C+AH0Af8C9wHy - Af8C9gHwAf8C9QHuAf8BuQLfAf8CrwGqAf8D9wH/A0sBjgMtAUYDBAEGAyIBMgJOAU0BlgJeAVoB2AJ/ - ATAB/gHuAagBAAH/AmoBQQH5AmQBXAHnA1ABmgM9AWkDGAEhAkwBSwGPAkwBSwGPAyoBQQwAA0MBeAH5 - Ae4B2AH/AfEB5AHKAf8B8AHiAcgB/wHvAeABxgH/Ae4B3QHDAf8B6gHXAb0B/wHnAdABtgH/AfIB4gHM - Af8B1AGwAYUB/wH2AecB0gH/AdABrAGCAf8B9wHrAdYB/wJMAUsBkAQAAz4BagP6Af8BAAGqAQAB/wP4 - Af8DuwH/A8wB/wPUAf8D2gH/A/gB/wP4Af8D+AH/A/gB/wP6Af8DPgFqEAADQAFxAv0B+wH/AvsB+AH/ - AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/At4B1AH/A1YBtgKAAv8CVgFY - AcEIAAMCAQMDVQG1AmQBUwHxAecBrgEAAf8B4QGlAQAB/wJkAVMB8QNVAbUDAgEDBAADNQFXA0QBehAA - AkIBQQFzAfgB7QHYAf8B8AHiAcgB/wHvAeABxgH/Ae4B3QHDAf8B6gHXAb0B/wHCAaQBhQH/AcIBpAGF - Af8BwgGkAYUB/wG/AZcBAAH/AfQB5AHOAf8B0gGuAYQB/wH3AeoB1QH/A0oBigQAAz0BaAP9Af8D/AH/ - A/wB/wP8Af8D/AH/A/wB/wP8Af8BqwHAAdQB/wIAAZkB/wGRAaYBugH/A8oB/wPLAf8DPQFoEAADQAFv - Av0B+gH/AvoB9gH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/AuwB3wH/AvQB5QH/ - A0wBjwNUAa8DKgFAAwMBBAMZASMDPQFpAlABTwGbAl8BVwHoAmoBYQH5Ae0BtgEAAf8CfwFlAf4CXgFa - AdgCTgFNAZYDIAEvAlwBWQHMAlwBWQHMAzgBXAwAAkABPwFuAfgB7AHXAf8B7wHgAcYB/wHuAd0BwwH/ - AeoB1wG9Af8B5wHQAbYB/wHSAbYBmgL/AfYB5QH/AdYBsQGHAf8B4AHDAaQB/wHyAeIBzAH/AdQBsAGF - Af8B9gHnAdIB/wNIAYQEAAM9AWcI/wGwAcUB2gH/AgABoAH/AbABxQHaBf8BrQHCAdYB/wIAAZkB/wGB - AbQB5gH/AgABqgH/AZMBpwG8Af8DzAH/Az0BZxAAAz8BbQL8AfgB/wL4AfQB/wL3AfIB/wL2AfAB/wL1 - Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLzAeIB/wM/AW0IAAI/AT4BbANMAZMDUQGfA1UBsgNb - AcMCXQFOAfADKwH8AfQBvwEAAf8CqAFAAf0CXwFYAeMCXAFYAdECXAFZAcwB9AHCAQAB/wJcAVkBzAM4 - AVwIAAM+AWoB+wHxAd0B/wH3AeoB1QH/AfUB5wHSAf8B9AHkAc4B/wHyAeIBzAH/AdwBwgGnAf8B1wGy - AYkB/wHCAaABAAH/AcIBpAGFAf8BwgGkAYUB/wG/AZcBAAH/AfQB5AHOAf8CRgFFAX4EAAM9AWkDuwH/ - A7kB/wIAAZgB/wGPAcIB8QH/AgABpAH/AgABlgH/AgABiQH/AYQBtwHoAf8CAAGqAf8BhAG3AegB/wIA - Aa4B/wIAAZIB/wNTAaoDEwEaDAADPwFsAvwB9wH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/ - AuwB3wH/AugB2QH/AuYB1QH/AvIB4QH/Az8BbAgAAkwBSwGPA1YBswNWAbMDVgGzA1QBrwJZAVcBwgJh - AV0B4gNNAfoB9wHFAQAB/wH2AcQBAAH/AfgBygEAAf8B+AHLAQAB/wHyAbsBAAH/AfYBxgEAAf8CXAFZ - AcwDLgFIBAADMQFNAz0BZwJTAVIBqAHgAcABmgH/AdsBuQGPAf8B2gG4AY4B/wHYAbMBigH/AeEBxAGl - Af8B0gG2AZoC/wH2AeUB/wHWAbEBhwH/AeABwwGkAf8B8gHiAcwB/wNDAXgEAAM3AVsDYAHUA9sB/wGb - AbEBxgH/AQABigG9Af8BlQHIAfUB/wIAAZ8B/wGJAbwB6wH/AgABqgH/AYkBvAHrAf8BAAGIAbsB/wGJ - AbwB6wH/AXMCfwH+A10B7QJWAVkBvgM4AV4IAAM+AWsC+wH2Af8C9gHwAf8C9QHuAf8C9AHsAf8C8QHn - Af8C7AHfAf8C6AHZAf8C5gHVAf8C5QHUAf8C8gHhAf8DPgFrCAACTAFLAY8DVgGxA1QBrANSAaEDTAGS - AzEBTwJAAT8BbwJcAVkBzwJlAWQB5QNlAfQDKwH8AfoB0AGEAf8B9gHBAQAB/wH4Ac0BgQH/AlwBWQHM - Ay4BSAwAAz4BagH7AfEB3QH/AfcB6gHVAf8B9QHnAdIB/wH0AeQBzgH/AfIB4gHMAf8B3AHCAacB/wHX - AbIBiQH/AcIBoAEAAf8BwgGkAYUB/wHCAaQBhQH/AlIBUAGjBAADGAEiAzYBWQM8AWYDPAFmAUsCTAGP - AVoCXgHYAZ0B0AH4Af8BAAGIAbsB/wGSAcUB8AH/AQABiAG7Af8BnQHQAfgB/wGHAboB5wH/AQABqQHa - Af8BAAGwAeAB/wNcAeoBUgJTAagIAAM9AWkC+gH0Af8C9QHuAf8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZ - Af8C5gHVAf8CpAGTAf8CpAGTAf8CpAGTAf8CRQFEAXwIAAM/AWwDSgGNAkYBRQF/AzgBXgMaASQIAAMj - ATMDSAGFA1YBswJcAVkByQJcAVkBzAH8AdUBiQH/AlwBWQHMAzgBXBAAAzEBTQM9AWcCUwFSAagB4AHA - AZoB/wHbAbkBjwH/AdoBuAGOAf8B2AGzAYoB/wHhAcQBpQH/AdIBtgGaAv8B9gHlAf8CQAE/AW4DHAEn - FAADMQFOA1ABnQEAAZwBywH/AaQB1wH8Af8BAAGIAbsB/wGkAdcB/AH/AYwBvwHrAf8BAAGkAdUB/wEA - Aa0B3QH/AYQBtwHlAf8BjAG/AewB/wNQAZ0IAAM9AWgC+gHzAf8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZ - Af8C5gHVAf8C5QHUAf8CtgGlBf8DPQFoAxoBJTQAAlwBWQHMAlwBWQHMAzgBXBwAAz4BagH7AfEB3QH/ - AfcB6gHVAf8B9QHnAdIB/wH0AeQBzgH/AfIB4gHMAf8B3AHCAacB/wM+AWoDGwEmGAADTAGTAaUB2AH8 - Af8BAAGvAd0B/wEAAZ0BzAH/AakB3AL/AaUB2AH8Af8BigG9AecB/wGOAcEB6gH/AZMBxgHvAf8BmQHM - AfQB/wNMAZMDMAFLCAADPQFnAvwB9QH/AvkB7wH/AvYB6gH/AvQB5QH/AvMB4gH/AvIB4QH/AvIB4QH/ - AsIBsQH/Az0BZwMaASU4AANOAZkDOAFcIAADMQFNAz0BZwM9AWcDPQFnAz0BZwM9AWcDPQFnAxoBJBwA - Ay4BRwNKAYwDSgGMA0oBjANKAYwDSgGMA0oBjANKAYwDSgGMA0oBjAMuAUcMAAMxAU0DPAFmAzwBZgM8 - AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgMaASQQAAFCAU0BPgcAAT4DAAEoAwABQAMAAVADAAEBAQABAQUA - AYABAhYAA/+BAAL/Af4BPwH/AeMCAAL/Af4BHwH/AeMIAAGAAQMGAAHAAQMGAAHAAQMGAAHAAQMGAAHA - AQMGAAHAAQMGAAHAAQMGAAHAAQMGAAHAAQMGAAHAAQMBDAEwAQwBMAEMATABwAEDAQwBMAEMATABDAEw - AcABAQEMATABDAEwAQwBMAHAAQAG/wHgAQAB/wHjAgABwAcAAcAFAAHAAQAB8AEAAcADAAHAAQAB8AEA - AcADAAHAAQAB8AEAAcADAAHAAQMCAAHAAQECAAHAAQMCAAHAAQMCAAHAAQMCAAHAAQMCAAHAAQMCAAHA - AQMCAAHAAQMCAAHAAQMCAAHAAQMCAAHAAQMCAAHAAQMB8AEAAcABAwIAAcABAwHwAQABwAEDAgABwAED - AfABAAHAAQMCAAHAAQcB8AEBAcABBwL/AcABDwHwAQMBwAEPAv8EAAL/AYABDwYAAYABDwYAAfwBHwGA - AQEBgAEBAgAB4AEfAYABAQGAAQECAAHsAR8BgAEBAYABAQIAAewBHwGAAQEBgAEBAgAB7wH/BgAB7wH/ - BgAB7wGDBgAB7AGDBgABhAGDBgAB/AGDAcABAAHAAwAB/wGDAcABAAHAAwAC/wHAAQEBwAEDAgAC/wHA - AQMBwAEDAv8DAAEPBwABAwQAAf8B4wGAAQMBAAEDAcABAwEGAQEBgAIAAQMBwAEDAgABgAIAAQMBwAED - AgABgAEBAQABAwHAAQEBAAEBAYABAQEAAQMBwAIAAQMBgAEBAQABAwHAAQABwAEnAYABAQEAAQMBwAIA - AQMBgAEBAQABAwHAAQMBAAEBAYABAQEAAQEBwAEDAgABgAEBAgABwAEDAgAB4AEBAgABwAEDAQYBAQHg - AQEB8AEAAcABAwH/AeMB+AEDAfABAAHAAQcB/wHnAfgBBwHwAQEBwAEPCw== + Af8DAAH/AwAB/wGTAaQBAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wPhAf8DPgFqAX0BXgFT + AdAB4wGeAYcB/wH3Ac4BwQH/AeMBngGHAf8BfQFeAVMB0BQAAzUBVwNpAbgD/QH/A2kBuAM1AVcMAAJL + AUwBjwGNAaYBwAH/Aa4BxwHhAf8BrgHHAeEB/wGuAccB4QH/AZ4BtwHRAf8BvAGGAQAC/wHjAZIC/wHV + AQAC/wHRAQAC/wHRAQAC/wHRAQAC/wHYAQAB/wJcAVkBzAgAAksBTAGPAY0BpgHAAf8BrgHHAeEB/wGu + AccB4QH/Aa4BxwHhAf8BngG3AdEB/wGeAbcB0QH/AgABpgH/AgAB9wH/AgAB9wH/AgAB9wH/AgAB9wH/ + AgAB9wH/AlkBXAHMAz0BaQPkAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/AwAB/wMAAf8DAAH/ + AwAB/wMAAf8D5AH/Az0BaQMdASkBhgFpAV4B0AHpAYMBXgH/AYYBaQFeAdADHQEpFAADDQERAzQBVAM9 + AWcDNAFUAw0BEQwAA0QBewNdAfABrAHFAd8B/wG5AdIB7AH/AbkB0gHsAf8BqwHEAd4B/wG/AZwBAAH/ + Ac0BlgEAAf8BzQGWAQAB/wHKAZMBAAH/AysB/AH/AeUBlwH/AlwBWQHMAzgBXAgAA0QBewNdAfABrAHF + Ad8B/wG5AdIB7AH/AbkB0gHsAf8BqwHEAd4B/wGrAcQB3gH/AgABwwH/AgABtQH/AgABswH/AysB/AJe + AWUB5QJZAVwBzANOAZkDPQFoA+oB/wPlAf8D5QH/A+UB/wPlAf8D5QH/A+UB/wPlAf8D5QH/A+UB/wPl + Af8D5QH/A+UB/wPqAf8DPQFoSAADLgFIA1IBqQNhAe4BqAHBAdsB/wGoAcEB2wH/AagBwQHbAf8BqAHB + AdsB/wGoAcEB2wH/AagBwQHbAf8DYQHuAmEBVAHuAl8BWgHbAzgBXAwAAy4BSANSAakDYQHuAagBwQHb + Af8BqAHBAdsB/wGoAcEB2wH/AagBwQHbAf8BqAHBAdsB/wGoAcEB2wH/A2EB7gNSAakDLgFICAADMQFN + AzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8AWYDMQFN + SAADBQEHAy0BRQI/AUABbgNEAXkDRAF5A0QBeQNEAXkDRAF5A0QBeQI/AUABbgNVAbIDOAFeEAADBQEH + Ay0BRQI/AUABbgNEAXkDRAF5A0QBeQNEAXkDRAF5A0QBeQI/AUABbgMtAUUDBQEHSwABAQMCAQMDBAEG + AwcECgEOAw0BEgMQARYDEgEYAxMBGgMTARoDEwEaAxIBGAMOARMDCQEMAwQBBgMAAQEDFgEfAlEBTwGc + AlgBVgHBAlgBVgHBAlgBVgHBAlgBVgHBAlgBVgHBAlgBVgHBAlgBVgHBAlgBVgHBAlEBTwGcAxgBIhAA + Az0BagNIAYUDSAGFA0gBhQNIAYUDSAGFA0gBhQNIAYUDSAGFA0gBhQNIAYUDSAGFA0gBhQNAAXADHQEq + AxIBGAMNARIDHwEsA0EBcgNIAYcDSAGHA0gBhwNIAYcDAAH/A1oB2ANQAaQDSAGHA0gBhwNIAYcDQQFy + Ax8BLAMNARIDAAEBAwQBBgMJAQwDDwQUARwDGQEjAx4BKwMhATADIwEzAyMBMwMjATMDQwF4AzMBUgMS + ARgDCAELAwEBAgMMARADUwGqAf0B9AHhAf8B+wHyAdwB/wH6AfEB3AH/AfoB8AHbAf8B+QHwAdoB/wH5 + Ae8B2QH/AfkB7gHYAf8B/AHyAd8B/wNWAbMDHgErAxMBGgMNAREIAANEAXsD6wH/A+cB/wPnAf8D5wH/ + A+cB/wPnAf8D5wH/A+cB/wPnAf8D5wH/A+cB/wPrAf8DRAF7AxABFQMJAQwDBwEJAxABFgNHAYIO/wH+ + Af8BgAG2AccB/wHZAfQC/wEAAZ8BrwH/AbsB2QHdAf8C/AH4Af8C/gH5Af8DRwGCAxABFgMHAQksAAJM + AUsBjwJMAUsBjwMqAUEMAAJPAU4BlwH7AfIB3AH/AfUB7AHSAf8B9QHrAdEB/wH0AeoB0AH/AfMB6AHO + Af8B8gHmAcwB/wHxAeQBygH/AfgB7QHXAf8CYQFYAeYCWAFWAcECUQFPAZwDGAEiCAADQgF2A+oB/wPi + Af8D4gH/A+IB/wPiAf8D4gH/A+IB/wPiAf8D4gH/A+IB/wPiAf8D6gH/A0IBdhAAA0QBewj/A/4B/wL9 + AfwB/wHXAekB7gH/AQABtQHFAf8BAAHmAfcB/wEAAZ0BrQH/AbYB1gHYAf8C+wH2Af8DRAF7CAADTgGZ + AVwCWQHJAVYCVQG0A0gBhgMjATMIAAMaASQDOAFdAkYBRQF+A0oBjQJMAUsBjwNWAbMCTAFLAY8DKgFB + CAACTAFLAZAB+gHxAdwB/wH1AesB0QH/AfQB6gHQAf8B8wHoAc4B/wHyAeYBzAH/AfEB5AHKAf8B8AHi + AcgB/wH3AesB1gH/Ac4BqwGCAf8B/AHyAd8B/wNWAbMDEwEaAxMBGgMNAREDQQFzA+0C/wGZAQAB/wPm + Af8DvQH/A6wB/wO9Af8DvQH/A6wB/wO9Af8DyQH/A+YB/wPtAf8DQQFzEAADQwF3BP8D/gH/Av0B/AH/ + Av0B+wH/AvwB+QH/Ab4B5AHoAf8BAAG0AcQB/wEAAeYB9wH/AQABnQGsAf8BugHZAdoB/wNDAXcIAAFc + AlkBzAMrAfwCWQFCAfUCZQFeAeUBXAFaAVkBzwJAAT8BbwMxAU8DTAGSAlIBUQGhAlYBVAGrAlYBVQGx + A1YBswNWAbMDVgGzAkwBSwGPAyMBMwQAA0oBigH6AfAB2wH/AfQB6gHQAf8B8wHoAc4B/wHyAeYBzAH/ + AfEB5AHKAf8B8AHiAcgB/wHvAeABxgH/AfcB6gHVAf8BzQGqAQAB/wH4Ae0B1wH/AmEBWAHmAlgBVgHB + AlEBTwGcAxgBIgNAAXED8AH/A+sB/wPrAf8D6wH/A+sB/wPrAf8D6wH/A+sB/wPrAf8D6wH/A+sB/wPw + Af8DQAFxEAADQgF2Av8B/gH/Av0B/AH/Av0B+wH/AvwB+QH/AvsB+AH/AvoB9gH/AbwB4gHlAf8BAAG0 + AcMB/wEAAeYB9wH/AQABngGsAf8DTgGZCAABXAJZAcwB+QHCAQAC/wG0AQAC/wGzAQAB/wJNASkB+gJh + AV0B4gJZAVcBwgNUAa8DVgGzA1YBswNWAbMDVgGzA1YBswNWAbMCTAFLAY8DIwEzBAADSAGEAfkB8AHa + Af8B8wHoAc4B/wHyAeYBzAH/AfEB5AHKAf8B8AHiAcgB/wHvAeABxgH/Ae4B3QHDAf8B9gHnAdIB/wHQ + AawBggH/AfcB6wHWAf8BzgGrAYIB/wH8AfIB3wH/A1MBqgQAA0ABbgPzAf8CAAHCAf8D7wH/A7wB/wPF + Af8DxQH/A8UB/wO8Af8DxQH/A7wB/wPFAf8D8wH/A0ABbhAAA0IBdAL+Af0B/wL9AfsB/wL8AfkB/wL7 + AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wG7AeEB4gH/AQABswHCAf8BAAHmAfcB/wNWAbgDIAEuBAADTgGZ + Al0BWQHSAl8BWAHjAqgBQAH9AfwBsAEAAf8DKwH8AmIBWAHvAlsBWQHDA1UBsgJRAVABnwNMAZMCTAFL + AY8DVgGzAkwBSwGPAyoBQQgAAkYBRQF+AfkB7wHZAf8B8gHmAcwB/wHxAeQBygH/AfAB4gHIAf8B7wHg + AcYB/wHuAd0BwwH/AeoB1wG9Af8B9AHkAc4B/wHSAa4BhAH/AfcB6gHVAf8BzQGqAQAB/wH4Ae0B1wH/ + Ak8BTgGXBAADPwFsA/cB/wP0Af8D9AH/A/QB/wP0Af8D9AH/A/QB/wP0Af8D9AH/A/QB/wP0Af8D9wH/ + Az8BbBAAA0EBcgL+AfwB/wL8AfkB/wL7AfgB/wL6AfYB/wL4AfQB/wL3AfIB/wL2AfAB/wL1Ae4B/wG5 + At8B/wKvAaoB/wP3Af8DSwGOAy0BRgMEAQYDIgEyAk4BTQGWAl4BWgHYAn8BMAH+Ae4BqAEAAf8CagFB + AfkCZAFcAecDUAGaAz0BaQMYASECTAFLAY8CTAFLAY8DKgFBDAADQwF4AfkB7gHYAf8B8QHkAcoB/wHw + AeIByAH/Ae8B4AHGAf8B7gHdAcMB/wHqAdcBvQH/AecB0AG2Af8B8gHiAcwB/wHUAbABhQH/AfYB5wHS + Af8B0AGsAYIB/wH3AesB1gH/AkwBSwGQBAADPgFqA/oB/wEAAaoBAAH/A/gB/wO7Af8DzAH/A9QB/wPa + Af8D+AH/A/gB/wP4Af8D+AH/A/oB/wM+AWoQAANAAXEC/QH7Af8C+wH4Af8C+gH2Af8C+AH0Af8C9wHy + Af8C9gHwAf8C9QHuAf8C9AHsAf8C8QHnAf8C3gHUAf8DVgG2AoAC/wJWAVgBwQgAAwIBAwNVAbUCZAFT + AfEB5wGuAQAB/wHhAaUBAAH/AmQBUwHxA1UBtQMCAQMEAAM1AVcDRAF6EAACQgFBAXMB+AHtAdgB/wHw + AeIByAH/Ae8B4AHGAf8B7gHdAcMB/wHqAdcBvQH/AcIBpAGFAf8BwgGkAYUB/wHCAaQBhQH/Ab8BlwEA + Af8B9AHkAc4B/wHSAa4BhAH/AfcB6gHVAf8DSgGKBAADPQFoA/0B/wP8Af8D/AH/A/wB/wP8Af8D/AH/ + A/wB/wGrAcAB1AH/AgABmQH/AZEBpgG6Af8DygH/A8sB/wM9AWgQAANAAW8C/QH6Af8C+gH2Af8C+AH0 + Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C8QHnAf8C7AHfAf8C9AHlAf8DTAGPA1QBrwMqAUADAwEE + AxkBIwM9AWkCUAFPAZsCXwFXAegCagFhAfkB7QG2AQAB/wJ/AWUB/gJeAVoB2AJOAU0BlgMgAS8CXAFZ + AcwCXAFZAcwDOAFcDAACQAE/AW4B+AHsAdcB/wHvAeABxgH/Ae4B3QHDAf8B6gHXAb0B/wHnAdABtgH/ + AdIBtgGaAv8B9gHlAf8B1gGxAYcB/wHgAcMBpAH/AfIB4gHMAf8B1AGwAYUB/wH2AecB0gH/A0gBhAQA + Az0BZwj/AbABxQHaAf8CAAGgAf8BsAHFAdoF/wGtAcIB1gH/AgABmQH/AYEBtAHmAf8CAAGqAf8BkwGn + AbwB/wPMAf8DPQFnEAADPwFtAvwB+AH/AvgB9AH/AvcB8gH/AvYB8AH/AvUB7gH/AvQB7AH/AvEB5wH/ + AuwB3wH/AugB2QH/AvMB4gH/Az8BbQgAAj8BPgFsA0wBkwNRAZ8DVQGyA1sBwwJdAU4B8AMrAfwB9AG/ + AQAB/wKoAUAB/QJfAVgB4wJcAVgB0QJcAVkBzAH0AcIBAAH/AlwBWQHMAzgBXAgAAz4BagH7AfEB3QH/ + AfcB6gHVAf8B9QHnAdIB/wH0AeQBzgH/AfIB4gHMAf8B3AHCAacB/wHXAbIBiQH/AcIBoAEAAf8BwgGk + AYUB/wHCAaQBhQH/Ab8BlwEAAf8B9AHkAc4B/wJGAUUBfgQAAz0BaQO7Af8DuQH/AgABmAH/AY8BwgHx + Af8CAAGkAf8CAAGWAf8CAAGJAf8BhAG3AegB/wIAAaoB/wGEAbcB6AH/AgABrgH/AgABkgH/A1MBqgMT + ARoMAAM/AWwC/AH3Af8C9wHyAf8C9gHwAf8C9QHuAf8C9AHsAf8C8QHnAf8C7AHfAf8C6AHZAf8C5gHV + Af8C8gHhAf8DPwFsCAACTAFLAY8DVgGzA1YBswNWAbMDVAGvAlkBVwHCAmEBXQHiA00B+gH3AcUBAAH/ + AfYBxAEAAf8B+AHKAQAB/wH4AcsBAAH/AfIBuwEAAf8B9gHGAQAB/wJcAVkBzAMuAUgEAAMxAU0DPQFn + AlMBUgGoAeABwAGaAf8B2wG5AY8B/wHaAbgBjgH/AdgBswGKAf8B4QHEAaUB/wHSAbYBmgL/AfYB5QH/ + AdYBsQGHAf8B4AHDAaQB/wHyAeIBzAH/A0MBeAQAAzcBWwNgAdQD2wH/AZsBsQHGAf8BAAGKAb0B/wGV + AcgB9QH/AgABnwH/AYkBvAHrAf8CAAGqAf8BiQG8AesB/wEAAYgBuwH/AYkBvAHrAf8BcwJ/Af4DXQHt + AlYBWQG+AzgBXggAAz4BawL7AfYB/wL2AfAB/wL1Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLm + AdUB/wLlAdQB/wLyAeEB/wM+AWsIAAJMAUsBjwNWAbEDVAGsA1IBoQNMAZIDMQFPAkABPwFvAlwBWQHP + AmUBZAHlA2UB9AMrAfwB+gHQAYQB/wH2AcEBAAH/AfgBzQGBAf8CXAFZAcwDLgFIDAADPgFqAfsB8QHd + Af8B9wHqAdUB/wH1AecB0gH/AfQB5AHOAf8B8gHiAcwB/wHcAcIBpwH/AdcBsgGJAf8BwgGgAQAB/wHC + AaQBhQH/AcIBpAGFAf8CUgFQAaMEAAMYASIDNgFZAzwBZgM8AWYBSwJMAY8BWgJeAdgBnQHQAfgB/wEA + AYgBuwH/AZIBxQHwAf8BAAGIAbsB/wGdAdAB+AH/AYcBugHnAf8BAAGpAdoB/wEAAbAB4AH/A1wB6gFS + AlMBqAgAAz0BaQL6AfQB/wL1Ae4B/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLmAdUB/wKkAZMB/wKk + AZMB/wKkAZMB/wJFAUQBfAgAAz8BbANKAY0CRgFFAX8DOAFeAxoBJAgAAyMBMwNIAYUDVgGzAlwBWQHJ + AlwBWQHMAfwB1QGJAf8CXAFZAcwDOAFcEAADMQFNAz0BZwJTAVIBqAHgAcABmgH/AdsBuQGPAf8B2gG4 + AY4B/wHYAbMBigH/AeEBxAGlAf8B0gG2AZoC/wH2AeUB/wJAAT8BbgMcAScUAAMxAU4DUAGdAQABnAHL + Af8BpAHXAfwB/wEAAYgBuwH/AaQB1wH8Af8BjAG/AesB/wEAAaQB1QH/AQABrQHdAf8BhAG3AeUB/wGM + Ab8B7AH/A1ABnQgAAz0BaAL6AfMB/wL0AewB/wLxAecB/wLsAd8B/wLoAdkB/wLmAdUB/wLlAdQB/wK2 + AaUF/wM9AWgDGgElNAACXAFZAcwCXAFZAcwDOAFcHAADPgFqAfsB8QHdAf8B9wHqAdUB/wH1AecB0gH/ + AfQB5AHOAf8B8gHiAcwB/wHcAcIBpwH/Az4BagMbASYYAANMAZMBpQHYAfwB/wEAAa8B3QH/AQABnQHM + Af8BqQHcAv8BpQHYAfwB/wGKAb0B5wH/AY4BwQHqAf8BkwHGAe8B/wGZAcwB9AH/A0wBkwMwAUsIAAM9 + AWcC/AH1Af8C+QHvAf8C9gHqAf8C9AHlAf8C8wHiAf8C8gHhAf8C8gHhAf8CwgGxAf8DPQFnAxoBJTgA + A04BmQM4AVwgAAMxAU0DPQFnAz0BZwM9AWcDPQFnAz0BZwM9AWcDGgEkHAADLgFHA0oBjANKAYwDSgGM + A0oBjANKAYwDSgGMA0oBjANKAYwDSgGMAy4BRwwAAzEBTQM8AWYDPAFmAzwBZgM8AWYDPAFmAzwBZgM8 + AWYDPAFmAxoBJBAAAUIBTQE+BwABPgMAASgDAAFAAwABUAMAAQEBAAEBBQABgAECFgAD/wEAAv9eAAHz + Ac8GAAHwAQ8GAAH4AR8GAAL/BgAC/wH+AT8B/wHjAgAC/wH+AR8B/wHjCAABgAEDBgABwAEDBgABwAED + BgABwAEDBgABwAEDBgABwAEDBgABwAEDBgABwAEDBgABwAEDBgABwAEDAQwBMAEMATABDAEwAcABAwEM + ATABDAEwAQwBMAHAAQEBDAEwAQwBMAEMATABwAEABv8B4AEAAf8B4wIAAcAHAAHABQABwAEAAfABAAHA + AwABwAEAAfABAAHAAwABwAEAAfABAAHAAwABwAEDAgABwAEBAgABwAEDAgABwAEDAgABwAEDAgABwAED + AgABwAEDAgABwAEDAgABwAEDAgABwAEDAgABwAEDAgABwAEDAgABwAEDAfABAAHAAQMCAAHAAQMB8AEA + AcABAwIAAcABAwHwAQABwAEDAgABwAEHAfABAQHAAQcC/wHAAQ8B8AEDAcABDwL/BAAC/wHABwABwAcA + Af8BwQGAAQEBgAEBAgAB/gEBAYABAQGAAQECAAH+AcEBgAEBAYABAQIAAf4BwQGAAQEBgAEBAgAB/gH/ + BgAB/gH/BgABBgHBBgABBgHBBwABAQYAAQcBwQHAAQABwAMAAQcBwQHAAQABwAMAAv8BwAEBAcABAwIA + Av8BwAEDAcABAwL/AwABDwcAAQMEAAH/AeMBgAEDAQABAwHAAQMBBgEBAYACAAEDAcABAwIAAYACAAED + AcABAwIAAYABAQEAAQMBwAEBAQABAQGAAQEBAAEDAcACAAEDAYABAQEAAQMBwAEAAcABJwGAAQEBAAED + AcACAAEDAYABAQEAAQMBwAEDAQABAQGAAQEBAAEBAcABAwIAAYABAQIAAcABAwIAAeABAQIAAcABAwEG + AQEB4AEBAfABAAHAAQMB/wHjAfgBAwHwAQABwAEHAf8B5wH4AQcB8AEBAcABDws= @@ -789,6 +807,112 @@ wgNemEQshhELYQRjEpPwwhw8AL4H3oADWXjATg6ovuUtrwtMUEEMbjAHFmpwDi2ExA1W+L882EGETxlA GHZQhB72sAtdCIUKZFS4QiKqUAWQiAER8iCC/ijIBggsRBEKUQggAlEFf8DiEIc4hRh4IBIhCFeTdDgI JlCRilZMowqESAQ4HMCJiFJACIRABCak0YpDHEQkVgDHegHgBDYQAtQaQchICCEECMJRQAAAOw== + + + + 943, 13 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAm + CAAAAk1TRnQBSQFMAgEBAgEAAbABDgGwAQ4BEAEAARABAAT/AREBAAj/AUIBTQE2BwABNgMAASgDAAFA + AwABEAMAAQEBAAEQBgABCBIAAf8BfwHeAXsBsgFeAW0BWgFtAVoBbQFaAW0BWgFtAVoBbQFaAW0BWgFt + AVoBbQFaAW0BWgGyAV4B3gF7Af8BfwIAAd4BewG9AXcBvQF3Ab0BdwG9AXcBvQF3Ab0BdwG9AXcBvQF3 + Ab0BdwG9AXcBvQF3Ab0BdwHeAXtCAAH/AX8B/wF/Aa4BYgEwAXsBMAF3ATABdwEwAXcBMAF3ATABdwEw + AXcBMAF7ASkBWgEwAXsBrgFiAZsBcwH/AX8CAAG9AXcB3gF7Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/ + Af8BfwH/AX8B/wF/Af8BfwHeAXsBvQF3RgAB0AFmATABdwEPAXcBDwF3AQ8BdwEPAXcBDwF3AQ8BdwEw + AXcBagFeATABdwHeARYB0AFmAgAB/wF/Ab0BdwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/ + Af8BfwH/AX8B/wF/Af8BfwG9AXdGAAHyAWoBUAF3AS8BdwEvAXcBLwF3AS8BdwEvAXcBLwF3AVABdwGL + AWIBUAF3AT8BIwHyAWoCAAH/AX8BvQF3Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/ + Af8BfwH/AX8B/wF/Ab0BdwH/AX9EAAESAWsBUQF7ATABdwEwAXcBMAF3ATABdwEwAXcBMAF3AVEBewGM + AWYBUQF7Ab0BbwESAWsCAAH/AX8BvQF3Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/ + Af8BfwH/AX8B/wF/Ab0BdwH/AX9EAAETAW8BUQF7AVABdwFQAXcBUAF3AVABdwFQAXcBUAF3AVEBewGs + AWYBUQF7Ad4BcwETAW8CAAH/AX8BvQF3Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/ + Af8BfwH/AX8B/wF/Ab0BdwH/AX9EAAETAW8BcgF7AVEBewFRAXsBUQF7AVEBewFRAXsBUQF7AXIBewGt + AWYBcgF7Af8BewETAW8CAAH/AX8BvQF3Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/ + Af8BfwH/AX8B/wF/Ab0BdwH/AX9EAAEzAW8BcgF7AXIBewFyAXsBcgF7AXIBewFyAXsBcgF7AXIBewHv + AW4B7wFuAf8BfwEzAW8CAAH/AX8BvQF3Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/ + Ad4BewHeAXsB/wF/Ab0BdwH/AX9EAAE0AW8BkwF7AXIBewFyAXsBcgF7AXIBewFyAXsBcgF7AXIBewGT + AX8BDwFvATQBbwHdAXsCAAH/AX8BvQF3Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B3gF7 + Ad4BewHeAXsB/wF/Ab0BdwH/AX9EAAE0AXMBkwF/AXMBewFzAXsBcwF7AXMBewFzAXsBcwF7AXMBewFz + AXsBtAF/ATQBcwQAAf8BfwG9AXcB/wF/Af8BfwH/AX8B/wF/Af8BfwH/AX8B/wF/Ad4BewHeAXsBvQF3 + Ab0BdwH/AX8BvQF3Af8Bf0QAATUBcwG0AX8BkwF/AZMBfwGTAX8BkwF/AZMBfwGTAX8BkwF/AZMBfwG0 + AX8BNQFzBAAB/wF/Ab0BdwH/AX8B/wF/Af8BfwH/AX8B/wF/Af8BfwHeAXsB3gF7Ab0BdwG9AXcBnAFz + Af8BfwG9AXcB/wF/RAABVQFzAbQBfwGUAX8BlAF/AZQBfwGUAX8BlAF/AZQBfwGUAX8BlAF/AbQBfwFV + AXMEAAH/AX8BvQF3Af8BfwH/AX8B/wF/Af8BfwHeAXsB3gF7Ad4BewG9AXcB/wF/Af8BfwH/AX8B/wF/ + Ab0BdwH/AX9EAAFVAXMBtQF/AbQBfwG0AX8BtAF/AbQBfwG0AX8BtAF/AbQBfwG0AX8BtQF/AVUBcwQA + Af8BfwG9AXcB/wF/Ad4BewH/AX8B3gF7Ad4BewHeAXsB3gF7Ab0BdwH/AX8B3gF7Ad4BewFaAWsB3gF7 + RgABVgFzAdUBfwG0AX8BtAF/AbQBfwG0AX8BtAF/AbQBfwG0AX8BtAF/AdUBfwFWAXMGAAG9AXcB/wF/ + Ad4BewHeAXsB3gF7Ad4BewHeAXsBvQF3Ab0BdwH/AX8BnAFzAVoBawHeAXsB/wF/RgABVgFzAdYBfwHV + AX8B1QF/AdUBfwHVAX8B1QF/AdUBfwHVAX8B1QF/AdYBfwFWAXMGAAG9AXcB3gF7Af8BfwH/AX8B/wF/ + Af8BfwH/AX8B/wF/Af8BfwH/AX8BWgFrAd4BewH/AX9IAAGaAXcBVgFzAVYBcwFWAXMBVgFzAVYBcwFW + AXMBVgFzAVYBcwFWAXMBVgFzAZoBdwYAAf8BfwG9AXcBvQF3Ab0BdwG9AXcBvQF3Ab0BdwG9AXcBvQF3 + Ab0BdwHeAXsB/wF/RgABQgFNAT4HAAE+AwABKAMAAUADAAEQAwABAQEAAQEFAAGAFwAD/wMAAYABAQYA + AYABAQQAAcABAQEAAQEEAAHAAQEGAAHAAQEGAAHAAQEGAAHAAQEGAAHAAQEGAAHAAQEGAAHAAQMGAAHA + AQMGAAHAAQMGAAHAAQMBAAEBBAABwAEDAYABAQQAAcABAwGAAQMEAAHAAQMBgAEHBAAL + + + + 779, 13 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAH2SURBVDhPjY5dSFNhHIf/SGGEia7YRbdFCMpmdBeUeFE3 + QZAg3eRHJVJdFoLKarrMj0zLFNzUDU3RkhYNJfrAFEQ0nR+ghWgoZenGdB3nNJe6n+c953UHmh78wcP/ + 4jzPy6GdDZfS9aFSKtwPzOWZssESMmHVAfjeqCM6zOWZsoFHVITl1wgutqnCHObyTFnfQyre8r7CprtF + FeYwl2fKek1UtulpxcZ8kyrMYS7PlPUUUPmGqxmBOasqzGEuz5R9NlJl4LcNa7NmVf65msBcnin7aKCq + vz/q4Z+u2ZPALxtmegxg7of7dIan8t7nU83aTC18k892hX373pUnkoutYBDM56m8JEv019MdOmR+ugBh + ojwM/9RzjNpvS3dlfR2deVTLU3lHbbGeLG8O9PZ4LI2VhOH7Vglne7Z05wUBjhyqk8sGjYWssc5j5pjF + VE829G1xEulvk+AZNoUQxh9joPWGdKfdbtjvkVV+oDrGmbyQgv/RN56Ce9AY4o/4F33NGdJN/hJE+11q + lB+oOGKhJ1FOrTHSm/DzHHTmkxJpLWfh6jeE8I4Uoav+qnR17/x4cYdeyg8QHRbRah8cEo7PxiOx6gSW + hgrDEEaL4Xh6SbrVN6kz/Txd4S1pRBKiL0f0ajMOruizDiyUXaNuNW5dpAbWEJFmG0WwP24GDiWlAAAA + AElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHjSURBVDhPfZJLKIRhFIY/jCKESZSdMguRa2kSuRUKJYYs + JHcmhmYao8xoSsqGDSthIzY2UlIsZ2MzCwsWVpPLzIjJZe7345zp488w/1vv5u99n/985/vYtwZWVrr7 + jcYpMSuMxmIe/yuFXj/tCYfhPRCAF68XrG43PLhccO90xnxqMgFleg0GGa/8Vs/y8owrGAQHFu2fn2Bx + OODu+RlubTa4sVrh6PwcSJT7F9Kt0yndCHjzeP6FbB8e/ljW3m7gNUFdWu2sNxSCDxw/EYQmoeNQltcE + tanVcz7cgdPnE4UQgLK8JqhVpVL5EeD2+0UhtFjK8pqgFqVyIRiJgBf3IAah26Esrwmqn5xUhxDgxz2I + QV7wG2V5TVDdyIgmHI1CAI+RCDJ8NQ+VF62Qt1V+xWuCaoeGtBEE0BSJIJVnzTDxtgiS/fxHXhNUMzio + i+JDCSMgHjJmwj+fNKEbof91CiRbBU9sP9fM9qQ7vM5YRV/fEr20KE4RD6k6boRme+8fs+0cM68zJuvo + 0BOAFA8Zv1BB1UFDzGUPDSBZy7OyjUwz28yKTZCOzi+Qy1d5PyY6Du2EFksguuLq3XootJRCymK2jTq8 + y6TosrSiIk1GScm6mJMVudfJo6n2pM60S+owxqRfZJFD73bmYb4AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFRSURBVDhPzY2vS0NhFIbPX6BM7wRRB4LTNpjo2uJgYbCw + YhhTh7A6FrauoMmgRcEwGfiTgUVQDCYxXcEgKFjFYLGKweP7Xs69l+F1xeILDx/nPO/hk/+VE5H8qYjL + 11ZB+jkvhxBHKGirpXw5mwrcR73+wwXpQHw1m/pQKOhno6GcQd5w36pVz72Uy56zszBtFPch3ms1vc5k + 9LVSUc7ksVj0dne5nLdj1856swcB3OdSSS9SKb3NZvUqndZ2PK7HiYTSsWP16OyisIPieTKpnVjM48Bx + lDs6q/2eLZS2UT7Dr10c+3BHZ7XobKIA3EscREHHjtV7sw6xgcINij6co3bs2lmYVYh7FHw4r6FIopyd + hVlAsQ7xhAJfzqb6Oj/jYHpWZGURhTmRZcxTYAKMgcl5kSU6djDPAN4EGQDDYNQYAUNgENDFQBz43gHc + /zUi3+z5slrGfejKAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJySURBVDhPrZNrSJNRGMePboNwfYouKrjS7it1KzNTa10s + ZYGahTeCd/NSK4qGGbQkpA+5MoKCCJFphBSkGEFzzNFmFKGiuIqXMbd5Q7qwUNCN6MPk6TzHs4ER9KU/ + /OC8z/n/nhdeeMn/j9KaGK9y1ElU/e1xmQ4bgmec4R1v/T2SDHuRfL/z9RHDuK/uztzC1WYx0kDBs6bW + 68M77PD6ykgyrEXr8l3vhNa5UL35Bwi3vkHljWkobfAy6s1BEFqCoTW0g12u8ezoTZJn2a1Cy1Soqmka + KkxTjMb7PsB4Jn+B9tJnwLvqxqmQPKvPig63CYlXvqzPFz76y68HoNjoiWG862ELxMBPKDg3ymanr/lg + T8WwHx2uExK3tbuj3DSxWHjBDVE0+kFIL7FB2vEexpYTvYzt2legrnQsosN1XPCsv6pJjOBbDtcMg/qM + E0ytLhgbGwNRFOFx1whs01pjKPc6I+hwnS7Y3OXQlA8s5QlDsLvsLShLXbCz2AGPng6B3+8Hjc7FZlEy + NQNL6HCdLtj0pPOoMBxSVY1AZuUyBYZRJltefIrNomzUfgihw3X6EVPaDamFzomc2nHYp/Mybre5YXZ2 + FoSbIjx8PhObI8kH+ibR4TqNoi1pVarFnqP3hXMNXyH3/Bc4a3JDMBiE+fl5uNcpshmiPuUNyxQWOzrc + Xo4k8YFWntYxmF0TCGuuLMAhirrazci7+J09Z+kC4QTawS7X/khCzUnZWvOblIO2mWw9XVQiLiF4xhne + YYe3V0RK2UDZRSSKY0Ra1kykl7uJzPiegWec4R0h6RT8qdCJJZ6ymrKekvwP8EXYpQ4hvwHzCneZ9/p1 + 7gAAAABJRU5ErkJggg== @@ -800,6 +924,9 @@ that have the "Necessary update" status and the newest one. 155, 16 + + 155, 16 + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 @@ -839,6 +966,24 @@ that have the "Necessary update" status and the newest one. BXpk4tvLgGcnAyOiBsNkBmPa1yX3hgq9ZLh1FbpJuCtfwR/BMO9PyeJIhyR25QAAAABJRU5ErkJggg== + + True + + + True + + + True + + + True + + + True + + + True + AAABAAkAICAQAAEABADoAgAAlgAAABAQEAABAAQAKAEAAH4DAAAwMAAAAQAIAKgOAACmBAAAICAAAAEA diff --git a/nUpdate.Administration/UI/Dialogs/PackagesToAffectDialog.cs b/nUpdate.Administration/UI/Dialogs/PackagesToAffectDialog.cs index adddb252..25423f31 100644 --- a/nUpdate.Administration/UI/Dialogs/PackagesToAffectDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/PackagesToAffectDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// PackagesToAffectDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/UI/Dialogs/PreferencesDialog.cs b/nUpdate.Administration/UI/Dialogs/PreferencesDialog.cs index 46834a45..3eba53b7 100644 --- a/nUpdate.Administration/UI/Dialogs/PreferencesDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/PreferencesDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// PreferencesDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/UI/Dialogs/ProjectDialog.Designer.cs b/nUpdate.Administration/UI/Dialogs/ProjectDialog.Designer.cs index 0d41ed52..96df90a9 100644 --- a/nUpdate.Administration/UI/Dialogs/ProjectDialog.Designer.cs +++ b/nUpdate.Administration/UI/Dialogs/ProjectDialog.Designer.cs @@ -46,7 +46,7 @@ private void InitializeComponent() this.assemblyPathTextBox = new nUpdate.Administration.UI.Controls.ButtonTextBox(); this.label8 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); - this.line5 = new Line(); + this.line5 = new nUpdate.Internal.UI.Controls.Line(); this.label3 = new System.Windows.Forms.Label(); this.stepTwoLabel = new System.Windows.Forms.Label(); this.programmingLanguageComboBox = new System.Windows.Forms.ComboBox(); @@ -56,7 +56,7 @@ private void InitializeComponent() this.assumeHeader = new System.Windows.Forms.Label(); this.checkingUrlPictureBox = new System.Windows.Forms.PictureBox(); this.tickPictureBox = new System.Windows.Forms.PictureBox(); - this.line3 = new Line(); + this.line3 = new nUpdate.Internal.UI.Controls.Line(); this.newestPackageLabel = new System.Windows.Forms.Label(); this.amountLabel = new System.Windows.Forms.Label(); this.checkUpdateConfigurationLinkLabel = new System.Windows.Forms.LinkLabel(); @@ -71,15 +71,15 @@ private void InitializeComponent() this.projectIdLabel = new System.Windows.Forms.Label(); this.publicKeyTextBox = new System.Windows.Forms.TextBox(); this.publicKeyLabel = new System.Windows.Forms.Label(); - this.line2 = new Line(); + this.line2 = new nUpdate.Internal.UI.Controls.Line(); this.projectDataHeader = new System.Windows.Forms.Label(); - this.line1 = new Line(); + this.line1 = new nUpdate.Internal.UI.Controls.Line(); this.ftpDirectoryLabel = new System.Windows.Forms.Label(); this.ftpHostLabel = new System.Windows.Forms.Label(); this.overviewHeader = new System.Windows.Forms.Label(); this.newestPackageReleasedLabel = new System.Windows.Forms.Label(); this.releasedPackagesAmountLabel = new System.Windows.Forms.Label(); - this.line4 = new Line(); + this.line4 = new nUpdate.Internal.UI.Controls.Line(); this.panel2 = new System.Windows.Forms.Panel(); this.loadFromAssemblyRadioButton = new System.Windows.Forms.RadioButton(); this.enterVersionManuallyRadioButton = new System.Windows.Forms.RadioButton(); @@ -108,7 +108,7 @@ private void InitializeComponent() this.searchTextBox = new nUpdate.Administration.UI.Controls.CueTextBox(); this.statisticsTabPage = new System.Windows.Forms.TabPage(); this.updateStatisticsButton = new System.Windows.Forms.Button(); - this.controlPanel1 = new BottomPanel(); + this.controlPanel1 = new nUpdate.Internal.UI.Controls.BottomPanel(); this.lastUpdatedLabel = new System.Windows.Forms.Label(); this.chartPanel = new System.Windows.Forms.Panel(); this.gatheringStatisticsPictureBox = new System.Windows.Forms.PictureBox(); @@ -248,7 +248,7 @@ private void InitializeComponent() // line5 // this.line5.BackColor = System.Drawing.Color.White; - this.line5.LineAlignment = Line.Alignment.Horizontal; + this.line5.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line5.Location = new System.Drawing.Point(132, 368); this.line5.Name = "line5"; this.line5.Size = new System.Drawing.Size(398, 13); @@ -263,7 +263,7 @@ private void InitializeComponent() this.label3.ImeMode = System.Windows.Forms.ImeMode.NoControl; this.label3.Location = new System.Drawing.Point(20, 361); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(106, 20); + this.label3.Size = new System.Drawing.Size(105, 20); this.label3.TabIndex = 42; this.label3.Text = "Version linking"; // @@ -351,7 +351,7 @@ private void InitializeComponent() // line3 // this.line3.BackColor = System.Drawing.Color.White; - this.line3.LineAlignment = Line.Alignment.Horizontal; + this.line3.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line3.Location = new System.Drawing.Point(25, 167); this.line3.Name = "line3"; this.line3.Size = new System.Drawing.Size(505, 10); @@ -497,7 +497,7 @@ private void InitializeComponent() // line2 // this.line2.BackColor = System.Drawing.Color.White; - this.line2.LineAlignment = Line.Alignment.Horizontal; + this.line2.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line2.Location = new System.Drawing.Point(110, 270); this.line2.Name = "line2"; this.line2.Size = new System.Drawing.Size(420, 13); @@ -519,7 +519,7 @@ private void InitializeComponent() // line1 // this.line1.BackColor = System.Drawing.Color.White; - this.line1.LineAlignment = Line.Alignment.Horizontal; + this.line1.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line1.Location = new System.Drawing.Point(144, 24); this.line1.Name = "line1"; this.line1.Size = new System.Drawing.Size(386, 13); @@ -578,7 +578,7 @@ private void InitializeComponent() // line4 // this.line4.BackColor = System.Drawing.Color.White; - this.line4.LineAlignment = Line.Alignment.Horizontal; + this.line4.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line4.Location = new System.Drawing.Point(101, 532); this.line4.Name = "line4"; this.line4.Size = new System.Drawing.Size(432, 10); diff --git a/nUpdate.Administration/UI/Dialogs/ProjectDialog.cs b/nUpdate.Administration/UI/Dialogs/ProjectDialog.cs index 7cdedd8b..67678294 100644 --- a/nUpdate.Administration/UI/Dialogs/ProjectDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/ProjectDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ProjectDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections; @@ -13,6 +14,7 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; +using Ionic.Zip; using MySql.Data.MySqlClient; using nUpdate.Administration.Core; using nUpdate.Administration.Core.Application; @@ -561,9 +563,6 @@ private void InitializePackageItems() UpdatePackage package1 = package; Invoke(new Action(() => { - Popup.ShowPopup(this, SystemIcons.Information, "Missing package file.", - $"The package of version \"{new UpdateVersion(package1.Version).FullText}\" could not be found on your computer. Specific actions and information won't be available.", - PopupButtons.Ok); packageListViewItem.SubItems.Add("-"); packageListViewItem.SubItems.Add("-"); })); @@ -1079,6 +1078,134 @@ from Control c in statisticsTabPage.Controls where c.GetType() != typeof(Panel) } await InitializeAsync(); + + if (Project.ConfigVersion.Equals("1b2")) + { + if (!_foundWithUrl) + { + Popup.ShowPopup(this, SystemIcons.Error, "Migration not possible.", + "This project needs to be migrated in order to work properly with the newest version, but the update configuration file could not be loaded. Please make sure the update configuration is reachable over HTTP(S) and open the project again to start this process automatically.", + PopupButtons.Ok); + Close(); + return; + } + + Popup.ShowPopup(this, SystemIcons.Warning, "Migration necessary.", + "This project needs to be migrated in order to work properly with the newest version. This will be done automatically.", + PopupButtons.Ok); + await Migrate(); + } + } + + private async Task Migrate() + { + SetUiState(false); + Invoke(new Action(() => loadingLabel.Text = "Migrating project...")); + + IEnumerable config = + await UpdateConfiguration.DownloadAsync(_configurationFileUrl, Project.Proxy); + + string projectDir = Path.Combine(Program.Path, "Projects", Project.Name); + string migrationDir = Path.Combine(projectDir, "migrate"); + var updateConfigFile = Path.Combine(projectDir, "updates.json"); + + if (!Directory.Exists(migrationDir)) + Directory.CreateDirectory(migrationDir); + + foreach (var entry in config) + { + if (entry.Operations == null) + continue; + + var packageFolder = Path.Combine(projectDir, entry.LiteralVersion); + var packageFile = Path.Combine(packageFolder, $"{Project.Guid}.zip"); + var extractedPackageDirectory = Path.Combine(packageFolder, Project.Guid); + + if (!File.Exists(packageFile)) + { + using (var wc = new WebClientWrapper()) + { + wc.DownloadProgressChanged += (o, e) => + { + Invoke(new Action(() => + loadingLabel.Text = + $"Downloading {entry.LiteralVersion} ({e.ProgressPercentage}%)")); + }; + await wc.DownloadFileTaskAsync(entry.UpdatePackageUri, packageFile); + } + } + + await Task.Factory.StartNew(() => + { + Invoke(new Action(() => loadingLabel.Text = $"Migrating package {entry.LiteralVersion}...")); + + using (var stream = File.OpenRead(packageFile)) + { + using (ZipFile zip = ZipFile.Read(stream)) + { + zip.ParallelDeflateThreshold = -1; + zip.ExtractAll(extractedPackageDirectory); + } + } + + File.Delete(packageFile); + + File.WriteAllText(Path.Combine(extractedPackageDirectory, "operations.json"), + Serializer.Serialize(entry.Operations)); + using (var newZip = new ZipFile()) + { + newZip.ParallelDeflateThreshold = -1; + newZip.UseZip64WhenSaving = Zip64Option.AsNecessary; + newZip.AddDirectory(extractedPackageDirectory); + newZip.Save(packageFile); + } + + Directory.Delete(extractedPackageDirectory, true); + entry.Operations = null; + + Invoke(new Action(() => loadingLabel.Text = "Signing package...")); + + using (var stream = File.Open(packageFile, FileMode.Open)) + { + entry.Signature = + Convert.ToBase64String(new RsaManager(Project.PrivateKey).SignData(stream)); + } + + var versionConfigFile = Path.Combine(projectDir, entry.LiteralVersion, "updates.json"); + File.WriteAllText(versionConfigFile, Serializer.Serialize(config)); + + Invoke(new Action(() => + { + loadingLabel.Text = $"Uploading package {entry.LiteralVersion} (0%)"; + cancelLabel.Visible = true; + })); + + _ftp.ProgressChanged += (o, e) => + { + Invoke( + new Action( + () => + loadingLabel.Text = + $"Uploading package {entry.LiteralVersion} ({e.PercentComplete}% | {e.BytesPerSecond / 1024}KiB/s)")); + }; + _ftp.UploadPackage(packageFile, entry.LiteralVersion); + }); + } + + await Task.Factory.StartNew(() => + { + Invoke(new Action(() => loadingLabel.Text = "Uploading configuration...")); + + File.WriteAllText(updateConfigFile, Serializer.Serialize(config)); + _ftp.UploadFile(updateConfigFile); + + Invoke(new Action(() => loadingLabel.Text = "Saving project...")); + Project.ConfigVersion = "v3"; + UpdateProject.SaveProject(Project.Path, Project); + }); + + InitializePackageItems(); + SetUiState(true); } private void readOnlyTextBox_KeyDown(object sender, KeyEventArgs e) @@ -1366,7 +1493,7 @@ private void ProgressChanged(object sender, TransferProgressEventArgs e) new Action( () => loadingLabel.Text = - $"Uploading... {$"{e.PercentComplete}% | {e.BytesPerSecond / 1024}KB/s"}")); + $"Uploading... {$"{e.PercentComplete}% | {e.BytesPerSecond / 1024}KiB/s"}")); if (_uploadCancelled) Invoke(new Action(() => { loadingLabel.Text = "Cancelling upload..."; })); diff --git a/nUpdate.Administration/UI/Dialogs/ProjectDialog.resx b/nUpdate.Administration/UI/Dialogs/ProjectDialog.resx index 8cbeb983..75d6df7d 100644 --- a/nUpdate.Administration/UI/Dialogs/ProjectDialog.resx +++ b/nUpdate.Administration/UI/Dialogs/ProjectDialog.resx @@ -125,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAD0 - EAAAAk1TRnQBSQFMAgEBBAEAAUgBBwFIAQcBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA + EAAAAk1TRnQBSQFMAgEBBAEAAVABBwFQAQcBEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA AwABIAMAAQEBAAEgBgABIP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AP8AYgADFgEeAx0BKQMf ASwDGgEkAxsBJgMjATMDOQFfAlQBVgGrAlkBXAHMAlkBXAHMAlkBXAHMA1MBqgMyAVADDAEQAwYBCAMA AQEDMAFMA0kBiQM9AWkDIQExAyABLgMdASoDGwEmAxgBIgMWAR4DEgEZAxABFQMMARADCQEMAwYBCAME @@ -200,7 +200,85 @@ AfABAwH/AQMB/wHHAv8B8AEHAf8BgwL/Cw== + + 17, 61 + + + 17, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHLSURBVDhPY6AK2F/PwLI/iSXjQCJzNwzX2zGcQcbIciC1 + ID1Q7QwMe+PYlU9Vay59v6fz/7vdHWA8O8MUBcPEQWpAakF6oNoZGHYlMLvfnOJ9BNmA5SWOcLyk0A7F + AJBakB6odgaGHfEsufeXZT94trnhPwxvafSD43XVHnBxEAapBemBamdg2BrDPHX//uV//99d9R+G764q + h+MzM9Pg4iAMUgvSA9XOwLA5innGz0vz/38+MRWOd3eEwvHmBl8UOZBakB6odgaGDVHMs7+dm/3/w5GJ + cAzSuKrcBUwvK3ZAkQOpBemBamdgWB3BPP/TyWn/3+zvgWOQZmQaGYPUgvRAtTMwLA9jXvzuUP//l7va + 8eLYDc7/9dfo/E/c6vEfpAeqnYFhSQjjslfAKHq6tQkv1luu9T/lXel//ZXa/0F6oNoZGOYHMK5+sqXx + /8MNtVhx9FLb/7oL1cE49HXaf71FGv/FJwm8Z5gjNBNswBRPxh0P1lX/v7+2CivWnaX63/F5EAZmmCxw + BmxAuyvj5DYXxqO4sFEe60vueu4vIKzzyPY/iBasZ3vF0MsLcQHRoJnnjNR97f8gGipCIshhm8mQyXoG + TIMBAwMAZ/TcCnoyco8AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHySURBVDhPrZHfS1NhGMefl7Pwshv/gCQsuvDSy0RhaiGV + QkqM0mWhg1IUDdGhmyE5naChRjLwWNmZbCWLTTJ/7Ggo5g+EhPwFwwUpKDKlwtGFPPUc3vOyWQqBX/jw + cp7n+3luDpxKVBsY1GKDZeKu5NSxpcFCLLE76pLDdYDxwoTzc9ZLr/fGWjAy6tBwWVLj0OfUoS45XAcY + MUvZa105U7EH3NUZgv7KtLgD1CWH6wDDRYayDeVBeMtvR51A43XBoPWKmBPUJYfrAEO3pW5VdR9iyIM6 + IU+NYKGnRMwJ6pLDdQC/SXr+a0nGH5+6BaOOfIHffi1uR11yuA7gM0mug0UX7k89FZDoqTFqr1KVHrfb + e1GLnxNZeAYgXTvgvSXJ32ef4a7aJiA59tVZ8TXhh4b7iHY7vmNsUjvgLpBeRT624/ZI84mEAqWoOMsw + Go1iecrZlT6ALO1A/02m7Pz5RZtDj49l3XcP1b6LGN2qRUdFATZlnnmvyRQ5l3m/BRrxq6/+n6y+MWNQ + vqDJA84knH9ZjORwHaDrKhsOD1px423dXyx77mCwN1mT3a3ncE42IXXJ4TpAcybrfGJk00dpyWGLio1F + SO4oZ/uOPPZF35HD9ePT8RBs+HMNOxtYsLUCjHz8X0HLDeZ9ZIbL/PtIAH4D5gvpVeW0o4AAAAAASUVO + RK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGNSURBVDhPxZG/S0JRGIa/y5Uc+gey1ZbmaJUCwyKKhoqQ + sB9DCNEQBUISakUaBRFpJA4O2RWURFBBtLoRBhXS0NYgGlSghEZF0RAnPzn3cC8VOAQdeDjwfe/zcuDA + nxzRBipxUmU+meDXJWw6yMqR7zCLDtUBjkxq7aW1db9yuEbKaVcNn7ldgTTHDGbRoTpAapw33Lh7M/KC + 4HwnIzCrUxRgFh2qAyTHVDN5YbrwELMTibijnxGxdrM5gll0qA6QGOU9ohj8JLkQkciFLIysd4rNEcyi + Q3WAmJHf/bj2k5dzDyPtGmLE7H2KHWbRoTpA1Mj73q585CmzxUAxZNHXbmGuQ7HDLDpUBwiP8P7nix3y + KG4wUJbfcjCLDtUBgsP8Xvl0kxRTzrrALDpUBwgMckKp+kX3iaW6wCw6VAfwD3Dhu7iD3EYXf+TY0EZi + Wg0j3tJMBDVUqg3eWoG7h0sWIlaSP1j4EUHbRN5Npm9UvyFbK3B2cdureu7sN1Y0ULQ1wquCBigtSy/4 + xwPwBQ9S2GP6zpJaAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHXSURBVDhPY6AK2F/PwLI/iSXjQCJzNwzX2zGcQcbIciC1 + ID1Q7QwMe+PYlU9Vay59v6fz/7vdHWA8O8MUBcPEQWpAakF6oNoZGHYlMLvfnOJ9BNmA5SWOcLyk0A7F + AJBakB6odgaGHfEsufeXZT94trnhPwxvafSD43XVHnBxEAapBemBamdg2BrDPHX//uV//99d9R+G764q + h+MzM9Pg4iAMUgvSA9XOwLA5innGz0vz/38+MRWOd3eEwvHmBl8UOZBakB6odgaGDVHMs7+dm/3/w5GJ + cAzSuKrcBUwvK3ZAkQOpBemBamdgWB3BPP/TyWn/3+zvgWOQZmQaGYPUgvRAtTMwLA9jXvzuUP//l7va + CeLmlQf/b9i+8T9ID1Q7A8OSEMZlr4BR9HRrE0EcNfvs/+g55/6X5SYcg2pnYJgfwLj6yZbG/w831GLg + 0ukb/gf1H0TB05/+/29evuW9Tuv5GLABUzwZdzxYV/3//toqDOzZvPX/pMf//2dd/f8/9iICF9/4/1+5 + 8vAZkH65VGPGeW0ujEexYfuwvJdKKdO+IGOLo///K6bMeiPgUpoPMoAfiMWBWIoYzBu1+CII8wRMTAPy + QXpJA2yBc2ayBsyG+J2BgQEArv7u+Dx4PIUAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJhSURBVDhPY6AJ4FilJKe6z6LdZq7HdJ+iwJLQ0NCksLCw + YCAw9/Pz44Uqww44V0gHm570fpC4s+D+6cuX7z998+YHCIPY0+bPX5WYmJgZFBSkAVWOBuYJ+xqe8Xih + tS/sz4Und/6//vjx/76DB8E0CN9+/vz/rjNnHqdlZFRgGjJHWEpklcop16th/8sOtf1/+eEDWFNPTw/c + AJDYhQcP/h8CGhITF5fj4eHBB9UNBFMEctSPm7833un8f+21nXBNLS0tcDYI33r27P+5+/f/T507d42X + l5cVVDcQ9PAul7/h/FtnudX/nddO/T9z9y4Yx8TEwNnI+PiFCw/d3NyiGBiauWcytPCcAWHtBzb/NWea + /decbvY/bkMG2EZ/f38UFzx//x5swIlHj344OTllMzDUc3kwVHGdUXhg+B+G9Sdb/F95ceN/U1PT/+Xl + 5f+Bfv0PjMr/SUlJ//Py8v4vWLny/4mnT3/Y29vnQpyfxe7BkMV6Ruye+n/NRoP/K8+sB9t2B+hXCwsL + MA3Dt4H4zM2b/89dv/4IKBcHMQAIpLyl4vnSxJ5O27MI7EyYk0GaYGwQBsldfvTo/4zZszebmJjYQ7Uz + MOjr6ws4ubiUH7t48dmTt29RNCHjp0C5i7duPXMBqgXpgWqHAG1tbX1g1HSCFLz7/BlDM0js9u3bz3x8 + fDpBaqHaUIGIiIgR0ORGYALaff3mzWcvX778CcI3gIaCxEByIDVQ5RgAlFFUWFhYbDg4OOJ4eHgquLm5 + 20EYxAaJgeSAatSBmB+IGYEYBbADsRAQSxHAIkDMwcDAwAgAUfzARVSDkZ8AAAAASUVORK5CYII= + + R0lGODlhMAAwAP8AAOj5+7nY4kOjncTc5i+jnEazrLHO2lfFu7TT3GnTybjk6kiXp9Ts8qXK1zaXmKfU @@ -553,140 +631,60 @@ ARhvDLxADPQnWDPQqUgGkI//MwAAgCyIfFYym24AAAAASUVORK5CYII= - - 17, 61 - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAB5UlEQVQ4T6XSX0hTYRjH8Wee - Y2AKmoKCF91EGv4FxQsvFCUhCQzSlFAklZgT8UI0JE04eqOhEIWL1sQ/5bacJoOplJOMMEg4CHknItMo - xZIZFUEX9fT+Bns5I7WgA5+9nPd9vu/NGTHzf6GlBhXUlw2qRRgI0YpINzKeCRY0aOlFvQpn9FtpjoPF - 2xzw9QfZLXlhQvuYwSwatOS7ptJinXphfahs2XiBq71YmmgtDLsAs2jQ0nPxI7T4nc1bO16NQ2Z7Lkkz - XaVyHzCLBi3N1ypg/bXh+smbbg7ZdHdIus0s9wGzaNCSt0aBBz/WRvnrG6vk66+UvFpZ2Blm0aAlT7UC - 9u+rdv68fFdC6O4oCa7OtqKwM8yiQUvTVxUY/bJyn/eXBiXExtUIs2jQ0pMqBR4HXt3hvYW+Y9V6znP2 - dAbXz5UyGrQ0cSUCnB/FJ/ow13usLFcaXw/c4OzJdEZTcfMk0djlCJh6P9vD257uQ9U4CjhzPDWo8pOZ - sx6d46R7cQc0HG+jlAQTDV00Pdua6WL/085DZT48y8W75X8ga5xO4jltzjWN9JWYXh8lpzVqL1GL+QYZ - 7woY66nemH1qjHbgglghSUj+Ky36bbI/nbGKdzRo//HJF3/blhM2aorUgyveieg3zn8k9o1oG/MAAAAA - SUVORK5CYII= + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHlSURBVDhPpdJfSFNhGMfxZ55jYAqagoIX3UQa/gXF + Cy8UJSEJDNKUUCSVmBPxQjQkTTh6o6EQhYvWxD/ltpwmg6mUk4wwSDgIeSci0yjFkhkVQRf19P4Gezkj + taADn72c932+780ZMfN/oaUGFdSXDapFGAjRikg3Mp4JFjRo6UW9Cmf0W2mOg8XbHPD1B9kteWFC+5jB + LBq05Lum0mKdemF9qGzZeIGrvViaaC0MuwCzaNDSc/EjtPidzVs7Xo1DZnsuSTNdpXIfMIsGLc3XKmD9 + teH6yZtuDtl0d0i6zSz3AbNo0JK3RoEHP9ZG+esbq+Trr5S8WlnYGWbRoCVPtQL276t2/rx8V0Lo7igJ + rs62orAzzKJBS9NXFRj9snKf95cGJcTG1QizaNDSkyoFHgde3eG9hb5j1XrOc/Z0BtfPlTIatDRxJQKc + H8Un+jDXe6wsVxpfD9zg7Ml0RlNx8yTR2OUImHo/28Pbnu5D1TgKOHM8Najyk5mzHp3jpHtxBzQcb6OU + BBMNXTQ925rpYv/TzkNlPjzLxbvlfyBrnE7iOW3ONY30lZheHyWnNWovUYv5BhnvChjrqd6YfWqMduCC + WCFJSP4rLfptsj+dsYp3NGj/8ckXf9uWEzZqitSDK96J6DfOfyT2jWgb8wAAAABJRU5ErkJggg== - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAACCUlEQVQ4T6XRXUhTcRjH8ee/ - c6DLkIigiyhCA6Fuostigb0QqKQlYYi2iQ3C6A3GsuSYgqsZvaBRDDyr7EymyWLrxSZbhUYvw4uoTGO4 - IIUiplQ0uqin8xudw84qb/rDZwf+z/P934yY+b9QwiGD/MAhu3Q+g2KnZL78mc6FBi3F98mwOnmi9Mbc - yGnOxLw5ftcGC+MeO9hFg5Zi9TKNNMjbJrvLR/MfCB7bbOo7vMnyAHbRoKVh/UfXPK0dSM9GFDZE2ypM - Qy3bzXvALhq0dKdOgp6fb4M/OBViQyrkNiWvNJn3gF00aCmyV4LL31+o/OVJjynm3W2KKOWWGXbRJNbZ - iMK1Evi/jft5fvSCCWHIXZb7akftltncVQ+/XCrSj4Ww0+AeCdTPTy/xp0SXCXH+1zAR7uDh1kZmReFb - Qjyk/hoJrmceneMP9zsXlIruZ83XzNlslg+uLZpQibZS3y4baB/1v2jm9ql/mgo7ORFYw9lZD3sP1XDH - lkV3A6WCKLDTBgPvo238Lnzyr94MNnBcLcnF/b5V/Pyag9GgpZIlgrp3iHvpoRaevnn8D69DdRzvLc7F - wTMr+Zlay9hFgxZnRdN60dtZJsYKdVWIca1dZBBfPCLmvVXilTFDgxYPLNYt0y0v1O4UZ/nrJJ/3iDFn - NVUVzNGgXfCwq1IMuOvFxsbq3zeWQ/QLcuUwAJjM/EMAAAAASUVORK5CYII= + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIJSURBVDhPpdFdSFNxGMfx579zoMuQiKCLKEIDoW6i + y2KBvRCopCVhiLaJDcLoDcay5JiCqxm9oFEMPKvsTKbJYuvFJluFRi/Di6hMY7gghSKmVDS6qKfzG53D + zipv+sNnB/7P8/3fjJj5v1DCIYP8wCG7dD6DYqdkvvyZzoUGLcX3ybA6eaL0xtzIac7EvDl+1wYL4x47 + 2EWDlmL1Mo00yNsmu8tH8x8IHtts6ju8yfIAdtGgpWH9R9c8rR1Iz0YUNkTbKkxDLdvNe8AuGrR0p06C + np9vgz84FWJDKuQ2Ja80mfeAXTRoKbJXgsvfX6j85UmPKebdbYoo5ZYZdtEk1tmIwrUS+L+N+3l+9IIJ + YchdlvtqR+2W2dxVD79cKtKPhbDT4B4J1M9PL/GnRJcJcf7XMBHu4OHWRmZF4VtCPKT+GgmuZx6d4w/3 + OxeUiu5nzdfM2WyWD64tmlCJtlLfLhtoH/W/aOb2qX+aCjs5EVjD2VkPew/VcMeWRXcDpYIosNMGA++j + bfwufPKv3gw2cFwtycX9vlX8/JqD0aClkiWCuneIe+mhFp6+efwPr0N1HO8tzsXBMyv5mVrL2EWDFmdF + 03rR21kmxgp1VYhxrV1kEF88Iua9VeKVMUODFg8s1i3TLS/U7hRn+eskn/eIMWc1VRXM0aBd8LCrUgy4 + 68XGxurfN5ZD9Aty5TAAmMz8QwAAAABJRU5ErkJggg== - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAABnklEQVQ4T6XTTyiDcRzH8e/j - eS6iHBywg8vksKtcRSlSUwqJ/D1oJQdRyp9sUpsoKTStUOah+ZPaCBMSRS0HN0koFGmEyIGv56P263ky - NVm99tTz+7x/lzVi5n+h7QYFlJ0GxaYZiLDnUkhPf6axoUFLW/UKmENdlpmHzX4OB13fPLZsg8h7bLBF - g5aCtQpt1ikFJyPWPf0Fs215grclx3ABtmjQ0rr2pWk+V5subvx2jgg4ioWlzkLxHrBFg5ZWq2UY/Tyd - /eAzH0ec+dqF0HijeA/YokFL/ioZ3O/Hk/x8MCoEXWWC3241nGGLBi0tV8rgeT3y8OPesIDQ157//VRb - cw1n2KJBSwsVMkw+HY7x/faggFj/1MMWDVqaK5dhOrw7xLcbzphgiwYteUvjQL3TfqLrld6YYItGtUhE - UyVxMH8VcPDlcndUWwVZ7DenCYEME6uJ9KASjVNmskQjRdLaxVInny92RKWaU/mtpuYHN1GItE96Y5Y0 - 4cyX9n/Tl0a3jgR60euJp/s6ohlckKRJ0Zj+CE1S1L9o7Ji+AJagUMYulKGeAAAAAElFTkSuQmCC + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGeSURBVDhPpdNPKINxHMfx7+N5LqIcHLCDy+Swq1xF + KVJTCon8PWglB1HKn2xSmygpNK1Q5qH5k9oIExJFLQc3SSgUaYTIga/no/breTI1Wb321PP7vH+XNWLm + f6HtBgWUnQbFphmIsOdSSE9/prGhQUtb9QqYQ12WmYfNfg4HXd88tmyDyHtssEWDloK1Cm3WKQUnI9Y9 + /QWzbXmCtyXHcAG2aNDSuvalaT5Xmy5u/HaOCDiKhaXOQvEesEWDllarZRj9PJ394DMfR5z52oXQeKN4 + D9iiQUv+Khnc78eT/HwwKgRdZYLfbjWcYYsGLS1XyuB5PfLw496wgNDXnv/9VFtzDWfYokFLCxUyTD4d + jvH99qCAWP/UwxYNWporl2E6vDvEtxvOmGCLBi15S+NAvdN+ouuV3phgi0a1SERTJXEwfxVw8OVyd1Rb + BVnsN6cJgQwTq4n0oBKNU2ayRCNF0trFUiefL3ZEpZpT+a2m5gc3UYi0T3pjljThzJf2f9OXRreOBHrR + 64mn+zqiGVyQpEnRmP4ITVLUv2jsmL4AlqBQxi6UoZ4AAAAASUVORK5CYII= - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAAB5UlEQVQ4T6XRX0hTYRjH8Wee - QzcZBl0EXXQjCgldSdBVKSwywXRiIXMjExljYRIrpUycimgkyMS/zDKYzVoli83+TTJLQ2FKCkIRomEK - iqhoBF3U4/sT9noOCxQ88Dkv532f73tziJn3hQaLVFA/FKl24X6UK40iWtozwY4GLb2/qkJi5G7K47WB - e7wabtjmsZ/Sie5jBrNo0FL4ikoDher5by1Zw9oLem+mSz03zuguwCwatPRWvISSWd+1ucWgi6NC1Rel - vooMuQ+YRYOWXlkVaP33vfcvz/g5asZfLkU6bXIfMIsGLQULFOj4M9XNm6OtUrjhkhR0ZenOMIsGLQXM - Cnh+T3h4fdgtIfSXG7dXnzNNd4ZZNGjpeb4C3Rtjbbwy2Cgh1q5amEWDlp5cVsC7+rGJl97V76r26RAH - Xr9kNGipJy8OfMviFy301+zK7Bnngq4JList/Oy47iB6ZIqDZz9D1fwjUBnjVnuAc5uGdNoXmM9WhdZO - 1n2xUPIRA7VkGt7M9VXw7Is7MS7U9nPzPLNjmtk6ucP5lTnx9qcIiee4LdXwsN5oGPmfdItzKaW445fW - 6RHmpOIHK4fPlZXiggThqHBsLw6ZvZMQb3LbxDfavT/KiWw6YOrqFCwHc9xih2gLWd04Qz1T2awAAAAA - SUVORK5CYII= - - - - 17, 17 - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHLSURBVDhPY6AK2F/PwLI/iSXjQCJzNwzX2zGcQcbIciC1 - ID1Q7QwMe+PYlU9Vay59v6fz/7vdHWA8O8MUBcPEQWpAakF6oNoZGHYlMLvfnOJ9BNmA5SWOcLyk0A7F - AJBakB6odgaGHfEsufeXZT94trnhPwxvafSD43XVHnBxEAapBemBamdg2BrDPHX//uV//99d9R+G764q - h+MzM9Pg4iAMUgvSA9XOwLA5innGz0vz/38+MRWOd3eEwvHmBl8UOZBakB6odgaGDVHMs7+dm/3/w5GJ - cAzSuKrcBUwvK3ZAkQOpBemBamdgWB3BPP/TyWn/3+zvgWOQZmQaGYPUgvRAtTMwLA9jXvzuUP//l7va - 8eLYDc7/9dfo/E/c6vEfpAeqnYFhSQjjslfAKHq6tQkv1luu9T/lXel//ZXa/0F6oNoZGOYHMK5+sqXx - /8MNtVhx9FLb/7oL1cE49HXaf71FGv/FJwm8Z5gjNBNswBRPxh0P1lX/v7+2CivWnaX63/F5EAZmmCxw - BmxAuyvj5DYXxqO4sFEe60vueu4vIKzzyPY/iBasZ3vF0MsLcQHRoJnnjNR97f8gGipCIshhm8mQyXoG - TIMBAwMAZ/TcCnoyco8AAAAASUVORK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHySURBVDhPrZHfS1NhGMefl7Pwshv/gCQsuvDSy0RhaiGV - QkqM0mWhg1IUDdGhmyE5naChRjLwWNmZbCWLTTJ/7Ggo5g+EhPwFwwUpKDKlwtGFPPUc3vOyWQqBX/jw - cp7n+3luDpxKVBsY1GKDZeKu5NSxpcFCLLE76pLDdYDxwoTzc9ZLr/fGWjAy6tBwWVLj0OfUoS45XAcY - MUvZa105U7EH3NUZgv7KtLgD1CWH6wDDRYayDeVBeMtvR51A43XBoPWKmBPUJYfrAEO3pW5VdR9iyIM6 - IU+NYKGnRMwJ6pLDdQC/SXr+a0nGH5+6BaOOfIHffi1uR11yuA7gM0mug0UX7k89FZDoqTFqr1KVHrfb - e1GLnxNZeAYgXTvgvSXJ32ef4a7aJiA59tVZ8TXhh4b7iHY7vmNsUjvgLpBeRT624/ZI84mEAqWoOMsw - Go1iecrZlT6ALO1A/02m7Pz5RZtDj49l3XcP1b6LGN2qRUdFATZlnnmvyRQ5l3m/BRrxq6/+n6y+MWNQ - vqDJA84knH9ZjORwHaDrKhsOD1px423dXyx77mCwN1mT3a3ncE42IXXJ4TpAcybrfGJk00dpyWGLio1F - SO4oZ/uOPPZF35HD9ePT8RBs+HMNOxtYsLUCjHz8X0HLDeZ9ZIbL/PtIAH4D5gvpVeW0o4AAAAAASUVO - RK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGNSURBVDhPxZG/S0JRGIa/y5Uc+gey1ZbmaJUCwyKKhoqQ - sB9DCNEQBUISakUaBRFpJA4O2RWURFBBtLoRBhXS0NYgGlSghEZF0RAnPzn3cC8VOAQdeDjwfe/zcuDA - nxzRBipxUmU+meDXJWw6yMqR7zCLDtUBjkxq7aW1db9yuEbKaVcNn7ldgTTHDGbRoTpAapw33Lh7M/KC - 4HwnIzCrUxRgFh2qAyTHVDN5YbrwELMTibijnxGxdrM5gll0qA6QGOU9ohj8JLkQkciFLIysd4rNEcyi - Q3WAmJHf/bj2k5dzDyPtGmLE7H2KHWbRoTpA1Mj73q585CmzxUAxZNHXbmGuQ7HDLDpUBwiP8P7nix3y - KG4wUJbfcjCLDtUBgsP8Xvl0kxRTzrrALDpUBwgMckKp+kX3iaW6wCw6VAfwD3Dhu7iD3EYXf+TY0EZi - Wg0j3tJMBDVUqg3eWoG7h0sWIlaSP1j4EUHbRN5Npm9UvyFbK3B2cdureu7sN1Y0ULQ1wquCBigtSy/4 - xwPwBQ9S2GP6zpJaAAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHXSURBVDhPY6AK2F/PwLI/iSXjQCJzNwzX2zGcQcbIciC1 - ID1Q7QwMe+PYlU9Vay59v6fz/7vdHWA8O8MUBcPEQWpAakF6oNoZGHYlMLvfnOJ9BNmA5SWOcLyk0A7F - AJBakB6odgaGHfEsufeXZT94trnhPwxvafSD43XVHnBxEAapBemBamdg2BrDPHX//uV//99d9R+G764q - h+MzM9Pg4iAMUgvSA9XOwLA5innGz0vz/38+MRWOd3eEwvHmBl8UOZBakB6odgaGDVHMs7+dm/3/w5GJ - cAzSuKrcBUwvK3ZAkQOpBemBamdgWB3BPP/TyWn/3+zvgWOQZmQaGYPUgvRAtTMwLA9jXvzuUP//l7va - CeLmlQf/b9i+8T9ID1Q7A8OSEMZlr4BR9HRrE0EcNfvs/+g55/6X5SYcg2pnYJgfwLj6yZbG/w831GLg - 0ukb/gf1H0TB05/+/29evuW9Tuv5GLABUzwZdzxYV/3//toqDOzZvPX/pMf//2dd/f8/9iICF9/4/1+5 - 8vAZkH65VGPGeW0ujEexYfuwvJdKKdO+IGOLo///K6bMeiPgUpoPMoAfiMWBWIoYzBu1+CII8wRMTAPy - QXpJA2yBc2ayBsyG+J2BgQEArv7u+Dx4PIUAAAAASUVORK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 - YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAJhSURBVDhPY6AJ4FilJKe6z6LdZq7HdJ+iwJLQ0NCksLCw - YCAw9/Pz44Uqww44V0gHm570fpC4s+D+6cuX7z998+YHCIPY0+bPX5WYmJgZFBSkAVWOBuYJ+xqe8Xih - tS/sz4Und/6//vjx/76DB8E0CN9+/vz/rjNnHqdlZFRgGjJHWEpklcop16th/8sOtf1/+eEDWFNPTw/c - AJDYhQcP/h8CGhITF5fj4eHBB9UNBFMEctSPm7833un8f+21nXBNLS0tcDYI33r27P+5+/f/T507d42X - l5cVVDcQ9PAul7/h/FtnudX/nddO/T9z9y4Yx8TEwNnI+PiFCw/d3NyiGBiauWcytPCcAWHtBzb/NWea - /decbvY/bkMG2EZ/f38UFzx//x5swIlHj344OTllMzDUc3kwVHGdUXhg+B+G9Sdb/F95ceN/U1PT/+Xl - 5f+Bfv0PjMr/SUlJ//Py8v4vWLny/4mnT3/Y29vnQpyfxe7BkMV6Ruye+n/NRoP/K8+sB9t2B+hXCwsL - MA3Dt4H4zM2b/89dv/4IKBcHMQAIpLyl4vnSxJ5O27MI7EyYk0GaYGwQBsldfvTo/4zZszebmJjYQ7Uz - MOjr6ws4ubiUH7t48dmTt29RNCHjp0C5i7duPXMBqgXpgWqHAG1tbX1g1HSCFLz7/BlDM0js9u3bz3x8 - fDpBaqHaUIGIiIgR0ORGYALaff3mzWcvX778CcI3gIaCxEByIDVQ5RgAlFFUWFhYbDg4OOJ4eHgquLm5 - 20EYxAaJgeSAatSBmB+IGYEYBbADsRAQSxHAIkDMwcDAwAgAUfzARVSDkZ8AAAAASUVORK5CYII= + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAABl0RVh0U29m + dHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHlSURBVDhPpdFfSFNhGMfxZ55DNxkGXQRddCMKCV1J + 0FUpLDLBdGIhcyMTGWNhEiulTJyKaCTIxL/MMpjNWiWLzf5NMktDYUoKQhGiYQqKqGgEXdTj+xP2eg4L + FDzwOS/nfZ/ve3OImfeFBotUUD8UqXbhfpQrjSJa2jPBjgYtvb+qQmLkbsrjtYF7vBpu2Oaxn9KJ7mMG + s2jQUviKSgOF6vlvLVnD2gt6b6ZLPTfO6C7ALBq09Fa8hJJZ37W5xaCLo0LVF6W+igy5D5hFg5ZeWRVo + /fe99y/P+Dlqxl8uRTptch8wiwYtBQsU6Pgz1c2bo61SuOGSFHRl6c4wiwYtBcwKeH5PeHh92C0h9Jcb + t1efM013hlk0aOl5vgLdG2NtvDLYKCHWrlqYRYOWnlxWwLv6sYmX3tXvqvbpEAdev2Q0aKknLw58y+IX + LfTX7MrsGeeCrgkuKy387LjuIHpkioNnP0PV/CNQGeNWe4Bzm4Z02heYz1aF1k7WfbFQ8hEDtWQa3sz1 + VfDsizsxLtT2c/M8s2Oa2Tq5w/mVOfH2pwiJ57gt1fCw3mgY+Z90i3Mppbjjl9bpEeak4gcrh8+VleKC + BOGocGwvDpm9kxBvctvEN9q9P8qJbDpg6uoULAdz3GKHaAtZ3ThDPVPZrAAAAABJRU5ErkJggg== diff --git a/nUpdate.Administration/UI/Dialogs/ProjectEditDialog.cs b/nUpdate.Administration/UI/Dialogs/ProjectEditDialog.cs index 42ac2ed1..eb5aeb38 100644 --- a/nUpdate.Administration/UI/Dialogs/ProjectEditDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/ProjectEditDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ProjectEditDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/UI/Dialogs/ProjectImportDialog.cs b/nUpdate.Administration/UI/Dialogs/ProjectImportDialog.cs index eabfb842..26c2606e 100644 --- a/nUpdate.Administration/UI/Dialogs/ProjectImportDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/ProjectImportDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ProjectImportDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.Designer.cs b/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.Designer.cs index 58bda17b..971057fe 100644 --- a/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.Designer.cs +++ b/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.Designer.cs @@ -32,7 +32,7 @@ private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProjectRemovalDialog)); this.projectsTreeView = new nUpdate.Administration.UI.Controls.ExplorerTreeView(); - this.line1 = new Line(); + this.line1 = new nUpdate.Internal.UI.Controls.Line(); this.label2 = new System.Windows.Forms.Label(); this.pictureBox1 = new System.Windows.Forms.PictureBox(); this.noProjectsLabel = new System.Windows.Forms.Label(); @@ -53,7 +53,7 @@ private void InitializeComponent() // // line1 // - this.line1.LineAlignment = Line.Alignment.Horizontal; + this.line1.LineAlignment = nUpdate.Internal.UI.Controls.Line.Alignment.Horizontal; this.line1.Location = new System.Drawing.Point(-6, 225); this.line1.Name = "line1"; this.line1.Size = new System.Drawing.Size(401, 10); diff --git a/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.cs b/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.cs index 605cb5d8..70a03a8a 100644 --- a/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ProjectRemovalDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.resx b/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.resx index 12df510c..2b7300c8 100644 --- a/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.resx +++ b/nUpdate.Administration/UI/Dialogs/ProjectRemovalDialog.resx @@ -118,7 +118,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - To remove a project from nUpdate Administration, uncheck the relating node above. This will only remove local project files, online packages and statistic entries will still be retained and must be removed previously. + To remove a project from nUpdate Administration, uncheck the relating node above. This will only remove local project files. Online packages and statistic entries will still be retained and must be removed previously. diff --git a/nUpdate.Administration/UI/Dialogs/StatisticsServerAddDialog.cs b/nUpdate.Administration/UI/Dialogs/StatisticsServerAddDialog.cs index b05ce300..60f0bf8a 100644 --- a/nUpdate.Administration/UI/Dialogs/StatisticsServerAddDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/StatisticsServerAddDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// StatisticsServerAddDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Windows.Forms; diff --git a/nUpdate.Administration/UI/Dialogs/StatisticsServerDialog.cs b/nUpdate.Administration/UI/Dialogs/StatisticsServerDialog.cs index 79458d95..b10b2b2e 100644 --- a/nUpdate.Administration/UI/Dialogs/StatisticsServerDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/StatisticsServerDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// StatisticsServerDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.Administration/UI/Dialogs/StatisticsServerEditDialog.cs b/nUpdate.Administration/UI/Dialogs/StatisticsServerEditDialog.cs index eae1baf9..3e2258ae 100644 --- a/nUpdate.Administration/UI/Dialogs/StatisticsServerEditDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/StatisticsServerEditDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// StatisticsServerEditDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Windows.Forms; diff --git a/nUpdate.Administration/UI/Dialogs/UpdatingInfoDialog.cs b/nUpdate.Administration/UI/Dialogs/UpdatingInfoDialog.cs index 3ce47601..b185411d 100644 --- a/nUpdate.Administration/UI/Dialogs/UpdatingInfoDialog.cs +++ b/nUpdate.Administration/UI/Dialogs/UpdatingInfoDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdatingInfoDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Administration/UI/Popups/Popup.cs b/nUpdate.Administration/UI/Popups/Popup.cs index 2da6e4a6..b5606809 100644 --- a/nUpdate.Administration/UI/Popups/Popup.cs +++ b/nUpdate.Administration/UI/Popups/Popup.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// Popup.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/UI/Popups/PopupButtons.cs b/nUpdate.Administration/UI/Popups/PopupButtons.cs index cbefad30..d7125582 100644 --- a/nUpdate.Administration/UI/Popups/PopupButtons.cs +++ b/nUpdate.Administration/UI/Popups/PopupButtons.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// PopupButtons.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Administration.UI.Popups { diff --git a/nUpdate.Administration/UI/Popups/PopupDialog.cs b/nUpdate.Administration/UI/Popups/PopupDialog.cs index c958ae2a..685ad5b0 100644 --- a/nUpdate.Administration/UI/Popups/PopupDialog.cs +++ b/nUpdate.Administration/UI/Popups/PopupDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// PopupDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Administration/nUpdate.Administration.csproj b/nUpdate.Administration/nUpdate.Administration.csproj index e2f53a1c..45e219a5 100644 --- a/nUpdate.Administration/nUpdate.Administration.csproj +++ b/nUpdate.Administration/nUpdate.Administration.csproj @@ -28,6 +28,7 @@ prompt 4 true + false AnyCPU @@ -37,6 +38,7 @@ TRACE prompt 4 + false LocalIntranet @@ -51,13 +53,11 @@ Trade-Updater-Logo-v3.ico - - ..\packages\DotNetZip.1.10.1\lib\net20\DotNetZip.dll - True + + ..\packages\DotNetZip.1.13.3\lib\net40\DotNetZip.dll - - ..\packages\FCTB.2.16.11.0\lib\FastColoredTextBox.dll - True + + ..\packages\FCTB.2.16.24\lib\FastColoredTextBox.dll ..\packages\Microsoft.Bcl.Async.1.0.168\lib\net40\Microsoft.Threading.Tasks.dll @@ -73,11 +73,9 @@ ..\packages\MySql.Data.6.9.9\lib\net40\MySql.Data.dll - True - - ..\packages\Newtonsoft.Json.9.0.1\lib\net40\Newtonsoft.Json.dll - True + + ..\packages\Newtonsoft.Json.12.0.1\lib\net40\Newtonsoft.Json.dll ..\nUpdate.Administration.TransferInterface\bin\Debug\nUpdate.Administration.TransferInterface.dll @@ -86,7 +84,6 @@ ..\packages\starksoft.aspen.1.1.0\lib\net40\starksoft.aspen.dll - True @@ -608,6 +605,7 @@ + diff --git a/nUpdate.Administration/packages.config b/nUpdate.Administration/packages.config index bcbafb41..1a00891e 100644 --- a/nUpdate.Administration/packages.config +++ b/nUpdate.Administration/packages.config @@ -1,11 +1,12 @@  + - - + + - + \ No newline at end of file diff --git a/nUpdate.Client.GuiInterface/IProgressReporter.cs b/nUpdate.Client.GuiInterface/IProgressReporter.cs index 4a0223f4..7192901c 100644 --- a/nUpdate.Client.GuiInterface/IProgressReporter.cs +++ b/nUpdate.Client.GuiInterface/IProgressReporter.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// IProgressReporter.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Client.GuiInterface/Properties/AssemblyInfo.cs b/nUpdate.Client.GuiInterface/Properties/AssemblyInfo.cs index 7151913d..06ec7bde 100644 --- a/nUpdate.Client.GuiInterface/Properties/AssemblyInfo.cs +++ b/nUpdate.Client.GuiInterface/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// AssemblyInfo.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System.Reflection; using System.Runtime.InteropServices; @@ -37,5 +38,5 @@ // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.3.1.0")] -[assembly: AssemblyFileVersion("3.3.1.0")] +[assembly: AssemblyVersion("3.4.1.0")] +[assembly: AssemblyFileVersion("3.4.1.0")] diff --git a/nUpdate.Client.GuiInterface/ServiceProviderAttribute.cs b/nUpdate.Client.GuiInterface/ServiceProviderAttribute.cs index dbd2532a..b8e5109c 100644 --- a/nUpdate.Client.GuiInterface/ServiceProviderAttribute.cs +++ b/nUpdate.Client.GuiInterface/ServiceProviderAttribute.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// ServiceProviderAttribute.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System; @@ -17,7 +18,7 @@ public ServiceProviderAttribute(Type serviceType) { if (serviceType == null) throw new ArgumentNullException(nameof(serviceType)); - if (!typeof (IServiceProvider).IsAssignableFrom(serviceType)) + if (!typeof(IServiceProvider).IsAssignableFrom(serviceType)) throw new ArgumentException("Implementation of IServiceProvider is missing.", nameof(serviceType)); ServiceType = serviceType; } diff --git a/nUpdate.Internal/Core/Architecture.cs b/nUpdate.Internal/Core/Architecture.cs index 349865b0..86bb3918 100644 --- a/nUpdate.Internal/Core/Architecture.cs +++ b/nUpdate.Internal/Core/Architecture.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// Architecture.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Internal.Core { diff --git a/nUpdate.Internal/Core/ConnectionManager.cs b/nUpdate.Internal/Core/ConnectionManager.cs index 714cee39..b7295e10 100644 --- a/nUpdate.Internal/Core/ConnectionManager.cs +++ b/nUpdate.Internal/Core/ConnectionManager.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// ConnectionManager.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using nUpdate.Internal.Core.Win32; diff --git a/nUpdate.Internal/Core/DevelopmentalStage.cs b/nUpdate.Internal/Core/DevelopmentalStage.cs index dfbcb737..2d0218ba 100644 --- a/nUpdate.Internal/Core/DevelopmentalStage.cs +++ b/nUpdate.Internal/Core/DevelopmentalStage.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// DevelopmentalStage.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Internal.Core { diff --git a/nUpdate.Internal/Core/Extensions.cs b/nUpdate.Internal/Core/Extensions.cs index 94027335..6d5d30f6 100644 --- a/nUpdate.Internal/Core/Extensions.cs +++ b/nUpdate.Internal/Core/Extensions.cs @@ -1,4 +1,7 @@ -using System.IO; +// Extensions.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System.IO; namespace nUpdate.Internal.Core { @@ -12,4 +15,4 @@ public static void Empty(this DirectoryInfo directory) subDirectory.Delete(true); } } -} +} \ No newline at end of file diff --git a/nUpdate.Internal/Core/IDeepCopy.cs b/nUpdate.Internal/Core/IDeepCopy.cs index b4300c01..5f455bf5 100644 --- a/nUpdate.Internal/Core/IDeepCopy.cs +++ b/nUpdate.Internal/Core/IDeepCopy.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// IDeepCopy.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Internal.Core { diff --git a/nUpdate.Internal/Core/IconHelper.cs b/nUpdate.Internal/Core/IconHelper.cs index a3765fcd..c7fecbb3 100644 --- a/nUpdate.Internal/Core/IconHelper.cs +++ b/nUpdate.Internal/Core/IconHelper.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// IconHelper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Internal/Core/Localization/LocalizationHelper.cs b/nUpdate.Internal/Core/Localization/LocalizationHelper.cs index 40805b76..f1d75887 100644 --- a/nUpdate.Internal/Core/Localization/LocalizationHelper.cs +++ b/nUpdate.Internal/Core/Localization/LocalizationHelper.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// LocalizationHelper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -16,6 +17,7 @@ internal class LocalizationHelper internal static CultureInfo[] IntegratedCultures => new[] { new CultureInfo("de-AT"), new CultureInfo("de-CH"), new CultureInfo("de-DE"), new CultureInfo("zh-CN"), + new CultureInfo("it-IT"), new CultureInfo("en") }; @@ -72,8 +74,7 @@ internal static IEnumerable GetLocalizedEnumerationValues(LocalizationPr internal static bool IsIntegratedCulture(CultureInfo cultureInfo, Dictionary localizationFilePaths) { - string localizationFilePath; - localizationFilePaths.TryGetValue(cultureInfo, out localizationFilePath); + localizationFilePaths.TryGetValue(cultureInfo, out var localizationFilePath); return IntegratedCultures.Contains(cultureInfo) || localizationFilePath != null; } } diff --git a/nUpdate.Internal/Core/Localization/LocalizationProperties.cs b/nUpdate.Internal/Core/Localization/LocalizationProperties.cs index 44a1414e..15e330c8 100644 --- a/nUpdate.Internal/Core/Localization/LocalizationProperties.cs +++ b/nUpdate.Internal/Core/Localization/LocalizationProperties.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// LocalizationProperties.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Internal.Core.Localization { diff --git a/nUpdate.Internal/Core/Localization/it-IT.json b/nUpdate.Internal/Core/Localization/it-IT.json new file mode 100644 index 00000000..6a764e77 --- /dev/null +++ b/nUpdate.Internal/Core/Localization/it-IT.json @@ -0,0 +1,63 @@ +{ + "CancelButtonText": "Annulla", + "ContinueButtonText": "Continua", + "InstallButtonText": "Installa", + "CloseButtonText": "Chiudi", + "UpdateSearchDialogHeader": "Ricerca aggiornamenti...", + "NewUpdateDialogMultipleUpdatesHeader": "{0} aggiornamenti disponibili.", + "NewUpdateDialogSingleUpdateHeader": "{0} nuovo aggiornamento disponibile.", + "NewUpdateDialogInfoText": "New updates can be downloaded for {0}.", + "NewUpdateDialogAvailableVersionsText": "Versioni disponibili: {0}", + "NewUpdateDialogCurrentVersionText": "Versione corrente: {0}", + "NewUpdateDialogSizeText": "Dimensione del pacchetto: {0}", + "NewUpdateDialogChangelogText": "Changelog:", + "NewUpdateDialogAccessText": "Accessi:", + "NewUpdateDialogRegistryAccessText": "Registro", + "NewUpdateDialogFilesAccessText": "File system", + "NewUpdateDialogProcessesAccessText": "Processi", + "NewUpdateDialogServicesAccessText": "Servizi", + "NoUpdateDialogHeader": "Non ci sono aggiornamenti disponibili.", + "NoUpdateDialogInfoText": "L'applicazione è già aggiornata.", + "UpdateDownloadDialogLoadingHeader": "Download degli aggiornamenti...", + "UpdateDownloadDialogLoadingInfo": "Attendere mentre gli aggiornamenti\nsono in download... ({0}%)", + "InstallerExtractingFilesText": "\"Estrazione dei file...\"", + "InstallerCopyingText": "\"Copia {0}...\"", + "InstallerInitializingErrorCaption": "\"Errore durante l'inizializzaione dei dati.\"", + "InstallerUpdatingErrorCaption": "\"Errore durante l'aggiornamento dell'applicazione.\"", + "InstallerFileInUseError": + "Impossibile sovrascrivere il file '{0}' perché in uso da un altro processo. Terminare tutte le applicazioni che bloccano il processo e premere \"OK\".", + "FileRenamingOperationText": "\"Rinomina il file \"{0}\" in \"{1}\"...\"", + "FileDeletingOperationText": "\"Rimozione del file \"{0}\"...\"", + "RegistrySubKeyCreateOperationText": "\"Creazione della chiave di registro \"{0}\"...\"", + "RegistrySubKeyDeleteOperationText": "\"Rimozione della chiave di registro \"{0}\"...\"", + "RegistryNameValuePairSetValueOperationText": "\"Impostazione di \"{0}\" nel registro in \"{1}\"...\"", + "RegistryNameValuePairDeleteValueOperationText": "\"Elimnazione di nome-valore \"{0}\"...\"", + "ProcessStartOperationText": "\"Avvio del processo \"{0}\"...\"", + "ProcessStopOperationText": "\"Terminazione del processo \"{0}\"...\"", + "ServiceStartOperationText": "\"Avvio del servizio \"{0}\"...\"", + "ServiceStopOperationText": "\"Terminazione del servizio \"{0}\"...\"", + "UpdateSearchErrorCaption": "Errore durante la ricerca degli aggiornamenti.", + "UnfulfilledRequirementErrorCaption": "Dipendenze insoddisfatte.", + "UnfulfilledRequirementErrorText": + "L'installazione di alcuni aggiornamenti non può essere completata a causa della mancanza delle seguenti dipendenze:", + "OperatingSystemText": "Sistema operativo:", + "DotNetFrameworkText": ".NET Framework:", + "RequiredVersionText": "Versione richiesta:", + "PackageValidityCheckErrorCaption": "Errore durante la verifica della firma del pacchetto.", + "PackageNotFoundErrorText": "Il pacchetto non è stato trovato.", + "InvalidSignatureErrorCaption": "Firma non valida del pacchetto.", + "SignatureNotMatchingErrorText": + "nUpdate eliminerà i pacchetti non riconosciuti senza possibilità di recupero.", + "InvalidSignatureErrorText": "La firma del pacchetto non è una firma RSA valida.", + "SearchProcessRunningExceptionText": "È già in corso la ricerca di aggiornamenti.", + "DownloadingProcessRunningExceptionText": "È già in corso il download di un pacchetto.", + "NetworkConnectionExceptionText": "Nessuna connessione ad Internet disponibile.", + "PackageSizeCalculationExceptionText": + "Impossibile calcolare le dimensioni del pacchetto. Il pacchetto dell'aggiornamento potrebbe non essere presente.", + "InvalidJsonExceptionText": + "Il file contenete le informazioni di aggiornamento non è un file JSON valido. Le informazioni non possono essere processate.", + "StatisticsScriptExceptionText": + "Errore durante il trasferimento dei dati al server delle statistiche. Comunicare il seguente errore allo sviluppatore. Risposta dallo script PHP: {0}", + "PackageFileNotFoundExceptionText": "Il pacchetto dell'aggiornamento \"{0}\" non è stato trovato.", + "MainFolderCreationExceptionText": "Impossibile creare la cartella principale. {0}" +} \ No newline at end of file diff --git a/nUpdate.Internal/Core/Operations/Operation.cs b/nUpdate.Internal/Core/Operations/Operation.cs index 8d30461b..6713fc2c 100644 --- a/nUpdate.Internal/Core/Operations/Operation.cs +++ b/nUpdate.Internal/Core/Operations/Operation.cs @@ -1,6 +1,10 @@ -// Copyright © Dominic Beger 2017 +// Operation.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 +using Newtonsoft.Json; using System; +using System.ComponentModel; +using System.IO; namespace nUpdate.Internal.Core.Operations { @@ -34,6 +38,9 @@ public Operation(OperationArea area, OperationMethod method, string value, objec /// public object Value2 { get; set; } + [DefaultValue(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] + public bool ExecuteBeforeReplacingFiles { get; set; } /// /// Gets the operation area and method from a given tag. /// @@ -68,6 +75,7 @@ public static Tuple GetOperation(object areaTag) case "ExecuteScript": return new Tuple(OperationArea.Scripts, OperationMethod.Execute); } + return null; } @@ -90,6 +98,7 @@ public static string GetOperationTag(Operation operation) case OperationMethod.Rename: return "RenameFile"; } + break; case OperationArea.Registry: switch (operation.Method) @@ -103,6 +112,7 @@ public static string GetOperationTag(Operation operation) case OperationMethod.DeleteValue: return "DeleteRegistryValue"; } + break; case OperationArea.Processes: switch (operation.Method) @@ -112,6 +122,7 @@ public static string GetOperationTag(Operation operation) case OperationMethod.Stop: return "TerminateProcess"; } + break; case OperationArea.Services: switch (operation.Method) @@ -121,6 +132,7 @@ public static string GetOperationTag(Operation operation) case OperationMethod.Stop: return "StopService"; } + break; case OperationArea.Scripts: switch (operation.Method) @@ -128,8 +140,10 @@ public static string GetOperationTag(Operation operation) case OperationMethod.Execute: return "ExecuteScript"; } + break; } + return null; } } diff --git a/nUpdate.Internal/Core/Operations/OperationArea.cs b/nUpdate.Internal/Core/Operations/OperationArea.cs index d1d47d62..6b0dd171 100644 --- a/nUpdate.Internal/Core/Operations/OperationArea.cs +++ b/nUpdate.Internal/Core/Operations/OperationArea.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// OperationArea.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.ComponentModel; @@ -9,10 +10,19 @@ namespace nUpdate.Internal.Core.Operations /// public enum OperationArea { - [Description("NewUpdateDialogFilesAccessText")] Files, - [Description("NewUpdateDialogRegistryAccessText")] Registry, - [Description("NewUpdateDialogProcessesAccessText")] Processes, - [Description("NewUpdateDialogServicesAccessText")] Services, - [Description("NewUpdateDialogCodeExecutionAccessText")] Scripts + [Description("NewUpdateDialogFilesAccessText")] + Files, + + [Description("NewUpdateDialogRegistryAccessText")] + Registry, + + [Description("NewUpdateDialogProcessesAccessText")] + Processes, + + [Description("NewUpdateDialogServicesAccessText")] + Services, + + [Description("NewUpdateDialogCodeExecutionAccessText")] + Scripts } } \ No newline at end of file diff --git a/nUpdate.Internal/Core/Operations/OperationMethod.cs b/nUpdate.Internal/Core/Operations/OperationMethod.cs index f376af9c..ffb5452f 100644 --- a/nUpdate.Internal/Core/Operations/OperationMethod.cs +++ b/nUpdate.Internal/Core/Operations/OperationMethod.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// OperationMethod.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Internal.Core.Operations { diff --git a/nUpdate.Internal/Core/RolloutCondition.cs b/nUpdate.Internal/Core/RolloutCondition.cs new file mode 100644 index 00000000..299ceb16 --- /dev/null +++ b/nUpdate.Internal/Core/RolloutCondition.cs @@ -0,0 +1,26 @@ +// RolloutCondition.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System; + +namespace nUpdate.Internal.Core +{ + [Serializable] + public class RolloutCondition + { + public RolloutCondition() + { + } + + public RolloutCondition(string key, string value, bool isNegative = false) + { + Key = key; + Value = value; + IsNegativeCondition = isNegative; + } + + public string Key { get; set; } + public string Value { get; set; } + public bool IsNegativeCondition { get; set; } + } +} \ No newline at end of file diff --git a/nUpdate.Internal/Core/RolloutConditionMode.cs b/nUpdate.Internal/Core/RolloutConditionMode.cs new file mode 100644 index 00000000..f317e4e7 --- /dev/null +++ b/nUpdate.Internal/Core/RolloutConditionMode.cs @@ -0,0 +1,11 @@ +// RolloutConditionMode.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +namespace nUpdate.Internal.Core +{ + public enum RolloutConditionMode + { + AtLeastOne = 0, + All = 1 + } +} \ No newline at end of file diff --git a/nUpdate.Internal/Core/RsaManager.cs b/nUpdate.Internal/Core/RsaManager.cs index 51e1c963..00748c93 100644 --- a/nUpdate.Internal/Core/RsaManager.cs +++ b/nUpdate.Internal/Core/RsaManager.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// RsaManager.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.IO; diff --git a/nUpdate.Internal/Core/Serializer.cs b/nUpdate.Internal/Core/Serializer.cs index 0cf40907..fc2c170e 100644 --- a/nUpdate.Internal/Core/Serializer.cs +++ b/nUpdate.Internal/Core/Serializer.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// Serializer.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.IO; using System.Text; diff --git a/nUpdate.Internal/Core/SizeHelper.cs b/nUpdate.Internal/Core/SizeHelper.cs index d4d3ae47..bc0c00d5 100644 --- a/nUpdate.Internal/Core/SizeHelper.cs +++ b/nUpdate.Internal/Core/SizeHelper.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// SizeHelper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.IO; @@ -24,6 +25,7 @@ public static bool HasEnoughSpace(double packageSize, out double necessaryBytesT necessaryBytesToFree = 0; return true; } + necessaryBytesToFree = Math.Abs(packageSize * 2 - drive.AvailableFreeSpace); // Multiply this value with 2 because the files are copied during the installation, so we have download + installation (copying) return false; diff --git a/nUpdate.Internal/Core/SystemInformation.cs b/nUpdate.Internal/Core/SystemInformation.cs index 3b6b376c..9768506a 100644 --- a/nUpdate.Internal/Core/SystemInformation.cs +++ b/nUpdate.Internal/Core/SystemInformation.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// SystemInformation.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Linq; @@ -45,6 +46,7 @@ public static string OperatingSystemName case 3: return "Windows 8.1"; } + break; case 10: @@ -53,6 +55,7 @@ public static string OperatingSystemName case 0: return "Windows 10"; } + break; } diff --git a/nUpdate.Internal/Core/UriConnector.cs b/nUpdate.Internal/Core/UriConnector.cs index 98c27131..bfc18fd9 100644 --- a/nUpdate.Internal/Core/UriConnector.cs +++ b/nUpdate.Internal/Core/UriConnector.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// UriConnector.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Internal/Core/WebClientWrapper.cs b/nUpdate.Internal/Core/WebClientWrapper.cs index ebbc2a65..01e8d76b 100644 --- a/nUpdate.Internal/Core/WebClientWrapper.cs +++ b/nUpdate.Internal/Core/WebClientWrapper.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// WebClientWrapper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Net; diff --git a/nUpdate.Internal/Core/Win32/NativeMethods.cs b/nUpdate.Internal/Core/Win32/NativeMethods.cs index ca8f67b3..12493a25 100644 --- a/nUpdate.Internal/Core/Win32/NativeMethods.cs +++ b/nUpdate.Internal/Core/Win32/NativeMethods.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// NativeMethods.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Runtime.InteropServices; diff --git a/nUpdate.Internal/Properties/AssemblyInfo.cs b/nUpdate.Internal/Properties/AssemblyInfo.cs index b19bf735..2ae6bccb 100644 --- a/nUpdate.Internal/Properties/AssemblyInfo.cs +++ b/nUpdate.Internal/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// AssemblyInfo.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Reflection; using System.Runtime.CompilerServices; @@ -38,8 +39,11 @@ // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.3.1.0")] -[assembly: AssemblyFileVersion("3.3.1.0")] +[assembly: AssemblyVersion("3.4.1.0")] +[assembly: AssemblyFileVersion("3.4.1.0")] [assembly: InternalsVisibleTo("nUpdate.Shared")] [assembly: InternalsVisibleTo("nUpdate.ProvideTAP")] -[assembly: InternalsVisibleTo("nUpdate.WithoutTAP")] \ No newline at end of file +[assembly: InternalsVisibleTo("nUpdate.WithoutTAP")] +[assembly: InternalsVisibleTo("nUpdate.UpdateInstaller")] +[assembly: InternalsVisibleTo("nUpdate.WPFUserInterface")] +[assembly: InternalsVisibleTo("nUpdate.WPFUpdateInstaller")] \ No newline at end of file diff --git a/nUpdate.Internal/Properties/Resources.Designer.cs b/nUpdate.Internal/Properties/Resources.Designer.cs index 53a8e29a..ec7c81ee 100644 --- a/nUpdate.Internal/Properties/Resources.Designer.cs +++ b/nUpdate.Internal/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace nUpdate.Internal.Properties { // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -63,9 +63,9 @@ internal Resources() { /// /// Sucht eine lokalisierte Ressource vom Typ System.Byte[]. /// - internal static byte[] Ionic_Zip { + internal static byte[] DotNetZip { get { - object obj = ResourceManager.GetObject("Ionic_Zip", resourceCulture); + object obj = ResourceManager.GetObject("DotNetZip", resourceCulture); return ((byte[])(obj)); } } @@ -99,5 +99,15 @@ internal static byte[] nUpdate_UpdateInstaller_Client_GuiInterface { return ((byte[])(obj)); } } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Byte[]. + /// + internal static byte[] nUpdate_UpdateInstaller_pdb { + get { + object obj = ResourceManager.GetObject("nUpdate_UpdateInstaller_pdb", resourceCulture); + return ((byte[])(obj)); + } + } } } diff --git a/nUpdate.Internal/Properties/Resources.resx b/nUpdate.Internal/Properties/Resources.resx index 33789466..f6cacb00 100644 --- a/nUpdate.Internal/Properties/Resources.resx +++ b/nUpdate.Internal/Properties/Resources.resx @@ -118,16 +118,19 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - ..\Resources\Ionic.Zip.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\DotNetZip.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ..\Resources\Newtonsoft.Json.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - ..\Resources\nUpdate UpdateInstaller.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + ..\Resources\nUpdate.UpdateInstaller.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ..\Resources\nUpdate.UpdateInstaller.Client.GuiInterface.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\nUpdate.UpdateInstaller.pdb;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/nUpdate.Internal/Resources/DotNetZip.dll b/nUpdate.Internal/Resources/DotNetZip.dll new file mode 100644 index 00000000..35d04839 Binary files /dev/null and b/nUpdate.Internal/Resources/DotNetZip.dll differ diff --git a/nUpdate.Internal/Resources/Newtonsoft.Json.dll b/nUpdate.Internal/Resources/Newtonsoft.Json.dll index 55d537fb..554e99de 100644 Binary files a/nUpdate.Internal/Resources/Newtonsoft.Json.dll and b/nUpdate.Internal/Resources/Newtonsoft.Json.dll differ diff --git a/nUpdate.Internal/Resources/nUpdate UpdateInstaller.exe b/nUpdate.Internal/Resources/nUpdate UpdateInstaller.exe index 758c78cb..b8b57fbd 100644 Binary files a/nUpdate.Internal/Resources/nUpdate UpdateInstaller.exe and b/nUpdate.Internal/Resources/nUpdate UpdateInstaller.exe differ diff --git a/nUpdate.Internal/Resources/nUpdate UpdateInstaller.pdb b/nUpdate.Internal/Resources/nUpdate UpdateInstaller.pdb new file mode 100644 index 00000000..943fc9e1 Binary files /dev/null and b/nUpdate.Internal/Resources/nUpdate UpdateInstaller.pdb differ diff --git a/nUpdate.Internal/Resources/nUpdate.UpdateInstaller.Client.GuiInterface.dll b/nUpdate.Internal/Resources/nUpdate.UpdateInstaller.Client.GuiInterface.dll index 6bcf5690..8d01141e 100644 Binary files a/nUpdate.Internal/Resources/nUpdate.UpdateInstaller.Client.GuiInterface.dll and b/nUpdate.Internal/Resources/nUpdate.UpdateInstaller.Client.GuiInterface.dll differ diff --git a/nUpdate.Internal/Resources/nUpdate.UpdateInstaller.exe b/nUpdate.Internal/Resources/nUpdate.UpdateInstaller.exe new file mode 100644 index 00000000..060306d3 Binary files /dev/null and b/nUpdate.Internal/Resources/nUpdate.UpdateInstaller.exe differ diff --git a/nUpdate.Internal/Resources/nUpdate.UpdateInstaller.pdb b/nUpdate.Internal/Resources/nUpdate.UpdateInstaller.pdb new file mode 100644 index 00000000..9c9253bc Binary files /dev/null and b/nUpdate.Internal/Resources/nUpdate.UpdateInstaller.pdb differ diff --git a/nUpdate.Internal/UI/Controls/BottomPanel.cs b/nUpdate.Internal/UI/Controls/BottomPanel.cs index a787779c..6bf4691a 100644 --- a/nUpdate.Internal/UI/Controls/BottomPanel.cs +++ b/nUpdate.Internal/UI/Controls/BottomPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// BottomPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.ComponentModel; using System.Drawing; diff --git a/nUpdate.Internal/UI/Controls/Line.cs b/nUpdate.Internal/UI/Controls/Line.cs index 170b2282..236d56f0 100644 --- a/nUpdate.Internal/UI/Controls/Line.cs +++ b/nUpdate.Internal/UI/Controls/Line.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// Line.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Drawing; using System.Windows.Forms; diff --git a/nUpdate.Internal/UI/Popups/Popup.cs b/nUpdate.Internal/UI/Popups/Popup.cs index e63c7608..977c75fe 100644 --- a/nUpdate.Internal/UI/Popups/Popup.cs +++ b/nUpdate.Internal/UI/Popups/Popup.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// Popup.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; @@ -25,7 +26,7 @@ public static DialogResult ShowPopup(Icon popupIcon, string title, string infoMe Buttons = buttons, StartPosition = FormStartPosition.CenterParent }; - + return popupWindow.ShowDialog(Form.ActiveForm); } @@ -47,7 +48,7 @@ public static DialogResult ShowPopup(Icon popupIcon, string title, Exception ex, StartPosition = FormStartPosition.CenterParent, Exception = ex }; - + return popupWindow.ShowDialog(Form.ActiveForm); } diff --git a/nUpdate.Internal/UI/Popups/PopupButtons.cs b/nUpdate.Internal/UI/Popups/PopupButtons.cs index 09427183..3fb491dd 100644 --- a/nUpdate.Internal/UI/Popups/PopupButtons.cs +++ b/nUpdate.Internal/UI/Popups/PopupButtons.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// PopupButtons.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Internal.UI.Popups { diff --git a/nUpdate.Internal/UI/Popups/PopupDialog.cs b/nUpdate.Internal/UI/Popups/PopupDialog.cs index 8f20a413..fa5e69f8 100644 --- a/nUpdate.Internal/UI/Popups/PopupDialog.cs +++ b/nUpdate.Internal/UI/Popups/PopupDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2017 +// PopupDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.Internal/nUpdate.Internal.csproj b/nUpdate.Internal/nUpdate.Internal.csproj index e54c6d44..37656f27 100644 --- a/nUpdate.Internal/nUpdate.Internal.csproj +++ b/nUpdate.Internal/nUpdate.Internal.csproj @@ -64,9 +64,8 @@ MinimumRecommendedRules.ruleset - - False - ..\packages\Newtonsoft.Json.10.0.3\lib\net40\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.12.0.2\lib\net40\Newtonsoft.Json.dll True @@ -79,6 +78,8 @@ + + @@ -129,28 +130,37 @@ - + + - - PreserveNewest - + + + + + + + + + + - - PreserveNewest - + - + + + + diff --git a/nUpdate.Internal/packages.config b/nUpdate.Internal/packages.config index 03c70925..5710d21a 100644 --- a/nUpdate.Internal/packages.config +++ b/nUpdate.Internal/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/nUpdate.ProvideTAP/Extensions.cs b/nUpdate.ProvideTAP/Extensions.cs index 8fff3ee4..721561c3 100644 --- a/nUpdate.ProvideTAP/Extensions.cs +++ b/nUpdate.ProvideTAP/Extensions.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// Extensions.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Net; diff --git a/nUpdate.ProvideTAP/Properties/AssemblyInfo.cs b/nUpdate.ProvideTAP/Properties/AssemblyInfo.cs index e0a5349f..548ed8f2 100644 --- a/nUpdate.ProvideTAP/Properties/AssemblyInfo.cs +++ b/nUpdate.ProvideTAP/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// AssemblyInfo.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Reflection; using System.Runtime.InteropServices; @@ -35,5 +36,5 @@ // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, // indem Sie "*" wie unten gezeigt eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.3.1.0")] -[assembly: AssemblyFileVersion("3.3.1.0")] +[assembly: AssemblyVersion("3.4.1.0")] +[assembly: AssemblyFileVersion("3.4.1.0")] diff --git a/nUpdate.ProvideTAP/UI/Dialogs/BaseDialog.cs b/nUpdate.ProvideTAP/UI/Dialogs/BaseDialog.cs index 3d24afb1..f3dd8f89 100644 --- a/nUpdate.ProvideTAP/UI/Dialogs/BaseDialog.cs +++ b/nUpdate.ProvideTAP/UI/Dialogs/BaseDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// BaseDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Windows.Forms; using nUpdate.Updating; diff --git a/nUpdate.ProvideTAP/UI/Dialogs/NewUpdateDialog.cs b/nUpdate.ProvideTAP/UI/Dialogs/NewUpdateDialog.cs index 4ec28fb7..cf7a59c6 100644 --- a/nUpdate.ProvideTAP/UI/Dialogs/NewUpdateDialog.cs +++ b/nUpdate.ProvideTAP/UI/Dialogs/NewUpdateDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// NewUpdateDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -26,8 +27,6 @@ internal NewUpdateDialog() InitializeComponent(); } - public List OperationAreas { get; set; } - internal static void AddShieldToButton(Button btn) { const int bcmSetshield = 0x160C; @@ -109,16 +108,6 @@ private void NewUpdateDialog_Load(object sender, EventArgs e) } AddShieldToButton(installButton); - - if (OperationAreas == null || OperationAreas.Count == 0) - { - accessLabel.Text = $"{_lp.NewUpdateDialogAccessText} -"; - _allowCancel = true; - return; - } - - accessLabel.Text = - $"{_lp.NewUpdateDialogAccessText} {string.Join(", ", LocalizationHelper.GetLocalizedEnumerationValues(_lp, OperationAreas.Cast().GroupBy(item => item).Select(item => item.First()).ToArray()))}"; _allowCancel = true; } } diff --git a/nUpdate.ProvideTAP/UI/Dialogs/NoUpdateFoundDialog.cs b/nUpdate.ProvideTAP/UI/Dialogs/NoUpdateFoundDialog.cs index 4dc54f4d..3ee2d902 100644 --- a/nUpdate.ProvideTAP/UI/Dialogs/NoUpdateFoundDialog.cs +++ b/nUpdate.ProvideTAP/UI/Dialogs/NoUpdateFoundDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// NoUpdateFoundDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.ProvideTAP/UI/Dialogs/UpdateDownloadDialog.cs b/nUpdate.ProvideTAP/UI/Dialogs/UpdateDownloadDialog.cs index 0ac5d3be..b7d4b88d 100644 --- a/nUpdate.ProvideTAP/UI/Dialogs/UpdateDownloadDialog.cs +++ b/nUpdate.ProvideTAP/UI/Dialogs/UpdateDownloadDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdateDownloadDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.ProvideTAP/UI/Dialogs/UpdateSearchDialog.cs b/nUpdate.ProvideTAP/UI/Dialogs/UpdateSearchDialog.cs index 2d6462f3..2532088a 100644 --- a/nUpdate.ProvideTAP/UI/Dialogs/UpdateSearchDialog.cs +++ b/nUpdate.ProvideTAP/UI/Dialogs/UpdateSearchDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdateSearchDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.ProvideTAP/Updating/UpdateConfiguration.cs b/nUpdate.ProvideTAP/Updating/UpdateConfiguration.cs index deb8d733..85816bfe 100644 --- a/nUpdate.ProvideTAP/Updating/UpdateConfiguration.cs +++ b/nUpdate.ProvideTAP/Updating/UpdateConfiguration.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdateConfiguration.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; diff --git a/nUpdate.ProvideTAP/Updating/UpdateManager.cs b/nUpdate.ProvideTAP/Updating/UpdateManager.cs index f15eb6b1..b1700588 100644 --- a/nUpdate.ProvideTAP/Updating/UpdateManager.cs +++ b/nUpdate.ProvideTAP/Updating/UpdateManager.cs @@ -1,6 +1,8 @@ -// Copyright � Dominic Beger 2018 +// UpdateManager.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; @@ -8,6 +10,7 @@ using System.Threading.Tasks; using nUpdate.Exceptions; using nUpdate.Internal.Core; +using nUpdate.Internal.Core.Operations; using nUpdate.UpdateEventArgs; namespace nUpdate.Updating @@ -18,32 +21,6 @@ namespace nUpdate.Updating /// public partial class UpdateManager { - /// - /// Releases all managed and unmanaged resources used by the current -instance. - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// - /// true to release both managed and unmanaged resources; false to release only - /// unmanaged resources. - /// - protected virtual void Dispose(bool disposing) - { - if (!disposing || _disposed) - return; - - _searchCancellationTokenSource.Dispose(); - _downloadCancellationTokenSource.Dispose(); - _disposed = true; - } - /// /// Downloads the available update packages from the server. /// @@ -222,7 +199,7 @@ public bool SearchForUpdates() SearchTimeout); var result = new UpdateResult(configuration, CurrentVersion, - IncludeAlpha, IncludeBeta); + IncludeAlpha, IncludeBeta, Conditions); if (!result.UpdatesFound) return false; @@ -238,6 +215,9 @@ public bool SearchForUpdates() throw new SizeCalculationException(_lp.PackageSizeCalculationExceptionText); updatePackageSize += newPackageSize.Value; + if (updateConfiguration.Operations == null) continue; + if (_packageOperations == null) + _packageOperations = new Dictionary>(); _packageOperations.Add(new UpdateVersion(updateConfiguration.LiteralVersion), updateConfiguration.Operations); } @@ -273,7 +253,7 @@ await UpdateConfiguration.DownloadAsync(UpdateConfigurationFileUri, HttpAuthenti _searchCancellationTokenSource.Token.ThrowIfCancellationRequested(); var result = new UpdateResult(configuration, CurrentVersion, - IncludeAlpha, IncludeBeta); + IncludeAlpha, IncludeBeta, Conditions); if (!result.UpdatesFound) return false; @@ -290,6 +270,9 @@ await UpdateConfiguration.DownloadAsync(UpdateConfigurationFileUri, HttpAuthenti throw new SizeCalculationException(_lp.PackageSizeCalculationExceptionText); updatePackageSize += newPackageSize.Value; + if (updateConfiguration.Operations == null) continue; + if (_packageOperations == null) + _packageOperations = new Dictionary>(); _packageOperations.Add(new UpdateVersion(updateConfiguration.LiteralVersion), updateConfiguration.Operations); } diff --git a/nUpdate.ProvideTAP/Updating/UpdaterUI.cs b/nUpdate.ProvideTAP/Updating/UpdaterUI.cs index 47dbd3da..f42afd88 100644 --- a/nUpdate.ProvideTAP/Updating/UpdaterUI.cs +++ b/nUpdate.ProvideTAP/Updating/UpdaterUI.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdaterUI.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.ProvideTAP/app.config b/nUpdate.ProvideTAP/app.config index e03ea0a5..870df23a 100644 --- a/nUpdate.ProvideTAP/app.config +++ b/nUpdate.ProvideTAP/app.config @@ -1,4 +1,5 @@  + diff --git a/nUpdate.ProvideTAP/packages.config b/nUpdate.ProvideTAP/packages.config index f70161ba..2164004d 100644 --- a/nUpdate.ProvideTAP/packages.config +++ b/nUpdate.ProvideTAP/packages.config @@ -1,4 +1,5 @@  + diff --git a/nUpdate.Shared/Core/HostApplicationOptions.cs b/nUpdate.Shared/Core/HostApplicationOptions.cs new file mode 100644 index 00000000..86e5660b --- /dev/null +++ b/nUpdate.Shared/Core/HostApplicationOptions.cs @@ -0,0 +1,12 @@ +// HostApplicationOptions.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +namespace nUpdate.Shared.Core +{ + public enum HostApplicationOptions + { + CloseAndRestart, + Close, + None + } +} \ No newline at end of file diff --git a/nUpdate.Shared/Core/nUpdateVersionAttribute.cs b/nUpdate.Shared/Core/nUpdateVersionAttribute.cs index 712d7adb..800f5c7a 100644 --- a/nUpdate.Shared/Core/nUpdateVersionAttribute.cs +++ b/nUpdate.Shared/Core/nUpdateVersionAttribute.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// nUpdateVersionAttribute.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Shared/Exceptions/PackageDeleteException.cs b/nUpdate.Shared/Exceptions/PackageDeleteException.cs index b7f92ae9..10eff062 100644 --- a/nUpdate.Shared/Exceptions/PackageDeleteException.cs +++ b/nUpdate.Shared/Exceptions/PackageDeleteException.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// PackageDeleteException.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Shared/Exceptions/SizeCalculationException.cs b/nUpdate.Shared/Exceptions/SizeCalculationException.cs index cf2978d9..09474e09 100644 --- a/nUpdate.Shared/Exceptions/SizeCalculationException.cs +++ b/nUpdate.Shared/Exceptions/SizeCalculationException.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// SizeCalculationException.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Shared/Exceptions/StatisticsException.cs b/nUpdate.Shared/Exceptions/StatisticsException.cs index 765dee93..3ccf6a10 100644 --- a/nUpdate.Shared/Exceptions/StatisticsException.cs +++ b/nUpdate.Shared/Exceptions/StatisticsException.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// StatisticsException.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Shared/UpdateEventArgs/UpdateDownloadProgressChangedEventArgs.cs b/nUpdate.Shared/UpdateEventArgs/UpdateDownloadProgressChangedEventArgs.cs index 2d3cd9bc..d95c8979 100644 --- a/nUpdate.Shared/UpdateEventArgs/UpdateDownloadProgressChangedEventArgs.cs +++ b/nUpdate.Shared/UpdateEventArgs/UpdateDownloadProgressChangedEventArgs.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdateDownloadProgressChangedEventArgs.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.Shared/Updating/UpdateArgument.cs b/nUpdate.Shared/Updating/UpdateArgument.cs index f7ff26c9..d651f94c 100644 --- a/nUpdate.Shared/Updating/UpdateArgument.cs +++ b/nUpdate.Shared/Updating/UpdateArgument.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdateArgument.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Updating { diff --git a/nUpdate.Shared/Updating/UpdateArgumentExecutionOptions.cs b/nUpdate.Shared/Updating/UpdateArgumentExecutionOptions.cs index 68314b5f..14792d22 100644 --- a/nUpdate.Shared/Updating/UpdateArgumentExecutionOptions.cs +++ b/nUpdate.Shared/Updating/UpdateArgumentExecutionOptions.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdateArgumentExecutionOptions.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.Updating { diff --git a/nUpdate.Shared/Updating/UpdateConfiguration.cs b/nUpdate.Shared/Updating/UpdateConfiguration.cs index 2d817f8f..3c2ec722 100644 --- a/nUpdate.Shared/Updating/UpdateConfiguration.cs +++ b/nUpdate.Shared/Updating/UpdateConfiguration.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdateConfiguration.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -13,7 +14,7 @@ namespace nUpdate.Updating { [Serializable] - public partial class UpdateConfiguration : IDeepCopy + public partial class UpdateConfiguration { /// /// The architecture settings of the update package. @@ -37,8 +38,16 @@ public partial class UpdateConfiguration : IDeepCopy public bool NecessaryUpdate { get; set; } /// - /// The operations of the update package. + /// Gets or sets the rollout condition mode used for selecting the updates. /// + public RolloutConditionMode RolloutConditionMode { get; set; } + + /// + /// Gets or sets the rollout conditions which contain additional specifications that the client must meet in order to + /// receive an update. + /// + public List RolloutConditions { get; set; } + public List Operations { get; set; } /// @@ -71,15 +80,6 @@ public partial class UpdateConfiguration : IDeepCopy /// public int VersionId { get; set; } - /// - /// Performs a deep copy of the current -instance. - /// - /// Returns a copy of the given -instance. - public UpdateConfiguration DeepCopy() - { - return (UpdateConfiguration) MemberwiseClone(); - } - /// /// Downloads the update configurations from the server. /// diff --git a/nUpdate.Shared/Updating/UpdateManager.cs b/nUpdate.Shared/Updating/UpdateManager.cs index 1b0eae27..27411a5d 100644 --- a/nUpdate.Shared/Updating/UpdateManager.cs +++ b/nUpdate.Shared/Updating/UpdateManager.cs @@ -1,4 +1,5 @@ -// Copyright � Dominic Beger 2018 +// UpdateManager.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -18,6 +19,7 @@ using nUpdate.Internal.Core.Localization; using nUpdate.Internal.Core.Operations; using nUpdate.Internal.Properties; +using nUpdate.Shared.Core; namespace nUpdate.Updating { @@ -31,10 +33,11 @@ public partial class UpdateManager : IDisposable private readonly Dictionary _packageFilePaths = new Dictionary(); - private readonly Dictionary> _packageOperations = - new Dictionary>(); + private Dictionary> _packageOperations; // obsolete private bool _disposed; + private readonly ManualResetEvent _searchManualResetEvent = new ManualResetEvent(false); + private CancellationTokenSource _downloadCancellationTokenSource = new CancellationTokenSource(); private CultureInfo _languageCulture = new CultureInfo("en"); @@ -115,13 +118,6 @@ public UpdateManager(Uri updateConfigurationFileUri, string publicKey, /// public List Arguments { get; set; } - /// - /// Gets or sets a value indicating whether the host application should be closed when the nUpdate UpdateInstaller is - /// started, or - /// not. - /// - public bool CloseHostApplication { get; set; } = true; - /// /// Gets or sets the paths to the files that contain the localized strings of their corresponding /// . @@ -138,6 +134,11 @@ public UpdateManager(Uri updateConfigurationFileUri, string publicKey, /// public string CustomInstallerUiAssemblyPath { get; set; } + /// + /// Gets or sets the update installer options for the host application. + /// + public HostApplicationOptions HostApplicationOptions { get; set; } + /// /// Gets or sets the HTTP(S) authentication credentials. /// @@ -158,6 +159,11 @@ public UpdateManager(Uri updateConfigurationFileUri, string publicKey, /// public bool IncludeCurrentPcIntoStatistics { get; set; } = true; + /// + /// Gets or sets the additional conditions that determine whether an update should be loaded or not. + /// + public List> Conditions { get; set; } + /// /// Gets or sets the culture of the language to use. /// @@ -198,12 +204,6 @@ public CultureInfo LanguageCulture /// public string PublicKey { get; } - /// - /// Gets or sets a value indicating whether the host application should be restarted once the update installation has - /// completed, or not. - /// - public bool RestartHostApplication { get; set; } = true; - /// /// Gets or sets the timeout in milliseconds that should be used when searching for updates. /// @@ -272,7 +272,6 @@ public void CancelSearchAsync() private void Cleanup() { _packageFilePaths.Clear(); - _packageOperations.Clear(); } private Uri ConvertPackageUri(Uri updatePackageUri) @@ -326,11 +325,29 @@ public void DeletePackages() } /// - /// Finalizes an instance of the class. + /// Releases all managed and unmanaged resources used by the current -instance. /// - ~UpdateManager() + public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// + /// true to release both managed and unmanaged resources; false to release only + /// unmanaged resources. + /// + protected virtual void Dispose(bool disposing) + { + if (!disposing || _disposed) + return; + + _searchCancellationTokenSource.Dispose(); + _downloadCancellationTokenSource.Dispose(); + _disposed = true; } private double? GetUpdatePackageSize(Uri packageUri) @@ -378,34 +395,30 @@ private void Initialize() public void InstallPackage() { var installerDirectory = Path.Combine(Path.GetTempPath(), "nUpdate Installer"); - var dotNetZipPath = Path.Combine(installerDirectory, "Ionic.Zip.dll"); + var dotNetZipPath = Path.Combine(installerDirectory, "DotNetZip.dll"); var guiInterfacePath = Path.Combine(installerDirectory, "nUpdate.UpdateInstaller.Client.GuiInterface.dll"); var jsonNetPath = Path.Combine(installerDirectory, "Newtonsoft.Json.dll"); var installerFilePath = Path.Combine(installerDirectory, "nUpdate UpdateInstaller.exe"); + var unpackerAppPdbPath = Path.Combine(installerDirectory, "nUpdate UpdateInstaller.pdb"); if (Directory.Exists(installerDirectory)) Directory.Delete(installerDirectory, true); Directory.CreateDirectory(installerDirectory); - File.WriteAllBytes(dotNetZipPath, Resources.Ionic_Zip); + File.WriteAllBytes(dotNetZipPath, Resources.DotNetZip); File.WriteAllBytes(guiInterfacePath, Resources.nUpdate_UpdateInstaller_Client_GuiInterface); File.WriteAllBytes(jsonNetPath, Resources.Newtonsoft_Json); File.WriteAllBytes(installerFilePath, Resources.nUpdate_UpdateInstaller); + File.WriteAllBytes(unpackerAppPdbPath, Resources.nUpdate_UpdateInstaller_pdb); - //if (!File.Exists(unpackerAppPdbPath)) - // File.WriteAllBytes(unpackerAppPath, Resources.nUpdate_UpdateInstaller_Pdb); - - var installerUiAssemblyPath = UseCustomInstallerUserInterface - ? $"\"{CustomInstallerUiAssemblyPath}\"" - : string.Empty; string[] args = { $"\"{string.Join("%", _packageFilePaths.Select(item => item.Value))}\"", $"\"{Application.StartupPath}\"", $"\"{Application.ExecutablePath}\"", $"\"{Application.ProductName}\"", - $"\"{Convert.ToBase64String(Encoding.UTF8.GetBytes(Serializer.Serialize(_packageOperations)))}\"", - $"\"{installerUiAssemblyPath}\"", + _packageOperations == null ? string.Empty : $"\"{Convert.ToBase64String(Encoding.UTF8.GetBytes(Serializer.Serialize(_packageOperations)))}\"", + $"\"{(UseCustomInstallerUserInterface ? CustomInstallerUiAssemblyPath : string.Empty)}\"", _lp.InstallerExtractingFilesText, _lp.InstallerCopyingText, _lp.FileDeletingOperationText, @@ -421,8 +434,7 @@ public void InstallPackage() _lp.InstallerUpdatingErrorCaption, _lp.InstallerInitializingErrorCaption, $"\"{Convert.ToBase64String(Encoding.UTF8.GetBytes(Serializer.Serialize(Arguments)))}\"", - $"\"{CloseHostApplication}\"", - $"\"{RestartHostApplication}\"", + $"\"{HostApplicationOptions}\"", $"\"{_lp.InstallerFileInUseError}\"" }; @@ -447,7 +459,7 @@ public void InstallPackage() return; } - if (CloseHostApplication) + if (HostApplicationOptions != HostApplicationOptions.None) TerminateApplication(); } diff --git a/nUpdate.Shared/Updating/UpdateResult.cs b/nUpdate.Shared/Updating/UpdateResult.cs index ec38fba9..78784e1d 100644 --- a/nUpdate.Shared/Updating/UpdateResult.cs +++ b/nUpdate.Shared/Updating/UpdateResult.cs @@ -1,10 +1,14 @@ -// Copyright © Dominic Beger 2018 +// UpdateResult.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using nUpdate.Internal.Core; +[assembly: InternalsVisibleTo("nUpdate.Test")] + namespace nUpdate.Updating { internal class UpdateResult @@ -15,7 +19,7 @@ internal class UpdateResult /// Initializes a new instance of the class. /// public UpdateResult(IEnumerable packageConfigurations, UpdateVersion currentVersion, - bool isAlphaWished, bool isBetaWished) + bool isAlphaWished, bool isBetaWished, List> conditions = null) { if (packageConfigurations != null) { @@ -23,7 +27,7 @@ public UpdateResult(IEnumerable packageConfigurations, Upda foreach ( var config in packageConfigurations.Where( - item => new UpdateVersion(item.LiteralVersion) > currentVersion || item.NecessaryUpdate) + item => new UpdateVersion(item.LiteralVersion) > currentVersion) .Where( config => new UpdateVersion(config.LiteralVersion).DevelopmentalStage == @@ -47,24 +51,77 @@ var config in config.Architecture == Architecture.X64 && !is64Bit) continue; - if (new UpdateVersion(config.LiteralVersion) <= currentVersion) + if (!CheckConditions(conditions, config)) + { continue; + } + _newUpdateConfigurations.Add(config); } - - var highestVersion = - UpdateVersion.GetHighestUpdateVersion( - _newUpdateConfigurations.Select(item => new UpdateVersion(item.LiteralVersion))); - _newUpdateConfigurations.RemoveAll( - item => new UpdateVersion(item.LiteralVersion) < highestVersion && !item.NecessaryUpdate); - _newUpdateConfigurations.Sort( - (x, y) => new UpdateVersion(x.LiteralVersion).CompareTo(new UpdateVersion(y.LiteralVersion))); } + var highestVersion = + UpdateVersion.GetHighestUpdateVersion( + _newUpdateConfigurations.Select(item => new UpdateVersion(item.LiteralVersion))); + _newUpdateConfigurations.RemoveAll( + item => new UpdateVersion(item.LiteralVersion) < highestVersion && !item.NecessaryUpdate); + _newUpdateConfigurations.Sort( + (x, y) => new UpdateVersion(x.LiteralVersion).CompareTo(new UpdateVersion(y.LiteralVersion))); + UpdatesFound = _newUpdateConfigurations.Count != 0; } + internal bool CheckConditions(List> clientConditions, + UpdateConfiguration config) + { + if (config.RolloutConditions != null && config.RolloutConditions.Any()) + { + if (clientConditions != null && clientConditions.Any()) + { + // If any negative condition is met, this update does not interest us. + if (clientConditions.Any(x => config.RolloutConditions.Where(n => n.IsNegativeCondition) + .Any(c => + c.Key == x.Key && + string.Equals(c.Value, x.Value, + StringComparison.CurrentCultureIgnoreCase)))) + return false; + + switch (config.RolloutConditionMode) + { + // If no positive condition is met, this update does not interest us. + case RolloutConditionMode.AtLeastOne: + if (config.RolloutConditions.Where(n => !n.IsNegativeCondition).All(x => + !clientConditions.Any(c => c.Key == x.Key && + string.Equals(c.Value, x.Value, + StringComparison.CurrentCultureIgnoreCase)))) + return false; + break; + + // If not all positive conditions are met, this update does not interest us. + case RolloutConditionMode.All: + if (config.RolloutConditions.Where(n => !n.IsNegativeCondition).Any(x => + !clientConditions.Any(c => c.Key == x.Key && string.Equals(c.Value, x.Value, + StringComparison.CurrentCultureIgnoreCase)))) + return false; + break; + + default: + throw new ArgumentOutOfRangeException(nameof(config), + "Invalid rollout condition mode."); + } + } + else + { + // This should be discussed again as it may be senseful that a user with no local key for a positive condition may eventually also receive the update. + if (config.RolloutConditions.Any(c => !c.IsNegativeCondition)) + return false; + } + } + + return true; + } + /// /// Returns all new configurations. /// diff --git a/nUpdate.Shared/Updating/UpdateVersion.cs b/nUpdate.Shared/Updating/UpdateVersion.cs index bd1daf72..44517f4c 100644 --- a/nUpdate.Shared/Updating/UpdateVersion.cs +++ b/nUpdate.Shared/Updating/UpdateVersion.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdateVersion.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -182,7 +183,7 @@ public int CompareTo(UpdateVersion version) /// public override bool Equals(object obj) { - return obj.GetType() == typeof(UpdateVersion) && ToString() == obj.ToString(); + return obj != null && (obj.GetType() == typeof(UpdateVersion) && ToString() == obj.ToString()); } /// diff --git a/nUpdate.Shared/Updating/UpdaterUI.cs b/nUpdate.Shared/Updating/UpdaterUI.cs index 7a0673b7..7e814c73 100644 --- a/nUpdate.Shared/Updating/UpdaterUI.cs +++ b/nUpdate.Shared/Updating/UpdaterUI.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdaterUI.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Threading; using nUpdate.Internal.Core.Localization; @@ -8,12 +9,14 @@ namespace nUpdate.Updating public sealed partial class UpdaterUI { private readonly LocalizationProperties _lp; +#pragma warning disable IDE0051 // Nicht verwendete private Member entfernen private bool _active; +#pragma warning restore IDE0051 // Nicht verwendete private Member entfernen /// /// Initializes a new instance of the -class. /// - /// The instance of the to handle over. + /// The instance of the to handle over. /// The synchronization context to use. public UpdaterUI(UpdateManager updateManager, SynchronizationContext context) : this(updateManager, context, false) @@ -45,7 +48,7 @@ public UpdaterUI(UpdateManager updateManager, SynchronizationContext context, bo internal SynchronizationContext Context { get; set; } /// - /// Gets or sets the given instance of the -class. + /// Gets or sets the given instance of the -class. /// internal UpdateManager UpdateManager { get; set; } diff --git a/nUpdate.Shared/nUpdate.Shared.projitems b/nUpdate.Shared/nUpdate.Shared.projitems index 8525883f..702120b3 100644 --- a/nUpdate.Shared/nUpdate.Shared.projitems +++ b/nUpdate.Shared/nUpdate.Shared.projitems @@ -9,6 +9,7 @@ nUpdate.Shared + diff --git a/nUpdate.Test/ConditionsAllTest.cs b/nUpdate.Test/ConditionsAllTest.cs new file mode 100644 index 00000000..0fbd92f1 --- /dev/null +++ b/nUpdate.Test/ConditionsAllTest.cs @@ -0,0 +1,227 @@ +// ConditionsAllTest.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using nUpdate.Internal.Core; +using nUpdate.Updating; + +namespace nUpdate.Test +{ + [TestClass] + public class ConditionsAllTest + { + private List> _clientConditions; + private List _updateConfigs; + + [TestInitialize] + public void InitTest() + { + _clientConditions = new List>(); + _updateConfigs = new List(); + } + + [TestMethod] + [TestCategory("Conditions.Mode.All.FirstScenario")] + public void ConditionCheckWithFirstScenarioMustWorkWell_1() + { + SetFirstConfigScenario(); + _clientConditions.Add(new KeyValuePair("R", "east")); + _clientConditions.Add(new KeyValuePair("CNR", "23654")); + + var sutWishedUpdates = new List {"1.2.0.0"}; + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + [TestMethod] + [TestCategory("Conditions.Mode.All.FirstScenario")] + public void ConditionCheckWithFirstScenarioMustWorkWell_2() + { + SetFirstConfigScenario(); // 1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("R", "east")); + _clientConditions.Add(new KeyValuePair("CNR", "36448")); + + var sutWishedUpdates = new List {"1.3.0.0"}; + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions.Mode.All.FirstScenario")] + public void ConditionCheckWithFirstScenarioMustWorkWell_3() + { + SetFirstConfigScenario(); // 1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("R", "east")); + _clientConditions.Add(new KeyValuePair("CNR", "36447")); + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(0, sutUpdateResults.Count); + } + + [TestMethod] + [TestCategory("Conditions.Mode.All.SecondScenario")] + public void ConditionCheckWithSecondScenarioMustWorkWell_1() + { + SetSecondConfigScenario(); // 1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("CC", "3")); + + var sutWishedUpdates = new List {"1.2.0.0"}; + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + [TestMethod] + [TestCategory("Conditions.Mode.All")] + public void ConditionCheckWithoutClientValuesButWithRemoteValuesMustWorkWell() + { + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.All, new List + {new RolloutCondition("P", "secure")})); + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.All, new List())); + + var sutWishedUpdates = new List {"1.3.0.0"}; + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + [TestMethod] + [TestCategory("Conditions.Mode.All")] + public void ConditionCheckWithoutClientValuesAndWithoutRemoteValuesMustWorkWell() + { + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.All, new List())); + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.All, new List())); + + var sutWishedUpdates = new List {"1.2.0.0", "1.3.0.0"}; + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + private void SetFirstConfigScenario() + { + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.All, new List + {new RolloutCondition("R", "east"), new RolloutCondition("CNR", "23654")})); + + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.All, new List + {new RolloutCondition("R", "east"), new RolloutCondition("CNR", "36448")})); + } + + private void SetSecondConfigScenario() + { + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.All, new List + {new RolloutCondition("CC", "3"), new RolloutCondition("CNR", "23654", true)})); + + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.All, new List + { + new RolloutCondition("CC", "1"), new RolloutCondition("CC", "3"), new RolloutCondition("CC", "4", true) + })); + } + + private UpdateConfiguration CreateConfig(string version, RolloutConditionMode conditionMode, + List conditions, bool isNecessary = true) + { + var config = new UpdateConfiguration + { + LiteralVersion = version, + RolloutConditionMode = conditionMode, + RolloutConditions = conditions, + NecessaryUpdate = isNecessary + }; + return config; + } + } +} \ No newline at end of file diff --git a/nUpdate.Test/ConditionsAtLeastOneTest.cs b/nUpdate.Test/ConditionsAtLeastOneTest.cs new file mode 100644 index 00000000..b71f4382 --- /dev/null +++ b/nUpdate.Test/ConditionsAtLeastOneTest.cs @@ -0,0 +1,579 @@ +// ConditionsAtLeastOneTest.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using nUpdate.Internal.Core; +using nUpdate.Updating; + +namespace nUpdate.Test +{ + [TestClass] + public class ConditionsAtLeastOneTest + { + private List> _clientConditions; + private List _updateConfigs; + + [TestInitialize] + public void InitTest() + { + _clientConditions = new List>(); + _updateConfigs = new List(); + } + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne.FirstScenario")] + public void ConditionCheckWithFirstScenarioMustWorkWell_1() + { + SetFirstConfigScenario(); + _clientConditions.Add(new KeyValuePair("R", "east")); + _clientConditions.Add(new KeyValuePair("CNR", "23654")); + + var sutWishedUpdates = new List {"1.3.0.0"}; + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne.FirstScenario")] + public void ConditionCheckWithFirstScenarioMustWorkWell_2() + { + SetFirstConfigScenario(); // 1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("R", "west")); + _clientConditions.Add(new KeyValuePair("CNR", "23654")); + + var sutWishedUpdates = new List {"1.3.0.0"}; + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne.FirstScenario")] + public void ConditionCheckWithFirstScenarioMustWorkWell_3() + { + SetFirstConfigScenario(); // 1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("R", "east")); + _clientConditions.Add(new KeyValuePair("CNR", "56478")); + + var sutWishedUpdates = new List {"1.2.0.0", "1.3.0.0"}; + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne.FirstScenario")] + public void ConditionCheckWithFirstScenarioMustWorkWell_4() + { + SetFirstConfigScenario(); //1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("R", "west")); + _clientConditions.Add(new KeyValuePair("CNR", "10394")); + + var sutWishedUpdates = new List {"1.3.0.0"}; + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne.SecondScenario")] + public void ConditionCheckWithSecondScenarioMustWorkWell_1() + { + SetSecondConfigScenario(); //1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("CC", "3")); + _clientConditions.Add(new KeyValuePair("CNR", "23654")); + + var sutWishedUpdates = new List {"1.3.0.0"}; + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne.SecondScenario")] + public void ConditionCheckWithSecondScenarioMustWorkWell_2() + { + SetSecondConfigScenario(); //1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("CC", "4")); + _clientConditions.Add(new KeyValuePair("CNR", "23654")); + + // ReSharper disable once CollectionNeverUpdated.Local + var sutWishedUpdates = new List(); + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne.SecondScenario")] + public void ConditionCheckWithSecondScenarioMustWorkWell_3() + { + SetSecondConfigScenario(); //1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("CC", "3")); + _clientConditions.Add(new KeyValuePair("CNR", "56478")); + + var sutWishedUpdates = new List {"1.2.0.0", "1.3.0.0"}; + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne.SecondScenario")] + public void ConditionCheckWithSecondScenarioMustWorkWell_4() + { + SetSecondConfigScenario(); //1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("CC", "1")); + _clientConditions.Add(new KeyValuePair("CNR", "10394")); + + var sutWishedUpdates = new List {"1.3.0.0"}; + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne.ThirdScenario")] + public void ConditionCheckWithThirdScenarioMustWorkWell_1() + { + SetThirdConfigScenario(); //1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("P", "special")); + + var sutWishedUpdates = new List {"1.3.0.0"}; + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne.ThirdScenario")] + public void ConditionCheckWithThirdScenarioMustWorkWell_2() + { + SetThirdConfigScenario(); //1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("P", "test")); + + // ReSharper disable once CollectionNeverUpdated.Local + var sutWishedUpdates = new List(); + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne.ThirdScenario")] + public void ConditionCheckWithThirdScenarioMustWorkWell_3() + { + SetThirdConfigScenario(); //1.2.0.0 and 1.3.0.0 + _clientConditions.Add(new KeyValuePair("P", "secure")); + + var sutWishedUpdates = new List {"1.2.0.0", "1.3.0.0"}; + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne")] + public void ConditionCheckWithoutClientValuesButWithRemoteValuesMustWorkWell() + { + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.AtLeastOne, new List + {new RolloutCondition("P", "secure")})); + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.AtLeastOne, new List())); + + var sutWishedUpdates = new List {"1.3.0.0"}; + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions.Mode.AtLeastOne")] + public void ConditionCheckWithoutClientValuesAndWithoutRemoteValuesMustWorkWell() + { + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.AtLeastOne, new List())); + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.AtLeastOne, new List())); + + var sutWishedUpdates = new List {"1.2.0.0", "1.3.0.0"}; + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutUpdateResults = new List(); + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions")] + [Description("If no conditions are defined in the package, we always pull the update")] + public void ConditionCheckWithoutRemoteValuesMustAllwayReturnTrue() + { + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.AtLeastOne, new List())); + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + Assert.IsTrue(sut.CheckConditions(_clientConditions, _updateConfigs.First())); + } + + [TestMethod] + [TestCategory("Conditions")] + [Description("If no conditions are defined in the package, we always pull the update")] + public void ConditionCheckWithoutRemoteValuesMustReturnAllUpdates() + { + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.AtLeastOne, new List())); + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.AtLeastOne, new List())); + _updateConfigs.Add(CreateConfig("1.3.4.0", RolloutConditionMode.AtLeastOne, new List())); + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutWishedUpdates = new List {"1.2.0.0", "1.3.0.0", "1.3.4.0"}; + var sutUpdateResults = new List(); + + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + + [TestMethod] + [TestCategory("Conditions")] + public void ConditionCheckCaseUnsensitiveValueOnClientsideTest() + { + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.AtLeastOne, new List + {new RolloutCondition("R", "east"), new RolloutCondition("CNR", "23654", true)})); + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.AtLeastOne, new List + {new RolloutCondition("R", "west"), new RolloutCondition("CNR", "23654", true)})); + + _clientConditions.Add(new KeyValuePair("R", "eAsT")); + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutWishedUpdates = new List {"1.2.0.0"}; + var sutUpdateResults = new List(); + + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + [TestMethod] + [TestCategory("Conditions")] + public void ConditionCheckCaseUnsensitiveValueOnServersideTest() + { + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.AtLeastOne, new List + {new RolloutCondition("R", "EaSt"), new RolloutCondition("CNR", "23654", true)})); + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.AtLeastOne, new List + {new RolloutCondition("R", "weST"), new RolloutCondition("CNR", "23654", true)})); + + _clientConditions.Add(new KeyValuePair("R", "east")); + + var sut = new UpdateResult(_updateConfigs, new UpdateVersion(1, 0, 0, 0), false, false, + _clientConditions); + + var sutWishedUpdates = new List {"1.2.0.0"}; + var sutUpdateResults = new List(); + + foreach (var c in _updateConfigs) + { + if (sut.CheckConditions(_clientConditions, c)) + { + sutUpdateResults.Add(c.LiteralVersion); + } + } + + Assert.AreEqual(sutWishedUpdates.Count, sutUpdateResults.Count); + foreach (var wu in sutWishedUpdates) + { + Assert.IsTrue(sutUpdateResults.Any(r => r.Equals(wu))); + } + } + + private void SetFirstConfigScenario() + { + // Roll out to all customers in region „east”, but without customer „23654", no matter in what region the customer is. + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.AtLeastOne, new List + {new RolloutCondition("R", "east"), new RolloutCondition("CNR", "23654", true)})); + + // Roll out to all customers in regions „east” and „west”, but without customers „36587" and „32578", no matter in what region they are. + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.AtLeastOne, new List + { + new RolloutCondition("R", "east"), new RolloutCondition("R", "west"), + new RolloutCondition("CNR", "36587", true), new RolloutCondition("CNR", "32578", true) + })); + } + + private void SetSecondConfigScenario() + { + // Roll out to all customers in customer circle „3", but without customer „23654". + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.AtLeastOne, new List + {new RolloutCondition("CC", "3"), new RolloutCondition("CNR", "23654", true)})); + + // Roll out to all customers in customer circle „1" and „3", but not customer circle „4". + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.AtLeastOne, new List + { + new RolloutCondition("CC", "1"), new RolloutCondition("CC", "3"), new RolloutCondition("CC", "4", true) + })); + } + + + private void SetThirdConfigScenario() + { + // Password „secure” is needed. + _updateConfigs.Add(CreateConfig("1.2.0.0", RolloutConditionMode.AtLeastOne, new List + {new RolloutCondition("P", "secure")})); + + // Password „secure” or „special” is valid. + _updateConfigs.Add(CreateConfig("1.3.0.0", RolloutConditionMode.AtLeastOne, new List + {new RolloutCondition("P", "secure"), new RolloutCondition("P", "special")})); + } + + private UpdateConfiguration CreateConfig(string version, RolloutConditionMode conditionMode, + List conditions, bool isnecessary = true) + { + var config = new UpdateConfiguration() + { + LiteralVersion = version, + RolloutConditionMode = conditionMode, + RolloutConditions = conditions, + NecessaryUpdate = isnecessary + }; + return config; + } + } +} \ No newline at end of file diff --git a/nUpdate.Test/ConnectionCheckerTest.cs b/nUpdate.Test/ConnectionCheckerTest.cs index 405a05e4..717cf7b9 100644 --- a/nUpdate.Test/ConnectionCheckerTest.cs +++ b/nUpdate.Test/ConnectionCheckerTest.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// ConnectionCheckerTest.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using Microsoft.VisualStudio.TestTools.UnitTesting; using nUpdate.Internal.Core; diff --git a/nUpdate.Test/Properties/AssemblyInfo.cs b/nUpdate.Test/Properties/AssemblyInfo.cs index 5568e01b..3b858243 100644 --- a/nUpdate.Test/Properties/AssemblyInfo.cs +++ b/nUpdate.Test/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// AssemblyInfo.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System.Reflection; using System.Runtime.InteropServices; @@ -37,5 +38,5 @@ // durch Einsatz von '*', wie in nachfolgendem Beispiel: // [Assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.3.1.0")] -[assembly: AssemblyFileVersion("3.3.1.0")] +[assembly: AssemblyVersion("3.4.1.0")] +[assembly: AssemblyFileVersion("3.4.1.0")] \ No newline at end of file diff --git a/nUpdate.Test/RsaSignatureTest.cs b/nUpdate.Test/RsaSignatureTest.cs index 9b36d8cc..d6c65cc9 100644 --- a/nUpdate.Test/RsaSignatureTest.cs +++ b/nUpdate.Test/RsaSignatureTest.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// RsaSignatureTest.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.IO; diff --git a/nUpdate.Test/UpdateVersionTest.cs b/nUpdate.Test/UpdateVersionTest.cs index d0976d65..7fd54243 100644 --- a/nUpdate.Test/UpdateVersionTest.cs +++ b/nUpdate.Test/UpdateVersionTest.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// UpdateVersionTest.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -24,7 +25,7 @@ public void CanCheckVersionValidity() public void CanGetHighestVersion() { var versionArray = new[] - {"1.0.0.0", "1.1.0.0", "1.2.0.0a1", "1.3.0.0b1", "1.2.0.0b3", "1.3.0.0b3", "1.3.0.1b97", "1.1.1.0"}; + {"1.0.0.0", "1.1.0.0", "1.2.0.0a1", "1.3.0.0b1", "1.2.0.0b3", "1.3.0.0b3", "1.3.0.1b97", "1.1.1.0"}; var versions = versionArray.Select(entry => new UpdateVersion(entry)).ToList(); Assert.AreEqual("1.3.0.1b97", UpdateVersion.GetHighestUpdateVersion(versions).ToString()); diff --git a/nUpdate.Test/UriConnectorTest.cs b/nUpdate.Test/UriConnectorTest.cs index dd02accf..11cc8b77 100644 --- a/nUpdate.Test/UriConnectorTest.cs +++ b/nUpdate.Test/UriConnectorTest.cs @@ -1,4 +1,5 @@ -// Author: Dominic Beger (Trade/ProgTrade) 2016 +// UriConnectorTest.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Diagnostics; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/nUpdate.Test/UseDynamicUpdateUriTest.cs b/nUpdate.Test/UseDynamicUpdateUriTest.cs index 8f799236..9c980f2d 100644 --- a/nUpdate.Test/UseDynamicUpdateUriTest.cs +++ b/nUpdate.Test/UseDynamicUpdateUriTest.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UseDynamicUpdateUriTest.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Globalization; diff --git a/nUpdate.Test/app.config b/nUpdate.Test/app.config index ddb87682..a51f2fad 100644 --- a/nUpdate.Test/app.config +++ b/nUpdate.Test/app.config @@ -1,11 +1,12 @@  + - - - - + + + + @@ -16,4 +17,4 @@ - + \ No newline at end of file diff --git a/nUpdate.Test/nUpdate.Test.csproj b/nUpdate.Test/nUpdate.Test.csproj index 9be58323..3ac9e2f8 100644 --- a/nUpdate.Test/nUpdate.Test.csproj +++ b/nUpdate.Test/nUpdate.Test.csproj @@ -83,8 +83,10 @@ + + diff --git a/nUpdate.Test/packages.config b/nUpdate.Test/packages.config index 8c796f5b..b98ec14f 100644 --- a/nUpdate.Test/packages.config +++ b/nUpdate.Test/packages.config @@ -1,4 +1,5 @@  + diff --git a/nUpdate.UpdateInstaller/Core/CodeDomHelper.cs b/nUpdate.UpdateInstaller/Core/CodeDomHelper.cs index 9861e436..34f8f581 100644 --- a/nUpdate.UpdateInstaller/Core/CodeDomHelper.cs +++ b/nUpdate.UpdateInstaller/Core/CodeDomHelper.cs @@ -1,8 +1,8 @@ -// Copyright © Dominic Beger 2018 +// CodeDomHelper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.CodeDom.Compiler; using System.Linq; -using System.Reflection; using Microsoft.CSharp; using nUpdate.UpdateInstaller.Exceptions; @@ -21,15 +21,15 @@ public void ExecuteScript(string sourceCode) _compileParameters.GenerateInMemory = false; _compileParameters.GenerateExecutable = true; - CompilerResults compilerResults = _cSharpCodeDomProvider.CompileAssemblyFromSource(_compileParameters, + var compilerResults = _cSharpCodeDomProvider.CompileAssemblyFromSource(_compileParameters, sourceCode); foreach ( - CompilerError compilerError in compilerResults.Errors.Cast().Where(ce => !ce.IsWarning)) + var compilerError in compilerResults.Errors.Cast().Where(ce => !ce.IsWarning)) throw new CompileException( $"({compilerError.Line},{compilerError.Column}: Error {compilerError.ErrorNumber}): {compilerError.ErrorText}"); - MethodInfo entryPoint = compilerResults.CompiledAssembly.EntryPoint; - object entryPointInstance = compilerResults.CompiledAssembly.CreateInstance(entryPoint.Name); + var entryPoint = compilerResults.CompiledAssembly.EntryPoint; + var entryPointInstance = compilerResults.CompiledAssembly.CreateInstance(entryPoint.Name); object[] parameters = {new[] {Program.AimFolder}}; entryPoint.Invoke(entryPointInstance, parameters); } diff --git a/nUpdate.UpdateInstaller/Core/FileHelper.cs b/nUpdate.UpdateInstaller/Core/FileHelper.cs index 6c3e13b1..156893d2 100644 --- a/nUpdate.UpdateInstaller/Core/FileHelper.cs +++ b/nUpdate.UpdateInstaller/Core/FileHelper.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// FileHelper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Runtime.InteropServices; @@ -12,7 +13,7 @@ public class FileHelper public static bool IsFileLocked(Exception exception) { - int errorCode = Marshal.GetHRForException(exception) & ((1 << 16) - 1); + var errorCode = Marshal.GetHRForException(exception) & ((1 << 16) - 1); return errorCode == ERROR_SHARING_VIOLATION || errorCode == ERROR_LOCK_VIOLATION; } } diff --git a/nUpdate.UpdateInstaller/Core/IconHelper.cs b/nUpdate.UpdateInstaller/Core/IconHelper.cs index 9b76dc3a..5581b0e7 100644 --- a/nUpdate.UpdateInstaller/Core/IconHelper.cs +++ b/nUpdate.UpdateInstaller/Core/IconHelper.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// IconHelper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; @@ -23,7 +24,7 @@ internal class IconHelper /// internal static Icon ExtractAssociatedIcon(string filePath) { - int index = 0; + var index = 0; Uri uri; if (filePath == null) diff --git a/nUpdate.UpdateInstaller/Core/InstallerServiceProvider.cs b/nUpdate.UpdateInstaller/Core/InstallerServiceProvider.cs index d0bcb6ef..e9a09a91 100644 --- a/nUpdate.UpdateInstaller/Core/InstallerServiceProvider.cs +++ b/nUpdate.UpdateInstaller/Core/InstallerServiceProvider.cs @@ -1,7 +1,9 @@ -// Copyright © Dominic Beger 2018 +// InstallerServiceProvider.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; +using System.Windows.Forms; using nUpdate.UpdateInstaller.Client.GuiInterface; using nUpdate.UpdateInstaller.Core; @@ -23,13 +25,15 @@ public object GetService(Type serviceType) { if (serviceType == null) throw new ArgumentNullException(nameof(serviceType)); - object service; - return !_services.TryGetValue(serviceType, out service) ? null : service; + return !_services.TryGetValue(serviceType, out var service) ? null : service; } private void InitializeServices() { - _services.Add(typeof(IProgressReporter), new ProgressReporterService()); + if (WindowsServiceHelper.IsRunningInServiceContext) + _services.Add(typeof(IProgressReporter), new ProgressReporterServiceEventLog()); + else + _services.Add(typeof(IProgressReporter), new ProgressReporterService()); } } } \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/Core/Operations/OperationArea.cs b/nUpdate.UpdateInstaller/Core/Operations/OperationArea.cs deleted file mode 100644 index 7eb314db..00000000 --- a/nUpdate.UpdateInstaller/Core/Operations/OperationArea.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright © Dominic Beger 2018 - -namespace nUpdate.UpdateInstaller.Core.Operations -{ - /// - /// Represents the different areas in which operations can take place. - /// - public enum OperationArea - { - Files, - Registry, - Processes, - Services, - Scripts - } -} \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/Core/ProgressReporterService.cs b/nUpdate.UpdateInstaller/Core/ProgressReporterService.cs index 889ef761..b2033b55 100644 --- a/nUpdate.UpdateInstaller/Core/ProgressReporterService.cs +++ b/nUpdate.UpdateInstaller/Core/ProgressReporterService.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ProgressReporterService.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using nUpdate.UpdateInstaller.Client.GuiInterface; diff --git a/nUpdate.UpdateInstaller/Core/ProgressReporterServiceEventLog.cs b/nUpdate.UpdateInstaller/Core/ProgressReporterServiceEventLog.cs new file mode 100644 index 00000000..bccb24cf --- /dev/null +++ b/nUpdate.UpdateInstaller/Core/ProgressReporterServiceEventLog.cs @@ -0,0 +1,44 @@ +// ProgressReporterServiceEventLog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System; +using System.Threading; +using nUpdate.UpdateInstaller.Client.GuiInterface; + +namespace nUpdate.UpdateInstaller.Core +{ + public class ProgressReporterServiceEventLog : IProgressReporter + { + private bool _shouldRun = true; + + public void Fail(Exception ex) + { + WindowsEventLog.LogException(ex); + } + + public void Initialize() + { + if (!WindowsServiceHelper.IsRunningInServiceContext) return; + while (_shouldRun) + Thread.Sleep(2000); + } + + public void InitializingFail(Exception ex) + { + WindowsEventLog.LogException(ex); + } + + public void ReportOperationProgress(float progress, string currentOperation) + { + } + + public void ReportUnpackingProgress(float progress, string currentFile) + { + } + + public void Terminate() + { + _shouldRun = false; + } + } +} \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/Core/RegistryManager.cs b/nUpdate.UpdateInstaller/Core/RegistryManager.cs index 4e2cb2d1..1798b64c 100644 --- a/nUpdate.UpdateInstaller/Core/RegistryManager.cs +++ b/nUpdate.UpdateInstaller/Core/RegistryManager.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// RegistryManager.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Linq; diff --git a/nUpdate.UpdateInstaller/Core/ServiceManager.cs b/nUpdate.UpdateInstaller/Core/ServiceManager.cs index b3a2e39b..c64f84b9 100644 --- a/nUpdate.UpdateInstaller/Core/ServiceManager.cs +++ b/nUpdate.UpdateInstaller/Core/ServiceManager.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ServiceManager.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.ServiceProcess; @@ -43,7 +44,7 @@ public static void StartService(string serviceName, string[] arguments) { var timeout = TimeSpan.FromMilliseconds(5000); - if (arguments != null || arguments.Length != 0) + if (arguments != null && arguments.Length != 0) serviceController.Start(arguments); else serviceController.Start(); diff --git a/nUpdate.UpdateInstaller/Core/ServiceProviderHelper.cs b/nUpdate.UpdateInstaller/Core/ServiceProviderHelper.cs index bcfdbf0e..1d59f870 100644 --- a/nUpdate.UpdateInstaller/Core/ServiceProviderHelper.cs +++ b/nUpdate.UpdateInstaller/Core/ServiceProviderHelper.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ServiceProviderHelper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Linq; diff --git a/nUpdate.UpdateInstaller/Core/Win32/NativeMethods.cs b/nUpdate.UpdateInstaller/Core/Win32/NativeMethods.cs index bd530789..fe43be65 100644 --- a/nUpdate.UpdateInstaller/Core/Win32/NativeMethods.cs +++ b/nUpdate.UpdateInstaller/Core/Win32/NativeMethods.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// NativeMethods.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Runtime.InteropServices; diff --git a/nUpdate.UpdateInstaller/Core/DevelopmentalStage.cs b/nUpdate.UpdateInstaller/DevelopmentalStage.cs similarity index 51% rename from nUpdate.UpdateInstaller/Core/DevelopmentalStage.cs rename to nUpdate.UpdateInstaller/DevelopmentalStage.cs index d9591128..db47b311 100644 --- a/nUpdate.UpdateInstaller/Core/DevelopmentalStage.cs +++ b/nUpdate.UpdateInstaller/DevelopmentalStage.cs @@ -1,6 +1,7 @@ -// Copyright © Dominic Beger 2018 +// DevelopmentalStage.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 -namespace nUpdate.UpdateInstaller.Core +namespace nUpdate.UpdateInstaller { public enum DevelopmentalStage { diff --git a/nUpdate.UpdateInstaller/Exceptions/CompileException.cs b/nUpdate.UpdateInstaller/Exceptions/CompileException.cs index b8c7bae9..4b6b132c 100644 --- a/nUpdate.UpdateInstaller/Exceptions/CompileException.cs +++ b/nUpdate.UpdateInstaller/Exceptions/CompileException.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// CompileException.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; diff --git a/nUpdate.UpdateInstaller/HostApplicationOptions.cs b/nUpdate.UpdateInstaller/HostApplicationOptions.cs new file mode 100644 index 00000000..c5327f76 --- /dev/null +++ b/nUpdate.UpdateInstaller/HostApplicationOptions.cs @@ -0,0 +1,12 @@ +// HostApplicationOptions.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +namespace nUpdate.UpdateInstaller +{ + public enum HostApplicationOptions + { + CloseAndRestart, + Close, + None + } +} \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/Core/Operations/Operation.cs b/nUpdate.UpdateInstaller/Operations/Operation.cs similarity index 93% rename from nUpdate.UpdateInstaller/Core/Operations/Operation.cs rename to nUpdate.UpdateInstaller/Operations/Operation.cs index bb4feef8..1f751a39 100644 --- a/nUpdate.UpdateInstaller/Core/Operations/Operation.cs +++ b/nUpdate.UpdateInstaller/Operations/Operation.cs @@ -1,9 +1,12 @@ -// Copyright © Dominic Beger 2018 +// Operation.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; +using System.ComponentModel; using System.IO; +using Newtonsoft.Json; -namespace nUpdate.UpdateInstaller.Core.Operations +namespace nUpdate.UpdateInstaller.Operations { public class Operation { @@ -35,6 +38,10 @@ public Operation(OperationArea area, OperationMethod method, string value, objec /// public object Value2 { get; set; } + [DefaultValue(false)] + [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] + public bool ExecuteBeforeReplacingFiles { get; set; } + /// /// Gets the full directory path for the given tag. /// @@ -125,6 +132,8 @@ public static string GetOperationTag(Operation operation) return "DeleteRegistrySubKey"; case OperationMethod.SetValue: return "SetRegistryValue"; + case OperationMethod.DeleteValue: + return "DeleteRegistryValue"; } break; diff --git a/nUpdate.UpdateInstaller/Operations/OperationArea.cs b/nUpdate.UpdateInstaller/Operations/OperationArea.cs new file mode 100644 index 00000000..240b2418 --- /dev/null +++ b/nUpdate.UpdateInstaller/Operations/OperationArea.cs @@ -0,0 +1,28 @@ +// OperationArea.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System.ComponentModel; + +namespace nUpdate.UpdateInstaller.Operations +{ + /// + /// Represents the different areas in which operations can take place. + /// + public enum OperationArea + { + [Description("NewUpdateDialogFilesAccessText")] + Files, + + [Description("NewUpdateDialogRegistryAccessText")] + Registry, + + [Description("NewUpdateDialogProcessesAccessText")] + Processes, + + [Description("NewUpdateDialogServicesAccessText")] + Services, + + [Description("NewUpdateDialogCodeExecutionAccessText")] + Scripts + } +} \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/Core/Operations/OperationMethod.cs b/nUpdate.UpdateInstaller/Operations/OperationMethod.cs similarity index 71% rename from nUpdate.UpdateInstaller/Core/Operations/OperationMethod.cs rename to nUpdate.UpdateInstaller/Operations/OperationMethod.cs index d99e9083..717c3731 100644 --- a/nUpdate.UpdateInstaller/Core/Operations/OperationMethod.cs +++ b/nUpdate.UpdateInstaller/Operations/OperationMethod.cs @@ -1,6 +1,7 @@ -// Copyright © Dominic Beger 2018 +// OperationMethod.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 -namespace nUpdate.UpdateInstaller.Core.Operations +namespace nUpdate.UpdateInstaller.Operations { /// /// Represents the different methods of the operations performed in different areas. diff --git a/nUpdate.UpdateInstaller/Program.cs b/nUpdate.UpdateInstaller/Program.cs index 34a287a5..cb8dd6eb 100644 --- a/nUpdate.UpdateInstaller/Program.cs +++ b/nUpdate.UpdateInstaller/Program.cs @@ -1,19 +1,25 @@ -// Copyright © Dominic Beger 2018 +// Program.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; using System.Drawing; +using System.IO; using System.Text; using System.Threading; using System.Windows.Forms; -using nUpdate.UpdateInstaller.Core; -using nUpdate.UpdateInstaller.Core.Operations; using nUpdate.UpdateInstaller.UI.Popups; +using Operation = nUpdate.UpdateInstaller.Operations.Operation; namespace nUpdate.UpdateInstaller { internal static class Program { + /// + /// The paths of the package files. + /// + public static string[] PackageFilePaths { get; set; } + /// /// The program folder where the updated files should be copied to. /// @@ -29,16 +35,6 @@ internal static class Program /// public static string AppName { get; set; } - /// - /// Gets or sets the arguments to handle over to the application. - /// - public static List Arguments { get; set; } - - /// - /// The text of the "Copying..."-label. - /// - public static string CopyingText { get; set; } - /// /// The path of the external GUI assembly. /// @@ -50,14 +46,9 @@ internal static class Program public static string ExtractFilesText { get; set; } /// - /// The text of the file delete information. - /// - public static string FileDeletingOperationText { get; set; } - - /// - /// The text of the error that a file is currently being used by another program. + /// The text of the "Copying..."-label. /// - public static string FileInUseError { get; set; } + public static string CopyingText { get; set; } /// /// The text of the file rename information. @@ -65,24 +56,26 @@ internal static class Program public static string FileRenamingOperationText { get; set; } /// - /// The caption of the initializing error message. + /// The text of the file delete information. /// - public static string InitializingErrorCaption { get; set; } + public static string FileDeletingOperationText { get; set; } /// - /// Gets or sets a value indicating whether the host application has been closed, or not. + /// The text of the registry sub key creation information. /// - public static bool IsHostApplicationClosed { get; set; } + public static string RegistrySubKeyCreateOperationText { get; set; } /// - /// The operations to perform. + /// The text of the registry name-value-pair value setting information. /// - public static Dictionary> Operations { get; set; } + public static string RegistryNameValuePairSetValueOperationText { get; set; } + + public static string RegistryNameValuePairDeleteValueOperationText { get; set; } /// /// The paths of the package files. /// - public static string[] PackageFilePaths { get; set; } + public static string RegistrySubKeyDeleteOperationText { get; set; } /// /// The text of the process start information. @@ -95,53 +88,42 @@ internal static class Program public static string ProcessStopOperationText { get; set; } /// - /// The text of the registry name-value-pair value deleting information. + /// The text of the service start information. /// - public static string RegistryNameValuePairDeleteValueOperationText { get; set; } + public static string ServiceStartOperationText { get; set; } /// - /// The text of the registry name-value-pair value setting information. + /// The text of the service stop information. /// - public static string RegistryNameValuePairSetValueOperationText { get; set; } + public static string ServiceStopOperationText { get; set; } /// - /// The text of the registry sub key creation information. + /// The caption of the updating error message. /// - public static string RegistrySubKeyCreateOperationText { get; set; } + public static string UpdatingErrorCaption { get; set; } /// - /// The text of the registry sub key deletion information. + /// The caption of the initializing error message. /// - public static string RegistrySubKeyDeleteOperationText { get; set; } + public static string InitializingErrorCaption { get; set; } /// - /// Gets or sets a value indicating whether the host application should be restarted, or not. + /// Gets or sets the arguments to handle over to the application. /// - public static bool RestartHostApplication { get; set; } + public static List Arguments { get; set; } /// - /// The text of the service start information. + /// Gets or sets the host application options after the update installation. /// - public static string ServiceStartOperationText { get; set; } + public static HostApplicationOptions HostApplicationOptions { get; set; } - /// - /// The text of the service stop information. - /// - public static string ServiceStopOperationText { get; set; } + // Deprecated, there for compatiblity + public static Dictionary> Operations { get; set; } /// - /// The caption of the updating error message. + /// The text of the error that a file is currently being used by another program. /// - public static string UpdatingErrorCaption { get; set; } - - private static void HandlerMethod(object sender, UnhandledExceptionEventArgs e) - { - if (e.ExceptionObject is ThreadAbortException) - return; - var exception = e.ExceptionObject as Exception; - if (exception != null) MessageBox.Show(exception.InnerException?.ToString() ?? exception.ToString()); - Application.Exit(); - } + public static string FileInUseError { get; set; } /// /// Der Haupteinstiegspunkt für die Anwendung. @@ -151,13 +133,13 @@ private static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); + Application.ThreadException += ApplicationOnThreadException; AppDomain.CurrentDomain.UnhandledException += HandlerMethod; if (args.Length != 1) { - Popup.ShowPopup(SystemIcons.Error, "Updating the application has failed.", - $"Invalid arguments count ({args.Length}) where 1 argument was expected.", - PopupButtons.Ok); + MessageBox.Show($"Invalid arguments count ({args.Length}) where 1 argument was expected.", + "Updating the application has failed.", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } @@ -169,9 +151,10 @@ private static void Main(string[] args) AimFolder = appArguments[1]; ApplicationExecutablePath = appArguments[2]; AppName = appArguments[3]; - Operations = - Serializer.Deserialize>>( - Encoding.UTF8.GetString(Convert.FromBase64String(appArguments[4]))); + // Argument 4 became deprecated, but for compatibility reasons we need to have this + Operations = appArguments[4].Equals(string.Empty) + ? null + : Serializer.Deserialize>>(Encoding.UTF8.GetString(Convert.FromBase64String(appArguments[4]))); ExternalGuiAssemblyPath = appArguments[5]; ExtractFilesText = appArguments[6]; CopyingText = appArguments[7]; @@ -190,17 +173,29 @@ private static void Main(string[] args) Arguments = Serializer.Deserialize>( Encoding.UTF8.GetString(Convert.FromBase64String(appArguments[20]))); // Arguments-property can't be "null" as UpdateManager creates an instance of a List and handles that over - IsHostApplicationClosed = Convert.ToBoolean(appArguments[21]); - RestartHostApplication = Convert.ToBoolean(appArguments[22]); - FileInUseError = appArguments[23]; + HostApplicationOptions = + (HostApplicationOptions) Enum.Parse(typeof(HostApplicationOptions), appArguments[21]); + FileInUseError = appArguments[22]; } catch (Exception ex) { - Popup.ShowPopup(SystemIcons.Error, "Updating the application has failed.", ex, PopupButtons.Ok); + MessageBox.Show(ex.StackTrace, "Error while updating the application.", MessageBoxButtons.OK, + MessageBoxIcon.Error); return; } new Updater().RunUpdate(); } + + private static void ApplicationOnThreadException(object sender, ThreadExceptionEventArgs e) + { + MessageBox.Show(e.Exception.Message + "\n" + e.Exception.StackTrace, "Error while updating the application.", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + private static void HandlerMethod(object sender, UnhandledExceptionEventArgs e) + { + var ex = (Exception) e.ExceptionObject; + MessageBox.Show(ex.Message + "\n" + ex.StackTrace, "Error while updating the application.", MessageBoxButtons.OK, MessageBoxIcon.Error); + } } } \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/Properties/AssemblyInfo.cs b/nUpdate.UpdateInstaller/Properties/AssemblyInfo.cs index de751b57..210d11e4 100644 --- a/nUpdate.UpdateInstaller/Properties/AssemblyInfo.cs +++ b/nUpdate.UpdateInstaller/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// AssemblyInfo.cs, 01.08.2018 +// Copyright (C) Dominic Beger 17.06.2019 using System.Reflection; using System.Runtime.InteropServices; @@ -37,5 +38,5 @@ // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.3.1.0")] -[assembly: AssemblyFileVersion("3.3.1.0")] +[assembly: AssemblyVersion("3.4.1.0")] +[assembly: AssemblyFileVersion("3.4.1.0")] diff --git a/nUpdate.UpdateInstaller/Core/Serializer.cs b/nUpdate.UpdateInstaller/Serializer.cs similarity index 88% rename from nUpdate.UpdateInstaller/Core/Serializer.cs rename to nUpdate.UpdateInstaller/Serializer.cs index ffefb43e..7ec5b9eb 100644 --- a/nUpdate.UpdateInstaller/Core/Serializer.cs +++ b/nUpdate.UpdateInstaller/Serializer.cs @@ -1,9 +1,11 @@ -// Copyright © Dominic Beger 2018 +// Serializer.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.IO; +using System.Text; using Newtonsoft.Json; -namespace nUpdate.UpdateInstaller.Core +namespace nUpdate.UpdateInstaller { public class Serializer { @@ -27,7 +29,7 @@ public static T Deserialize(string content) public static T Deserialize(Stream stream) { string streamContent; - using (var reader = new StreamReader(stream)) + using (var reader = new StreamReader(stream, Encoding.UTF8)) { streamContent = reader.ReadToEnd(); } diff --git a/nUpdate.UpdateInstaller/UI/Controls/ControlPanel.cs b/nUpdate.UpdateInstaller/UI/Controls/ControlPanel.cs index 857c37fb..62db746a 100644 --- a/nUpdate.UpdateInstaller/UI/Controls/ControlPanel.cs +++ b/nUpdate.UpdateInstaller/UI/Controls/ControlPanel.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// ControlPanel.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System.Drawing; using System.Windows.Forms; diff --git a/nUpdate.UpdateInstaller/UI/Dialogs/MainForm.cs b/nUpdate.UpdateInstaller/UI/Dialogs/MainForm.cs index c09f69a2..0cfcb8e3 100644 --- a/nUpdate.UpdateInstaller/UI/Dialogs/MainForm.cs +++ b/nUpdate.UpdateInstaller/UI/Dialogs/MainForm.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// MainForm.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; diff --git a/nUpdate.UpdateInstaller/UI/Popups/Popup.cs b/nUpdate.UpdateInstaller/UI/Popups/Popup.cs index f7d6c4e7..fd0bda35 100644 --- a/nUpdate.UpdateInstaller/UI/Popups/Popup.cs +++ b/nUpdate.UpdateInstaller/UI/Popups/Popup.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// Popup.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; @@ -17,6 +18,9 @@ public class Popup /// The buttons to show for the user-interaction. public static DialogResult ShowPopup(Icon popupIcon, string title, string infoMessage, PopupButtons buttons) { + if (LoggedIntoEventlog(popupIcon, infoMessage)) return DialogResult.OK; + + var popupWindow = new PopupDialog { PopupIcon = popupIcon, @@ -38,6 +42,7 @@ public static DialogResult ShowPopup(Icon popupIcon, string title, string infoMe /// The buttons to show for the user-interaction. public static DialogResult ShowPopup(Icon popupIcon, string title, Exception ex, PopupButtons buttons) { + if (LoggedIntoEventlog(popupIcon, ex.ToString())) return DialogResult.OK; var popupWindow = new PopupDialog { PopupIcon = popupIcon, @@ -62,6 +67,7 @@ public static DialogResult ShowPopup(Icon popupIcon, string title, Exception ex, public static DialogResult ShowPopup(IWin32Window owner, Icon popupIcon, string title, string infoMessage, PopupButtons buttons) { + if (LoggedIntoEventlog(popupIcon, infoMessage)) return DialogResult.OK; var popupWindow = new PopupDialog { PopupIcon = popupIcon, @@ -85,6 +91,7 @@ public static DialogResult ShowPopup(IWin32Window owner, Icon popupIcon, string public static DialogResult ShowPopup(IWin32Window owner, Icon popupIcon, string title, Exception exception, PopupButtons buttons) { + if (LoggedIntoEventlog(popupIcon, exception.ToString())) return DialogResult.OK; var popupWindow = new PopupDialog { PopupIcon = popupIcon, @@ -97,5 +104,22 @@ public static DialogResult ShowPopup(IWin32Window owner, Icon popupIcon, string return popupWindow.ShowDialog(); } + + + private static bool LoggedIntoEventlog(Icon popupIcon, string infoMessage) + { + if (WindowsServiceHelper.IsRunningInServiceContext) + { + if (popupIcon == SystemIcons.Error) + WindowsEventLog.LogError(infoMessage); + else if (popupIcon == SystemIcons.Warning) + WindowsEventLog.LogWarning(infoMessage); + else + WindowsEventLog.LogInformation(infoMessage); + return true; + } + + return false; + } } } \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/UI/Popups/PopupButtons.cs b/nUpdate.UpdateInstaller/UI/Popups/PopupButtons.cs index b184aa3b..3ded3cc5 100644 --- a/nUpdate.UpdateInstaller/UI/Popups/PopupButtons.cs +++ b/nUpdate.UpdateInstaller/UI/Popups/PopupButtons.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// PopupButtons.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 namespace nUpdate.UpdateInstaller.UI.Popups { diff --git a/nUpdate.UpdateInstaller/UI/Popups/PopupDialog.cs b/nUpdate.UpdateInstaller/UI/Popups/PopupDialog.cs index e8b95741..60a62142 100644 --- a/nUpdate.UpdateInstaller/UI/Popups/PopupDialog.cs +++ b/nUpdate.UpdateInstaller/UI/Popups/PopupDialog.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// PopupDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Drawing; @@ -65,7 +66,7 @@ private void PopupDialog_Shown(object sender, EventArgs e) if (messageLabel.Height > 41) { - int difference = messageLabel.Height - 41; + var difference = messageLabel.Height - 41; messageLabel.Height += difference; Height += difference; controlPanel1.Location = new Point(controlPanel1.Location.X, controlPanel1.Location.Y + difference); diff --git a/nUpdate.UpdateInstaller/Core/UpdateArgument.cs b/nUpdate.UpdateInstaller/UpdateArgument.cs similarity index 91% rename from nUpdate.UpdateInstaller/Core/UpdateArgument.cs rename to nUpdate.UpdateInstaller/UpdateArgument.cs index 4771e9a2..09c59cb1 100644 --- a/nUpdate.UpdateInstaller/Core/UpdateArgument.cs +++ b/nUpdate.UpdateInstaller/UpdateArgument.cs @@ -1,6 +1,7 @@ -// Copyright © Dominic Beger 2018 +// UpdateArgument.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 -namespace nUpdate.UpdateInstaller.Core +namespace nUpdate.UpdateInstaller { /// /// Represents an argument that is handled over to the application after the installation of an update. diff --git a/nUpdate.UpdateInstaller/UpdateArgumentExecutionOptions.cs b/nUpdate.UpdateInstaller/UpdateArgumentExecutionOptions.cs new file mode 100644 index 00000000..9ed0ed77 --- /dev/null +++ b/nUpdate.UpdateInstaller/UpdateArgumentExecutionOptions.cs @@ -0,0 +1,21 @@ +// UpdateArgumentExecutionOptions.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +namespace nUpdate.UpdateInstaller +{ + /// + /// Sets the behaviour of an when an update is installed. + /// + public enum UpdateArgumentExecutionOptions + { + /// + /// Sets that the parameter should only be executed if the installation of an update succeeded. + /// + OnlyOnSucceeded, + + /// + /// Sets that the parameter should only be executed if the installation of an update failed. + /// + OnlyOnFaulted + } +} \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/Core/UpdateVersion.cs b/nUpdate.UpdateInstaller/UpdateVersion.cs similarity index 94% rename from nUpdate.UpdateInstaller/Core/UpdateVersion.cs rename to nUpdate.UpdateInstaller/UpdateVersion.cs index 476449b9..9d38422c 100644 --- a/nUpdate.UpdateInstaller/Core/UpdateVersion.cs +++ b/nUpdate.UpdateInstaller/UpdateVersion.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// UpdateVersion.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -6,7 +7,7 @@ using System.Linq; using System.Text.RegularExpressions; -namespace nUpdate.UpdateInstaller.Core +namespace nUpdate.UpdateInstaller { public class UpdateVersion : IComparable { @@ -24,7 +25,7 @@ public UpdateVersion() /// The update version. public UpdateVersion(string version) { - Match match = Regex.Match(version, + var match = Regex.Match(version, @"^(?((?\d+)\.){0,3}(?\d+))((-| )?(?(?[ab]|rc)(\.?(?\d+))?))?$"); if (!match.Success || !match.Groups["Version"].Success) throw new ArgumentException("The specified version is not valid."); @@ -43,12 +44,21 @@ public UpdateVersion(string version) if (!match.Groups["DevStage"].Success) return; - var devStage = match.Groups["Type"].Value; - DevelopmentalStage = devStage == "a" - ? DevelopmentalStage.Alpha - : devStage == "b" - ? DevelopmentalStage.Beta - : DevelopmentalStage.ReleaseCandidate; + var developmentalStage = match.Groups["Type"].Value; + switch (developmentalStage) + { + case "a": + DevelopmentalStage = DevelopmentalStage.Alpha; + break; + case "b": + DevelopmentalStage = DevelopmentalStage.Beta; + break; + case "rc": + DevelopmentalStage = DevelopmentalStage.ReleaseCandidate; + break; + default: + throw new ArgumentException("The specified developmental stage is not valid."); + } DevelopmentBuild = match.Groups["DevBuild"].Success ? int.Parse(match.Groups["DevBuild"].Value) : 0; } @@ -188,10 +198,10 @@ public static UpdateVersion FromFullText(string fullText) throw new ArgumentException("fullText"); var versionParts = versionSections[0].Split('.'); - int major = int.Parse(versionParts[0]); - int minor = int.Parse(versionParts[1]); - int build = int.Parse(versionParts[2]); - int revision = int.Parse(versionParts[3]); + var major = int.Parse(versionParts[0]); + var minor = int.Parse(versionParts[1]); + var build = int.Parse(versionParts[2]); + var revision = int.Parse(versionParts[3]); if (versionSections.Length == 1) return new UpdateVersion(major, minor, build, revision); @@ -213,7 +223,7 @@ public static UpdateVersion FromFullText(string fullText) if (versionSections.Length == 2) return new UpdateVersion(major, minor, build, revision, devStage, 0); - int developmentBuild = int.Parse(versionSections[2]); + var developmentBuild = int.Parse(versionSections[2]); return new UpdateVersion(major, minor, build, revision, devStage, developmentBuild); } diff --git a/nUpdate.UpdateInstaller/Updater.cs b/nUpdate.UpdateInstaller/Updater.cs index 6645bd87..9e43fea0 100644 --- a/nUpdate.UpdateInstaller/Updater.cs +++ b/nUpdate.UpdateInstaller/Updater.cs @@ -1,4 +1,5 @@ -// Copyright © Dominic Beger 2018 +// Updater.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 using System; using System.Collections.Generic; @@ -11,11 +12,11 @@ using System.Threading; using Ionic.Zip; using Microsoft.Win32; +using Newtonsoft.Json.Linq; using nUpdate.UpdateInstaller.Client.GuiInterface; using nUpdate.UpdateInstaller.Core; -using nUpdate.UpdateInstaller.Core.Operations; +using nUpdate.UpdateInstaller.Operations; using nUpdate.UpdateInstaller.UI.Popups; -using Newtonsoft.Json.Linq; namespace nUpdate.UpdateInstaller { @@ -25,93 +26,6 @@ public class Updater private IProgressReporter _progressReporter; private int _totalTaskCount; - /// - /// Performs a recursive copy of a given directory. - /// - /// The path of the source directory. - /// The path of the destination directory. - private void CopyDirectoryRecursively(string sourceDirName, string destDirName) - { - try - { - var dir = new DirectoryInfo(sourceDirName); - var sourceDirectories = dir.GetDirectories(); - - if (!Directory.Exists(destDirName)) - Directory.CreateDirectory(destDirName); - - var files = dir.GetFiles(); - foreach (var file in files) - { - bool continueCopyLoop = true; - var aimPath = Path.Combine(destDirName, file.Name); - while (continueCopyLoop) - try - { - file.CopyTo(aimPath, true); - continueCopyLoop = false; - } - catch (IOException ex) - { - if (FileHelper.IsFileLocked(ex)) - _progressReporter.Fail(new Exception(string.Format(Program.FileInUseError, aimPath))); - else - throw; - } - - _doneTaskAmount += 1; - var percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; - _progressReporter.ReportUnpackingProgress(percentage, file.Name); - } - - foreach (var subDirectories in sourceDirectories) - { - var aimDirectoryPath = Path.Combine(destDirName, subDirectories.Name); - CopyDirectoryRecursively(subDirectories.FullName, aimDirectoryPath); - } - } - catch (Exception ex) - { - _progressReporter.Fail(ex); - _progressReporter.Terminate(); - if (!Program.IsHostApplicationClosed) - return; - - var process = new Process - { - StartInfo = - { - UseShellExecute = true, - FileName = Program.ApplicationExecutablePath, - Arguments = - string.Join("|", - Program.Arguments.Where( - item => - item.ExecutionOptions == - UpdateArgumentExecutionOptions.OnlyOnFaulted).Select(item => item.Argument)) - } - }; - process.Start(); - } - } - - /// - /// Loads the GUI either from a given external assembly, if one is set, or otherwise, uses the integrated GUI. - /// - /// - /// Returns a new instance of the given object that implements the - /// -interface. - /// - private IProgressReporter GetProgressReporter() - { - Assembly assembly = string.IsNullOrEmpty(Program.ExternalGuiAssemblyPath) || - !File.Exists(Program.ExternalGuiAssemblyPath) - ? Assembly.GetExecutingAssembly() - : Assembly.LoadFrom(Program.ExternalGuiAssemblyPath); - IServiceProvider provider = ServiceProviderHelper.CreateServiceProvider(assembly); - return (IProgressReporter) provider.GetService(typeof(IProgressReporter)); - } - /// /// Runs the updating process. /// @@ -123,13 +37,12 @@ public void RunUpdate() } catch (Exception ex) { - Popup.ShowPopup(SystemIcons.Error, "Error while initializing the graphical user interface.", ex, + Popup.ShowPopup(SystemIcons.Error, "Error while initializing the graphic user interface.", ex, PopupButtons.Ok); return; } ThreadPool.QueueUserWorkItem(arg => RunUpdateAsync()); - try { _progressReporter.Initialize(); @@ -141,18 +54,36 @@ public void RunUpdate() } } + /// + /// Loads the GUI either from a given external assembly, if one is set, or otherwise, from the integrated GUI. + /// + /// + /// Returns a new instance of the given object that implements the + /// -interface. + /// + private IProgressReporter GetProgressReporter() + { + var assembly = string.IsNullOrEmpty(Program.ExternalGuiAssemblyPath) || + !File.Exists(Program.ExternalGuiAssemblyPath) + ? Assembly.GetExecutingAssembly() + : Assembly.LoadFrom(Program.ExternalGuiAssemblyPath); + var provider = ServiceProviderHelper.CreateServiceProvider(assembly); + return (IProgressReporter) provider.GetService(typeof(IProgressReporter)); + } + /// /// Runs the updating process. This method does not block the calling thread. /// private void RunUpdateAsync() { - string parentPath = Directory.GetParent(Program.PackageFilePaths.First()).FullName; + Thread.Sleep(500); + var parentPath = Directory.GetParent(Program.PackageFilePaths.First()).FullName; /* Extract and count for the progress */ foreach (var packageFilePath in Program.PackageFilePaths) { - var version = new UpdateVersion(Path.GetFileNameWithoutExtension(packageFilePath)); - string extractedDirectoryPath = - Path.Combine(parentPath, version.ToString()); + var versionString = Path.GetFileNameWithoutExtension(packageFilePath); + var extractedDirectoryPath = + Path.Combine(parentPath, versionString ?? throw new InvalidOperationException()); Directory.CreateDirectory(extractedDirectoryPath); using (var zf = ZipFile.Read(packageFilePath)) { @@ -164,8 +95,9 @@ private void RunUpdateAsync() catch (Exception ex) { _progressReporter.Fail(ex); + CleanUp(); _progressReporter.Terminate(); - if (!Program.IsHostApplicationClosed || !Program.RestartHostApplication) + if (Program.HostApplicationOptions != HostApplicationOptions.CloseAndRestart) return; var process = new Process @@ -189,62 +121,73 @@ private void RunUpdateAsync() _totalTaskCount += new DirectoryInfo(extractedDirectoryPath).GetDirectories().Sum( directory => Directory.GetFiles(directory.FullName, "*.*", SearchOption.AllDirectories).Length); + + var currentVersionOperations = Program.Operations != null + ? Program.Operations[versionString].ToList() + : Serializer.Deserialize>( + File.ReadAllText(Path.Combine(extractedDirectoryPath, "operations.json"))).ToList(); + + // Multiple entries for: + /* + * Files: Delete operation + * Registry: All operations + */ + + _totalTaskCount += + currentVersionOperations.Count( + item => item.Area != OperationArea.Registry && + (item.Area != OperationArea.Files || item.Method != OperationMethod.Delete)); + + foreach (var op in currentVersionOperations.Where(o => o.Area == OperationArea.Registry + || o.Area == OperationArea.Files && + o.Method == OperationMethod.Delete)) + _totalTaskCount += ((JArray) op.Value2).Count; } } - foreach (var operationEnumerable in Program.Operations.Select(item => item.Value)) - _totalTaskCount += - operationEnumerable.Count( - item => item.Area != OperationArea.Registry && item.Method != OperationMethod.Delete); - foreach ( - var array in - Program.Operations.Select(entry => entry.Value) - .Select(operationEnumerable => operationEnumerable.Where( - item => - item.Area == OperationArea.Registry && item.Method != OperationMethod.SetValue) - .Select(registryOperation => registryOperation.Value2) - .OfType()).SelectMany(entries => - { - var entryEnumerable = entries as JArray[] ?? entries.ToArray(); - return entryEnumerable; - })) - _totalTaskCount += array.ToObject>().Count(); + var packageFilePath in + Program.PackageFilePaths.OrderBy(item => new UpdateVersion(Path.GetFileNameWithoutExtension(item)))) + { + var versionString = Path.GetFileNameWithoutExtension(packageFilePath); + var extractedDirectoryPath = + Path.Combine(parentPath, versionString); - foreach ( - var array in - Program.Operations.Select(entry => entry.Value) - .Select(operationEnumerable => operationEnumerable.Where( - item => item.Area == OperationArea.Files && item.Method == OperationMethod.Delete) - .Select(registryOperation => registryOperation.Value2) - .OfType()).SelectMany(entries => - { - var entryEnumerable = entries as JArray[] ?? entries.ToArray(); - return entryEnumerable; - })) - _totalTaskCount += array.ToObject>().Count(); + List currentVersionOperations; + try + { + currentVersionOperations = Program.Operations != null + ? Program.Operations[versionString].ToList() + : Serializer.Deserialize>( + File.ReadAllText(Path.Combine(extractedDirectoryPath, "operations.json"))).ToList(); + ExecuteOperations(currentVersionOperations.Where(o => o.ExecuteBeforeReplacingFiles)); + } + catch (Exception ex) + { + _progressReporter.Fail(ex); + CleanUp(); + _progressReporter.Terminate(); + if (Program.HostApplicationOptions != HostApplicationOptions.CloseAndRestart) + return; - foreach ( - var array in - Program.Operations.Select(entry => entry.Value) - .Select(operationEnumerable => operationEnumerable.Where( - item => - item.Area == OperationArea.Registry && item.Method == OperationMethod.SetValue) - .Select(registryOperation => registryOperation.Value2) - .OfType()).SelectMany(entries => + var process = new Process { - var entryEnumerable = entries as JArray[] ?? entries.ToArray(); - return entryEnumerable; - })) - _totalTaskCount += array.ToObject>>().Count(); + StartInfo = + { + UseShellExecute = true, + FileName = Program.ApplicationExecutablePath, + Arguments = + string.Join("|", + Program.Arguments.Where( + item => + item.ExecutionOptions == + UpdateArgumentExecutionOptions.OnlyOnFaulted).Select(item => item.Argument)) + } + }; + process.Start(); + return; + } - foreach ( - var packageFilePath in - Program.PackageFilePaths) - { - var version = new UpdateVersion(Path.GetFileNameWithoutExtension(packageFilePath)); - string extractedDirectoryPath = - Path.Combine(parentPath, version.ToString()); foreach (var directory in new DirectoryInfo(extractedDirectoryPath).GetDirectories()) switch (directory.Name) { @@ -259,6 +202,7 @@ var packageFilePath in CopyDirectoryRecursively(directory.FullName, Path.GetTempPath()); break; case "Desktop": + if (WindowsServiceHelper.IsRunningInServiceContext) continue; CopyDirectoryRecursively(directory.FullName, Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)); break; @@ -266,256 +210,347 @@ var packageFilePath in try { - IEnumerable currentVersionOperations = - Program.Operations.Any(item => new UpdateVersion(item.Key) == version) - ? Program.Operations.First(item => new UpdateVersion(item.Key) == version).Value - : Enumerable.Empty(); - foreach (var operation in currentVersionOperations) + ExecuteOperations(currentVersionOperations.Where(o => !o.ExecuteBeforeReplacingFiles)); + } + catch (Exception ex) + { + _progressReporter.Fail(ex); + CleanUp(); + _progressReporter.Terminate(); + if (Program.HostApplicationOptions != HostApplicationOptions.CloseAndRestart) + return; + + var process = new Process { - float percentage; - JArray secondValueAsArray; - switch (operation.Area) + StartInfo = { - case OperationArea.Files: - switch (operation.Method) - { - case OperationMethod.Delete: - var deleteFilePathParts = operation.Value.Split('\\'); - var deleteFileFullPath = Path.Combine( - Operation.GetDirectory(deleteFilePathParts[0]), - string.Join("\\", - deleteFilePathParts.Where(item => item != deleteFilePathParts[0]))); - secondValueAsArray = operation.Value2 as JArray; - if (secondValueAsArray != null) - foreach ( - var fileToDelete in secondValueAsArray.ToObject>()) - { - string path = Path.Combine(deleteFileFullPath, fileToDelete); - if (File.Exists(path)) - File.Delete(path); - - _doneTaskAmount += 1; - percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; - _progressReporter.ReportOperationProgress(percentage, - string.Format(Program.FileDeletingOperationText, fileToDelete)); - } - - break; - - case OperationMethod.Rename: - var renameFilePathParts = operation.Value.Split('\\'); - var renameFileFullPath = Path.Combine( - Operation.GetDirectory(renameFilePathParts[0]), - string.Join("\\", - renameFilePathParts.Where(item => item != renameFilePathParts[0]))); - if (File.Exists(renameFileFullPath)) - File.Move(renameFileFullPath, - Path.Combine(Directory.GetParent(renameFileFullPath).FullName, - operation.Value2.ToString())); + UseShellExecute = true, + FileName = Program.ApplicationExecutablePath, + Arguments = + string.Join("|", + Program.Arguments.Where( + item => + item.ExecutionOptions == + UpdateArgumentExecutionOptions.OnlyOnFaulted).Select(item => item.Argument)) + } + }; + process.Start(); + return; + } + } + + CleanUp(); + if (Program.HostApplicationOptions == HostApplicationOptions.CloseAndRestart) + { + var p = new Process + { + StartInfo = + { + UseShellExecute = true, + FileName = Program.ApplicationExecutablePath, + Arguments = + string.Join("|", + Program.Arguments.Where( + item => + item.ExecutionOptions == UpdateArgumentExecutionOptions.OnlyOnSucceeded) + .Select(item => item.Argument)) + } + }; + p.Start(); + } + + _progressReporter.Terminate(); + } + + private void ExecuteOperations(IEnumerable operations) + { + foreach (var operation in operations) + { + float percentage; + JArray secondValueAsArray; + switch (operation.Area) + { + case OperationArea.Files: + switch (operation.Method) + { + case OperationMethod.Delete: + var deleteFilePathParts = operation.Value.Split('\\'); + var deleteFileFullPath = Path.Combine( + Operation.GetDirectory(deleteFilePathParts[0]), + string.Join("\\", + deleteFilePathParts.Where(item => item != deleteFilePathParts[0]))); + secondValueAsArray = operation.Value2 as JArray; + if (secondValueAsArray != null) + foreach ( + var fileToDelete in secondValueAsArray.ToObject>()) + { + var path = Path.Combine(deleteFileFullPath, fileToDelete); + if (File.Exists(path)) + File.Delete(path); _doneTaskAmount += 1; percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; _progressReporter.ReportOperationProgress(percentage, - string.Format(Program.FileRenamingOperationText, - Path.GetFileName(operation.Value), - operation.Value2)); - break; - } + string.Format(Program.FileDeletingOperationText, fileToDelete)); + } break; - case OperationArea.Registry: - switch (operation.Method) - { - case OperationMethod.Create: - secondValueAsArray = operation.Value2 as JArray; - if (secondValueAsArray != null) - foreach ( - var registryKey in secondValueAsArray.ToObject>()) - { - RegistryManager.CreateSubKey(operation.Value, registryKey); - - _doneTaskAmount += 1; - percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; - _progressReporter.ReportOperationProgress(percentage, - string.Format(Program.RegistrySubKeyCreateOperationText, - registryKey)); - } - - break; - - case OperationMethod.Delete: - secondValueAsArray = operation.Value2 as JArray; - if (secondValueAsArray != null) - foreach ( - var registryKey in secondValueAsArray.ToObject>()) - { - RegistryManager.DeleteSubKey(operation.Value, registryKey); - - _doneTaskAmount += 1; - percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; - _progressReporter.ReportOperationProgress(percentage, - string.Format(Program.RegistrySubKeyDeleteOperationText, - registryKey)); - } - - break; - - case OperationMethod.SetValue: - secondValueAsArray = operation.Value2 as JArray; - if (secondValueAsArray != null) - foreach ( - var nameValuePair in - secondValueAsArray - .ToObject>> - ()) - { - RegistryManager.SetValue(operation.Value, nameValuePair.Item1, - nameValuePair.Item2, nameValuePair.Item3); - - _doneTaskAmount += 1; - percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; - _progressReporter.ReportOperationProgress(percentage, - string.Format(Program.RegistryNameValuePairSetValueOperationText, - nameValuePair.Item1, nameValuePair.Item2)); - } - - break; - - case OperationMethod.DeleteValue: - secondValueAsArray = operation.Value2 as JArray; - if (secondValueAsArray != null) - foreach (var valueName in secondValueAsArray.ToObject>() - ) - { - RegistryManager.DeleteValue(operation.Value, valueName); - - _doneTaskAmount += 1; - percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; - _progressReporter.ReportOperationProgress(percentage, - string.Format(Program.RegistryNameValuePairDeleteValueOperationText, - valueName)); - } - - break; - } + case OperationMethod.Rename: + var renameFilePathParts = operation.Value.Split('\\'); + var renameFileFullPath = Path.Combine( + Operation.GetDirectory(renameFilePathParts[0]), + string.Join("\\", + renameFilePathParts.Where(item => item != renameFilePathParts[0]))); + if (File.Exists(renameFileFullPath)) + File.Move(renameFileFullPath, + Path.Combine(Directory.GetParent(renameFileFullPath).FullName, + operation.Value2.ToString())); + + _doneTaskAmount += 1; + percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; + _progressReporter.ReportOperationProgress(percentage, + string.Format(Program.FileRenamingOperationText, + Path.GetFileName(operation.Value), + operation.Value2)); break; + } - case OperationArea.Processes: - switch (operation.Method) - { - case OperationMethod.Start: - var processFilePathParts = operation.Value.Split('\\'); - var processFileFullPath = - Path.Combine(Operation.GetDirectory(processFilePathParts[0]), - string.Join("\\", - processFilePathParts.Where(item => - item != processFilePathParts[0]))); - - var process = new Process - { - StartInfo = - { - FileName = processFileFullPath, - Arguments = operation.Value2.ToString() - } - }; - try - { - process.Start(); - } - catch (Win32Exception ex) - { - if (ex.NativeErrorCode != 1223) - throw; - } + break; + case OperationArea.Registry: + switch (operation.Method) + { + case OperationMethod.Create: + secondValueAsArray = operation.Value2 as JArray; + if (secondValueAsArray != null) + foreach ( + var registryKey in secondValueAsArray.ToObject>()) + { + RegistryManager.CreateSubKey(operation.Value, registryKey); _doneTaskAmount += 1; percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; _progressReporter.ReportOperationProgress(percentage, - string.Format(Program.ProcessStartOperationText, operation.Value)); - break; + string.Format(Program.RegistrySubKeyCreateOperationText, registryKey)); + } - case OperationMethod.Stop: - var processes = Process.GetProcessesByName(operation.Value); - foreach (var foundProcess in processes) - foundProcess.Kill(); + break; + + case OperationMethod.Delete: + secondValueAsArray = operation.Value2 as JArray; + if (secondValueAsArray != null) + foreach ( + var registryKey in secondValueAsArray.ToObject>()) + { + RegistryManager.DeleteSubKey(operation.Value, registryKey); _doneTaskAmount += 1; percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; _progressReporter.ReportOperationProgress(percentage, - string.Format(Program.ProcessStopOperationText, operation.Value)); - break; - } + string.Format(Program.RegistrySubKeyDeleteOperationText, registryKey)); + } break; - case OperationArea.Services: - switch (operation.Method) - { - case OperationMethod.Start: - ServiceManager.StartService(operation.Value, - ((JArray) operation.Value2).ToObject()); + case OperationMethod.SetValue: + secondValueAsArray = operation.Value2 as JArray; + if (secondValueAsArray != null) + foreach ( + var nameValuePair in + secondValueAsArray + .ToObject>> + ()) + { + RegistryManager.SetValue(operation.Value, nameValuePair.Item1, + nameValuePair.Item2, nameValuePair.Item3); _doneTaskAmount += 1; percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; _progressReporter.ReportOperationProgress(percentage, - string.Format(Program.ServiceStartOperationText, operation.Value)); - break; + string.Format(Program.RegistryNameValuePairSetValueOperationText, + nameValuePair.Item1, nameValuePair.Item2)); + } + + break; - case OperationMethod.Stop: - ServiceManager.StopService(operation.Value); + case OperationMethod.DeleteValue: + secondValueAsArray = operation.Value2 as JArray; + if (secondValueAsArray != null) + foreach (var valueName in secondValueAsArray.ToObject>() + ) + { + RegistryManager.DeleteValue(operation.Value, valueName); _doneTaskAmount += 1; percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; _progressReporter.ReportOperationProgress(percentage, - string.Format(Program.ServiceStopOperationText, operation.Value)); - break; - } + string.Format(Program.RegistryNameValuePairSetValueOperationText, + valueName)); + } break; - case OperationArea.Scripts: - switch (operation.Method) + } + + break; + + case OperationArea.Processes: + switch (operation.Method) + { + case OperationMethod.Start: + var processFilePathParts = operation.Value.Split('\\'); + var processFileFullPath = + Path.Combine(Operation.GetDirectory(processFilePathParts[0]), + string.Join("\\", + processFilePathParts.Where(item => item != processFilePathParts[0]))); + + var process = new Process + { + StartInfo = + { + FileName = processFileFullPath, + Arguments = operation.Value2.ToString() + } + }; + try { - case OperationMethod.Execute: - var helper = new CodeDomHelper(); - helper.ExecuteScript(operation.Value); - break; + process.Start(); } + catch (Win32Exception ex) + { + if (ex.NativeErrorCode != 1223) + throw; + } + + _doneTaskAmount += 1; + percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; + _progressReporter.ReportOperationProgress(percentage, + string.Format(Program.ProcessStartOperationText, operation.Value)); + break; + + case OperationMethod.Stop: + var processes = Process.GetProcessesByName(operation.Value); + foreach (var foundProcess in processes) + foundProcess.Kill(); + _doneTaskAmount += 1; + percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; + _progressReporter.ReportOperationProgress(percentage, + string.Format(Program.ProcessStopOperationText, operation.Value)); break; } - } - } - catch (Exception ex) - { - _progressReporter.Fail(ex); - _progressReporter.Terminate(); - if (!Program.IsHostApplicationClosed || !Program.RestartHostApplication) - return; - var process = new Process - { - StartInfo = + break; + + case OperationArea.Services: + switch (operation.Method) { - UseShellExecute = true, - FileName = Program.ApplicationExecutablePath, - Arguments = - string.Join("|", - Program.Arguments.Where( - item => - item.ExecutionOptions == - UpdateArgumentExecutionOptions.OnlyOnFaulted).Select(item => item.Argument)) + case OperationMethod.Start: + ServiceManager.StartService(operation.Value, (string[]) operation.Value2); + + _doneTaskAmount += 1; + percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; + _progressReporter.ReportOperationProgress(percentage, + string.Format(Program.ServiceStartOperationText, operation.Value)); + break; + + case OperationMethod.Stop: + ServiceManager.StopService(operation.Value); + + _doneTaskAmount += 1; + percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; + _progressReporter.ReportOperationProgress(percentage, + string.Format(Program.ServiceStopOperationText, operation.Value)); + break; } - }; - process.Start(); - return; + + break; + case OperationArea.Scripts: + switch (operation.Method) + { + case OperationMethod.Execute: + var helper = new CodeDomHelper(); + helper.ExecuteScript(operation.Value); + + _doneTaskAmount += 1; + percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; + _progressReporter.ReportOperationProgress(percentage, "Executing operation."); + break; + } + + break; } } + } - if (Program.IsHostApplicationClosed && Program.RestartHostApplication) + /// + /// Cleans up all resources. + /// + private void CleanUp() + { + try { - var p = new Process + Directory.Delete(Directory.GetParent(Program.PackageFilePaths.First()).FullName, true); + } + catch (Exception ex) + { + _progressReporter.Fail(ex); + } + } + + /// + /// Performs a recursive copy of a given directory. + /// + /// The path of the source directory. + /// The path of the destination directory. + private void CopyDirectoryRecursively(string sourceDirName, string destDirName) + { + try + { + var dir = new DirectoryInfo(sourceDirName); + var sourceDirectories = dir.GetDirectories(); + + if (!Directory.Exists(destDirName)) + Directory.CreateDirectory(destDirName); + + var files = dir.GetFiles(); + foreach (var file in files) + { + var continueCopyLoop = true; + var aimPath = Path.Combine(destDirName, file.Name); + while (continueCopyLoop) + try + { + file.CopyTo(aimPath, true); + continueCopyLoop = false; + } + catch (IOException ex) + { + if (FileHelper.IsFileLocked(ex)) + _progressReporter.Fail(new Exception(string.Format(Program.FileInUseError, aimPath))); + else + throw; + } + + _doneTaskAmount += 1; + var percentage = (float) _doneTaskAmount / _totalTaskCount * 100f; + _progressReporter.ReportUnpackingProgress(percentage, file.Name); + } + + foreach (var subDirectories in sourceDirectories) + { + var aimDirectoryPath = Path.Combine(destDirName, subDirectories.Name); + CopyDirectoryRecursively(subDirectories.FullName, aimDirectoryPath); + } + } + catch (Exception ex) + { + _progressReporter.Fail(ex); + CleanUp(); + _progressReporter.Terminate(); + if (Program.HostApplicationOptions != HostApplicationOptions.CloseAndRestart) + return; + + var process = new Process { StartInfo = { @@ -524,15 +559,13 @@ var nameValuePair in Arguments = string.Join("|", Program.Arguments.Where( - item => - item.ExecutionOptions == UpdateArgumentExecutionOptions.OnlyOnSucceeded) - .Select(item => item.Argument)) + item => + item.ExecutionOptions == + UpdateArgumentExecutionOptions.OnlyOnFaulted).Select(item => item.Argument)) } }; - p.Start(); + process.Start(); } - - _progressReporter.Terminate(); } } } \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/WindowsEventLog.cs b/nUpdate.UpdateInstaller/WindowsEventLog.cs new file mode 100644 index 00000000..410c7019 --- /dev/null +++ b/nUpdate.UpdateInstaller/WindowsEventLog.cs @@ -0,0 +1,100 @@ +// WindowsEventLog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System; +using System.Diagnostics; +using System.Globalization; +using System.Security; + +namespace nUpdate.UpdateInstaller +{ + public static class WindowsEventLog + { + private const string DefaultSource = "nUpdate"; + + // https://stackoverflow.com/questions/25725151/write-to-windows-application-event-log + // Note: The actual limit is higher than this, but different Microsoft operating systems actually have different limits. So just use 30,000 to be safe. + private const int MaxEventLogEntryLength = 30000; + private static string _source; + + public static string Source + { + get + { + if (string.IsNullOrEmpty(_source)) + { + _source = DefaultSource; + CreateEventSource(); + } + + return _source; + } + set + { + _source = value; + if (string.IsNullOrEmpty(_source)) _source = DefaultSource; + + CreateEventSource(); + } + } + + private static void CreateEventSource() + { + try + { + // searching the source throws a security exception ONLY if not exists! + if (!EventLog.SourceExists(_source)) + EventLog.CreateEventSource(_source, "Application"); + } + catch (SecurityException) + { + _source = "Application"; + } + } + + public static void LogInformation(string message) + { + Log(message, EventLogEntryType.Information); + } + + public static void LogWarning(string message) + { + Log(message, EventLogEntryType.Warning); + } + + public static void LogError(string message) + { + Log(message, EventLogEntryType.Error); + } + + public static void LogException(Exception ex) + { + if (ex == null) + throw new ArgumentNullException(nameof(ex)); + + if (Environment.UserInteractive) + Console.WriteLine(ex.ToString()); + + Log(ex.ToString(), EventLogEntryType.Error); + } + + private static void Log(string message, EventLogEntryType entryType) + { + var possiblyTruncatedMessage = EnsureLogMessageLimit(message); + EventLog.WriteEntry(Source, possiblyTruncatedMessage, entryType); + } + + private static string EnsureLogMessageLimit(string logMessage) + { + if (logMessage.Length <= MaxEventLogEntryLength) + return logMessage; + var truncateWarningText = string.Format(CultureInfo.CurrentCulture, + "... | Log Message Truncated [ Limit: {0} ]", MaxEventLogEntryLength); + + logMessage = logMessage.Substring(0, MaxEventLogEntryLength - truncateWarningText.Length); + logMessage = string.Format(CultureInfo.CurrentCulture, "{0}{1}", logMessage, truncateWarningText); + + return logMessage; + } + } +} \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/WindowsServiceHelper.cs b/nUpdate.UpdateInstaller/WindowsServiceHelper.cs new file mode 100644 index 00000000..c6f2d78d --- /dev/null +++ b/nUpdate.UpdateInstaller/WindowsServiceHelper.cs @@ -0,0 +1,24 @@ +// WindowsServiceHelper.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System; + +namespace nUpdate.UpdateInstaller +{ + public static class WindowsServiceHelper + { + private static bool? _isRunningInServiceContext; + + /// + /// Gets a value indicating, if the application runs in service context + /// + public static bool IsRunningInServiceContext => _isRunningInServiceContext ?? + (_isRunningInServiceContext = + DetermineIfRunningInServiceContext()).Value; + + private static bool DetermineIfRunningInServiceContext() + { + return !Environment.UserInteractive; + } + } +} \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/nUpdate.UpdateInstaller.csproj b/nUpdate.UpdateInstaller/nUpdate.UpdateInstaller.csproj index fe867f0a..f5873073 100644 --- a/nUpdate.UpdateInstaller/nUpdate.UpdateInstaller.csproj +++ b/nUpdate.UpdateInstaller/nUpdate.UpdateInstaller.csproj @@ -1,153 +1,157 @@ - - - - - Debug - AnyCPU - {2BBC927A-B18C-4BFE-8325-D9387F217095} - WinExe - Properties - nUpdate.UpdateInstaller - nUpdate UpdateInstaller - v4.0 - 512 - - cd9b7350 - ..\ - true - - - AnyCPU - true - full - true - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - false - bin\Release\ - TRACE - prompt - 4 - - - Trade-Updater-Logo-v3.ico - - - - - - - - - ..\packages\DotNetZip.1.9\lib\Ionic.Zip.dll - True - - - ..\packages\Newtonsoft.Json.6.0.8\lib\net40\Newtonsoft.Json.dll - True - - - False - ..\nUpdate.Client.GuiInterface\bin\nUpdate.UpdateInstaller.Client.GuiInterface.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - Component - - - Form - - - MainForm.cs - - - - - - - Form - - - PopupDialog.cs - - - - MainForm.cs - Designer - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - PopupDialog.cs - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - - - Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Aktivieren Sie die Wiederherstellung von NuGet-Paketen, um die fehlende Datei herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". - - - + + + + + Debug + AnyCPU + {2BBC927A-B18C-4BFE-8325-D9387F217095} + WinExe + Properties + nUpdate.UpdateInstaller + nUpdate.UpdateInstaller + v4.0 + 512 + + cd9b7350 + ..\ + true + + + AnyCPU + true + full + true + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + false + bin\Release\ + TRACE + prompt + 4 + + + Trade-Updater-Logo-v3.ico + + + + + + + + + ..\packages\DotNetZip.1.13.3\lib\net40\DotNetZip.dll + + + ..\packages\Newtonsoft.Json.12.0.2\lib\net40\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + Component + + + Form + + + MainForm.cs + + + + + + + Form + + + PopupDialog.cs + + + + + + + + + MainForm.cs + Designer + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + PopupDialog.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + {5e63208a-8f06-4b99-a41d-f469be4cfd00} + nUpdate.UpdateInstaller.Client.GuiInterface + + + + + + + Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Aktivieren Sie die Wiederherstellung von NuGet-Paketen, um die fehlende Datei herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". + + + + --> \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/packages.config b/nUpdate.UpdateInstaller/packages.config index 021ee3df..2584cabe 100644 --- a/nUpdate.UpdateInstaller/packages.config +++ b/nUpdate.UpdateInstaller/packages.config @@ -1,5 +1,5 @@  - - + + \ No newline at end of file diff --git a/nUpdate.UserInterfaceTest/App.config b/nUpdate.UserInterfaceTest/App.config index ee1232e2..af4478f0 100644 --- a/nUpdate.UserInterfaceTest/App.config +++ b/nUpdate.UserInterfaceTest/App.config @@ -1,8 +1,9 @@  + - - - + + + @@ -15,4 +16,4 @@ - + \ No newline at end of file diff --git a/nUpdate.UserInterfaceTest/MainDialog.cs b/nUpdate.UserInterfaceTest/MainDialog.cs index c3c8863d..d734b65a 100644 --- a/nUpdate.UserInterfaceTest/MainDialog.cs +++ b/nUpdate.UserInterfaceTest/MainDialog.cs @@ -1,4 +1,7 @@ -using System; +// MainDialog.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System; using System.Globalization; using System.Threading; using System.Windows.Forms; @@ -14,9 +17,7 @@ public MainDialog() { InitializeComponent(); - var manager = new UpdateManager(new Uri("http://localhost/nupdate/updates.json"), "sK3GI4HI8Qd+33LTWXdhSLs/DMX+GZw/Onsh7J71rPUR7UHabuzr03LaUvzQhZfLMvi8V+RKXYz3/6s/ILc0c44IUJ1e9j2Hwq4sgsguQmnOKEcJzOyqA/0lNuf7/2UeyM/478G5UksoFeop4tirMHF5zqQnlxSjcWbCIvzFpkqYKI9vTjgirtFwnGknbXcArN9a5FXDtdZXNUwSO0NP7SIifIKv8Rzwq4d4PnAqhlawafHpJCLyUOd2erUvchUD3h+Q7yUZUWd8/UN5M81wZqA/CthJx2yM2JuclpQgc+5fv7uvcGe0tEep1Fa0e71cXt8CtLNLlWv2lttATE4VxIOzhbiUfLz+BCQBE/dUmBFn3crSLmJHnaqOqIWFx6y5Q5wJReHSKPqRtskuV0Wqy0CwHglaCy1lY8fPJSITZbfXGLGaKstUZN53YWC4QDfQIA5wj6c+TOMvF1yI0IuwV/4M7MtO2veFTXPxHUcAmJMcubwDJnAeyH7bkxLPMTFzBSGGOMdDFs0vvs7z0ZXwn6NCdmgVlgDdD32wd704IiTuskjBKB2HwZxp8ppI7kbCmGuOQTdc5R6qW5IKcvEeEAyM7o/7qvbRXtWrVbfiD9uPE2n3Pt9DIYZbtAHObxs+7XU67yMYWn7KyAL3BE+/5g7V/PkLsWD4jynv23MZnxfQ0Lw70Dw2zZjiLK10pzXRVCJNC5DoZGyocF/JaAqyAxOYoVqleFHvV6G9JmawxtY9w2L++c3NkOVhpks8aiJkjiZ/KR+GHSXHHKFrtg80eyn0Nqmycpq40jEQWqoo3z5dLifFFCjwPG8R6gF7ZK1Kw4CB/sFp7qps5C84F6HRk22bG+YXmUhDOVE9Npagq7reL5dbsoiuoQPEbzuVc2ADI/6RzNLtlnE/RLD2Jl7QW0qc5sVJrdS45x5bQRnQFz6FgSjuZ6hMxOjRIrJHB9RIZoiFqaqZzWOKANvkpI6dlb/Vv01hc1ETsjdsqUFvqZ0ltlMs9BxP0Hl6tiQs15Q0u6HPOiJ50wnXInLQPlKX1kYas1rsChV3tNwzOl75+LNReWwj2HZgBV97dWvk6i5wZcnZJL4+PKf4r9a3Csqi1cygM4U6kESrxAjH4dDwTXfhFsZ0pwbxAfeatcLw9MWFdUc3ZEi2FbxbSOOUFD2HyIQrFR3aBQ9WmXJAmzNW96t47KGVoepPRlAQqwD3TJWkZVfh0bWaZtG9RsifNDz/BUabfqbzPvwEkQI9ShhPApip3lx8ryKgulLpAlVGYWmvtnfSxba1Ah0f8iSEoJIhfdFeahvRoNpxvsk9Bt/Y1TL08LulkYh17xusR4zR3T4i8j8qOrnm4bMTDGrORLQ+OQ==AQAB", new CultureInfo("en")); - manager.UseDynamicUpdateUri = true; - // manager.HttpAuthenticationCredentials = new NetworkCredential("trade", "test123"); + UpdateManager manager = new UpdateManager(new Uri("http://localhost/test/updates.json"), "v6ftlHsEjF+Mgtu439+GMXMdBDOmMlAdi+cQ4VVrU9J68ldgmJk3PmqWpeY5Pk1NALwG4Z3ByDHHG9nihSSavn/COOt2+4jqSJRcW1KshaZ1tVFmKl1KOPmEGdz0Snv4K8CkR5GjZ4IhgDrVYt1SHs1fTB2o5GE24zFofah31okw/UGVVFnQCnSLyt5Gr5fl6lILA91iTOy4vL+S9MLGgXrbYPJTsxL7cATDtqenTglbI60zAhl+kSwbpP+Gp+aELH+L8p3eo52toFBKTASi3mK2nK4op5LgApUJIqGEqcjFSjAphtsCw7Y7SV/KMIJTSOkMzzUTO0djF40y/fmOvJHY4Hn9dcaTByt9m48sQUFuB+eXBk6nSoGDHk5prlueOnZrd0jYcnZJMFPGLiNBeqZBbIgakIEpawy0sZTDu6e4xiRPhWuepcSw6jwxjCtpjLJ+o6V7Xc24spapV5z33cmqx014m0qQJP0XW/jWUgDwzhFiNxPFvJnQ7LEjl/3E0y00uOl8UB0y5aWZJdbC5fCLxpmo0N/Vmw9qUOrhj932eGqr1MOT2HfVm9901aACQHyqj/RpGCzW31OdyweYocs/i9CK3FHFRedVQFg1azgvIn8MR5v3Br8SnIFMua+COSMw5MgUkbLzk21j8jnbF8+cWzSuGo1H3CY4C4+4MFRjCpbOUiKoUOD24zw+0QV9Wz5tTrY4sySYmYBhiuefm7QgJtVmOn1pZGyE5e7Ytqhbw1sid2iYtUhyuLkD6b16UrEujR5K1736ROMfw5Bb3JP5ufiflvuCk+SuzfwuFU4QfglScZnX+qdXKMHDpf6/IVGAJgxWAA+KgE1wLstDDR8tqmy1oWwRfiZusEA/Cd5VRv6iAZ2hVQsMurWWS701P3uuOLOv0A3iHYcgxvM2fk9MZbdxO39atgsvMfG/EVMgUTDk5l/TIE9RWcqI4IFmKI1wPqUG3fGzzZOKCAAKMFgzLrMn9aVzC8+jyl5Wp24Xzn6/vWJRiHEwvuwyvXBtJW+g3EZa4PJLhRcsUkUz2VtToD0YRupKt8wPFTo2QvgmHgic+/llKp0SV1XZI2o77T8NSIJUOzetFCeckdEeE+a9NQbWJ3JNHnhQR+gSixaFx7nXMHbKux+JSmZZmtxtqNgHxsdnREEG4FYEHFSL3dwzH4hOAuUJ0539zTkh4gAovzvLWMA36VpY0SlX0PVWSHpTUWhdcTrII4zuSW8OsJV1v+pv6ZaL48rYxiJ4N/b2qkI3F2dqztwS0fdq64CCa70nHgRiNENUIIElC+HbeIRzpLeHTbmlF6csayu7P8S/ui1KEqOFYigBBPk+ZcGb3gG1yeAoBKMA6V1fl0Y8IQ==AQAB", new CultureInfo("en")); _updaterUI = new UpdaterUI(manager, SynchronizationContext.Current); } diff --git a/nUpdate.UserInterfaceTest/Program.cs b/nUpdate.UserInterfaceTest/Program.cs index 37427e89..a651410c 100644 --- a/nUpdate.UserInterfaceTest/Program.cs +++ b/nUpdate.UserInterfaceTest/Program.cs @@ -1,4 +1,7 @@ -using System; +// Program.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System; using System.Windows.Forms; namespace nUpdate.UserInterfaceTest @@ -16,4 +19,4 @@ static void Main() Application.Run(new MainDialog()); } } -} +} \ No newline at end of file diff --git a/nUpdate.UserInterfaceTest/Properties/AssemblyInfo.cs b/nUpdate.UserInterfaceTest/Properties/AssemblyInfo.cs index 1b890683..34dbb374 100644 --- a/nUpdate.UserInterfaceTest/Properties/AssemblyInfo.cs +++ b/nUpdate.UserInterfaceTest/Properties/AssemblyInfo.cs @@ -1,4 +1,7 @@ -using System.Reflection; +// AssemblyInfo.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System.Reflection; using System.Runtime.InteropServices; using nUpdate.Core; diff --git a/nUpdate.UserInterfaceTest/Properties/Settings.settings b/nUpdate.UserInterfaceTest/Properties/Settings.settings index 39645652..e04fc631 100644 --- a/nUpdate.UserInterfaceTest/Properties/Settings.settings +++ b/nUpdate.UserInterfaceTest/Properties/Settings.settings @@ -1,7 +1,8 @@  + - + \ No newline at end of file diff --git a/nUpdate.UserInterfaceTest/nUpdate.UserInterfaceTest.csproj b/nUpdate.UserInterfaceTest/nUpdate.UserInterfaceTest.csproj index 298032df..05ff3c33 100644 --- a/nUpdate.UserInterfaceTest/nUpdate.UserInterfaceTest.csproj +++ b/nUpdate.UserInterfaceTest/nUpdate.UserInterfaceTest.csproj @@ -65,7 +65,6 @@ - diff --git a/nUpdate.UserInterfaceTest/packages.config b/nUpdate.UserInterfaceTest/packages.config index f70161ba..2164004d 100644 --- a/nUpdate.UserInterfaceTest/packages.config +++ b/nUpdate.UserInterfaceTest/packages.config @@ -1,4 +1,5 @@  + diff --git a/nUpdate.WPFUpdateInstaller/App.config b/nUpdate.WPFUpdateInstaller/App.config new file mode 100644 index 00000000..9350691e --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/App.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/nUpdate.WPFUpdateInstaller/App.xaml b/nUpdate.WPFUpdateInstaller/App.xaml new file mode 100644 index 00000000..bcd810b7 --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/App.xaml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/nUpdate.WPFUpdateInstaller/App.xaml.cs b/nUpdate.WPFUpdateInstaller/App.xaml.cs new file mode 100644 index 00000000..171b753d --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/App.xaml.cs @@ -0,0 +1,18 @@ +// App.xaml.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System.Windows; + +namespace nUpdate.WPFUpdateInstaller +{ + /// + /// Interaktionslogik für "App.xaml" + /// + public partial class App + { + private void Application_Startup(object sender, StartupEventArgs e) + { + Program.Main(e.Args); + } + } +} \ No newline at end of file diff --git a/nUpdate.WPFUpdateInstaller/InstallerServiceProvider.cs b/nUpdate.WPFUpdateInstaller/InstallerServiceProvider.cs new file mode 100644 index 00000000..315baa23 --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/InstallerServiceProvider.cs @@ -0,0 +1,38 @@ +// InstallerServiceProvider.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System; +using System.Collections.Generic; +using nUpdate.UpdateInstaller.Client.GuiInterface; +using nUpdate.WPFUpdateInstaller; + +[assembly: ServiceProvider(typeof(InstallerServiceProvider))] + +namespace nUpdate.WPFUpdateInstaller +{ + public class InstallerServiceProvider : IServiceProvider + { + private readonly Dictionary _services; + + public InstallerServiceProvider() + { + _services = new Dictionary(); + InitializeServices(); + } + + public object GetService(Type serviceType) + { + if (serviceType == null) + throw new ArgumentNullException(nameof(serviceType)); + return !_services.TryGetValue(serviceType, out var service) ? null : service; + } + + private void InitializeServices() + { + var application = new App(); + application.InitializeComponent(); + + _services.Add(typeof(IProgressReporter), new ProgressReporterService()); + } + } +} \ No newline at end of file diff --git a/nUpdate.WPFUpdateInstaller/MainWindow.xaml b/nUpdate.WPFUpdateInstaller/MainWindow.xaml new file mode 100644 index 00000000..92bf5ae7 --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/MainWindow.xaml @@ -0,0 +1,18 @@ + + + + + + + + + \ No newline at end of file diff --git a/nUpdate.WPFUpdateInstaller/MainWindow.xaml.cs b/nUpdate.WPFUpdateInstaller/MainWindow.xaml.cs new file mode 100644 index 00000000..76565b04 --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/MainWindow.xaml.cs @@ -0,0 +1,80 @@ +// MainWindow.xaml.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System; +using System.Drawing.Imaging; +using System.IO; +using System.Windows; +using System.Windows.Media.Imaging; +using nUpdate.Internal.Core; +using nUpdate.UpdateInstaller.Client.GuiInterface; + +namespace nUpdate.WPFUpdateInstaller +{ + /// + /// Interaktionslogik für MainWindow.xaml + /// + public partial class MainWindow : IProgressReporter + { + public MainWindow() + { + InitializeComponent(); + } + + public void Initialize() + { + ShowDialog(); + using (var memory = new MemoryStream()) + { + var bitmap = IconHelper.ExtractAssociatedIcon(Program.ApplicationExecutablePath).ToBitmap(); + bitmap.Save(memory, ImageFormat.Png); + memory.Position = 0; + var bitmapImage = new BitmapImage(); + bitmapImage.BeginInit(); + bitmapImage.StreamSource = memory; + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.EndInit(); + Icon = bitmapImage; + } + + Title = Program.AppName; + copyingLabel.Text = Program.ExtractFilesText; + } + + + public void ReportUnpackingProgress(float progress, string currentFile) + { + Dispatcher.Invoke(() => + { + extractProgressBar.Value = (int) progress; + copyingLabel.Text = string.Format(Program.CopyingText, currentFile); + }); + } + + public void ReportOperationProgress(float progress, string currentOperation) + { + Dispatcher.Invoke(() => + { + extractProgressBar.Value = (int) progress; + copyingLabel.Text = $"{currentOperation}"; + }); + } + + public void Fail(Exception ex) + { + Dispatcher.Invoke(new Action(() => + MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error))); + } + + public void InitializingFail(Exception ex) + { + Dispatcher.Invoke(new Action(() => + MessageBox.Show(ex.Message, "Initialisation Fail", MessageBoxButton.OK, MessageBoxImage.Error))); + } + + public void Terminate() + { + Dispatcher.Invoke(Close); + } + } +} \ No newline at end of file diff --git a/nUpdate.WPFUpdateInstaller/Program.cs b/nUpdate.WPFUpdateInstaller/Program.cs new file mode 100644 index 00000000..98ae391a --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/Program.cs @@ -0,0 +1,199 @@ +// Program.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Windows; +using nUpdate.Internal.Core; +using nUpdate.Internal.Core.Operations; + +namespace nUpdate.WPFUpdateInstaller +{ + internal static class Program + { + /// + /// The program folder where the updated files should be copied to. + /// + public static string AimFolder { get; set; } + + /// + /// The path of the program's executable file. + /// + public static string ApplicationExecutablePath { get; set; } + + /// + /// The name of the program. + /// + public static string AppName { get; set; } + + /// + /// Gets or sets the arguments to handle over to the application. + /// + public static List Arguments { get; set; } + + /// + /// The text of the "Copying..."-label. + /// + public static string CopyingText { get; set; } + + /// + /// The path of the external GUI assembly. + /// + public static string ExternalGuiAssemblyPath { get; set; } + + /// + /// The text of the "Extracting files..."-label. + /// + public static string ExtractFilesText { get; set; } + + /// + /// The text of the file delete information. + /// + public static string FileDeletingOperationText { get; set; } + + /// + /// The text of the error that a file is currently being used by another program. + /// + public static string FileInUseError { get; set; } + + /// + /// The text of the file rename information. + /// + public static string FileRenamingOperationText { get; set; } + + /// + /// The caption of the initializing error message. + /// + public static string InitializingErrorCaption { get; set; } + + /// + /// Gets or sets a value indicating whether the host application has been closed, or not. + /// + public static bool IsHostApplicationClosed { get; set; } + + /// + /// The operations to perform. + /// + public static Dictionary> Operations { get; set; } + + /// + /// The paths of the package files. + /// + public static string[] PackageFilePaths { get; set; } + + /// + /// The text of the process start information. + /// + public static string ProcessStartOperationText { get; set; } + + /// + /// The text of the process stop information. + /// + public static string ProcessStopOperationText { get; set; } + + /// + /// The text of the registry name-value-pair value deleting information. + /// + public static string RegistryNameValuePairDeleteValueOperationText { get; set; } + + /// + /// The text of the registry name-value-pair value setting information. + /// + public static string RegistryNameValuePairSetValueOperationText { get; set; } + + /// + /// The text of the registry sub key creation information. + /// + public static string RegistrySubKeyCreateOperationText { get; set; } + + /// + /// The text of the registry sub key deletion information. + /// + public static string RegistrySubKeyDeleteOperationText { get; set; } + + /// + /// Gets or sets a value indicating whether the host application should be restarted, or not. + /// + public static bool RestartHostApplication { get; set; } + + /// + /// The text of the service start information. + /// + public static string ServiceStartOperationText { get; set; } + + /// + /// The text of the service stop information. + /// + public static string ServiceStopOperationText { get; set; } + + /// + /// The caption of the updating error message. + /// + public static string UpdatingErrorCaption { get; set; } + + + private static void HandlerMethod(object sender, UnhandledExceptionEventArgs e) + { + if (e.ExceptionObject is ThreadAbortException) + return; + if (e.ExceptionObject is Exception exception) + MessageBox.Show(exception.InnerException?.ToString() ?? exception.ToString()); + Application.Current.Shutdown(); + } + + /// + /// Der Haupteinstiegspunkt für die Anwendung. + /// + [STAThread] + internal static void Main(string[] args) + { + AppDomain.CurrentDomain.UnhandledException += HandlerMethod; + + if (args.Length != 1) + { + MessageBox.Show("Updating the application has failed."); + return; + } + + var appArguments = args[0].Split('|'); + + try + { + PackageFilePaths = appArguments[0].Split('%'); + AimFolder = appArguments[1]; + ApplicationExecutablePath = appArguments[2]; + AppName = appArguments[3]; + Operations = + Serializer.Deserialize>>( + Encoding.UTF8.GetString(Convert.FromBase64String(appArguments[4]))); + ExternalGuiAssemblyPath = appArguments[5]; + ExtractFilesText = appArguments[6]; + CopyingText = appArguments[7]; + FileDeletingOperationText = appArguments[8]; + FileRenamingOperationText = appArguments[9]; + RegistrySubKeyCreateOperationText = appArguments[10]; + RegistrySubKeyDeleteOperationText = appArguments[11]; + RegistryNameValuePairDeleteValueOperationText = appArguments[12]; + RegistryNameValuePairSetValueOperationText = appArguments[13]; + ProcessStartOperationText = appArguments[14]; + ProcessStopOperationText = appArguments[15]; + ServiceStartOperationText = appArguments[16]; + ServiceStopOperationText = appArguments[17]; + UpdatingErrorCaption = appArguments[18]; + InitializingErrorCaption = appArguments[19]; + Arguments = Serializer.Deserialize>( + Encoding.UTF8.GetString(Convert.FromBase64String(appArguments[20]))); + // Arguments-property can't be "null" as UpdateManager creates an instance of a List and handles that over + IsHostApplicationClosed = Convert.ToBoolean(appArguments[21]); + RestartHostApplication = Convert.ToBoolean(appArguments[22]); + FileInUseError = appArguments[23]; + } + catch (Exception ex) + { + MessageBox.Show(ex.ToString(), "Error", MessageBoxButton.OK, MessageBoxImage.Error); + } + } + } +} \ No newline at end of file diff --git a/nUpdate.WPFUpdateInstaller/ProgressReporterService.cs b/nUpdate.WPFUpdateInstaller/ProgressReporterService.cs new file mode 100644 index 00000000..fe93b911 --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/ProgressReporterService.cs @@ -0,0 +1,48 @@ +// ProgressReporterService.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System; +using nUpdate.UpdateInstaller.Client.GuiInterface; + +namespace nUpdate.WPFUpdateInstaller +{ + public class ProgressReporterService : IProgressReporter + { + private readonly MainWindow _mainWindow; + + public ProgressReporterService() + { + _mainWindow = new MainWindow(); + } + + public void Fail(Exception ex) + { + _mainWindow.Fail(ex); + } + + public void Initialize() + { + _mainWindow.Initialize(); + } + + public void InitializingFail(Exception ex) + { + _mainWindow.InitializingFail(ex); + } + + public void ReportOperationProgress(float progress, string currentOperation) + { + _mainWindow.ReportOperationProgress(progress, currentOperation); + } + + public void ReportUnpackingProgress(float progress, string currentFile) + { + _mainWindow.ReportUnpackingProgress(progress, currentFile); + } + + public void Terminate() + { + _mainWindow.Terminate(); + } + } +} \ No newline at end of file diff --git a/nUpdate.WPFUpdateInstaller/Properties/AssemblyInfo.cs b/nUpdate.WPFUpdateInstaller/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..d2c4ccb5 --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/Properties/AssemblyInfo.cs @@ -0,0 +1,56 @@ +// AssemblyInfo.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows; + +// Allgemeine Informationen über eine Assembly werden über die folgenden +// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +// die einer Assembly zugeordnet sind. +[assembly: AssemblyTitle("WPFUpdateInstaller for nUpdate")] +[assembly: AssemblyDescription("Ein Installer mit WPF UI im Standarddesign")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("SPS")] +[assembly: AssemblyProduct("nUpdate.WPFUpdateInstaller")] +[assembly: AssemblyCopyright("Copyright © 2018 Sascha Patschka")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly +// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von +// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. +[assembly: ComVisible(false)] + +//Um mit dem Erstellen lokalisierbarer Anwendungen zu beginnen, legen Sie +//ImCodeVerwendeteKultur in der .csproj-Datei +//in einer fest. Wenn Sie in den Quelldateien beispielsweise Deutsch +//(Deutschland) verwenden, legen Sie auf \"de-DE\" fest. Heben Sie dann die Auskommentierung +//des nachstehenden NeutralResourceLanguage-Attributs auf. Aktualisieren Sie "en-US" in der nachstehenden Zeile, +//sodass es mit der UICulture-Einstellung in der Projektdatei übereinstimmt. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //Speicherort der designspezifischen Ressourcenwörterbücher + //(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird, + // oder in den Anwendungsressourcen-Wörterbüchern nicht gefunden werden kann.) + ResourceDictionaryLocation.SourceAssembly //Speicherort des generischen Ressourcenwörterbuchs + //(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird, + // designspezifischen Ressourcenwörterbuch nicht gefunden werden kann.) +)] + + +// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +// +// Hauptversion +// Nebenversion +// Buildnummer +// Revision +// +// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +// übernehmen, indem Sie "*" eingeben: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("0.1.0.0")] +[assembly: AssemblyFileVersion("0.1.0.0")] \ No newline at end of file diff --git a/nUpdate.WPFUpdateInstaller/Properties/Resources.Designer.cs b/nUpdate.WPFUpdateInstaller/Properties/Resources.Designer.cs new file mode 100644 index 00000000..70b6543c --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion: 4.0.30319.42000 +// +// Änderungen an dieser Datei können fehlerhaftes Verhalten verursachen und gehen verloren, wenn +// der Code neu generiert wird. +// +//------------------------------------------------------------------------------ + +namespace nUpdate.WPFUpdateInstaller.Properties +{ + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder-Klasse + // über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der Option /str erneut aus, oder erstellen Sie Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("nUpdate.WPFUpdateInstaller.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenlookups, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/nUpdate.WPFUpdateInstaller/Properties/Resources.resx b/nUpdate.WPFUpdateInstaller/Properties/Resources.resx new file mode 100644 index 00000000..af7dbebb --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/nUpdate.WPFUpdateInstaller/Properties/Settings.Designer.cs b/nUpdate.WPFUpdateInstaller/Properties/Settings.Designer.cs new file mode 100644 index 00000000..271a919b --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace nUpdate.WPFUpdateInstaller.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/nUpdate.WPFUpdateInstaller/Properties/Settings.settings b/nUpdate.WPFUpdateInstaller/Properties/Settings.settings new file mode 100644 index 00000000..c14891b9 --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/Properties/Settings.settings @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/nUpdate.WPFUpdateInstaller/Trade-Updater-Logo-v3.ico b/nUpdate.WPFUpdateInstaller/Trade-Updater-Logo-v3.ico new file mode 100644 index 00000000..40578890 Binary files /dev/null and b/nUpdate.WPFUpdateInstaller/Trade-Updater-Logo-v3.ico differ diff --git a/nUpdate.WPFUpdateInstaller/UpdateArgument.cs b/nUpdate.WPFUpdateInstaller/UpdateArgument.cs new file mode 100644 index 00000000..0cbd350c --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/UpdateArgument.cs @@ -0,0 +1,32 @@ +// UpdateArgument.cs, 12.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +namespace nUpdate.WPFUpdateInstaller +{ + /// + /// Represents an argument that is handled over to the application after the installation of an update. + /// + public class UpdateArgument + { + /// + /// Initializes a new instance of the class. + /// + /// The argument. + /// The execution options that should be used for the . + public UpdateArgument(string argument, UpdateArgumentExecutionOptions executionOptions) + { + Argument = argument; + ExecutionOptions = executionOptions; + } + + /// + /// Gets or sets the argument of the current . + /// + public string Argument { get; set; } + + /// + /// Gets or sets the execution options that should be used for the current . + /// + public UpdateArgumentExecutionOptions ExecutionOptions { get; set; } + } +} \ No newline at end of file diff --git a/nUpdate.UpdateInstaller/Core/UpdateArgumentExecutionOptions.cs b/nUpdate.WPFUpdateInstaller/UpdateArgumentExecutionOptions.cs similarity index 80% rename from nUpdate.UpdateInstaller/Core/UpdateArgumentExecutionOptions.cs rename to nUpdate.WPFUpdateInstaller/UpdateArgumentExecutionOptions.cs index 548d3d5f..054328f6 100644 --- a/nUpdate.UpdateInstaller/Core/UpdateArgumentExecutionOptions.cs +++ b/nUpdate.WPFUpdateInstaller/UpdateArgumentExecutionOptions.cs @@ -1,6 +1,7 @@ -// Copyright © Dominic Beger 2018 +// UpdateArgumentExecutionOptions.cs, 12.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 -namespace nUpdate.UpdateInstaller.Core +namespace nUpdate.WPFUpdateInstaller { /// /// Sets the behaviour of an when an update is installed. diff --git a/nUpdate.WPFUpdateInstaller/nUpdate.WPFUpdateInstaller.csproj b/nUpdate.WPFUpdateInstaller/nUpdate.WPFUpdateInstaller.csproj new file mode 100644 index 00000000..e5eff15b --- /dev/null +++ b/nUpdate.WPFUpdateInstaller/nUpdate.WPFUpdateInstaller.csproj @@ -0,0 +1,122 @@ + + + + + Debug + AnyCPU + {E2E8A9EA-9A0D-4C3C-8DFE-30339FCE1810} + Library + nUpdate.WPFUpdateInstaller + nUpdate.WPFUpdateInstaller + v4.6 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + Trade-Updater-Logo-v3.ico + + + + + + + + + + + + + 4.0 + + + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + MainWindow.xaml + Code + + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + {5E63208A-8F06-4B99-A41D-F469BE4CFD00} + nUpdate.UpdateInstaller.Client.GuiInterface + + + {EFB71D69-EBF9-4F60-B776-DE443730A3DD} + nUpdate.Internal + + + + + + + \ No newline at end of file diff --git a/nUpdate.WPFUserInterface.Test/App.config b/nUpdate.WPFUserInterface.Test/App.config new file mode 100644 index 00000000..9350691e --- /dev/null +++ b/nUpdate.WPFUserInterface.Test/App.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/nUpdate.WPFUserInterface.Test/App.xaml b/nUpdate.WPFUserInterface.Test/App.xaml new file mode 100644 index 00000000..8cf2ae82 --- /dev/null +++ b/nUpdate.WPFUserInterface.Test/App.xaml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/nUpdate.WPFUserInterface.Test/App.xaml.cs b/nUpdate.WPFUserInterface.Test/App.xaml.cs new file mode 100644 index 00000000..be0d0b3d --- /dev/null +++ b/nUpdate.WPFUserInterface.Test/App.xaml.cs @@ -0,0 +1,20 @@ +// App.xaml.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace nUpdate.WPFUserInterface.Test +{ + /// + /// Interaktionslogik für "App.xaml" + /// + public partial class App : Application + { + } +} \ No newline at end of file diff --git a/nUpdate.WPFUserInterface.Test/MainWindow.xaml b/nUpdate.WPFUserInterface.Test/MainWindow.xaml new file mode 100644 index 00000000..2dec2a1c --- /dev/null +++ b/nUpdate.WPFUserInterface.Test/MainWindow.xaml @@ -0,0 +1,16 @@ + + + + + + + \ No newline at end of file diff --git a/nUpdate.WPFUserInterface/UI/UserControls/uclChangelogView.xaml.cs b/nUpdate.WPFUserInterface/UI/UserControls/uclChangelogView.xaml.cs new file mode 100644 index 00000000..29fef564 --- /dev/null +++ b/nUpdate.WPFUserInterface/UI/UserControls/uclChangelogView.xaml.cs @@ -0,0 +1,18 @@ +// uclChangelogView.xaml.cs, 10.06.2019 +// Copyright (C) Dominic Beger 17.06.2019 + +using System.Windows.Controls; + +namespace nUpdate.WPFUserInterface.UI.UserControls +{ + /// + /// Interaktionslogik für uclChangelogView.xaml + /// + public partial class uclChangelogView : UserControl + { + public uclChangelogView() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/nUpdate.WPFUserInterface/UI/UserControls/uclDownloadUpdate.xaml b/nUpdate.WPFUserInterface/UI/UserControls/uclDownloadUpdate.xaml new file mode 100644 index 00000000..7f071716 --- /dev/null +++ b/nUpdate.WPFUserInterface/UI/UserControls/uclDownloadUpdate.xaml @@ -0,0 +1,38 @@ + + + + + + +