/*
 * 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.Serializable;
import java.math.BigInteger;
import java.util.zip.ZipException;

import static org.apache.commons.compress.archivers.zip.ZipUtil.reverse;
import static org.apache.commons.compress.archivers.zip.ZipUtil.signedByteToUnsignedInt;
import static org.apache.commons.compress.archivers.zip.ZipUtil.unsignedIntToSignedByte;

/**
 * An extra field that stores UNIX UID/GID data (owner &amp; group ownership) for a given
 * zip entry.  We're using the field definition given in Info-Zip's source archive:
 * zip-3.0.tar.gz/proginfo/extrafld.txt
 *
 * <pre>
 * Local-header version:
 *
 * Value         Size        Description
 * -----         ----        -----------
 * 0x7875        Short       tag for this extra block type ("ux")
 * TSize         Short       total data size for this block
 * Version       1 byte      version of this extra field, currently 1
 * UIDSize       1 byte      Size of UID field
 * UID           Variable    UID for this entry (little endian)
 * GIDSize       1 byte      Size of GID field
 * GID           Variable    GID for this entry (little endian)
 *
 * Central-header version:
 *
 * Value         Size        Description
 * -----         ----        -----------
 * 0x7855        Short       tag for this extra block type ("Ux")
 * TSize         Short       total data size for this block (0)
 * </pre>
 * @since 1.5
 */
public class X7875_NewUnix implements ZipExtraField, Cloneable, Serializable {
    private static final ZipShort HEADER_ID = new ZipShort(0x7875);
    private static final ZipShort ZERO = new ZipShort(0);
    private static final BigInteger ONE_THOUSAND = BigInteger.valueOf(1000);
    private static final long serialVersionUID = 1L;

    private int version = 1; // always '1' according to current info-zip spec.

    // BigInteger helps us with little-endian / big-endian conversions.
    // (thanks to BigInteger.toByteArray() and a reverse() method we created).
    // Also, the spec theoretically allows UID/GID up to 255 bytes long!
    //
    // NOTE:  equals() and hashCode() currently assume these can never be null.
    private BigInteger uid;
    private BigInteger gid;

    /**
     * Constructor for X7875_NewUnix.
     */
    public X7875_NewUnix() {
        reset();
    }

    /**
     * The Header-ID.
     *
     * @return the value for the header id for this extrafield
     */
    @Override
    public ZipShort getHeaderId() {
        return HEADER_ID;
    }

    /**
     * Gets the UID as a long.  UID is typically a 32 bit unsigned
     * value on most UNIX systems, so we return a long to avoid
     * integer overflow into the negatives in case values above
     * and including 2^31 are being used.
     *
     * @return the UID value.
     */
    public long getUID() { return ZipUtil.bigToLong(uid); }

    /**
     * Gets the GID as a long.  GID is typically a 32 bit unsigned
     * value on most UNIX systems, so we return a long to avoid
     * integer overflow into the negatives in case values above
     * and including 2^31 are being used.
     *
     * @return the GID value.
     */
    public long getGID() { return ZipUtil.bigToLong(gid); }

    /**
     * Sets the UID.
     *
     * @param l UID value to set on this extra field.
     */
    public void setUID(long l) {
        this.uid = ZipUtil.longToBig(l);
    }

    /**
     * Sets the GID.
     *
     * @param l GID value to set on this extra field.
     */
    public void setGID(long l) {
        this.gid = ZipUtil.longToBig(l);
    }

    /**
     * Length of the extra field in the local file data - without
     * Header-ID or length specifier.
     *
     * @return a <code>ZipShort</code> for the length of the data of this extra field
     */
    @Override
    public ZipShort getLocalFileDataLength() {
        int uidSize = trimLeadingZeroesForceMinLength(uid.toByteArray()).length;
        int gidSize = trimLeadingZeroesForceMinLength(gid.toByteArray()).length;

        // The 3 comes from:  version=1 + uidsize=1 + gidsize=1
        return new ZipShort(3 + uidSize + gidSize);
    }

    /**
     * Length of the extra field in the central directory data - without
     * Header-ID or length specifier.
     *
     * @return a <code>ZipShort</code> for the length of the data of this extra field
     */
    @Override
    public ZipShort getCentralDirectoryLength() {
        return ZERO;
    }

    /**
     * The actual data to put into local file data - without Header-ID
     * or length specifier.
     *
     * @return get the data
     */
    @Override
    public byte[] getLocalFileDataData() {
        byte[] uidBytes = uid.toByteArray();
        byte[] gidBytes = gid.toByteArray();

        // BigInteger might prepend a leading-zero to force a positive representation
        // (e.g., so that the sign-bit is set to zero).  We need to remove that
        // before sending the number over the wire.
        uidBytes = trimLeadingZeroesForceMinLength(uidBytes);
        gidBytes = trimLeadingZeroesForceMinLength(gidBytes);

        // Couldn't bring myself to just call getLocalFileDataLength() when we've
        // already got the arrays right here.  Yeah, yeah, I know, premature
        // optimization is the root of all...
        //
        // The 3 comes from:  version=1 + uidsize=1 + gidsize=1
        byte[] data = new byte[3 + uidBytes.length + gidBytes.length];

        // reverse() switches byte array from big-endian to little-endian.
        reverse(uidBytes);
        reverse(gidBytes);

        int pos = 0;
        data[pos++] = unsignedIntToSignedByte(version);
        data[pos++] = unsignedIntToSignedByte(uidBytes.length);
        System.arraycopy(uidBytes, 0, data, pos, uidBytes.length);
        pos += uidBytes.length;
        data[pos++] = unsignedIntToSignedByte(gidBytes.length);
        System.arraycopy(gidBytes, 0, data, pos, gidBytes.length);
        return data;
    }

