    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one
    003     * or more contributor license agreements.  See the NOTICE file
    004     * distributed with this work for additional information
    005     * regarding copyright ownership.  The ASF licenses this file
    006     * to you under the Apache License, Version 2.0 (the
    007     * "License"); you may not use this file except in compliance
    008     * with the License.  You may obtain a copy of the License at
    009     *
    010     * http://www.apache.org/licenses/LICENSE-2.0
    011     *
    012     * Unless required by applicable law or agreed to in writing,
    013     * software distributed under the License is distributed on an
    014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015     * KIND, either express or implied.  See the License for the
    016     * specific language governing permissions and limitations
    017     * under the License.
    018     */
    019    package org.apache.commons.compress.archivers.zip;
    020
    021    /**
    022     * Wrapper for extra field data that doesn't conform to the recommended format of header-tag + size + data.
    023     *
    024     * <p>The header-id is artificial (and not listed as a known ID in
    025     * {@link <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
    026     * APPNOTE.TXT</a>}).  Since it isn't used anywhere except to satisfy the
    027     * ZipExtraField contract it shouldn't matter anyway.</p>
    028     *
    029     * @since Apache Commons Compress 1.1
    030     * @NotThreadSafe
    031     */
    032    public final class UnparseableExtraFieldData implements ZipExtraField {
    033        private static final ZipShort HEADER_ID = new ZipShort(0xACC1);
    034
    035        private byte[] localFileData;
    036        private byte[] centralDirectoryData;
    037
    038        /**
    039         * The Header-ID.
    040         *
    041         * @return a completely arbitrary value that should be ignored.
    042         */
    043        public ZipShort getHeaderId() {
    044            return HEADER_ID;
    045        }
    046
    047        /**
    048         * Length of the complete extra field in the local file data.
    049         *
    050         * @return The LocalFileDataLength value
    051         */
    052        public ZipShort getLocalFileDataLength() {
    053            return new ZipShort(localFileData == null ? 0 : localFileData.length);
    054        }
    055
    056        /**
    057         * Length of the complete extra field in the central directory.
    058         *
    059         * @return The CentralDirectoryLength value
    060         */
    061        public ZipShort getCentralDirectoryLength() {
    062            return centralDirectoryData == null
    063                ? getLocalFileDataLength()
    064                : new ZipShort(centralDirectoryData.length);
    065        }
    066
    067        /**
    068         * The actual data to put into local file data.
    069         *
    070         * @return The LocalFileDataData value
    071         */
    072        public byte[] getLocalFileDataData() {
    073            return ZipUtil.copy(localFileData);
    074        }
    075
    076        /**
    077         * The actual data to put into central directory.
    078         *
    079         * @return The CentralDirectoryData value
    080         */
    081        public byte[] getCentralDirectoryData() {
    082            return centralDirectoryData == null
    083                ? getLocalFileDataData() : ZipUtil.copy(centralDirectoryData);
    084        }
    085
    086        /**
    087         * Populate data from this array as if it was in local file data.
    088         *
    089         * @param buffer the buffer to read data from
    090         * @param offset offset into buffer to read data
    091         * @param length the length of data
    092         */
    093        public void parseFromLocalFileData(byte[] buffer, int offset, int length) {
    094            localFileData = new byte[length];
    095            System.arraycopy(buffer, offset, localFileData, 0, length);
    096        }
    097
    098        /**
    099         * Populate data from this array as if it was in central directory data.
    100         *
    101         * @param buffer the buffer to read data from
    102         * @param offset offset into buffer to read data
    103         * @param length the length of data
    104         */
    105        public void parseFromCentralDirectoryData(byte[] buffer, int offset,
    106                                                  int length) {
    107            centralDirectoryData = new byte[length];
    108            System.arraycopy(buffer, offset, centralDirectoryData, 0, length);
    109            if (localFileData == null) {
    110                parseFromLocalFileData(buffer, offset, length);
    111            }
    112        }
    113
    114    }