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

dorkbox.cabParser.structure.CabHeader Maven / Gradle / Ivy

Go to download

Parse and extract data from inside Microsoft .cab files, specifically those compressed with LZX, for java.

There is a newer version: 3.4
Show newest version
/*
 * Copyright 2012 dorkbox, llc
 *
 * 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 dorkbox.cabParser.structure;

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

import dorkbox.cabParser.CabException;
import dorkbox.cabParser.CorruptCabException;
import dorkbox.util.bytes.LittleEndian;
import dorkbox.cabParser.CabStreamSaver;

public final class CabHeader implements CabConstants {

    /** reserved , 4 bytes */
    public long reserved1;
    /** size of this cabinet file in bytes , 4 bytes */
    public long cbCabinet;
    /** reserved, 4 bytes */
    public long reserved2;
    /** offset of the first CFFILE entry , 4 bytes */
    public long coffFiles;
    /** reserved, 4 bytes*/
    public long reserved3;

    /** cabinet file format version, minor/major , 1 bytes*2 */
    public int version;

    /** number of CFFOLDER entries in this cabinet , 2 bytes */
    public int cFolders;
    /** number of CFFILE entries in this cabinet , 2 bytes */
    public int cFiles;

    /** cabinet file option indicators , 2 bytes */
    public int flags;
    /** must be the same for all cabinets in a set , 2 bytes */
    public int setID;
    /** number of this cabinet file in a set , 2 bytes */
    public int iCabinet;

    /** (optional) size of per-cabinet reserved area , 2 bytes */
    public int cbCFHeader = 0;
    /** (optional) size of per-folder reserved area , 1 bytes */
    public int cbCFFolder = 0;
    /** (optional) size of per-datablock reserved area , 1 bytes */
    public int cbCFData = 0;

    /** (optional) per-cabinet reserved area , 1*n bytes */
    //final short abReserve[];

    /** (optional) name of previous cabinet file , 1*n bytes */
    //final String szCabinetPrev;

    /** (optional) name of previous disk , 1*n bytes */
    //final String szDiskPrev;

    /** (optional) name of next cabinet file , 1*n bytes */
    //final String szCabinetNext;

    /** (optional) name of next disk , 1*n bytes */
    //final String szDiskNext;


    private CabStreamSaver decoder;

    public CabHeader(CabStreamSaver paramCabDecoderInterface) {
        this.decoder = paramCabDecoderInterface;
    }

    public void read(InputStream input) throws IOException, CabException {
        int i = input.read();
        int j = input.read();
        int k = input.read();
        int m = input.read();
        // MSCF
        if (i != 77 || j != 83 || k != 67 || m != 70) {
            throw new CorruptCabException("Missing header signature");
        }

        this.reserved1 = LittleEndian.UInt_.from(input).longValue();
        this.cbCabinet = LittleEndian.UInt_.from(input).longValue();
        this.reserved2 = LittleEndian.UInt_.from(input).longValue();
        this.coffFiles = LittleEndian.UInt_.from(input).longValue();
        this.reserved3 = LittleEndian.UInt_.from(input).longValue();


        // Currently, versionMajor = 1 and versionMinor = 3
        this.version = LittleEndian.UShort_.from(input).intValue();
        this.cFolders = LittleEndian.UShort_.from(input).intValue();
        this.cFiles = LittleEndian.UShort_.from(input).intValue();
        this.flags = LittleEndian.UShort_.from(input).intValue();
        this.setID = LittleEndian.UShort_.from(input).intValue();
        this.iCabinet = LittleEndian.UShort_.from(input).intValue();



        if ((this.flags & FLAG_RESERVE_PRESENT) == FLAG_RESERVE_PRESENT) {
            this.cbCFHeader = LittleEndian.UShort_.from(input).intValue();
            this.cbCFFolder = input.read();
            this.cbCFData = input.read();
        }

        if ((this.flags & FLAG_PREV_CABINET) == FLAG_PREV_CABINET ||
            (this.flags & FLAG_NEXT_CABINET) == FLAG_NEXT_CABINET) {
            throw new CabException("Spanned cabinets not supported");
        }

        // not supported
//        if (prevCabinet()) {
//            szCabinetPrev = bytes.readString(false);
//            szDiskPrev = bytes.readString(false);
//        } else {
//            szCabinetPrev = null;
//            szDiskPrev = null;
//        }
//
//        if (nextCabinet()) {
//            szCabinetNext = bytes.readString(false);
//            szDiskNext = bytes.readString(false);
//        } else {
//            szCabinetNext = null;
//            szDiskNext = null;
//        }

        if (this.cbCFHeader != 0) {
            if (this.decoder.saveReservedAreaData(null, this.cbCFHeader) == true) {
                byte[] data = new byte[this.cbCFHeader];

                if (this.cbCFHeader != 0) {
                    int readTotal = 0;
                    while (readTotal < this.cbCFHeader) {
                        int read = input.read(data, readTotal, this.cbCFHeader - readTotal);
                        if (read < 0) {
                            throw new EOFException();
                        }
                        readTotal += read;
                    }
                }

                this.decoder.saveReservedAreaData(data, this.cbCFHeader);
                return;
            }

            input.skip(this.cbCFHeader);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy