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        : 2007-03-18
0007  * Description : Database Engine storage container for connection parameters.
0008  *
0009  * SPDX-FileCopyrightText: 2007-2008 by Marcel Wiesweg  <marcel dot wiesweg at gmx dot de>
0010  * SPDX-FileCopyrightText: 2010      by Holger Foerster <hamsi2k at freenet dot de>
0011  * SPDX-FileCopyrightText: 2010-2024 by Gilles Caulier  <caulier dot gilles at gmail dot com>
0012  * SPDX-FileCopyrightText: 2018      by Mario Frank     <mario dot frank at uni minus potsdam dot de>
0013  *
0014  * SPDX-License-Identifier: GPL-2.0-or-later
0015  *
0016  * ============================================================ */
0017 
0018 #include "dbengineparameters.h"
0019 
0020 // Qt includes
0021 
0022 #include <QDir>
0023 #include <QUrlQuery>
0024 #include <QFile>
0025 #include <QCryptographicHash>
0026 #include <QStandardPaths>
0027 
0028 // KDE includes
0029 
0030 #include <kconfiggroup.h>
0031 #include <ksharedconfig.h>
0032 
0033 // Local includes
0034 
0035 #include "digikam_config.h"
0036 #include "digikam_globals.h"
0037 #include "digikam_debug.h"
0038 #include "o0simplecrypt.h"      // For password encrypt
0039 
0040 namespace
0041 {
0042 
0043 static const QLatin1String configGroupDatabase                         ("Database Settings");
0044 static const QLatin1String configInternalDatabaseServer                ("Internal Database Server");
0045 static const QLatin1String configInternalDatabaseServerPath            ("Internal Database Server Path");
0046 static const QLatin1String configInternalDatabaseServerUseMariaDB      ("Internal Database Server Use MariaDB");
0047 static const QLatin1String configInternalDatabaseServerMysqlInitCmd    ("Internal Database Server Mysql Init Command");
0048 static const QLatin1String configInternalDatabaseServerMysqlAdminCmd   ("Internal Database Server Mysql Admin Command");
0049 static const QLatin1String configInternalDatabaseServerMysqlServerCmd  ("Internal Database Server Mysql Server Command");
0050 static const QLatin1String configInternalDatabaseServerMysqlUpgradeCmd ("Internal Database Server Mysql Upgrade Command");
0051 static const QLatin1String configDatabaseType                          ("Database Type");
0052 static const QLatin1String configDatabaseName                          ("Database Name");              ///< For Sqlite the DB file path, for Mysql the DB name
0053 static const QLatin1String configDatabaseNameThumbnails                ("Database Name Thumbnails");   ///< For Sqlite the DB file path, for Mysql the DB name
0054 static const QLatin1String configDatabaseNameFace                      ("Database Name Face");         ///< For Sqlite the DB file path, for Mysql the DB name
0055 static const QLatin1String configDatabaseNameSimilarity                ("Database Name Similarity");   ///< For Sqlite the DB file path, for Mysql the DB name
0056 static const QLatin1String configDatabaseHostName                      ("Database Hostname");
0057 static const QLatin1String configDatabasePort                          ("Database Port");
0058 static const QLatin1String configDatabaseUsername                      ("Database Username");
0059 static const QLatin1String configDatabasePassword                      ("Database Password");          ///< For compatbilitity. Use encrypted version instead.
0060 static const QLatin1String configDatabaseEncryptedPassword             ("Database Encrypted Password");
0061 static const QLatin1String configDatabaseConnectOptions                ("Database Connectoptions");
0062 static const QLatin1String configDatabaseWALMode                       ("Database WAL Mode");
0063 
0064 /// Legacy for older versions.
0065 static const QLatin1String configDatabaseFilePathEntry                 ("Database File Path");
0066 static const QLatin1String configAlbumPathEntry                        ("Album Path");
0067 /// Sqlite DB file names
0068 static const QLatin1String digikam4db                                  ("digikam4.db");
0069 static const QLatin1String thumbnails_digikamdb                        ("thumbnails-digikam.db");
0070 static const QLatin1String face_digikamdb                              ("recognition.db");
0071 static const QLatin1String similarity_digikamdb                        ("similarity.db");
0072 
0073 }
0074 
0075 namespace Digikam
0076 {
0077 
0078 QString DbEngineParameters::serverPrivatePath()
0079 {
0080     return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
0081                                             QLatin1String("/digikam/");
0082 }
0083 
0084 DbEngineParameters::DbEngineParameters()
0085     : port          (-1),
0086       walMode       (false),
0087       internalServer(false)
0088 {
0089 }
0090 
0091 DbEngineParameters::DbEngineParameters(const QString& _type,
0092                                        const QString& _databaseNameCore,
0093                                        const QString& _connectOptions,
0094                                        const QString& _hostName,
0095                                        int            _port,
0096                                        bool           _walMode,
0097                                        bool           _internalServer,
0098                                        const QString& _userName,
0099                                        const QString& _password,
0100                                        const QString& _databaseNameThumbnails,
0101                                        const QString& _databaseNameFace,
0102                                        const QString& _databaseNameSimilarity,
0103                                        const QString& _internalServerDBPath,
0104                                        const QString& _internalServerMysqlInitCmd,
0105                                        const QString& _internalServerMysqlAdminCmd,
0106                                        const QString& _internalServerMysqlServerCmd,
0107                                        const QString& _internalServerMysqlUpgradeCmd)
0108     : databaseType                  (_type),
0109       databaseNameCore              (_databaseNameCore),
0110       connectOptions                (_connectOptions),
0111       hostName                      (_hostName),
0112       port                          (_port),
0113       walMode                       (_walMode),
0114       internalServer                (_internalServer),
0115       userName                      (_userName),
0116       password                      (_password),
0117       databaseNameThumbnails        (_databaseNameThumbnails),
0118       databaseNameFace              (_databaseNameFace),
0119       databaseNameSimilarity        (_databaseNameSimilarity),
0120       internalServerDBPath          (_internalServerDBPath),
0121       internalServerMysqlInitCmd    (_internalServerMysqlInitCmd),
0122       internalServerMysqlAdminCmd   (_internalServerMysqlAdminCmd),
0123       internalServerMysqlServerCmd  (_internalServerMysqlServerCmd),
0124       internalServerMysqlUpgradeCmd (_internalServerMysqlUpgradeCmd)
0125 {
0126 }
0127 
0128 DbEngineParameters::DbEngineParameters(const QUrl& url)
0129     : databaseType          (QUrlQuery(url).queryItemValue(QLatin1String("databaseType"))),
0130       databaseNameCore      (QUrlQuery(url).queryItemValue(QLatin1String("databaseNameCore"))),
0131       connectOptions        (QUrlQuery(url).queryItemValue(QLatin1String("connectOptions"))),
0132       hostName              (QUrlQuery(url).queryItemValue(QLatin1String("hostName"))),
0133       port                  (-1),
0134       walMode               (false),
0135       internalServer        (false),
0136       databaseNameThumbnails(QUrlQuery(url).queryItemValue(QLatin1String("databaseNameThumbnails"))),
0137       databaseNameFace      (QUrlQuery(url).queryItemValue(QLatin1String("databaseNameFace"))),
0138       databaseNameSimilarity(QUrlQuery(url).queryItemValue(QLatin1String("databaseNameSimilarity")))
0139 {
0140     QString queryPort    = QUrlQuery(url).queryItemValue(QLatin1String("port"));
0141 
0142     if (!queryPort.isNull())
0143     {
0144         port = queryPort.toInt();
0145     }
0146 
0147     QString queryWalMode = QUrlQuery(url).queryItemValue(QLatin1String("walMode"));
0148 
0149     if (!queryWalMode.isNull())
0150     {
0151         walMode = (queryWalMode == QLatin1String("true"));
0152     }
0153 
0154 #if defined(HAVE_MYSQLSUPPORT) && defined(HAVE_INTERNALMYSQL)
0155 
0156     QString queryServer  = QUrlQuery(url).queryItemValue(QLatin1String("internalServer"));
0157 
0158     if (!queryServer.isNull())
0159     {
0160         internalServer = (queryServer == QLatin1String("true"));
0161     }
0162 
0163     queryServer          = QUrlQuery(url).queryItemValue(QLatin1String("internalServerPath"));
0164 
0165     if (!queryServer.isNull())
0166     {
0167         internalServerDBPath = QUrlQuery(url).queryItemValue(QLatin1String("internalServerPath"));
0168     }
0169     else
0170     {
0171         internalServerDBPath = serverPrivatePath();
0172     }
0173 
0174     internalServerMysqlInitCmd    = QUrlQuery(url).queryItemValue(QLatin1String("internalServerMysqlInitCmd"));
0175     internalServerMysqlAdminCmd   = QUrlQuery(url).queryItemValue(QLatin1String("internalServerMysqlAdminCmd"));
0176     internalServerMysqlServerCmd  = QUrlQuery(url).queryItemValue(QLatin1String("internalServerMysqlServerCmd"));
0177     internalServerMysqlUpgradeCmd = QUrlQuery(url).queryItemValue(QLatin1String("internalServerMysqlUpgradeCmd"));
0178 
0179 #else
0180 
0181     internalServer = false;
0182 
0183 #endif
0184 
0185     userName       = QUrlQuery(url).queryItemValue(QLatin1String("userName"));
0186     password       = QUrlQuery(url).queryItemValue(QLatin1String("password"));
0187 }
0188 
0189 void DbEngineParameters::insertInUrl(QUrl& url) const
0190 {
0191     removeFromUrl(url);
0192 
0193     QUrlQuery q(url);
0194     q.addQueryItem(QLatin1String("databaseType"),           databaseType);
0195     q.addQueryItem(QLatin1String("databaseNameCore"),       databaseNameCore);
0196     q.addQueryItem(QLatin1String("databaseNameThumbnails"), databaseNameThumbnails);
0197     q.addQueryItem(QLatin1String("databaseNameFace"),       databaseNameFace);
0198     q.addQueryItem(QLatin1String("databaseNameSimilarity"), databaseNameSimilarity);
0199 
0200     if (!connectOptions.isNull())
0201     {
0202         q.addQueryItem(QLatin1String("connectOptions"), connectOptions);
0203     }
0204 
0205     if (!hostName.isNull())
0206     {
0207         q.addQueryItem(QLatin1String("hostName"), hostName);
0208     }
0209 
0210     if (port != -1)
0211     {
0212         q.addQueryItem(QLatin1String("port"), QString::number(port));
0213     }
0214 
0215     if (walMode)
0216     {
0217         q.addQueryItem(QLatin1String("walMode"), QLatin1String("true"));
0218     }
0219 
0220     if (internalServer)
0221     {
0222         q.addQueryItem(QLatin1String("internalServer"),                QLatin1String("true"));
0223         q.addQueryItem(QLatin1String("internalServerPath"),            internalServerDBPath);
0224         q.addQueryItem(QLatin1String("internalServerMysqlInitCmd"),    internalServerMysqlInitCmd);
0225         q.addQueryItem(QLatin1String("internalServerMysqlAdminCmd"),   internalServerMysqlAdminCmd);
0226         q.addQueryItem(QLatin1String("internalServerMysqlServerCmd"),  internalServerMysqlServerCmd);
0227         q.addQueryItem(QLatin1String("internalServerMysqlUpgradeCmd"), internalServerMysqlUpgradeCmd);
0228     }
0229 
0230     if (!userName.isNull())
0231     {
0232         q.addQueryItem(QLatin1String("userName"), userName);
0233     }
0234 
0235     if (!password.isNull())
0236     {
0237         q.addQueryItem(QLatin1String("password"), password);
0238     }
0239 
0240     url.setQuery(q);
0241 }
0242 
0243 void DbEngineParameters::removeFromUrl(QUrl& url)
0244 {
0245     QUrlQuery q(url);
0246 
0247     q.removeQueryItem(QLatin1String("databaseType"));
0248     q.removeQueryItem(QLatin1String("databaseNameCore"));
0249     q.removeQueryItem(QLatin1String("databaseNameThumbnails"));
0250     q.removeQueryItem(QLatin1String("databaseNameFace"));
0251     q.removeQueryItem(QLatin1String("databaseNameSimilarity"));
0252     q.removeQueryItem(QLatin1String("connectOptions"));
0253     q.removeQueryItem(QLatin1String("hostName"));
0254     q.removeQueryItem(QLatin1String("port"));
0255     q.removeQueryItem(QLatin1String("walMode"));
0256     q.removeQueryItem(QLatin1String("internalServer"));
0257     q.removeQueryItem(QLatin1String("internalServerPath"));
0258     q.removeQueryItem(QLatin1String("internalServerMysqlInitCmd"));
0259     q.removeQueryItem(QLatin1String("internalServerMysqlAdminCmd"));
0260     q.removeQueryItem(QLatin1String("internalServerMysqlServerCmd"));
0261     q.removeQueryItem(QLatin1String("internalServerMysqlUpgradeCmd"));
0262     q.removeQueryItem(QLatin1String("userName"));
0263     q.removeQueryItem(QLatin1String("password"));
0264 
0265     url.setQuery(q);
0266 }
0267 
0268 bool DbEngineParameters::operator==(const DbEngineParameters& other) const
0269 {
0270     return (
0271             (databaseType                  == other.databaseType)                  &&
0272             (databaseNameCore              == other.databaseNameCore)              &&
0273             (databaseNameThumbnails        == other.databaseNameThumbnails)        &&
0274             (databaseNameFace              == other.databaseNameFace)              &&
0275             (databaseNameSimilarity        == other.databaseNameSimilarity)        &&
0276             (connectOptions                == other.connectOptions)                &&
0277             (hostName                      == other.hostName)                      &&
0278             (port                          == other.port)                          &&
0279             (walMode                       == other.walMode)                       &&
0280             (internalServer                == other.internalServer)                &&
0281             (internalServerDBPath          == other.internalServerDBPath)          &&
0282             (internalServerMysqlInitCmd    == other.internalServerMysqlInitCmd)    &&
0283             (internalServerMysqlAdminCmd   == other.internalServerMysqlAdminCmd)   &&
0284             (internalServerMysqlServerCmd  == other.internalServerMysqlServerCmd)  &&
0285             (internalServerMysqlUpgradeCmd == other.internalServerMysqlUpgradeCmd) &&
0286             (userName                      == other.userName)                      &&
0287             (password                      == other.password)
0288            );
0289 }
0290 
0291 bool DbEngineParameters::operator!=(const DbEngineParameters& other) const
0292 {
0293     return (!operator == (other));
0294 }
0295 
0296 bool DbEngineParameters::isValid() const
0297 {
0298     if (isSQLite())
0299     {
0300         return !databaseNameCore.isEmpty();
0301     }
0302 
0303     return false;
0304 }
0305 
0306 bool DbEngineParameters::isSQLite() const
0307 {
0308     return (databaseType == QLatin1String("QSQLITE"));
0309 }
0310 
0311 bool DbEngineParameters::isMySQL() const
0312 {
0313     return (databaseType == QLatin1String("QMYSQL"));
0314 }
0315 
0316 QString DbEngineParameters::SQLiteDatabaseType()
0317 {
0318     return QLatin1String("QSQLITE");
0319 }
0320 
0321 QString DbEngineParameters::MySQLDatabaseType()
0322 {
0323     return QLatin1String("QMYSQL");
0324 }
0325 
0326 QString DbEngineParameters::SQLiteDatabaseFile() const
0327 {
0328     if (isSQLite())
0329     {
0330         return databaseNameCore;
0331     }
0332 
0333     return QString();
0334 }
0335 
0336 QByteArray DbEngineParameters::hash() const
0337 {
0338     QCryptographicHash md5(QCryptographicHash::Md5);
0339 
0340     md5.addData(databaseType.toUtf8());
0341     md5.addData(databaseNameCore.toUtf8());
0342     md5.addData(databaseNameThumbnails.toUtf8());
0343     md5.addData(databaseNameFace.toUtf8());
0344     md5.addData(databaseNameSimilarity.toUtf8());
0345     md5.addData(connectOptions.toUtf8());
0346     md5.addData(hostName.toUtf8());
0347     md5.addData((const char*)&port, sizeof(int));
0348     md5.addData(userName.toUtf8());
0349     md5.addData(password.toUtf8());
0350     md5.addData((const char*)&internalServer, sizeof(bool));
0351     md5.addData(internalServerDBPath.toUtf8());
0352 
0353     return md5.result().toHex();
0354 }
0355 
0356 DbEngineParameters DbEngineParameters::parametersFromConfig(const QString& configGroup)
0357 {
0358     DbEngineParameters parameters;
0359     parameters.readFromConfig(configGroup);
0360 
0361     return parameters;
0362 }
0363 
0364 void DbEngineParameters::readFromConfig(const QString& configGroup)
0365 {
0366     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0367     KConfigGroup group;
0368 
0369     if (configGroup.isNull())
0370     {
0371         group = config->group(configGroupDatabase);
0372     }
0373     else
0374     {
0375         group = config->group(configGroup);
0376     }
0377 
0378     databaseType = group.readEntry(configDatabaseType, QString());
0379 
0380     if (isSQLite())     // see bug #267131
0381     {
0382         databaseNameCore          = group.readPathEntry(configDatabaseName,                      QString());
0383         databaseNameThumbnails    = group.readPathEntry(configDatabaseNameThumbnails,            QString());
0384         databaseNameFace          = group.readPathEntry(configDatabaseNameFace,                  QString());
0385         databaseNameSimilarity    = group.readPathEntry(configDatabaseNameSimilarity,            QString());
0386         walMode                   = group.readEntry(configDatabaseWALMode,                       true);
0387     }
0388     else
0389     {
0390         databaseNameCore          = group.readEntry(configDatabaseName,                          QString());
0391         databaseNameThumbnails    = group.readEntry(configDatabaseNameThumbnails,                QString());
0392         databaseNameFace          = group.readEntry(configDatabaseNameFace,                      QString());
0393         databaseNameSimilarity    = group.readEntry(configDatabaseNameSimilarity,                QString());
0394     }
0395 
0396     hostName                      = group.readEntry(configDatabaseHostName,                      QString());
0397     port                          = group.readEntry(configDatabasePort,                          -1);
0398     userName                      = group.readEntry(configDatabaseUsername,                      QString());
0399 
0400     // Non encrypted password for compatibility.
0401 
0402     password                      = group.readEntry(configDatabasePassword,                      QString());
0403 
0404     if (password.isEmpty())
0405     {
0406         password                  = group.readEntry(configDatabaseEncryptedPassword,             QString());
0407 
0408         if (!password.isEmpty())
0409         {
0410             O0SimpleCrypt crypto(QCryptographicHash::hash(configDatabaseEncryptedPassword.latin1(),
0411                                                           QCryptographicHash::Sha1).toULongLong());
0412             password = crypto.decryptToString(password);
0413         }
0414     }
0415 
0416     connectOptions                = group.readEntry(configDatabaseConnectOptions,                QString());
0417 
0418 #if defined(HAVE_MYSQLSUPPORT) && defined(HAVE_INTERNALMYSQL)
0419 
0420     if (isSQLite())
0421     {
0422         internalServer                = group.readEntry(configInternalDatabaseServer,                false);
0423         internalServerDBPath          = group.readEntry(configInternalDatabaseServerPath,            QString());
0424         internalServerMysqlInitCmd    = group.readEntry(configInternalDatabaseServerMysqlInitCmd,    QString());
0425         internalServerMysqlAdminCmd   = group.readEntry(configInternalDatabaseServerMysqlAdminCmd,   QString());
0426         internalServerMysqlServerCmd  = group.readEntry(configInternalDatabaseServerMysqlServerCmd,  QString());
0427         internalServerMysqlUpgradeCmd = group.readEntry(configInternalDatabaseServerMysqlUpgradeCmd, QString());
0428     }
0429     else
0430     {
0431         internalServer                = group.readEntry(configInternalDatabaseServer,                false);
0432         internalServerDBPath          = group.readEntry(configInternalDatabaseServerPath,            serverPrivatePath());
0433         internalServerMysqlInitCmd    = group.readEntry(configInternalDatabaseServerMysqlInitCmd,    defaultMysqlInitCmd());
0434         internalServerMysqlAdminCmd   = group.readEntry(configInternalDatabaseServerMysqlAdminCmd,   defaultMysqlAdminCmd());
0435         internalServerMysqlServerCmd  = group.readEntry(configInternalDatabaseServerMysqlServerCmd,  defaultMysqlServerCmd());
0436         internalServerMysqlUpgradeCmd = group.readEntry(configInternalDatabaseServerMysqlUpgradeCmd, defaultMysqlUpgradeCmd());
0437     }
0438 
0439 #else
0440 
0441     internalServer                = false;
0442 
0443 #endif
0444 
0445     if (isSQLite() && !databaseNameCore.isNull())
0446     {
0447         QString orgName = databaseNameCore;
0448         setCoreDatabasePath(orgName);
0449         setThumbsDatabasePath(orgName);
0450         setFaceDatabasePath(orgName);
0451         setSimilarityDatabasePath(orgName);
0452     }
0453 }
0454 
0455 void DbEngineParameters::setInternalServerPath(const QString& path)
0456 {
0457     internalServerDBPath = path;
0458 }
0459 
0460 QString DbEngineParameters::internalServerPath() const
0461 {
0462     QFileInfo fileInfo(internalServerDBPath);
0463 
0464     return QDir::cleanPath(fileInfo.filePath());
0465 }
0466 
0467 void DbEngineParameters::setCoreDatabasePath(const QString& folderOrFileOrName)
0468 {
0469     if (isSQLite())
0470     {
0471         databaseNameCore = coreDatabaseFileSQLite(folderOrFileOrName);
0472     }
0473     else
0474     {
0475         databaseNameCore = folderOrFileOrName;
0476     }
0477 }
0478 
0479 void DbEngineParameters::setThumbsDatabasePath(const QString& folderOrFileOrName)
0480 {
0481     if (isSQLite())
0482     {
0483         databaseNameThumbnails = thumbnailDatabaseFileSQLite(folderOrFileOrName);
0484     }
0485     else
0486     {
0487         databaseNameThumbnails = folderOrFileOrName;
0488     }
0489 }
0490 
0491 void DbEngineParameters::setFaceDatabasePath(const QString& folderOrFileOrName)
0492 {
0493     if (isSQLite())
0494     {
0495         databaseNameFace = faceDatabaseFileSQLite(folderOrFileOrName);
0496     }
0497     else
0498     {
0499         databaseNameFace = folderOrFileOrName;
0500     }
0501 }
0502 
0503 void DbEngineParameters::setSimilarityDatabasePath(const QString& folderOrFileOrName)
0504 {
0505     if (isSQLite())
0506     {
0507         databaseNameSimilarity = similarityDatabaseFileSQLite(folderOrFileOrName);
0508     }
0509     else
0510     {
0511         databaseNameSimilarity = folderOrFileOrName;
0512     }
0513 }
0514 
0515 QString DbEngineParameters::coreDatabaseFileSQLite(const QString& folderOrFile)
0516 {
0517     QFileInfo fileInfo(folderOrFile);
0518 
0519     if (fileInfo.isDir())
0520     {
0521         return (QDir::cleanPath(fileInfo.filePath() + QLatin1Char('/') + QLatin1String(digikam4db)));
0522     }
0523 
0524     return QDir::cleanPath(folderOrFile);
0525 }
0526 
0527 QString DbEngineParameters::thumbnailDatabaseFileSQLite(const QString& folderOrFile)
0528 {
0529     QFileInfo fileInfo(folderOrFile);
0530 
0531     if (fileInfo.isDir())
0532     {
0533         return (QDir::cleanPath(fileInfo.filePath() + QLatin1Char('/') + QLatin1String(thumbnails_digikamdb)));
0534     }
0535 
0536     return QDir::cleanPath(folderOrFile);
0537 }
0538 
0539 QString DbEngineParameters::faceDatabaseFileSQLite(const QString& folderOrFile)
0540 {
0541     QFileInfo fileInfo(folderOrFile);
0542 
0543     if (fileInfo.isDir())
0544     {
0545         return (QDir::cleanPath(fileInfo.filePath() + QLatin1Char('/') + QLatin1String(face_digikamdb)));
0546     }
0547 
0548     return QDir::cleanPath(folderOrFile);
0549 }
0550 
0551 QString DbEngineParameters::similarityDatabaseFileSQLite(const QString& folderOrFile)
0552 {
0553     QFileInfo fileInfo(folderOrFile);
0554 
0555     if (fileInfo.isDir())
0556     {
0557         return (QDir::cleanPath(fileInfo.filePath() + QLatin1Char('/') + QLatin1String(similarity_digikamdb)));
0558     }
0559 
0560     return QDir::cleanPath(folderOrFile);
0561 }
0562 
0563 void DbEngineParameters::legacyAndDefaultChecks(const QString& suggestedPath)
0564 {
0565     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0566 
0567     // Additional semantic checks for the database section.
0568     // If the internal server should be started, then the connection options must be reset
0569 
0570     if ((databaseType == QLatin1String("QMYSQL")) && internalServer)
0571     {
0572         const QString miscDir      = serverPrivatePath() + QLatin1String("db_misc");
0573         databaseNameCore           = QLatin1String("digikam");
0574         databaseNameThumbnails     = QLatin1String("digikam");
0575         databaseNameFace           = QLatin1String("digikam");
0576         databaseNameSimilarity     = QLatin1String("digikam");
0577         internalServer             = true;
0578         userName                   = QLatin1String("root");
0579         password.clear();
0580 
0581 #ifdef Q_OS_WIN
0582 
0583         hostName                   = QLatin1String("localhost");
0584         port                       = 3307;
0585         connectOptions.clear();
0586 
0587 #else
0588 
0589         hostName.clear();
0590         port                       = -1;
0591         connectOptions             = QString::fromLatin1("UNIX_SOCKET=%1/mysql.socket").arg(miscDir);
0592 
0593 #endif
0594 
0595     }
0596 
0597     if (databaseType.isEmpty())
0598     {
0599         // Empty 1.3 config: migration from older versions
0600 
0601         KConfigGroup group = config->group(QLatin1String("Album Settings"));
0602 
0603         QString databaseFilePath;
0604 
0605         if      (group.hasKey(configDatabaseFilePathEntry))
0606         {
0607             // 1.0 - 1.2 style database file path?
0608 
0609             databaseFilePath = group.readEntry(configDatabaseFilePathEntry, QString());
0610         }
0611         else if (group.hasKey(configAlbumPathEntry))
0612         {
0613             // <= 0.9 style album path entry?
0614 
0615             databaseFilePath = group.readEntry(configAlbumPathEntry, QString());
0616         }
0617         else if (!suggestedPath.isNull())
0618         {
0619             databaseFilePath = suggestedPath;
0620         }
0621 
0622         if (!databaseFilePath.isEmpty())
0623         {
0624             *this = parametersForSQLite(coreDatabaseFileSQLite(databaseFilePath));
0625         }
0626 
0627         // Be aware that schema updating from version <= 0.9 requires reading the "Album Path", so do not remove it here
0628     }
0629 }
0630 
0631 void DbEngineParameters::removeLegacyConfig()
0632 {
0633     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0634     KConfigGroup group        = config->group(QLatin1String("Album Settings"));
0635 
0636     if (group.hasKey(configDatabaseFilePathEntry))
0637     {
0638         group.deleteEntry(configDatabaseFilePathEntry);
0639     }
0640 
0641     if (group.hasKey(configAlbumPathEntry))
0642     {
0643         group.deleteEntry(configAlbumPathEntry);
0644     }
0645 }
0646 
0647 void DbEngineParameters::writeToConfig(const QString& configGroup) const
0648 {
0649     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0650     KConfigGroup group;
0651 
0652     if (configGroup.isNull())
0653     {
0654         group = config->group(configGroupDatabase);
0655     }
0656     else
0657     {
0658         group = config->group(configGroup);
0659     }
0660 
0661     QString dbName           = getCoreDatabaseNameOrDir();
0662     QString dbNameThumbs     = getThumbsDatabaseNameOrDir();
0663     QString dbNameFace       = getFaceDatabaseNameOrDir();
0664     QString dbNameSimilarity = getSimilarityDatabaseNameOrDir();
0665 
0666     group.writeEntry(configDatabaseType,                          databaseType);
0667     group.writeEntry(configDatabaseName,                          dbName);
0668     group.writeEntry(configDatabaseNameThumbnails,                dbNameThumbs);
0669     group.writeEntry(configDatabaseNameFace,                      dbNameFace);
0670     group.writeEntry(configDatabaseNameSimilarity,                dbNameSimilarity);
0671     group.writeEntry(configDatabaseHostName,                      hostName);
0672     group.writeEntry(configDatabasePort,                          port);
0673     group.writeEntry(configDatabaseWALMode,                       walMode);
0674     group.writeEntry(configDatabaseUsername,                      userName);
0675 
0676     O0SimpleCrypt crypto(QCryptographicHash::hash(configDatabaseEncryptedPassword.latin1(),
0677                                                   QCryptographicHash::Sha1).toULongLong());
0678     group.writeEntry(configDatabaseEncryptedPassword,             crypto.encryptToString(password));
0679 
0680     group.writeEntry(configDatabaseConnectOptions,                connectOptions);
0681     group.writeEntry(configInternalDatabaseServer,                internalServer);
0682     group.writeEntry(configInternalDatabaseServerPath,            internalServerDBPath);
0683     group.writeEntry(configInternalDatabaseServerMysqlInitCmd,    internalServerMysqlInitCmd);
0684     group.writeEntry(configInternalDatabaseServerMysqlAdminCmd,   internalServerMysqlAdminCmd);
0685     group.writeEntry(configInternalDatabaseServerMysqlServerCmd,  internalServerMysqlServerCmd);
0686     group.writeEntry(configInternalDatabaseServerMysqlUpgradeCmd, internalServerMysqlUpgradeCmd);
0687 
0688     group.deleteEntry(configDatabasePassword);  // Remove non encrypted password
0689 }
0690 
0691 QString DbEngineParameters::getCoreDatabaseNameOrDir() const
0692 {
0693     if (isSQLite())
0694     {
0695         return coreDatabaseDirectorySQLite(databaseNameCore);
0696     }
0697 
0698     return databaseNameCore;
0699 }
0700 
0701 QString DbEngineParameters::getThumbsDatabaseNameOrDir() const
0702 {
0703     if (isSQLite())
0704     {
0705         return thumbnailDatabaseDirectorySQLite(databaseNameThumbnails);
0706     }
0707 
0708     return databaseNameThumbnails;
0709 }
0710 
0711 QString DbEngineParameters::getFaceDatabaseNameOrDir() const
0712 {
0713     if (isSQLite())
0714     {
0715         return faceDatabaseDirectorySQLite(databaseNameFace);
0716     }
0717 
0718     return databaseNameFace;
0719 }
0720 
0721 QString DbEngineParameters::getSimilarityDatabaseNameOrDir() const
0722 {
0723     if (isSQLite())
0724     {
0725         return similarityDatabaseDirectorySQLite(databaseNameSimilarity);
0726     }
0727 
0728     return databaseNameSimilarity;
0729 }
0730 
0731 QString DbEngineParameters::coreDatabaseDirectorySQLite(const QString& path)
0732 {
0733     if (path.endsWith(QLatin1String(digikam4db)))
0734     {
0735         QString chopped(path);
0736         chopped.chop(QString(QLatin1String(digikam4db)).length());
0737 
0738         return chopped;
0739     }
0740 
0741     return path;
0742 }
0743 
0744 QString DbEngineParameters::thumbnailDatabaseDirectorySQLite(const QString& path)
0745 {
0746     if (path.endsWith(QLatin1String(thumbnails_digikamdb)))
0747     {
0748         QString chopped(path);
0749         chopped.chop(QString(QLatin1String(thumbnails_digikamdb)).length());
0750 
0751         return chopped;
0752     }
0753 
0754     return path;
0755 }
0756 
0757 QString DbEngineParameters::faceDatabaseDirectorySQLite(const QString& path)
0758 {
0759     if (path.endsWith(QLatin1String(face_digikamdb)))
0760     {
0761         QString chopped(path);
0762         chopped.chop(QString(QLatin1String(face_digikamdb)).length());
0763 
0764         return chopped;
0765     }
0766 
0767     return path;
0768 }
0769 
0770 QString DbEngineParameters::similarityDatabaseDirectorySQLite(const QString& path)
0771 {
0772     if (path.endsWith(QLatin1String(similarity_digikamdb)))
0773     {
0774         QString chopped(path);
0775         chopped.chop(QString(QLatin1String(similarity_digikamdb)).length());
0776 
0777         return chopped;
0778     }
0779 
0780     return path;
0781 }
0782 
0783 DbEngineParameters DbEngineParameters::defaultParameters(const QString& databaseType)
0784 {
0785     DbEngineParameters parameters;
0786 
0787     // only the database name is needed
0788 
0789     DbEngineConfigSettings config            = DbEngineConfig::element(databaseType);
0790     parameters.databaseType                  = databaseType;
0791     parameters.databaseNameCore              = config.databaseName;
0792     parameters.databaseNameThumbnails        = config.databaseName;
0793     parameters.databaseNameFace              = config.databaseName;
0794     parameters.databaseNameSimilarity        = config.databaseName;
0795     parameters.userName                      = config.userName;
0796     parameters.password                      = config.password;
0797     parameters.walMode                       = false;
0798     parameters.internalServer                = (databaseType == QLatin1String("QMYSQL"));
0799     parameters.internalServerDBPath          = (databaseType == QLatin1String("QMYSQL")) ? serverPrivatePath()      : QString();
0800     parameters.internalServerMysqlInitCmd    = (databaseType == QLatin1String("QMYSQL")) ? defaultMysqlInitCmd()    : QString();
0801     parameters.internalServerMysqlAdminCmd   = (databaseType == QLatin1String("QMYSQL")) ? defaultMysqlAdminCmd()   : QString();
0802     parameters.internalServerMysqlServerCmd  = (databaseType == QLatin1String("QMYSQL")) ? defaultMysqlServerCmd()  : QString();
0803     parameters.internalServerMysqlUpgradeCmd = (databaseType == QLatin1String("QMYSQL")) ? defaultMysqlUpgradeCmd() : QString();
0804 
0805     QString hostName                       = config.hostName;
0806     QString port                           = config.port;
0807     QString connectOptions                 = config.connectOptions;
0808 
0809 #ifdef Q_OS_WIN
0810 
0811     hostName.replace(QLatin1String("$$DBHOSTNAME$$"),      (databaseType == QLatin1String("QMYSQL"))
0812                                                            ? QLatin1String("localhost")
0813                                                            : QString());
0814 
0815     port.replace(QLatin1String("$$DBPORT$$"),              (databaseType == QLatin1String("QMYSQL"))
0816                                                            ? QLatin1String("3307")
0817                                                            : QLatin1String("-1"));
0818 
0819     connectOptions.replace(QLatin1String("$$DBOPTIONS$$"), QString());
0820 
0821 #else
0822 
0823     hostName.replace(QLatin1String("$$DBHOSTNAME$$"),      QString());
0824 
0825     port.replace(QLatin1String("$$DBPORT$$"),              QLatin1String("-1"));
0826 
0827     const QString miscDir                 = serverPrivatePath() + QLatin1String("db_misc");
0828     connectOptions.replace(QLatin1String("$$DBOPTIONS$$"), (databaseType == QLatin1String("QMYSQL"))
0829                                                            ? QString::fromLatin1("UNIX_SOCKET=%1/mysql.socket").arg(miscDir)
0830                                                            : QString());
0831 #endif
0832 
0833     parameters.hostName                   = hostName;
0834     parameters.port                       = port.toInt();
0835     parameters.connectOptions             = connectOptions;
0836 
0837     qCDebug(DIGIKAM_DBENGINE_LOG) << "ConnectOptions " << parameters.connectOptions;
0838 
0839     return parameters;
0840 }
0841 
0842 DbEngineParameters DbEngineParameters::thumbnailParameters() const
0843 {
0844     DbEngineParameters params = *this;
0845     params.databaseNameCore   = databaseNameThumbnails;
0846 
0847     return params;
0848 }
0849 
0850 DbEngineParameters DbEngineParameters::faceParameters() const
0851 {
0852     DbEngineParameters params = *this;
0853     params.databaseNameCore   = databaseNameFace;
0854 
0855     return params;
0856 }
0857 
0858 DbEngineParameters DbEngineParameters::similarityParameters() const
0859 {
0860     DbEngineParameters params = *this;
0861     params.databaseNameCore   = databaseNameSimilarity;
0862 
0863     return params;
0864 }
0865 
0866 DbEngineParameters DbEngineParameters::parametersForSQLite(const QString& databaseFile)
0867 {
0868     // only the database name is needed
0869 
0870     DbEngineParameters params(QLatin1String("QSQLITE"), databaseFile);
0871     params.setCoreDatabasePath(databaseFile);
0872     params.setThumbsDatabasePath(params.getCoreDatabaseNameOrDir());
0873     params.setFaceDatabasePath(params.getCoreDatabaseNameOrDir());
0874     params.setSimilarityDatabasePath(params.getCoreDatabaseNameOrDir());
0875 
0876     return params;
0877 }
0878 
0879 DbEngineParameters DbEngineParameters::parametersForSQLiteDefaultFile(const QString& directory)
0880 {
0881     return parametersForSQLite(QDir::cleanPath(directory + QLatin1Char('/') + QLatin1String(digikam4db)));
0882 }
0883 
0884 QString DbEngineParameters::defaultMysqlInitCmd()      // For Linux, Windows and OSX
0885 {
0886     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0887     KConfigGroup group        = config->group(configGroupDatabase);
0888 
0889     if (group.readEntry(configInternalDatabaseServerUseMariaDB, true))
0890     {
0891         return QLatin1String("mariadb-install-db");
0892     }
0893 
0894     return QLatin1String("mysql_install_db");
0895 }
0896 
0897 QString DbEngineParameters::defaultMysqlAdminCmd()     // For Linux, Windows and OSX
0898 {
0899     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0900     KConfigGroup group        = config->group(configGroupDatabase);
0901 
0902     if (group.readEntry(configInternalDatabaseServerUseMariaDB, true))
0903     {
0904         return QLatin1String("mariadb-admin");
0905     }
0906 
0907     return QLatin1String("mysqladmin");
0908 }
0909 
0910 QString DbEngineParameters::defaultMysqlServerCmd()    // For Linux, Windows and OSX
0911 {
0912     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0913     KConfigGroup group        = config->group(configGroupDatabase);
0914 
0915     if (group.readEntry(configInternalDatabaseServerUseMariaDB, true))
0916     {
0917         return QLatin1String("mariadbd");
0918     }
0919 
0920     return QLatin1String("mysqld");
0921 }
0922 
0923 QString DbEngineParameters::defaultMysqlUpgradeCmd()   // For Linux, Windows and OSX
0924 {
0925     KSharedConfig::Ptr config = KSharedConfig::openConfig();
0926     KConfigGroup group        = config->group(configGroupDatabase);
0927 
0928     if (group.readEntry(configInternalDatabaseServerUseMariaDB, true))
0929     {
0930         return QLatin1String("mariadb-upgrade");
0931     }
0932 
0933     return QLatin1String("mysql_upgrade");
0934 }
0935 
0936 // --------------------------------
0937 
0938 QDebug operator<<(QDebug dbg, const DbEngineParameters& p)
0939 {
0940     dbg.nospace() << "Database Parameters:"                                                                    << QT_ENDL;
0941     dbg.nospace() << "   Type:                        " << p.databaseType                                      << QT_ENDL;
0942     dbg.nospace() << "   DB Core Name:                " << p.databaseNameCore                                  << QT_ENDL;
0943     dbg.nospace() << "   DB Thumbs Name:              " << p.databaseNameThumbnails                            << QT_ENDL;
0944     dbg.nospace() << "   DB Face Name:                " << p.databaseNameFace                                  << QT_ENDL;
0945     dbg.nospace() << "   DB Similarity Name:          " << p.databaseNameSimilarity                            << QT_ENDL;
0946     dbg.nospace() << "   Connect Options:             " << p.connectOptions                                    << QT_ENDL;
0947     dbg.nospace() << "   Host Name:                   " << p.hostName                                          << QT_ENDL;
0948     dbg.nospace() << "   Host Port:                   " << p.port                                              << QT_ENDL;
0949     dbg.nospace() << "   WAL Mode:                    " << p.walMode                                           << QT_ENDL;
0950     dbg.nospace() << "   Internal Server:             " << p.internalServer                                    << QT_ENDL;
0951     dbg.nospace() << "   Internal Server Path:        " << p.internalServerDBPath                              << QT_ENDL;
0952     dbg.nospace() << "   Internal Server Init Cmd:    " << p.internalServerMysqlInitCmd                        << QT_ENDL;
0953     dbg.nospace() << "   Internal Server Admin Cmd:   " << p.internalServerMysqlAdminCmd                       << QT_ENDL;
0954     dbg.nospace() << "   Internal Server Server Cmd:  " << p.internalServerMysqlServerCmd                      << QT_ENDL;
0955     dbg.nospace() << "   Internal Server Upgrade Cmd: " << p.internalServerMysqlUpgradeCmd                     << QT_ENDL;
0956     dbg.nospace() << "   Username:                    " << p.userName                                          << QT_ENDL;
0957     dbg.nospace() << "   Password:                    " << QString().fill(QLatin1Char('X'), p.password.size()) << QT_ENDL;
0958 
0959     return dbg.space();
0960 }
0961 
0962 } // namespace Digikam