/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed 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 java.util.zip;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.BufferOverflowException;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import static java.util.zip.ZipOutputStream.writeIntAsUint16;
import static java.util.zip.ZipOutputStream.writeLongAsUint32;
import static java.util.zip.ZipOutputStream.writeLongAsUint64;

/**
 * @hide
 */
public class Zip64 {

    /* Non instantiable */
    private Zip64() {}

    /**
     * The maximum supported entry / archive size for standard (non zip64) entries and archives.
     *
     * @hide
     */
    public static final long MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE = 0x00000000ffffffffL;

    /**
     * The header ID of the zip64 extended info header. This value is used to identify
     * zip64 data in the "extra" field in the file headers.
     */
    private static final short ZIP64_EXTENDED_INFO_HEADER_ID = 0x0001;


    /*
     * Size (in bytes) of the zip64 end of central directory locator. This will be located
     * immediately before the end of central directory record if a given zipfile is in the
     * zip64 format.
     */
    private static final int ZIP64_LOCATOR_SIZE = 20;

    /**
     * The zip64 end of central directory locator signature (4 bytes wide).
     */
    private static final int ZIP64_LOCATOR_SIGNATURE = 0x07064b50;

    /**
     * The zip64 end of central directory record singature (4 bytes wide).
     */
    private static final int ZIP64_EOCD_RECORD_SIGNATURE = 0x06064b50;

    /**
     * The "effective" size of the zip64 eocd record. This excludes the fields that
     * are proprietary, signature, or fields we aren't interested in. We include the
     * following (contiguous) fields in this calculation :
     * - disk number (4 bytes)
     * - disk with start of central directory (4 bytes)
     * - number of central directory entries on this disk (8 bytes)
     * - total number of central directory entries (8 bytes)
     * - size of the central directory (8 bytes)
     * - offset of the start of the central directory (8 bytes)
     */
    private static final int ZIP64_EOCD_RECORD_EFFECTIVE_SIZE = 40;

    /**
     * Parses the zip64 end of central directory record locator. The locator
     * must be placed immediately before the end of central directory (eocd) record
     * starting at {@code eocdOffset}.
     *
     * The position of the file cursor for {@code raf} after a call to this method
     * is undefined an callers must reposition it after each call to this method.
     */
    public static long parseZip64EocdRecordLocator(RandomAccessFile raf, long eocdOffset)
            throws IOException {
        // The spec stays curiously silent about whether a zip file with an EOCD record,
        // a zip64 locator and a zip64 eocd record is considered "empty". In our implementation,
        // we parse all records and read the counts from them instead of drawing any size or
        // layout based information.
        if (eocdOffset > ZIP64_LOCATOR_SIZE) {
            raf.seek(eocdOffset - ZIP64_LOCATOR_SIZE);
            if (Integer.reverseBytes(raf.readInt()) == ZIP64_LOCATOR_SIGNATURE) {
                byte[] zip64EocdLocator = new byte[ZIP64_LOCATOR_SIZE  - 4];
                raf.readFully(zip64EocdLocator);
                ByteBuffer buf = ByteBuffer.wrap(zip64EocdLocator).order(ByteOrder.LITTLE_ENDIAN);

                final int diskWithCentralDir = buf.getInt();
                final long zip64EocdRecordOffset = buf.getLong();
                final int numDisks = buf.getInt();

                if (numDisks != 1 || diskWithCentralDir != 0) {
                    throw new ZipException("Spanned archives not supported");
                }

                return zip64EocdRecordOffset;
            }
        }

        return -1;
    }

