1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.compress.archivers.zip;
18
19 import static java.nio.charset.StandardCharsets.UTF_8;
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertNotEquals;
23
24 import java.io.ByteArrayOutputStream;
25 import java.io.File;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.OutputStream;
29 import java.nio.file.Files;
30 import java.util.Arrays;
31
32 import org.junit.jupiter.api.Test;
33 import org.junit.jupiter.api.io.TempDir;
34
35 public class DataDescriptorTest {
36
37 @TempDir
38 private File dir;
39
40 private int findCentralDirectory(final byte[] data) {
41
42 return (int) ZipLong.getValue(data, data.length - 22 + 16);
43 }
44
45 @Test
46 public void testDoesntWriteDataDescriptorForDeflatedEntryOnSeekableOutput() throws IOException {
47 final File file = new File(dir, "test.zip");
48 try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(file)) {
49 zos.putArchiveEntry(new ZipArchiveEntry("test1.txt"));
50 zos.write("foo".getBytes(UTF_8));
51 zos.closeArchiveEntry();
52 }
53
54 final byte[] data = Files.readAllBytes(file.toPath());
55
56 final byte[] versionInLFH = Arrays.copyOfRange(data, 4, 6);
57
58 assertArrayEquals(new byte[] { 20, 0 }, versionInLFH);
59 final byte[] gpbInLFH = Arrays.copyOfRange(data, 6, 8);
60
61 assertArrayEquals(new byte[] { 0, 8 }, gpbInLFH);
62
63 final int cdhStart = findCentralDirectory(data);
64 final byte[] versionInCDH = Arrays.copyOfRange(data, cdhStart + 6, cdhStart + 8);
65 assertArrayEquals(new byte[] { 20, 0 }, versionInCDH);
66 final byte[] gpbInCDH = Arrays.copyOfRange(data, cdhStart + 8, cdhStart + 10);
67 assertArrayEquals(new byte[] { 0, 8 }, gpbInCDH);
68
69 final int ddStart = cdhStart - 16;
70 assertNotEquals(ZipLong.DD_SIG, new ZipLong(data, ddStart));
71 final long crcFromLFH = ZipLong.getValue(data, 14);
72 final long cSizeFromLFH = ZipLong.getValue(data, 18);
73 final long sizeFromLFH = ZipLong.getValue(data, 22);
74 assertEquals(3, sizeFromLFH);
75
76 final long crcFromCDH = ZipLong.getValue(data, cdhStart + 16);
77 assertEquals(crcFromLFH, crcFromCDH);
78 final long cSizeFromCDH = ZipLong.getValue(data, cdhStart + 20);
79 assertEquals(cSizeFromLFH, cSizeFromCDH);
80 final long sizeFromCDH = ZipLong.getValue(data, cdhStart + 24);
81 assertEquals(sizeFromLFH, sizeFromCDH);
82 }
83
84 @Test
85 public void testDoesntWriteDataDescriptorWhenAddingRawEntries() throws IOException {
86 final ByteArrayOutputStream init = new ByteArrayOutputStream();
87 try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(init)) {
88 zos.putArchiveEntry(new ZipArchiveEntry("test1.txt"));
89 zos.write("foo".getBytes(UTF_8));
90 zos.closeArchiveEntry();
91 }
92
93 final File f = new File(dir, "test.zip");
94 try (OutputStream fos = Files.newOutputStream(f.toPath())) {
95 fos.write(init.toByteArray());
96 }
97
98 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
99 try (ZipFile zf = ZipFile.builder().setFile(f).get();
100 ZipArchiveOutputStream zos = new ZipArchiveOutputStream(baos)) {
101 final ZipArchiveEntry zae = zf.getEntry("test1.txt");
102 try (InputStream rawInputStream = zf.getRawInputStream(zae)) {
103 zos.addRawArchiveEntry(zae, rawInputStream);
104 }
105 }
106
107 final byte[] data = baos.toByteArray();
108 final byte[] versionInLFH = Arrays.copyOfRange(data, 4, 6);
109
110 assertArrayEquals(new byte[] { 20, 0 }, versionInLFH);
111 final byte[] gpbInLFH = Arrays.copyOfRange(data, 6, 8);
112
113 assertArrayEquals(new byte[] { 0, 8 }, gpbInLFH);
114
115 final int cdhStart = findCentralDirectory(data);
116 final byte[] versionInCDH = Arrays.copyOfRange(data, cdhStart + 6, cdhStart + 8);
117 assertArrayEquals(new byte[] { 20, 0 }, versionInCDH);
118 final byte[] gpbInCDH = Arrays.copyOfRange(data, cdhStart + 8, cdhStart + 10);
119 assertArrayEquals(new byte[] { 0, 8 }, gpbInCDH);
120
121 final int ddStart = cdhStart - 16;
122 assertNotEquals(ZipLong.DD_SIG, new ZipLong(data, ddStart));
123 final long crcFromLFH = ZipLong.getValue(data, 14);
124 final long cSizeFromLFH = ZipLong.getValue(data, 18);
125 final long sizeFromLFH = ZipLong.getValue(data, 22);
126 assertEquals(3, sizeFromLFH);
127
128 final long crcFromCDH = ZipLong.getValue(data, cdhStart + 16);
129 assertEquals(crcFromLFH, crcFromCDH);
130 final long cSizeFromCDH = ZipLong.getValue(data, cdhStart + 20);
131 assertEquals(cSizeFromLFH, cSizeFromCDH);
132 final long sizeFromCDH = ZipLong.getValue(data, cdhStart + 24);
133 assertEquals(sizeFromLFH, sizeFromCDH);
134 }
135
136 @Test
137 public void testWritesDataDescriptorForDeflatedEntryOnUnseekableOutput() throws IOException {
138 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
139 try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(baos)) {
140 zos.putArchiveEntry(new ZipArchiveEntry("test1.txt"));
141 zos.write("foo".getBytes(UTF_8));
142 zos.closeArchiveEntry();
143 }
144 final byte[] data = baos.toByteArray();
145
146 final byte[] versionInLFH = Arrays.copyOfRange(data, 4, 6);
147
148 assertArrayEquals(new byte[] { 20, 0 }, versionInLFH);
149 final byte[] gpbInLFH = Arrays.copyOfRange(data, 6, 8);
150
151 assertArrayEquals(new byte[] { 8, 8 }, gpbInLFH);
152 final byte[] crcAndSizedInLFH = Arrays.copyOfRange(data, 14, 26);
153 assertArrayEquals(new byte[12], crcAndSizedInLFH);
154
155 final int cdhStart = findCentralDirectory(data);
156 final byte[] versionInCDH = Arrays.copyOfRange(data, cdhStart + 6, cdhStart + 8);
157 assertArrayEquals(new byte[] { 20, 0 }, versionInCDH);
158 final byte[] gpbInCDH = Arrays.copyOfRange(data, cdhStart + 8, cdhStart + 10);
159 assertArrayEquals(new byte[] { 8, 8 }, gpbInCDH);
160
161 final int ddStart = cdhStart - 16;
162 assertEquals(ZipLong.DD_SIG, new ZipLong(data, ddStart));
163 final long crcFromDD = ZipLong.getValue(data, ddStart + 4);
164 final long cSizeFromDD = ZipLong.getValue(data, ddStart + 8);
165 final long sizeFromDD = ZipLong.getValue(data, ddStart + 12);
166 assertEquals(3, sizeFromDD);
167
168 final long crcFromCDH = ZipLong.getValue(data, cdhStart + 16);
169 assertEquals(crcFromDD, crcFromCDH);
170 final long cSizeFromCDH = ZipLong.getValue(data, cdhStart + 20);
171 assertEquals(cSizeFromDD, cSizeFromCDH);
172 final long sizeFromCDH = ZipLong.getValue(data, cdhStart + 24);
173 assertEquals(sizeFromDD, sizeFromCDH);
174 }
175 }