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