All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.reandroid.archive.block.EndRecord Maven / Gradle / Ivy

/*
 *  Copyright (C) 2022 github.com/REAndroid
 *
 *  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 com.reandroid.archive.block;

import com.reandroid.archive.ArchiveException;
import com.reandroid.archive.ZipSignature;
import com.reandroid.archive.io.ZipInput;
import com.reandroid.utils.HexUtil;

import java.io.IOException;
import java.io.InputStream;

public class EndRecord extends ZipHeader{
    private Zip64Locator zip64Locator;
    private Zip64Record zip64Record;
    public EndRecord() {
        super(MIN_LENGTH, ZipSignature.END_RECORD);
    }

    public int getTotalBytesCount(){
        int count = countBytes();
        ZipHeader zipHeader = getZip64Locator();
        if(zipHeader != null){
            count += zip64Locator.countBytes();
        }
        zipHeader = getZip64Record();
        if(zipHeader != null){
            count += zip64Locator.countBytes();
        }
        return count;
    }
    private boolean isZip64Value(){
        return getInteger(OFFSET_offsetOfCentralDirectory) == 0xffffffff;
    }
    public Zip64Locator getZip64Locator(){
        return zip64Locator;
    }
    public void setZip64Locator(Zip64Locator zip64Locator){
        this.zip64Locator = zip64Locator;
    }
    public Zip64Record getZip64Record(){
        return zip64Record;
    }
    public void setZip64Record(Zip64Record zip64Record){
        this.zip64Record = zip64Record;
    }
    public void findEndRecord(ZipInput zipInput) throws IOException {
        byte[] footer = zipInput.getFooter(SignatureFooter.MIN_SIZE + EndRecord.MAX_LENGTH);
        findEndRecord(footer);
        Zip64Locator zip64Locator = getZip64Locator();
        if(zip64Locator == null){
            return;
        }
        Zip64Record zip64Record = new Zip64Record();
        InputStream inputStream = zipInput.getInputStream(zip64Locator.getOffsetZip64Record(),
                Zip64Record.MAX_LENGTH);
        zip64Record.readBytes(inputStream);
        if(!zip64Record.isValidSignature()){
            throw new IOException("Invalid " + ZipSignature.ZIP64_RECORD + ": "
                    + HexUtil.toHex8(zip64Record.getSignatureValue()));
        }
        setZip64Record(zip64Record);
    }
    public void findEndRecord(byte[] footer) throws IOException {
        int length = footer.length;
        int minLength = EndRecord.MIN_LENGTH;
        int start = length - minLength;
        int offset = 0;
        for(offset = start; offset >= 0; offset--){
            putBytes(footer, offset, 0, minLength);
            if(isValidSignature()){
                break;
            }
        }
        if(!isValidSignature()){
            throw new ArchiveException("Failed to find end record");
        }
        if(!isZip64Value()){
            return;
        }
        Zip64Locator zip64Locator = new Zip64Locator();
        minLength = Zip64Locator.MIN_LENGTH;
        offset = offset - minLength;
        while (offset >= 0){
            zip64Locator.putBytes(footer, offset, 0, minLength);
            if(zip64Locator.isValidSignature()){
                break;
            }
            offset--;
        }
        if(!zip64Locator.isValidSignature()){
            throw new ArchiveException("Failed to find zip64 locator");
        }
        setZip64Locator(zip64Locator);
    }


    public int getNumberOfDisk(){
        return getShortUnsigned(OFFSET_numberOfDisk);
    }
    public void setNumberOfDisk(int value){
        putShort(OFFSET_numberOfDisk, value);
    }
    public int getCentralDirectoryStartDisk(){
        return getShortUnsigned(OFFSET_centralDirectoryStartDisk);
    }
    public void setCentralDirectoryStartDisk(int value){
        putShort(OFFSET_centralDirectoryStartDisk, value);
    }
    public int getNumberOfDirectories(){
        return getShortUnsigned(OFFSET_numberOfDirectories);
    }
    public void setNumberOfDirectories(int value){
        putShort(OFFSET_numberOfDirectories, value);
        Zip64Record zip64Record = getZip64Record();
        if(zip64Record != null){
            zip64Record.setNumberOfCDRecords(value);
        }
    }
    public int getTotalNumberOfDirectories(){
        return getShortUnsigned(OFFSET_totalNumberOfDirectories);
    }
    public void setTotalNumberOfDirectories(int value){
        putShort(OFFSET_totalNumberOfDirectories, value);
        Zip64Record zip64Record = getZip64Record();
        if(zip64Record != null){
            zip64Record.setTotalCDRecords(value);
        }
    }
    public long getLengthOfCentralDirectory(){
        return getIntegerUnsigned(OFFSET_lengthOfCentralDirectory);
    }
    public void setLengthOfCentralDirectory(long value){
        putInteger(OFFSET_lengthOfCentralDirectory, value);
        Zip64Record zip64Record = getZip64Record();
        if(zip64Record != null){
            zip64Record.setSizeOfCD(value);
        }
    }
    public long getOffsetOfCentralDirectory(){
        Zip64Record zip64Record = getZip64Record();
        if(zip64Record != null){
            return zip64Record.getOffsetOfCentralDirectory();
        }
        return getIntegerUnsigned(OFFSET_offsetOfCentralDirectory);
    }
    public void setOffsetOfCentralDirectory(long value){
        if((value & 0xffffffff00000000L) == 0){
            putInteger(OFFSET_offsetOfCentralDirectory, value);
            this.zip64Locator = null;
            this.zip64Record = null;
        }else {
            Zip64Record zip64Record = this.zip64Record;
            if(zip64Record == null){
                zip64Record = Zip64Record.newZip64Record();
                this.zip64Record = zip64Record;
            }
            putInteger(OFFSET_offsetOfCentralDirectory, -1);
            zip64Record.setOffsetOfCentralDirectory(value);
            Zip64Locator zip64Locator = this.zip64Locator;
            if(zip64Locator == null){
                zip64Locator = Zip64Locator.newZip64Locator();
                this.zip64Locator = zip64Locator;
            }
        }
    }
    public int getLastShort(){
        return getShortUnsigned(OFFSET_lastShort);
    }
    public void getLastShort(int value){
        putShort(OFFSET_lastShort, value);
    }


    @Override
    public String toString(){
        if(countBytes()© 2015 - 2025 Weber Informatics LLC | Privacy Policy