1
0

fix: extractZipFile is not part of Client but more generic.

This solve a crash from mainmenu while extracting the zip
This commit is contained in:
Loic Blot 2021-05-06 09:02:11 +02:00 committed by luk3yx
parent 2a38a33ff8
commit 1f4ff9cea6
4 changed files with 88 additions and 74 deletions

View File

@ -381,6 +381,7 @@ public:
// Insert a media file appropriately into the appropriate manager
bool loadMedia(const std::string &data, const std::string &filename,
bool from_media_push = false);
// Send a request for conventional media transfer
void request_media(const std::vector<std::string> &file_requests);

View File

@ -749,6 +749,79 @@ bool safeWriteToFile(const std::string &path, const std::string &content)
return true;
}
bool extractZipFile(io::IFileSystem *fs, const char *filename,
const std::string &destination, const char *password, std::string *errorMessage)
{
if (!fs->addFileArchive(filename, false, false, io::EFAT_ZIP, password)) {
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);
if (toread == nullptr) {
// Wrong password
fs->removeFileArchive(fs->getFileArchiveCount()-1);
if (errorMessage != nullptr)
*errorMessage = "invalid password";
return false;
}
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);

View File

@ -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
{
@ -125,6 +129,10 @@ 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, const char *password = "",
std::string *errorMessage = nullptr);
bool ReadFile(const std::string &path, std::string &out);
bool Rename(const std::string &from, const std::string &to);

View File

@ -660,81 +660,13 @@ int ModApiMainMenu::l_extract_zip(lua_State *L)
if (ModApiMainMenu::mayModifyPath(absolute_destination)) {
fs::CreateAllDirs(absolute_destination);
io::IFileSystem *fs = RenderingEngine::get_filesystem();
if (!fs->addFileArchive(zipfile, false, false, io::EFAT_ZIP, password)) {
lua_pushboolean(L,false);
return 1;
std::string errorMessage;
lua_pushboolean(L, fs::extractZipFile(RenderingEngine::get_filesystem(),
zipfile, destination, password, &errorMessage));
if (!errorMessage.empty()) {
lua_pushstring(L, errorMessage.c_str());
return 2;
}
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);
lua_pushboolean(L,false);
return 1;
}
io::IReadFile* toread = opened_zip->createAndOpenFile(i);
if (toread == nullptr) {
// Wrong password
fs->removeFileArchive(fs->getFileArchiveCount()-1);
lua_pushboolean(L, false);
lua_pushstring(L, "invalid password");
return 2;
}
FILE *targetfile = fopen(fullpath.c_str(),"wb");
if (targetfile == NULL) {
fs->removeFileArchive(fs->getFileArchiveCount()-1);
lua_pushboolean(L,false);
return 1;
}
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);
lua_pushboolean(L,false);
return 1;
}
total_read += bytes_read;
}
fclose(targetfile);
}
}
fs->removeFileArchive(fs->getFileArchiveCount()-1);
lua_pushboolean(L,true);
return 1;
}