// Detect a zip archive.
// Author: Jason Hood <jadoxa@yahoo.com.au>

includeScript("archive-file");
sName = "Zip";

function detect_Zip(bFile, bShowOptions) {
    var nOffset = 0;
    if (bFile) {
        // Don't know what this is, but I happened to have a file that started
        // with it.
        if (File.compare("'PK00'")) {
            nOffset = 4;
        }
        if (Binary.compare("'PK'0708", nOffset)) {
            sOptions = "extended";
            bDetected = true;
            return;
        }
    } else {
        if (File.compareOverlay("'PK'0304")) {
            nOffset = File.getOverlayOffset();
        } else {
            var nSize = File.getSize();
            if (nSize < 64) {
                return;
            }
            nSize -= 11;
            nOffset = nSize;
            if (!File.compare("'PK'0506'", nOffset)) {
                if (nSize < 4096) {
                    nOffset = 0;
                } else {
                    nOffset -= 4096;
                    nSize = 4096;
                }
                nOffset = File.findSignature(nOffset, nSize, "'PK'0506");
                if (nOffset == -1) {
                    return;
                }
                var nBase = File.readDword(nOffset + 16);
                nOffset -= File.readDword(nOffset + 12);
                if (!File.compare("'PK'0102", nOffset)) {
                    return;
                }
                nOffset += File.readDword(nOffset + 0x2a) - nBase;
            }
        }
    }

    if (File.compare("'PK'0304", nOffset)) {
        bDetected = true;

        if (File.findString(nOffset, 0x40, "META-INF/MANIFEST.MF") != -1) {
            sOptions = sOptions.append("JAR"); // Java archive
        }

        if (File.findString(nOffset, 0x40, "classes.dex") != -1) {
            sOptions = sOptions.append("APK"); // Android application package file
        }

        var nVer = 0;
        if (!bShowOptions) {
            // Just take the first file and assume it carries through.
            if (File.readByte(nOffset + 6) & 1) {
                sOptions = "encrypted";
            }
            nVer = File.readByte(nOffset + 4);
        } else {
            var bEncrypted = 0;
            do {
                var v = File.readByte(nOffset + 4);
                if (v > nVer) {
                    nVer = v;
                }
                if (!bEncrypted && (File.readByte(nOffset + 6) & 1)) {
                    bEncrypted = 1;
                }
                var nPacked = File.readDword(nOffset + 0x12);
                var nName = File.readWord(nOffset + 0x1A);
                Archive.add(File.readDword(nOffset + 0x16), nPacked,
                    nPacked == 0 && File.readByte(nOffset + 0x1E + nName - 1) == 0x2F);
                nOffset += 0x1E + nName + File.readWord(nOffset + 0x1C) + nPacked;
            } while (File.compare("'PK'0304", nOffset));
            if (bEncrypted) {
                sOptions = "encrypted";
            }
            sOptions = sOptions.append(Archive.contents());
        }
        sVersion = (nVer / 10).toFixed(1);
    }
}