public void ReplacementChecking() { var wnt = new WindowsNameTransform(); try { wnt.Replacement = '*'; Assert.Fail("Expected an exception"); } catch (ArgumentException) { } try { wnt.Replacement = '?'; Assert.Fail("Expected an exception"); } catch (ArgumentException) { } try { wnt.Replacement = ':'; Assert.Fail("Expected an exception"); } catch (ArgumentException) { } try { wnt.Replacement = '/'; Assert.Fail("Expected an exception"); } catch (ArgumentException) { } try { wnt.Replacement = '\\'; Assert.Fail("Expected an exception"); } catch (ArgumentException) { } }
public override IAsyncOperation <IStorageItem> GetItemAsync(string name) { return(AsyncInfo.Run <IStorageItem>(async(cancellationToken) => { var hFile = NativeFileOperationsHelper.OpenFileForRead(ContainerPath); if (hFile.IsInvalid) { return null; } using (ZipFile zipFile = new ZipFile(new FileStream(hFile, FileAccess.Read))) { zipFile.IsStreamOwner = true; ZipEncoding ??= DetectFileEncoding(zipFile); var entry = zipFile.GetEntry(name); if (entry != null) { var wnt = new WindowsNameTransform(ContainerPath); if (entry.IsDirectory) { return new ZipStorageFolder(wnt.TransformDirectory(DecodeEntryName(entry, ZipEncoding)), ContainerPath, entry) { ZipEncoding = ZipEncoding }; } else { return new ZipStorageFile(wnt.TransformFile(DecodeEntryName(entry, ZipEncoding)), ContainerPath, entry); } } return null; } })); }
public override IAsyncOperation <IStorageItem> GetItemAsync(string name) { return(AsyncInfo.Run <IStorageItem>(async(cancellationToken) => { using ZipFile zipFile = await OpenZipFileAsync(FileAccessMode.Read); if (zipFile == null) { return null; } zipFile.IsStreamOwner = true; ZipEncoding ??= DetectFileEncoding(zipFile); var entry = zipFile.GetEntry(name); if (entry != null) { var wnt = new WindowsNameTransform(ContainerPath); if (entry.IsDirectory) { return new ZipStorageFolder(wnt.TransformDirectory(DecodeEntryName(entry, ZipEncoding)), ContainerPath, entry) { ZipEncoding = ZipEncoding, BackingFile = BackingFile }; } else { return new ZipStorageFile(wnt.TransformFile(DecodeEntryName(entry, ZipEncoding)), ContainerPath, entry) { BackingFile = BackingFile }; } } return null; })); }
public void Replacement() { var wnt = new WindowsNameTransform(); wnt.TrimIncomingPaths = false; TestFile(wnt, "c::", "_"); TestFile(wnt, "c\\/>", Path.Combine("c", "_")); }
public void LengthBoundaryOk() { var wnt = new WindowsNameTransform(); string veryLong = "c:\\" + new string('x', 260); try { string transformed = wnt.TransformDirectory(veryLong); } catch { Assert.Fail("Expected no exception"); } }
public void NameTooLong() { var wnt = new WindowsNameTransform(); var veryLong = new string('x', 261); try { wnt.TransformDirectory(veryLong); Assert.Fail("Expected an exception"); } catch (PathTooLongException) { } }
public void BasicFiles() { var wnt = new WindowsNameTransform(); wnt.TrimIncomingPaths = false; TestFile(wnt, "Bogan", "Bogan"); TestFile(wnt, "absolute/file2", Path.Combine("absolute", "file2")); TestFile(wnt, "C:/base/////////t", Path.Combine("base", "t")); TestFile(wnt, "//unc/share/zebidi/and/dylan", Path.Combine("zebidi", "and", "dylan")); TestFile(wnt, @"\\unc\share\/zebidi\/and\/dylan", Path.Combine("zebidi", "and", "dylan")); }
public override IAsyncOperation <IReadOnlyList <IStorageItem> > GetItemsAsync() { return(AsyncInfo.Run <IReadOnlyList <IStorageItem> >(async(cancellationToken) => { using (ZipFile zipFile = await OpenZipFileAsync(FileAccessMode.Read)) { if (zipFile == null) { return null; } zipFile.IsStreamOwner = true; ZipEncoding ??= DetectFileEncoding(zipFile); var wnt = new WindowsNameTransform(ContainerPath, true); // Check with Path.GetFullPath var items = new List <IStorageItem>(); foreach (var entry in zipFile.OfType <ZipEntry>()) // Returns all items recursively { string winPath = System.IO.Path.GetFullPath(entry.IsDirectory ? wnt.TransformDirectory(DecodeEntryName(entry, ZipEncoding)) : wnt.TransformFile(DecodeEntryName(entry, ZipEncoding))); if (winPath.StartsWith(Path.WithEnding("\\"), StringComparison.Ordinal)) // Child of self { var split = winPath.Substring(Path.Length).Split('\\', StringSplitOptions.RemoveEmptyEntries); if (split.Length > 0) { if (entry.IsDirectory || split.Length > 1) // Not all folders have a ZipEntry { var itemPath = System.IO.Path.Combine(Path, split[0]); if (!items.Any(x => x.Path == itemPath)) { items.Add(new ZipStorageFolder(itemPath, ContainerPath, entry) { ZipEncoding = ZipEncoding, BackingFile = BackingFile }); } } else { items.Add(new ZipStorageFile(winPath, ContainerPath, entry) { BackingFile = BackingFile }); } } } } return items; } })); }
public override IAsyncOperation <BaseStorageFile> CreateFileAsync(string desiredName, CreationCollisionOption options) { return(AsyncInfo.Run <BaseStorageFile>(async(cancellationToken) => { using (ZipFile zipFile = await OpenZipFileAsync(FileAccessMode.ReadWrite)) { if (zipFile == null) { return null; } zipFile.IsStreamOwner = true; var znt = new ZipNameTransform(ContainerPath); var zipDesiredName = znt.TransformFile(System.IO.Path.Combine(Path, desiredName)); var entry = zipFile.GetEntry(zipDesiredName); zipFile.BeginUpdate(new MemoryArchiveStorage(FileUpdateMode.Direct)); if (entry != null) { if (options != CreationCollisionOption.ReplaceExisting) { zipFile.AbortUpdate(); return null; } zipFile.Delete(entry); } zipFile.Add(new FileDataSource() { Stream = new MemoryStream() }, zipDesiredName); zipFile.CommitUpdate(); var wnt = new WindowsNameTransform(ContainerPath); return new ZipStorageFile(wnt.TransformFile(zipDesiredName), ContainerPath) { BackingFile = BackingFile }; } })); }
public override IAsyncOperation <BaseStorageFolder> CreateFolderAsync(string desiredName, CreationCollisionOption options) { return(AsyncInfo.Run <BaseStorageFolder>(async(cancellationToken) => { var hFile = NativeFileOperationsHelper.OpenFileForRead(ContainerPath, true); if (hFile.IsInvalid) { return null; } using (ZipFile zipFile = new ZipFile(new FileStream(hFile, FileAccess.ReadWrite))) { zipFile.IsStreamOwner = true; var znt = new ZipNameTransform(ContainerPath); var zipDesiredName = znt.TransformDirectory(System.IO.Path.Combine(Path, desiredName)); var entry = zipFile.GetEntry(zipDesiredName); zipFile.BeginUpdate(new MemoryArchiveStorage(FileUpdateMode.Direct)); if (entry != null) { if (options != CreationCollisionOption.ReplaceExisting) { zipFile.AbortUpdate(); return null; } zipFile.Delete(entry); } zipFile.AddDirectory(zipDesiredName); zipFile.CommitUpdate(); var wnt = new WindowsNameTransform(ContainerPath); return new ZipStorageFolder(wnt.TransformFile(zipDesiredName), ContainerPath) { ZipEncoding = ZipEncoding }; } })); }
protected static bool ExtractPackage(IFile wrapFile, IDirectory destinationDirectory) { try { var nt = new WindowsNameTransform(destinationDirectory.Path.FullPath); using (var zipFile = new ZipFile(wrapFile.OpenRead())) { foreach (ZipEntry zipEntry in zipFile) { if (zipEntry.IsFile) { IFile destinationFile; if (System.IO.Path.DirectorySeparatorChar == '\\') { destinationFile = destinationDirectory.FileSystem.GetFile(nt.TransformFile(zipEntry.Name)); } else { destinationFile = destinationDirectory.GetFile(zipEntry.Name); } using (var targetFile = destinationFile.MustExist().OpenWrite()) using (var sourceFile = zipFile.GetInputStream(zipEntry)) StreamExtensions.CopyTo(sourceFile, targetFile); destinationFile.LastModifiedTimeUtc = zipEntry.DateTime.ToUniversalTime(); } } } } catch (Exception) { return(false); } return(true); }
public void BasicDirectories() { WindowsNameTransform wnt = new WindowsNameTransform(); wnt.TrimIncomingPaths = false; string tutu = Path.GetDirectoryName("\\bogan\\ping.txt"); TestDirectory(wnt, "d/", "d"); TestDirectory(wnt, "d", "d"); TestDirectory(wnt, "absolute/file2", @"absolute\file2"); const string BaseDir1 = @"C:\Dir"; wnt.BaseDirectory = BaseDir1; TestDirectory(wnt, "talofa", Path.Combine(BaseDir1, "talofa")); const string BaseDir2 = @"C:\Dir\"; wnt.BaseDirectory = BaseDir2; TestDirectory(wnt, "talofa", Path.Combine(BaseDir2, "talofa")); }
public void BasicDirectories() { var wnt = new WindowsNameTransform(); wnt.TrimIncomingPaths = false; string tutu = Path.GetDirectoryName("\\bogan\\ping.txt"); TestDirectory(wnt, "d/", "d"); TestDirectory(wnt, "d", "d"); TestDirectory(wnt, "absolute/file2", @"absolute\file2"); string BaseDir1 = Path.Combine("C:\\", "Dir"); wnt.BaseDirectory = BaseDir1; TestDirectory(wnt, "talofa", Path.Combine(BaseDir1, "talofa")); string BaseDir2 = string.Format(@"C:{0}Dir{0}", Path.DirectorySeparatorChar); wnt.BaseDirectory = BaseDir2; TestDirectory(wnt, "talofa", Path.Combine(BaseDir2, "talofa")); }
object extractZip(object zipFileName, string rootDirectory, IStringFilter nf, IStringFilter df) { object ret = null; WindowsNameTransform extractNameTransform = new WindowsNameTransform(rootDirectory); Dictionary <string, bool> dirs = new Dictionary <string, bool>(StringComparer.InvariantCultureIgnoreCase); Stream str; if (zipFileName is byte[]) { str = new MemoryStream((byte[])zipFileName); } else { str = new SeekableStream(Context.OpenStream(zipFileName.ToString()), true); } using (ZipFile zip = new ZipFile(str)) { if (Password != null) { zip.Password = Context.TransformStr(Password, Transform); } foreach (ZipEntry entry in zip) { string targetName = null; if (entry.IsFile) { targetName = extractNameTransform.TransformFile(entry.Name); if (!UsePath) { targetName = Path.Combine(rootDirectory, Path.GetFileName(targetName)); } } else if (entry.IsDirectory) { if (UsePath) { targetName = extractNameTransform.TransformDirectory(entry.Name); } else { targetName = rootDirectory; } } if (string.IsNullOrEmpty(targetName)) { continue; } if (!Hidden) { if (isDos(entry) && (((FileAttributes)entry.ExternalFileAttributes) & (FileAttributes.Hidden)) != 0) { continue; } } if (string.IsNullOrEmpty(entry.Name)) { continue; } var n = new ZipFSEntry(entry, ZipTime); if ((entry.IsFile && df.IsMatch(Path.GetDirectoryName(n.FullName)) && nf.IsMatch(n.Name)) || (entry.IsDirectory && df.IsMatch(n.FullName))) { object r = extract(zip, rootDirectory, targetName, entry, dirs); if (r != null) { return(r); } } } } return(ret); }
public static async Task ExtractArchive(BaseStorageFile archive, BaseStorageFolder destinationFolder, IProgress <float> progressDelegate, CancellationToken cancellationToken) { ZipFile zipFile = await Filesystem.FilesystemTasks.Wrap(async() => new ZipFile(await archive.OpenStreamForReadAsync())); if (zipFile == null) { return; } using (zipFile) { zipFile.IsStreamOwner = true; List <ZipEntry> directoryEntries = new List <ZipEntry>(); List <ZipEntry> fileEntries = new List <ZipEntry>(); foreach (ZipEntry entry in zipFile) { if (entry.IsFile) { fileEntries.Add(entry); } else { directoryEntries.Add(entry); } } if (cancellationToken.IsCancellationRequested) // Check if cancelled { return; } var wnt = new WindowsNameTransform(destinationFolder.Path); var zipEncoding = ZipStorageFolder.DetectFileEncoding(zipFile); var directories = new List <string>(); try { directories.AddRange(directoryEntries.Select((entry) => wnt.TransformDirectory(ZipStorageFolder.DecodeEntryName(entry, zipEncoding)))); directories.AddRange(fileEntries.Select((entry) => Path.GetDirectoryName(wnt.TransformFile(ZipStorageFolder.DecodeEntryName(entry, zipEncoding))))); } catch (InvalidNameException ex) { App.Logger.Warn(ex, $"Error transforming zip names into: {destinationFolder.Path}\n" + $"Directories: {string.Join(", ", directoryEntries.Select(x => x.Name))}\n" + $"Files: {string.Join(", ", fileEntries.Select(x => x.Name))}"); return; } foreach (var dir in directories.Distinct().OrderBy(x => x.Length)) { if (!NativeFileOperationsHelper.CreateDirectoryFromApp(dir, IntPtr.Zero)) { var dirName = destinationFolder.Path; foreach (var component in dir.Substring(destinationFolder.Path.Length).Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries)) { dirName = Path.Combine(dirName, component); NativeFileOperationsHelper.CreateDirectoryFromApp(dirName, IntPtr.Zero); } } if (cancellationToken.IsCancellationRequested) // Check if canceled { return; } } if (cancellationToken.IsCancellationRequested) // Check if canceled { return; } // Fill files byte[] buffer = new byte[4096]; int entriesAmount = fileEntries.Count; int entriesFinished = 0; foreach (var entry in fileEntries) { if (cancellationToken.IsCancellationRequested) // Check if canceled { return; } if (entry.IsCrypted) { App.Logger.Info($"Skipped encrypted zip entry: {entry.Name}"); continue; // TODO: support password protected archives } string filePath = wnt.TransformFile(ZipStorageFolder.DecodeEntryName(entry, zipEncoding)); var hFile = NativeFileOperationsHelper.CreateFileForWrite(filePath); if (hFile.IsInvalid) { return; // TODO: handle error } // We don't close hFile because FileStream.Dispose() already does that using (FileStream destinationStream = new FileStream(hFile, FileAccess.Write)) { int currentBlockSize = 0; using (Stream entryStream = zipFile.GetInputStream(entry)) { while ((currentBlockSize = await entryStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { await destinationStream.WriteAsync(buffer, 0, currentBlockSize); if (cancellationToken.IsCancellationRequested) // Check if cancelled { return; } } } } entriesFinished++; float percentage = (float)((float)entriesFinished / (float)entriesAmount) * 100.0f; progressDelegate?.Report(percentage); } } }
public static async Task ExtractArchive(StorageFile archive, StorageFolder destinationFolder, IProgress <float> progressDelegate, CancellationToken cancellationToken) { using (ZipFile zipFile = new ZipFile(await archive.OpenStreamForReadAsync())) { zipFile.IsStreamOwner = true; List <ZipEntry> directoryEntries = new List <ZipEntry>(); List <ZipEntry> fileEntries = new List <ZipEntry>(); foreach (ZipEntry entry in zipFile) { if (entry.IsFile) { fileEntries.Add(entry); } else { directoryEntries.Add(entry); } } if (cancellationToken.IsCancellationRequested) // Check if cancelled { return; } var wnt = new WindowsNameTransform(destinationFolder.Path); var directories = new List <string>(); directories.AddRange(directoryEntries.Select((item) => wnt.TransformDirectory(item.Name))); directories.AddRange(fileEntries.Select((item) => Path.GetDirectoryName(wnt.TransformFile(item.Name)))); foreach (var dir in directories.Distinct().OrderBy(x => x.Length)) { if (!NativeFileOperationsHelper.CreateDirectoryFromApp(dir, IntPtr.Zero)) { var dirName = destinationFolder.Path; foreach (var component in dir.Substring(destinationFolder.Path.Length).Split(Path.DirectorySeparatorChar, StringSplitOptions.RemoveEmptyEntries)) { dirName = Path.Combine(dirName, component); NativeFileOperationsHelper.CreateDirectoryFromApp(dirName, IntPtr.Zero); } } } if (cancellationToken.IsCancellationRequested) // Check if cancelled { return; } // Fill files byte[] buffer = new byte[4096]; int entriesAmount = fileEntries.Count; int entriesFinished = 0; foreach (var entry in fileEntries) { if (cancellationToken.IsCancellationRequested) // Check if cancelled { return; } string filePath = wnt.TransformFile(entry.Name); var hFile = NativeFileOperationsHelper.CreateFileForWrite(filePath); if (hFile.IsInvalid) { return; // TODO: handle error } using (FileStream destinationStream = new FileStream(hFile, FileAccess.ReadWrite)) { int currentBlockSize = 0; using (Stream entryStream = zipFile.GetInputStream(entry)) { while ((currentBlockSize = await entryStream.ReadAsync(buffer, 0, buffer.Length)) > 0) { await destinationStream.WriteAsync(buffer, 0, buffer.Length); if (cancellationToken.IsCancellationRequested) // Check if cancelled { return; } } } } // We don't close handleContext because FileStream.Dispose() already does that entriesFinished++; float percentage = (float)((float)entriesFinished / (float)entriesAmount) * 100.0f; progressDelegate?.Report(percentage); } } }