2

I have a vector (which is just a wrapper over a char array) that is the input. The pkzip was created using c# sharpZipLib.

I stored the data into a file which I ran through a hex editor zip template that checked out. The input is good, it's not malformed. This all but the compressed data:

50 4B 03 04 14 00 00 00 08 00 51 B2 8B 4A B3 B6
6C B0 F6 18 00 00 40 07 01 00 07 00 00 00 2D 33
31 2F 31 32 38

<compressed data (6390 bytes)>

50 4B 01 02 14 00 14 00 00 00 08 00 51 B2 8B 4A
B3 B6 6C B0 F6 18 00 00 40 07 01 00 07 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 2D 33
31 2F 31 32 38 50 4B 05 06 00 00 00 00 01 00 01
00 35 00 00 00 1B 19 00 00 00 00

I have another vector which is to be the output. The inflated data will have about 67-68k, so I know it fits into the buffer.

For the life of me, I cannot get the minizip to inflate the former and store it into latter.

This is what I have so far:

#include "minizip\zlib.h"

#define ZLIB_WINAPI

std::vector<unsigned char> data;

/*...*/

std::vector<unsigned char> outBuffer(1024 * 1024);

z_stream stream;

stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;

stream.data_type = Z_BINARY;

stream.avail_in = data.size();
stream.avail_out = outBuffer.size();

stream.next_in = &data[0];
stream.next_out = &outBuffer[0];

int ret = inflateInit(&stream);
ret = inflate(&stream, 1);
ret = inflateEnd(&stream);

I used the debugger to step through the method and monitor the ret. inflate returned value -3 with message "incorrect header check".

This is a pkzip, which is a wrapper around zlib, but minizip should be a wrapper library around zlib that should support pkzip, shouldn't it be? How do I have to modify this to work?

Karlovsky120
  • 6,212
  • 8
  • 41
  • 94
  • 1
    What's the point of returning `nullptr`? You don't modify `data` as it's passed by value, so your function essentially does nothing, to my mind. – ForceBru May 22 '17 at 18:36
  • I'm trying to test it, I used nullptr as a holder. I wanted to confirm the inflate works via VS watcher before implementing the rest of the method. EDIT: Fixed it so it makes some sense. – Karlovsky120 May 22 '17 at 18:37
  • Why am I offtopic? – Karlovsky120 May 22 '17 at 18:42
  • You are trying to create a mcve without actually bothering to make it work. For example, after that edit, you return a pointer to an object which has gone out of scope and been destructed. But you say the only thing that matters is what happens with a third party library function when called with data that you didn't provide. How do we know the input is valid? Maybe it actually has a bad header, just like inflate is telling you. (oh, third party link -- we don't use those because when it goes away, nobody can use this question as a reference. Maybe provide code to compress some text?) – Kenny Ostrom May 22 '17 at 18:48
  • I modified it further to remove any emphasis to what is done with the data after it's inflated. I copied all the data of the zip here, except for the actual compressed bit. I've been struggling with this stupid simple thing for a week now. Compressing it is a whole another battle I have to win after I get this working. – Karlovsky120 May 22 '17 at 18:56
  • Actually I think you are trying to read a zip file with functions for a completely different format. Look for a zip.h or zlib/unzip.h – Kenny Ostrom May 22 '17 at 19:33
  • There are no such files in minizip. Please help me. I've been trying to do this for a week now. I'm on a brink of losing it. I'm tired. I just want to unzip a stupid file, I cannot fathom how it is that there is no clear and simple way to do it in c++. I'll pay you. I'll do anything. I just need a library and a few lines of code. I'm begging here. Please. – Karlovsky120 May 22 '17 at 19:39
  • https://github.com/madler/zlib/tree/master/contrib/minizip I see "zip.h" and "unzip.h" – Kenny Ostrom May 22 '17 at 19:46
  • I stand corrected. I must've used a different release. However, I don't have a file (it's a part of a bigger structure), I only have the data as an array. I can't use it yet again. This must be the 4th or 5th library that wont work. – Karlovsky120 May 22 '17 at 19:50

3 Answers3

2

Since it starts with 50 4B 03 04 it is a PKZIP file, according to https://users.cs.jmu.edu/buchhofp/forensics/formats/pkzip.html

If these are zip files, then inflate is the wrong function. The zlib, gzip and zip formats are all different. You can read zip with zlib, if you use the right functions to do so. If you don't have the contrib, maybe download and rebuild zlib.

Here's some old code I have which works for zip files, using the zlib library. I might have moved some headers around, because the official zlib has them under zlib/contrib/minizip.

The arguments are filenames, so you'll have to modify it, or write your array to a file.

// #include <zlib/unzip.h>
#include <zlib/contrib/minizip/unzip.h>

/// return list of filenames in zip archive
std::list<std::string> GetZipFilenames(const char *szZipArchive){
    std::list<std::string> results;
    unzFile zip = unzOpen(szZipArchive);
    if (zip){
        unz_global_info info;
        int rv = unzGetGlobalInfo(zip, &info);

        if (UNZ_OK == unzGoToFirstFile(zip)){
            do {
                char szFilename[BUFSIZ];
                if (UNZ_OK == unzGetCurrentFileInfo(zip, NULL, szFilename, sizeof(szFilename), NULL, 0, NULL, 0))
                    results.push_back(std::string(szFilename));
            } while (UNZ_OK == unzGoToNextFile(zip));
        }
    }
    return results;
}

/// extract the contents of szFilename inside szZipArchive
bool ExtractZipFileContents(const char *szZipArchive, const char *szFilename, std::string &contents){
    bool result = false;
    unzFile zip = unzOpen(szZipArchive);
    if (zip){
        if (UNZ_OK == unzLocateFile(zip, szFilename, 0)){
            if (UNZ_OK == unzOpenCurrentFile(zip)){
                char buffer[BUFSIZ];
                size_t bytes;
                while (0 < (bytes = unzReadCurrentFile(zip, buffer, sizeof(buffer)))){
                    contents += std::string(buffer, bytes);
                }
                unzCloseCurrentFile(zip);
                result = (bytes == 0);
            }
        }
        unzClose(zip);
    }
    return result;
}
Kenny Ostrom
  • 5,639
  • 2
  • 21
  • 30
2

If I understand the question correctly, you are trying to decompress the 6390 bytes of compressed data. That compressed data is a raw deflate stream, which has no zlib header or trailer. For that you would need to use inflateInit2(&stream, -MAX_WBITS) instead of inflateInit(&stream). The -MAX_WBITS requests decompression of raw deflate.

Mark Adler
  • 101,978
  • 13
  • 118
  • 158
  • I think it is better to use `-MAX_WBITS` instead of `-15`. Just like [in unzip.c](https://github.com/madler/zlib/blob/cacf7f1d4e3d44d871b605da3b647f07d718623f/contrib/minizip/unzip.c#L1584). – tav Feb 04 '20 at 10:05
0

Zip-Utils

std::vector<unsigned char> inputBuffer;
std::vector<unsigned char> outBuffer(1024 * 1024);

HZIP hz = OpenZip(&inputBuffer[0], inputBuffer.capacity(), 0);
ZIPENTRY ze;
GetZipItem(hz, 0, &ze);
UnzipItem(hz, 0, &outBuffer[0], 1024 * 1024);

outBuffer.resize(ze.unc_size);

If inputBuffer contains a pkzip file, this snippet will unzip it and store contents in outBuffer.

That is all.

Karlovsky120
  • 6,212
  • 8
  • 41
  • 94