From 8eebf87f904e3bcdba226602788cde6c161fc31c Mon Sep 17 00:00:00 2001 From: Alexander van Delft <56023674+lxatstariongroup@users.noreply.github.com> Date: Wed, 23 Oct 2024 15:10:54 +0200 Subject: [PATCH] [REFACTOR] Remove DotNetZip, replace with SharpZipLib; fixes #349 (#353) * [REFACTOR] Remove DotNetZip, replace with System.IO.Compression * Add support for Extensions folder and beautify code according to sonarqube * Use SharpZipLib and implement AES 256 encryption * Throw error on invalid zip entry name --- CDP4Common/CDP4Common.csproj | 5 +- CDP4Common/Encryption/SharpZipLibUtils.cs | 99 +++++ CDP4Dal/CDP4Dal.csproj | 2 +- CDP4DalCommon/CDP4DalCommon.csproj | 2 +- CDP4JsonFileDal/CDP4JsonFileDal.csproj | 5 +- CDP4JsonFileDal/JsonFileDal.cs | 395 ++++++++---------- CDP4JsonSerializer/CDP4JsonSerializer.csproj | 2 +- .../CDP4MessagePackSerializer.csproj | 2 +- CDP4Reporting/CDP4Reporting.csproj | 2 +- .../CDP4RequirementsVerification.csproj | 2 +- CDP4Rules/CDP4Rules.csproj | 2 +- CDP4ServicesDal/CDP4ServicesDal.csproj | 2 +- .../CDP4ServicesMessaging.csproj | 2 +- CDP4Web/CDP4Web.csproj | 2 +- CDP4WspDal/CDP4WspDal.csproj | 2 +- 15 files changed, 299 insertions(+), 227 deletions(-) create mode 100644 CDP4Common/Encryption/SharpZipLibUtils.cs diff --git a/CDP4Common/CDP4Common.csproj b/CDP4Common/CDP4Common.csproj index abf0832a..6c901a3f 100644 --- a/CDP4Common/CDP4Common.csproj +++ b/CDP4Common/CDP4Common.csproj @@ -4,7 +4,7 @@ net48;netstandard2.0 Starion Group S.A. CDP4Common Community Edition - 27.3.5 + 27.4.0 CDP4 Common Class Library that contains DTOs, POCOs Copyright © Starion Group S.A. Sam, Merlin, Alex, Naron, Alexander, Yevhen, Nathanael, Ahmed @@ -20,7 +20,7 @@ CDP COMET ECSS-E-TM-10-25 LGPL-3.0-only - [Fix] Iteration.QueryUnreferencedElements in case topelement is not set + [ADD] SharpZipLibUtils README.md @@ -45,6 +45,7 @@ + diff --git a/CDP4Common/Encryption/SharpZipLibUtils.cs b/CDP4Common/Encryption/SharpZipLibUtils.cs new file mode 100644 index 00000000..dec047f7 --- /dev/null +++ b/CDP4Common/Encryption/SharpZipLibUtils.cs @@ -0,0 +1,99 @@ +// ------------------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) 2015-2024 Starion Group S.A. +// +// Author: Sam Gerené, Alex Vorobiev, Alexander van Delft, Nathanael Smiechowski, Antoine Théate, Omar Elebiary, Jaime Bernar +// +// This file is part of CDP4-COMET SDK Community Edition +// +// The CDP4-COMET SDK Community Edition is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// The CDP4-COMET SDK Community Edition is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// ------------------------------------------------------------------------------------------------------------------------------- + +namespace CDP4Common.Encryption +{ + using System.IO; + + using ICSharpCode.SharpZipLib.Zip; + + /// + /// A class containing Helper Methods for working with SharpZipLib and creating AES 256 encrypted zip files + /// + public static class SharpZipLibUtils + { + /// + /// Create a to create a AES 256 encrypted zip file + /// + /// The input to write to + /// The password to be used to protect the data + /// The created + public static ZipOutputStream CreateZipOutputStream(Stream inputStream, string password) + { + var zipStream = new ZipOutputStream(inputStream); + zipStream.Password = password; + zipStream.IsStreamOwner = true; // underlying streams will be forcibly closed + + return zipStream; + } + + /// + /// Add a and add it to a + /// + /// The + /// The input from which to create the + /// The name of the entry, including (sub)folder information + public static void AddEntryFromStream(ZipOutputStream zipOutputStream, Stream stream, string name) + { + if (stream.Length == 0) + { + return; + } + + var entry = new ZipEntry(name) + { + AESKeySize = 256, // Set AES encryption to 256 bits for each individual entry + }; + + zipOutputStream.PutNextEntry(entry); + stream.Flush(); + stream.Position = 0; + stream.CopyTo(zipOutputStream); + zipOutputStream.CloseEntry(); + } + + /// + /// Add a file as a to an existing + /// + /// The + /// The location of the file to add + /// The location (fullname) of the file to create in the , including (sub)folder information + public static void AddEntryFromFile(ZipOutputStream zipOutputStream, string extraFile, string entryLocation) + { + var entry = new ZipEntry(entryLocation) + { + AESKeySize = 256, // Set AES encryption to 256 bits + }; + + zipOutputStream.PutNextEntry(entry); + + using (var fileStream = File.OpenRead(extraFile)) + { + fileStream.CopyTo(zipOutputStream); + } + + zipOutputStream.CloseEntry(); + } + } +} diff --git a/CDP4Dal/CDP4Dal.csproj b/CDP4Dal/CDP4Dal.csproj index 1a48f5e7..bc5c9575 100644 --- a/CDP4Dal/CDP4Dal.csproj +++ b/CDP4Dal/CDP4Dal.csproj @@ -4,7 +4,7 @@ net48;netstandard2.0 Starion Group S.A. CDP4Dal Community Edition - 27.3.5 + 27.4.0 CDP4 Data Access Layer library, a consumer of an ECSS-E-TM-10-25 Annex C API Copyright © Starion Group S.A. Sam, Merlin, Alex, Naron, Alexander, Yevhen, Nathanael, Ahmed diff --git a/CDP4DalCommon/CDP4DalCommon.csproj b/CDP4DalCommon/CDP4DalCommon.csproj index b43fb0c5..171811c7 100644 --- a/CDP4DalCommon/CDP4DalCommon.csproj +++ b/CDP4DalCommon/CDP4DalCommon.csproj @@ -5,7 +5,7 @@ Starion Group S.A. latest CDP4DalCommon Community Edition - 27.3.5 + 27.4.0 CDP4 Common Class Library that contains common types for any CDP4 server and the CDP4Dal Copyright © Starion Group S.A. Sam, Alex, Alexander, Nathanael, Antoine, Omar, Jaime diff --git a/CDP4JsonFileDal/CDP4JsonFileDal.csproj b/CDP4JsonFileDal/CDP4JsonFileDal.csproj index e2512646..3b71d367 100644 --- a/CDP4JsonFileDal/CDP4JsonFileDal.csproj +++ b/CDP4JsonFileDal/CDP4JsonFileDal.csproj @@ -4,7 +4,7 @@ net48;netstandard2.0 Starion Group S.A. CDP4JsonFileDal Community Edition - 27.3.5 + 27.4.0 CDP4 Json File Dal Plugin Copyright © Starion Group S.A. Sam, Merlin, Alex, Naron, Alexander, Yevhen, Nathanael @@ -20,7 +20,7 @@ CDP COMET ECSS-E-TM-10-25 LGPL-3.0-only - [BUMP] To CDP4Common 27.3.5 + - Remove DotNetZip and use SharpZipLib README.md @@ -43,7 +43,6 @@ - diff --git a/CDP4JsonFileDal/JsonFileDal.cs b/CDP4JsonFileDal/JsonFileDal.cs index 08851198..d4cdd255 100644 --- a/CDP4JsonFileDal/JsonFileDal.cs +++ b/CDP4JsonFileDal/JsonFileDal.cs @@ -1,6 +1,6 @@ // ------------------------------------------------------------------------------------------------------------------------------- // -// Copyright (c) 2015-2023 Starion Group S.A. +// Copyright (c) 2015-2024 Starion Group S.A. // // Author: Sam Gerené, Merlin Bieze, Alex Vorobiev, Naron Phou, Alexandervan Delft, Nathanael Smiechowski, Ahmed Abulwafa Ahmed // @@ -26,7 +26,6 @@ namespace CDP4JsonFileDal { using System; using System.Collections.Generic; - using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; @@ -35,6 +34,7 @@ namespace CDP4JsonFileDal using CDP4Common.CommonData; using CDP4Common.Comparers; + using CDP4Common.Encryption; using CDP4Common.EngineeringModelData; using CDP4Common.Exceptions; using CDP4Common.Extensions; @@ -52,16 +52,17 @@ namespace CDP4JsonFileDal using CDP4JsonSerializer; - using Ionic.Zip; + using ICSharpCode.SharpZipLib.Zip; using NLog; + using File = System.IO.File; using Person = CDP4Common.SiteDirectoryData.Person; using SiteDirectory = CDP4Common.SiteDirectoryData.SiteDirectory; using Thing = CDP4Common.DTO.Thing; + #if NETFRAMEWORK using System.ComponentModel.Composition; - using Newtonsoft.Json.Linq; #endif /// @@ -306,22 +307,27 @@ public override Task> Write(IEnumerable o try { - using (var zipFile = new ZipFile()) + using (var file = new FileStream(path, FileMode.Create)) { - zipFile.Password = this.Session.Credentials.Password; + var password = this.Session.Credentials.Password; + + using (var zipArchive = SharpZipLibUtils.CreateZipOutputStream(file, password)) + { + this.WriteHeaderToZipFile(exchangeFileHeader, zipArchive); - this.WriteHeaderToZipFile(exchangeFileHeader, zipFile, path); + this.WriteSiteDirectoryToZipFile(prunedSiteDirectoryDtos, zipArchive); - this.WriteSiteDirectoryToZipFile(prunedSiteDirectoryDtos, zipFile, path); + this.WriteSiteReferenceDataLibraryToZipFile(siteReferenceDataLibraryData, zipArchive); - this.WriteSiteReferenceDataLibraryToZipFile(siteReferenceDataLibraryData, zipFile, path); + this.WriteModelReferenceDataLibraryToZipFile(modelReferenceDataLibraryData, zipArchive); - this.WriteModelReferenceDataLibraryToZipFile(modelReferenceDataLibraryData, zipFile, path); + this.WriteIterationsToZipFile(iterationData, zipArchive); - this.WriteIterationsToZipFile(iterationData, zipFile, path); + //ToDo: GH283: Remove extensionsFiles that are referenced by removed instances + this.WriteExtensionFilesToZipFile(extensionFiles, zipArchive); - //ToDo: GH283: Remove extensionsFiles that are referenced by removed instances - this.WriteExtensionFilesToZipFile(extensionFiles, zipFile, path); + zipArchive.Finish(); + } } Logger.Info("Successfully exported the open session {1} to {0}.", path, this.Session.Credentials.Uri); @@ -428,7 +434,7 @@ private IEnumerable RemoveUnlinkedMandatoryReferences(IEnumerable if (newThingsToRemove.Any()) { dtosToCheck = dtosToCheck.Where(x => !newThingsToRemove.Contains(x.Iid)).ToList(); - iidsToCheck.RemoveWhere(x=> newThingsToRemove.Contains(x)); + iidsToCheck.RemoveWhere(x => newThingsToRemove.Contains(x)); } else { @@ -444,7 +450,7 @@ private IEnumerable RemoveUnlinkedMandatoryReferences(IEnumerable /// /// A collection of s that are involved in the Annex.C3 export. /// If a property cannot be removed because that would lead to model errors, this exception is thrown - private void TryRemoveUnlinkedReferences(IEnumerable allDtos) + private void TryRemoveUnlinkedReferences(IEnumerable allDtos) { var dtos = allDtos.ToList(); var dtoIids = dtos.Select(x => x.Iid).ToList(); @@ -497,20 +503,23 @@ public override async Task> Read(T thing, CancellationToke var filePath = this.Credentials.Uri.LocalPath; - if (!System.IO.File.Exists(filePath)) + if (!File.Exists(filePath)) { throw new FileNotFoundException($"The specified filepath does not exist or you do not have access to it: {filePath}"); } try { - // re-read the to extract the reference data libraries that have not yet been fully dereferenced - // and that are part of the required RDL's - var siteDirectoryData = this.ReadSiteDirectoryJson(filePath, this.Credentials).ToList(); + var preReadEntries = this.GetAllZipEntries(filePath); - // read file, SiteDirectory first. - using (var zip = ZipFile.Read(filePath)) + using (var zipFile = new ZipFile(File.OpenRead(filePath))) { + zipFile.Password = this.Session.Credentials.Password; // Set the password for decryption + + // re-read the to extract the reference data libraries that have not yet been fully dereferenced + // and that are part of the required RDL's + var siteDirectoryData = this.ReadSiteDirectoryJson(zipFile, preReadEntries).ToList(); + // get all relevant info from the selected iteration var siteDir = this.Session.RetrieveSiteDirectory(); @@ -519,10 +528,10 @@ public override async Task> Read(T thing, CancellationToke switch (thing.ClassKind) { case ClassKind.Iteration: - returned = this.RetrieveIterationThings(thing as CDP4Common.DTO.Iteration, siteDirectoryData, zip, siteDir); + returned = this.RetrieveIterationThings(thing as CDP4Common.DTO.Iteration, siteDirectoryData, zipFile, preReadEntries, siteDir); break; case ClassKind.SiteReferenceDataLibrary: - returned = this.RetrieveSRDLThings(thing as CDP4Common.DTO.SiteReferenceDataLibrary, siteDirectoryData, zip, siteDir); + returned = this.RetrieveSRDLThings(thing as CDP4Common.DTO.SiteReferenceDataLibrary, siteDirectoryData, zipFile, preReadEntries, siteDir); break; case ClassKind.DomainOfExpertise: returned = this.RetrieveDomainOfExpertiseThings(thing as CDP4Common.DTO.DomainOfExpertise, siteDirectoryData); @@ -546,6 +555,28 @@ public override async Task> Read(T thing, CancellationToke } } + /// + /// Retrieve a list of all full names (location in the zip file) of all the entries in a zip file + /// + /// The location of the zip file + /// A collection of full names + private List GetAllZipEntries(string zipFilePath) + { + var result = new List(); + + using (var zip = new ZipInputStream(File.OpenRead(zipFilePath))) + { + ZipEntry entry; + + while ((entry = zip.GetNextEntry()) != null) + { + result.Add(entry.Name); + } + } + + return result; + } + /// /// Reads the data related to the provided from the data-source /// @@ -687,10 +718,11 @@ private List RetrieveDomainOfExpertiseThings(CDP4Common.DTO.DomainOfExper /// /// The /// All SiteDirectory DTOs - /// The zip file + /// The + /// A collection of pre read entry names (location in the zip file) /// The object /// List of things contained by the particular srdl - private List RetrieveSRDLThings(CDP4Common.DTO.SiteReferenceDataLibrary siteRdl, List siteDirectoryData, ZipFile zip, SiteDirectory siteDir) + private List RetrieveSRDLThings(CDP4Common.DTO.SiteReferenceDataLibrary siteRdl, List siteDirectoryData, ZipFile zipFile, List preReadEntries, SiteDirectory siteDir) { var returned = new List(); @@ -706,8 +738,8 @@ private List RetrieveSRDLThings(CDP4Common.DTO.SiteReferenceDataLibrary s returned.Add(requiredRdlDto); var siteRdlFilePath = $"{requiredRdl.Iid}.json"; - var siteRdlZipEntry = zip.Entries.SingleOrDefault(x => x.FileName.EndsWith(siteRdlFilePath)); - var siteRdlItems = this.ReadInfoFromArchiveEntry(siteRdlZipEntry, this.Credentials.Password); + var siteRdlZipEntry = preReadEntries.SingleOrDefault(x => x.EndsWith(siteRdlFilePath)); + var siteRdlItems = this.ReadInfoFromArchive(zipFile, siteRdlZipEntry); returned.AddRange(siteRdlItems); // set the requiredRdl for the next iteration @@ -722,10 +754,11 @@ private List RetrieveSRDLThings(CDP4Common.DTO.SiteReferenceDataLibrary s /// /// The /// All SiteDirectory DTOs - /// The zip file + /// The + /// A collection of pre read entry names (location in the zip file) /// The object /// List of things relevant for a particular iteration - private List RetrieveIterationThings(CDP4Common.DTO.Iteration iteration, List siteDirectoryData, ZipFile zip, SiteDirectory siteDir) + private List RetrieveIterationThings(CDP4Common.DTO.Iteration iteration, List siteDirectoryData, ZipFile zipFile, List preReadEntries, SiteDirectory siteDir) { var engineeringModelSetup = siteDir.Model.SingleOrDefault(x => x.IterationSetup.Any(y => y.IterationIid == iteration.Iid)); @@ -739,13 +772,14 @@ private List RetrieveIterationThings(CDP4Common.DTO.Iteration iteration, var engineeringModelFilePath = $"{engineeringModelSetup.EngineeringModelIid}.json"; var engineeringModelZipEntry = - zip.Entries.SingleOrDefault(x => x.FileName.EndsWith(engineeringModelFilePath)); + preReadEntries.SingleOrDefault(x => x.EndsWith(engineeringModelFilePath)); - var returned = this.ReadInfoFromArchiveEntry(engineeringModelZipEntry, this.Credentials.Password); + var returned = this.ReadInfoFromArchive(zipFile, engineeringModelZipEntry); var iterationFilePath = $"{iteration.Iid}.json"; - var iterationZipEntry = zip.Entries.SingleOrDefault(x => x.FileName.EndsWith(iterationFilePath)); - returned.AddRange(this.ReadIterationArchiveEntry(iterationZipEntry, this.Credentials.Password)); + + var iterationZipEntry = preReadEntries.SingleOrDefault(x => x.EndsWith(iterationFilePath)); + returned.AddRange(this.ReadIterationFromArchive(zipFile, iterationZipEntry)); // use the loaded sitedirectory information to determine the required model reference data library var modelRdl = engineeringModelSetup.RequiredRdl.Single(); @@ -759,8 +793,8 @@ private List RetrieveIterationThings(CDP4Common.DTO.Iteration iteration, // based on engineering model setup load rdl chain var modelRdlFilePath = $"{modelRdl.Iid}.json"; - var modelRdlZipEntry = zip.Entries.SingleOrDefault(x => x.FileName.EndsWith(modelRdlFilePath)); - var modelRdlItems = this.ReadInfoFromArchiveEntry(modelRdlZipEntry, this.Credentials.Password); + var modelRdlZipEntry = preReadEntries.SingleOrDefault(x => x.EndsWith(modelRdlFilePath)); + var modelRdlItems = this.ReadInfoFromArchive(zipFile, modelRdlZipEntry); returned.AddRange(modelRdlItems); // load the reference data libraries as per the containment chain @@ -773,8 +807,8 @@ private List RetrieveIterationThings(CDP4Common.DTO.Iteration iteration, returned.Add(requiredRdlDto); var siteRdlFilePath = $"{requiredRdl.Iid}.json"; - var siteRdlZipEntry = zip.Entries.SingleOrDefault(x => x.FileName.EndsWith(siteRdlFilePath)); - var siteRdlItems = this.ReadInfoFromArchiveEntry(siteRdlZipEntry, this.Credentials.Password); + var siteRdlZipEntry = preReadEntries.SingleOrDefault(x => x.EndsWith(siteRdlFilePath)); + var siteRdlItems = this.ReadInfoFromArchive(zipFile, siteRdlZipEntry); returned.AddRange(siteRdlItems); // set the requiredRdl for the next iteration @@ -873,35 +907,44 @@ public override async Task> Open(Credentials credentials, Can var filePath = credentials.Uri.LocalPath; - if (!System.IO.File.Exists(filePath)) + if (!File.Exists(filePath)) { throw new FileLoadException($"The specified filepath does not exist or you do not have access to it: {filePath}"); } try { - var returned = this.ReadSiteDirectoryJson(filePath, credentials).ToList(); + var preReadEntries = this.GetAllZipEntries(filePath); - Logger.Debug("The SiteDirectory contains {0} Things", returned.Count); + using (var zipFile = new ZipFile(File.OpenRead(filePath))) + { + zipFile.Password = this.Session.Credentials.Password; // Set the password for decryption - // check for credentials in the returned DTO's to see if the current Person is authorised to look into this SiteDirectory - var person = returned.SingleOrDefault(p => - p.ClassKind == ClassKind.Person && - ((CDP4Common.DTO.Person)p).ShortName == credentials.UserName) as - CDP4Common.DTO.Person; + // re-read the to extract the reference data libraries that have not yet been fully dereferenced + // and that are part of the required RDL's + var returned = this.ReadSiteDirectoryJson(zipFile, preReadEntries).ToList(); - if (person == null) - { - var msg = $"{credentials.UserName} is unauthorized"; - Logger.Error(msg); + Logger.Debug("The SiteDirectory contains {0} Things", returned.Count); - throw new UnauthorizedAccessException(msg); - } + // check for credentials in the returned DTO's to see if the current Person is authorised to look into this SiteDirectory + var person = returned.SingleOrDefault(p => + p.ClassKind == ClassKind.Person && + ((CDP4Common.DTO.Person)p).ShortName == credentials.UserName) as + CDP4Common.DTO.Person; + + if (person == null) + { + var msg = $"{credentials.UserName} is unauthorized"; + Logger.Error(msg); - // set the credentials - this.Credentials = credentials; + throw new UnauthorizedAccessException(msg); + } - return returned; + // set the credentials + this.Credentials = credentials; + + return returned; + } } catch (UnauthorizedAccessException ex) { @@ -948,7 +991,7 @@ public override void Close() /// public override bool IsValidUri(string uri) { - return System.IO.File.Exists(uri); + return File.Exists(uri); } /// @@ -993,7 +1036,7 @@ private void ValidateOperationContainers(IEnumerable operati { if (operationContainer.Operations.Any(operation => operation.ModifiedThing.GetType() != typeof(CDP4Common.DTO.Iteration))) { - throw new ArgumentException($"Only instances of Things of type {typeof(CDP4Common.DTO.Iteration).Name} are eligible for export", nameof(operationContainers)); + throw new ArgumentException($"Only instances of Things of type {nameof(CDP4Common.DTO.Iteration)} are eligible for export", nameof(operationContainers)); } } } @@ -1002,42 +1045,30 @@ private void ValidateOperationContainers(IEnumerable operati /// Write the header file to the zip export archive. /// /// - /// The that is to be written to the + /// The that is to be written to the /// - /// + /// /// The zip archive instance to add the information to. /// - /// - /// The path of the file. - /// - private void WriteHeaderToZipFile(ExchangeFileHeader echExchangeFileHeader, ZipFile zipFile, string filePath) + private void WriteHeaderToZipFile(ExchangeFileHeader echExchangeFileHeader, ZipOutputStream zipArchive) { using (var memoryStream = new MemoryStream()) { this.Serializer.SerializeToStream(echExchangeFileHeader, memoryStream); - - using (var outputStream = new MemoryStream(memoryStream.ToArray())) - { - var zipEntry = zipFile.AddEntry("Header.json", outputStream); - zipEntry.Comment = "The Header for this file based source"; - zipFile.Save(filePath); - } + SharpZipLibUtils.AddEntryFromStream(zipArchive, memoryStream, "Header.json"); } } /// - /// Writes the pruned to the + /// Writes the pruned to the /// /// - /// The that has been pruned of all unnecessary data + /// The that has been pruned of all unnecessary data /// - /// - /// The target + /// + /// The target /// - /// - /// The file Path. - /// - private void WriteSiteDirectoryToZipFile(IEnumerable prunedSiteDirectoryContents, ZipFile zipFile, string filePath) + private void WriteSiteDirectoryToZipFile(IEnumerable prunedSiteDirectoryContents, ZipOutputStream zipOutputStream) { using (var memoryStream = new MemoryStream()) { @@ -1045,20 +1076,15 @@ private void WriteSiteDirectoryToZipFile(IEnumerable prunedSiteDirectoryC this.Serializer.SerializeToStream(orderedContents, memoryStream); - using (var outputStream = new MemoryStream(memoryStream.ToArray())) - { - var zipEntry = zipFile.AddEntry("SiteDirectory.json", outputStream); - zipEntry.Comment = "The SiteDirectory for this file based source"; - zipFile.Save(filePath); - } + SharpZipLibUtils.AddEntryFromStream(zipOutputStream, memoryStream, "SiteDirectory.json"); } } /// - /// Retrieves all the DTO's + /// Retrieves all the DTO's /// /// - /// The s + /// The s private Dictionary> GetSiteReferenceDataLibraryDtos(IEnumerable siteReferenceDataLibraries) { var result = new Dictionary>(); @@ -1085,41 +1111,34 @@ private Dictionary> GetSiteReferenc } /// - /// Writes s to the + /// Writes s to the /// /// - /// The that contains the s and related Dtos that are to be written to the - /// - /// - /// The target that the are written to. + /// The that contains the s and related Dtos that are to be written to the /// - /// - /// The file of the target + /// + /// The target that the are written to. /// - private void WriteSiteReferenceDataLibraryToZipFile(Dictionary> siteReferenceDataLibraries, ZipFile zipFile, string filePath) + private void WriteSiteReferenceDataLibraryToZipFile(Dictionary> siteReferenceDataLibraries, ZipOutputStream zipOutputStream) { foreach (var siteReferenceDataLibrary in siteReferenceDataLibraries) { + var siteReferenceDataLibraryFilename = $"{SiteRdlZipLocation}\\{siteReferenceDataLibrary.Key.Iid}.json"; + using (var memoryStream = new MemoryStream()) { this.Serializer.SerializeToStream(siteReferenceDataLibrary.Value, memoryStream); - using (var outputStream = new MemoryStream(memoryStream.ToArray())) - { - var siteReferenceDataLibraryFilename = $"{SiteRdlZipLocation}\\{siteReferenceDataLibrary.Key.Iid}.json"; - var zipEntry = zipFile.AddEntry(siteReferenceDataLibraryFilename, outputStream); - zipEntry.Comment = $"The {siteReferenceDataLibrary.Key.ShortName} SiteReferenceDataLibrary"; - zipFile.Save(filePath); - } + SharpZipLibUtils.AddEntryFromStream(zipOutputStream, memoryStream, siteReferenceDataLibraryFilename); } } } /// - /// Gets the s DTO's + /// Gets the s DTO's /// /// - /// The s + /// The s /// private Dictionary> GetModelReferenceDataLibraryDtos(IEnumerable modelReferenceDataLibraries) { @@ -1147,41 +1166,33 @@ private Dictionary> GetModelRefere } /// - /// Writes the to the + /// Writes the to the /// /// - /// The that contains the s and related Dtos that are to be written to the + /// The that contains the s and related Dtos that are to be written to the /// - /// - /// The target that the are written to. + /// + /// The target that the are written to. /// - /// - /// The file of the target - /// - private void WriteModelReferenceDataLibraryToZipFile(Dictionary> modelReferenceDataLibraries, ZipFile zipFile, string filePath) + private void WriteModelReferenceDataLibraryToZipFile(Dictionary> modelReferenceDataLibraries, ZipOutputStream zipOutputStream) { foreach (var modelReferenceDataLibrary in modelReferenceDataLibraries) { + var modelReferenceDataLibraryFilename = $"{ModelRdlZipLocation}\\{modelReferenceDataLibrary.Key.Iid}.json"; + using (var memoryStream = new MemoryStream()) { this.Serializer.SerializeToStream(modelReferenceDataLibrary.Value, memoryStream); - - using (var outputStream = new MemoryStream(memoryStream.ToArray())) - { - var modelReferenceDataLibraryFilename = $"{ModelRdlZipLocation}\\{modelReferenceDataLibrary.Key.Iid}.json"; - var zipEntry = zipFile.AddEntry(modelReferenceDataLibraryFilename, outputStream); - zipEntry.Comment = $"The {modelReferenceDataLibrary.Key.ShortName} ModelReferenceDataLibrary"; - zipFile.Save(filePath); - } + SharpZipLibUtils.AddEntryFromStream(zipOutputStream, memoryStream, modelReferenceDataLibraryFilename); } } } /// - /// Retrieves the and related DTO's. + /// Retrieves the and related DTO's. /// /// - /// The s + /// The s /// private Dictionary> GetIterationDtos(IEnumerable iterations) { @@ -1204,19 +1215,16 @@ private Dictionary> GetIterationDtos(IEnumerable - /// Writes the to the + /// Writes the to the /// /// - /// The that contains the s and related Dtos that are to be written to the - /// The that are to be written to the + /// The that contains the s and related Dtos that are to be written to the + /// The that are to be written to the /// - /// - /// The target that the are written to. + /// + /// The target that the are written to. /// - /// - /// The file of the target - /// - private void WriteIterationsToZipFile(Dictionary> iterations, ZipFile zipFile, string filePath) + private void WriteIterationsToZipFile(Dictionary> iterations, ZipOutputStream zipOutputStream) { var engineeringModels = new List(); @@ -1227,44 +1235,34 @@ private void WriteIterationsToZipFile(Dictionary> if (!engineeringModels.Contains(engineeringModel)) { - using (var engineeringModelMemoryStream = new MemoryStream()) + var engineeringModelFilename = $@"{EngineeringModelZipLocation}\{engineeringModelDto.Iid}\{engineeringModelDto.Iid}.json"; + + using (var memoryStream = new MemoryStream()) { - this.Serializer.SerializeToStream(new[] { engineeringModelDto }, engineeringModelMemoryStream); - - using (var outputStream = new MemoryStream(engineeringModelMemoryStream.ToArray())) - { - var engineeringModelFilename = $@"{EngineeringModelZipLocation}\{engineeringModelDto.Iid}\{engineeringModelDto.Iid}.json"; - var engineeringModelZipEntry = zipFile.AddEntry(engineeringModelFilename, outputStream); - engineeringModelZipEntry.Comment = $"The {engineeringModel.EngineeringModelSetup.ShortName} EngineeringModel"; - zipFile.Save(filePath); - } + this.Serializer.SerializeToStream(new[] { engineeringModelDto }, memoryStream); + SharpZipLibUtils.AddEntryFromStream(zipOutputStream, memoryStream, engineeringModelFilename); } engineeringModels.Add(engineeringModel); } - using (var iterationMemoryStream = new MemoryStream()) + var iterationFilename = $@"{EngineeringModelZipLocation}\{engineeringModelDto.Iid}\{IterationZipLocation}\{iteration.Key.Iid}.json"; + + using (var memoryStream = new MemoryStream()) { - this.Serializer.SerializeToStream(iteration.Value, iterationMemoryStream); + this.Serializer.SerializeToStream(iteration.Value, memoryStream); - using (var outputStream = new MemoryStream(iterationMemoryStream.ToArray())) - { - var iterationFilename = $@"{EngineeringModelZipLocation}\{engineeringModelDto.Iid}\{IterationZipLocation}\{iteration.Key.Iid}.json"; - var iterationZipEntry = zipFile.AddEntry(iterationFilename, outputStream); - iterationZipEntry.Comment = $"The {iteration.Key.IterationSetup.IsDeleted} Iteration"; - zipFile.Save(filePath); - } + SharpZipLibUtils.AddEntryFromStream(zipOutputStream, memoryStream, iterationFilename); } } } /// - /// Writes the application dependend files inside specific folder to the + /// Writes the application dependend files inside specific folder to the /// - /// The files list that will be written - /// The target - /// The file path of the target - private void WriteExtensionFilesToZipFile(IEnumerable extraFilesPath, ZipFile zipFile, string filePath) + /// The list of files that will be written to the + /// The target + private void WriteExtensionFilesToZipFile(IEnumerable extraFilesPath, ZipOutputStream zipOutputStream) { if (extraFilesPath is null) { @@ -1273,53 +1271,47 @@ private void WriteExtensionFilesToZipFile(IEnumerable extraFilesPath, Zi foreach (var extraFile in extraFilesPath) { - var zipEntry = zipFile.AddFile(extraFile, ExtensionsZipLocation); - zipEntry.Comment = $"The {extraFile} file"; - } + var extraFileName = Path.GetFileName(extraFile); + var entryLocation = Path.Combine(ExtensionsZipLocation, extraFileName); - zipFile.Save(filePath); + SharpZipLibUtils.AddEntryFromFile(zipOutputStream, extraFile, entryLocation); + } } /// - /// Reads SiteDirectory data from the archive + /// Reads SiteDirectory data from the . /// - /// - /// the file path to the archive - /// - /// - /// the used to read the archive - /// + /// The + /// A (pre-read) collection of available entry names (=location in the zip file) in the /// - /// an containing data + /// an containing data /// - private IEnumerable ReadSiteDirectoryJson(string filePath, Credentials credentials) + private IEnumerable ReadSiteDirectoryJson(ZipFile zipFile, List entries) { - using (var zip = ZipFile.Read(filePath)) - { - // read SiteDirectory - var siteDirectoryFilePath = "SiteDirectory.json"; - var siteDirectoryZipEntry = zip.Entries.SingleOrDefault(x => x.FileName.EndsWith(siteDirectoryFilePath)); - var returned = this.ReadInfoFromArchiveEntry(siteDirectoryZipEntry, credentials.Password); + var siteDirectoryFilePath = "SiteDirectory.json"; + + var entry = entries.SingleOrDefault(x => x.EndsWith(siteDirectoryFilePath)); + if (entry != null) + { + var returned = this.ReadInfoFromArchive(zipFile, entry); return returned; } + + return new List(); } /// - /// Read an iteration file from the specified archive entry. + /// Read an iteration file from the specified . /// - /// - /// The zip entry pointing to the iteration file in the archive. - /// - /// - /// The password of the archive. - /// + /// The + /// The name / location of the entry in the /// - /// The . + /// A /// - private List ReadIterationArchiveEntry(ZipEntry zipEntry, string archivePassword) + private List ReadIterationFromArchive(ZipFile zipFile, string entryName) { - var returned = this.ReadInfoFromArchiveEntry(zipEntry, archivePassword); + var returned = this.ReadInfoFromArchive(zipFile, entryName); // set the iteration id for returned objects var iterationId = returned.First().Iid; @@ -1329,55 +1321,36 @@ private List ReadIterationArchiveEntry(ZipEntry zipEntry, string archiveP } /// - /// Read info from a specified archive entry. + /// Read info from a specified . /// - /// - /// The zip entry. - /// - /// - /// The password of the archive. - /// + /// The + /// The name / location of the entry in the /// /// A /// - /// - /// throws exception if the file failed to open - /// - private List ReadInfoFromArchiveEntry(ZipEntry zipEntry, string archivePassword) + private List ReadInfoFromArchive(ZipFile zipFile, string entryName) { - if (zipEntry == null) - { - throw new ArgumentNullException(nameof(zipEntry), "Supplied archive entry is invalid."); - } - var watch = Stopwatch.StartNew(); - var stream = new MemoryStream(); + var entry = zipFile.GetEntry(entryName); - try + if (entry == null) { - zipEntry.Password = archivePassword; - zipEntry.Extract(stream); + throw new ArgumentOutOfRangeException(entryName, "Supplied archive entry name could not be found in the ZipFile."); } - catch (Exception ex) - { - var msg = $"{"Failed to open file. Error"}: {ex.Message}"; - Logger.Error(msg); - throw new FileLoadException(msg); - } + var stream = zipFile.GetInputStream(entry); watch.Stop(); - Logger.Info("ZipEntry {0} retrieved in {1} [ms]", zipEntry.FileName, watch.ElapsedMilliseconds); + Logger.Info("ZipEntry {0} retrieved in {1} [ms]", entryName, watch.ElapsedMilliseconds); watch = Stopwatch.StartNew(); - stream.Position = 0; var returned = this.Serializer.Deserialize(stream).ToList(); stream.Dispose(); watch.Stop(); - Logger.Info("JSON Deserializer of {0} completed in {1} [ms]", zipEntry.FileName, watch.ElapsedMilliseconds); + Logger.Info("JSON Deserializer of {0} completed in {1} [ms]", entryName, watch.ElapsedMilliseconds); return returned; } } diff --git a/CDP4JsonSerializer/CDP4JsonSerializer.csproj b/CDP4JsonSerializer/CDP4JsonSerializer.csproj index dfaff0d0..0663678e 100644 --- a/CDP4JsonSerializer/CDP4JsonSerializer.csproj +++ b/CDP4JsonSerializer/CDP4JsonSerializer.csproj @@ -4,7 +4,7 @@ net48;netstandard2.0 Starion Group S.A. CDP4JsonSerializer Community Edition - 27.3.5 + 27.4.0 CDP4 JSON Serialization Library Copyright © Starion Group S.A. Sam, Merlin, Alex, Naron, Alexander, Yevhen, Nathanael diff --git a/CDP4MessagePackSerializer/CDP4MessagePackSerializer.csproj b/CDP4MessagePackSerializer/CDP4MessagePackSerializer.csproj index 7278b1f5..16683b90 100644 --- a/CDP4MessagePackSerializer/CDP4MessagePackSerializer.csproj +++ b/CDP4MessagePackSerializer/CDP4MessagePackSerializer.csproj @@ -4,7 +4,7 @@ net48;netstandard2.0 Starion Group S.A. CDP4MessagePackSerializer Community Edition - 27.3.5 + 27.4.0 CDP4 MessagePack Serialization Library Copyright © Starion Group S.A. Sam, Alex, Alexander, Nathanael, Antoine, Omar diff --git a/CDP4Reporting/CDP4Reporting.csproj b/CDP4Reporting/CDP4Reporting.csproj index ec2e0e66..71104e9f 100644 --- a/CDP4Reporting/CDP4Reporting.csproj +++ b/CDP4Reporting/CDP4Reporting.csproj @@ -4,7 +4,7 @@ netstandard2.0 Starion Group S.A. CDP4Reporting Community Edition - 27.3.5 + 27.4.0 CDP4 Reporting Copyright © Starion Group S.A. Sam, Alex, Alexander diff --git a/CDP4RequirementsVerification/CDP4RequirementsVerification.csproj b/CDP4RequirementsVerification/CDP4RequirementsVerification.csproj index 87292b0d..06fe624a 100644 --- a/CDP4RequirementsVerification/CDP4RequirementsVerification.csproj +++ b/CDP4RequirementsVerification/CDP4RequirementsVerification.csproj @@ -4,7 +4,7 @@ net48;netstandard2.0 Starion Group S.A. CDP4RequirementsVerification Community Edition - 27.3.5 + 27.4.0 CDP4 Class Library that provides requirement verification Copyright © Starion Group S.A. Sam, Alex, Alexander, Yevhen, Nathanael diff --git a/CDP4Rules/CDP4Rules.csproj b/CDP4Rules/CDP4Rules.csproj index 9335c347..0e78f0b7 100644 --- a/CDP4Rules/CDP4Rules.csproj +++ b/CDP4Rules/CDP4Rules.csproj @@ -4,7 +4,7 @@ net48;netstandard2.0 Starion Group S.A. CDP4Rules Community Edition - 27.3.5 + 27.4.0 CDP4 Class Library that provides Model Analysis and Rule Checking Copyright © Starion Group S.A. Sam, Alex, Alexander, Yevhen, Nathanael diff --git a/CDP4ServicesDal/CDP4ServicesDal.csproj b/CDP4ServicesDal/CDP4ServicesDal.csproj index 9f5762b6..4f1f21e3 100644 --- a/CDP4ServicesDal/CDP4ServicesDal.csproj +++ b/CDP4ServicesDal/CDP4ServicesDal.csproj @@ -4,7 +4,7 @@ net48;netstandard2.0 Starion Group S.A. CDP4ServicesDal Community Edition - 27.3.5 + 27.4.0 CDP4ServicesDal Dal Plugin Copyright © Starion Group S.A. Sam, Merlin, Alex, Naron, Alexander, Yevhen, Nathanael diff --git a/CDP4ServicesMessaging/CDP4ServicesMessaging.csproj b/CDP4ServicesMessaging/CDP4ServicesMessaging.csproj index 7b12e322..7a6e3388 100644 --- a/CDP4ServicesMessaging/CDP4ServicesMessaging.csproj +++ b/CDP4ServicesMessaging/CDP4ServicesMessaging.csproj @@ -4,7 +4,7 @@ netstandard2.0 Starion Group S.A. CDP4Common Community Edition - 27.3.5 + 27.4.0 CDP4 Services Messaging is a Class Library that contains clients and messages class that can be used for inter services communication Copyright © Starion Group S.A. Sam, Alex, Alexander, Nathanael, Antoine diff --git a/CDP4Web/CDP4Web.csproj b/CDP4Web/CDP4Web.csproj index b3424a44..5a17cc2e 100644 --- a/CDP4Web/CDP4Web.csproj +++ b/CDP4Web/CDP4Web.csproj @@ -5,7 +5,7 @@ latest Starion Group S.A. CDP4Web Community Edition - 27.3.5 + 27.4.0 CDP4Web Dedicated Sdk for CDPServicesDal Copyright © Starion Group S.A. Sam, Alex, Alexander, Nathanael, Antoine, Omar, Jaime diff --git a/CDP4WspDal/CDP4WspDal.csproj b/CDP4WspDal/CDP4WspDal.csproj index bc6b45d1..fa67b4c7 100644 --- a/CDP4WspDal/CDP4WspDal.csproj +++ b/CDP4WspDal/CDP4WspDal.csproj @@ -4,7 +4,7 @@ net48;netstandard2.0 Starion Group S.A. CDP4WspDal Community Edition - 27.3.5 + 27.4.0 CDP4 WSP Dal Plugin Copyright © Starion Group S.A. Sam, Merlin, Alex, Naron, Alexander, Yevhen, Nathanael