diff --git a/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs b/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs index 878649017..852b241ea 100644 --- a/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs +++ b/src/ICSharpCode.SharpZipLib/Tar/TarArchive.cs @@ -855,14 +855,34 @@ private void WriteEntryCore(TarEntry sourceEntry, bool recurse) string newName = null; + // need to have a test if the root path is set to a child directory of the working directory + var currentDirectory = Directory.GetCurrentDirectory() + .ToTarArchivePath(); + if (!String.IsNullOrEmpty(rootPath)) { + // hack: fix this + if (entry.Name.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase)) { newName = entry.Name.Substring(rootPath.Length + 1); } + // root path is set, is root path under the current directory? + else if (entry.Name.StartsWith(currentDirectory + "/" + RootPath, StringComparison.OrdinalIgnoreCase)) + { + newName = entry.Name.Substring(rootPath.Length + 2 + currentDirectory.Length); + } + } + else + { + + if (entry.Name.StartsWith(currentDirectory, StringComparison.OrdinalIgnoreCase)) + { + newName = entry.Name.Substring(currentDirectory.Length); + } } + if (pathPrefix != null) { newName = (newName == null) ? pathPrefix + "/" + entry.Name : pathPrefix + "/" + newName; diff --git a/src/ICSharpCode.SharpZipLib/Tar/TarEntry.cs b/src/ICSharpCode.SharpZipLib/Tar/TarEntry.cs index 82c813367..e59165afe 100644 --- a/src/ICSharpCode.SharpZipLib/Tar/TarEntry.cs +++ b/src/ICSharpCode.SharpZipLib/Tar/TarEntry.cs @@ -348,11 +348,17 @@ public void GetFileTarHeader(TarHeader header, string file) // bugfix from torhovl from #D forum: string name = file; + // not sure if I understand this comment, unsure if this needs to move // 23-Jan-2004 GnuTar allows device names in path where the name is not local to the current directory - if (name.IndexOf(Directory.GetCurrentDirectory(), StringComparison.Ordinal) == 0) - { - name = name.Substring(Directory.GetCurrentDirectory().Length); - } + + // the functional difference here is that TarEntry has changed + // is this something that we are concerned about? + + // TODO: this has moved + //if (name.IndexOf(Directory.GetCurrentDirectory(), StringComparison.Ordinal) == 0) + //{ + // name = name.Substring(Directory.GetCurrentDirectory().Length); + //} /* if (Path.DirectorySeparatorChar == '\\') diff --git a/test/ICSharpCode.SharpZipLib.Tests/Tar/TarTests.cs b/test/ICSharpCode.SharpZipLib.Tests/Tar/TarTests.cs index c6a35ff08..261aef1d7 100644 --- a/test/ICSharpCode.SharpZipLib.Tests/Tar/TarTests.cs +++ b/test/ICSharpCode.SharpZipLib.Tests/Tar/TarTests.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using NUnit.Framework.Internal; +using System.Linq; namespace ICSharpCode.SharpZipLib.Tests.Tar { @@ -916,5 +917,179 @@ public void RootPathIsRespected() } } } + + /// + /// This tests ensure that the property is respected, even if the + /// path is under the current working directory. + /// + [Test] + [Category("Tar")] + public void RootPathUnderWorkDirRespected() + { + // If a user specifies that the RootDir is a path under the working directory + // the RootDir properly must correctly trim away the root path + // this must not alter existing behavior + using (var workDir = new TempDir()) + using (var tarFileName = new TempFile()) + using (var extractDirectory = new TempDir()) + { + // the files created must be under the current working dir + Environment.CurrentDirectory = workDir.FullName; + + // create a temp dir and file under this path + var expectDir = Path.Combine(workDir.FullName, "temp"); // TODO: improve quality of this + Directory.CreateDirectory(expectDir); + var fileName = Path.Combine(expectDir, "testFile.txt"); + File.WriteAllText(fileName, "test123"); + + // extract files under the given path + using (var tarFile = File.Open(tarFileName.FullName, FileMode.Create)) + { + using (var tarOutputStream = TarArchive.CreateOutputTarArchive(tarFile)) + { + tarOutputStream.RootPath = Path.Combine(Environment.CurrentDirectory, "temp"); + var entry = TarEntry.CreateEntryFromFile(fileName); + tarOutputStream.WriteEntry(entry, true); + } + } + + using (var file = File.OpenRead(tarFileName.FullName)) + { + using (var archive = TarArchive.CreateInputTarArchive(file, Encoding.UTF8)) + { + archive.ExtractContents(extractDirectory.FullName); + } + } + + // the resulting files must be the same as the expectation dir, should no longer have the "temp" prefix + var expectationDirectory = new DirectoryInfo(expectDir); + var expectedFile = expectationDirectory.GetFiles("", SearchOption.AllDirectories) + .First(); + + // the archive should contain the entry "testFile.txt", not "temp/testFile.txt", because + // the root dir is configured to "{CurrentDirectory}/tmp/" + FileAssert.DoesNotExist(Path.Combine(extractDirectory.FullName, "temp", "testFile.txt")); + FileAssert.Exists(Path.Combine(extractDirectory.FullName, "testFile.txt")); + + FileAssert.AreEqual(fileName, Path.Combine(extractDirectory.FullName, "testFile.txt")); + } + } + + /// + /// This tests ensure that the property is respected, even if the + /// path is under the current working directory. + /// + [Test] + [Category("Tar")] + public void RootPathUnderWorkDirRespectedExistingBehavior() + { + // If a user specifies that the RootDir is a path under the working directory + // the RootDir properly must correctly trim away the root path + // this must not alter existing behavior + using (var workDir = new TempDir()) + using (var tarFileName = new TempFile()) + using (var extractDirectory = new TempDir()) + { + // the files created must be under the current working dir + Environment.CurrentDirectory = workDir.FullName; + + // create a temp dir and file under this path + var expectDir = Path.Combine(workDir.FullName, "temp"); // TODO: improve quality of this + Directory.CreateDirectory(expectDir); + var fileName = Path.Combine(expectDir, "testFile.txt"); + File.WriteAllText(fileName, "test123"); + + // extract files under the given path + using (var tarFile = File.Open(tarFileName.FullName, FileMode.Create)) + { + using (var tarOutputStream = TarArchive.CreateOutputTarArchive(tarFile)) + { + // when root path is NOT included, maintain the existing behavior + // tarOutputStream.RootPath = Path.Combine(Environment.CurrentDirectory, "temp"); + var entry = TarEntry.CreateEntryFromFile(fileName); + tarOutputStream.WriteEntry(entry, true); + } + } + + using (var file = File.OpenRead(tarFileName.FullName)) + { + using (var archive = TarArchive.CreateInputTarArchive(file, Encoding.UTF8)) + { + archive.ExtractContents(extractDirectory.FullName); + } + } + + // the resulting files must be the same as the expectation dir, should no longer have the "temp" prefix + var expectationDirectory = new DirectoryInfo(expectDir); + var expectedFile = expectationDirectory.GetFiles("", SearchOption.AllDirectories) + .First(); + + // the archive should contain the entry "testFile.txt", not "temp/testFile.txt", because + // the root dir is configured to "{CurrentDirectory}/tmp/" + FileAssert.Exists(Path.Combine(extractDirectory.FullName, "temp", "testFile.txt")); + FileAssert.DoesNotExist(Path.Combine(extractDirectory.FullName, "testFile.txt")); + + FileAssert.AreEqual(fileName, Path.Combine(extractDirectory.FullName, "temp", "testFile.txt")); + } + } + + /// + /// This tests ensure that the property is respected, even if the + /// path is under the current working directory. + /// + [Test] + [Category("Tar")] + public void RootPathUnderWorkDirRespectedExistingBehaviorRootPathIsRelative() + { + // If a user specifies that the RootDir is a path under the working directory + // the RootDir properly must correctly trim away the root path + // this must not alter existing behavior + using (var workDir = new TempDir()) + using (var tarFileName = new TempFile()) + using (var extractDirectory = new TempDir()) + { + // the files created must be under the current working dir + Environment.CurrentDirectory = workDir.FullName; + + // create a temp dir and file under this path + var expectDir = Path.Combine(workDir.FullName, "temp"); // TODO: improve quality of this + Directory.CreateDirectory(expectDir); + var fileName = Path.Combine(expectDir, "testFile.txt"); + File.WriteAllText(fileName, "test123"); + + // extract files under the given path + using (var tarFile = File.Open(tarFileName.FullName, FileMode.Create)) + { + using (var tarOutputStream = TarArchive.CreateOutputTarArchive(tarFile)) + { + // when root path is NOT included, maintain the existing behavior + // tarOutputStream.RootPath = Path.Combine(Environment.CurrentDirectory, "temp"); + tarOutputStream.RootPath = "temp"; + var entry = TarEntry.CreateEntryFromFile(fileName); + tarOutputStream.WriteEntry(entry, true); + } + } + + using (var file = File.OpenRead(tarFileName.FullName)) + { + using (var archive = TarArchive.CreateInputTarArchive(file, Encoding.UTF8)) + { + archive.ExtractContents(extractDirectory.FullName); + } + } + + // the resulting files must be the same as the expectation dir, should no longer have the "temp" prefix + var expectationDirectory = new DirectoryInfo(expectDir); + var expectedFile = expectationDirectory.GetFiles("", SearchOption.AllDirectories) + .First(); + + // the archive should contain the entry "testFile.txt", not "temp/testFile.txt", because + // the root dir is configured to "{CurrentDirectory}/tmp/" + FileAssert.DoesNotExist(Path.Combine(extractDirectory.FullName, "temp", "testFile.txt")); + FileAssert.Exists(Path.Combine(extractDirectory.FullName, "testFile.txt")); + + FileAssert.AreEqual(fileName, Path.Combine(extractDirectory.FullName, "temp", "testFile.txt")); + } + } } }