1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.codehaus.plexus.archiver.zip;
25
26 import javax.annotation.Nonnull;
27
28 import java.io.ByteArrayInputStream;
29 import java.io.ByteArrayOutputStream;
30 import java.io.File;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.Writer;
34 import java.nio.charset.StandardCharsets;
35 import java.nio.file.Files;
36 import java.nio.file.Path;
37 import java.nio.file.attribute.FileTime;
38 import java.text.DateFormat;
39 import java.text.ParseException;
40 import java.text.SimpleDateFormat;
41 import java.util.Arrays;
42 import java.util.Date;
43 import java.util.Enumeration;
44 import java.util.Map;
45 import java.util.TimeZone;
46 import java.util.zip.ZipEntry;
47 import java.util.zip.ZipInputStream;
48 import java.util.zip.ZipOutputStream;
49
50 import org.apache.commons.compress.archivers.zip.ExtraFieldUtils;
51 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
52 import org.apache.commons.compress.archivers.zip.ZipExtraField;
53 import org.apache.commons.compress.archivers.zip.ZipFile;
54 import org.apache.commons.io.input.BoundedInputStream;
55 import org.codehaus.plexus.archiver.ArchiveEntry;
56 import org.codehaus.plexus.archiver.Archiver;
57 import org.codehaus.plexus.archiver.ArchiverException;
58 import org.codehaus.plexus.archiver.BasePlexusArchiverTest;
59 import org.codehaus.plexus.archiver.UnArchiver;
60 import org.codehaus.plexus.archiver.UnixStat;
61 import org.codehaus.plexus.archiver.exceptions.EmptyArchiveException;
62 import org.codehaus.plexus.archiver.tar.TarArchiver;
63 import org.codehaus.plexus.archiver.tar.TarFile;
64 import org.codehaus.plexus.archiver.util.ArchiveEntryUtils;
65 import org.codehaus.plexus.archiver.util.DefaultArchivedFileSet;
66 import org.codehaus.plexus.archiver.util.DefaultFileSet;
67 import org.codehaus.plexus.archiver.util.Streams;
68 import org.codehaus.plexus.components.io.attributes.FileAttributes;
69 import org.codehaus.plexus.components.io.attributes.PlexusIoResourceAttributeUtils;
70 import org.codehaus.plexus.components.io.attributes.PlexusIoResourceAttributes;
71 import org.codehaus.plexus.components.io.attributes.SimpleResourceAttributes;
72 import org.codehaus.plexus.components.io.filemappers.FileMapper;
73 import org.codehaus.plexus.components.io.filemappers.PrefixFileMapper;
74 import org.codehaus.plexus.components.io.functions.InputStreamTransformer;
75 import org.codehaus.plexus.components.io.resources.PlexusIoFileResourceCollection;
76 import org.codehaus.plexus.components.io.resources.PlexusIoResource;
77 import org.codehaus.plexus.components.io.resources.ResourceFactory;
78 import org.codehaus.plexus.util.FileUtils;
79 import org.codehaus.plexus.util.IOUtil;
80 import org.junit.jupiter.api.Disabled;
81 import org.junit.jupiter.api.Test;
82 import org.junit.jupiter.api.condition.DisabledOnOs;
83 import org.junit.jupiter.api.condition.OS;
84 import org.junit.jupiter.api.io.TempDir;
85
86 import static org.junit.jupiter.api.Assertions.assertEquals;
87 import static org.junit.jupiter.api.Assertions.assertFalse;
88 import static org.junit.jupiter.api.Assertions.assertNotNull;
89 import static org.junit.jupiter.api.Assertions.assertThrows;
90 import static org.junit.jupiter.api.Assertions.assertTrue;
91 import static org.junit.jupiter.api.Assertions.fail;
92
93
94
95
96 @SuppressWarnings("OctalInteger")
97 class ZipArchiverTest extends BasePlexusArchiverTest {
98
99 @TempDir
100 private File tempDir;
101
102 @Test
103 void testImplicitPermissions() throws IOException {
104 File zipFile = getTestFile("target/output/zip-with-implicit-dirmode.zip");
105
106 ZipArchiver archiver = getZipArchiver(zipFile);
107
108 archiver.setDefaultDirectoryMode(0777);
109 archiver.setDirectoryMode(0641);
110 archiver.setFileMode(0222);
111 archiver.addFile(new File("pom.xml"), "fizz/buzz/pom.xml");
112 archiver.setDefaultDirectoryMode(0530);
113 archiver.setDirectoryMode(-1);
114 archiver.setFileMode(0111);
115 archiver.addFile(new File("pom.xml"), "fazz/bazz/pam.xml");
116 archiver.createArchive();
117
118 assertTrue(zipFile.exists());
119 ZipFile zf = ZipFile.builder().setFile(zipFile).get();
120 ZipArchiveEntry fizz = zf.getEntry("fizz/");
121 assertEquals(040641, fizz.getUnixMode());
122 ZipArchiveEntry pom = zf.getEntry("fizz/buzz/pom.xml");
123 assertEquals(0100222, pom.getUnixMode());
124
125 ZipArchiveEntry fazz = zf.getEntry("fazz/");
126 assertEquals(040530, fazz.getUnixMode());
127 ZipArchiveEntry pam = zf.getEntry("fazz/bazz/pam.xml");
128 assertEquals(0100111, pam.getUnixMode());
129 }
130
131 @Test
132 @DisabledOnOs(OS.WINDOWS)
133 void testOveriddenPermissions() throws IOException {
134 File zipFile = getTestFile("target/output/zip-with-overriden-modes.zip");
135
136 ZipArchiver archiver = getZipArchiver(zipFile);
137 archiver.setDefaultDirectoryMode(0777);
138 archiver.setDirectoryMode(0641);
139 archiver.setFileMode(0777);
140 archiver.addDirectory(new File("src/test/resources/symlinks/src"));
141 archiver.createArchive();
142
143 assertTrue(zipFile.exists());
144 ZipFile zf = ZipFile.builder().setFile(zipFile).get();
145 ZipArchiveEntry fizz = zf.getEntry("symDir");
146 assertTrue(fizz.isUnixSymlink());
147 ZipArchiveEntry symR = zf.getEntry("symR");
148 assertTrue(symR.isUnixSymlink());
149 }
150
151 @Test
152 @DisabledOnOs(OS.WINDOWS)
153 void testCreateArchiveWithDetectedModes() throws Exception {
154
155 String[] executablePaths = {"path/to/executable", "path/to/executable.bat"};
156
157 String[] confPaths = {"path/to/etc/file", "path/to/etc/file2"};
158
159 String[] logPaths = {"path/to/logs/log.txt"};
160
161 int exeMode = 0777;
162 int confMode = 0600;
163 int logMode = 0640;
164
165 for (String executablePath : executablePaths) {
166 writeFile(tempDir, executablePath, exeMode);
167 }
168
169 for (String confPath : confPaths) {
170 writeFile(tempDir, confPath, confMode);
171 }
172
173 for (String logPath : logPaths) {
174 writeFile(tempDir, logPath, logMode);
175 }
176
177 {
178 Map<String, PlexusIoResourceAttributes> attributesByPath =
179 PlexusIoResourceAttributeUtils.getFileAttributesByPath(tempDir);
180 for (String path : executablePaths) {
181 PlexusIoResourceAttributes attrs = attributesByPath.get(path);
182 if (attrs == null) {
183 attrs = attributesByPath.get(new File(tempDir, path).getAbsolutePath());
184 }
185
186 assertNotNull(attrs);
187 assertEquals(exeMode, attrs.getOctalMode(), "Wrong mode for: " + path);
188 }
189
190 for (String path : confPaths) {
191 PlexusIoResourceAttributes attrs = attributesByPath.get(path);
192 if (attrs == null) {
193 attrs = attributesByPath.get(new File(tempDir, path).getAbsolutePath());
194 }
195
196 assertNotNull(attrs);
197 assertEquals(confMode, attrs.getOctalMode(), "Wrong mode for: " + path);
198 }
199
200 for (String path : logPaths) {
201 PlexusIoResourceAttributes attrs = attributesByPath.get(path);
202 if (attrs == null) {
203 attrs = attributesByPath.get(new File(tempDir, path).getAbsolutePath());
204 }
205
206 assertNotNull(attrs);
207 assertEquals(logMode, attrs.getOctalMode(), "Wrong mode for: " + path);
208 }
209 }
210
211 File zipFile = getTestFile("target/output/zip-with-modes.zip");
212
213 ZipArchiver archiver = getZipArchiver(zipFile);
214
215 archiver.addDirectory(tempDir);
216 archiver.createArchive();
217
218 assertTrue(zipFile.exists());
219
220 File zipFile2 = getTestFile("target/output/zip-with-modes-L2.zip");
221
222 archiver = getZipArchiver();
223 archiver.setDestFile(zipFile2);
224
225 archiver.addArchivedFileSet(zipFile);
226 archiver.createArchive();
227
228 ZipFile zf = ZipFile.builder().setFile(zipFile2).get();
229
230 for (String path : executablePaths) {
231 ZipArchiveEntry ze = zf.getEntry(path);
232
233 int mode = ze.getUnixMode() & UnixStat.PERM_MASK;
234
235 assertEquals(exeMode, mode, "Wrong mode for: " + path);
236 }
237
238 for (String path : confPaths) {
239 ZipArchiveEntry ze = zf.getEntry(path);
240
241 int mode = ze.getUnixMode() & UnixStat.PERM_MASK;
242
243 assertEquals(confMode, mode, "Wrong mode for: " + path);
244 }
245
246 for (String path : logPaths) {
247 ZipArchiveEntry ze = zf.getEntry(path);
248
249 int mode = ze.getUnixMode() & UnixStat.PERM_MASK;
250
251 assertEquals(logMode, mode, "Wrong mode for: " + path);
252 }
253 }
254
255 @Test
256 void testCreateEmptyArchive() throws Exception {
257 ZipArchiver archiver = getZipArchiver();
258 archiver.setDestFile(getTestFile("target/output/empty.zip"));
259 try {
260 archiver.createArchive();
261
262 fail("Creating empty archive should throw EmptyArchiveException");
263 } catch (EmptyArchiveException ignore) {
264 }
265 }
266
267 private ZipArchiver getZipArchiver() {
268 try {
269 return (ZipArchiver) lookup(Archiver.class, "zip");
270 } catch (Exception e) {
271 throw new RuntimeException(e);
272 }
273 }
274
275 private ZipArchiver getZipArchiver(File destFile) {
276 final ZipArchiver zipArchiver = getZipArchiver();
277 zipArchiver.setDestFile(destFile);
278 return zipArchiver;
279 }
280
281 private ZipUnArchiver getZipUnArchiver(File testJar) {
282 ZipUnArchiver zu = (ZipUnArchiver) lookup(UnArchiver.class, "zip");
283 zu.setSourceFile(testJar);
284 return zu;
285 }
286
287 private void writeFile(File dir, String fname, int mode) throws IOException, ArchiverException {
288 File file = new File(dir, fname);
289
290 if (file.getParentFile() != null) {
291 file.getParentFile().mkdirs();
292 }
293
294 try (Writer writer = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) {
295 writer.write("This is a test file.");
296 }
297
298 ArchiveEntryUtils.chmod(file, mode);
299 }
300
301 @Test
302 void testCreateArchive() throws Exception {
303 ZipArchiver archiver = newArchiver("archive1.zip");
304
305 createArchive(archiver);
306 }
307
308 @Test
309 void testRecompressAddedZips() throws Exception {
310
311
312 final File zipFileRecompress = getTestFile("target/output/recompress-added-zips.zip");
313 final ZipArchiver zipArchiverRecompress = getZipArchiver(zipFileRecompress);
314 zipArchiverRecompress.addDirectory(getTestFile("src/test/jars"));
315 FileUtils.removePath(zipFileRecompress.getPath());
316 zipArchiverRecompress.createArchive();
317
318 final ZipFile zfRecompress =
319 ZipFile.builder().setFile(zipFileRecompress).get();
320 assertEquals(ZipEntry.DEFLATED, zfRecompress.getEntry("test.zip").getMethod());
321 assertEquals(ZipEntry.DEFLATED, zfRecompress.getEntry("test.jar").getMethod());
322 assertEquals(ZipEntry.DEFLATED, zfRecompress.getEntry("test.rar").getMethod());
323 assertEquals(ZipEntry.DEFLATED, zfRecompress.getEntry("test.tar.gz").getMethod());
324 zfRecompress.close();
325
326
327
328 final File zipFileDontRecompress = getTestFile("target/output/dont-recompress-added-zips.zip");
329 ZipArchiver zipArchiver = getZipArchiver(zipFileDontRecompress);
330 zipArchiver.addDirectory(getTestFile("src/test/jars"));
331 zipArchiver.setRecompressAddedZips(false);
332 FileUtils.removePath(zipFileDontRecompress.getPath());
333 zipArchiver.createArchive();
334
335 final ZipFile zfDontRecompress =
336 ZipFile.builder().setFile(zipFileDontRecompress).get();
337 final ZipArchiveEntry zipEntry = zfDontRecompress.getEntry("test.zip");
338 final ZipArchiveEntry jarEntry = zfDontRecompress.getEntry("test.jar");
339 final ZipArchiveEntry rarEntry = zfDontRecompress.getEntry("test.rar");
340 final ZipArchiveEntry tarEntry = zfDontRecompress.getEntry("test.tar.gz");
341
342 assertEquals(ZipEntry.STORED, zipEntry.getMethod());
343 assertEquals(ZipEntry.STORED, jarEntry.getMethod());
344 assertEquals(ZipEntry.STORED, rarEntry.getMethod());
345 assertEquals(ZipEntry.DEFLATED, tarEntry.getMethod());
346
347 assertTrue(IOUtil.contentEquals(
348 Files.newInputStream(getTestFile("src/test/jars/test.zip").toPath()),
349 zfDontRecompress.getInputStream(zipEntry)));
350 assertTrue(IOUtil.contentEquals(
351 Files.newInputStream(getTestFile("src/test/jars/test.jar").toPath()),
352 zfDontRecompress.getInputStream(jarEntry)));
353 assertTrue(IOUtil.contentEquals(
354 Files.newInputStream(getTestFile("src/test/jars/test.rar").toPath()),
355 zfDontRecompress.getInputStream(rarEntry)));
356 assertTrue(IOUtil.contentEquals(
357 Files.newInputStream(getTestFile("src/test/jars/test.tar.gz").toPath()),
358 zfDontRecompress.getInputStream(tarEntry)));
359 zfDontRecompress.close();
360 }
361
362 @Test
363 void testAddArchivedFileSet() throws Exception {
364 File toBeAdded = new File("src/test/resources/test.zip");
365 DefaultArchivedFileSet sfd = DefaultArchivedFileSet.archivedFileSet(toBeAdded);
366 File zipFIle = getTestFile("target/output/withZip.zip");
367 final ZipArchiver zipArchiver = getZipArchiver(zipFIle);
368 InputStreamTransformer is = new InputStreamTransformer() {
369
370 @Nonnull
371 public InputStream transform(@Nonnull PlexusIoResource resource, @Nonnull InputStream inputStream)
372 throws IOException {
373 return BoundedInputStream.builder()
374 .setInputStream(inputStream)
375 .setMaxCount(3)
376 .get();
377 }
378 };
379 sfd.setStreamTransformer(is);
380 PrefixFileMapper mapper = new PrefixFileMapper();
381 mapper.setPrefix("prefix");
382 sfd.setFileMappers(new FileMapper[] {mapper});
383 zipArchiver.addArchivedFileSet(sfd);
384 zipArchiver.createArchive();
385
386 final ZipUnArchiver zipUnArchiver = getZipUnArchiver(zipFIle);
387 File destFile = new File("target/output/withZip");
388 destFile.mkdirs();
389 zipUnArchiver.setDestFile(destFile);
390 zipUnArchiver.extract();
391 File a3byteFile = new File(
392 destFile,
393 "prefixUsers/kristian/lsrc/plexus/plexus-archiver/src/main/java/org/codehaus/plexus/archiver/zip/ZipArchiver.java");
394 assertTrue(a3byteFile.exists());
395 assertEquals(3, a3byteFile.length());
396 }
397
398 @Test
399 void testCreateArchiveWithStreamTransformer() throws IOException {
400 InputStreamTransformer is = new InputStreamTransformer() {
401
402 @Nonnull
403 @Override
404 public InputStream transform(@Nonnull PlexusIoResource resource, @Nonnull InputStream inputStream)
405 throws IOException {
406 return BoundedInputStream.builder()
407 .setInputStream(inputStream)
408 .setBufferSizeMax(3)
409 .get();
410 }
411 };
412
413 final ZipArchiver zipArchiver = getZipArchiver(getTestFile("target/output/all3bytes.zip"));
414 File zipFIle = new File("src/test/resources/test.zip");
415 DefaultArchivedFileSet afs = new DefaultArchivedFileSet(zipFIle);
416 afs.setStreamTransformer(is);
417 afs.setPrefix("azip/");
418 zipArchiver.addArchivedFileSet(afs);
419
420 DefaultFileSet dfs = new DefaultFileSet(new File("src/test/resources/mjar179"));
421 dfs.setStreamTransformer(is);
422 dfs.setPrefix("mj179/");
423 zipArchiver.addFileSet(dfs);
424
425 PlexusIoFileResourceCollection files = new PlexusIoFileResourceCollection();
426 files.setBaseDir(new File("src/test/resources"));
427 files.setStreamTransformer(is);
428 files.setPrefix("plexus/");
429 zipArchiver.addResources(files);
430
431 zipArchiver.createArchive();
432 }
433
434 private ZipArchiver newArchiver(String name) {
435 ZipArchiver archiver = getZipArchiver(getTestFile("target/output/" + name));
436
437 archiver.setFileMode(0640);
438 archiver.addFile(getTestFile("src/test/resources/manifests/manifest1.mf"), "one.txt");
439 archiver.addFile(getTestFile("src/test/resources/manifests/manifest2.mf"), "two.txt", 0664);
440
441
442 archiver.setFileMode(0400);
443 archiver.setDirectoryMode(0777);
444 archiver.addDirectory(getTestFile("src/test/resources/world-writable/"), "worldwritable/");
445
446 archiver.setDirectoryMode(0070);
447 archiver.addDirectory(getTestFile("src/test/resources/group-writable/"), "groupwritable/");
448
449 archiver.setDirectoryMode(0500);
450 archiver.setFileMode(0400);
451 archiver.addDirectory(getTestFile("src"));
452
453 return archiver;
454 }
455
456 private void fileModeAssert(int expected, int actual) {
457 assertEquals(Integer.toString(expected, 8), Integer.toString(actual, 8));
458 }
459
460 private void createArchive(ZipArchiver archiver) throws ArchiverException, IOException {
461 archiver.createArchive();
462
463 ZipFile zf = ZipFile.builder().setFile(archiver.getDestFile()).get();
464
465 Enumeration<ZipArchiveEntry> e = zf.getEntries();
466
467 while (e.hasMoreElements()) {
468 ZipArchiveEntry ze = e.nextElement();
469 if (ze.isDirectory()) {
470 if (ze.getName().startsWith("worldwritable")) {
471 fileModeAssert(0777, UnixStat.PERM_MASK & ze.getUnixMode());
472 } else if (ze.getName().startsWith("groupwritable")) {
473 fileModeAssert(0070, UnixStat.PERM_MASK & ze.getUnixMode());
474 } else {
475 fileModeAssert(0500, UnixStat.PERM_MASK & ze.getUnixMode());
476 }
477 } else {
478 if (ze.getName().equals("one.txt")) {
479 fileModeAssert(0640, UnixStat.PERM_MASK & ze.getUnixMode());
480 } else if (ze.getName().equals("two.txt")) {
481 fileModeAssert(0664, UnixStat.PERM_MASK & ze.getUnixMode());
482 } else if (ze.isUnixSymlink()) {
483
484 } else {
485 fileModeAssert(0400, UnixStat.PERM_MASK & ze.getUnixMode());
486 }
487 }
488 }
489 }
490
491 @Test
492 @DisabledOnOs(OS.WINDOWS)
493 void testSymlinkZip() throws Exception {
494 final File zipFile = getTestFile("target/output/pasymlinks.zip");
495 final ZipArchiver zipArchiver = getZipArchiver(zipFile);
496 PlexusIoFileResourceCollection files = new PlexusIoFileResourceCollection();
497 files.setFollowingSymLinks(false);
498 files.setBaseDir(new File("src/test/resources/symlinks"));
499 files.setPrefix("plexus/");
500 zipArchiver.addResources(files);
501 zipArchiver.createArchive();
502 final File output = getTestFile("target/output/unzipped");
503 output.mkdirs();
504 final ZipUnArchiver zipUnArchiver = getZipUnArchiver(zipFile);
505 zipUnArchiver.setDestFile(output);
506 zipUnArchiver.extract();
507 File symDir = new File("target/output/unzipped/plexus/src/symDir");
508 PlexusIoResourceAttributes fa = FileAttributes.uncached(symDir);
509 assertTrue(fa.isSymbolicLink());
510 }
511
512 @Test
513 @DisabledOnOs(OS.WINDOWS)
514 @SuppressWarnings("ResultOfMethodCallIgnored")
515 void testSymlinkFileSet() throws Exception {
516 final File zipFile = getTestFile("target/output/pasymlinks-fileset.zip");
517 final ZipArchiver zipArchiver = getZipArchiver(zipFile);
518 final DefaultFileSet fs = new DefaultFileSet();
519 fs.setPrefix("bzz/");
520 fs.setDirectory(new File("src/test/resources/symlinks/src"));
521 zipArchiver.addFileSet(fs);
522 zipArchiver.createArchive();
523 final File output = getTestFile("target/output/unzipped/symlFs");
524 output.mkdirs();
525 final ZipUnArchiver zipUnArchiver = getZipUnArchiver(zipFile);
526 zipUnArchiver.setDestFile(output);
527 zipUnArchiver.extract();
528 File symDir = new File(output, "bzz/symDir");
529 PlexusIoResourceAttributes fa = FileAttributes.uncached(symDir);
530 assertTrue(fa.isSymbolicLink());
531 }
532
533 @Test
534 void testSymlinkArchivedFileSet() throws Exception {
535 final File zipFile = getTestFile("src/test/resources/symlinks/symlinks.zip");
536 final File zipFile2 = getTestFile("target/output/pasymlinks-archivedFileset.zip");
537 final ZipArchiver zipArchiver = getZipArchiver(zipFile2);
538 zipArchiver.addArchivedFileSet(zipFile);
539 zipArchiver.createArchive();
540
541 final ZipFile cmp1 = ZipFile.builder().setFile(zipFile).get();
542 final ZipFile cmp2 = ZipFile.builder().setFile(zipFile2).get();
543 ArchiveFileComparator.assertZipEquals(cmp1, cmp2, "");
544 }
545
546
547
548
549
550 @Test
551 void testLastModifiedTimeRounding() throws Exception {
552 Path oddSecondsTimestampFile = Files.createTempFile(tempDir.toPath(), "odd-seconds-timestamp", null);
553
554 Files.setLastModifiedTime(oddSecondsTimestampFile, FileTime.fromMillis(1534189011_000L));
555 Path evenSecondsTimestampFile = Files.createTempFile(tempDir.toPath(), "even-seconds-timestamp", null);
556 Files.setLastModifiedTime(evenSecondsTimestampFile, FileTime.fromMillis(1534189012_000L));
557
558 File destFile = getTestFile("target/output/last-modified-time.zip");
559 ZipArchiver archiver = getZipArchiver(destFile);
560 archiver.addFile(oddSecondsTimestampFile.toFile(), "odd-seconds");
561 archiver.addFile(evenSecondsTimestampFile.toFile(), "even-seconds");
562 archiver.createArchive();
563
564
565 try (ZipFile resultingZipFile = ZipFile.builder().setFile(destFile).get()) {
566 assertEquals(
567 1534189012_000L, resultingZipFile.getEntry("odd-seconds").getTime());
568 assertEquals(
569 1534189012_000L, resultingZipFile.getEntry("even-seconds").getTime());
570
571 FileTime expected = FileTime.fromMillis(1534189012_000L);
572 assertEquals(expected, resultingZipFile.getEntry("odd-seconds").getLastModifiedTime());
573 assertEquals(expected, resultingZipFile.getEntry("even-seconds").getLastModifiedTime());
574 }
575 }
576
577
578
579 @Test
580 void testForced() throws Exception {
581 ZipArchiver archiver = newArchiver("archive2.zip");
582
583 assertTrue(archiver.isForced());
584 File f = archiver.getDestFile();
585 if (f.exists()) {
586 FileUtils.fileDelete(f.getPath());
587 }
588 assertFalse(f.exists());
589 createArchive(archiver);
590 long l1 = f.lastModified();
591 assertTrue(f.exists());
592
593 archiver = newArchiver("archive2.zip");
594 waitUntilNewTimestamp(archiver.getDestFile(), l1);
595 createArchive(archiver);
596 long l2 = f.lastModified();
597 assertTrue(f.exists());
598 assertTrue(l2 > l1);
599
600 archiver = newArchiver("archive2.zip");
601 assertTrue(archiver.isSupportingForced());
602 archiver.setForced(false);
603 assertFalse(archiver.isForced());
604
605 createArchive(archiver);
606 long l3 = f.lastModified();
607 assertTrue(f.exists());
608 assertEquals(l2, l3);
609 }
610
611
612 @Test
613 void testLookAtExtraZipFields_from_macos() throws IOException {
614 InputStream fis = Streams.fileInputStream(new File("src/test/resources/zip-timestamp/macOsZipFile.zip"));
615 ZipInputStream zis = new ZipInputStream(fis);
616 final java.util.zip.ZipEntry evenEntry = zis.getNextEntry();
617 final ZipExtraField[] parse = ExtraFieldUtils.parse(evenEntry.getExtra());
618 System.out.println(Arrays.asList(parse));
619 final java.util.zip.ZipEntry oddEntry = zis.getNextEntry();
620
621 System.out.println(Arrays.asList(ExtraFieldUtils.parse(oddEntry.getExtra())));
622
623 System.out.println("oddEntry.getTime() = " + new Date(oddEntry.getTime()));
624 System.out.println("oddEntry.getName() = " + oddEntry.getName());
625 System.out.println("new String(oddEntry.getExtra()) = " + new String(oddEntry.getExtra()));
626 System.out.println("evenEntry.getName() = " + evenEntry.getName());
627 System.out.println("evenEntry.getTime() = " + new Date(evenEntry.getTime()));
628 System.out.println("new String(evenEntry.getExtra()) = " + new String(evenEntry.getExtra()));
629 }
630
631
632 @Test
633 void testZipStuff() throws IOException {
634 ByteArrayOutputStream baos = new ByteArrayOutputStream();
635 ZipOutputStream zos = new ZipOutputStream(baos);
636
637 final File oddFile = new File("src/test/resources/zip-timestamp/file-with-odd-time.txt");
638 final File evenFile = new File("src/test/resources/zip-timestamp/file-with-even-time.txt");
639 final ZipEntry oddZe = new ZipEntry(oddFile.getName());
640 oddZe.setTime(oddFile.lastModified());
641 zos.putNextEntry(oddZe);
642 final ZipEntry evenZe = new ZipEntry(evenFile.getName());
643 evenZe.setTime(evenFile.lastModified());
644 zos.putNextEntry(evenZe);
645 zos.close();
646
647 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
648 ZipInputStream zipInputStream = new ZipInputStream(bais);
649 final java.util.zip.ZipEntry oddEntry = zipInputStream.getNextEntry();
650 System.out.println("oddEntry.getTime() = " + new Date(oddEntry.getTime()));
651 System.out.println("oddEntry.getName() = " + oddEntry.getName());
652 final java.util.zip.ZipEntry evenEntry = zipInputStream.getNextEntry();
653 System.out.println("evenEntry.getName() = " + evenEntry.getName());
654 System.out.println("evenEntry.getTime() = " + new Date(evenEntry.getTime()));
655 }
656
657 @Disabled("Junit3 method name is notest")
658 @Test
659 void notestJustThatOne() throws Exception {
660 final File srcDir = new File("src");
661 String[] inc = {"test/java/org/codehaus/plexus/archiver/zip/ZipShortTest.java"};
662 final File zipFile = new File("target/output/zz1.zip");
663
664 final File zipFile2 = new File("target/output/zz2.zip");
665 ZipArchiver zipArchiver2 = getZipArchiver(zipFile2);
666
667
668 zipArchiver2.addArchivedFileSet(zipFile);
669 FileUtils.removePath(zipFile2.getPath());
670 zipArchiver2.createArchive();
671 }
672
673 @Test
674 void testCreateResourceCollection() throws Exception {
675 final File srcDir = new File("src");
676 final File zipFile = new File("target/output/src.zip");
677 ZipArchiver zipArchiver = getZipArchiver(zipFile);
678 zipArchiver.addDirectory(srcDir, null, FileUtils.getDefaultExcludes());
679 zipArchiver.setEncoding("UTF-8");
680 FileUtils.removePath(zipFile.getPath());
681 zipArchiver.createArchive();
682
683 final File zipFile2 = new File("target/output/src2.zip");
684 ZipArchiver zipArchiver2 = getZipArchiver(zipFile2);
685 zipArchiver2.addArchivedFileSet(zipFile, "prfx/");
686 zipArchiver2.setEncoding("UTF-8");
687 FileUtils.removePath(zipFile2.getPath());
688 zipArchiver2.createArchive();
689
690 final ZipFile cmp1 = ZipFile.builder().setFile(zipFile).get();
691 final ZipFile cmp2 = ZipFile.builder().setFile(zipFile2).get();
692 ArchiveFileComparator.assertZipEquals(cmp1, cmp2, "prfx/");
693 cmp1.close();
694 cmp2.close();
695 }
696
697 @Test
698 void testZipNonConcurrentResourceCollection() throws Exception {
699 final File tarFile = getTestFile("target/output/zip-non-concurrent.tar");
700 TarArchiver tarArchiver = (TarArchiver) lookup(Archiver.class, "tar");
701
702
703 tarArchiver.setOverrideUid(100);
704 tarArchiver.setOverrideGid(100);
705 tarArchiver.setDestFile(tarFile);
706
707 for (int i = 0; i < 100; i++) {
708 tarArchiver.addFile(getTestFile("src/test/resources/manifests/manifest1.mf"), "manifest1.mf" + i);
709
710 tarArchiver.addFile(
711 getTestFile("src/test/resources/manifests/manifest2.mf"), "subdir" + i + "/manifest2.mf");
712 }
713 tarArchiver.createArchive();
714
715 final File zipFile = new File("target/output/zip-non-concurrent.zip");
716 ZipArchiver zipArchive = getZipArchiver(zipFile);
717 zipArchive.addArchivedFileSet(tarFile, "prfx/");
718 zipArchive.setEncoding("UTF-8");
719 zipArchive.createArchive();
720
721 final TarFile cmp1 = new TarFile(tarFile);
722 final ZipFile cmp2 = ZipFile.builder().setFile(zipFile).get();
723 ArchiveFileComparator.assertTarZipEquals(cmp1, cmp2, "prfx/");
724 cmp1.close();
725 cmp2.close();
726 }
727
728 @Test
729 void testDefaultUTF8() throws IOException {
730 final ZipArchiver zipArchiver = getZipArchiver(new File("target/output/utf8-default.zip"));
731 zipArchiver.addDirectory(new File("src/test/resources/miscUtf8"));
732 zipArchiver.createArchive();
733 }
734
735 @Test
736 void testDefaultUTF8withUTF8() throws IOException {
737 final ZipArchiver zipArchiver = getZipArchiver(new File("target/output/utf8-with_utf.zip"));
738 zipArchiver.setEncoding("UTF-8");
739 zipArchiver.addDirectory(new File("src/test/resources/miscUtf8"));
740 zipArchiver.createArchive();
741 }
742
743 @Test
744 void testForcedFileModes() throws IOException {
745 File step1file = new File("target/output/forced-file-mode.zip");
746 {
747 final ZipArchiver zipArchiver = getZipArchiver(step1file);
748 zipArchiver.setFileMode(0077);
749 zipArchiver.setDirectoryMode(0007);
750 PlexusIoResourceAttributes attrs = new SimpleResourceAttributes(123, "fred", 22, "filntstones", 0111);
751 PlexusIoResource resource = ResourceFactory.createResource(
752 new File("src/test/resources/folders/File.txt"), "Test.txt", null, attrs);
753 zipArchiver.addResource(resource, "Test2.txt", 0707);
754 PlexusIoFileResourceCollection files = new PlexusIoFileResourceCollection();
755 files.setBaseDir(new File("src/test/resources/folders"));
756 files.setPrefix("sixsixsix/");
757 zipArchiver.addResources(files);
758
759 zipArchiver.createArchive();
760
761 ZipFile zf = ZipFile.builder().setFile(step1file).get();
762 fileModeAssert(040007, zf.getEntry("sixsixsix/a/").getUnixMode());
763 fileModeAssert(0100077, zf.getEntry("sixsixsix/b/FileInB.txt").getUnixMode());
764 fileModeAssert(0100707, zf.getEntry("Test2.txt").getUnixMode());
765 zf.close();
766 }
767
768 File Step2file = new File("target/output/forced-file-mode-from-zip.zip");
769 {
770 final ZipArchiver za2 = getZipArchiver(Step2file);
771 za2.setFileMode(0666);
772 za2.setDirectoryMode(0676);
773
774 PlexusIoZipFileResourceCollection zipSrc = new PlexusIoZipFileResourceCollection();
775 zipSrc.setFile(step1file);
776 zipSrc.setPrefix("zz/");
777 za2.addResources(zipSrc);
778 za2.createArchive();
779 ZipFile zf = ZipFile.builder().setFile(Step2file).get();
780 fileModeAssert(040676, zf.getEntry("zz/sixsixsix/a/").getUnixMode());
781 fileModeAssert(0100666, zf.getEntry("zz/Test2.txt").getUnixMode());
782 zf.close();
783 }
784
785 File step3file = new File("target/output/forced-file-mode-from-zip2.zip");
786 {
787 final ZipArchiver za2 = getZipArchiver(step3file);
788 za2.setFileMode(0666);
789 za2.setDirectoryMode(0676);
790
791 PlexusArchiverZipFileResourceCollection zipSrc = new PlexusArchiverZipFileResourceCollection();
792 zipSrc.setFile(step1file);
793 zipSrc.setPrefix("zz/");
794 za2.addResources(zipSrc);
795 za2.createArchive();
796 ZipFile zf = ZipFile.builder().setFile(Step2file).get();
797 fileModeAssert(040676, zf.getEntry("zz/sixsixsix/a/").getUnixMode());
798 fileModeAssert(0100666, zf.getEntry("zz/Test2.txt").getUnixMode());
799 zf.close();
800 }
801 }
802
803 @Test
804 void testFixedEntryModificationTime() throws IOException {
805 final long almostMinDosTime = toLocalTimeZone(315532802000L);
806
807 final File zipFile = getTestFile("target/output/zip-with-fixed-entry-modification-times.zip");
808 final ZipArchiver archiver = getZipArchiver(zipFile);
809 archiver.setLastModifiedTime(FileTime.fromMillis(almostMinDosTime));
810 archiver.addDirectory(new File("src/test/resources/zip-timestamp"));
811 archiver.createArchive();
812
813 assertTrue(zipFile.exists());
814 try (final ZipFile zf = ZipFile.builder().setFile(zipFile).get()) {
815 assertEquals(
816 almostMinDosTime, zf.getEntry("file-with-even-time.txt").getTime());
817 assertEquals(almostMinDosTime, zf.getEntry("file-with-odd-time.txt").getTime());
818 assertEquals(almostMinDosTime, zf.getEntry("foo/").getTime());
819 }
820 }
821
822 @Test
823 @DisabledOnOs(OS.WINDOWS)
824 void testNonExistingSymlink() throws Exception {
825 File zipFile = new File("src/test/resources/symlinks/non_existing_symlink.zip");
826 ZipUnArchiver unArchiver = getZipUnArchiver(zipFile);
827 String tmpdir = Files.createTempDirectory("tmpe_extract").toFile().getAbsolutePath();
828 unArchiver.setDestDirectory(new File(tmpdir));
829 ArchiverException exception = assertThrows(ArchiverException.class, unArchiver::extract);
830 assertEquals("Entry is outside of the target directory (entry1)", exception.getMessage());
831 }
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846 private long toLocalTimeZone(long timestamp) {
847 String dateFormat = "dd-MM-yyyy hh:mm:ss a";
848 DateFormat formatterWithTimeZone = new SimpleDateFormat(dateFormat);
849 formatterWithTimeZone.setTimeZone(TimeZone.getTimeZone("GMT"));
850 String sDate = formatterWithTimeZone.format(new Date(timestamp));
851
852 DateFormat formatter = new SimpleDateFormat(dateFormat);
853 try {
854 Date dateWithTimeZone = formatter.parse(sDate);
855 return dateWithTimeZone.getTime();
856 } catch (ParseException e) {
857 fail("Date '" + sDate + "' can not be parsed!");
858 return 0L;
859 }
860 }
861
862
863
864
865
866 @Test
867 void testGetFilesReturnsForwardSlashes() throws Exception {
868 File zipFile = getTestFile("target/output/test-getfiles-slashes.zip");
869 ZipArchiver archiver = getZipArchiver(zipFile);
870
871
872 File pomFile = new File("pom.xml");
873 archiver.addFile(pomFile, "dir1/dir2/pom.xml");
874 archiver.addFile(pomFile, "another/nested/path/file.xml");
875
876
877 Map<String, ArchiveEntry> files = archiver.getFiles();
878
879
880 for (String entryName : files.keySet()) {
881 assertFalse(entryName.contains("\\"), "Entry name should not contain backslashes, but got: " + entryName);
882 assertTrue(
883 entryName.contains("/") || !entryName.contains(File.separator),
884 "Entry name should use forward slashes as separator: " + entryName);
885 }
886
887
888 assertTrue(files.containsKey("dir1/dir2/pom.xml"), "Should contain dir1/dir2/pom.xml");
889 assertTrue(files.containsKey("another/nested/path/file.xml"), "Should contain another/nested/path/file.xml");
890
891
892 archiver.createArchive();
893 assertTrue(zipFile.exists());
894 }
895 }