zipper icon indicating copy to clipboard operation
zipper copied to clipboard

unzipper does not extract folder and files more than one level.

Open snahmad opened this issue 6 years ago • 7 comments

snahmad avatar Jun 21 '18 12:06 snahmad

Can you give me a short example code ?

Lecrapouille avatar Apr 11 '19 19:04 Lecrapouille

I'm having this issue right now. I have a zip that contains only one folder and inside that folder there are a bunch of files. If I try to extract everything to a specific path, the library just fails.

#include <iostream>
#include "zipper/unzipper.h"

int main()
{
    zipper::Unzipper unzipper("test.zip");
    unzipper.extract();
    if (!unzipper.extract(PATH)) {
        std::cerr << "There was an error while extracting the files from the ZIP archive." << std::endl;
        return -1;
    }
    unzipper.close();
}

test.zip

For now, I've patched the library by adding a check in the extractToFile() method in unzipper.cpp which returns a UNZ_ISDIRECTORY error in case the filename is a directory:

int extractToFile(const std::string& filename, ZipEntry& info)
    {
        int err = UNZ_ERRNO;

        /* If zip entry is a directory then create it on disk */
        makedir(parentDirectory(filename));
        if(isDirectory(filename))
        {
            err = UNZ_ISDIRECTORY;
            return err;
        }

After that the method extractCurrentEntryToFile checks if err is UNZ_ISDIRECTORY and if it does it changes it to ok, letting the program go on.

err = extractToFile(fileName, entryinfo);
        if (UNZ_OK == err)
        {
            err = unzCloseCurrentFile(m_zf);
            if (UNZ_OK != err)
            {
                std::stringstream str;
                str << "Error " << err << " openinginternal file '"
                    << entryinfo.name << "' in zip";

                throw EXCEPTION_CLASS(str.str().c_str());
            }
        }
        else if(UNZ_ISDIRECTORY == err)
            err = UNZ_OK;

I know that this is quick dirty hack and that's why I don't make any pull request, as I'm sure there are more elegant solutions :)

JackHack96 avatar Sep 06 '21 09:09 JackHack96

@JackHack96 strange, both functions work well for me :( if I comment unzipper.extract(); and instead of PATH I use "ici" the extracted folder are ok. And also tested with an extra folder depth. Have you an '/' at the end of the dir path ?

 tree ici/
ici/
└── test
    ├── test1.txt
    └── test2.txt

1 directory, 2 files

With #102 this is the second times people have a different behavior than me. Can you try this following patch:

#include <iostream>

    int extractToFile(const std::string& filename, ZipEntry& info)
    {
        int err = UNZ_ERRNO;

        /* If zip entry is a directory then create it on disk */
        if (!makedir(parentDirectory(filename))) // BEFORE PATCH: SILENT ERROR 
        {
           std::cerr << "FAILED makedir" << std::endl;
        }

        /* Create the file on disk so we can unzip to it */
        std::ofstream output_file(filename.c_str(), std::ofstream::binary);

        if (output_file.good())
        {
            if (UNZ_OK == extractToStream(output_file, info))
            {
                std::cerr << "OK extractToStream" << std::endl;
                err = UNZ_OK;
            }

            output_file.close();

            /* Set the time of the file that has been unzipped */
            tm_unz timeaux;
            memcpy(&timeaux, &info.unixdate, sizeof(timeaux));

            changeFileDate(filename, info.dosdate, timeaux);
        }
        else
        {
            std::cerr << "FAILED ofstream" << std::endl;
            output_file.close();
        }

        return err;
    }

I'm seeing:

OK extractToStream
OK extractToStream

What branch do you use, What OS ?

Lecrapouille avatar Sep 06 '21 17:09 Lecrapouille

@JackHack96 In fact can you replace your zipper folder by this one ? Recompile it and install it and re-run your test. I added more logs.

zipper.zip

Lecrapouille avatar Sep 06 '21 17:09 Lecrapouille

Hello, I have the same issue (1.0.3) In fact, the issue comes from when the zip file has been created with an external tool ( and the zip contains a folder)

The extraction fails and return false (without an exception): unzipper.extract();

However, if the zip files has been created with zipper (and the zip contains a folder), then the extraction works perfectly...

srroger avatar Dec 02 '21 10:12 srroger

i also have this problem,but i can sloving this problem like Unzipper unzipper(src_file); std::vector<ZipEntry> entries = unzipper.entries(); for (ZipEntry entry : entries) { unzipper.extractEntry(entry.name, des_folder); }

v77777 avatar May 16 '22 04:05 v77777

Sorry, I have few time to concern on this project especially on this master that want to stall. @v77777 how do you compile the project ? Can you try with the v2.x.y git branch ? https://github.com/sebastiandev/zipper/tree/v2.x.y (in this branch I no longer compile with CMake but with a simple Makefile and with local thirdparts) ?

git clone https://github.com/sebastiandev/zipper.git -b "v2.x.y" --recursive
cd zipper
make download-external-libs
make compile-external-libs
make -j`nproc --all`

PS: I have just updated the submodule Makefile to the newest version. Hope it will work. I have to fix github actions.

Lecrapouille avatar May 17 '22 16:05 Lecrapouille

Closed since working on branch 2.x.y. Please reopen this ticket in not fixed

Lecrapouille avatar Sep 11 '22 01:09 Lecrapouille