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