BibleTime
btinstallbackend.cpp
Go to the documentation of this file.
1/*********
2*
3* In the name of the Father, and of the Son, and of the Holy Spirit.
4*
5* This file is part of BibleTime's source code, https://bibletime.info/
6*
7* Copyright 1999-2026 by the BibleTime developers.
8* The BibleTime source code is licensed under the GNU General Public License
9* version 2.0.
10*
11**********/
12
13#include "btinstallbackend.h"
14
15#include <QByteArray>
16#include <QDebug>
17#include <QDir>
18#include <type_traits>
19#include <utility>
20#include "../util/btassert.h"
21#include "../util/directory.h"
23#include "btinstallmgr.h"
24
25// Sword includes:
26#ifdef __GNUC__
27#pragma GCC diagnostic push
28#pragma GCC diagnostic ignored "-Wsuggest-override"
29#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
30#endif
31#include <installmgr.h>
32#include <multimapwdef.h>
33#include <swconfig.h>
34#include <swbuf.h>
35#ifdef __GNUC__
36#pragma GCC diagnostic pop
37#endif
38
39
40using namespace sword;
41
43
44/** Adds the source described by Source to the backend. */
45bool addSource(sword::InstallSource& source) {
46 SWConfig config(configFilename().toLatin1());
47 if (isRemote(source)) {
48 if (source.directory[ source.directory.length()-1 ] == '/') {
49 source.directory--;
50 }
51 static_assert(std::is_same_v<decltype(source.type), SWBuf>);
52 if (source.type == "FTP") {
53 config["Sources"].emplace("FTPSource", source.getConfEnt());
54 }
55 else if (source.type == "SFTP") {
56 config["Sources"].emplace("SFTPSource", source.getConfEnt());
57 }
58 else if (source.type == "HTTP") {
59 config["Sources"].emplace("HTTPSource", source.getConfEnt());
60 }
61 else if (source.type == "HTTPS") {
62 config["Sources"].emplace("HTTPSSource", source.getConfEnt());
63 }
64 }
65 else if (source.type == "DIR") {
66 config["Sources"].emplace("DIRSource", source.getConfEnt());
67 }
68 config.save();
69 return true;
70}
71
72/** Returns the Source struct. */
73sword::InstallSource source(const QString &name) {
74 BtInstallMgr mgr;
75 auto const source = mgr.sources.find(name.toLatin1().data());
76 if (source != mgr.sources.end()) {
77 return *(source->second);
78 }
79 else { //not found in Sword, may be a local DIR source
80 SWConfig config(configFilename().toLatin1());
81 auto const sections = config.getSections();
82 auto const sourcesSection = sections.find("Sources");
83 if (sourcesSection != sections.end()) {
84 auto sourceBegin =
85 sourcesSection->second.lower_bound("DIRSource");
86 auto const sourceEnd =
87 sourcesSection->second.upper_bound("DIRSource");
88
89 while (sourceBegin != sourceEnd) {
90 InstallSource is("DIR", sourceBegin->second.c_str());
91 if (is.caption == name) { // found local dir source
92 return is;
93 }
94
95 ++sourceBegin; //next source
96 }
97 }
98 }
99
100 InstallSource is("EMPTY"); //default return value
101 is.caption = "unknown caption";
102 is.source = "unknown source";
103 is.directory = "unknown dir";
104 return is;
105}
106
107/** Deletes the source. */
108bool deleteSource(const QString &name) {
109 sword::InstallSource is = source(name );
110
111 SWConfig config(configFilename().toLatin1());
112
113 //this code can probably be shortened by using the stl remove_if functionality
114 SWBuf sourceConfigEntry = is.getConfEnt();
115 bool notFound = true;
116 auto it(config["Sources"].begin());
117 while (it != config["Sources"].end()) {
118 //SWORD lib gave us a "nice" surprise: getConfEnt() adds uid, so old sources added by BT are not recognized here
119 if (it->second == sourceConfigEntry) {
120 config["Sources"].erase(it);
121 notFound = false;
122 break;
123 }
124 ++it;
125 }
126 if (notFound) {
127 qDebug() << "source was not found, trying without uid";
128 //try again without uid
129 QString sce(sourceConfigEntry.c_str());
130 QStringList l = sce.split('|');
131 l.removeLast();
132 sce = l.join('|').append('|');
133 it = config["Sources"].begin();
134 while (it != config["Sources"].end()) {
135 if (it->second == sce) {
136 config["Sources"].erase(it);
137 break;
138 }
139 ++it;
140 }
141 }
142
143 config.save();
144 return true; /// \todo dummy
145}
146
147bool isRemote(const sword::InstallSource& source) {
148 return source.type == "FTP"
149 || source.type == "SFTP"
150 || source.type == "HTTP"
151 || source.type == "HTTPS";
152}
153
154QString configPath() {
155 return util::directory::getUserHomeSwordDir().absolutePath()
156 + QStringLiteral("/InstallMgr");
157}
158
160{ return configPath() + QStringLiteral("/InstallMgr.conf"); }
161
162QStringList sourceNameList() {
163 BtInstallMgr mgr;
164 BT_ASSERT(mgr.installConf);
165
166 QStringList names;
167
168 //add Sword remote sources
169 for (auto const & sourcePair : mgr.sources)
170 names << QString::fromLocal8Bit(sourcePair.second->caption.c_str());
171
172 // Add local directory sources
173 SWConfig config(configFilename().toLatin1());
174 auto const sourcesSection = config.getSections().find("Sources");
175 if (sourcesSection != config.getSections().end()) {
176 auto sourceBegin = sourcesSection->second.lower_bound("DIRSource");
177 auto const sourceEnd = sourcesSection->second.upper_bound("DIRSource");
178
179 while (sourceBegin != sourceEnd) {
180 InstallSource is("DIR", sourceBegin->second.c_str());
181 names << QString::fromLatin1(is.caption.c_str());
182
183 ++sourceBegin;
184 }
185 }
186
187 return names;
188}
189
190std::unique_ptr<CSwordBackend> backend(sword::InstallSource const & is) {
191 /// \anchor BackendNotSingleton
192 auto ret(std::make_unique<CSwordBackend>(isRemote(is)
193 ? is.localShadow.c_str()
194 : is.directory.c_str(),
195 false));
196 ret->initModules();
197 return ret;
198}
199
200} // namespace BtInstallBackend
#define BT_ASSERT(...)
Definition btassert.h:17
bool isRemote(const sword::InstallSource &source)
bool deleteSource(const QString &name)
bool addSource(sword::InstallSource &source)
sword::InstallSource source(const QString &name)
QStringList sourceNameList()
std::unique_ptr< CSwordBackend > backend(sword::InstallSource const &is)
const QDir & getUserHomeSwordDir()