diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | libbible.h | 3 | ||||
-rw-r--r-- | mods.cc | 69 | ||||
-rw-r--r-- | testLibbible.cc | 4 |
4 files changed, 69 insertions, 11 deletions
@@ -1,6 +1,6 @@ CC=g++ -LIBS=sword -CFLAGS=-c -Wall -fPIC +LIBS=sword minizip +CFLAGS=-c -Wall -fPIC -std=c++17 LDFLAGS= SOURCES=libbible.cc mods.cc settings.cc OBJECTS=$(SOURCES:.cc=.o) @@ -79,8 +79,9 @@ namespace libbible { /** * @param filename Path to the .zip compressed module to be installed + * @return true on success, false otherwise */ - void installModFromZip(std::string filename); + bool installModFromZip(std::string filename); /** * @param modname The name of the module to be removed @@ -4,6 +4,8 @@ #include <sword/installmgr.h> #include <sword/filemgr.h> #include <sword/remotetrans.h> +#include <unzip.h> +#include <filesystem> using namespace std; @@ -116,16 +118,71 @@ bool libbible::installModFromInternet(string language, string name) { return false; } -void libbible::installModFromZip(string filename) { +#define READ_SIZE 8192 +#define delim '/' + +bool libbible::installModFromZip(string filename) { // So... turns out it's a mite unsupported to install from a .zip // Here's the deal. We do a syscall to unzip. We fancy like that. // TODO: Use the ZipCompress module from SWORD instead. - string command = "unzip -o " + filename + " -d " + basedir + "&> /dev/null"; - if(system(command.c_str())) { - //Uh oh... - printf("Something bad happened when unpacking %s\n. Is unzip installed?", filename.c_str()); + /*string command = "unzip -o " + filename + " -d " + basedir + "&> /dev/null"; + if(system(command.c_str())) { + //Uh oh... + printf("Something bad happened when unpacking %s\n. Is unzip installed?", filename.c_str()); + }*/ + unzFile zipfile = unzOpen(filename.c_str()); + if(zipfile == NULL) { + return false; } - + unz_global_info global_info; + if(unzGetGlobalInfo(zipfile, &global_info) != UNZ_OK) { + unzClose(zipfile); + return false; + } + char read_buffer[READ_SIZE]; + ulong i; + for(i = 0; i < global_info.number_entry; i++) { + unz_file_info file_info; + if(unzGetCurrentFileInfo(zipfile, &file_info, read_buffer, READ_SIZE, NULL, 0, NULL, 0) != UNZ_OK) { + unzClose(zipfile); + return false; + } + string fname = basedir + string(read_buffer); + size_t pos = fname.find_last_of(delim); + if(pos != string::npos) { + string path = fname.substr(0, pos); + filesystem::create_directories(path); + } + if(unzOpenCurrentFile(zipfile) != UNZ_OK) { + unzCloseCurrentFile(zipfile); + unzClose(zipfile); + return false; + } + FILE *out = fopen(fname.c_str(), "wb"); + if(out == NULL) { + unzCloseCurrentFile(zipfile); + unzClose(zipfile); + return false; + } + int bytesRead; + do { + bytesRead = unzReadCurrentFile(zipfile, read_buffer, READ_SIZE); + if(bytesRead < 0) { + printf("error %d\n", bytesRead); + unzCloseCurrentFile(zipfile); + unzClose(zipfile); + return false; + } + if(bytesRead > 0) { + fwrite(read_buffer, bytesRead, 1, out); + } + } while(bytesRead > 0); + fclose(out); + unzCloseCurrentFile(zipfile); + unzGoToNextFile(zipfile); + } + unzClose(zipfile); + return true; } void libbible::uninstallMod(string modname) { diff --git a/testLibbible.cc b/testLibbible.cc index b8f93b3..20ff7d9 100644 --- a/testLibbible.cc +++ b/testLibbible.cc @@ -78,8 +78,8 @@ void TestLibbible::testGetModules(void) { libbible::uninstallMod(pair.first); } CPPUNIT_ASSERT(libbible::getModules().empty()); - libbible::installModFromZip("modules/KJV.zip"); - libbible::installModFromZip("modules/JPS.zip"); + CPPUNIT_ASSERT(libbible::installModFromZip("modules/KJV.zip")); + CPPUNIT_ASSERT(libbible::installModFromZip("modules/JPS.zip")); mods = libbible::getModules(); CPPUNIT_ASSERT(mods.find("KJV") != mods.end()); CPPUNIT_ASSERT(mods["KJV"].size() == 66); |