1 package org.codehaus.plexus.archiver.zip;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.lang.reflect.Method;
6 import java.util.Arrays;
7 import java.util.HashSet;
8 import java.util.Set;
9
10 import org.codehaus.plexus.archiver.Archiver;
11 import org.codehaus.plexus.archiver.TestSupport;
12 import org.codehaus.plexus.archiver.UnArchiver;
13 import org.codehaus.plexus.components.io.fileselectors.FileInfo;
14 import org.codehaus.plexus.components.io.fileselectors.FileSelector;
15 import org.codehaus.plexus.components.io.fileselectors.IncludeExcludeFileSelector;
16 import org.codehaus.plexus.util.FileUtils;
17 import org.junit.jupiter.api.Test;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertNotNull;
21 import static org.junit.jupiter.api.Assertions.assertTrue;
22
23
24
25
26 class ZipUnArchiverTest extends TestSupport {
27
28 @Test
29 void testExtractingZipPreservesExecutableFlag() throws Exception {
30
31 String s = "target/zip-unarchiver-tests";
32 File testZip = new File(getBasedir(), "src/test/jars/test.zip");
33 File outputDirectory = new File(getBasedir(), s);
34
35 FileUtils.deleteDirectory(outputDirectory);
36
37 ZipUnArchiver zu = getZipUnArchiver(testZip);
38 zu.extract("", outputDirectory);
39 File testScript = new File(outputDirectory, "test.sh");
40
41 final Method canExecute;
42 try {
43 canExecute = File.class.getMethod("canExecute");
44 canExecute.invoke(testScript);
45 assertTrue((Boolean) canExecute.invoke(testScript));
46 } catch (NoSuchMethodException ignore) {
47 }
48 }
49
50 @Test
51 void testZeroFileModeInZip() throws Exception {
52
53 String s = "target/zip-unarchiver-filemode-tests";
54 File testZip = new File(getBasedir(), "src/test/resources/zeroFileMode/foobar.zip");
55 File outputDirectory = new File(getBasedir(), s);
56
57 FileUtils.deleteDirectory(outputDirectory);
58
59 ZipUnArchiver zu = getZipUnArchiver(testZip);
60 zu.setIgnorePermissions(false);
61 zu.extract("", outputDirectory);
62
63 File testScript = new File(outputDirectory, "foo.txt");
64
65 final Method canRead;
66 try {
67 canRead = File.class.getMethod("canRead");
68 canRead.invoke(testScript);
69 assertTrue((Boolean) canRead.invoke(testScript));
70 } catch (NoSuchMethodException ignore) {
71 }
72 }
73
74 @Test
75 void testUnarchiveUtf8() throws Exception {
76 File dest = new File("target/output/unzip/utf8");
77 dest.mkdirs();
78
79 final File zipFile = new File("target/output/unzip/utf8-default.zip");
80 final ZipArchiver zipArchiver = getZipArchiver(zipFile);
81 zipArchiver.addDirectory(new File("src/test/resources/miscUtf8"));
82 zipArchiver.createArchive();
83 final ZipUnArchiver unarchiver = getZipUnArchiver(zipFile);
84 unarchiver.setDestFile(dest);
85 unarchiver.extract();
86 assertTrue(new File(dest, "aPi\u00F1ata.txt").exists());
87 assertTrue(new File(dest, "an\u00FCmlaut.txt").exists());
88 assertTrue(new File(dest, "\u20acuro.txt").exists());
89 }
90
91 @Test
92 void testUnarchiveUnicodePathExtra() throws Exception {
93 File dest = new File("target/output/unzip/unicodePathExtra");
94 dest.mkdirs();
95 for (String name : dest.list()) {
96 new File(dest, name).delete();
97 }
98 assertEquals(0, dest.list().length);
99
100 final ZipUnArchiver unarchiver = getZipUnArchiver(new File("src/test/resources/unicodePathExtra/efsclear.zip"));
101 unarchiver.setDestFile(dest);
102 unarchiver.extract();
103
104 assertEquals(
105 new HashSet<>(Arrays.asList("nameonly-name", "goodextra-extra", "badextra-name")),
106 new HashSet<>(Arrays.asList(dest.list())),
107 "should use good extra fields but not bad ones");
108 }
109
110 @Test
111 void testUnarchiveUnicodePathExtraSelector() throws Exception {
112 File dest = new File("target/output/unzip/unicodePathExtraSelector");
113 dest.mkdirs();
114 for (String name : dest.list()) {
115 new File(dest, name).delete();
116 }
117 assertEquals(0, dest.list().length);
118
119 class CollectingSelector implements FileSelector {
120 public Set<String> collection = new HashSet<>();
121
122 @Override
123 public boolean isSelected(FileInfo fileInfo) throws IOException {
124 collection.add(fileInfo.getName());
125 return false;
126 }
127 }
128 CollectingSelector selector = new CollectingSelector();
129
130 final ZipUnArchiver unarchiver = getZipUnArchiver(new File("src/test/resources/unicodePathExtra/efsclear.zip"));
131 unarchiver.setDestFile(dest);
132 unarchiver.setFileSelectors(new FileSelector[] {selector});
133 unarchiver.extract();
134
135 assertEquals(0, dest.list().length, "should not extract anything");
136
137 assertEquals(
138 new HashSet<>(Arrays.asList("nameonly-name", "goodextra-extra", "badextra-name")),
139 selector.collection,
140 "should use good extra fields but not bad ones");
141 }
142
143 private void runUnarchiver(String path, FileSelector[] selectors, boolean[] results) throws Exception {
144 String s = "target/zip-unarchiver-tests";
145
146 File testJar = new File(getBasedir(), "src/test/jars/test.jar");
147
148 File outputDirectory = new File(getBasedir(), s);
149
150 ZipUnArchiver zu = getZipUnArchiver(testJar);
151 zu.setFileSelectors(selectors);
152
153 FileUtils.deleteDirectory(outputDirectory);
154
155 zu.extract(path, outputDirectory);
156
157 File f0 = new File(getBasedir(), s + "/resources/artifactId/test.properties");
158
159 assertEquals(results[0], f0.exists());
160
161 File f1 = new File(getBasedir(), s + "/resources/artifactId/directory/test.properties");
162
163 assertEquals(results[1], f1.exists());
164
165 File f2 = new File(getBasedir(), s + "/META-INF/MANIFEST.MF");
166
167 assertEquals(results[2], f2.exists());
168 }
169
170 private ZipUnArchiver getZipUnArchiver(File testJar) throws Exception {
171 ZipUnArchiver zu = (ZipUnArchiver) lookup(UnArchiver.class, "zip");
172 zu.setSourceFile(testJar);
173 return zu;
174 }
175
176 @Test
177 void testExtractingADirectoryFromAJarFile() throws Exception {
178 runUnarchiver("resources/artifactId", null, new boolean[] {true, true, false});
179 runUnarchiver("", null, new boolean[] {true, true, true});
180 }
181
182 @Test
183 void testSelectors() throws Exception {
184 IncludeExcludeFileSelector fileSelector = new IncludeExcludeFileSelector();
185 runUnarchiver("", new FileSelector[] {fileSelector}, new boolean[] {true, true, true});
186 fileSelector.setExcludes(new String[] {"**/test.properties"});
187 runUnarchiver("", new FileSelector[] {fileSelector}, new boolean[] {false, false, true});
188 fileSelector.setIncludes(new String[] {"**/test.properties"});
189 fileSelector.setExcludes(null);
190 runUnarchiver("", new FileSelector[] {fileSelector}, new boolean[] {true, true, false});
191 fileSelector.setExcludes(new String[] {"resources/artifactId/directory/test.properties"});
192 runUnarchiver("", new FileSelector[] {fileSelector}, new boolean[] {true, false, false});
193 }
194
195 @Test
196 void testExtractingZipWithEntryOutsideDestDirThrowsException() throws Exception {
197 Exception ex = null;
198 String s = "target/zip-unarchiver-slip-tests";
199 File testZip = new File(getBasedir(), "src/test/zips/zip-slip.zip");
200 File outputDirectory = new File(getBasedir(), s);
201
202 FileUtils.deleteDirectory(outputDirectory);
203
204 try {
205 ZipUnArchiver zu = getZipUnArchiver(testZip);
206 zu.extract("", outputDirectory);
207 } catch (Exception e) {
208 ex = e;
209 }
210
211 assertNotNull(ex);
212 assertTrue(ex.getMessage().startsWith("Entry is outside of the target directory"));
213 }
214
215 @Test
216 void testZipOutputSizeException() throws Exception {
217 Exception ex = null;
218 String s = "target/zip-size-tests";
219 File testZip = new File(getBasedir(), "src/test/jars/test.zip");
220 File outputDirectory = new File(getBasedir(), s);
221
222 FileUtils.deleteDirectory(outputDirectory);
223
224 try {
225 ZipUnArchiver zu = getZipUnArchiver(testZip);
226 zu.setMaxOutputSize(10L);
227 zu.extract("", outputDirectory);
228 } catch (Exception e) {
229 ex = e;
230 }
231
232 assertNotNull(ex);
233 assertTrue(ex.getMessage().startsWith("Maximum output size limit reached"));
234 }
235
236 @Test
237 void testZipMaxOutputSizeEqualToExtractedFileSize() throws Exception {
238 long extractedFileSize = 11L;
239 String s = "target/zip-size-tests";
240 File testZip = new File(getBasedir(), "src/test/jars/test.zip");
241 File outputDirectory = new File(getBasedir(), s);
242
243 FileUtils.deleteDirectory(outputDirectory);
244
245 ZipUnArchiver zu = getZipUnArchiver(testZip);
246 zu.setMaxOutputSize(extractedFileSize);
247 zu.extract("", outputDirectory);
248
249 File extractedFile = new File(outputDirectory, "test.sh");
250 assertEquals(extractedFileSize, extractedFile.length());
251 }
252
253 private ZipArchiver getZipArchiver() {
254 try {
255 return (ZipArchiver) lookup(Archiver.class, "zip");
256 } catch (Exception e) {
257 throw new RuntimeException(e);
258 }
259 }
260
261 private ZipArchiver getZipArchiver(File destFile) {
262 final ZipArchiver zipArchiver = getZipArchiver();
263 zipArchiver.setDestFile(destFile);
264 return zipArchiver;
265 }
266 }