From f581a022075a22e38e33a5923cbb8d2f867739f4 Mon Sep 17 00:00:00 2001 From: Eugene Petrenko Date: Mon, 28 Oct 2019 16:37:01 +0100 Subject: [PATCH] Decompressor - flip cut dirs and filter, add more tests GitOrigin-RevId: 437231f0e937bbdc79285246a5429110dc047173 --- .../com/intellij/util/io/Decompressor.java | 20 +++++++------- .../com/intellij/util/io/DecompressorTest.kt | 27 ++++++++++++++++--- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/Decompressor.java b/platform/util/src/com/intellij/util/io/Decompressor.java index 6ee99f4781a6..19a58599e906 100644 --- a/platform/util/src/com/intellij/util/io/Decompressor.java +++ b/platform/util/src/com/intellij/util/io/Decompressor.java @@ -19,8 +19,6 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.Enumeration; import java.util.List; -import java.util.StringJoiner; -import java.util.function.Function; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -156,7 +154,9 @@ public abstract class Decompressor { /** * Removes several leading directories from the archive during extraction. * Some entries may clash, so use {@link #overwrite(boolean)} to control it. - * Some short file entries may be lost + * Some short file entries may be lost. + * + * Executed AFTER filter test! * * @param dirsToCut how many directories has to be removed from archive entry names * @return self @@ -172,19 +172,17 @@ public abstract class Decompressor { try { Entry entry; while ((entry = nextEntry()) != null) { - entry = entry.cutDirs(myCutDirs); - if (entry == null) continue; - - String name = entry.name; - if (myFilter != null) { - String entryName = entry.type == Type.DIR && !StringUtil.endsWithChar(name, '/') ? name + '/' : name; + String entryName = entry.type == Type.DIR && !StringUtil.endsWithChar(entry.name, '/') ? entry.name + '/' : entry.name; if (!myFilter.value(entryName)) { continue; } } - File outputFile = entryFile(outputDir, name); + entry = entry.cutDirs(myCutDirs); + if (entry == null) continue; + + File outputFile = entryFile(outputDir, entry.name); switch (entry.type) { case DIR: @@ -215,7 +213,7 @@ public abstract class Decompressor { case SYMLINK: if (StringUtil.isEmpty(entry.linkTarget) || !FileUtil.isAncestor(outputDir, new File(FileUtil.toCanonicalPath(outputFile.getParent() + '/' + entry.linkTarget)), true)) { - throw new IOException("Invalid symlink entry: " + name + " -> " + entry.linkTarget); + throw new IOException("Invalid symlink entry: " + entry.name + " -> " + entry.linkTarget); } FileUtil.createParentDirs(outputFile); Files.createSymbolicLink(outputFile.toPath(), Paths.get(entry.linkTarget)); diff --git a/platform/util/testSrc/com/intellij/util/io/DecompressorTest.kt b/platform/util/testSrc/com/intellij/util/io/DecompressorTest.kt index 6296ab21da83..1f5fe7072c1d 100644 --- a/platform/util/testSrc/com/intellij/util/io/DecompressorTest.kt +++ b/platform/util/testSrc/com/intellij/util/io/DecompressorTest.kt @@ -142,7 +142,7 @@ class DecompressorTest { testNoTraversal(Decompressor.Tar(tar).withSymlinks(), dir, File(dir, "rogue")) } - @Test fun mapsFilesInZip() { + @Test fun cutDirsFilesInZip() { val zip = tempDir.newFile("test.zip") ZipOutputStream(FileOutputStream(zip)).use { writeEntry(it, "a/b/c.txt") } val dir = tempDir.newFolder("unpacked") @@ -154,7 +154,26 @@ class DecompressorTest { assertThat(File(dir, "b")).doesNotExist() } - @Test fun mapsFilesInTarWithSymlinks() { + @Test fun cutDirsFilesInZipWitFilter() { + val zip = tempDir.newFile("test.zip") + ZipOutputStream(FileOutputStream(zip)).use { + writeEntry(it, "a/b/c.txt") + writeEntry(it, "skip.txt") + } + val dir = tempDir.newFolder("unpacked") + val filterLog = mutableListOf() + Decompressor.Zip(zip).cutDirs(2).filter { filterLog.add(it) }.extract(dir) + + assertThat(File(dir, "c.txt")).isFile() + assertThat(File(dir, "a")).doesNotExist() + assertThat(File(dir, "a/b")).doesNotExist() + assertThat(File(dir, "b")).doesNotExist() + + //it must call filter before cut-dirs + Assert.assertEquals(setOf("a/b/c.txt", "skip.txt"), filterLog.toSet()) + } + + @Test fun cutDirsFilesInTarWithSymlinks() { assumeSymLinkCreationIsSupported() val tar = tempDir.newFile("test.tar") @@ -169,7 +188,7 @@ class DecompressorTest { assertThat(File(dir, "links/ok").toPath()).isSymbolicLink().hasSameContentAs(File(dir, "f").toPath()) } - @Test fun mapRogueSymlinks() { + @Test fun cutDirRogueSymlinks() { assumeSymLinkCreationIsSupported() val tar = tempDir.newFile("test.tar") @@ -178,7 +197,7 @@ class DecompressorTest { testNoTraversal(Decompressor.Tar(tar).cutDirs(3), dir, File(dir, "rogue")) } - @Test fun mapSkipsTooShortPaths() { + @Test fun cutDirSkipsTooShortPaths() { assumeSymLinkCreationIsSupported() val tar = tempDir.newFile("test.tar")