    public static ZipFile.EocdRecord parseZip64EocdRecord(RandomAccessFile raf,
            long eocdRecordOffset, int commentLength) throws IOException {
        raf.seek(eocdRecordOffset);
        final int signature = Integer.reverseBytes(raf.readInt());
        if (signature != ZIP64_EOCD_RECORD_SIGNATURE) {
            throw new ZipException("Invalid zip64 eocd record offset, sig="
                    + Integer.toHexString(signature) + " offset=" + eocdRecordOffset);
        }

        // The zip64 eocd record specifies its own size as an 8 byte integral type. It is variable
        // length because of the "zip64 extensible data sector" but that field is reserved for
        // pkware's proprietary use. We therefore disregard it altogether and treat the end of
        // central directory structure as fixed length.
        //
        // We also skip "version made by" (2 bytes) and "version needed to extract" (2 bytes)
        // fields. We perform additional validation at the ZipEntry level, where applicable.
        //
        // That's a total of 12 bytes to skip
        raf.skipBytes(12);

        byte[] zip64Eocd = new byte[ZIP64_EOCD_RECORD_EFFECTIVE_SIZE];
        raf.readFully(zip64Eocd);

        ByteBuffer buf = ByteBuffer.wrap(zip64Eocd).order(ByteOrder.LITTLE_ENDIAN);
        try {
            int diskNumber = buf.getInt();
            int diskWithCentralDirStart = buf.getInt();
            long numEntries = buf.getLong();
            long totalNumEntries = buf.getLong();
            buf.getLong(); // Ignore the size of the central directory
            long centralDirOffset = buf.getLong();

            if (numEntries != totalNumEntries || diskNumber != 0 || diskWithCentralDirStart != 0) {
                throw new ZipException("Spanned archives not supported :" +
                        " numEntries=" + numEntries + ", totalNumEntries=" + totalNumEntries +
                        ", diskNumber=" + diskNumber + ", diskWithCentralDirStart=" +
                        diskWithCentralDirStart);
            }

            return new ZipFile.EocdRecord(numEntries, centralDirOffset, commentLength);
        } catch (BufferUnderflowException bue) {
            ZipException zipException = new ZipException("Error parsing zip64 eocd record.");
            zipException.initCause(bue);
            throw zipException;
        }
    }

    /**
     * Parse the zip64 extended info record from the extras present in {@code ze}.
     *
     * If {@code fromCentralDirectory} is true, we assume we're parsing a central directory
     * record. We assume a local file header otherwise. The difference between the two is that
     * a central directory entry is required to be complete, whereas a local file header isn't.
     * This is due to the presence of an optional data descriptor after the file content.
     *
     * @return {@code} true iff. a zip64 extended info record was found.
     */
    public static boolean parseZip64ExtendedInfo(ZipEntry ze, boolean fromCentralDirectory)
            throws ZipException {
        int extendedInfoSize = -1;
        int extendedInfoStart = -1;
        // If this file contains a zip64 central directory locator, entries might
        // optionally contain a zip64 extended information extra entry.
        if (ze.extra != null && ze.extra.length > 0) {
            // Extensible data fields are of the form header1+data1 + header2+data2 and so
            // on, where each header consists of a 2 byte header ID followed by a 2 byte size.
            // We need to iterate through the entire list of headers to find the header ID
            // for the zip64 extended information extra field (0x0001).
            final ByteBuffer buf = ByteBuffer.wrap(ze.extra).order(ByteOrder.LITTLE_ENDIAN);
            extendedInfoSize = getZip64ExtendedInfoSize(buf);
            if (extendedInfoSize != -1) {
                extendedInfoStart = buf.position();
                try {
                    // The size & compressed size only make sense in the central directory *or* if
                    // we know them beforehand. If we don't know them beforehand, they're stored in
                    // the data descriptor and should be read from there.
                    //
                    // Note that the spec says that the local file header "MUST" contain the
                    // original and compressed size fields. We don't care too much about that.
                    // The spec claims that the order of fields is fixed anyway.
                    if (fromCentralDirectory || (ze.getMethod() == ZipEntry.STORED)) {
                        if (ze.size == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) {
                            ze.size = buf.getLong();
                        }

                        if (ze.compressedSize == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) {
                            ze.compressedSize = buf.getLong();
                        }
                    }

                    // The local header offset is significant only in the central directory. It makes no
                    // sense within the local header itself.
                    if (fromCentralDirectory) {
                        if (ze.localHeaderRelOffset == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) {
                            ze.localHeaderRelOffset = buf.getLong();
                        }
                    }
                } catch (BufferUnderflowException bue) {
                    ZipException zipException = new ZipException("Error parsing extended info");
                    zipException.initCause(bue);
                    throw zipException;
                }
            }
        }

        // This entry doesn't contain a zip64 extended information data entry header.
        // We have to check that the compressedSize / size / localHeaderRelOffset values
        // are valid and don't require the presence of the extended header.
        if (extendedInfoSize == -1) {
            if (ze.compressedSize == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE ||
                    ze.size == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE ||
                    ze.localHeaderRelOffset == MAX_ZIP_ENTRY_AND_ARCHIVE_SIZE) {
                throw new ZipException("File contains no zip64 extended information: "
                        + "name=" + ze.name + "compressedSize=" + ze.compressedSize + ", size="
                        + ze.size + ", localHeader=" + ze.localHeaderRelOffset);
            }

            return false;
        } else {
            // If we're parsed the zip64 extended info header, we remove it from the extras
            // so that applications that set their own extras will see the data they set.

            // This is an unfortunate workaround needed due to a gap in the spec. The spec demands
            // that extras are present in the "extensible" format, which means that each extra field
            // must be prefixed with a header ID and a length. However, earlier versions of the spec
            // made no mention of this, nor did any existing API enforce it. This means users could
            // set "free form" extras without caring very much whether the implementation wanted to
            // extend or add to them.

            // The start of the extended info header.
            final int extendedInfoHeaderStart = extendedInfoStart - 4;
            // The total size of the extended info, including the header.
            final int extendedInfoTotalSize = extendedInfoSize + 4;

            final int extrasLen = ze.extra.length - extendedInfoTotalSize;
            byte[] extrasWithoutZip64 = new byte[extrasLen];

            System.arraycopy(ze.extra, 0, extrasWithoutZip64, 0, extendedInfoHeaderStart);
            System.arraycopy(ze.extra, extendedInfoHeaderStart + extendedInfoTotalSize,
                    extrasWithoutZip64, extendedInfoHeaderStart, (extrasLen - extendedInfoHeaderStart));

            ze.extra = extrasWithoutZip64;
            return true;
        }
    }

