You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ZipUtilsTest.java 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2019 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.api.utils;
  21. import com.google.common.collect.Iterators;
  22. import java.io.File;
  23. import java.io.FileInputStream;
  24. import java.io.IOException;
  25. import java.io.InputStream;
  26. import java.net.URL;
  27. import java.util.ArrayList;
  28. import java.util.Collections;
  29. import java.util.Iterator;
  30. import java.util.zip.ZipEntry;
  31. import java.util.zip.ZipFile;
  32. import org.apache.commons.io.FileUtils;
  33. import org.assertj.core.util.Files;
  34. import org.junit.Rule;
  35. import org.junit.Test;
  36. import org.junit.rules.ExpectedException;
  37. import org.junit.rules.TemporaryFolder;
  38. import static org.assertj.core.api.Assertions.assertThat;
  39. public class ZipUtilsTest {
  40. @Rule
  41. public TemporaryFolder temp = new TemporaryFolder();
  42. @Rule
  43. public ExpectedException expectedException = ExpectedException.none();
  44. @Test
  45. public void zip_directory() throws IOException {
  46. File foo = FileUtils.toFile(getClass().getResource("/org/sonar/api/utils/ZipUtilsTest/shouldZipDirectory/foo.txt"));
  47. File dir = foo.getParentFile();
  48. File zip = temp.newFile();
  49. ZipUtils.zipDir(dir, zip);
  50. assertThat(zip).exists().isFile();
  51. assertThat(zip.length()).isGreaterThan(1L);
  52. ArrayList<? extends ZipEntry> zipEntries = Collections.list(new ZipFile(zip).entries());
  53. assertThat(zipEntries).hasSize(4);
  54. File unzipDir = temp.newFolder();
  55. ZipUtils.unzip(zip, unzipDir);
  56. assertThat(new File(unzipDir, "bar.txt")).exists().isFile();
  57. assertThat(new File(unzipDir, "foo.txt")).exists().isFile();
  58. assertThat(new File(unzipDir, "dir1/hello.properties")).exists().isFile();
  59. }
  60. @Test
  61. public void unzipping_creates_target_directory_if_it_does_not_exist() throws IOException {
  62. File zip = FileUtils.toFile(urlToZip());
  63. File tempDir = temp.newFolder();
  64. Files.delete(tempDir);
  65. File subDir = new File(tempDir, "subDir");
  66. ZipUtils.unzip(zip, subDir);
  67. assertThat(subDir.list()).hasSize(3);
  68. }
  69. @Test
  70. public void unzip_file() throws IOException {
  71. File zip = FileUtils.toFile(urlToZip());
  72. File toDir = temp.newFolder();
  73. ZipUtils.unzip(zip, toDir);
  74. assertThat(toDir.list()).hasSize(3);
  75. }
  76. @Test
  77. public void unzip_stream() throws Exception {
  78. InputStream zip = urlToZip().openStream();
  79. File toDir = temp.newFolder();
  80. ZipUtils.unzip(zip, toDir);
  81. assertThat(toDir.list()).hasSize(3);
  82. }
  83. @Test
  84. public void unzipping_file_extracts_subset_of_files() throws IOException {
  85. File zip = FileUtils.toFile(urlToZip());
  86. File toDir = temp.newFolder();
  87. ZipUtils.unzip(zip, toDir, (ZipUtils.ZipEntryFilter)ze -> ze.getName().equals("foo.txt"));
  88. assertThat(toDir.listFiles()).containsOnly(new File(toDir, "foo.txt"));
  89. }
  90. @Test
  91. public void unzipping_stream_extracts_subset_of_files() throws IOException {
  92. InputStream zip = urlToZip().openStream();
  93. File toDir = temp.newFolder();
  94. ZipUtils.unzip(zip, toDir, (ZipUtils.ZipEntryFilter)ze -> ze.getName().equals("foo.txt"));
  95. assertThat(toDir.listFiles()).containsOnly(new File(toDir, "foo.txt"));
  96. }
  97. @Test
  98. public void fail_if_unzipping_file_outside_target_directory() throws Exception {
  99. File zip = new File(getClass().getResource("ZipUtilsTest/zip-slip.zip").toURI());
  100. File toDir = temp.newFolder();
  101. expectedException.expect(IllegalStateException.class);
  102. expectedException.expectMessage("Unzipping an entry outside the target directory is not allowed: ../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../tmp/evil.txt");
  103. ZipUtils.unzip(zip, toDir);
  104. }
  105. @Test
  106. public void fail_if_unzipping_stream_outside_target_directory() throws Exception {
  107. File zip = new File(getClass().getResource("ZipUtilsTest/zip-slip.zip").toURI());
  108. File toDir = temp.newFolder();
  109. expectedException.expect(IllegalStateException.class);
  110. expectedException.expectMessage("Unzipping an entry outside the target directory is not allowed: ../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../tmp/evil.txt");
  111. try (InputStream input = new FileInputStream(zip)) {
  112. ZipUtils.unzip(input, toDir);
  113. }
  114. }
  115. private URL urlToZip() {
  116. return getClass().getResource("/org/sonar/api/utils/ZipUtilsTest/shouldUnzipFile.zip");
  117. }
  118. }