diff --git a/src/Files.Package/nupkgs/SevenZipSharp.1.0.0.nupkg b/src/Files.Package/nupkgs/SevenZipSharp.1.0.0.nupkg index e03417d4f445..8026675e34ac 100644 Binary files a/src/Files.Package/nupkgs/SevenZipSharp.1.0.0.nupkg and b/src/Files.Package/nupkgs/SevenZipSharp.1.0.0.nupkg differ diff --git a/src/Files.Uwp/Filesystem/StorageItems/ZipStorageFolder.cs b/src/Files.Uwp/Filesystem/StorageItems/ZipStorageFolder.cs index 8ef088f7e0a1..7e8bdbd189c8 100644 --- a/src/Files.Uwp/Filesystem/StorageItems/ZipStorageFolder.cs +++ b/src/Files.Uwp/Filesystem/StorageItems/ZipStorageFolder.cs @@ -76,11 +76,11 @@ public static bool IsZipPath(string path, bool includeRoot = true) public async Task GetUncompressedSize() { long uncompressedSize = 0; - using (SevenZipExtractor zipFile = await FilesystemTasks.Wrap(async () => + using SevenZipExtractor zipFile = await FilesystemTasks.Wrap(async () => { var arch = await OpenZipFileAsync(); return arch?.ArchiveFileData is null ? null : arch; // Force load archive (1665013614u) - })) + }); if (zipFile != null) { @@ -179,7 +179,10 @@ public override IAsyncOperation GetItemAsync(string name) return null; } //zipFile.IsStreamOwner = true; - var entry = zipFile.ArchiveFileData.FirstOrDefault(x => System.IO.Path.Combine(containerPath, x.FileName) == System.IO.Path.Combine(Path, name)); + + var filePath = System.IO.Path.Combine(Path, name); + + var entry = zipFile.ArchiveFileData.FirstOrDefault(x => System.IO.Path.Combine(containerPath, x.FileName) == filePath); if (entry.FileName is null) { return null; @@ -187,10 +190,10 @@ public override IAsyncOperation GetItemAsync(string name) if (entry.IsDirectory) { - return new ZipStorageFolder(entry.FileName, containerPath, entry, backingFile); + return new ZipStorageFolder(filePath, containerPath, entry, backingFile); } - return new ZipStorageFile(entry.FileName, containerPath, entry, backingFile); + return new ZipStorageFile(filePath, containerPath, entry, backingFile); }); } public override IAsyncOperation TryGetItemAsync(string name) @@ -500,6 +503,44 @@ private static async Task CheckAccess(IStorageFile file) }); } + public static Task InitArchive(string path, OutArchiveFormat format) + { + return SafetyExtensions.IgnoreExceptions(() => + { + var hFile = NativeFileOperationsHelper.OpenFileForRead(path, true); + if (hFile.IsInvalid) + { + return Task.FromResult(false); + } + using var stream = new FileStream(hFile, FileAccess.ReadWrite); + return InitArchive(stream, format); + }); + } + public static Task InitArchive(IStorageFile file, OutArchiveFormat format) + { + return SafetyExtensions.IgnoreExceptions(async () => + { + using var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite); + using var stream = fileStream.AsStream(); + return await InitArchive(stream, format); + }); + } + private static async Task InitArchive(Stream stream, OutArchiveFormat format) + { + if (stream.Length == 0) // File is empty + { + var compressor = new SevenZipCompressor() + { + CompressionMode = CompressionMode.Create, + ArchiveFormat = format + }; + await compressor.CompressStreamDictionaryAsync(stream, new Dictionary()); + await stream.FlushAsync(); + return true; + } + return false; + } + private IAsyncOperation OpenZipFileAsync() { return AsyncInfo.Run(async (cancellationToken) => diff --git a/src/Files.Uwp/Helpers/FileExtensionHelpers.cs b/src/Files.Uwp/Helpers/FileExtensionHelpers.cs index f60069aa131f..495744b1f4cd 100644 --- a/src/Files.Uwp/Helpers/FileExtensionHelpers.cs +++ b/src/Files.Uwp/Helpers/FileExtensionHelpers.cs @@ -48,12 +48,23 @@ public static bool IsPowerShellFile(string fileExtensionToCheck) /// otherwise false. public static bool IsZipFile(string fileExtensionToCheck) { + if (string.IsNullOrEmpty(fileExtensionToCheck)) + { + return false; + } + return new[] { ".zip", ".msix", ".appx", ".msixbundle", ".7z", ".rar", ".tar" } .Contains(fileExtensionToCheck, StringComparer.OrdinalIgnoreCase); } public static bool IsBrowsableZipFile(string filePath, out string ext) { + if (string.IsNullOrEmpty(filePath)) + { + ext = null; + return false; + } + ext = new[] { ".zip", ".7z", ".rar", ".tar" } // Only ext we want to browse .FirstOrDefault(x => filePath.Contains(x, StringComparison.OrdinalIgnoreCase)); return ext is not null; diff --git a/src/Files.Uwp/ViewModels/SettingsViewModels/AboutViewModel.cs b/src/Files.Uwp/ViewModels/SettingsViewModels/AboutViewModel.cs index e9444aae00a8..eb176e717284 100644 --- a/src/Files.Uwp/ViewModels/SettingsViewModels/AboutViewModel.cs +++ b/src/Files.Uwp/ViewModels/SettingsViewModels/AboutViewModel.cs @@ -18,6 +18,8 @@ using Windows.Storage.Pickers; using Windows.System; using Windows.UI.Xaml.Controls; +using System.Text; +using SevenZip; namespace Files.Uwp.ViewModels.SettingsViewModels { @@ -59,20 +61,19 @@ private async Task ExportSettings() { try { - var zipFolder = await ZipStorageFolder.FromStorageFileAsync(file); + await ZipStorageFolder.InitArchive(file, OutArchiveFormat.Zip); + var zipFolder = (ZipStorageFolder)await ZipStorageFolder.FromStorageFileAsync(file); if (zipFolder == null) { return; } var localFolderPath = ApplicationData.Current.LocalFolder.Path; // Export user settings - var userSettings = await zipFolder.CreateFileAsync(Constants.LocalSettings.UserSettingsFileName, CreationCollisionOption.ReplaceExisting); - string exportSettings = (string)UserSettingsService.ExportSettings(); - await userSettings.WriteTextAsync(exportSettings); + var exportSettings = UTF8Encoding.UTF8.GetBytes((string)UserSettingsService.ExportSettings()); + await zipFolder.CreateFileAsync(new MemoryStream(exportSettings), Constants.LocalSettings.UserSettingsFileName, CreationCollisionOption.ReplaceExisting); // Export bundles - var bundles = await zipFolder.CreateFileAsync(Constants.LocalSettings.BundlesSettingsFileName, CreationCollisionOption.ReplaceExisting); - string exportBundles = (string)BundlesSettingsService.ExportSettings(); - await bundles.WriteTextAsync(exportBundles); + var exportBundles = UTF8Encoding.UTF8.GetBytes((string)BundlesSettingsService.ExportSettings()); + await zipFolder.CreateFileAsync(new MemoryStream(exportBundles), Constants.LocalSettings.BundlesSettingsFileName, CreationCollisionOption.ReplaceExisting); // Export pinned items var pinnedItems = await BaseStorageFile.GetFileFromPathAsync(Path.Combine(localFolderPath, Constants.LocalSettings.SettingsFolderName, App.SidebarPinnedController.JsonFileName)); await pinnedItems.CopyAsync(zipFolder, pinnedItems.Name, NameCollisionOption.ReplaceExisting); @@ -80,16 +81,13 @@ private async Task ExportSettings() var terminals = await BaseStorageFile.GetFileFromPathAsync(Path.Combine(localFolderPath, Constants.LocalSettings.SettingsFolderName, App.TerminalController.JsonFileName)); await terminals.CopyAsync(zipFolder, terminals.Name, NameCollisionOption.ReplaceExisting); // Export file tags list and DB - var fileTagsList = await zipFolder.CreateFileAsync(Constants.LocalSettings.FileTagSettingsFileName, CreationCollisionOption.ReplaceExisting); - string exportTags = (string)FileTagsSettingsService.ExportSettings(); - await fileTagsList.WriteTextAsync(exportTags); - var fileTagsDB = await zipFolder.CreateFileAsync(Path.GetFileName(FileTagsHelper.FileTagsDbPath), CreationCollisionOption.ReplaceExisting); - string exportTagsDB = FileTagsHelper.DbInstance.Export(); - await fileTagsDB.WriteTextAsync(exportTagsDB); + var exportTags = UTF8Encoding.UTF8.GetBytes((string)FileTagsSettingsService.ExportSettings()); + await zipFolder.CreateFileAsync(new MemoryStream(exportTags), Constants.LocalSettings.FileTagSettingsFileName, CreationCollisionOption.ReplaceExisting); + var exportTagsDB = UTF8Encoding.UTF8.GetBytes(FileTagsHelper.DbInstance.Export()); + await zipFolder.CreateFileAsync(new MemoryStream(exportTagsDB), Path.GetFileName(FileTagsHelper.FileTagsDbPath), CreationCollisionOption.ReplaceExisting); // Export layout preferences DB - var layoutPrefsDB = await zipFolder.CreateFileAsync(Path.GetFileName(FolderSettingsViewModel.LayoutSettingsDbPath), CreationCollisionOption.ReplaceExisting); - string exportPrefsDB = FolderSettingsViewModel.DbInstance.Export(); - await layoutPrefsDB.WriteTextAsync(exportPrefsDB); + var exportPrefsDB = UTF8Encoding.UTF8.GetBytes(FolderSettingsViewModel.DbInstance.Export()); + await zipFolder.CreateFileAsync(new MemoryStream(exportPrefsDB), Path.GetFileName(FolderSettingsViewModel.LayoutSettingsDbPath), CreationCollisionOption.ReplaceExisting); } catch (Exception ex) {