File indexing completed on 2025-01-19 03:53:33

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2009-06-27
0007  * Description : Database Engine element configuration loader
0008  *
0009  * SPDX-FileCopyrightText: 2009-2010 by Holger Foerster <hamsi2k at freenet dot de>
0010  * SPDX-FileCopyrightText: 2010-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "dbengineconfigloader.h"
0017 
0018 // Qt includes
0019 
0020 #include <QDir>
0021 #include <QDomDocument>
0022 #include <QDomNode>
0023 #include <QDomNodeList>
0024 #include <QFile>
0025 #include <QIODevice>
0026 #include <QTextStream>
0027 
0028 // KDE includes
0029 
0030 #include <klocalizedstring.h>
0031 
0032 // Local includes
0033 
0034 #include "digikam_debug.h"
0035 
0036 namespace Digikam
0037 {
0038 
0039 DbEngineConfigSettingsLoader::DbEngineConfigSettingsLoader(const QString& filepath, int xmlVersion)
0040 {
0041     isValid = readConfig(filepath, xmlVersion);
0042 
0043     if (!isValid)
0044     {
0045         qCDebug(DIGIKAM_DBENGINE_LOG) << errorMessage;
0046     }
0047 }
0048 
0049 DbEngineConfigSettings DbEngineConfigSettingsLoader::readDatabase(QDomElement& databaseElement)
0050 {
0051     DbEngineConfigSettings configElement;
0052     configElement.databaseID = QLatin1String("Unidentified");
0053     (void)configElement.databaseID; // prevent cppcheck warning.
0054 
0055     if (!databaseElement.hasAttribute(QLatin1String("name")))
0056     {
0057         qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing statement attribute <name>.";
0058     }
0059 
0060     configElement.databaseID = databaseElement.attribute(QLatin1String("name"));
0061     QDomElement element      = databaseElement.namedItem(QLatin1String("databaseName")).toElement();
0062 
0063     if (element.isNull())
0064     {
0065         qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <databaseName>.";
0066     }
0067 
0068     configElement.databaseName = element.text();
0069     element                    = databaseElement.namedItem(QLatin1String("userName")).toElement();
0070 
0071     if (element.isNull())
0072     {
0073         qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <userName>.";
0074     }
0075 
0076     configElement.userName = element.text();
0077     element                = databaseElement.namedItem(QLatin1String("password")).toElement();
0078 
0079     if (element.isNull())
0080     {
0081         qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <password>.";
0082     }
0083 
0084     configElement.password = element.text();
0085     element                = databaseElement.namedItem(QLatin1String("hostName")).toElement();
0086 
0087     if (element.isNull())
0088     {
0089         qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <hostName>.";
0090     }
0091 
0092     configElement.hostName = element.text();
0093     element                = databaseElement.namedItem(QLatin1String("port")).toElement();
0094 
0095     if (element.isNull())
0096     {
0097         qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <port>.";
0098     }
0099 
0100     configElement.port = element.text();
0101     element            = databaseElement.namedItem(QLatin1String("connectoptions")).toElement();
0102 
0103     if (element.isNull())
0104     {
0105         qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <connectoptions>.";
0106     }
0107 
0108     configElement.connectOptions = element.text();
0109     element                      = databaseElement.namedItem(QLatin1String("dbactions")).toElement();
0110 
0111     if (element.isNull())
0112     {
0113         qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing element <dbactions>.";
0114     }
0115 
0116     readDBActions(element, configElement);
0117 
0118     return configElement;
0119 }
0120 
0121 void DbEngineConfigSettingsLoader::readDBActions(const QDomElement& sqlStatementElements,
0122                                                  DbEngineConfigSettings& configElement)
0123 {
0124     QDomElement dbActionElement = sqlStatementElements.firstChildElement(QLatin1String("dbaction"));
0125 
0126     for ( ; !dbActionElement.isNull();  dbActionElement=dbActionElement.nextSiblingElement(QLatin1String("dbaction")))
0127     {
0128         if (!dbActionElement.hasAttribute(QLatin1String("name")))
0129         {
0130             qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing statement attribute <name>.";
0131         }
0132 
0133         DbEngineAction action;
0134         action.name = dbActionElement.attribute(QLatin1String("name"));
0135 
0136         //qCDebug(DIGIKAM_DBENGINE_LOG) << "Getting attribute " << dbActionElement.attribute("name");
0137 
0138         if (dbActionElement.hasAttribute(QLatin1String("mode")))
0139         {
0140             action.mode = dbActionElement.attribute(QLatin1String("mode"));
0141         }
0142 
0143         QDomElement databaseElement = dbActionElement.firstChildElement(QLatin1String("statement"));
0144 
0145         for ( ; !databaseElement.isNull();  databaseElement = databaseElement.nextSiblingElement(QLatin1String("statement")))
0146         {
0147             if (!databaseElement.hasAttribute(QLatin1String("mode")))
0148             {
0149                 qCDebug(DIGIKAM_DBENGINE_LOG) << "Missing statement attribute <mode>.";
0150             }
0151 
0152             DbEngineActionElement actionElement;
0153             actionElement.mode      = databaseElement.attribute(QLatin1String("mode"));
0154             actionElement.statement = databaseElement.text();
0155 
0156             action.dbActionElements.append(actionElement);
0157         }
0158 
0159         configElement.sqlStatements.insert(action.name, action);
0160     }
0161 }
0162 
0163 bool DbEngineConfigSettingsLoader::readConfig(const QString& filepath, int xmlVersion)
0164 {
0165     qCDebug(DIGIKAM_DBENGINE_LOG) << "Loading SQL code from config file" << filepath;
0166     QFile file(filepath);
0167 
0168     if (!file.exists())
0169     {
0170         errorMessage = i18n("Could not open the configuration file <b>%1</b>. "
0171                             "This file is installed with the digikam application "
0172                             "and is absolutely required to run digikam. "
0173                             "Please check your installation.", filepath);
0174         return false;
0175     }
0176 
0177     if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
0178     {
0179         errorMessage = i18n("Could not open configuration file <b>%1</b>", filepath);
0180         return false;
0181     }
0182 
0183     QDomDocument doc(QLatin1String("DBConfig"));
0184 
0185     if (!doc.setContent(&file))
0186     {
0187         errorMessage = i18n("The XML in the configuration file <b>%1</b> is invalid and cannot be read.", filepath);
0188         file.close();
0189 
0190         return false;
0191     }
0192 
0193     file.close();
0194 
0195     QDomElement element = doc.namedItem(QLatin1String("databaseconfig")).toElement();
0196 
0197     if (element.isNull())
0198     {
0199         errorMessage = i18n("The XML in the configuration file <b>%1</b> "
0200                             "is missing the required element <icode>%2</icode>",
0201                             filepath, element.tagName());
0202         return false;
0203     }
0204 
0205     QDomElement defaultDB =  element.namedItem(QLatin1String("defaultDB")).toElement();
0206 
0207     if (defaultDB.isNull())
0208     {
0209         errorMessage = i18n("The XML in the configuration file <b>%1</b> "
0210                             "is missing the required element <b>%2</b>",
0211                             filepath, element.tagName());
0212         return false;
0213     }
0214 
0215     QDomElement versionElement = element.namedItem(QLatin1String("version")).toElement();
0216     int version                = 0;
0217 
0218     qCDebug(DIGIKAM_DBENGINE_LOG) << "Checking XML version ID => expected: " << xmlVersion
0219                                   << " found: " << versionElement.text().toInt();
0220 
0221     if (!versionElement.isNull())
0222     {
0223         version = versionElement.text().toInt();
0224     }
0225 
0226     if (version < xmlVersion)
0227     {
0228         errorMessage = i18n("An old version of the configuration file <b>%1</b> "
0229                             "is found. Please ensure that the version released "
0230                             "with the running version of digiKam is installed. ",
0231                             filepath);
0232         return false;
0233     }
0234 
0235     //qCDebug(DIGIKAM_DBENGINE_LOG) << "Default DB Node contains: " << defaultDB.text();
0236 
0237     QDomElement databaseElement = element.firstChildElement(QLatin1String("database"));
0238 
0239     for ( ; !databaseElement.isNull(); databaseElement=databaseElement.nextSiblingElement(QLatin1String("database")))
0240     {
0241         DbEngineConfigSettings l_DBCfgElement = readDatabase(databaseElement);
0242         databaseConfigs.insert(l_DBCfgElement.databaseID, l_DBCfgElement);
0243     }
0244 
0245 /*
0246     qCDebug(DIGIKAM_DBENGINE_LOG) << "Found entries: " << databaseConfigs.size();
0247 
0248     Q_FOREACH (const DbEngineConfigSettings& configElement, databaseConfigs )
0249     {
0250         qCDebug(DIGIKAM_DBENGINE_LOG) << "DatabaseID: "          << configElement.databaseID;
0251         qCDebug(DIGIKAM_DBENGINE_LOG) << "HostName: "            << configElement.hostName;
0252         qCDebug(DIGIKAM_DBENGINE_LOG) << "DatabaseName: "        << configElement.databaseName;
0253         qCDebug(DIGIKAM_DBENGINE_LOG) << "UserName: "            << configElement.userName;
0254         qCDebug(DIGIKAM_DBENGINE_LOG) << "Password: "            << configElement.password;
0255         qCDebug(DIGIKAM_DBENGINE_LOG) << "Port: "                << configElement.port;
0256         qCDebug(DIGIKAM_DBENGINE_LOG) << "ConnectOptions: "      << configElement.connectOptions;
0257         qCDebug(DIGIKAM_DBENGINE_LOG) << "Database Server CMD: " << configElement.dbServerCmd;
0258         qCDebug(DIGIKAM_DBENGINE_LOG) << "Database Init CMD: "   << configElement.dbInitCmd;
0259         qCDebug(DIGIKAM_DBENGINE_LOG) << "Statements:";
0260 
0261         Q_FOREACH (const QString& actionKey, configElement.sqlStatements.keys())
0262         {
0263             QList<databaseActionElement> l_DBActionElement = configElement.sqlStatements[actionKey].dBActionElements;
0264             qCDebug(DIGIKAM_DBENGINE_LOG) << "DBAction [" << actionKey << "] has [" << l_DBActionElement.size() << "] actions";
0265 
0266             Q_FOREACH (const databaseActionElement statement, l_DBActionElement)
0267             {
0268                 qCDebug(DIGIKAM_DBENGINE_LOG) << "\tMode ["<< statement.mode <<"] Value ["<< statement.statement <<"]";
0269             }
0270         }
0271 
0272     }
0273 */
0274     return true;
0275 }
0276 
0277 } // namespace Digikam