#include "libbible.h" #include #include #include #include #include #include #include using namespace std; class myStatusReporter : public sword::StatusReporter { public: myStatusReporter(libbible::Status *status); ~myStatusReporter(); void preStatus(long totalBytes, long completedBytes, const char *message); void update(unsigned long totalBytes, unsigned long completedBytes); protected: libbible::Status *status; string message; }; myStatusReporter::myStatusReporter(libbible::Status *s) { status = s; } myStatusReporter::~myStatusReporter() {}; //virtual void libbible::Status::update(unsigned long totalBytes, unsigned long completedBytes, string message) {} void myStatusReporter::preStatus(long totalBytes, long completedBytes, const char *msg) { message = string(msg); status->update((unsigned long) totalBytes, (unsigned long) completedBytes, message); //printf("Got a status update: %ld / %ld, \"%s\"\n", completedBytes, totalBytes, message.c_str()); } void myStatusReporter::update(unsigned long totalBytes, unsigned long completedBytes) { status->update(totalBytes, completedBytes, message); //printf("Got a status update: %ld / %ld, \"%s\"\n", completedBytes, totalBytes, message.c_str()); } string basedir = (getenv("HOME")) + string("/.sword/"); sword::InstallMgr *installMgr = new sword::InstallMgr((basedir + std::string("InstallMgr")).c_str(), nullptr); map>> installSources; void libbible::setStatusReporter(libbible::Status& status) { myStatusReporter *msr = new myStatusReporter(&status); free(installMgr); installMgr = new sword::InstallMgr((basedir + std::string("InstallMgr")).c_str(), msr); installMgr->setUserDisclaimerConfirmed(true); } map> libbible::downloadModsAvailable() { installSources.clear(); mkdir((basedir + std::string("mods.d/")).c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); mkdir((basedir + std::string("modules/")).c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); installMgr->setUserDisclaimerConfirmed(true); string confpath = basedir + string("InstallMgr/InstallMgr.conf"); if(! sword::FileMgr::existsFile(confpath.c_str())) { // Lifted directly from xiphos sword::FileMgr::createParent(confpath.c_str()); sword::SWConfig config(confpath.c_str()); sword::InstallSource is("FTP"); is.caption = "CrossWire"; is.source = "ftp.crosswire.org"; is.directory = "/pub/sword/raw"; config["General"]["PassiveFTP"] = "true"; config["Sources"]["FTPSource"] = is.getConfEnt(); config.save(); installMgr->refreshRemoteSourceConfiguration(); } installMgr->readInstallConf(); map> modsAvailable; //printf("Getting langs...\n"); for(auto src : installMgr->sources) { if(src.second->getMgr()->Modules.empty()) { //printf("Refreshing remote source: %s\n", src.second->getConfEnt().c_str()); installMgr->refreshRemoteSource(src.second); } for(auto mod : src.second->getMgr()->Modules) { auto *curMod = mod.second; string type(curMod->getType()); if(type == "Biblical Texts") { string language(curMod->getLanguage()); //printf("Got language %s\n", language.c_str()); vector newMods; vector> newSources; // emplace only adds if key is unique modsAvailable.emplace(language, newMods); installSources.emplace(language, newSources); modsAvailable[language].push_back(string(curMod->getName())); pair p(string(curMod->getName()), src.second); installSources[language].push_back(p); } } } return modsAvailable; } void libbible::terminateDownload() { installMgr->terminate(); } bool libbible::installModFromInternet(string language, string name) { // Searching through map>> installSources; if(installSources.empty()) { downloadModsAvailable(); } for (pair p : installSources[language]) { if(p.first == name) { sword::SWMgr mgr(basedir.c_str()); if(installMgr->installModule(&mgr, 0, name.c_str(), p.second) == 0) { return true; } return false; } } return false; } #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()); }*/ 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) { sword::SWMgr mgr(basedir.c_str()); sword::ModMap::iterator it = mgr.Modules.find(modname.c_str()); if(it != mgr.Modules.end()) { installMgr->removeModule(&mgr, it->second->getName()); } }