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.compress.utils.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 = new ZipFile(zipFile);
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 = new ZipFile(zipFile);
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 = new ZipFile(zipFile2);
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) throws Exception {
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 = new ZipFile(zipFileRecompress);
318 assertEquals(ZipEntry.DEFLATED, zfRecompress.getEntry("test.zip").getMethod());
319 assertEquals(ZipEntry.DEFLATED, zfRecompress.getEntry("test.jar").getMethod());
320 assertEquals(ZipEntry.DEFLATED, zfRecompress.getEntry("test.rar").getMethod());
321 assertEquals(ZipEntry.DEFLATED, zfRecompress.getEntry("test.tar.gz").getMethod());
322 zfRecompress.close();
323
324
325
326 final File zipFileDontRecompress = getTestFile("target/output/dont-recompress-added-zips.zip");
327 ZipArchiver zipArchiver = getZipArchiver(zipFileDontRecompress);
328 zipArchiver.addDirectory(getTestFile("src/test/jars"));
329 zipArchiver.setRecompressAddedZips(false);
330 FileUtils.removePath(zipFileDontRecompress.getPath());
331 zipArchiver.createArchive();
332
333 final ZipFile zfDontRecompress = new ZipFile(zipFileDontRecompress);
334 final ZipArchiveEntry zipEntry = zfDontRecompress.getEntry("test.zip");
335 final ZipArchiveEntry jarEntry = zfDontRecompress.getEntry("test.jar");
336 final ZipArchiveEntry rarEntry = zfDontRecompress.getEntry("test.rar");
337 final ZipArchiveEntry tarEntry = zfDontRecompress.getEntry("test.tar.gz");
338
339 assertEquals(ZipEntry.STORED, zipEntry.getMethod());
340 assertEquals(ZipEntry.STORED, jarEntry.getMethod());
341 assertEquals(ZipEntry.STORED, rarEntry.getMethod());
342 assertEquals(ZipEntry.DEFLATED, tarEntry.getMethod());
343
344 assertTrue(IOUtil.contentEquals(
345 Files.newInputStream(getTestFile("src/test/jars/test.zip").toPath()),
346 zfDontRecompress.getInputStream(zipEntry)));
347 assertTrue(IOUtil.contentEquals(
348 Files.newInputStream(getTestFile("src/test/jars/test.jar").toPath()),
349 zfDontRecompress.getInputStream(jarEntry)));
350 assertTrue(IOUtil.contentEquals(
351 Files.newInputStream(getTestFile("src/test/jars/test.rar").toPath()),
352 zfDontRecompress.getInputStream(rarEntry)));
353 assertTrue(IOUtil.contentEquals(
354 Files.newInputStream(getTestFile("src/test/jars/test.tar.gz").toPath()),
355 zfDontRecompress.getInputStream(tarEntry)));
356 zfDontRecompress.close();
357 }
358
359 @Test
360 void testAddArchivedFileSet() throws Exception {
361 File toBeAdded = new File("src/test/resources/test.zip");
362 DefaultArchivedFileSet sfd = DefaultArchivedFileSet.archivedFileSet(toBeAdded);
363 File zipFIle = getTestFile("target/output/withZip.zip");
364 final ZipArchiver zipArchiver = getZipArchiver(zipFIle);
365 InputStreamTransformer is = new InputStreamTransformer() {
366
367 @Nonnull
368 public InputStream transform(@Nonnull PlexusIoResource resource, @Nonnull InputStream inputStream)
369 throws IOException {
370 return new BoundedInputStream(inputStream, 3);
371 }
372 };
373 sfd.setStreamTransformer(is);
374 PrefixFileMapper mapper = new PrefixFileMapper();
375 mapper.setPrefix("prefix");
376 sfd.setFileMappers(new FileMapper[] {mapper});
377 zipArchiver.addArchivedFileSet(sfd);
378 zipArchiver.createArchive();
379
380 final ZipUnArchiver zipUnArchiver = getZipUnArchiver(zipFIle);
381 File destFile = new File("target/output/withZip");
382 destFile.mkdirs();
383 zipUnArchiver.setDestFile(destFile);
384 zipUnArchiver.extract();
385 File a3byteFile = new File(
386 destFile,
387 "prefixUsers/kristian/lsrc/plexus/plexus-archiver/src/main/java/org/codehaus/plexus/archiver/zip/ZipArchiver.java");
388 assertTrue(a3byteFile.exists());
389 assertTrue(a3byteFile.length() == 3);
390 }
391
392 @Test
393 void testCreateArchiveWithStreamTransformer() throws IOException {
394 InputStreamTransformer is = new InputStreamTransformer() {
395
396 @Nonnull
397 @Override
398 public InputStream transform(@Nonnull PlexusIoResource resource, @Nonnull InputStream inputStream)
399 throws IOException {
400 return new BoundedInputStream(inputStream, 3);
401 }
402 };
403
404 final ZipArchiver zipArchiver = getZipArchiver(getTestFile("target/output/all3bytes.zip"));
405 File zipFIle = new File("src/test/resources/test.zip");
406 DefaultArchivedFileSet afs = new DefaultArchivedFileSet(zipFIle);
407 afs.setStreamTransformer(is);
408 afs.setPrefix("azip/");
409 zipArchiver.addArchivedFileSet(afs);
410
411 DefaultFileSet dfs = new DefaultFileSet(new File("src/test/resources/mjar179"));
412 dfs.setStreamTransformer(is);
413 dfs.setPrefix("mj179/");
414 zipArchiver.addFileSet(dfs);
415
416 PlexusIoFileResourceCollection files = new PlexusIoFileResourceCollection();
417 files.setBaseDir(new File("src/test/resources"));
418 files.setStreamTransformer(is);
419 files.setPrefix("plexus/");
420 zipArchiver.addResources(files);
421
422 zipArchiver.createArchive();
423 }
424
425 private ZipArchiver newArchiver(String name) throws Exception {
426 ZipArchiver archiver = getZipArchiver(getTestFile("target/output/" + name));
427
428 archiver.setFileMode(0640);
429 archiver.addFile(getTestFile("src/test/resources/manifests/manifest1.mf"), "one.txt");
430 archiver.addFile(getTestFile("src/test/resources/manifests/manifest2.mf"), "two.txt", 0664);
431
432
433 archiver.setFileMode(0400);
434 archiver.setDirectoryMode(0777);
435 archiver.addDirectory(getTestFile("src/test/resources/world-writable/"), "worldwritable/");
436
437 archiver.setDirectoryMode(0070);
438 archiver.addDirectory(getTestFile("src/test/resources/group-writable/"), "groupwritable/");
439
440 archiver.setDirectoryMode(0500);
441 archiver.setFileMode(0400);
442 archiver.addDirectory(getTestFile("src"));
443
444 return archiver;
445 }
446
447 private void fileModeAssert(int expected, int actual) {
448 assertEquals(Integer.toString(expected, 8), Integer.toString(actual, 8));
449 }
450
451 private void createArchive(ZipArchiver archiver) throws ArchiverException, IOException {
452 archiver.createArchive();
453
454 ZipFile zf = new ZipFile(archiver.getDestFile());
455
456 Enumeration e = zf.getEntries();
457
458 while (e.hasMoreElements()) {
459 ZipArchiveEntry ze = (ZipArchiveEntry) e.nextElement();
460 if (ze.isDirectory()) {
461 if (ze.getName().startsWith("worldwritable")) {
462 fileModeAssert(0777, UnixStat.PERM_MASK & ze.getUnixMode());
463 } else if (ze.getName().startsWith("groupwritable")) {
464 fileModeAssert(0070, UnixStat.PERM_MASK & ze.getUnixMode());
465 } else {
466 fileModeAssert(0500, UnixStat.PERM_MASK & ze.getUnixMode());
467 }
468 } else {
469 if (ze.getName().equals("one.txt")) {
470 fileModeAssert(0640, UnixStat.PERM_MASK & ze.getUnixMode());
471 } else if (ze.getName().equals("two.txt")) {
472 fileModeAssert(0664, UnixStat.PERM_MASK & ze.getUnixMode());
473 } else if (ze.isUnixSymlink()) {
474
475 } else {
476 fileModeAssert(0400, UnixStat.PERM_MASK & ze.getUnixMode());
477 }
478 }
479 }
480 }
481
482 @Test
483 @DisabledOnOs(OS.WINDOWS)
484 void testSymlinkZip() throws Exception {
485 final File zipFile = getTestFile("target/output/pasymlinks.zip");
486 final ZipArchiver zipArchiver = getZipArchiver(zipFile);
487 PlexusIoFileResourceCollection files = new PlexusIoFileResourceCollection();
488 files.setFollowingSymLinks(false);
489 files.setBaseDir(new File("src/test/resources/symlinks"));
490 files.setPrefix("plexus/");
491 zipArchiver.addResources(files);
492 zipArchiver.createArchive();
493 final File output = getTestFile("target/output/unzipped");
494 output.mkdirs();
495 final ZipUnArchiver zipUnArchiver = getZipUnArchiver(zipFile);
496 zipUnArchiver.setDestFile(output);
497 zipUnArchiver.extract();
498 File symDir = new File("target/output/unzipped/plexus/src/symDir");
499 PlexusIoResourceAttributes fa = FileAttributes.uncached(symDir);
500 assertTrue(fa.isSymbolicLink());
501 }
502
503 @Test
504 @DisabledOnOs(OS.WINDOWS)
505 @SuppressWarnings("ResultOfMethodCallIgnored")
506 void testSymlinkFileSet() throws Exception {
507 final File zipFile = getTestFile("target/output/pasymlinks-fileset.zip");
508 final ZipArchiver zipArchiver = getZipArchiver(zipFile);
509 final DefaultFileSet fs = new DefaultFileSet();
510 fs.setPrefix("bzz/");
511 fs.setDirectory(new File("src/test/resources/symlinks/src"));
512 zipArchiver.addFileSet(fs);
513 zipArchiver.createArchive();
514 final File output = getTestFile("target/output/unzipped/symlFs");
515 output.mkdirs();
516 final ZipUnArchiver zipUnArchiver = getZipUnArchiver(zipFile);
517 zipUnArchiver.setDestFile(output);
518 zipUnArchiver.extract();
519 File symDir = new File(output, "bzz/symDir");
520 PlexusIoResourceAttributes fa = FileAttributes.uncached(symDir);
521 assertTrue(fa.isSymbolicLink());
522 }
523
524 @Test
525 void testSymlinkArchivedFileSet() throws Exception {
526 final File zipFile = getTestFile("src/test/resources/symlinks/symlinks.zip");
527 final File zipFile2 = getTestFile("target/output/pasymlinks-archivedFileset.zip");
528 final ZipArchiver zipArchiver = getZipArchiver(zipFile2);
529 zipArchiver.addArchivedFileSet(zipFile);
530 zipArchiver.createArchive();
531
532 final ZipFile cmp1 = new ZipFile(zipFile);
533 final ZipFile cmp2 = new ZipFile(zipFile2);
534 ArchiveFileComparator.assertZipEquals(cmp1, cmp2, "");
535 }
536
537
538
539
540
541 @Test
542 void testLastModifiedTimeRounding() throws Exception {
543 Path oddSecondsTimestampFile = Files.createTempFile(tempDir.toPath(), "odd-seconds-timestamp", null);
544
545 Files.setLastModifiedTime(oddSecondsTimestampFile, FileTime.fromMillis(1534189011_000L));
546 Path evenSecondsTimestampFile = Files.createTempFile(tempDir.toPath(), "even-seconds-timestamp", null);
547 Files.setLastModifiedTime(evenSecondsTimestampFile, FileTime.fromMillis(1534189012_000L));
548
549 File destFile = getTestFile("target/output/last-modified-time.zip");
550 ZipArchiver archiver = getZipArchiver(destFile);
551 archiver.addFile(oddSecondsTimestampFile.toFile(), "odd-seconds");
552 archiver.addFile(evenSecondsTimestampFile.toFile(), "even-seconds");
553 archiver.createArchive();
554
555
556 try (ZipFile resultingZipFile = new ZipFile(destFile)) {
557 assertEquals(
558 1534189012_000L, resultingZipFile.getEntry("odd-seconds").getTime());
559 assertEquals(
560 1534189012_000L, resultingZipFile.getEntry("even-seconds").getTime());
561
562 FileTime expected = FileTime.fromMillis(1534189012_000L);
563 assertEquals(expected, resultingZipFile.getEntry("odd-seconds").getLastModifiedTime());
564 assertEquals(expected, resultingZipFile.getEntry("even-seconds").getLastModifiedTime());
565 }
566 }
567
568
569
570 @Test
571 void testForced() throws Exception {
572 ZipArchiver archiver = newArchiver("archive2.zip");
573
574 assertTrue(archiver.isForced());
575 File f = archiver.getDestFile();
576 if (f.exists()) {
577 FileUtils.fileDelete(f.getPath());
578 }
579 assertFalse(f.exists());
580 createArchive(archiver);
581 long l1 = f.lastModified();
582 assertTrue(f.exists());
583
584 archiver = newArchiver("archive2.zip");
585 waitUntilNewTimestamp(archiver.getDestFile(), l1);
586 createArchive(archiver);
587 long l2 = f.lastModified();
588 assertTrue(f.exists());
589 assertTrue(l2 > l1);
590
591 archiver = newArchiver("archive2.zip");
592 assertTrue(archiver.isSupportingForced());
593 archiver.setForced(false);
594 assertFalse(archiver.isForced());
595
596 createArchive(archiver);
597 long l3 = f.lastModified();
598 assertTrue(f.exists());
599 assertEquals(l2, l3);
600 }
601
602
603 @Test
604 void testLookAtExtraZipFields_from_macos() throws IOException {
605 InputStream fis = Streams.fileInputStream(new File("src/test/resources/zip-timestamp/macOsZipFile.zip"));
606 ZipInputStream zis = new ZipInputStream(fis);
607 final java.util.zip.ZipEntry evenEntry = zis.getNextEntry();
608 final ZipExtraField[] parse = ExtraFieldUtils.parse(evenEntry.getExtra());
609 System.out.println(Arrays.asList(parse));
610 final java.util.zip.ZipEntry oddEntry = zis.getNextEntry();
611
612 System.out.println(Arrays.asList(ExtraFieldUtils.parse(oddEntry.getExtra())));
613
614 System.out.println("oddEntry.getTime() = " + new Date(oddEntry.getTime()).toString());
615 System.out.println("oddEntry.getName() = " + oddEntry.getName());
616 System.out.println("new String(oddEntry.getExtra()) = " + new String(oddEntry.getExtra()));
617 System.out.println("evenEntry.getName() = " + evenEntry.getName());
618 System.out.println("evenEntry.getTime() = " + new Date(evenEntry.getTime()).toString());
619 System.out.println("new String(evenEntry.getExtra()) = " + new String(evenEntry.getExtra()));
620 }
621
622
623 @Test
624 void testZipStuff() throws IOException {
625 ByteArrayOutputStream baos = new ByteArrayOutputStream();
626 ZipOutputStream zos = new ZipOutputStream(baos);
627
628 final File oddFile = new File("src/test/resources/zip-timestamp/file-with-odd-time.txt");
629 final File evenFile = new File("src/test/resources/zip-timestamp/file-with-even-time.txt");
630 final ZipEntry oddZe = new ZipEntry(oddFile.getName());
631 oddZe.setTime(oddFile.lastModified());
632 zos.putNextEntry(oddZe);
633 final ZipEntry evenZe = new ZipEntry(evenFile.getName());
634 evenZe.setTime(evenFile.lastModified());
635 zos.putNextEntry(evenZe);
636 zos.close();
637
638 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
639 ZipInputStream zipInputStream = new ZipInputStream(bais);
640 final java.util.zip.ZipEntry oddEntry = zipInputStream.getNextEntry();
641 System.out.println("oddEntry.getTime() = " + new Date(oddEntry.getTime()).toString());
642 System.out.println("oddEntry.getName() = " + oddEntry.getName());
643 final java.util.zip.ZipEntry evenEntry = zipInputStream.getNextEntry();
644 System.out.println("evenEntry.getName() = " + evenEntry.getName());
645 System.out.println("evenEntry.getTime() = " + new Date(evenEntry.getTime()).toString());
646 }
647
648 @Disabled("Junit3 method name is notest")
649 @Test
650 void notestJustThatOne() throws Exception {
651 final File srcDir = new File("src");
652 String[] inc = {"test/java/org/codehaus/plexus/archiver/zip/ZipShortTest.java"};
653 final File zipFile = new File("target/output/zz1.zip");
654
655 final File zipFile2 = new File("target/output/zz2.zip");
656 ZipArchiver zipArchiver2 = getZipArchiver(zipFile2);
657
658
659 zipArchiver2.addArchivedFileSet(zipFile);
660 FileUtils.removePath(zipFile2.getPath());
661 zipArchiver2.createArchive();
662 }
663
664 @Test
665 void testCreateResourceCollection() throws Exception {
666 final File srcDir = new File("src");
667 final File zipFile = new File("target/output/src.zip");
668 ZipArchiver zipArchiver = getZipArchiver(zipFile);
669 zipArchiver.addDirectory(srcDir, null, FileUtils.getDefaultExcludes());
670 zipArchiver.setEncoding("UTF-8");
671 FileUtils.removePath(zipFile.getPath());
672 zipArchiver.createArchive();
673
674 final File zipFile2 = new File("target/output/src2.zip");
675 ZipArchiver zipArchiver2 = getZipArchiver(zipFile2);
676 zipArchiver2.addArchivedFileSet(zipFile, "prfx/");
677 zipArchiver2.setEncoding("UTF-8");
678 FileUtils.removePath(zipFile2.getPath());
679 zipArchiver2.createArchive();
680
681 final ZipFile cmp1 = new ZipFile(zipFile);
682 final ZipFile cmp2 = new ZipFile(zipFile2);
683 ArchiveFileComparator.assertZipEquals(cmp1, cmp2, "prfx/");
684 cmp1.close();
685 cmp2.close();
686 }
687
688 @Test
689 void testZipNonConcurrentResourceCollection() throws Exception {
690 final File tarFile = getTestFile("target/output/zip-non-concurrent.tar");
691 TarArchiver tarArchiver = (TarArchiver) lookup(Archiver.class, "tar");
692
693
694 tarArchiver.setOverrideUid(100);
695 tarArchiver.setOverrideGid(100);
696 tarArchiver.setDestFile(tarFile);
697
698 for (int i = 0; i < 100; i++) {
699 tarArchiver.addFile(getTestFile("src/test/resources/manifests/manifest1.mf"), "manifest1.mf" + i);
700
701 tarArchiver.addFile(
702 getTestFile("src/test/resources/manifests/manifest2.mf"), "subdir" + i + "/manifest2.mf");
703 }
704 tarArchiver.createArchive();
705
706 final File zipFile = new File("target/output/zip-non-concurrent.zip");
707 ZipArchiver zipArchive = getZipArchiver(zipFile);
708 zipArchive.addArchivedFileSet(tarFile, "prfx/");
709 zipArchive.setEncoding("UTF-8");
710 zipArchive.createArchive();
711
712 final TarFile cmp1 = new TarFile(tarFile);
713 final ZipFile cmp2 = new ZipFile(zipFile);
714 ArchiveFileComparator.assertTarZipEquals(cmp1, cmp2, "prfx/");
715 cmp1.close();
716 cmp2.close();
717 }
718
719 @Test
720 void testDefaultUTF8() throws IOException {
721 final ZipArchiver zipArchiver = getZipArchiver(new File("target/output/utf8-default.zip"));
722 zipArchiver.addDirectory(new File("src/test/resources/miscUtf8"));
723 zipArchiver.createArchive();
724 }
725
726 @Test
727 void testDefaultUTF8withUTF8() throws IOException {
728 final ZipArchiver zipArchiver = getZipArchiver(new File("target/output/utf8-with_utf.zip"));
729 zipArchiver.setEncoding("UTF-8");
730 zipArchiver.addDirectory(new File("src/test/resources/miscUtf8"));
731 zipArchiver.createArchive();
732 }
733
734 @Test
735 void testForcedFileModes() throws IOException {
736 File step1file = new File("target/output/forced-file-mode.zip");
737 {
738 final ZipArchiver zipArchiver = getZipArchiver(step1file);
739 zipArchiver.setFileMode(0077);
740 zipArchiver.setDirectoryMode(0007);
741 PlexusIoResourceAttributes attrs = new SimpleResourceAttributes(123, "fred", 22, "filntstones", 0111);
742 PlexusIoResource resource = ResourceFactory.createResource(
743 new File("src/test/resources/folders/File.txt"), "Test.txt", null, attrs);
744 zipArchiver.addResource(resource, "Test2.txt", 0707);
745 PlexusIoFileResourceCollection files = new PlexusIoFileResourceCollection();
746 files.setBaseDir(new File("src/test/resources/folders"));
747 files.setPrefix("sixsixsix/");
748 zipArchiver.addResources(files);
749
750 zipArchiver.createArchive();
751
752 ZipFile zf = new ZipFile(step1file);
753 fileModeAssert(040007, zf.getEntry("sixsixsix/a/").getUnixMode());
754 fileModeAssert(0100077, zf.getEntry("sixsixsix/b/FileInB.txt").getUnixMode());
755 fileModeAssert(0100707, zf.getEntry("Test2.txt").getUnixMode());
756 zf.close();
757 }
758
759 File Step2file = new File("target/output/forced-file-mode-from-zip.zip");
760 {
761 final ZipArchiver za2 = getZipArchiver(Step2file);
762 za2.setFileMode(0666);
763 za2.setDirectoryMode(0676);
764
765 PlexusIoZipFileResourceCollection zipSrc = new PlexusIoZipFileResourceCollection();
766 zipSrc.setFile(step1file);
767 zipSrc.setPrefix("zz/");
768 za2.addResources(zipSrc);
769 za2.createArchive();
770 ZipFile zf = new ZipFile(Step2file);
771 fileModeAssert(040676, zf.getEntry("zz/sixsixsix/a/").getUnixMode());
772 fileModeAssert(0100666, zf.getEntry("zz/Test2.txt").getUnixMode());
773 zf.close();
774 }
775
776 File step3file = new File("target/output/forced-file-mode-from-zip2.zip");
777 {
778 final ZipArchiver za2 = getZipArchiver(step3file);
779 za2.setFileMode(0666);
780 za2.setDirectoryMode(0676);
781
782 PlexusArchiverZipFileResourceCollection zipSrc = new PlexusArchiverZipFileResourceCollection();
783 zipSrc.setFile(step1file);
784 zipSrc.setPrefix("zz/");
785 za2.addResources(zipSrc);
786 za2.createArchive();
787 ZipFile zf = new ZipFile(Step2file);
788 fileModeAssert(040676, zf.getEntry("zz/sixsixsix/a/").getUnixMode());
789 fileModeAssert(0100666, zf.getEntry("zz/Test2.txt").getUnixMode());
790 zf.close();
791 }
792 }
793
794 @Test
795 void testFixedEntryModificationTime() throws IOException {
796 final long almostMinDosTime = toLocalTimeZone(315532802000L);
797
798 final File zipFile = getTestFile("target/output/zip-with-fixed-entry-modification-times.zip");
799 final ZipArchiver archiver = getZipArchiver(zipFile);
800 archiver.setLastModifiedTime(FileTime.fromMillis(almostMinDosTime));
801 archiver.addDirectory(new File("src/test/resources/zip-timestamp"));
802 archiver.createArchive();
803
804 assertTrue(zipFile.exists());
805 try (final ZipFile zf = new ZipFile(zipFile)) {
806 assertEquals(
807 almostMinDosTime, zf.getEntry("file-with-even-time.txt").getTime());
808 assertEquals(almostMinDosTime, zf.getEntry("file-with-odd-time.txt").getTime());
809 assertEquals(almostMinDosTime, zf.getEntry("foo/").getTime());
810 }
811 }
812
813 @Test
814 @DisabledOnOs(OS.WINDOWS)
815 void testNonExistingSymlink() throws Exception {
816 File zipFile = new File("src/test/resources/symlinks/non_existing_symlink.zip");
817 ZipUnArchiver unArchiver = getZipUnArchiver(zipFile);
818 String tmpdir = Files.createTempDirectory("tmpe_extract").toFile().getAbsolutePath();
819 unArchiver.setDestDirectory(new File(tmpdir));
820 ArchiverException exception = assertThrows(ArchiverException.class, unArchiver::extract);
821 assertEquals("Entry is outside of the target directory (entry1)", exception.getMessage());
822 }
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837 private long toLocalTimeZone(long timestamp) {
838 String dateFormat = "dd-MM-yyyy hh:mm:ss a";
839 DateFormat formatterWithTimeZone = new SimpleDateFormat(dateFormat);
840 formatterWithTimeZone.setTimeZone(TimeZone.getTimeZone("GMT"));
841 String sDate = formatterWithTimeZone.format(new Date(timestamp));
842
843 DateFormat formatter = new SimpleDateFormat(dateFormat);
844 try {
845 Date dateWithTimeZone = formatter.parse(sDate);
846 return dateWithTimeZone.getTime();
847 } catch (ParseException e) {
848 fail("Date '" + sDate + "' can not be parsed!");
849 return 0L;
850 }
851 }
852 }