/*
 * 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;

import static org.junit.Assert.*;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream; 	
import java.io.FileOutputStream; 	
import java.io.IOException; 	
import java.io.InputStream; 	
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;

import org.apache.commons.compress.AbstractTestCase;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntryPredicate;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; 	
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream; 	
import org.apache.commons.compress.archivers.zip.ZipFile; 	
import org.apache.commons.compress.archivers.zip.ZipMethod;
import org.apache.commons.compress.utils.IOUtils;
import org.junit.Assert;
import org.junit.Test;

public final class ZipTestCase extends AbstractTestCase {
    /**
     * Archives 2 files and unarchives it again. If the file length of result
     * and source is the same, it looks like the operations have worked
     * @throws Exception
     */
    @Test
    public void testZipArchiveCreation() throws Exception {
        // Archive
        final File output = new File(dir, "bla.zip");
        final File file1 = getFile("test1.xml");
        final File file2 = getFile("test2.xml");

        final OutputStream out = new FileOutputStream(output);
        ArchiveOutputStream os = null;
        try {
            os = new ArchiveStreamFactory()
                .createArchiveOutputStream("zip", out);
            os.putArchiveEntry(new ZipArchiveEntry("testdata/test1.xml"));
            IOUtils.copy(new FileInputStream(file1), os);
            os.closeArchiveEntry();

            os.putArchiveEntry(new ZipArchiveEntry("testdata/test2.xml"));
            IOUtils.copy(new FileInputStream(file2), os);
            os.closeArchiveEntry();
        } finally {
            if (os != null) {
                os.close();
            }
        }
        out.close();

        // Unarchive the same
        final List<File> results = new ArrayList<>();

        final InputStream is = new FileInputStream(output);
        ArchiveInputStream in = null;
        try {
            in = new ArchiveStreamFactory()
                .createArchiveInputStream("zip", is);

            ZipArchiveEntry entry = null;
            while((entry = (ZipArchiveEntry)in.getNextEntry()) != null) {
                final File outfile = new File(resultDir.getCanonicalPath() + "/result/" + entry.getName());
                outfile.getParentFile().mkdirs();
                final OutputStream o = new FileOutputStream(outfile);
                try {
                    IOUtils.copy(in, o);
                } finally {
                    o.close();
                }
                results.add(outfile);
            }
        } finally {
            if (in != null) {
                in.close();
            }
        }
        is.close();

        assertEquals(results.size(), 2);
        File result = results.get(0);
        assertEquals(file1.length(), result.length());
        result = results.get(1);
        assertEquals(file2.length(), result.length());
    }

    /**
     * Simple unarchive test. Asserts nothing.
     * @throws Exception
     */
    @Test
    public void testZipUnarchive() throws Exception {
        final File input = getFile("bla.zip");
        final InputStream is = new FileInputStream(input);
        final ArchiveInputStream in = new ArchiveStreamFactory().createArchiveInputStream("zip", is);
        final ZipArchiveEntry entry = (ZipArchiveEntry)in.getNextEntry();
        final OutputStream out = new FileOutputStream(new File(dir, entry.getName()));
        IOUtils.copy(in, out);
        out.close();
        in.close();
    }

    /**
     * Test case for 
     * <a href="https://issues.apache.org/jira/browse/COMPRESS-208"
     * >COMPRESS-208</a>.
     */
    @Test
    public void testSkipsPK00Prefix() throws Exception {
        final File input = getFile("COMPRESS-208.zip");
        final InputStream is = new FileInputStream(input);
        final ArrayList<String> al = new ArrayList<>();
        al.add("test1.xml");
        al.add("test2.xml");
        try {
            checkArchiveContent(new ZipArchiveInputStream(is), al);
        } finally {
            is.close();
        }
    }

    /**
     * Test case for
     * <a href="https://issues.apache.org/jira/browse/COMPRESS-93"
     * >COMPRESS-93</a>.
     */
    @Test
    public void testSupportedCompressionMethod() throws IOException {
        /*
        ZipFile bla = new ZipFile(getFile("bla.zip"));
        assertTrue(bla.canReadEntryData(bla.getEntry("test1.xml")));
        bla.close();
        */
        
        final ZipFile moby = new ZipFile(getFile("moby.zip"));
        final ZipArchiveEntry entry = moby.getEntry("README");
        assertEquals("method", ZipMethod.TOKENIZATION.getCode(), entry.getMethod());
        assertFalse(moby.canReadEntryData(entry));
        moby.close();
    }

    /**
     * Test case for being able to skip an entry in an 
     * {@link ZipArchiveInputStream} even if the compression method of that
     * entry is unsupported.
     *
     * @see <a href="https://issues.apache.org/jira/browse/COMPRESS-93"
     *        >COMPRESS-93</a>
     */
    @Test
    public void testSkipEntryWithUnsupportedCompressionMethod()
            throws IOException {
        final ZipArchiveInputStream zip =
            new ZipArchiveInputStream(new FileInputStream(getFile("moby.zip")));
        try {
            final ZipArchiveEntry entry = zip.getNextZipEntry();
            assertEquals("method", ZipMethod.TOKENIZATION.getCode(), entry.getMethod());
            assertEquals("README", entry.getName());
            assertFalse(zip.canReadEntryData(entry));
            try {
                assertNull(zip.getNextZipEntry());
            } catch (final IOException e) {
                e.printStackTrace();
                fail("COMPRESS-93: Unable to skip an unsupported zip entry");
            }
        } finally {
            zip.close();
        }
    }

    /**
     * Checks if all entries from a nested archive can be read.
     * The archive: OSX_ArchiveWithNestedArchive.zip contains:
     * NestedArchiv.zip and test.xml3.
     * 
     * The nested archive:  NestedArchive.zip contains test1.xml and test2.xml
     * 
     * @throws Exception
     */
    @Test
    public void testListAllFilesWithNestedArchive() throws Exception {
        final File input = getFile("OSX_ArchiveWithNestedArchive.zip");

        final List<String> results = new ArrayList<>();

        final InputStream is = new FileInputStream(input);
        ArchiveInputStream in = null;
        try {
            in = new ArchiveStreamFactory().createArchiveInputStream("zip", is);

            ZipArchiveEntry entry = null;
            while((entry = (ZipArchiveEntry)in.getNextEntry()) != null) {
                results.add(entry.getName());

                final ArchiveInputStream nestedIn = new ArchiveStreamFactory().createArchiveInputStream("zip", in);
                ZipArchiveEntry nestedEntry = null;
                while((nestedEntry = (ZipArchiveEntry)nestedIn.getNextEntry()) != null) {
                    results.add(nestedEntry.getName());
                }
               // nested stream must not be closed here
            }
        } finally {
            if (in != null) {
                in.close();
            }
        }
        is.close();

        results.contains("NestedArchiv.zip");
        results.contains("test1.xml");
        results.contains("test2.xml");
        results.contains("test3.xml");
    }

    @Test
    public void testDirectoryEntryFromFile() throws Exception {
        final File[] tmp = createTempDirAndFile();
        File archive = null;
        ZipArchiveOutputStream zos = null;
        ZipFile zf = null;
        try {
            archive = File.createTempFile("test.", ".zip", tmp[0]);
            archive.deleteOnExit();
            zos = new ZipArchiveOutputStream(archive);
            final long beforeArchiveWrite = tmp[0].lastModified();
            final ZipArchiveEntry in = new ZipArchiveEntry(tmp[0], "foo");
            zos.putArchiveEntry(in);
            zos.closeArchiveEntry();
            zos.close();
            zos = null;
            zf = new ZipFile(archive);
            final ZipArchiveEntry out = zf.getEntry("foo/");
            assertNotNull(out);
            assertEquals("foo/", out.getName());
            assertEquals(0, out.getSize());
            // ZIP stores time with a granularity of 2 seconds
            assertEquals(beforeArchiveWrite / 2000,
                         out.getLastModifiedDate().getTime() / 2000);
            assertTrue(out.isDirectory());
        } finally {
            ZipFile.closeQuietly(zf);
            if (zos != null) {
                zos.close();
            }
            tryHardToDelete(archive);
            tryHardToDelete(tmp[1]);
            rmdir(tmp[0]);
        }
    }

    @Test
    public void testExplicitDirectoryEntry() throws Exception {
        final File[] tmp = createTempDirAndFile();
        File archive = null;
        ZipArchiveOutputStream zos = null;
        ZipFile zf = null;
        try {
            archive = File.createTempFile("test.", ".zip", tmp[0]);
            archive.deleteOnExit();
            zos = new ZipArchiveOutputStream(archive);
            final long beforeArchiveWrite = tmp[0].lastModified();
            final ZipArchiveEntry in = new ZipArchiveEntry("foo/");
            in.setTime(beforeArchiveWrite);
            zos.putArchiveEntry(in);
            zos.closeArchiveEntry();
            zos.close();
            zos = null;
            zf = new ZipFile(archive);
            final ZipArchiveEntry out = zf.getEntry("foo/");
            assertNotNull(out);
            assertEquals("foo/", out.getName());
            assertEquals(0, out.getSize());
            assertEquals(beforeArchiveWrite / 2000,
                         out.getLastModifiedDate().getTime() / 2000);
            assertTrue(out.isDirectory());
        } finally {
            ZipFile.closeQuietly(zf);
            if (zos != null) {
                zos.close();
            }
            tryHardToDelete(archive);
            tryHardToDelete(tmp[1]);
            rmdir(tmp[0]);
        }
    }
    String first_payload = "ABBA";
    String second_payload = "AAAAAAAAAAAA";
    ZipArchiveEntryPredicate allFilesPredicate = new ZipArchiveEntryPredicate() {
        @Override
        public boolean test(final ZipArchiveEntry zipArchiveEntry) {
            return true;
        }
    };

    @Test
    public void testCopyRawEntriesFromFile()
            throws IOException {

        final File[] tmp = createTempDirAndFile();
        final File reference = createReferenceFile(tmp[0], Zip64Mode.Never, "expected.");

        final File a1 = File.createTempFile("src1.", ".zip", tmp[0]);
        final ZipArchiveOutputStream zos = new ZipArchiveOutputStream(a1);
        zos.setUseZip64(Zip64Mode.Never);
        createFirstEntry(zos).close();

        final File a2 = File.createTempFile("src2.", ".zip", tmp[0]);
        final ZipArchiveOutputStream zos1 = new ZipArchiveOutputStream(a2);
        zos1.setUseZip64(Zip64Mode.Never);
        createSecondEntry(zos1).close();

        final ZipFile zf1 = new ZipFile(a1);
        final ZipFile zf2 = new ZipFile(a2);
        final File fileResult = File.createTempFile("file-actual.", ".zip", tmp[0]);
        final ZipArchiveOutputStream zos2 = new ZipArchiveOutputStream(fileResult);
        zf1.copyRawEntries(zos2, allFilesPredicate);
        zf2.copyRawEntries(zos2, allFilesPredicate);
        zos2.close();
        // copyRawEntries does not add superfluous zip64 header like regular zip output stream
        // does when using Zip64Mode.AsNeeded so all the source material has to be Zip64Mode.Never,
        // if exact binary equality is to be achieved
        assertSameFileContents(reference, fileResult);
        zf1.close();
        zf2.close();
    }

    @Test
    public void testCopyRawZip64EntryFromFile()
            throws IOException {

        final File[] tmp = createTempDirAndFile();
        final File reference = File.createTempFile("z64reference.", ".zip", tmp[0]);
        final ZipArchiveOutputStream zos1 = new ZipArchiveOutputStream(reference);
        zos1.setUseZip64(Zip64Mode.Always);
        createFirstEntry(zos1);
        zos1.close();

        final File a1 = File.createTempFile("zip64src.", ".zip", tmp[0]);
        final ZipArchiveOutputStream zos = new ZipArchiveOutputStream(a1);
        zos.setUseZip64(Zip64Mode.Always);
        createFirstEntry(zos).close();

        final ZipFile zf1 = new ZipFile(a1);
        final File fileResult = File.createTempFile("file-actual.", ".zip", tmp[0]);
        final ZipArchiveOutputStream zos2 = new ZipArchiveOutputStream(fileResult);
        zos2.setUseZip64(Zip64Mode.Always);
        zf1.copyRawEntries(zos2, allFilesPredicate);
        zos2.close();
        assertSameFileContents(reference, fileResult);
        zf1.close();
    }

    @Test
    public void testUnixModeInAddRaw() throws IOException {

        final File[] tmp = createTempDirAndFile();

        final File a1 = File.createTempFile("unixModeBits.", ".zip", tmp[0]);
        final ZipArchiveOutputStream zos = new ZipArchiveOutputStream(a1);

        final ZipArchiveEntry archiveEntry = new ZipArchiveEntry("fred");
        archiveEntry.setUnixMode(0664);
        archiveEntry.setMethod(ZipEntry.DEFLATED);
        zos.addRawArchiveEntry(archiveEntry, new ByteArrayInputStream("fud".getBytes()));
        zos.close();

        final ZipFile zf1 = new ZipFile(a1);
        final ZipArchiveEntry fred = zf1.getEntry("fred");
        assertEquals(0664, fred.getUnixMode());
        zf1.close();
    }

    private File createReferenceFile(final File directory, final Zip64Mode zipMode, final String prefix) throws IOException {
        final File reference = File.createTempFile(prefix, ".zip", directory);
        final ZipArchiveOutputStream zos = new ZipArchiveOutputStream(reference);
        zos.setUseZip64(zipMode);
        createFirstEntry(zos);
        createSecondEntry(zos);
        zos.close();
        return reference;
    }

    private ZipArchiveOutputStream createFirstEntry(final ZipArchiveOutputStream zos) throws IOException {
        createArchiveEntry(first_payload, zos, "file1.txt");
        return zos;
    }

    private ZipArchiveOutputStream createSecondEntry(final ZipArchiveOutputStream zos) throws IOException {
        createArchiveEntry(second_payload, zos, "file2.txt");
        return zos;
    }


    private void assertSameFileContents(final File expectedFile, final File actualFile) throws IOException {
        final int size = (int) Math.max(expectedFile.length(), actualFile.length());
        final ZipFile expected = new ZipFile(expectedFile);
        final ZipFile actual = new ZipFile(actualFile);
        final byte[] expectedBuf = new byte[size];
        final byte[] actualBuf = new byte[size];

        final Enumeration<ZipArchiveEntry> actualInOrder = actual.getEntriesInPhysicalOrder();
        final Enumeration<ZipArchiveEntry> expectedInOrder = expected.getEntriesInPhysicalOrder();

        while (actualInOrder.hasMoreElements()){
            final ZipArchiveEntry actualElement = actualInOrder.nextElement();
            final ZipArchiveEntry expectedElement = expectedInOrder.nextElement();
            assertEquals( expectedElement.getName(), actualElement.getName());
            // Don't compare timestamps since they may vary;
            // there's no support for stubbed out clock (TimeSource) in ZipArchiveOutputStream
            assertEquals( expectedElement.getMethod(), actualElement.getMethod());
            assertEquals( expectedElement.getGeneralPurposeBit(), actualElement.getGeneralPurposeBit());
            assertEquals( expectedElement.getCrc(), actualElement.getCrc());
            assertEquals( expectedElement.getCompressedSize(), actualElement.getCompressedSize());
            assertEquals( expectedElement.getSize(), actualElement.getSize());
            assertEquals( expectedElement.getExternalAttributes(), actualElement.getExternalAttributes());
            assertEquals( expectedElement.getInternalAttributes(), actualElement.getInternalAttributes());

            final InputStream actualIs = actual.getInputStream(actualElement);
            final InputStream expectedIs = expected.getInputStream(expectedElement);
            IOUtils.readFully(expectedIs, expectedBuf);
            IOUtils.readFully(actualIs, actualBuf);
            expectedIs.close();
            actualIs.close();
            Assert.assertArrayEquals(expectedBuf, actualBuf); // Buffers are larger than payload. dont care
        }

        expected.close();
        actual.close();
    }


    private void createArchiveEntry(final String payload, final ZipArchiveOutputStream zos, final String name)
            throws IOException {
        final ZipArchiveEntry in = new ZipArchiveEntry(name);
        zos.putArchiveEntry(in);

        zos.write(payload.getBytes());
        zos.closeArchiveEntry();
    }

    @Test
    public void testFileEntryFromFile() throws Exception {
        final File[] tmp = createTempDirAndFile();
        File archive = null;
        ZipArchiveOutputStream zos = null;
        ZipFile zf = null;
        FileInputStream fis = null;
        try {
            archive = File.createTempFile("test.", ".zip", tmp[0]);
            archive.deleteOnExit();
            zos = new ZipArchiveOutputStream(archive);
            final ZipArchiveEntry in = new ZipArchiveEntry(tmp[1], "foo");
            zos.putArchiveEntry(in);
            final byte[] b = new byte[(int) tmp[1].length()];
            fis = new FileInputStream(tmp[1]);
            while (fis.read(b) > 0) {
                zos.write(b);
            }
            fis.close();
            fis = null;
            zos.closeArchiveEntry();
            zos.close();
            zos = null;
            zf = new ZipFile(archive);
            final ZipArchiveEntry out = zf.getEntry("foo");
            assertNotNull(out);
            assertEquals("foo", out.getName());
            assertEquals(tmp[1].length(), out.getSize());
            assertEquals(tmp[1].lastModified() / 2000,
                         out.getLastModifiedDate().getTime() / 2000);
            assertFalse(out.isDirectory());
        } finally {
            ZipFile.closeQuietly(zf);
            if (zos != null) {
                zos.close();
            }
            tryHardToDelete(archive);
            if (fis != null) {
                fis.close();
            }
            tryHardToDelete(tmp[1]);
            rmdir(tmp[0]);
        }
    }

    @Test
    public void testExplicitFileEntry() throws Exception {
        final File[] tmp = createTempDirAndFile();
        File archive = null;
        ZipArchiveOutputStream zos = null;
        ZipFile zf = null;
        FileInputStream fis = null;
        try {
            archive = File.createTempFile("test.", ".zip", tmp[0]);
            archive.deleteOnExit();
            zos = new ZipArchiveOutputStream(archive);
            final ZipArchiveEntry in = new ZipArchiveEntry("foo");
            in.setTime(tmp[1].lastModified());
            in.setSize(tmp[1].length());
            zos.putArchiveEntry(in);
            final byte[] b = new byte[(int) tmp[1].length()];
            fis = new FileInputStream(tmp[1]);
            while (fis.read(b) > 0) {
                zos.write(b);
            }
            fis.close();
            fis = null;
            zos.closeArchiveEntry();
            zos.close();
            zos = null;
            zf = new ZipFile(archive);
            final ZipArchiveEntry out = zf.getEntry("foo");
            assertNotNull(out);
            assertEquals("foo", out.getName());
            assertEquals(tmp[1].length(), out.getSize());
            assertEquals(tmp[1].lastModified() / 2000,
                         out.getLastModifiedDate().getTime() / 2000);
            assertFalse(out.isDirectory());
        } finally {
            ZipFile.closeQuietly(zf);
            if (zos != null) {
                zos.close();
            }
            tryHardToDelete(archive);
            if (fis != null) {
                fis.close();
            }
            tryHardToDelete(tmp[1]);
            rmdir(tmp[0]);
        }
    }
}
