1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.archivers.examples;
20
21 import static java.nio.charset.StandardCharsets.UTF_8;
22 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
23 import static org.junit.jupiter.api.Assertions.assertFalse;
24 import static org.junit.jupiter.api.Assertions.assertThrows;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
26 import static org.junit.jupiter.api.Assumptions.assumeFalse;
27 import static org.junit.jupiter.api.Assumptions.assumeTrue;
28
29 import java.io.BufferedInputStream;
30 import java.io.File;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.OutputStream;
34 import java.nio.channels.FileChannel;
35 import java.nio.channels.SeekableByteChannel;
36 import java.nio.file.Files;
37 import java.nio.file.StandardOpenOption;
38
39 import org.apache.commons.compress.AbstractTest;
40 import org.apache.commons.compress.archivers.ArchiveEntry;
41 import org.apache.commons.compress.archivers.ArchiveException;
42 import org.apache.commons.compress.archivers.ArchiveOutputStream;
43 import org.apache.commons.compress.archivers.ArchiveStreamFactory;
44 import org.apache.commons.compress.archivers.StreamingNotSupportedException;
45 import org.apache.commons.compress.archivers.sevenz.SevenZFile;
46 import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;
47 import org.apache.commons.compress.archivers.tar.TarFile;
48 import org.apache.commons.compress.archivers.zip.ZipFile;
49 import org.junit.jupiter.api.Test;
50
51 public class ExpanderTest extends AbstractTest {
52
53 private File archive;
54
55 private void assertHelloWorld(final String fileName, final String suffix) throws IOException {
56 assertTrue(new File(tempResultDir, fileName).isFile(), fileName + " does not exist");
57 final byte[] expected = ("Hello, world " + suffix).getBytes(UTF_8);
58 final byte[] actual = Files.readAllBytes(tempResultDir.toPath().resolve(fileName));
59 assertArrayEquals(expected, actual);
60 }
61
62 private void setup7z() throws IOException {
63 archive = newTempFile("test.7z");
64 final File dummy = newTempFile("x");
65 try (OutputStream o = Files.newOutputStream(dummy.toPath())) {
66 o.write(new byte[14]);
67 }
68 try (SevenZOutputFile aos = new SevenZOutputFile(archive)) {
69 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "a"));
70 aos.closeArchiveEntry();
71 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "a/b"));
72 aos.closeArchiveEntry();
73 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "a/b/c"));
74 aos.closeArchiveEntry();
75 aos.putArchiveEntry(aos.createArchiveEntry(dummy, "a/b/d.txt"));
76 aos.write("Hello, world 1".getBytes(UTF_8));
77 aos.closeArchiveEntry();
78 aos.putArchiveEntry(aos.createArchiveEntry(dummy, "a/b/c/e.txt"));
79 aos.write("Hello, world 2".getBytes(UTF_8));
80 aos.closeArchiveEntry();
81 aos.finish();
82 }
83 }
84
85 private void setupTar() throws IOException, ArchiveException {
86 archive = newTempFile("test.tar");
87 final File dummy = newTempFile("x");
88 try (OutputStream o = Files.newOutputStream(dummy.toPath())) {
89 o.write(new byte[14]);
90 }
91 try (@SuppressWarnings("resource")
92 ArchiveOutputStream<ArchiveEntry> aos = ArchiveStreamFactory.DEFAULT.createArchiveOutputStream("tar", Files.newOutputStream(archive.toPath()))) {
93 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "a"));
94 aos.closeArchiveEntry();
95 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "a/b"));
96 aos.closeArchiveEntry();
97 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "a/b/c"));
98 aos.closeArchiveEntry();
99 aos.putArchiveEntry(aos.createArchiveEntry(dummy, "a/b/d.txt"));
100 aos.write("Hello, world 1".getBytes(UTF_8));
101 aos.closeArchiveEntry();
102 aos.putArchiveEntry(aos.createArchiveEntry(dummy, "a/b/c/e.txt"));
103 aos.write("Hello, world 2".getBytes(UTF_8));
104 aos.closeArchiveEntry();
105 aos.finish();
106 }
107 }
108
109 private void setupTarForCompress603() throws IOException, ArchiveException {
110 archive = newTempFile("test.tar");
111 final File dummy = newTempFile("x");
112 try (OutputStream o = Files.newOutputStream(dummy.toPath())) {
113 o.write(new byte[14]);
114 }
115 try (@SuppressWarnings("resource")
116 ArchiveOutputStream<ArchiveEntry> aos = ArchiveStreamFactory.DEFAULT.createArchiveOutputStream("tar", Files.newOutputStream(archive.toPath()))) {
117 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "./"));
118 aos.closeArchiveEntry();
119 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "./a"));
120 aos.closeArchiveEntry();
121 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "./a/b"));
122 aos.closeArchiveEntry();
123 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "./a/b/c"));
124 aos.closeArchiveEntry();
125 aos.putArchiveEntry(aos.createArchiveEntry(dummy, "./a/b/d.txt"));
126 aos.write("Hello, world 1".getBytes(UTF_8));
127 aos.closeArchiveEntry();
128 aos.putArchiveEntry(aos.createArchiveEntry(dummy, "./a/b/c/e.txt"));
129 aos.write("Hello, world 2".getBytes(UTF_8));
130 aos.closeArchiveEntry();
131 aos.finish();
132 }
133 }
134
135 private void setupZip() throws IOException, ArchiveException {
136 archive = newTempFile("test.zip");
137 final File dummy = newTempFile("x");
138 try (OutputStream o = Files.newOutputStream(dummy.toPath())) {
139 o.write(new byte[14]);
140 }
141 try (@SuppressWarnings("resource")
142 ArchiveOutputStream<ArchiveEntry> aos = ArchiveStreamFactory.DEFAULT.createArchiveOutputStream("zip", Files.newOutputStream(archive.toPath()))) {
143 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "a"));
144 aos.closeArchiveEntry();
145 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "a/b"));
146 aos.closeArchiveEntry();
147 aos.putArchiveEntry(aos.createArchiveEntry(getTempDirFile(), "a/b/c"));
148 aos.closeArchiveEntry();
149 aos.putArchiveEntry(aos.createArchiveEntry(dummy, "a/b/d.txt"));
150 aos.write("Hello, world 1".getBytes(UTF_8));
151 aos.closeArchiveEntry();
152 aos.putArchiveEntry(aos.createArchiveEntry(dummy, "a/b/c/e.txt"));
153 aos.write("Hello, world 2".getBytes(UTF_8));
154 aos.closeArchiveEntry();
155 aos.finish();
156 }
157 }
158
159 private void setupZip(final String entry) throws IOException, ArchiveException {
160 archive = newTempFile("test.zip");
161 final File dummy = newTempFile("x");
162 try (OutputStream o = Files.newOutputStream(dummy.toPath())) {
163 o.write(new byte[14]);
164 }
165 try (@SuppressWarnings("resource")
166 ArchiveOutputStream<ArchiveEntry> aos = ArchiveStreamFactory.DEFAULT.createArchiveOutputStream("zip", Files.newOutputStream(archive.toPath()))) {
167 aos.putArchiveEntry(aos.createArchiveEntry(dummy, entry));
168 aos.write("Hello, world 1".getBytes(UTF_8));
169 aos.closeArchiveEntry();
170 aos.finish();
171 }
172 }
173
174 @Test
175 public void testCompress603Tar() throws IOException, ArchiveException {
176 setupTarForCompress603();
177 try (TarFile f = new TarFile(archive)) {
178 new Expander().expand(f, tempResultDir);
179 }
180 verifyTargetDir();
181 }
182
183 @Test
184 public void testFileCantEscapeDoubleDotPath() throws IOException, ArchiveException {
185 setupZip("../foo");
186 try (ZipFile f = ZipFile.builder().setFile(archive).get()) {
187 assertThrows(IOException.class, () -> new Expander().expand(f, tempResultDir));
188 }
189 }
190
191 @Test
192 public void testFileCantEscapeDoubleDotPathWithSimilarSibling() throws IOException, ArchiveException {
193 final String sibling = tempResultDir.getName() + "x";
194 final File s = new File(tempResultDir.getParentFile(), sibling);
195 assumeFalse(s.exists());
196 s.mkdirs();
197 assumeTrue(s.exists());
198 setupZip("../" + sibling + "/a");
199 try (ZipFile f = ZipFile.builder().setFile(archive).get()) {
200 assertThrows(IOException.class, () -> new Expander().expand(f, tempResultDir));
201 }
202 }
203
204 @Test
205 public void testFileCantEscapeViaAbsolutePath() throws IOException, ArchiveException {
206 setupZip("/tmp/foo");
207 try (ZipFile f = ZipFile.builder().setFile(archive).get()) {
208 assertThrows(IOException.class, () -> new Expander().expand(f, tempResultDir));
209 }
210 assertFalse(new File(tempResultDir, "tmp/foo").isFile());
211 }
212
213 @Test
214 public void testSevenZChannelVersion() throws IOException, ArchiveException {
215 setup7z();
216 try (SeekableByteChannel c = FileChannel.open(archive.toPath(), StandardOpenOption.READ)) {
217 new Expander().expand("7z", c, tempResultDir);
218 }
219 verifyTargetDir();
220 }
221
222 @Test
223 public void testSevenZFileVersion() throws IOException {
224 setup7z();
225 try (SevenZFile file = SevenZFile.builder().setFile(archive).get()) {
226 new Expander().expand(file, tempResultDir);
227 }
228 verifyTargetDir();
229 }
230
231 @Test
232 public void testSevenZInputStreamVersion() throws IOException {
233 setup7z();
234 try (InputStream i = new BufferedInputStream(Files.newInputStream(archive.toPath()))) {
235 assertThrows(StreamingNotSupportedException.class, () -> new Expander().expand("7z", i, tempResultDir));
236 }
237 }
238
239 @Test
240 public void testSevenZInputStreamVersionWithAutoDetection() throws IOException {
241 setup7z();
242 try (InputStream i = new BufferedInputStream(Files.newInputStream(archive.toPath()))) {
243 assertThrows(StreamingNotSupportedException.class, () -> new Expander().expand(i, tempResultDir));
244 }
245 }
246
247 @Test
248 public void testSevenZTwoFileVersion() throws IOException, ArchiveException {
249 setup7z();
250 new Expander().expand("7z", archive, tempResultDir);
251 verifyTargetDir();
252 }
253
254 @Test
255 public void testSevenZTwoFileVersionWithAutoDetection() throws IOException, ArchiveException {
256 setup7z();
257 new Expander().expand(archive, tempResultDir);
258 verifyTargetDir();
259 }
260
261 @Test
262 public void testTarFileVersion() throws IOException, ArchiveException {
263 setupTar();
264 try (TarFile f = new TarFile(archive)) {
265 new Expander().expand(f, tempResultDir);
266 }
267 verifyTargetDir();
268 }
269
270 @Test
271 public void testZipFileVersion() throws IOException, ArchiveException {
272 setupZip();
273 try (ZipFile f = ZipFile.builder().setFile(archive).get()) {
274 new Expander().expand(f, tempResultDir);
275 }
276 verifyTargetDir();
277 }
278
279 private void verifyTargetDir() throws IOException {
280 assertTrue(new File(tempResultDir, "a").isDirectory(), "a has not been created");
281 assertTrue(new File(tempResultDir, "a/b").isDirectory(), "a/b has not been created");
282 assertTrue(new File(tempResultDir, "a/b/c").isDirectory(), "a/b/c has not been created");
283 assertHelloWorld("a/b/d.txt", "1");
284 assertHelloWorld("a/b/c/e.txt", "2");
285 }
286
287 }