Skip to content

Commit

Permalink
fix: extractZipFile is not part of Client but more generic.
Browse files Browse the repository at this point in the history
This solve a crash from mainmenu while extracting the zip
  • Loading branch information
nerzhul committed May 6, 2021
1 parent ba40b39 commit 225d454
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 69 deletions.
66 changes: 0 additions & 66 deletions src/client/client.cpp
Expand Up @@ -725,72 +725,6 @@ bool Client::loadMedia(const std::string &data, const std::string &filename,
return false;
}

bool Client::extractZipFile(const char *filename, const std::string &destination)
{
auto fs = m_rendering_engine->get_filesystem();

if (!fs->addFileArchive(filename, false, false, io::EFAT_ZIP)) {
return false;
}

sanity_check(fs->getFileArchiveCount() > 0);

/**********************************************************************/
/* WARNING this is not threadsafe!! */
/**********************************************************************/
io::IFileArchive* opened_zip = fs->getFileArchive(fs->getFileArchiveCount() - 1);

const io::IFileList* files_in_zip = opened_zip->getFileList();

unsigned int number_of_files = files_in_zip->getFileCount();

for (unsigned int i=0; i < number_of_files; i++) {
std::string fullpath = destination;
fullpath += DIR_DELIM;
fullpath += files_in_zip->getFullFileName(i).c_str();
std::string fullpath_dir = fs::RemoveLastPathComponent(fullpath);

if (!files_in_zip->isDirectory(i)) {
if (!fs::PathExists(fullpath_dir) && !fs::CreateAllDirs(fullpath_dir)) {
fs->removeFileArchive(fs->getFileArchiveCount()-1);
return false;
}

io::IReadFile* toread = opened_zip->createAndOpenFile(i);

FILE *targetfile = fopen(fullpath.c_str(),"wb");

if (targetfile == NULL) {
fs->removeFileArchive(fs->getFileArchiveCount()-1);
return false;
}

char read_buffer[1024];
long total_read = 0;

while (total_read < toread->getSize()) {

unsigned int bytes_read =
toread->read(read_buffer,sizeof(read_buffer));
if ((bytes_read == 0 ) ||
(fwrite(read_buffer, 1, bytes_read, targetfile) != bytes_read))
{
fclose(targetfile);
fs->removeFileArchive(fs->getFileArchiveCount() - 1);
return false;
}
total_read += bytes_read;
}

fclose(targetfile);
}

}

fs->removeFileArchive(fs->getFileArchiveCount() - 1);
return true;
}

// Virtual methods from con::PeerHandler
void Client::peerAdded(con::Peer *peer)
{
Expand Down
2 changes: 0 additions & 2 deletions src/client/client.h
Expand Up @@ -384,8 +384,6 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
bool loadMedia(const std::string &data, const std::string &filename,
bool from_media_push = false);

bool extractZipFile(const char *filename, const std::string &destination);

// Send a request for conventional media transfer
void request_media(const std::vector<std::string> &file_requests);

Expand Down
64 changes: 64 additions & 0 deletions src/filesys.cpp
Expand Up @@ -727,6 +727,70 @@ bool safeWriteToFile(const std::string &path, const std::string &content)
return true;
}

bool extractZipFile(io::IFileSystem *fs, const char *filename, const std::string &destination)
{
if (!fs->addFileArchive(filename, false, false, io::EFAT_ZIP)) {
return false;
}

sanity_check(fs->getFileArchiveCount() > 0);

/**********************************************************************/
/* WARNING this is not threadsafe!! */
/**********************************************************************/
io::IFileArchive* opened_zip = fs->getFileArchive(fs->getFileArchiveCount() - 1);

const io::IFileList* files_in_zip = opened_zip->getFileList();

unsigned int number_of_files = files_in_zip->getFileCount();

for (unsigned int i=0; i < number_of_files; i++) {
std::string fullpath = destination;
fullpath += DIR_DELIM;
fullpath += files_in_zip->getFullFileName(i).c_str();
std::string fullpath_dir = fs::RemoveLastPathComponent(fullpath);

if (!files_in_zip->isDirectory(i)) {
if (!fs::PathExists(fullpath_dir) && !fs::CreateAllDirs(fullpath_dir)) {
fs->removeFileArchive(fs->getFileArchiveCount()-1);
return false;
}

io::IReadFile* toread = opened_zip->createAndOpenFile(i);

FILE *targetfile = fopen(fullpath.c_str(),"wb");

if (targetfile == NULL) {
fs->removeFileArchive(fs->getFileArchiveCount()-1);
return false;
}

char read_buffer[1024];
long total_read = 0;

while (total_read < toread->getSize()) {

unsigned int bytes_read =
toread->read(read_buffer,sizeof(read_buffer));
if ((bytes_read == 0 ) ||
(fwrite(read_buffer, 1, bytes_read, targetfile) != bytes_read))
{
fclose(targetfile);
fs->removeFileArchive(fs->getFileArchiveCount() - 1);
return false;
}
total_read += bytes_read;
}

fclose(targetfile);
}

}

fs->removeFileArchive(fs->getFileArchiveCount() - 1);
return true;
}

bool ReadFile(const std::string &path, std::string &out)
{
std::ifstream is(path, std::ios::binary | std::ios::ate);
Expand Down
6 changes: 6 additions & 0 deletions src/filesys.h
Expand Up @@ -36,6 +36,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define PATH_DELIM ":"
#endif

namespace irr { namespace io {
class IFileSystem;
}}

namespace fs
{

Expand Down Expand Up @@ -125,6 +129,8 @@ const char *GetFilenameFromPath(const char *path);

bool safeWriteToFile(const std::string &path, const std::string &content);

bool extractZipFile(irr::io::IFileSystem *fs, const char *filename, const std::string &destination);

bool ReadFile(const std::string &path, std::string &out);

bool Rename(const std::string &from, const std::string &to);
Expand Down
3 changes: 2 additions & 1 deletion src/script/lua_api/l_mainmenu.cpp
Expand Up @@ -628,8 +628,9 @@ int ModApiMainMenu::l_extract_zip(lua_State *L)
std::string absolute_destination = fs::RemoveRelativePathComponents(destination);

if (ModApiMainMenu::mayModifyPath(absolute_destination)) {
auto rendering_engine = getGuiEngine(L)->m_rendering_engine;
fs::CreateAllDirs(absolute_destination);
lua_pushboolean(L, getClient(L)->extractZipFile(zipfile, destination));
lua_pushboolean(L, fs::extractZipFile(rendering_engine->get_filesystem(), zipfile, destination));
return 1;
}

Expand Down

0 comments on commit 225d454

Please sign in to comment.