blob: 52078deb55326fcd2c6227bee5cd8d96ae609a17 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.commons.compress.archivers.zip;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import org.apache.commons.compress.utils.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.apache.commons.compress.AbstractTestCase.mkdir;
import static org.apache.commons.compress.AbstractTestCase.rmdir;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
public class DataDescriptorTest {
private File dir;
@Before
public void setUp() throws Exception {
dir = mkdir("ddtest");
}
@After
public void tearDown() throws Exception {
rmdir(dir);
}
@Test
public void writesDataDescriptorForDeflatedEntryOnUnseekableOutput() throws IOException {
ByteArrayOutputStream o = new ByteArrayOutputStream();
try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(o)) {
zos.putArchiveEntry(new ZipArchiveEntry("test1.txt"));
zos.write("foo".getBytes("UTF-8"));
zos.closeArchiveEntry();
}
byte[] data = o.toByteArray();
byte[] versionInLFH = Arrays.copyOfRange(data, 4, 6);
// 2.0 because of DD
assertArrayEquals(new byte[] { 20, 0 }, versionInLFH);
byte[] gpbInLFH = Arrays.copyOfRange(data, 6, 8);
// DD and EFS flags
assertArrayEquals(new byte[] { 8, 8 }, gpbInLFH);
byte[] crcAndSizedInLFH = Arrays.copyOfRange(data, 14, 26);
assertArrayEquals(new byte[12], crcAndSizedInLFH);
int cdhStart = findCentralDirectory(data);
byte[] versionInCDH = Arrays.copyOfRange(data, cdhStart + 6, cdhStart + 8);
assertArrayEquals(new byte[] { 20, 0 }, versionInCDH);
byte[] gpbInCDH = Arrays.copyOfRange(data, cdhStart + 8, cdhStart + 10);
assertArrayEquals(new byte[] { 8, 8 }, gpbInCDH);
int ddStart = cdhStart - 16;
assertEquals(ZipLong.DD_SIG, new ZipLong(data, ddStart));
long crcFromDD = ZipLong.getValue(data, ddStart + 4);
long cSizeFromDD = ZipLong.getValue(data, ddStart + 8);
long sizeFromDD = ZipLong.getValue(data, ddStart + 12);
assertEquals(3, sizeFromDD);
long crcFromCDH = ZipLong.getValue(data, cdhStart + 16);
assertEquals(crcFromDD, crcFromCDH);
long cSizeFromCDH = ZipLong.getValue(data, cdhStart + 20);
assertEquals(cSizeFromDD, cSizeFromCDH);
long sizeFromCDH = ZipLong.getValue(data, cdhStart + 24);
assertEquals(sizeFromDD, sizeFromCDH);
}
@Test
public void doesntWriteDataDescriptorForDeflatedEntryOnSeekableOutput() throws IOException {
File f = new File(dir, "test.zip");
try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(f)) {
zos.putArchiveEntry(new ZipArchiveEntry("test1.txt"));
zos.write("foo".getBytes("UTF-8"));
zos.closeArchiveEntry();
}
byte[] data;
try (FileInputStream fis = new FileInputStream(f)) {
data = IOUtils.toByteArray(fis);
}
byte[] versionInLFH = Arrays.copyOfRange(data, 4, 6);
// still 2.0 because of Deflate
assertArrayEquals(new byte[] { 20, 0 }, versionInLFH);
byte[] gpbInLFH = Arrays.copyOfRange(data, 6, 8);
// no DD but EFS flag
assertArrayEquals(new byte[] { 0, 8 }, gpbInLFH);
int cdhStart = findCentralDirectory(data);
byte[] versionInCDH = Arrays.copyOfRange(data, cdhStart + 6, cdhStart + 8);
assertArrayEquals(new byte[] { 20, 0 }, versionInCDH);
byte[] gpbInCDH = Arrays.copyOfRange(data, cdhStart + 8, cdhStart + 10);
assertArrayEquals(new byte[] { 0, 8 }, gpbInCDH);
int ddStart = cdhStart - 16;
assertNotEquals(ZipLong.DD_SIG, new ZipLong(data, ddStart));
long crcFromLFH = ZipLong.getValue(data, 14);
long cSizeFromLFH = ZipLong.getValue(data, 18);
long sizeFromLFH = ZipLong.getValue(data, 22);
assertEquals(3, sizeFromLFH);
long crcFromCDH = ZipLong.getValue(data, cdhStart + 16);
assertEquals(crcFromLFH, crcFromCDH);
long cSizeFromCDH = ZipLong.getValue(data, cdhStart + 20);
assertEquals(cSizeFromLFH, cSizeFromCDH);
long sizeFromCDH = ZipLong.getValue(data, cdhStart + 24);
assertEquals(sizeFromLFH, sizeFromCDH);
}
@Test
public void doesntWriteDataDescriptorWhenAddingRawEntries() throws IOException {
ByteArrayOutputStream init = new ByteArrayOutputStream();
try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream(init)) {
zos.putArchiveEntry(new ZipArchiveEntry("test1.txt"));
zos.write("foo".getBytes("UTF-8"));
zos.closeArchiveEntry();
}
File f = new File(dir, "test.zip");
try (FileOutputStream fos = new FileOutputStream(f)) {
fos.write(init.toByteArray());
}
ByteArrayOutputStream o = new ByteArrayOutputStream();
ZipArchiveEntry zae;
try (ZipFile zf = new ZipFile(f);
ZipArchiveOutputStream zos = new ZipArchiveOutputStream(o)) {
zae = zf.getEntry("test1.txt");
zos.addRawArchiveEntry(zae, zf.getRawInputStream(zae));
}
byte[] data = o.toByteArray();
byte[] versionInLFH = Arrays.copyOfRange(data, 4, 6);
// still 2.0 because of Deflate
assertArrayEquals(new byte[] { 20, 0 }, versionInLFH);
byte[] gpbInLFH = Arrays.copyOfRange(data, 6, 8);
// no DD but EFS flag
assertArrayEquals(new byte[] { 0, 8 }, gpbInLFH);
int cdhStart = findCentralDirectory(data);
byte[] versionInCDH = Arrays.copyOfRange(data, cdhStart + 6, cdhStart + 8);
assertArrayEquals(new byte[] { 20, 0 }, versionInCDH);
byte[] gpbInCDH = Arrays.copyOfRange(data, cdhStart + 8, cdhStart + 10);
assertArrayEquals(new byte[] { 0, 8 }, gpbInCDH);
int ddStart = cdhStart - 16;
assertNotEquals(ZipLong.DD_SIG, new ZipLong(data, ddStart));
long crcFromLFH = ZipLong.getValue(data, 14);
long cSizeFromLFH = ZipLong.getValue(data, 18);
long sizeFromLFH = ZipLong.getValue(data, 22);
assertEquals(3, sizeFromLFH);
long crcFromCDH = ZipLong.getValue(data, cdhStart + 16);
assertEquals(crcFromLFH, crcFromCDH);
long cSizeFromCDH = ZipLong.getValue(data, cdhStart + 20);
assertEquals(cSizeFromLFH, cSizeFromCDH);
long sizeFromCDH = ZipLong.getValue(data, cdhStart + 24);
assertEquals(sizeFromLFH, sizeFromCDH);
}
private int findCentralDirectory(byte[] data) {
// not a ZIP64 archive, no comment, "End of central directory record" at the end
return (int) ZipLong.getValue(data, data.length - 22 + 16);
}
}