aboutsummaryrefslogtreecommitdiff
path: root/mods.cc
blob: 1a31602a7ac9153c5f33dd6af7ae50808072cf65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "libbible.h"
#include <sword/swmgr.h>
#include <sword/swmodule.h>
#include <sword/installmgr.h>
#include <sword/filemgr.h>
#include <sword/remotetrans.h>

using namespace std;

class myStatusReporter : public sword::StatusReporter {
    public:
        myStatusReporter(libbible::Status *status);
        virtual ~myStatusReporter();
        virtual void preStatus(long totalBytes, long completedBytes, const char *message);
        virtual void update(unsigned long totalBytes, unsigned long completedBytes);
    protected:
        libbible::Status *status;
        string message;
};

myStatusReporter::myStatusReporter(libbible::Status *s) {
    status = s;
}

myStatusReporter::~myStatusReporter() {};

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);
}

void myStatusReporter::update(unsigned long totalBytes, unsigned long completedBytes) {
    status->update(totalBytes, completedBytes, message);
}

string basedir = (getenv("HOME")) + string("/.sword/");
sword::InstallMgr *installMgr = new sword::InstallMgr((basedir + std::string("InstallMgr")).c_str(), nullptr);
map<string, vector<pair<string, sword::InstallSource *>>> installSources;

map<string, vector<string>> libbible::downloadModsAvailable(libbible::Status *status) {
    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);
    myStatusReporter *msr = nullptr;
    if(status) {
        msr = new myStatusReporter(status);
    }
    free(installMgr);
    installMgr = new sword::InstallMgr((basedir + std::string("InstallMgr")).c_str(), msr);
    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<string, vector<string>> 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<string> newMods;
                vector<pair<string, sword::InstallSource *>> newSources;
                // emplace only adds if key is unique
                modsAvailable.emplace(language, newMods);
                installSources.emplace(language, newSources);
                modsAvailable[language].push_back(string(curMod->getName()));
                pair<string, sword::InstallSource *> 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<string, vector<pair<string, sword::InstallSource *>>> installSources;
    if(installSources.empty()) {
        downloadModsAvailable();
    }
    for (pair<string, sword::InstallSource *> 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;
}

void 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", filename.c_str());
    }

}

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());
    }
}