using ICSharpCode.SharpZipLib.Zip; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Configuration; using Microsoft.JSInterop; using MP.AppAuth; using MP.AppAuth.Services; using MP.Land.Data; using Newtonsoft.Json; using NLog; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; namespace MP.Land.Pages { public partial class UpdateManager : ComponentBase, IDisposable { #region Public Methods /// /// Procedura di aggiunta folder a ZipFile, ricorsiva /// /// /// /// public void AddFolderToZip(ZipFile f, string root, string folder) { string relative = folder.Substring(root.Length); if (relative.Length > 0) { f.AddDirectory(relative); } foreach (string file in Directory.GetFiles(folder)) { relative = file.Substring(root.Length); f.Add(file, relative); } foreach (string subFolder in Directory.GetDirectories(folder)) { this.AddFolderToZip(f, root, subFolder); } } public void Dispose() { ListRecords = null; GC.Collect(); } #endregion Public Methods #region Protected Fields protected UpdateMan updateManAuth = new UpdateMan("SWDownloader", "viaD@nte16"); #endregion Protected Fields #region Protected Properties [Inject] protected AppAuthService AppDService { get; set; } [Inject] protected LMessageService AppMService { get; set; } [Inject] protected IConfiguration Configuration { get; set; } [Inject] protected LicenseService LicServ { get; set; } = null!; protected string outMessages { get; set; } = ""; protected int percLoading { get; set; } = 0; protected bool showProgress { get; set; } = false; protected bool showUpdate { get; set; } = false; [Inject] protected SyncService SyncServ { get; set; } = null!; #endregion Protected Properties #region Protected Methods /// /// Restituisce size calcolata /// /// /// protected string CalcSize(long origSize) { return MeasureUtils.SizeSuffix(origSize, 1); } protected void CloseProgUpdate() { showUpdate = false; } [Inject] protected IJSRuntime JSRuntime { get; set; } = null!; /// /// Cicla su tutti i record ed effettua il download /// protected async Task DownloadAll() { if (!await JSRuntime.InvokeAsync("confirm", "Confermi di voler scaricare tutti gli update? L'operazione potrebbe richiedere alcuni minuti.")) return; // init progress... showProgress = true; showUpdate = true; outMessages = $"Iniziato download per {numSteps} packages"; percLoading = 0; TotalMb = 0; numApp = 0; await InvokeAsync(StateHasChanged); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); // ciclo su tutti quelli con licenza valida... List rawList = ListRecords .Where(x => !string.IsNullOrEmpty(x.LicenseKey)).ToList(); List authList = new List(); // ciclo SOLO tra quelli davvero autorizzati... foreach (var item in rawList) { if (LicServ.checkLicenseActive(item.LicenseKey)) { authList.Add(item); } } foreach (var item in authList) { ScaricaSingolo(item); await InvokeAsync(StateHasChanged); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; outMessages = $"Effettuato download di {numApp} update | {CalcSize(TotalMb)} in {ts.TotalSeconds:N2} s"; await InvokeAsync(StateHasChanged); await Task.Delay(1000); showProgress = false; await InvokeAsync(StateHasChanged); } protected string localPath(string localRepo) { return @$"{Configuration["ServerConf:downloadPath"]}\{localRepo}\{Configuration["appVers"]}"; ; } protected override async Task OnInitializedAsync() { ListRecords = null; #if DEBUG AppDir = new DirectoryInfo(Path.Combine("\\\\iis01.egalware.com", "c$\\inetpub\\wwwroot\\MP\\LAND")); #else AppDir = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)); #endif await Task.Delay(1); AppMService.ShowSearch = false; AppMService.PageName = "Update Manager"; AppMService.PageIcon = "fas fa-download pe-2"; await ReloadData(); } protected async Task ReloadData() { // importante altrimenti NON mostra update UI await Task.Delay(1); ListRecords = await AppDService.UpdManList(); totalCount = ListRecords.Count(); await Task.Delay(1); } /// /// Cicla su tutti i record applicativi, crea ZIP cifrato + upload su LiMan /// protected async Task UploadBackupConfig() { Log.Info("Inizio procedura UploadBackupConfig"); // init progress... showProgress = true; showUpdate = true; outMessages = $"Inizio preparazione per upload configurazioni di {numSteps} packages"; await InvokeAsync(StateHasChanged); Log.Info(outMessages); percLoading = 0; TotalMb = 0; numApp = 0; numIOB = 0; Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); // ciclo su tutti quelli con licenza valida... List rawList = ListRecords .Where(x => !string.IsNullOrEmpty(x.LicenseKey)).ToList(); authList = new List(); // ciclo SOLO tra quelli davvero autorizzati... foreach (var item in rawList) { if (LicServ.checkLicenseActive(item.LicenseKey)) { authList.Add(item); } } Log.Info($"Verifica App: {authList.Count} autorizzate"); // recupero conf files foreach (var item in authList) { // cerco i file di conf e li copio RecuperaConf(item); await Task.Delay(1); await InvokeAsync(StateHasChanged); } Log.Info($"Recuperato conf Applicazioni"); // recupero i file IOB RecuperaIobConf(); Log.Info($"Recuperato conf IOB"); // salvo Tab Db come json await SaveDbConfAsJson(); Log.Info($"Salvato conf DB come json"); // ora creo il file zip PrepareZip(); Log.Info($"Preparato file ZIP"); // effettuo upload await UploadZip(); Log.Info($"Completato upload ZIP"); // concludo! stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; outMessages = $"Effettuato Upload backup configurazioni | NumApp: {numApp} | NumTab: {numTab} | NumIob: {numIOB} | {CalcSize(TotalMb)} | {ts.TotalSeconds:N2} s"; Log.Info(outMessages); await InvokeAsync(StateHasChanged); await Task.Delay(1000); showProgress = false; await InvokeAsync(StateHasChanged); } protected long WriteTabJson(string filePath, List dataList) { long size = 0; try { string rawData = JsonConvert.SerializeObject(dataList, Formatting.Indented); File.WriteAllText(filePath, rawData); FileInfo fInfo = new FileInfo(filePath); size = fInfo.Length; } catch (Exception exc) { Log.Error($"Eccezione durante WriteTabJson{Environment.NewLine}{exc}"); } return size; } #endregion Protected Methods #region Private Fields /// /// Classe logger /// private static Logger Log = LogManager.GetCurrentClassLogger(); private List ListRecords; private int numApp = 0; private int numIOB = 0; private int numTab = 0; private int totalCount = 0; private long TotalMb = 0; #endregion Private Fields #region Private Properties private List authList { get; set; } = new List(); /// /// Numero complessivo files processati /// private int numDone => numApp + numTab + numIOB; /// /// Numero Step da eseguire... numapp + (9 * DB) + IOB /// private int numSteps => authList.Count + 9 + numIOB; private DirectoryInfo AppDir { get; set; } = new DirectoryInfo(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)); /// /// Nome del file ZIP da gestire /// private string zFileName => Path.Combine(AppDir.FullName, "temp", "zip", "MAPO.zip"); #endregion Private Properties #region Private Methods /// /// Preparazione ZIP con password = AuthKey /// private void PrepareZip() { string srcPath = Path.Combine(AppDir.FullName, "temp", "orig"); string destPath = Path.Combine(AppDir.FullName, "temp", "zip"); if (!Directory.Exists(destPath)) { Directory.CreateDirectory(destPath); } using (ZipFile zipFile = ZipFile.Create(zFileName)) { zipFile.Password = LicServ.MasterKey; zipFile.BeginUpdate(); AddFolderToZip(zipFile, srcPath, srcPath); zipFile.CommitUpdate(); zipFile.Close(); } } /// /// Recupera fdile di conf da app indicata /// /// private void RecuperaConf(AppAuth.Models.UpdMan item) { long size = 0; if (item.IsAuth) { string dstDir = Path.Combine(AppDir.FullName, "temp", "orig", item.PackName); if (!Directory.Exists(dstDir)) { Directory.CreateDirectory(dstDir); } string srcDir = Path.Combine(AppDir.Parent.FullName, item.PackName); // recupero elenco files tipo appsettings*.json if (Directory.Exists(srcDir)) { var dirInfo = new DirectoryInfo(srcDir); // recupero files CORE List fileList = dirInfo.GetFiles("appsettings*.json").ToList(); // recupero files Framework List fileListFram = dirInfo.GetFiles("web*.config").ToList(); // merge... foreach (var fileFrm in fileListFram) { fileList.Add(fileFrm); } // procedo! foreach (var file in fileList) { string fileDestPath = Path.Combine(dstDir, file.Name); file.CopyTo(fileDestPath, true); size += file.Length; } numApp++; percLoading = 100 * numDone / numSteps; TotalMb += size; outMessages = $"File preparati: {numDone}/{numSteps} | {CalcSize(TotalMb)}"; } } } /// /// recupera tutte le conf IOB trasferite all'MP-IO dai vari IOB-WIN /// private void RecuperaIobConf() { numIOB = 0; long size = 0; // calcolo path vari string dstDir = Path.Combine(AppDir.FullName, "temp", "orig", "IOB"); if (!Directory.Exists(dstDir)) { Directory.CreateDirectory(dstDir); } // recupero IOB folder relativa alla parent dir //string srcIobDir = Path.Combine(AppDir.Parent.FullName, "IO", "fileUpload"); string srcIobDir = Configuration.GetValue("ServerConf:IobUploadPath"); // recupero elenco files tipo appsettings*.json if (Directory.Exists(srcIobDir)) { var dirInfo = new DirectoryInfo(srcIobDir); // recupero files CORE List fileList = dirInfo.GetFiles("*", SearchOption.AllDirectories).ToList(); // procedo! foreach (var file in fileList) { string fileDestPath = Path.Combine(dstDir, file.Name); file.CopyTo(fileDestPath, true); size += file.Length; numIOB++; } numApp++; percLoading = 100 * numDone / numSteps; TotalMb += size; outMessages = $"File preparati: {numDone}/{numSteps} | {CalcSize(TotalMb)}"; } } /// /// Salvataggio tabelle di configurazione specifica come tracciati json /// /// private async Task SaveDbConfAsJson() { long size = 0; string dstDir = Path.Combine(AppDir.FullName, "temp", "orig", "DB"); if (!Directory.Exists(dstDir)) { Directory.CreateDirectory(dstDir); } // AnagKeyVal var anagKeyVal = await AppDService.AnagKeyValList(); size += WriteTabJson(Path.Combine(dstDir, "AnagKeyVal.json"), anagKeyVal); numTab++; // AnagCausaliScarto var anagCS = await AppDService.AnagCauSca(); size += WriteTabJson(Path.Combine(dstDir, "AnagCausaliScarto.json"), anagCS); numTab++; // AnagClassiTempo var anagCT = await AppDService.AnagClassiTempo(); size += WriteTabJson(Path.Combine(dstDir, "AnagClassiTempo.json"), anagCT); numTab++; // AnagEventi var anagEvt = await AppDService.AnagEventi(); size += WriteTabJson(Path.Combine(dstDir, "AnagEventi.json"), anagEvt); numTab++; // AnagIngressi var anagIn = await AppDService.AnagIngressi(); size += WriteTabJson(Path.Combine(dstDir, "AnagIngressi.json"), anagIn); numTab++; // AnagMicroStati var anagMSt = await AppDService.AnagIngressi(); size += WriteTabJson(Path.Combine(dstDir, "AnagMicroStati.json"), anagMSt); numTab++; // AnagStati var anagSta = await AppDService.AnagStati(); size += WriteTabJson(Path.Combine(dstDir, "AnagStati.json"), anagSta); numTab++; // Config var confData = await AppDService.ConfigList(); size += WriteTabJson(Path.Combine(dstDir, "Config.json"), confData); numTab++; // ListValues var listVal = await AppDService.ListValues(); size += WriteTabJson(Path.Combine(dstDir, "ListValues.json"), listVal); numTab++; percLoading = 100 * numDone / numSteps; TotalMb += size; outMessages = $"File preparati: {numDone}/{numSteps} | {CalcSize(TotalMb)}"; } /// /// Effettua download di una singola app /// /// private void ScaricaSingolo(AppAuth.Models.UpdMan item) { long size = 0; if (item.IsAuth) { size = updateManAuth.downloadLatest(item.ManifestUrl, localPath(item.LocalRepo), item.PackName); } else { size = UpdateMan.obj.downloadLatest(item.ManifestUrl, localPath(item.LocalRepo), item.PackName); } numApp++; percLoading = 100 * numApp / numSteps; TotalMb += size; outMessages = $"Scaricati {numApp}/{numSteps} packages | {CalcSize(TotalMb)}"; } /// /// Invio zip al server LiMan remoto /// /// /// private async Task UploadZip() { // chiamo SendZipFile di RestCallService... FileInfo zFileInfo = new FileInfo(zFileName); var fatto = await SyncServ.SendZipFile(LicServ.Applicazione, LicServ.Installazione, true, false, zFileInfo); Log.Info($"Richiesto invio file | Applicazione: {LicServ.Applicazione} | Installazione: {LicServ.Installazione}"); return fatto; } #endregion Private Methods } }