    /**
     * Appends a zip64 extended info record to the extras contained in {@code ze}. If {@code ze}
     * contains no extras, a new extras array is created.
     */
    public static void insertZip64ExtendedInfoToExtras(ZipEntry ze) throws ZipException {
        final byte[] output;
        // We always write the size, uncompressed size and local rel header offset in all our
        // Zip64 extended info headers (in both the local file header as well as the central
        // directory). We always omit the disk number because we don't support spanned
        // archives anyway.
        //
        //  2 bytes : Zip64 Extended Info Header ID
        //  2 bytes : Zip64 Extended Info Field Size.
        //  8 bytes : Uncompressed size
        //  8 bytes : Compressed size
        //  8 bytes : Local header rel offset.
        // ----------
        // 28 bytes : total
        final int extendedInfoSize = 28;

        if (ze.extra == null) {
            output = new byte[extendedInfoSize];
        } else {
            // If the existing extras are already too big, we have no choice but to throw
            // an error.
            if (ze.extra.length + extendedInfoSize > 65535) {
                throw new ZipException("No space in extras for zip64 extended entry info");
            }

            // We copy existing extras over and put the zip64 extended info at the beginning. This
            // is to avoid breakages in the presence of "old style" extras which don't contain
            // headers and lengths. The spec is again silent about these inconsistencies.
            //
            // This means that people that for ZipOutputStream users, the value ZipEntry.getExtra
            // after an entry is written will be different from before. This shouldn't be an issue
            // in practice.
            output = new byte[ze.extra.length + extendedInfoSize];
            System.arraycopy(ze.extra, 0, output,  extendedInfoSize, ze.extra.length);
        }

        ByteBuffer bb = ByteBuffer.wrap(output).order(ByteOrder.LITTLE_ENDIAN);
        bb.putShort(ZIP64_EXTENDED_INFO_HEADER_ID);
        // We subtract four because extendedInfoSize includes the ID and field
        // size itself.
        bb.putShort((short) (extendedInfoSize - 4));

        if (ze.getMethod() == ZipEntry.STORED) {
            bb.putLong(ze.size);
            bb.putLong(ze.compressedSize);
        } else {
            // Store these fields in the data descriptor instead.
            bb.putLong(0); // size.
            bb.putLong(0); // compressed size.
        }

        // The offset is only relevant in the central directory entry, but we write it out here
        // anyway, since we know what it is.
        bb.putLong(ze.localHeaderRelOffset);

        ze.extra = output;
    }

