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-2021 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"
22 #include "managers/cswordbackend.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 
36 using namespace sword;
37 
38 namespace BtInstallBackend {
39 
40 /** Adds the source described by Source to the backend. */
41 bool 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. */
69 sword::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. */
104 bool 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 
143 bool isRemote(const sword::InstallSource& source) {
144  return source.type == "FTP"
145  || source.type == "SFTP"
146  || source.type == "HTTP"
147  || source.type == "HTTPS";
148 }
149 
150 QString configPath() {
151  return util::directory::getUserHomeSwordDir().absolutePath()
152  + QStringLiteral("/InstallMgr");
153 }
154 
155 QString configFilename()
156 { return configPath() + QStringLiteral("/InstallMgr.conf"); }
157 
158 QStringList 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 
186 std::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()
Definition: directory.cpp:342