1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2009-06-27
7 * Description : Database Engine element configuration loader
8 *
9 * Copyright (C) 2009-2010 by Holger Foerster <hamsi2k at freenet dot de>
10 * Copyright (C) 2010-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
11 *
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation;
15 * either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "dbengineconfigloader.h"
26
27 // Qt includes
28
29 #include <QDir>
30 #include <QDomDocument>
31 #include <QDomElement>
32 #include <QDomNode>
33 #include <QDomNodeList>
34 #include <QFile>
35 #include <QIODevice>
36 #include <QTextStream>
37
38 // KDE includes
39
40 #include <klocalizedstring.h>
41
42 // Local includes
43
44 #include "digikam_debug.h"
45
46 namespace Digikam
47 {
48
DbEngineConfigSettingsLoader(const QString & filepath,int xmlVersion)49 DbEngineConfigSettingsLoader::DbEngineConfigSettingsLoader(const QString& filepath, int xmlVersion)
50 {
51 isValid = readConfig(filepath, xmlVersion);
52
53 if (!isValid)
54 {
55 qCDebug(DIGIKAM_DBENGINE_LOG) << errorMessage;
56 }
57 }
58
readDatabase(QDomElement & databaseElement)59 DbEngineConfigSettings DbEngineConfigSettingsLoader::readDatabase(QDomElement& databaseElement)
60 {
61 DbEngineConfigSettings configElement;
62 configElement.databaseID = QLatin1String("Unidentified");
63 (void)configElement.databaseID; // prevent cppcheck warning.
64
65 if (!databaseElement.hasAttribute(QLatin1String("name")))
66 {
67 qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing statement attribute <name>.";
68 }
69
70 configElement.databaseID = databaseElement.attribute(QLatin1String("name"));
71 QDomElement element = databaseElement.namedItem(QLatin1String("databaseName")).toElement();
72
73 if (element.isNull())
74 {
75 qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <databaseName>.";
76 }
77
78 configElement.databaseName = element.text();
79 element = databaseElement.namedItem(QLatin1String("userName")).toElement();
80
81 if (element.isNull())
82 {
83 qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <userName>.";
84 }
85
86 configElement.userName = element.text();
87 element = databaseElement.namedItem(QLatin1String("password")).toElement();
88
89 if (element.isNull())
90 {
91 qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <password>.";
92 }
93
94 configElement.password = element.text();
95 element = databaseElement.namedItem(QLatin1String("hostName")).toElement();
96
97 if (element.isNull())
98 {
99 qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <hostName>.";
100 }
101
102 configElement.hostName = element.text();
103 element = databaseElement.namedItem(QLatin1String("port")).toElement();
104
105 if (element.isNull())
106 {
107 qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <port>.";
108 }
109
110 configElement.port = element.text();
111 element = databaseElement.namedItem(QLatin1String("connectoptions")).toElement();
112
113 if (element.isNull())
114 {
115 qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <connectoptions>.";
116 }
117
118 configElement.connectOptions = element.text();
119 element = databaseElement.namedItem(QLatin1String("dbactions")).toElement();
120
121 if (element.isNull())
122 {
123 qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <dbactions>.";
124 }
125
126 readDBActions(element, configElement);
127
128 return configElement;
129 }
130
readDBActions(QDomElement & sqlStatementElements,DbEngineConfigSettings & configElement)131 void DbEngineConfigSettingsLoader::readDBActions(QDomElement& sqlStatementElements, DbEngineConfigSettings& configElement)
132 {
133 QDomElement dbActionElement = sqlStatementElements.firstChildElement(QLatin1String("dbaction"));
134
135 for ( ; !dbActionElement.isNull(); dbActionElement=dbActionElement.nextSiblingElement(QLatin1String("dbaction")))
136 {
137 if (!dbActionElement.hasAttribute(QLatin1String("name")))
138 {
139 qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing statement attribute <name>.";
140 }
141
142 DbEngineAction action;
143 action.name = dbActionElement.attribute(QLatin1String("name"));
144
145 //qCDebug(DIGIKAM_DBENGINE_LOG) << "Getting attribute " << dbActionElement.attribute("name");
146
147 if (dbActionElement.hasAttribute(QLatin1String("mode")))
148 {
149 action.mode = dbActionElement.attribute(QLatin1String("mode"));
150 }
151
152 QDomElement databaseElement = dbActionElement.firstChildElement(QLatin1String("statement"));
153
154 for ( ; !databaseElement.isNull(); databaseElement = databaseElement.nextSiblingElement(QLatin1String("statement")))
155 {
156 if (!databaseElement.hasAttribute(QLatin1String("mode")))
157 {
158 qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing statement attribute <mode>.";
159 }
160
161 DbEngineActionElement actionElement;
162 actionElement.mode = databaseElement.attribute(QLatin1String("mode"));
163 actionElement.statement = databaseElement.text();
164
165 action.dbActionElements.append(actionElement);
166 }
167
168 configElement.sqlStatements.insert(action.name, action);
169 }
170 }
171
readConfig(const QString & filepath,int xmlVersion)172 bool DbEngineConfigSettingsLoader::readConfig(const QString& filepath, int xmlVersion)
173 {
174 qCDebug(DIGIKAM_DBENGINE_LOG) << "Loading SQL code from config file" << filepath;
175 QFile file(filepath);
176
177 if (!file.exists())
178 {
179 errorMessage = i18n("Could not open the configuration file <b>%1</b>. "
180 "This file is installed with the digikam application "
181 "and is absolutely required to run digikam. "
182 "Please check your installation.", filepath);
183 return false;
184 }
185
186 if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
187 {
188 errorMessage = i18n("Could not open configuration file <b>%1</b>", filepath);
189 return false;
190 }
191
192 QDomDocument doc(QLatin1String("DBConfig"));
193
194 if (!doc.setContent(&file))
195 {
196 errorMessage = i18n("The XML in the configuration file <b>%1</b> is invalid and cannot be read.", filepath);
197 file.close();
198 return false;
199 }
200
201 file.close();
202
203 QDomElement element = doc.namedItem(QLatin1String("databaseconfig")).toElement();
204
205 if (element.isNull())
206 {
207 errorMessage = i18n("The XML in the configuration file <b>%1</b> "
208 "is missing the required element <icode>%2</icode>",
209 filepath, element.tagName());
210 return false;
211 }
212
213 QDomElement defaultDB = element.namedItem(QLatin1String("defaultDB")).toElement();
214
215 if (defaultDB.isNull())
216 {
217 errorMessage = i18n("The XML in the configuration file <b>%1</b> "
218 "is missing the required element <b>%2</b>",
219 filepath, element.tagName());
220 return false;
221 }
222
223 QDomElement versionElement = element.namedItem(QLatin1String("version")).toElement();
224 int version = 0;
225
226 qCDebug(DIGIKAM_DBENGINE_LOG) << "Checking XML version ID => expected: " << xmlVersion
227 << " found: " << versionElement.text().toInt();
228
229 if (!versionElement.isNull())
230 {
231 version = versionElement.text().toInt();
232 }
233
234 if (version < xmlVersion)
235 {
236 errorMessage = i18n("An old version of the configuration file <b>%1</b> "
237 "is found. Please ensure that the version released "
238 "with the running version of digiKam is installed. ",
239 filepath);
240 return false;
241 }
242
243 //qCDebug(DIGIKAM_DBENGINE_LOG) << "Default DB Node contains: " << defaultDB.text();
244
245 QDomElement databaseElement = element.firstChildElement(QLatin1String("database"));
246
247 for ( ; !databaseElement.isNull(); databaseElement=databaseElement.nextSiblingElement(QLatin1String("database")))
248 {
249 DbEngineConfigSettings l_DBCfgElement = readDatabase(databaseElement);
250 databaseConfigs.insert(l_DBCfgElement.databaseID, l_DBCfgElement);
251 }
252
253 /*
254 qCDebug(DIGIKAM_DBENGINE_LOG) << "Found entries: " << databaseConfigs.size();
255
256 foreach (const DbEngineConfigSettings& configElement, databaseConfigs )
257 {
258 qCDebug(DIGIKAM_DBENGINE_LOG) << "DatabaseID: " << configElement.databaseID;
259 qCDebug(DIGIKAM_DBENGINE_LOG) << "HostName: " << configElement.hostName;
260 qCDebug(DIGIKAM_DBENGINE_LOG) << "DatabaseName: " << configElement.databaseName;
261 qCDebug(DIGIKAM_DBENGINE_LOG) << "UserName: " << configElement.userName;
262 qCDebug(DIGIKAM_DBENGINE_LOG) << "Password: " << configElement.password;
263 qCDebug(DIGIKAM_DBENGINE_LOG) << "Port: " << configElement.port;
264 qCDebug(DIGIKAM_DBENGINE_LOG) << "ConnectOptions: " << configElement.connectOptions;
265 qCDebug(DIGIKAM_DBENGINE_LOG) << "Database Server CMD: " << configElement.dbServerCmd;
266 qCDebug(DIGIKAM_DBENGINE_LOG) << "Database Init CMD: " << configElement.dbInitCmd;
267 qCDebug(DIGIKAM_DBENGINE_LOG) << "Statements:";
268
269 foreach (const QString& actionKey, configElement.sqlStatements.keys())
270 {
271 QList<databaseActionElement> l_DBActionElement = configElement.sqlStatements[actionKey].dBActionElements;
272 qCDebug(DIGIKAM_DBENGINE_LOG) << "DBAction [" << actionKey << "] has [" << l_DBActionElement.size() << "] actions";
273
274 foreach (const databaseActionElement statement, l_DBActionElement)
275 {
276 qCDebug(DIGIKAM_DBENGINE_LOG) << "\tMode ["<< statement.mode <<"] Value ["<< statement.statement <<"]";
277 }
278 }
279
280 }
281 */
282 return true;
283 }
284
285 } // namespace Digikam
286