    /**
     * Returns the size of the extended info record if {@code extras} contains a zip64 extended info
     * record, {@code -1} otherwise. The buffer will be positioned at the start of the extended info
     * record.
     */
    private static int getZip64ExtendedInfoSize(ByteBuffer extras) {
        try {
            while (extras.hasRemaining()) {
                final int headerId = extras.getShort() & 0xffff;
                final int length = extras.getShort() & 0xffff;
                if (headerId == ZIP64_EXTENDED_INFO_HEADER_ID) {
                    if (extras.remaining() >= length) {
                        return length;
                    } else {
                        return -1;
                    }
                } else {
                    extras.position(extras.position() + length);
                }
            }

            return -1;
        } catch (BufferUnderflowException bue) {
            // We'll underflow if we have an incomplete header in our extras.
            return -1;
        } catch (IllegalArgumentException iae) {
            // ByteBuffer.position() will throw if we have a truncated extra or
            // an invalid length in the header.
            return -1;
        }
    }

    /**
     * Copy the size, compressed size and local header offset fields from {@code ze} to
     * inside {@code ze}'s extended info record. This is additional step is necessary when
     * we could calculate the correct sizes only after writing out the entry. In this case,
     * the local file header would not contain real sizes, and they would be present in the
     * data descriptor and the central directory only.
     *
     * We choose the simplest strategy of always writing out the size, compressedSize and
     * local header offset in all our Zip64 Extended info records.
     */
    public static void refreshZip64ExtendedInfo(ZipEntry ze) {
        if (ze.extra == null) {
            throw new IllegalStateException("Zip64 entry has no available extras: " + ze);
        }

        ByteBuffer buf = ByteBuffer.wrap(ze.extra).order(ByteOrder.LITTLE_ENDIAN);
        final int extendedInfoSize = getZip64ExtendedInfoSize(buf);
        if (extendedInfoSize == -1) {
            throw new IllegalStateException(
                    "Zip64 entry extras has no zip64 extended info record: " + ze);
        }

        try {
            buf.putLong(ze.size);
            buf.putLong(ze.compressedSize);
            buf.putLong(ze.localHeaderRelOffset);
        } catch (BufferOverflowException boe) {
            throw new IllegalStateException("Invalid extended info extra", boe);
        }
    }

    public static void writeZip64EocdRecordAndLocator(ByteArrayOutputStream baos,
            long numEntries, long offset, long cDirSize) throws IOException {
        // Step 1: Write out the zip64 EOCD record.
        writeLongAsUint32(baos, ZIP64_EOCD_RECORD_SIGNATURE);
        // The size of the zip64 eocd record. This is the effective size + the
        // size of the "version made by" (2 bytes) and the "version needed to extract" (2 bytes)
        // fields.
        writeLongAsUint64(baos, ZIP64_EOCD_RECORD_EFFECTIVE_SIZE + 4);
        // TODO: What values should we put here ? The pre-zip64 values we've chosen don't
        // seem to make much sense either.
        writeIntAsUint16(baos, 20);
        writeIntAsUint16(baos, 20);
        writeLongAsUint32(baos, 0L); // number of disk
        writeLongAsUint32(baos, 0L); // number of disk with start of central dir.
        writeLongAsUint64(baos, numEntries); // number of entries in this disk.
        writeLongAsUint64(baos, numEntries); // number of entries in total.
        writeLongAsUint64(baos, cDirSize); // size of the central directory.
        writeLongAsUint64(baos, offset); // offset of the central directory wrt. this file.

        // Step 2: Write out the zip64 EOCD record locator.
        writeLongAsUint32(baos, ZIP64_LOCATOR_SIGNATURE);
        writeLongAsUint32(baos, 0); // number of disk with start of central dir.
        writeLongAsUint64(baos, offset + cDirSize); // offset of the eocd record wrt. this file.
        writeLongAsUint32(baos, 1); // total number of disks.
    }
}