    /**
     * The actual data to put into central directory data - without Header-ID
     * or length specifier.
     *
     * @return get the data
     */
    @Override
    public byte[] getCentralDirectoryData() {
        return new byte[0];
    }

    /**
     * Populate data from this array as if it was in local file data.
     *
     * @param data   an array of bytes
     * @param offset the start offset
     * @param length the number of bytes in the array from offset
     * @throws java.util.zip.ZipException on error
     */
    @Override
    public void parseFromLocalFileData(
            byte[] data, int offset, int length
    ) throws ZipException {
        reset();
        this.version = signedByteToUnsignedInt(data[offset++]);
        int uidSize = signedByteToUnsignedInt(data[offset++]);
        byte[] uidBytes = new byte[uidSize];
        System.arraycopy(data, offset, uidBytes, 0, uidSize);
        offset += uidSize;
        this.uid = new BigInteger(1, reverse(uidBytes)); // sign-bit forced positive

        int gidSize = signedByteToUnsignedInt(data[offset++]);
        byte[] gidBytes = new byte[gidSize];
        System.arraycopy(data, offset, gidBytes, 0, gidSize);
        this.gid = new BigInteger(1, reverse(gidBytes)); // sign-bit forced positive
    }

    /**
     * Doesn't do anything since this class doesn't store anything
     * inside the central directory.
     */
    @Override
    public void parseFromCentralDirectoryData(
            byte[] buffer, int offset, int length
    ) throws ZipException {
    }

    /**
     * Reset state back to newly constructed state.  Helps us make sure
     * parse() calls always generate clean results.
     */
    private void reset() {
        // Typical UID/GID of the first non-root user created on a unix system.
        uid = ONE_THOUSAND;
        gid = ONE_THOUSAND;
    }

    /**
     * Returns a String representation of this class useful for
     * debugging purposes.
     *
     * @return A String representation of this class useful for
     *         debugging purposes.
     */
    @Override
    public String toString() {
        return "0x7875 Zip Extra Field: UID=" + uid + " GID=" + gid;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    @Override
    public boolean equals(Object o) {
        if (o instanceof X7875_NewUnix) {
            X7875_NewUnix xf = (X7875_NewUnix) o;
            // We assume uid and gid can never be null.
            return version == xf.version && uid.equals(xf.uid) && gid.equals(xf.gid);
        }
        return false;
    }

    @Override
    public int hashCode() {
        int hc = -1234567 * version;
        // Since most UID's and GID's are below 65,536, this is (hopefully!)
        // a nice way to make sure typical UID and GID values impact the hash
        // as much as possible.
        hc ^= Integer.rotateLeft(uid.hashCode(), 16);
        hc ^= gid.hashCode();
        return hc;
    }

    /**
     * Not really for external usage, but marked "package" visibility
     * to help us JUnit it.   Trims a byte array of leading zeroes while
     * also enforcing a minimum length, and thus it really trims AND pads
     * at the same time.
     *
     * @param array byte[] array to trim & pad.
     * @return trimmed & padded byte[] array.
     */
    static byte[] trimLeadingZeroesForceMinLength(byte[] array) {
        if (array == null) {
            return array;
        }

        int pos = 0;
        for (byte b : array) {
            if (b == 0) {
                pos++;
            } else {
                break;
            }
        }

        /*

        I agonized over my choice of MIN_LENGTH=1.  Here's the situation:
        InfoZip (the tool I am using to test interop) always sets these
        to length=4.  And so a UID of 0 (typically root) for example is
        encoded as {4,0,0,0,0} (len=4, 32 bits of zero), when it could just
        as easily be encoded as {1,0} (len=1, 8 bits of zero) according to
        the spec.

        In the end I decided on MIN_LENGTH=1 for four reasons:

        1.)  We are adhering to the spec as far as I can tell, and so
             a consumer that cannot parse this is broken.

        2.)  Fundamentally, zip files are about shrinking things, so
             let's save a few bytes per entry while we can.

        3.)  Of all the people creating zip files using commons-
             compress, how many care about UNIX UID/GID attributes
             of the files they store?   (e.g., I am probably thinking
             way too hard about this and no one cares!)

        4.)  InfoZip's tool, even though it carefully stores every UID/GID
             for every file zipped on a unix machine (by default) currently
             appears unable to ever restore UID/GID.
             unzip -X has no effect on my machine, even when run as root!!!!

        And thus it is decided:  MIN_LENGTH=1.

        If anyone runs into interop problems from this, feel free to set
        it to MIN_LENGTH=4 at some future time, and then we will behave
        exactly like InfoZip (requires changes to unit tests, though).

        And I am sorry that the time you spent reading this comment is now
        gone and you can never have it back.

        */
        final int MIN_LENGTH = 1;

        byte[] trimmedArray = new byte[Math.max(MIN_LENGTH, array.length - pos)];
        int startPos = trimmedArray.length - (array.length - pos);
        System.arraycopy(array, pos, trimmedArray, startPos, trimmedArray.length - startPos);
        return trimmedArray;
    }
}
