// Detect It Easy: detection rule file format
// Authors: hypn0 <hypn0@mail.ru>, Kaens (TG@kaens), LinXP

init("archive", "");

function detect(bShowType, bShowVersion, bShowOptions) {
    if (Binary.compare("a596fdff")) {
        bDetected = true;
        sName = "FTCOMP";
    } else if (Binary.compare("aced00057704")) {
        bDetected = true;
        sName = "IzPack";
    } else if (Binary.compare("'bvxn'")) {
        bDetected = true;
        sName = "LZFSE";
    } else if (Binary.compare("'SIT!'")) {
        bDetected = true;
        sName = "SIT";
    } else if (Binary.compare("06'SKF3.0'")) {
        bDetected = true;
        sName = "SKF";
    } else if (Binary.compare("'Archive'00................2800000064")) {
        bDetected = true;
        sName = "ArcFS";
    } else if (Binary.compare("'ARCV'0002")) {
        bDetected = true;
        sName = "ARCV 2";
    } else if (Binary.compare("09006bea")) {
        bDetected = true;
        sName = "BFF";
    } else if (Binary.compare("00069a68")) {
        bDetected = true;
        sName = "DCL";
    } else if (Binary.compare("....'-lh'..2d") || Binary.compare("....'-lz'..2d")) {
        sVersion = Binary.getString(2, 5)
        bDetected = true;
        switch (Binary.getString(3, 3)) {
            case "lh0":
            case "lh1":
            case "lh2":
            case "lh3":
            case "lh4":
            case "lh5":
            case "lh6":
            case "lh7":
            case "lhd":
                sName = "LHA archive (.LHA)";
                break;
            case "lh8":
            case "lh9":
            case "lha":
            case "lhb":
            case "lhc":
            case "lhe":
                sName = "LHA archive, Joe Jared ext (.LHA)";
                break;
            case "lhx":
                sName = "LHA archive, UNLHA32 ext (.LHA)";
                break;
            case "lzs":
            case "lz2":
            case "lz3":
            case "lz4":
            case "lz5":
            case "lz6":
            case "lz7":
            case "lz8":
                sName = "LHA archive, LArc ext (.LZS)";
                break;
            default:
                bDetected = false;
        }
    } else if (Binary.compare("'mflh'0100")) {
        bDetected = true;
        sName = "MVA";
    } else if (Binary.compare("'ViG'....1a")) {
        bDetected = true;
        sName = "PaperPort";
    } else if (Binary.compare("'sqsh'0000")) {
        bDetected = true;
        sName = "SquashFS";
        sOptions = "big endian";
    } else if (Binary.compare("'hsqs'0300")) {
        bDetected = true;
        sName = "SquashFS";
        sOptions = "little endian";
    } else if (Binary.compare("'im001V'......50....0000")) {
        sName = "SW";
        bDetected = true;
        var arch_offset = Binary.readByte(0x0e) + 15;
        if (Binary.compare("1f9d", arch_offset)) {
            sOptions = "Z archive";
        } else if (Binary.compare("1f1e", arch_offset)) {
            sOptions = "PACK 2 archive";
        }
    } else if (Binary.compare("0001000401000100010000000000000000000000000000000000000000000000010101")) {
        bDetected = true;
        sName = "VMS SaveSet";
    } else if (Binary.compare("'ZOO'............'Archive'")) {
        bDetected = true;
        sName = "ZOO";
    } else if (Binary.compare("602213636c00")) {
        bDetected = true;
        sName = "Asymetrix";
    } else if (Binary.compare("453dcd28........................'Compressed ROMFS'")) {
        bDetected = true;
        sName = "CRAMFS";
    } else if (Binary.compare("'IsZ!@'01")) {
        bDetected = true;
        sName = "Zipped ISO Disk Image (.ISZ)";
        switch (Binary.read_uint32(0x10)) {
            case 0:
                sOptions = "no password";
                break;
            case 1:
                sOptions = "password";
                break;
            case 2:
                sOptions = "password, aes128";
                break;
            case 3:
                sOptions = "password, aes182";
                break;
            case 4:
                sOptions = "password, aes256";
                break;
        }
    } else if (Binary.compare("aa59f0000002")) {
        bDetected = true;
        sName = "SaveDskF";
    } else if (Binary.compare("'AlB'1a")) {
        bDetected = true;
        sName = "BeOS package";
    } else if (Binary.compare("'BIGF'00")) {
        bDetected = true;
        sName = "BIGF";
    } else if (Binary.compare("01ca'Copyright (c) Genus Microprogramming, Inc.'")) {
        bDetected = true;
        sName = "GXL";
    } else if (Binary.compare("0100......00ecf9")) {
        bDetected = true;
        sName = "INSA";
    } else if (Binary.compare("..0fd28ccc1f..3c0d8e830dd88f25ac")) {
        bDetected = true;
        sName = "InstallShield ISN";
    } else if (Binary.compare("135d658c3a010200")) {
        bDetected = true;
        sName = "InstallShield";
        sVersion = "3.x"
    } else if (Binary.compare("2aab79d800010000")) {
        bDetected = true;
        sName = "InstallShield INST";
        sVersion = "3.x"
    } else if (Binary.compare("'SZDD'88")) {
        bDetected = true;
        sName = "SZDD";
        sOptions = "by Microsoft";
    } else if (Binary.compare("'KWAJ'88")) {
        bDetected = true;
        sName = "KWAJ";
        sOptions = "by Microsoft";
    } else if (Binary.compare("'MDmd'")) {
        bDetected = true;
        sName = "MDCD";
    } else if (Binary.compare("'MPQ'1a")) {
        bDetected = true;
        sName = "MPQ";
        sOptions = "by Blizzard";
    } else if (Binary.compare("'_MCT'00'KSLZ'789c")) {
        bDetected = true;
        sName = "MSKN 2";
        sOptions = "zlib";
    } else if (Binary.compare("'PACK'............0000")) {
        bDetected = true;
        sName = "PACK";
    } else if (Binary.compare("'PACK'") && File.read_uint32(4, _BE) > 0 && File.read_uint32(4, _BE) <= 3) {
        bDetected = true;
        sName = "Packed git objects (.pack)";
        sVersion = "v" + File.read_uint32(4, _BE);
        sOptions = File.read_uint32(8, _BE) + " object(s)"
    } else if (Binary.compare("FF'tOc'00000002")) {
        sName = "Index of packed git objects (.idx)";
        sVersion = "v" + File.read_uint32(4, _BE);
        bDetected = 1
    } else if (Binary.compare("'RIDX'00000001") && File.read_uint32(8, _BE) > 0 && File.read_uint32(8, _BE) <= 2) {
        sName = "Reverse index of packed git objects (.rev)";
        sVersion = "v1";
        bDetected = true;
        switch (File.read_uint32(8, _BE)) {
            case 1:
                sOptions = "SHA-1 hashes";
                break;
            case 2:
                sOptions = "SHA-256 hashes";
                break;
            default:
                sOptions = "unknown hashes";
        }
    } else if (Binary.compare("00000000000000000000000000007400010074000500")) {
        bDetected = true;
        sName = "PCInstall";
    } else if (Binary.compare("'PP20'09")) {
        bDetected = true;
        sName = "PP20";
    } else if (Binary.compare("edabeedb0300")) {
        bDetected = true;
        sName = "RPM package";
    } else if (Binary.compare("bd01..00..00..000000")) {
        bDetected = true;
        sName = "HUFF";
    } else if (Binary.compare("'SZ '88")) {
        bDetected = true;
        sName = "SZ";
        sOptions = "by Microsoft";
    } else if (Binary.compare("'BAGF'02")) {
        bDetected = true;
        sName = "BAGF";
    } else if (Binary.compare("'PAC - 'a9' BVRP Software 1990-2000'")) {
        bDetected = true;
        sName = "PAC";
        sOptions = "1990-2000 by BVRP Software";
    } else if (Binary.compare("'Cr24'02")) {
        bDetected = true;
        sName = "CRX";
    } else if (Binary.compare("74c42c84e1e5d428")) {
        bDetected = true;
        sName = "InstallShield INX";
        sVersion = "7.x"
    } else if (Binary.compare("5d0000....ffffffffffffffff00180ddd04")) {
        bDetected = true;
        sName = "LZMA";
    } else if (Binary.compare("1fa0")) {
        bDetected = true;
        sName = "SCO";
    } else if (Binary.compare("'# PaCkAgE DaTaStReAm'")) {
        bDetected = true;
        sName = "Solaris Package";
    } else if (Binary.compare("'SQZE'010000")) {
        bDetected = true;
        sName = "SQZE";
    } else if (Binary.compare("'xar!'001c00010000")) {
        bDetected = true;
        sName = "XAR";
    } else if (Binary.compare("fd'7zXZ'0000")) {
        bDetected = true;
        sName = "XZ";
    }

    function isCompress() {
        if (File.getSize() < 3 || !File.compare("1F9D")) return false;
        t = File.read_uint8(2);
        sversion = t & 0x80 ? "new" : "old";
        t &= 0x7F;
        if (t < 9 || t > 16) return false;
        return true;
    }
    if (!bDetected)
        if (isCompress()) {
            sName = "Compress (.Z)";
            sVersion = sversion;
            bDetected = true;
        } else if (Binary.compare("'LZK00'000000")) {
        bDetected = true;
        sName = "LZK00";
    } else if (Binary.compare("032401010100")) {
        bDetected = true;
        sName = "WPK";
    } else if (Binary.compare("'TPWM'")) {
        bDetected = true;
        sName = "TPWM (BlueByte)";
    } else if ((Binary.getSize() >= 500) && (Binary.compare("00'ustar'", 0x100))) {
        bDetected = true;
        sName = "tar";
    } else if (Binary.compare("'LB'0100")) {
        bDetected = true;
        sName = "XFL game resource file (.XFL)";
        sVersion = "v1.0";
        sOptions = sOptions.append(Binary.getString(12, 32));
        sOptions = sOptions.append("& other " + (Binary.readDword(8) - 1) + " files");
    } else if (Binary.compare("FF060000'sNaPpY'")) {
        bDetected = true;
        sName = "Snappy compressed data (.SZ)";
    } else if (Binary.compare("'blkzip'00")) {
        bDetected = true;
        sName = "BulkZip Archive (.BULK)";
    } else if (Binary.compare("AE01'NanoZip 0.09 alpha'")) {
        bDetected = true;
        sName = "NanoZip Archive (.NZ)";
        sVersion = "0.09 alpha";
    } else if (Binary.compare("'CM'2805060000")) {
        bDetected = true;
        sName = "RAZOR Archive (.RZ)";
    } else if (Binary.compare("28B52FFD")) {
        bDetected = true;
        sName = "Facebook Zstandard/ZSTD compressed data (.ZST)";
    }
    return result(bShowType, bShowVersion, bShowOptions);
}