From edab522e0ed1ad994febed2599115b122a366390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20=C5=A0taleker?= Date: Tue, 18 Jul 2023 11:30:02 +0200 Subject: [PATCH] prvi --- InfosysPublisher.sln | 25 ++ InfosysPublisher/App.xaml | 9 + InfosysPublisher/App.xaml.cs | 18 ++ InfosysPublisher/AssemblyInfo.cs | 10 + InfosysPublisher/Classes/Encryption.cs | 106 +++++++ InfosysPublisher/Classes/Settings.cs | 54 ++++ InfosysPublisher/InfosysPublisher.csproj | 27 ++ InfosysPublisher/WinMain.xaml | 54 ++++ InfosysPublisher/WinMain.xaml.cs | 388 +++++++++++++++++++++++ InfosysPublisher/WinSettings.xaml | 37 +++ InfosysPublisher/WinSettings.xaml.cs | 93 ++++++ InfosysPublisher/infosysPublisher.ico | Bin 0 -> 67646 bytes 12 files changed, 821 insertions(+) create mode 100644 InfosysPublisher.sln create mode 100644 InfosysPublisher/App.xaml create mode 100644 InfosysPublisher/App.xaml.cs create mode 100644 InfosysPublisher/AssemblyInfo.cs create mode 100644 InfosysPublisher/Classes/Encryption.cs create mode 100644 InfosysPublisher/Classes/Settings.cs create mode 100644 InfosysPublisher/InfosysPublisher.csproj create mode 100644 InfosysPublisher/WinMain.xaml create mode 100644 InfosysPublisher/WinMain.xaml.cs create mode 100644 InfosysPublisher/WinSettings.xaml create mode 100644 InfosysPublisher/WinSettings.xaml.cs create mode 100644 InfosysPublisher/infosysPublisher.ico diff --git a/InfosysPublisher.sln b/InfosysPublisher.sln new file mode 100644 index 0000000..53edfa0 --- /dev/null +++ b/InfosysPublisher.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33815.320 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InfosysPublisher", "InfosysPublisher\InfosysPublisher.csproj", "{96AECF20-EE37-45E8-BEA1-4C221E1E0BC7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {96AECF20-EE37-45E8-BEA1-4C221E1E0BC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {96AECF20-EE37-45E8-BEA1-4C221E1E0BC7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {96AECF20-EE37-45E8-BEA1-4C221E1E0BC7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {96AECF20-EE37-45E8-BEA1-4C221E1E0BC7}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {EA731043-FAF1-479E-8787-1E45190E5DC9} + EndGlobalSection +EndGlobal diff --git a/InfosysPublisher/App.xaml b/InfosysPublisher/App.xaml new file mode 100644 index 0000000..c3c539e --- /dev/null +++ b/InfosysPublisher/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/InfosysPublisher/App.xaml.cs b/InfosysPublisher/App.xaml.cs new file mode 100644 index 0000000..c958877 --- /dev/null +++ b/InfosysPublisher/App.xaml.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using System.Windows; + +namespace InfosysPublisher +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/InfosysPublisher/AssemblyInfo.cs b/InfosysPublisher/AssemblyInfo.cs new file mode 100644 index 0000000..8b5504e --- /dev/null +++ b/InfosysPublisher/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/InfosysPublisher/Classes/Encryption.cs b/InfosysPublisher/Classes/Encryption.cs new file mode 100644 index 0000000..133b0b6 --- /dev/null +++ b/InfosysPublisher/Classes/Encryption.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace ResevalnaScanner.Classes +{ + internal static class Encryption + { + public enum Type + { + General, + Licence, + } + + public static string AesEncrypt(this string iPlain, Type iType = Type.General, string iKey = "", string iSalt = "") + { + if (iPlain.Length > 16 && iPlain.Length % 16 != 0) + { + var size = ((iPlain.Length / 16) + 1) * 16; + iPlain += new string(' ', size - iPlain.Length); + } + + switch (iType) + { + case Type.General: + iKey = "DEWSCYUSBP2AQ6JnMc_InfosysPublisher_S9Gj3GU4hchg7J38zZ"; + iSalt = "P4TqMkZ3FZd6Y5K5uNykmngCATDpP7PrxnACj2sFkfc6"; + break; + case Type.Licence: + iKey = "2D849KZ6RjpQCG_ResevalnaLicense_crKwBTjnskwycCvy7N"; + iSalt = "kUt7E6ngrYqA7watQ8YMPYNdzYFgLcCpuuchS96SZwC6"; + break; + } + + if (string.IsNullOrEmpty(iPlain)) + { + return ""; + } + + var saltByes = Encoding.ASCII.GetBytes(iSalt); + var key = new Rfc2898DeriveBytes(iKey, saltByes); + + var aesAlgorithm = Aes.Create(); + aesAlgorithm.KeySize = 256; + aesAlgorithm.Key = key.GetBytes(aesAlgorithm.KeySize / 8); + aesAlgorithm.IV = key.GetBytes(aesAlgorithm.BlockSize / 8); + + var msEncrypt = new MemoryStream(); + using (var encrypt = aesAlgorithm.CreateEncryptor(aesAlgorithm.Key, aesAlgorithm.IV)) + using (var csEncrypt = new CryptoStream(msEncrypt, encrypt, CryptoStreamMode.Write)) + { + using (var swEncrypt = new StreamWriter(csEncrypt)) + { + swEncrypt.Write(iPlain); + } + } + + return Convert.ToBase64String(msEncrypt.ToArray()); + } + + public static string AesDecrypt(this string iCipherText, Type iType = Type.General, string iKey = "", string iSalt = "") + { + switch (iType) + { + case Type.General: + iKey = "DEWSCYUSBP2AQ6JnMc_InfosysPublisher_S9Gj3GU4hchg7J38zZ"; + iSalt = "P4TqMkZ3FZd6Y5K5uNykmngCATDpP7PrxnACj2sFkfc6"; + break; + case Type.Licence: + iKey = "2D849KZ6RjpQCG_ResevalnaLicense_crKwBTjnskwycCvy7N"; + iSalt = "kUt7E6ngrYqA7watQ8YMPYNdzYFgLcCpuuchS96SZwC6"; + break; + } + + if (string.IsNullOrEmpty(iCipherText)) + { + return ""; + } + + var saltByes = Encoding.ASCII.GetBytes(iSalt); + var key = new Rfc2898DeriveBytes(iKey, saltByes); + + var aesAlgorithm = Aes.Create(); + aesAlgorithm.KeySize = 256; + aesAlgorithm.Key = key.GetBytes(aesAlgorithm.KeySize / 8); + aesAlgorithm.IV = key.GetBytes(aesAlgorithm.BlockSize / 8); + + var cipherTextBytes = Convert.FromBase64String(iCipherText); + var plainTextBytes = new byte[iCipherText.Length]; + var byteCount = 0; + + using (var decrypt = aesAlgorithm.CreateDecryptor(aesAlgorithm.Key, aesAlgorithm.IV)) + using (var msDecrypt = new MemoryStream(cipherTextBytes)) + using (var csDecrypt = new CryptoStream(msDecrypt, decrypt, CryptoStreamMode.Read)) + { + byteCount = csDecrypt.Read(plainTextBytes, 0, plainTextBytes.Length); + } + + return Encoding.UTF8.GetString(plainTextBytes, 0, byteCount).Trim(); + } + } +} diff --git a/InfosysPublisher/Classes/Settings.cs b/InfosysPublisher/Classes/Settings.cs new file mode 100644 index 0000000..2207ca6 --- /dev/null +++ b/InfosysPublisher/Classes/Settings.cs @@ -0,0 +1,54 @@ +using Newtonsoft.Json; +using ResevalnaScanner.Classes; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace InfosysPublisher.Classes +{ + internal class Settings + { + public class Application + { + //SQL strežniki + //Privatna polja + [JsonProperty] private string _sftpUsername; + [JsonProperty] private string _sftpPassword; + + //Javna polja + public string SftpServerAddress { get; set; } + public int SftpPort { get; set; } + public int BuildSeconds { get; set; } + public string LastFolder { get; set; } + + [JsonIgnore] + public string SftpUsername + { + get => _sftpUsername.AesDecrypt(); + set => _sftpUsername = value.AesEncrypt(); + } + + [JsonIgnore] + public string SftpPassword + { + get => _sftpPassword.AesDecrypt(); + set => _sftpPassword = value.AesEncrypt(); + } + + public void Save(string iPath) + { + var json = JsonConvert.SerializeObject(this); + + if (!Directory.Exists(Path.GetDirectoryName(iPath))) + { + Directory.CreateDirectory(Path.GetDirectoryName(iPath)); + } + + File.WriteAllText(iPath, json); + } + } + } +} diff --git a/InfosysPublisher/InfosysPublisher.csproj b/InfosysPublisher/InfosysPublisher.csproj new file mode 100644 index 0000000..3521c28 --- /dev/null +++ b/InfosysPublisher/InfosysPublisher.csproj @@ -0,0 +1,27 @@ + + + + WinExe + net6.0-windows + enable + true + 1.0.1.0 + infosysPublisher.ico + + + + + + + + + + + + + + Always + + + + diff --git a/InfosysPublisher/WinMain.xaml b/InfosysPublisher/WinMain.xaml new file mode 100644 index 0000000..f493fb8 --- /dev/null +++ b/InfosysPublisher/WinMain.xaml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pripravi samo zip + + + + diff --git a/InfosysPublisher/WinMain.xaml.cs b/InfosysPublisher/WinMain.xaml.cs new file mode 100644 index 0000000..ce8d710 --- /dev/null +++ b/InfosysPublisher/WinMain.xaml.cs @@ -0,0 +1,388 @@ +using InfosysPublisher.Classes; +using Newtonsoft.Json; +using Renci.SshNet; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices.ComTypes; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using System.Xml; +using Path = System.IO.Path; + +namespace InfosysPublisher +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + #region Classes + + public class Project + { + public string Name { get; set; } + public string Path { get; set; } + } + + #endregion + private Settings.Application? _application; + + + private string _projectPath; + private List _projects; + private Project? _selectedProject = null; + private string _selectedProjectSubPath = ""; + private string _selectedProjectPublishLocation = ""; + private string _selectedProjectVersion = ""; + + private const string SftpArchivePath = "Archive"; + public MainWindow() + { + InitializeComponent(); + + var version = typeof(App).Assembly.GetName().Version; + this.Title += " " + version; + + _application = WinSettings.GetSettings(); + + TbProjectsPath.LostFocus += TbProjectsPath_LostFocus; + CbProjects.SelectionChanged += CbProjects_SelectionChanged; + + BtnPublish.Click += BtnPublish_Click; + BtnSettings.Click += BtnSettings_Click; + + Closing += MainWindow_Closing; + + if (_application == null) + { + OpenSettings(); + return; + } + + TbProjectsPath.Text = _application.LastFolder; + LoadProjects(); + } + + private void BtnSettings_Click(object sender, RoutedEventArgs e) + { + OpenSettings(); + } + + private void MainWindow_Closing(object? sender, System.ComponentModel.CancelEventArgs e) + { + var settings = WinSettings.GetSettings(); + if (settings == null) + return; + settings.LastFolder = TbProjectsPath.Text; + WinSettings.SaveSettings(settings); + } + + private void OpenSettings() + { + var win = new WinSettings(); + win.ShowDialog(); + if (win.DialogResult != null && (bool)win.DialogResult) + { + _application = WinSettings.GetSettings(); + } + } + + private void CbProjects_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + _selectedProject = (Project)CbProjects.SelectedItem; + LoadProject(); + } + + private void TbProjectsPath_LostFocus(object sender, RoutedEventArgs e) + { + LoadProjects(); + } + + private void LoadProjects() + { + _projectPath = TbProjectsPath.Text; + + if (!Directory.Exists(_projectPath)) + { + MessageBox.Show($"Pot {_projectPath} ne obstaja!"); + return; + } + + _projects = new List(); + var dirInfo = new DirectoryInfo(_projectPath); + + dirInfo.GetDirectories() + .ToList() + .ForEach(directoryInfo => directoryInfo.GetFiles("*.sln") + .ToList() + .ForEach(x => _projects.Add(new Project + { + Name = $"{directoryInfo.Name}/{x.Name}", + Path = x.FullName + }))); + + CbProjects.ItemsSource = _projects; + } + + private void LoadProject() + { + TbOutput.Text = ""; + LblProjectInfo.Content = ""; + BtnPublish.IsEnabled = false; + if (_selectedProject == null) + return; + + _selectedProjectVersion = ""; + _selectedProjectSubPath = ""; + _selectedProjectPublishLocation = ""; + + var lines = File.ReadLines(_selectedProject.Path); + lines.Where(line => line.StartsWith("Project")) + .ToList() + .ForEach(line => + { + var projectTitle = line.Split(",")[1].Replace(" ", "").Replace("\"", "").Split(@"\")[0]; + var projectSubPath = Path.Combine(new FileInfo(_selectedProject.Path)?.DirectoryName ?? "", projectTitle); + var projectFileInfos = new DirectoryInfo(projectSubPath) + .GetFiles("*.cs") + .Where(x => x.Name is "App.xaml.cs" or "Program.cs") + .ToList(); + + if (projectFileInfos.Count <= 0) return; + + var csLines = File.ReadLines(projectFileInfos[0].FullName).ToList(); + + csLines.Where(csLine => csLine.StartsWith("[assembly: AssemblyVersion(")) + .ToList() + .ForEach(csLine => + { + _selectedProjectVersion = csLine.Replace("[assembly: AssemblyVersion(\"", "").Replace("\")]", ""); + _selectedProjectSubPath = projectSubPath; + + System.Diagnostics.Debug.WriteLine(_selectedProjectVersion); + }); + if (_selectedProjectSubPath != "") + { + csLines.Where(csLine => csLine.StartsWith("//Publish location:")) + .ToList() + .ForEach(csLine => + { + _selectedProjectPublishLocation = csLine.Replace("//Publish location:", ""); + + System.Diagnostics.Debug.WriteLine(_selectedProjectPublishLocation); + }); + } + }); + + if (_selectedProjectVersion == "" || _selectedProjectSubPath == "" || _selectedProjectPublishLocation == "") + return; + + LblProjectInfo.Content = $"Verzija: {_selectedProjectVersion} Pot: {_selectedProjectPublishLocation}"; + + BtnPublish.IsEnabled = true; + } + + private async void BtnPublish_Click(object sender, RoutedEventArgs e) + { + if (_selectedProject == null || _application == null) + return; + + var releaseFolder = Path.Combine(_selectedProjectSubPath, @"bin\Release"); + if (!Directory.Exists(releaseFolder)) + { + MessageBox.Show($"Mapa {releaseFolder} ne obstaja!"); + return; + } + + GridProgress.Visibility = Visibility.Visible; + LblLoading.Content = $"Čiščenje mape {releaseFolder}"; + await Task.Run(() => + { + var diReleaseFolder = new DirectoryInfo(releaseFolder); + + foreach (var file in diReleaseFolder.GetFiles()) + { + file.Delete(); + } + foreach (var dir in diReleaseFolder.GetDirectories()) + { + dir.Delete(true); + } + }); + + LblLoading.Content = $"Rebuild {_selectedProject.Path}"; + var output = ""; + await Task.Run(() => + { + var command = $"devenv {_selectedProject.Path} /Rebuild \"Release\""; + var cmd = new Process(); + cmd.StartInfo.FileName = "cmd.exe"; + cmd.StartInfo.RedirectStandardInput = true; + cmd.StartInfo.RedirectStandardOutput = true; + cmd.StartInfo.CreateNoWindow = true; + cmd.StartInfo.UseShellExecute = false; + cmd.Start(); + + cmd.StandardInput.WriteLine(command); + //cmd.StandardInput.WriteLine("echo Oscar"); + cmd.StandardInput.Flush(); + cmd.StandardInput.Close(); + cmd.WaitForExit(_application.BuildSeconds * 1000); + output = cmd.StandardOutput.ReadToEnd(); + Debug.WriteLine("\n\n\n\n"); + Debug.WriteLine(output); + //System.Diagnostics.Process.Start("CMD.exe", ""); + }); + TbOutput.Text = output; + + var zipDirectory = new DirectoryInfo(releaseFolder).Parent?.FullName ?? ""; + var zipPath = Path.Combine(zipDirectory, "Package.zip"); + LblLoading.Content = $"Zip {zipPath}"; + if (File.Exists(zipPath)) + File.Delete(zipPath); + + await Task.Run(() => + { + ZipFile.CreateFromDirectory(releaseFolder, zipPath, CompressionLevel.Optimal, false); + }); + + if (ChbPripraviSamoZip.IsChecked != null && (bool) ChbPripraviSamoZip.IsChecked) + { + Process.Start("explorer.exe", zipDirectory); + } + else + { + //InfosysUpdate + //v&H6c$wTbTkgSgdWvL*8k$st3#z5X + LblLoading.Content = $"Upload to SFTP"; + var error = ""; + await Task.Run(() => + { + try + { + using var sftpClient = new SftpClient(_application.SftpServerAddress, _application.SftpPort, + _application.SftpUsername, _application.SftpPassword); + sftpClient.Connect(); + + if (!sftpClient.Exists(_selectedProjectPublishLocation)) + sftpClient.CreateDirectory(_selectedProjectPublishLocation); + + if (!sftpClient.Exists(SftpArchivePath)) + sftpClient.CreateDirectory(SftpArchivePath); + + var files = sftpClient.ListDirectory(_selectedProjectPublishLocation).ToList(); + var xmlVersion = ""; + //arhiv + foreach (var file in files) + { + if (!file.Name.ToLower().EndsWith(".xml")) + continue; + + var tmpXmlFile = Path.GetTempFileName(); + + using (var tmpFile = File.OpenWrite(tmpXmlFile)) + { + sftpClient.DownloadFile(file.FullName, tmpFile); + } + + try + { + var xmlContent = File.ReadAllText(tmpXmlFile); + if (!string.IsNullOrEmpty(xmlContent)) + { + //Oddaljena verzije + var xmlDocument = new XmlDocument(); + xmlDocument.LoadXml(xmlContent); + var xmlNode = xmlDocument.SelectSingleNode("/Update"); + xmlVersion = xmlNode["Version"].InnerText; + } + } + catch (Exception exception) + { + error += "\n\n"; + error += exception.ToString(); + } + + File.Delete(tmpXmlFile); + } + + if (xmlVersion != "") + { + var projectArchive = SftpArchivePath + "/" + _selectedProjectPublishLocation; + if (!sftpClient.Exists(projectArchive)) + sftpClient.CreateDirectory(projectArchive); + + var archiveFolderWithoutIndex = projectArchive + "/" + xmlVersion.Replace(".", "_"); + var archiveFolder = archiveFolderWithoutIndex; + var index = 1; + while (sftpClient.Exists(archiveFolder)) + { + archiveFolder = archiveFolderWithoutIndex + "_" + index; + index++; + } + + sftpClient.CreateDirectory(archiveFolder); + + foreach (var file in files) + { + if (!file.IsRegularFile) + continue; + + sftpClient.Get(file.FullName).MoveTo(archiveFolder + "/" + file.Name); + + } + } + + //Upload + var tmpXmlFileUpload = Path.GetTempFileName(); + string xml = $@" + + {_selectedProjectVersion} +"; + File.WriteAllText(tmpXmlFileUpload, xml); + using (var fileStream = new FileStream(tmpXmlFileUpload, FileMode.Open)) + { + sftpClient.UploadFile(fileStream, _selectedProjectPublishLocation + "/" + "Update.xml", + true); + } + + using (var fileStream = new FileStream(zipPath, FileMode.Open)) + { + sftpClient.UploadFile(fileStream, _selectedProjectPublishLocation + "/" + "Package.zip", + true); + } + + File.Delete(tmpXmlFileUpload); + sftpClient.Disconnect(); + } + catch (Exception ex) + { + error += "\n\n"; + error += ex.ToString(); + } + }); + if (error != "") + { + MessageBox.Show(error); + } + } + + GridProgress.Visibility = Visibility.Hidden; + LblLoading.Content = ""; + } + } +} diff --git a/InfosysPublisher/WinSettings.xaml b/InfosysPublisher/WinSettings.xaml new file mode 100644 index 0000000..2293fe2 --- /dev/null +++ b/InfosysPublisher/WinSettings.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/InfosysPublisher/WinSettings.xaml.cs b/InfosysPublisher/WinSettings.xaml.cs new file mode 100644 index 0000000..ca811ec --- /dev/null +++ b/InfosysPublisher/WinSettings.xaml.cs @@ -0,0 +1,93 @@ +using InfosysPublisher.Classes; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace InfosysPublisher +{ + /// + /// Interaction logic for WinSettings.xaml + /// + public partial class WinSettings : Window + { + private static string _settingsPath; + private static string _applicationPath; + + public WinSettings() + { + InitializeComponent(); + + BtnSave.Click += BtnSave_Click; + + LoadSettings(); + } + + private void BtnSave_Click(object sender, RoutedEventArgs e) + { + SaveSettings(); + } + + private void SaveSettings() + { + var settings = new Settings.Application + { + SftpServerAddress = TbSftpServer.Text, + SftpPort = Convert.ToInt32(TbSftpPort.Text), + SftpUsername = TbSftpUsername.Text, + SftpPassword = TbSftpPassword.Text, + BuildSeconds = Convert.ToInt32(TbBuildDuration.Text) + }; + + SaveSettings(settings); + + this.DialogResult = true; + } + + private void LoadSettings() + { + var settings = GetSettings() ?? new Settings.Application(); + + TbSftpServer.Text = settings.SftpServerAddress; + TbSftpPort.Text = settings.SftpPort.ToString(); + TbSftpUsername.Text = settings.SftpUsername; + TbSftpPassword.Text = settings.SftpPassword; + TbBuildDuration.Text = settings.BuildSeconds.ToString(); + } + + private static void SetPaths() + { + _applicationPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + _settingsPath = _applicationPath + @"\InfosysPublisher.json"; + } + + internal static Settings.Application? GetSettings() + { + SetPaths(); + + if (File.Exists(_settingsPath)) + { + return JsonConvert.DeserializeObject(File.ReadAllText(_settingsPath)) ?? new Settings.Application(); + } + + return null; + } + + internal static void SaveSettings(Settings.Application iSettings) + { + SetPaths(); + iSettings.Save(_settingsPath); + } + } +} diff --git a/InfosysPublisher/infosysPublisher.ico b/InfosysPublisher/infosysPublisher.ico new file mode 100644 index 0000000000000000000000000000000000000000..695d097b016ac720501000d173c1d35a4cef7d3e GIT binary patch literal 67646 zcmeHw2V7N2mi{yJPEYTI-I?v#|8Hk^rzg+s%=C29PPSqe15pJe2NNo0MMcG&6|~Kv z%~?{O)FVi9K*XHlTNxCky7y{(8>Lso%|=HSK#xb7oEZ zcJ8dH59ZB|fA+=fcqxuhM!uL6FVm+?koZYsW%8tPWua%N_r0X}iQ}G4of7vXx<^OI zifevg%f^r9&6#;`W5y;)UcX*aQZ{_gDYe-CugCA(upv!WtXL@v7A%y7ix$bkh5tCj z-@Ih$a+w@A{t@th65!qF!id;@-|ate;BjW=HrcUb2Wb2Ej7rhx?b~JN&K=-^4U&+M zAZrs7CGj7K64tE2Z%=(TbYP!nkp1%!fu8LGS~iv~o6_#y`|7@2xpGCm{PN2}bnV(T zsR+_-J8G+>JV$ky#(Jg6WBKF9k4tuTwj4QfYMbVivXG9arux+-Z(~KeS z$-L92Pb)fg>XeXp%{+!WO^3$3lP6D#rV}SlsIuf`#x*fNH#b-I@82&64jjN(u+vH$ z`?h0z*u8tV%4gg>9&&s!=k3|EN9AQ^W~#C*L)x}&n=p^Gb?a7Pz9wGp+qX}(tMgc% zv}MZ{mB)TC&it~{=FOYcZy~Q}KGh+4;^@)*C$R&12(T^~64UFay`mya5dj|6BEwpn zx_1oztFL>#uVzdc|Lxto_nv4SKv}(T;evWrd-v{DedTW{j#$o~Se|Lbmss!_>okVE zX8N&X$5h-{pLygH>M+KQdAd#hPGg?NiT5Mc8XMk=V}ELDs=9wlN($`7=aihBtZ-mk zj2rWkl9CkG#ENla9?NEBWhw0J>#c`f&HHC$WC-KB9^>o>e*;6EUe=Jmi*4ECPd#_6 z;P|t7v!_04es^5KDcEd@+Cbr`R<)NcQFoJRPxHP zm2$>sObp6GT7PleB~MWXbvqn`880X(P-74C^78Uj8C{O|CzdS7Jcc^&{Q2`r)^#4! zj~+d$h2i^)bg6rW^AZ=lw`5 zr|U3e9_z3!^GHl%$UgC2#x&;T=jW@o$SdSyJ~QIRXG<)JH?h+^phG@mBQNN5@(X2} z@}_ymsJ~f<_t0rNZOh_HC^*uvglOGU1=+-evVCOIU>svoD z`Fl0023c3whx@yk#trf{K_65R5z~?dvwr~o*dNoU^OGAlZhmL91^8UquI?v)yE8-{ zr`!=c##!G;lx_CYn8!HpMZIq<%lnbfHKvR+O_yPuJj3U2Y>(xrAK2ceO`B}=H}y5k za{M&vZtCas^mNs>y-wC+0eQ$+hvl>$PD@L(>U*ZK95H2IjCGjDd$AAfn{kY=zpwqZ zuFG~E$^Nlp1&>D$8z6q34UP})-~DI3yS6o9&Q~SO53 A9Vl;wm{X6p{-2aBZL0} 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