mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[tests] getting rid of obsolete API use in (de)compressor tests
GitOrigin-RevId: 9946ce70db26f9cb9912732157d59ab37d01b5f8
This commit is contained in:
committed by
intellij-monorepo-bot
parent
242652b9b4
commit
dbe0bbd184
@@ -1,22 +1,18 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.util.io
|
||||
|
||||
import com.intellij.openapi.util.io.IoTestUtil.assumeSymLinkCreationIsSupported
|
||||
import com.intellij.openapi.util.io.NioFiles
|
||||
import com.intellij.testFramework.rules.TempDirectory
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream
|
||||
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Assume.assumeTrue
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.jupiter.api.Assumptions.assumeTrue
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.attribute.PosixFilePermission
|
||||
import java.nio.file.attribute.PosixFilePermissions
|
||||
import java.util.jar.Attributes
|
||||
@@ -24,14 +20,19 @@ import java.util.jar.JarFile
|
||||
import java.util.jar.Manifest
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.createFile
|
||||
import kotlin.io.path.createParentDirectories
|
||||
import kotlin.io.path.createSymbolicLinkPointingTo
|
||||
import kotlin.io.path.getPosixFilePermissions
|
||||
import kotlin.io.path.inputStream
|
||||
import kotlin.io.path.name
|
||||
import kotlin.io.path.writeText
|
||||
|
||||
class CompressorTest {
|
||||
@Rule @JvmField var tempDir: TempDirectory = TempDirectory()
|
||||
|
||||
@Test fun simpleZip() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
val data = tempDir.newFile("file.txt", "789".toByteArray())
|
||||
@Test fun simpleZip(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
val data = tempDir.resolve("file.txt").apply { writeText("789") }
|
||||
Compressor.Zip(zip).use {
|
||||
it.addFile("empty.txt", byteArrayOf())
|
||||
it.addFile("file1.txt", "123".toByteArray())
|
||||
@@ -41,9 +42,9 @@ class CompressorTest {
|
||||
assertZip(zip, "empty.txt" to "", "file1.txt" to "123", "file2.txt" to "456", "file3.txt" to "789")
|
||||
}
|
||||
|
||||
@Test fun simpleTar() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
val data = tempDir.newFile("file.txt", "789".toByteArray())
|
||||
@Test fun simpleTar(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
val data = tempDir.resolve("file.txt").apply { writeText("789") }
|
||||
Compressor.Tar(tar, Compressor.Tar.Compression.GZIP).use {
|
||||
it.addFile("empty.txt", byteArrayOf())
|
||||
it.addFile("file1.txt", "123".toByteArray())
|
||||
@@ -53,8 +54,8 @@ class CompressorTest {
|
||||
assertTar(tar, "empty.txt" to "", "file1.txt" to "123", "file2.txt" to "456", "file3.txt" to "789")
|
||||
}
|
||||
|
||||
@Test fun simpleZipWithFilters() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
@Test fun simpleZipWithFilters(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
val set = mutableSetOf<String>()
|
||||
Compressor.Zip(zip).filter { entryName, _ -> set.add(entryName) && !entryName.startsWith("d1/") }.use {
|
||||
it.addFile("file1.txt", "123".toByteArray())
|
||||
@@ -66,9 +67,9 @@ class CompressorTest {
|
||||
assertZip(zip, "file1.txt" to "123", "file2.txt" to "456")
|
||||
}
|
||||
|
||||
@Test fun streamZip() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
FileOutputStream(zip).use { os ->
|
||||
@Test fun streamZip(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
zip.outputStream().use { os ->
|
||||
Compressor.Zip(os).withLevel(ZipEntry.STORED).use {
|
||||
it.addFile("file.txt", "123".toByteArray())
|
||||
}
|
||||
@@ -76,18 +77,18 @@ class CompressorTest {
|
||||
assertZip(zip, "file.txt" to "123")
|
||||
}
|
||||
|
||||
@Test fun recursiveZip() {
|
||||
val dir = tempDir.newDirectory("dir")
|
||||
tempDir.newFile("dir/f1").writeText("1")
|
||||
tempDir.newFile("dir/f2").writeText("2")
|
||||
tempDir.newFile("dir/d1/f11").writeText("11")
|
||||
tempDir.newFile("dir/d1/f12").writeText("12")
|
||||
tempDir.newFile("dir/d1/d11/f111").writeText("111")
|
||||
tempDir.newFile("dir/d1/d11/f112").writeText("112")
|
||||
tempDir.newFile("dir/d2/f21").writeText("21")
|
||||
tempDir.newFile("dir/d2/f22").writeText("22")
|
||||
@Test fun recursiveZip(@TempDir tempDir: Path) {
|
||||
val dir = tempDir.resolve("dir")
|
||||
tempDir.resolve("dir/f1").createParentDirectories().writeText("1")
|
||||
tempDir.resolve("dir/f2").createParentDirectories().writeText("2")
|
||||
tempDir.resolve("dir/d1/f11").createParentDirectories().writeText("11")
|
||||
tempDir.resolve("dir/d1/f12").createParentDirectories().writeText("12")
|
||||
tempDir.resolve("dir/d1/d11/f111").createParentDirectories().writeText("111")
|
||||
tempDir.resolve("dir/d1/d11/f112").createParentDirectories().writeText("112")
|
||||
tempDir.resolve("dir/d2/f21").createParentDirectories().writeText("21")
|
||||
tempDir.resolve("dir/d2/f22").createParentDirectories().writeText("22")
|
||||
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
Compressor.Zip(zip).filter { entryName, _ -> entryName != "d1/d11" }.use { it.addDirectory(dir) }
|
||||
assertZip(
|
||||
zip,
|
||||
@@ -97,18 +98,18 @@ class CompressorTest {
|
||||
"d2/f21" to "21", "d2/f22" to "22")
|
||||
}
|
||||
|
||||
@Test fun recursiveTarWithPrefix() {
|
||||
val dir = tempDir.newDirectory("dir")
|
||||
tempDir.newFile("dir/f1").writeText("1")
|
||||
tempDir.newFile("dir/f2").writeText("2")
|
||||
tempDir.newFile("dir/d1/f11").writeText("11")
|
||||
tempDir.newFile("dir/d1/f12").writeText("12")
|
||||
tempDir.newFile("dir/d1/d11/f111").writeText("111")
|
||||
tempDir.newFile("dir/d1/d11/f112").writeText("112")
|
||||
tempDir.newFile("dir/d2/f21").writeText("21")
|
||||
tempDir.newFile("dir/d2/f22").writeText("22")
|
||||
@Test fun recursiveTarWithPrefix(@TempDir tempDir: Path) {
|
||||
val dir = tempDir.resolve("dir")
|
||||
tempDir.resolve("dir/f1").createParentDirectories().writeText("1")
|
||||
tempDir.resolve("dir/f2").createParentDirectories().writeText("2")
|
||||
tempDir.resolve("dir/d1/f11").createParentDirectories().writeText("11")
|
||||
tempDir.resolve("dir/d1/f12").createParentDirectories().writeText("12")
|
||||
tempDir.resolve("dir/d1/d11/f111").createParentDirectories().writeText("111")
|
||||
tempDir.resolve("dir/d1/d11/f112").createParentDirectories().writeText("112")
|
||||
tempDir.resolve("dir/d2/f21").createParentDirectories().writeText("21")
|
||||
tempDir.resolve("dir/d2/f22").createParentDirectories().writeText("22")
|
||||
|
||||
val tar = tempDir.newFile("test.tgz")
|
||||
val tar = tempDir.resolve("test.tgz")
|
||||
Compressor.Tar(tar, Compressor.Tar.Compression.GZIP).use { it.addDirectory("tar/", dir) }
|
||||
assertTar(
|
||||
tar,
|
||||
@@ -119,69 +120,71 @@ class CompressorTest {
|
||||
"tar/d2/f21" to "21", "tar/d2/f22" to "22")
|
||||
}
|
||||
|
||||
@Test fun tarWithEmptyPrefix() {
|
||||
val file = tempDir.newFile("dir/file").toPath()
|
||||
val tar = tempDir.newFile("test.tgz")
|
||||
@Test fun tarWithEmptyPrefix(@TempDir tempDir: Path) {
|
||||
val file = tempDir.resolve("dir/file").createParentDirectories().createFile()
|
||||
val tar = tempDir.resolve("test.tgz")
|
||||
Compressor.Tar(tar, Compressor.Tar.Compression.GZIP).use { it.addDirectory("", file.parent) }
|
||||
assertTar(tar, file.name to "")
|
||||
}
|
||||
|
||||
@Test fun tarWithExecutableFiles() {
|
||||
@Test fun tarWithExecutableFiles(@TempDir tempDir: Path) {
|
||||
assumeTrue(FileSystems.getDefault().supportedFileAttributeViews().contains("posix"))
|
||||
|
||||
val dir = tempDir.newDirectory("dir").toPath()
|
||||
val regular = Files.createFile(dir.resolve("regular"))
|
||||
val executable = Files.createFile(dir.resolve("executable"), PosixFilePermissions.asFileAttribute(PosixFilePermission.values().toSet()))
|
||||
val dir = tempDir.resolve("dir").createDirectories()
|
||||
val regular = dir.resolve("regular").createFile()
|
||||
val executable = dir.resolve("executable").createFile(PosixFilePermissions.asFileAttribute(PosixFilePermission.entries.toSet()))
|
||||
|
||||
val tar = tempDir.newFile("test.tgz")
|
||||
val tar = tempDir.resolve("test.tgz")
|
||||
Compressor.Tar(tar, Compressor.Tar.Compression.GZIP).use { it.addDirectory(dir) }
|
||||
val out = tempDir.newDirectory("out").toPath()
|
||||
val out = tempDir.resolve("out")
|
||||
Decompressor.Tar(tar).extract(out)
|
||||
assertThat(Files.getPosixFilePermissions(out.resolve(regular.name))).doesNotContain(PosixFilePermission.OWNER_EXECUTE)
|
||||
assertThat(Files.getPosixFilePermissions(out.resolve(executable.name))).contains(PosixFilePermission.OWNER_EXECUTE)
|
||||
assertThat(out.resolve(regular.name).getPosixFilePermissions()).doesNotContain(PosixFilePermission.OWNER_EXECUTE)
|
||||
assertThat(out.resolve(executable.name).getPosixFilePermissions()).contains(PosixFilePermission.OWNER_EXECUTE)
|
||||
}
|
||||
|
||||
@Test fun tarWithSymbolicLinks() {
|
||||
@Test fun tarWithSymbolicLinks(@TempDir tempDir: Path) {
|
||||
assumeSymLinkCreationIsSupported()
|
||||
|
||||
val dir = tempDir.newDirectory("dir").toPath()
|
||||
val origin = Files.createFile(dir.resolve("origin"))
|
||||
val link = Files.createSymbolicLink(dir.resolve("link"), origin.fileName)
|
||||
val dir = tempDir.resolve("dir").createDirectories()
|
||||
val origin = dir.resolve("origin").createFile()
|
||||
val link = dir.resolve("link").createSymbolicLinkPointingTo(origin.fileName)
|
||||
|
||||
val tar = tempDir.newFile("test.tgz")
|
||||
val tar = tempDir.resolve("test.tgz")
|
||||
Compressor.Tar(tar, Compressor.Tar.Compression.GZIP).use { it.addDirectory(dir) }
|
||||
NioFiles.deleteRecursively(dir)
|
||||
|
||||
val out = tempDir.newDirectory("out").toPath()
|
||||
val out = tempDir.resolve("out")
|
||||
Decompressor.Tar(tar).extract(out)
|
||||
assertThat(out.resolve(link.name)).isSymbolicLink.hasSameBinaryContentAs(out.resolve(origin.name))
|
||||
}
|
||||
|
||||
@Test fun entryNameTrimming() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
@Test fun entryNameTrimming(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
Compressor.Zip(zip).use { it.addFile("//file.txt//", "123".toByteArray()) }
|
||||
assertZip(zip, "file.txt" to "123")
|
||||
}
|
||||
|
||||
@Test fun jarWithManifest() {
|
||||
val jar = tempDir.newFile("test.jar")
|
||||
@Test fun jarWithManifest(@TempDir tempDir: Path) {
|
||||
val jar = tempDir.resolve("test.jar")
|
||||
val mf = Manifest()
|
||||
mf.mainAttributes[Attributes.Name.MANIFEST_VERSION] = "9.75"
|
||||
Compressor.Jar(jar).use { it.addManifest(mf) }
|
||||
assertZip(jar, JarFile.MANIFEST_NAME to "Manifest-Version: 9.75")
|
||||
}
|
||||
|
||||
private fun assertZip(zip: File, vararg expected: Pair<String, String>) {
|
||||
val actual = ZipInputStream(FileInputStream(zip)).use {
|
||||
//<editor-fold desc="Helpers.">
|
||||
private fun assertZip(zip: Path, vararg expected: Pair<String, String>) {
|
||||
val actual = ZipInputStream(zip.inputStream()).use {
|
||||
generateSequence(it::getNextEntry).map { entry -> entry.name to it.readBytes().toString(StandardCharsets.UTF_8).trim() }.toList()
|
||||
}
|
||||
assertThat(actual).containsExactlyInAnyOrder(*expected)
|
||||
}
|
||||
|
||||
private fun assertTar(tar: File, vararg expected: Pair<String, String>) {
|
||||
val actual = TarArchiveInputStream(GzipCompressorInputStream(FileInputStream(tar))).use {
|
||||
generateSequence(it::getNextTarEntry).map { entry -> entry.name to it.readBytes().toString(StandardCharsets.UTF_8).trim() }.toList()
|
||||
private fun assertTar(tar: Path, vararg expected: Pair<String, String>) {
|
||||
val actual = TarArchiveInputStream(GzipCompressorInputStream(tar.inputStream())).use {
|
||||
generateSequence(it::getNextEntry).map { entry -> entry.name to it.readBytes().toString(StandardCharsets.UTF_8).trim() }.toList()
|
||||
}
|
||||
assertThat(actual).containsExactlyInAnyOrder(*expected)
|
||||
}
|
||||
//</editor-fold>
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ package com.intellij.util.io
|
||||
import com.github.marschall.memoryfilesystem.MemoryFileSystemBuilder
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.util.io.IoTestUtil.assumeSymLinkCreationIsSupported
|
||||
import com.intellij.testFramework.rules.TempDirectory
|
||||
import com.intellij.util.SystemProperties
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveEntry
|
||||
import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream
|
||||
@@ -15,11 +14,9 @@ import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.assertj.core.api.Condition
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import java.io.FileOutputStream
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.io.TempDir
|
||||
import java.io.IOException
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.attribute.FileTime
|
||||
import java.time.Instant
|
||||
@@ -28,102 +25,111 @@ import java.util.function.Predicate
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipException
|
||||
import java.util.zip.ZipOutputStream
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.createFile
|
||||
import kotlin.io.path.createParentDirectories
|
||||
import kotlin.io.path.createSymbolicLinkPointingTo
|
||||
import kotlin.io.path.isExecutable
|
||||
import kotlin.io.path.isHidden
|
||||
import kotlin.io.path.isWritable
|
||||
import kotlin.io.path.outputStream
|
||||
import kotlin.io.path.readSymbolicLink
|
||||
import kotlin.io.path.writeBytes
|
||||
import kotlin.io.path.writeText
|
||||
|
||||
class DecompressorTest {
|
||||
@Rule @JvmField var tempDir: TempDirectory = TempDirectory()
|
||||
|
||||
@Test fun noInternalTraversalInZip() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipOutputStream(FileOutputStream(zip)).use { writeEntry(it, "a/../bad.txt") }
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
@Test fun noInternalTraversalInZip(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipOutputStream(zip.outputStream()).use { writeEntry(it, "a/../bad.txt") }
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
testNoTraversal(Decompressor.Zip(zip), dir, dir.resolve("bad.txt"))
|
||||
testNoTraversal(Decompressor.Zip(zip).withZipExtensions(), dir, dir.resolve("bad.txt"))
|
||||
}
|
||||
|
||||
@Test fun noExternalTraversalInZip() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipOutputStream(FileOutputStream(zip)).use { writeEntry(it, "../evil.txt") }
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
@Test fun noExternalTraversalInZip(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipOutputStream(zip.outputStream()).use { writeEntry(it, "../evil.txt") }
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
testNoTraversal(Decompressor.Zip(zip), dir, dir.parent.resolve("evil.txt"))
|
||||
testNoTraversal(Decompressor.Zip(zip).withZipExtensions(), dir, dir.parent.resolve("evil.txt"))
|
||||
}
|
||||
|
||||
@Test fun noAbsolutePathsInZip() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipOutputStream(FileOutputStream(zip)).use { writeEntry(it, "/root.txt") }
|
||||
val dir1 = tempDir.newDirectory("unpacked1").toPath()
|
||||
@Test fun noAbsolutePathsInZip(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipOutputStream(zip.outputStream()).use { writeEntry(it, "/root.txt") }
|
||||
val dir1 = tempDir.resolve("unpacked1")
|
||||
Decompressor.Zip(zip).extract(dir1)
|
||||
assertThat(dir1.resolve("root.txt")).exists()
|
||||
val dir2 = tempDir.newDirectory("unpacked2").toPath()
|
||||
val dir2 = tempDir.resolve("unpacked2")
|
||||
Decompressor.Zip(zip).withZipExtensions().extract(dir2)
|
||||
assertThat(dir2.resolve("root.txt")).exists()
|
||||
}
|
||||
|
||||
@Test fun tarDetectionPlain() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "dir/file.txt") }
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
@Test fun tarDetectionPlain(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "dir/file.txt") }
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).extract(dir)
|
||||
assertThat(dir.resolve("dir/file.txt")).exists()
|
||||
}
|
||||
|
||||
@Test fun tarDetectionGZip() {
|
||||
val tar = tempDir.newFile("test.tgz")
|
||||
TarArchiveOutputStream(GzipCompressorOutputStream(FileOutputStream(tar))).use { writeEntry(it, "dir/file.txt") }
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
@Test fun tarDetectionGZip(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tgz")
|
||||
TarArchiveOutputStream(GzipCompressorOutputStream(tar.outputStream())).use { writeEntry(it, "dir/file.txt") }
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).extract(dir)
|
||||
assertThat(dir.resolve("dir/file.txt")).exists()
|
||||
}
|
||||
|
||||
@Test fun noInternalTraversalInTar() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "a/../bad.txt") }
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
@Test fun noInternalTraversalInTar(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "a/../bad.txt") }
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
testNoTraversal(Decompressor.Tar(tar), dir, dir.resolve("bad.txt"))
|
||||
}
|
||||
|
||||
@Test fun noExternalTraversalInTar() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "../evil.txt") }
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
@Test fun noExternalTraversalInTar(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "../evil.txt") }
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
testNoTraversal(Decompressor.Tar(tar), dir, dir.parent.resolve("evil.txt"))
|
||||
}
|
||||
|
||||
@Test fun noAbsolutePathsInTar() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "/root.txt") }
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
@Test fun noAbsolutePathsInTar(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "/root.txt") }
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).extract(dir)
|
||||
assertThat(dir.resolve("root.txt")).exists()
|
||||
}
|
||||
|
||||
@Test(expected = ZipException::class)
|
||||
fun failsOnCorruptedZip() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
zip.writeText("whatever")
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
Decompressor.Zip(zip).extract(dir)
|
||||
@Test
|
||||
fun failsOnCorruptedZip(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.createDirectories().resolve("test.zip").apply { writeText("whatever") }
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
assertThatThrownBy {
|
||||
Decompressor.Zip(zip).extract(dir)
|
||||
}.isInstanceOf(ZipException::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun failsOnCorruptedExtZip() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
zip.writeText("whatever")
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
fun failsOnCorruptedExtZip(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip").apply { writeText("whatever") }
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
assertThatThrownBy {
|
||||
Decompressor.Zip(zip).withZipExtensions().extract(dir)
|
||||
}.hasRootCauseInstanceOf(ZipException::class.java)
|
||||
}
|
||||
|
||||
@Test fun tarFileModes() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use {
|
||||
@Test fun tarFileModes(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "dir/r", mode = 0b100_000_000)
|
||||
writeEntry(it, "dir/rw", mode = 0b110_000_000)
|
||||
writeEntry(it, "dir/rx", mode = 0b101_000_000)
|
||||
writeEntry(it, "dir/rwx", mode = 0b111_000_000)
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).extract(dir)
|
||||
if (SystemInfo.isWindows) {
|
||||
arrayOf("r", "rw", "rx", "rwx").forEach {
|
||||
@@ -138,15 +144,15 @@ class DecompressorTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun zipUnixFileModes() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun zipUnixFileModes(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "dir/r", mode = 0b100_000_000)
|
||||
writeEntry(it, "dir/rw", mode = 0b110_000_000)
|
||||
writeEntry(it, "dir/rx", mode = 0b101_000_000)
|
||||
writeEntry(it, "dir/rwx", mode = 0b111_000_000)
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Zip(zip).withZipExtensions().extract(dir)
|
||||
if (SystemInfo.isWindows) {
|
||||
arrayOf("r", "rw", "rx", "rwx").forEach {
|
||||
@@ -161,14 +167,14 @@ class DecompressorTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun zipDosFileModes() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun zipDosFileModes(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "dir/ro", readOnly = true)
|
||||
writeEntry(it, "dir/rw")
|
||||
writeEntry(it, "dir/h", hidden = true)
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Zip(zip).withZipExtensions().extract(dir)
|
||||
assertThat(dir.resolve("dir/ro")).exists().isNot(Writable)
|
||||
assertThat(dir.resolve("dir/rw")).exists().`is`(Writable)
|
||||
@@ -177,91 +183,91 @@ class DecompressorTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun filtering() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun filtering(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "d1/f1.txt")
|
||||
writeEntry(it, "d2/f2.txt")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Zip(zip).filter(Predicate { !it.startsWith("d2/") }).extract(dir)
|
||||
assertThat(dir.resolve("d1/f1.txt")).isRegularFile()
|
||||
assertThat(dir.resolve("d2")).doesNotExist()
|
||||
}
|
||||
|
||||
@Test fun tarSymlinks() {
|
||||
@Test fun tarSymlinks(@TempDir tempDir: Path) {
|
||||
assumeSymLinkCreationIsSupported()
|
||||
|
||||
val rogueTarget = tempDir.newFile("rogue_f", "123789".toByteArray(Charsets.UTF_8))
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use {
|
||||
val rogueTarget = tempDir.resolve("rogue_f").apply { writeText("123789") }
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "f")
|
||||
writeEntry(it, "links/ok", link = "../f")
|
||||
writeEntry(it, "rogue", link = "../rogue_f")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).extract(dir)
|
||||
assertThat(dir.resolve("links/ok")).isSymbolicLink().hasSameBinaryContentAs(dir.resolve("f"))
|
||||
assertThat(dir.resolve("rogue")).isSymbolicLink().hasSameBinaryContentAs(rogueTarget.toPath())
|
||||
assertThat(dir.resolve("rogue")).isSymbolicLink().hasSameBinaryContentAs(rogueTarget)
|
||||
}
|
||||
|
||||
@Test fun tarHardlinks() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use {
|
||||
@Test fun tarHardlinks(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "hardlink", link = "hardlink", type = TarArchiveEntry.LF_LINK)
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).extract(dir)
|
||||
|
||||
assertThat(dir.resolve("hardlink")).doesNotExist()
|
||||
}
|
||||
|
||||
@Test fun zipSymlinks() {
|
||||
@Test fun zipSymlinks(@TempDir tempDir: Path) {
|
||||
assumeSymLinkCreationIsSupported()
|
||||
|
||||
val rogueTarget = tempDir.newFile("rogue_f", "123789".toByteArray(Charsets.UTF_8))
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use {
|
||||
val rogueTarget = tempDir.resolve("rogue_f").apply { writeText("123789") }
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "f")
|
||||
writeEntry(it, "links/ok", link = "../f")
|
||||
writeEntry(it, "rogue", link = "../rogue_f")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Zip(zip).withZipExtensions().extract(dir)
|
||||
assertThat(dir.resolve("links/ok")).isSymbolicLink().hasSameBinaryContentAs(dir.resolve("f"))
|
||||
assertThat(dir.resolve("rogue")).isSymbolicLink().hasSameBinaryContentAs(rogueTarget.toPath())
|
||||
assertThat(dir.resolve("rogue")).isSymbolicLink().hasSameBinaryContentAs(rogueTarget)
|
||||
}
|
||||
|
||||
@Test fun zipRogueSymlinks() {
|
||||
@Test fun zipRogueSymlinks(@TempDir tempDir: Path) {
|
||||
assumeSymLinkCreationIsSupported()
|
||||
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use { writeEntry(it, "rogue", link = "../f") }
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use { writeEntry(it, "rogue", link = "../f") }
|
||||
|
||||
val decompressor = Decompressor.Zip(zip).withZipExtensions().escapingSymlinkPolicy(
|
||||
Decompressor.EscapingSymlinkPolicy.DISALLOW)
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
testNoTraversal(decompressor, dir, dir.resolve("rogue"))
|
||||
}
|
||||
|
||||
@Test fun tarRogueSymlinks() {
|
||||
@Test fun tarRogueSymlinks(@TempDir tempDir: Path) {
|
||||
assumeSymLinkCreationIsSupported()
|
||||
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "rogue", link = "../f") }
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "rogue", link = "../f") }
|
||||
|
||||
val decompressor = Decompressor.Tar(tar).escapingSymlinkPolicy(
|
||||
Decompressor.EscapingSymlinkPolicy.DISALLOW)
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
testNoTraversal(decompressor, dir, dir.resolve("rogue"))
|
||||
}
|
||||
|
||||
@Test fun prefixPathsFilesInZip() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun prefixPathsFilesInZip(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "a/b/c.txt")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Zip(zip).removePrefixPath("a/b").extract(dir)
|
||||
|
||||
assertThat(dir.resolve("c.txt")).isRegularFile()
|
||||
@@ -270,12 +276,12 @@ class DecompressorTest {
|
||||
assertThat(dir.resolve("b")).doesNotExist()
|
||||
}
|
||||
|
||||
@Test fun prefixPathsFilesInCommonsZip() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun prefixPathsFilesInCommonsZip(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "a/b/c.txt")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Zip(zip).removePrefixPath("a/b").extract(dir)
|
||||
|
||||
assertThat(dir.resolve("c.txt")).isRegularFile()
|
||||
@@ -284,13 +290,13 @@ class DecompressorTest {
|
||||
assertThat(dir.resolve("b")).doesNotExist()
|
||||
}
|
||||
|
||||
@Test fun prefixPathFilesInZipWithFilter() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun prefixPathFilesInZipWithFilter(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "a/b/c.txt")
|
||||
writeEntry(it, "skip.txt")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
val filterLog = mutableListOf<String>()
|
||||
Decompressor.Zip(zip).removePrefixPath("a/b").filter(Predicate{ filterLog.add(it) }).extract(dir)
|
||||
|
||||
@@ -302,40 +308,40 @@ class DecompressorTest {
|
||||
assertThat(filterLog).containsExactlyInAnyOrder("a/b/c.txt", "skip.txt")
|
||||
}
|
||||
|
||||
@Test fun prefixPathsFilesInTarWithSymlinks() {
|
||||
@Test fun prefixPathsFilesInTarWithSymlinks(@TempDir tempDir: Path) {
|
||||
assumeSymLinkCreationIsSupported()
|
||||
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "a/f")
|
||||
writeEntry(it, "a/links/ok", link = "../f")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).removePrefixPath("a").extract(dir)
|
||||
|
||||
assertThat(dir.resolve("f")).isRegularFile()
|
||||
assertThat(dir.resolve("links/ok")).isSymbolicLink().hasSameBinaryContentAs(dir.resolve("f"))
|
||||
}
|
||||
|
||||
@Test fun prefixPathFillMatch() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use {
|
||||
@Test fun prefixPathFillMatch(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "./a/f")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).removePrefixPath("/a/f").extract(dir)
|
||||
|
||||
assertThat(dir.resolve("f")).doesNotExist()
|
||||
}
|
||||
|
||||
@Test fun prefixPathWithSlashTar() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use {
|
||||
@Test fun prefixPathWithSlashTar(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "./a/f")
|
||||
writeEntry(it, "/a/g")
|
||||
writeEntry(it, "././././././//a/h")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).removePrefixPath("/a/").extract(dir)
|
||||
|
||||
assertThat(dir.resolve("f")).isRegularFile()
|
||||
@@ -343,14 +349,14 @@ class DecompressorTest {
|
||||
assertThat(dir.resolve("h")).isRegularFile()
|
||||
}
|
||||
|
||||
@Test fun prefixPathWithDotTar() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use {
|
||||
@Test fun prefixPathWithDotTar(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "./a/b/f")
|
||||
writeEntry(it, "/a/b/g")
|
||||
writeEntry(it, "././././././//a/b/h")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).removePrefixPath("./a/b").extract(dir)
|
||||
|
||||
assertThat(dir.resolve("f")).isRegularFile()
|
||||
@@ -358,14 +364,14 @@ class DecompressorTest {
|
||||
assertThat(dir.resolve("h")).isRegularFile()
|
||||
}
|
||||
|
||||
@Test fun prefixPathWithCommonsZip() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun prefixPathWithCommonsZip(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "./a/b/f")
|
||||
writeEntry(it, "/a/b/g")
|
||||
writeEntry(it, "././././././//a/b/h")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Zip(zip).removePrefixPath("./a/b").extract(dir)
|
||||
|
||||
assertThat(dir.resolve("f")).isRegularFile()
|
||||
@@ -373,93 +379,92 @@ class DecompressorTest {
|
||||
assertThat(dir.resolve("h")).isRegularFile()
|
||||
}
|
||||
|
||||
@Test fun prefixPathTarSymlink() {
|
||||
@Test fun prefixPathTarSymlink(@TempDir tempDir: Path) {
|
||||
assumeSymLinkCreationIsSupported()
|
||||
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "./a/b/f")
|
||||
writeEntry(it, "a/b/links/ok", link = "../f")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).removePrefixPath("a/b").extract(dir)
|
||||
|
||||
assertThat(dir.resolve("f")).isRegularFile()
|
||||
assertThat(dir.resolve("links/ok")).isSymbolicLink().hasSameBinaryContentAs(dir.resolve("f"))
|
||||
}
|
||||
|
||||
@Test fun prefixPathZipSymlink() {
|
||||
@Test fun prefixPathZipSymlink(@TempDir tempDir: Path) {
|
||||
assumeSymLinkCreationIsSupported()
|
||||
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "./a/b/f")
|
||||
writeEntry(it, "a/b/links/ok", link = "../f")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Zip(zip).withZipExtensions().removePrefixPath("a/b").extract(dir)
|
||||
|
||||
assertThat(dir.resolve("f")).isRegularFile()
|
||||
assertThat(dir.resolve("links/ok")).isSymbolicLink().hasSameBinaryContentAs(dir.resolve("f"))
|
||||
}
|
||||
|
||||
@Test fun prefixPathTarRogueSymlinks() {
|
||||
@Test fun prefixPathTarRogueSymlinks(@TempDir tempDir: Path) {
|
||||
assumeSymLinkCreationIsSupported()
|
||||
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use { writeEntry(it, "a/b/c/rogue", link = "../f") }
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use { writeEntry(it, "a/b/c/rogue", link = "../f") }
|
||||
|
||||
val decompressor = Decompressor.Tar(tar).escapingSymlinkPolicy(
|
||||
Decompressor.EscapingSymlinkPolicy.DISALLOW).removePrefixPath("a/b/c")
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
testNoTraversal(decompressor, dir, dir.resolve("rogue"))
|
||||
}
|
||||
|
||||
@Test fun prefixPathZipRogueSymlinks() {
|
||||
@Test fun prefixPathZipRogueSymlinks(@TempDir tempDir: Path) {
|
||||
assumeSymLinkCreationIsSupported()
|
||||
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use { writeEntry(it, "a/b/c/rogue", link = "../f") }
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use { writeEntry(it, "a/b/c/rogue", link = "../f") }
|
||||
|
||||
val decompressor = Decompressor.Zip(zip).withZipExtensions().escapingSymlinkPolicy(
|
||||
Decompressor.EscapingSymlinkPolicy.DISALLOW).removePrefixPath("a/b/c")
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
testNoTraversal(decompressor, dir, dir.resolve("rogue"))
|
||||
}
|
||||
|
||||
@Test fun prefixPathSkipsTooShortPaths() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use {
|
||||
@Test fun prefixPathSkipsTooShortPaths(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "missed")
|
||||
writeEntry(it, "a/b/c/file.txt")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).removePrefixPath("a/b").extract(dir)
|
||||
assertThat(dir.resolve("c/file.txt")).isRegularFile()
|
||||
assertThat(dir.resolve("missed")).doesNotExist()
|
||||
}
|
||||
|
||||
@Test fun fileOverwrite() {
|
||||
val zip = tempDir.newFile("test.zip")
|
||||
ZipOutputStream(FileOutputStream(zip)).use { writeEntry(it, "a/file.txt") }
|
||||
val dir = tempDir.newDirectory("unpacked")
|
||||
val file = tempDir.newFile("unpacked/a/file.txt", byteArrayOf(0))
|
||||
@Test fun fileOverwrite(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("test.zip")
|
||||
ZipOutputStream(zip.outputStream()).use { writeEntry(it, "a/file.txt") }
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
val file = tempDir.resolve("unpacked/a/file.txt").createParentDirectories().apply { writeBytes(byteArrayOf(0)) }
|
||||
Decompressor.Zip(zip).extract(dir)
|
||||
assertThat(file).hasBinaryContent(TestContent)
|
||||
}
|
||||
|
||||
@Test fun symlinkOverwrite() {
|
||||
@Test fun symlinkOverwrite(@TempDir tempDir: Path) {
|
||||
assumeSymLinkCreationIsSupported()
|
||||
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "a/file")
|
||||
writeEntry(it, "a/link", link = "file")
|
||||
}
|
||||
val dir = tempDir.newDirectory("unpacked")
|
||||
val link = tempDir.rootPath.resolve("unpacked/a/link")
|
||||
val target = tempDir.newFile("unpacked/a/target", byteArrayOf(0)).toPath()
|
||||
Files.createSymbolicLink(link, target)
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
val target = tempDir.resolve("unpacked/a/target").createParentDirectories().apply { writeBytes(byteArrayOf(0)) }
|
||||
val link = tempDir.resolve("unpacked/a/link").createSymbolicLinkPointingTo(target)
|
||||
Decompressor.Tar(tar).extract(dir)
|
||||
assertThat(link).isSymbolicLink().hasBinaryContent(TestContent)
|
||||
}
|
||||
@@ -467,11 +472,11 @@ class DecompressorTest {
|
||||
@Test fun extZipPureNIO() {
|
||||
MemoryFileSystemBuilder.newLinux().build("${DecompressorTest::class.simpleName}.extZipPureNIO").use { fs ->
|
||||
val testDir = fs.getPath("/home/${SystemProperties.getUserName()}")
|
||||
val zip = Files.createFile(testDir.resolve("test.zip"))
|
||||
ZipArchiveOutputStream(Files.newOutputStream(zip)).use {
|
||||
val zip = testDir.resolve("test.zip").createFile()
|
||||
ZipArchiveOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "dir/r", mode = 0b100_000_000)
|
||||
}
|
||||
val dir = Files.createDirectory(testDir.resolve("unpacked"))
|
||||
val dir = testDir.resolve("unpacked").createDirectories()
|
||||
Decompressor.Zip(zip).withZipExtensions().extract(dir)
|
||||
assertThat(dir.resolve("dir/r")).exists()
|
||||
}
|
||||
@@ -480,40 +485,40 @@ class DecompressorTest {
|
||||
@Test fun tarPureNIO() {
|
||||
MemoryFileSystemBuilder.newLinux().build("${DecompressorTest::class.simpleName}.tarPureNIO").use { fs ->
|
||||
val testDir = fs.getPath("/home/${SystemProperties.getUserName()}")
|
||||
val tar = Files.createFile(testDir.resolve("test.tar"))
|
||||
TarArchiveOutputStream(Files.newOutputStream(tar)).use {
|
||||
val tar = testDir.resolve("test.tar").createFile()
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "dir/r", mode = 0b100_000_000)
|
||||
}
|
||||
val dir = Files.createDirectory(testDir.resolve("unpacked"))
|
||||
val dir = testDir.resolve("unpacked").createDirectories()
|
||||
Decompressor.Tar(tar).extract(dir)
|
||||
assertThat(dir.resolve("dir/r")).exists()
|
||||
}
|
||||
}
|
||||
|
||||
@Test fun absoluteSymlinkToRelativeWithOptionSet() {
|
||||
val tar = tempDir.newFile("test.tar")
|
||||
TarArchiveOutputStream(FileOutputStream(tar)).use {
|
||||
@Test fun absoluteSymlinkToRelativeWithOptionSet(@TempDir tempDir: Path) {
|
||||
val tar = tempDir.resolve("test.tar")
|
||||
TarArchiveOutputStream(tar.outputStream()).use {
|
||||
writeEntry(it, "symlink", link = "/root")
|
||||
}
|
||||
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Tar(tar).escapingSymlinkPolicy(
|
||||
Decompressor.EscapingSymlinkPolicy.RELATIVIZE_ABSOLUTE).extract(dir)
|
||||
|
||||
val symlink = dir.resolve("symlink")
|
||||
assertThat(symlink).isSymbolicLink()
|
||||
assertThat(Files.readSymbolicLink(symlink)).isEqualTo(dir.resolve("root"))
|
||||
assertThat(symlink.readSymbolicLink()).isEqualTo(dir.resolve("root"))
|
||||
}
|
||||
|
||||
@Test fun retryStrategyErrorHandler() {
|
||||
val zip = tempDir.newFile("retryStrategyErrorHandler.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun retryStrategyErrorHandler(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("retryStrategyErrorHandler.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "good-file.txt")
|
||||
writeEntry(it, "bad-file.txt", link = "")
|
||||
writeEntry(it, "good-file-too.md")
|
||||
}
|
||||
var retries = 3 // to make sure if we really make retrying
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
|
||||
Decompressor.Zip(zip).withZipExtensions().errorHandler { _, _ ->
|
||||
if (retries == 0) {
|
||||
@@ -529,46 +534,46 @@ class DecompressorTest {
|
||||
assertThat(dir.resolve("good-file-too.md")).exists()
|
||||
}
|
||||
|
||||
@Test fun abortStrategyErrorHandlerDeletingFiles() {
|
||||
val zip = tempDir.newFile("abortStrategyErrorHandlerDeletingFiles.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun abortStrategyErrorHandlerDeletingFiles(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("abortStrategyErrorHandlerDeletingFiles.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "good-file.txt")
|
||||
writeEntry(it, "very-good-file.java")
|
||||
writeEntry(it, "bad-file.txt", link = "")
|
||||
}
|
||||
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Zip(zip).withZipExtensions().errorHandler { _, _ -> Decompressor.ErrorHandlerChoice.ABORT }.extract(dir)
|
||||
|
||||
assertThat(dir.resolve("good-file.txt")).doesNotExist()
|
||||
assertThat(dir.resolve("very-good-file.java")).doesNotExist()
|
||||
}
|
||||
|
||||
@Test fun skipStrategyErrorHandlerNotDeletingFiles() {
|
||||
val zip = tempDir.newFile("skipStrategyErrorHandlerNotDeletingFiles.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun skipStrategyErrorHandlerNotDeletingFiles(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("skipStrategyErrorHandlerNotDeletingFiles.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "good-file.txt")
|
||||
writeEntry(it, "bad-file.txt", link = "")
|
||||
writeEntry(it, "very-good-file.java")
|
||||
}
|
||||
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
Decompressor.Zip(zip).withZipExtensions().errorHandler { _, _ -> Decompressor.ErrorHandlerChoice.SKIP }.extract(dir)
|
||||
|
||||
assertThat(dir.resolve("good-file.txt")).exists()
|
||||
assertThat(dir.resolve("very-good-file.java")).exists()
|
||||
}
|
||||
|
||||
@Test fun doNothingStrategyErrorHandlerNotDeletingFilesBeforeSkipAfter() {
|
||||
val zip = tempDir.newFile("doNothingStrategyErrorHandlerNotDeletingFilesBeforeSkipAfter.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun doNothingStrategyErrorHandlerNotDeletingFilesBeforeSkipAfter(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("doNothingStrategyErrorHandlerNotDeletingFilesBeforeSkipAfter.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "good-file.txt")
|
||||
writeEntry(it, "very-good-file.java")
|
||||
writeEntry(it, "bad-file.txt", link = "")
|
||||
writeEntry(it, "good-but-unlucky-file.kt")
|
||||
}
|
||||
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
assertThatThrownBy {
|
||||
Decompressor.Zip(zip).withZipExtensions().errorHandler { _, _ -> Decompressor.ErrorHandlerChoice.BAIL_OUT }.extract(dir)
|
||||
}.isInstanceOf(IOException::class.java)
|
||||
@@ -578,15 +583,15 @@ class DecompressorTest {
|
||||
assertThat(dir.resolve("good-but-unlucky-file.kt")).doesNotExist()
|
||||
}
|
||||
|
||||
@Test fun skipAllStrategyCalledOnlyOnce() {
|
||||
val zip = tempDir.newFile("skipAllStrategyCalledOnlyOnce.zip")
|
||||
ZipArchiveOutputStream(FileOutputStream(zip)).use {
|
||||
@Test fun skipAllStrategyCalledOnlyOnce(@TempDir tempDir: Path) {
|
||||
val zip = tempDir.resolve("skipAllStrategyCalledOnlyOnce.zip")
|
||||
ZipArchiveOutputStream(zip.outputStream()).use {
|
||||
writeEntry(it, "bad-file.txt", link = "")
|
||||
writeEntry(it, "another-bad-file.txt", link = "")
|
||||
writeEntry(it, "another-bad-file.cpp", link = "")
|
||||
}
|
||||
var isCalled = false
|
||||
val dir = tempDir.newDirectory("unpacked").toPath()
|
||||
val dir = tempDir.resolve("unpacked")
|
||||
|
||||
Decompressor.Zip(zip).withZipExtensions().errorHandler { _, _ ->
|
||||
if (!isCalled) {
|
||||
@@ -596,6 +601,8 @@ class DecompressorTest {
|
||||
throw AssertionError("SKIP_ALL strategy can't be called twice")
|
||||
}
|
||||
}.extract(dir)
|
||||
|
||||
assertThat(isCalled).isTrue
|
||||
}
|
||||
|
||||
//<editor-fold desc="Helpers.">
|
||||
@@ -658,9 +665,9 @@ class DecompressorTest {
|
||||
|
||||
companion object {
|
||||
private val TestContent = "...".toByteArray()
|
||||
private val Writable = Condition<Path>(Predicate { Files.isWritable(it) }, "writable")
|
||||
private val Executable = Condition<Path>(Predicate { Files.isExecutable(it) }, "executable")
|
||||
private val Hidden = Condition<Path>(Predicate { Files.isHidden(it) }, "hidden")
|
||||
private val Writable = Condition<Path>(Predicate { it.isWritable() }, "writable")
|
||||
private val Executable = Condition<Path>(Predicate { it.isExecutable() }, "executable")
|
||||
private val Hidden = Condition<Path>(Predicate { it.isHidden() }, "hidden")
|
||||
}
|
||||
//</editor-fold>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user