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