using System; using System.Collections.Generic; using Newtonsoft.Json; using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Core; using System.IO; using LCU.Library.Internal.FileOperationsModels.Models; using LCU.Library.Internal.FileOperationsModels.Shared; using LCU.Api.Internal.FileOperations.Validations; using LCU.Library.Internal.LCUServiceFactory.Configurations; namespace LCU.Api.Internal.FileOperations.Services.FileActionServices; public class UnzipPasswordProtectedFileService : FileActionService, IFileActionService, IActionService { public UnzipPasswordProtectedFileService(ServicesFactoryConfiguration servicesFactoryConfiguration) : base(servicesFactoryConfiguration) { } public RequestResponse ExecuteAction(QueueRequest queueRequest) { var requestResponse = new RequestResponse(); try { var unzipPasswordProtectedFileRequest = JsonConvert.DeserializeObject(queueRequest.Request); var requests = BuildFileList(unzipPasswordProtectedFileRequest); requestResponse = FileValidation.ValidateIfAnyRequest(requests, unzipPasswordProtectedFileRequest.FormattedSourceDirectoryPath, requestResponse); foreach (var request in requests) { var temporaryRequestResponse = PerformRequest(request); if (!temporaryRequestResponse.IsSuccessful) { requestResponse.IsSuccessful = temporaryRequestResponse.IsSuccessful; requestResponse.MessageStack.AddRange(temporaryRequestResponse.MessageStack); } } requestResponse.ReturnResponse = unzipPasswordProtectedFileRequest; return requestResponse; } catch (Exception exception) { return RequestResponseHelper.ExceptionUpdateRequestResponse(requestResponse, queueRequest.FileOperationType, exception.Message); } } public RequestResponse PerformRequest(UnzipPasswordProtectedFileRequest request) { return OperationService.PerformOperation(request, IsRequestValid, UnzipPasswordProtectedFile); } public void UnzipPasswordProtectedFile(UnzipPasswordProtectedFileRequest request) { ZipFile passwordProtectedZipFile = null; try { var fileStream = File.OpenRead(request.SourceFilePath); passwordProtectedZipFile = new ZipFile(fileStream) { Password = request.Password }; foreach (ZipEntry zipEntry in passwordProtectedZipFile) { if (!zipEntry.IsFile) { // Ignore directories continue; } var entryFileName = zipEntry.Name; // to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName); // Optionally match entrynames against a selection list here to skip as desired. // The unpacked length is available in the zipEntry.Size property. // 4K is optimum var buffer = new byte[4096]; var zipStream = passwordProtectedZipFile.GetInputStream(zipEntry); // Manipulate the output filename here as desired. var finalDestinationPath = request.FormattedDestinationPath; if (request.UseZipFileNameAsFinalDestination) { var zipFilename = request.PasswordProtectedZipFileNameWithDate.ToUpper().EndsWith(".ZIP") ? request.PasswordProtectedZipFileNameWithDate.ToUpper().Replace(".ZIP", "") : request.PasswordProtectedZipFileNameWithDate; finalDestinationPath = $"{finalDestinationPath}{zipFilename}\\"; } var fullZipToPath = Path.Combine(finalDestinationPath, entryFileName); var directoryName = Path.GetDirectoryName(fullZipToPath); if (directoryName.Length > 0) { Directory.CreateDirectory(directoryName); } // Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size // of the file, but does not waste memory. // The "using" will close the stream even if an exception occurs. using (FileStream streamWriter = File.Create(fullZipToPath)) { StreamUtils.Copy(zipStream, streamWriter, buffer); } } } catch (Exception exception) { throw new Exception($"Exception thrown while trying to ExecuteRequestAction. " + $"Request: {JsonConvert.SerializeObject(request)}" + $"ExceptionMessage: {exception.Message}"); } finally { if (passwordProtectedZipFile != null) { passwordProtectedZipFile.IsStreamOwner = true; // Makes close also shut the underlying stream passwordProtectedZipFile.Close(); // Ensure we release resources } } } public RequestResponse PreQueueValidation(UnzipPasswordProtectedFileRequest originalRequest) { var requestResponse = new RequestResponse(); var requestList = BuildFileList(originalRequest); requestResponse = FileValidation.ValidateIfAnyRequest(requestList, originalRequest.FormattedSourceDirectoryPath, requestResponse); foreach (var request in requestList) { requestResponse = IsRequestValid(request, requestResponse); } return requestResponse; } public List BuildFileList(UnzipPasswordProtectedFileRequest originalRequest) { var nameList = RegexNameHandler.BuildFileList(originalRequest.FormattedSourceDirectoryPath, originalRequest.FinalPasswordProtectedZipFileName, originalRequest.FileNameSetting); var requests = new List(); foreach (var name in nameList) { var newRequest = Clone.DeepClone(originalRequest); newRequest.PasswordProtectedZipFileName = name; requests.Add(newRequest); } return requests; } public RequestResponse IsRequestValid(UnzipPasswordProtectedFileRequest fileRequest, RequestResponse requestResponse) { requestResponse = DirectoryValidation.ValidateDirectoryExists(fileRequest.FormattedSourceDirectoryPath, requestResponse); requestResponse = FileValidation.ValidateFileExists(fileRequest.SourceFilePath, requestResponse); requestResponse = DirectoryValidation.ValidateDirectoryExists(fileRequest.FormattedDestinationPath, requestResponse); return requestResponse; } }