Subversion Repositories spk

Rev

Blame | Last modification | View Log | RSS feed

// XLib.cpp : Defines the functions for the static library.
//

#include "pch.h"
#include "framework.h"

unsigned char* UnPCKFile(const char* file, size_t* len, bool nocrypt)
{
        FileIO File(file);
        if (!File.startRead()) return NULL;

        size_t size;
        unsigned char* data = File.readAll(&size);

        if (data) {
                unsigned char* unData = UnPCKData(data, size, len, nocrypt);
                delete data;
                return unData;
        }

        return NULL;
}

unsigned char* UnPCKData(unsigned char* data, size_t datasize, size_t* len) { return UnPCKData(data, datasize, len, IsDataPCK(data, datasize)); }
unsigned char* UnPCKData(unsigned char* data, size_t datasize, size_t* len, bool nocrypt)
{
        bool isPCK = IsDataPCK(data, datasize);

        unsigned char* newData = data;
        unsigned char* tempData = NULL;

        if (nocrypt)
        {
                tempData = new unsigned char[datasize];
                newData = tempData;
                memcpy(newData, data, datasize);
                unsigned char magic = newData[0] ^ 0xC8;

                for (size_t i = 1; i < datasize; i++)
                        newData[i] ^= magic;
                ++newData;
                --datasize;
        }

        // create data buffer
        size_t* uncomprLenSize = (size_t*)(newData + (datasize - 4));
        unsigned long uncomprLen = (unsigned long)*uncomprLenSize;
        if (uncomprLen > (datasize * 100))
        {
                if (tempData) delete[]tempData;
                *len = 0;
                return NULL;
        }
        unsigned char* uncompr = new unsigned char[uncomprLen + 1];
        if (!uncompr) {
                if (tempData) delete[]tempData;
                return NULL;
        }
        memset(uncompr, 0, sizeof(uncompr));


        // find header size
        unsigned char* buf = newData + PCKHEADERSIZE;

        //      buf = data + (6 + sizeof(time_t));
        char flag = newData[3];

        if (flag & GZ_FLAG_EXTRA)
        {
                size_t xlen = *((short int*)(buf));
                buf += xlen;
        }

        if (flag & GZ_FLAG_FILENAME)
        {
                char* origname = (char*)(buf);
                buf += strlen(origname) + 1;
        }
        if (flag & GZ_FLAG_COMMENT)
        {
                char* comment = (char*)(buf);
                buf += strlen(comment) + 1;
        }
        if (flag & GZ_FLAG_HCRC)
                buf += 2;
        long bufSize = (long)(datasize - (buf - newData) - 8);

        int err = uncompress2(uncompr, &uncomprLen, buf, bufSize);
        if (err != Z_OK)
        {
                if (tempData) delete[]tempData;
                delete uncompr;
                *len = 0;
                return NULL;
        }

        *len = uncomprLen;
        uncompr[uncomprLen] = '\0';
        if (tempData) delete[]tempData;
        return uncompr;
}

bool IsDataPCK(const unsigned char* data, size_t size)
{
        if (size >= 3)
        {
                unsigned char magic = data[0] ^ 0xC8;
                return ((data[1] ^ magic) == 0x1F && (data[2] ^ magic) == 0x8B);
        }
        else
                return false;

}