1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2007-03-18
7 * Description : Database Engine storage container for connection parameters.
8 *
9 * Copyright (C) 2007-2008 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
10 * Copyright (C) 2010 by Holger Foerster <hamsi2k at freenet dot de>
11 * Copyright (C) 2010-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
12 * Copyright (C) 2018 by Mario Frank <mario dot frank at uni minus potsdam dot de>
13 *
14 * This program is free software; you can redistribute it
15 * and/or modify it under the terms of the GNU General
16 * Public License as published by the Free Software Foundation;
17 * either version 2, or (at your option)
18 * any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * ============================================================ */
26
27 #include "dbengineparameters.h"
28
29 // Qt includes
30
31 #include <QDir>
32 #include <QUrlQuery>
33 #include <QFile>
34 #include <QCryptographicHash>
35 #include <QStandardPaths>
36
37 // KDE includes
38
39 #include <kconfiggroup.h>
40 #include <ksharedconfig.h>
41
42 // Local includes
43
44 #include "digikam_config.h"
45 #include "digikam_debug.h"
46 #include "o0simplecrypt.h" // For password encrypt
47
48 namespace
49 {
50
51 static const char* configGroupDatabase = "Database Settings";
52 static const char* configInternalDatabaseServer = "Internal Database Server";
53 static const char* configInternalDatabaseServerPath = "Internal Database Server Path";
54 static const char* configInternalDatabaseServerMysqlAdminCmd = "Internal Database Server Mysql Admin Command";
55 static const char* configInternalDatabaseServerMysqlServCmd = "Internal Database Server Mysql Server Command";
56 static const char* configInternalDatabaseServerMysqlInitCmd = "Internal Database Server Mysql Init Command";
57 static const char* configDatabaseType = "Database Type";
58 static const char* configDatabaseName = "Database Name"; ///< For Sqlite the DB file path, for Mysql the DB name
59 static const char* configDatabaseNameThumbnails = "Database Name Thumbnails"; ///< For Sqlite the DB file path, for Mysql the DB name
60 static const char* configDatabaseNameFace = "Database Name Face"; ///< For Sqlite the DB file path, for Mysql the DB name
61 static const char* configDatabaseNameSimilarity = "Database Name Similarity"; ///< For Sqlite the DB file path, for Mysql the DB name
62 static const char* configDatabaseHostName = "Database Hostname";
63 static const char* configDatabasePort = "Database Port";
64 static const char* configDatabaseUsername = "Database Username";
65 static const char* configDatabasePassword = "Database Password"; ///< For compatbilitity. Use crypted version instead.
66 static const char* configDatabaseEncryptedPassword = "Database Encrypted Password";
67 static const char* configDatabaseConnectOptions = "Database Connectoptions";
68 /// Legacy for older versions.
69 static const char* configDatabaseFilePathEntry = "Database File Path";
70 static const char* configAlbumPathEntry = "Album Path";
71 /// Sqlite DB file names
72 static const char* digikam4db = "digikam4.db";
73 static const char* thumbnails_digikamdb = "thumbnails-digikam.db";
74 static const char* face_digikamdb = "recognition.db";
75 static const char* similarity_digikamdb = "similarity.db";
76
77 }
78
79 namespace Digikam
80 {
81
internalServerPrivatePath()82 QString DbEngineParameters::internalServerPrivatePath()
83 {
84 return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) +
85 QLatin1String("/digikam/");
86 }
87
DbEngineParameters()88 DbEngineParameters::DbEngineParameters()
89 : port (-1),
90 internalServer(false)
91 {
92 }
93
DbEngineParameters(const QString & _type,const QString & _databaseNameCore,const QString & _connectOptions,const QString & _hostName,int _port,bool _internalServer,const QString & _userName,const QString & _password,const QString & _databaseNameThumbnails,const QString & _databaseNameFace,const QString & _databaseNameSimilarity,const QString & _internalServerDBPath,const QString & _internalServerMysqlAdminCmd,const QString & _internalServerMysqlServCmd,const QString & _internalServerMysqlInitCmd)94 DbEngineParameters::DbEngineParameters(const QString& _type,
95 const QString& _databaseNameCore,
96 const QString& _connectOptions,
97 const QString& _hostName,
98 int _port,
99 bool _internalServer,
100 const QString& _userName,
101 const QString& _password,
102 const QString& _databaseNameThumbnails,
103 const QString& _databaseNameFace,
104 const QString& _databaseNameSimilarity,
105 const QString& _internalServerDBPath,
106 const QString& _internalServerMysqlAdminCmd,
107 const QString& _internalServerMysqlServCmd,
108 const QString& _internalServerMysqlInitCmd)
109 : databaseType (_type),
110 databaseNameCore (_databaseNameCore),
111 connectOptions (_connectOptions),
112 hostName (_hostName),
113 port (_port),
114 internalServer (_internalServer),
115 userName (_userName),
116 password (_password),
117 databaseNameThumbnails (_databaseNameThumbnails),
118 databaseNameFace (_databaseNameFace),
119 databaseNameSimilarity (_databaseNameSimilarity),
120 internalServerDBPath (_internalServerDBPath),
121 internalServerMysqlAdminCmd (_internalServerMysqlAdminCmd),
122 internalServerMysqlServCmd (_internalServerMysqlServCmd),
123 internalServerMysqlInitCmd (_internalServerMysqlInitCmd)
124 {
125 }
126
DbEngineParameters(const QUrl & url)127 DbEngineParameters::DbEngineParameters(const QUrl& url)
128 : databaseType (QUrlQuery(url).queryItemValue(QLatin1String("databaseType"))),
129 databaseNameCore (QUrlQuery(url).queryItemValue(QLatin1String("databaseNameCore"))),
130 connectOptions (QUrlQuery(url).queryItemValue(QLatin1String("connectOptions"))),
131 hostName (QUrlQuery(url).queryItemValue(QLatin1String("hostName"))),
132 port (-1),
133 internalServer (false),
134 databaseNameThumbnails(QUrlQuery(url).queryItemValue(QLatin1String("databaseNameThumbnails"))),
135 databaseNameFace (QUrlQuery(url).queryItemValue(QLatin1String("databaseNameFace"))),
136 databaseNameSimilarity(QUrlQuery(url).queryItemValue(QLatin1String("databaseNameSimilarity")))
137 {
138 QString queryPort = QUrlQuery(url).queryItemValue(QLatin1String("port"));
139
140 if (!queryPort.isNull())
141 {
142 port = queryPort.toInt();
143 }
144
145 #if defined(HAVE_MYSQLSUPPORT) && defined(HAVE_INTERNALMYSQL)
146
147 QString queryServer = QUrlQuery(url).queryItemValue(QLatin1String("internalServer"));
148
149 if (!queryServer.isNull())
150 {
151 internalServer = (queryServer == QLatin1String("true"));
152 }
153
154 queryServer = QUrlQuery(url).queryItemValue(QLatin1String("internalServerPath"));
155
156 if (!queryServer.isNull())
157 {
158 internalServerDBPath = QUrlQuery(url).queryItemValue(QLatin1String("internalServerPath"));
159 }
160 else
161 {
162 internalServerDBPath = internalServerPrivatePath();
163 }
164
165 internalServerMysqlAdminCmd = QUrlQuery(url).queryItemValue(QLatin1String("internalServerMysqlAdminCmd"));
166 internalServerMysqlServCmd = QUrlQuery(url).queryItemValue(QLatin1String("internalServerMysqlServCmd"));
167 internalServerMysqlInitCmd = QUrlQuery(url).queryItemValue(QLatin1String("internalServerMysqlInitCmd"));
168
169 #else
170
171 internalServer = false;
172
173 #endif
174
175 userName = QUrlQuery(url).queryItemValue(QLatin1String("userName"));
176 password = QUrlQuery(url).queryItemValue(QLatin1String("password"));
177 }
178
insertInUrl(QUrl & url) const179 void DbEngineParameters::insertInUrl(QUrl& url) const
180 {
181 removeFromUrl(url);
182
183 QUrlQuery q(url);
184 q.addQueryItem(QLatin1String("databaseType"), databaseType);
185 q.addQueryItem(QLatin1String("databaseNameCore"), databaseNameCore);
186 q.addQueryItem(QLatin1String("databaseNameThumbnails"), databaseNameThumbnails);
187 q.addQueryItem(QLatin1String("databaseNameFace"), databaseNameFace);
188 q.addQueryItem(QLatin1String("databaseNameSimilarity"), databaseNameSimilarity);
189
190 if (!connectOptions.isNull())
191 {
192 q.addQueryItem(QLatin1String("connectOptions"), connectOptions);
193 }
194
195 if (!hostName.isNull())
196 {
197 q.addQueryItem(QLatin1String("hostName"), hostName);
198 }
199
200 if (port != -1)
201 {
202 q.addQueryItem(QLatin1String("port"), QString::number(port));
203 }
204
205 if (internalServer)
206 {
207 q.addQueryItem(QLatin1String("internalServer"), QLatin1String("true"));
208 q.addQueryItem(QLatin1String("internalServerPath"), internalServerDBPath);
209 q.addQueryItem(QLatin1String("internalServerMysqlAdminCmd"), internalServerMysqlAdminCmd);
210 q.addQueryItem(QLatin1String("internalServerMysqlServCmd"), internalServerMysqlServCmd);
211 q.addQueryItem(QLatin1String("internalServerMysqlInitCmd"), internalServerMysqlInitCmd);
212 }
213
214 if (!userName.isNull())
215 {
216 q.addQueryItem(QLatin1String("userName"), userName);
217 }
218
219 if (!password.isNull())
220 {
221 q.addQueryItem(QLatin1String("password"), password);
222 }
223
224 url.setQuery(q);
225 }
226
removeFromUrl(QUrl & url)227 void DbEngineParameters::removeFromUrl(QUrl& url)
228 {
229 QUrlQuery q(url);
230
231 q.removeQueryItem(QLatin1String("databaseType"));
232 q.removeQueryItem(QLatin1String("databaseNameCore"));
233 q.removeQueryItem(QLatin1String("databaseNameThumbnails"));
234 q.removeQueryItem(QLatin1String("databaseNameFace"));
235 q.removeQueryItem(QLatin1String("databaseNameSimilarity"));
236 q.removeQueryItem(QLatin1String("connectOptions"));
237 q.removeQueryItem(QLatin1String("hostName"));
238 q.removeQueryItem(QLatin1String("port"));
239 q.removeQueryItem(QLatin1String("internalServer"));
240 q.removeQueryItem(QLatin1String("internalServerPath"));
241 q.removeQueryItem(QLatin1String("internalServerMysqlAdminCmd"));
242 q.removeQueryItem(QLatin1String("internalServerMysqlServCmd"));
243 q.removeQueryItem(QLatin1String("internalServerMysqlInitCmd"));
244 q.removeQueryItem(QLatin1String("userName"));
245 q.removeQueryItem(QLatin1String("password"));
246
247 url.setQuery(q);
248 }
249
operator ==(const DbEngineParameters & other) const250 bool DbEngineParameters::operator==(const DbEngineParameters& other) const
251 {
252 return (
253 (databaseType == other.databaseType) &&
254 (databaseNameCore == other.databaseNameCore) &&
255 (databaseNameThumbnails == other.databaseNameThumbnails) &&
256 (databaseNameFace == other.databaseNameFace) &&
257 (databaseNameSimilarity == other.databaseNameSimilarity) &&
258 (connectOptions == other.connectOptions) &&
259 (hostName == other.hostName) &&
260 (port == other.port) &&
261 (internalServer == other.internalServer) &&
262 (internalServerDBPath == other.internalServerDBPath) &&
263 (internalServerMysqlAdminCmd == other.internalServerMysqlAdminCmd) &&
264 (internalServerMysqlServCmd == other.internalServerMysqlServCmd) &&
265 (internalServerMysqlInitCmd == other.internalServerMysqlInitCmd) &&
266 (userName == other.userName) &&
267 (password == other.password)
268 );
269 }
270
operator !=(const DbEngineParameters & other) const271 bool DbEngineParameters::operator!=(const DbEngineParameters& other) const
272 {
273 return (!operator == (other));
274 }
275
isValid() const276 bool DbEngineParameters::isValid() const
277 {
278 if (isSQLite())
279 {
280 return !databaseNameCore.isEmpty();
281 }
282
283 return false;
284 }
285
isSQLite() const286 bool DbEngineParameters::isSQLite() const
287 {
288 return (databaseType == QLatin1String("QSQLITE"));
289 }
290
isMySQL() const291 bool DbEngineParameters::isMySQL() const
292 {
293 return (databaseType == QLatin1String("QMYSQL"));
294 }
295
SQLiteDatabaseType()296 QString DbEngineParameters::SQLiteDatabaseType()
297 {
298 return QLatin1String("QSQLITE");
299 }
300
MySQLDatabaseType()301 QString DbEngineParameters::MySQLDatabaseType()
302 {
303 return QLatin1String("QMYSQL");
304 }
305
SQLiteDatabaseFile() const306 QString DbEngineParameters::SQLiteDatabaseFile() const
307 {
308 if (isSQLite())
309 {
310 return databaseNameCore;
311 }
312
313 return QString();
314 }
315
hash() const316 QByteArray DbEngineParameters::hash() const
317 {
318 QCryptographicHash md5(QCryptographicHash::Md5);
319
320 md5.addData(databaseType.toUtf8());
321 md5.addData(databaseNameCore.toUtf8());
322 md5.addData(databaseNameThumbnails.toUtf8());
323 md5.addData(databaseNameFace.toUtf8());
324 md5.addData(databaseNameSimilarity.toUtf8());
325 md5.addData(connectOptions.toUtf8());
326 md5.addData(hostName.toUtf8());
327 md5.addData((const char*)&port, sizeof(int));
328 md5.addData(userName.toUtf8());
329 md5.addData(password.toUtf8());
330 md5.addData((const char*)&internalServer, sizeof(bool));
331 md5.addData(internalServerDBPath.toUtf8());
332
333 return md5.result().toHex();
334 }
335
parametersFromConfig(const QString & configGroup)336 DbEngineParameters DbEngineParameters::parametersFromConfig(const QString& configGroup)
337 {
338 DbEngineParameters parameters;
339 parameters.readFromConfig(configGroup);
340
341 return parameters;
342 }
343
readFromConfig(const QString & configGroup)344 void DbEngineParameters::readFromConfig(const QString& configGroup)
345 {
346 KSharedConfig::Ptr config = KSharedConfig::openConfig();
347 KConfigGroup group;
348
349 if (configGroup.isNull())
350 {
351 group = config->group(configGroupDatabase);
352 }
353 else
354 {
355 group = config->group(configGroup);
356 }
357
358 databaseType = group.readEntry(configDatabaseType, QString());
359
360 if (isSQLite()) // see bug #267131
361 {
362 databaseNameCore = group.readPathEntry(configDatabaseName, QString());
363 databaseNameThumbnails = group.readPathEntry(configDatabaseNameThumbnails, QString());
364 databaseNameFace = group.readPathEntry(configDatabaseNameFace, QString());
365 databaseNameSimilarity = group.readPathEntry(configDatabaseNameSimilarity, QString());
366 }
367 else
368 {
369 databaseNameCore = group.readEntry(configDatabaseName, QString());
370 databaseNameThumbnails = group.readEntry(configDatabaseNameThumbnails, QString());
371 databaseNameFace = group.readEntry(configDatabaseNameFace, QString());
372 databaseNameSimilarity = group.readEntry(configDatabaseNameSimilarity, QString());
373 }
374
375 hostName = group.readEntry(configDatabaseHostName, QString());
376 port = group.readEntry(configDatabasePort, -1);
377 userName = group.readEntry(configDatabaseUsername, QString());
378
379 // Non encrypted password for compatibility.
380
381 password = group.readEntry(configDatabasePassword, QString());
382
383 if (password.isEmpty())
384 {
385 password = group.readEntry(configDatabaseEncryptedPassword, QString());
386
387 if (!password.isEmpty())
388 {
389 O0SimpleCrypt crypto(QCryptographicHash::hash(configDatabaseEncryptedPassword, QCryptographicHash::Sha1).toULongLong());
390 password = crypto.decryptToString(password);
391 }
392 }
393
394 connectOptions = group.readEntry(configDatabaseConnectOptions, QString());
395
396 #if defined(HAVE_MYSQLSUPPORT) && defined(HAVE_INTERNALMYSQL)
397
398 internalServer = group.readEntry(configInternalDatabaseServer, false);
399 internalServerDBPath = group.readEntry(configInternalDatabaseServerPath, internalServerPrivatePath());
400 internalServerMysqlAdminCmd = group.readEntry(configInternalDatabaseServerMysqlAdminCmd, defaultMysqlAdminCmd());
401 internalServerMysqlServCmd = group.readEntry(configInternalDatabaseServerMysqlServCmd, defaultMysqlServerCmd());
402 internalServerMysqlInitCmd = group.readEntry(configInternalDatabaseServerMysqlInitCmd, defaultMysqlInitCmd());
403
404 #else
405
406 internalServer = false;
407
408 #endif
409
410 if (isSQLite() && !databaseNameCore.isNull())
411 {
412 QString orgName = databaseNameCore;
413 setCoreDatabasePath(orgName);
414 setThumbsDatabasePath(orgName);
415 setFaceDatabasePath(orgName);
416 setSimilarityDatabasePath(orgName);
417 }
418 }
419
setInternalServerPath(const QString & path)420 void DbEngineParameters::setInternalServerPath(const QString& path)
421 {
422 internalServerDBPath = path;
423 }
424
internalServerPath() const425 QString DbEngineParameters::internalServerPath() const
426 {
427 QFileInfo fileInfo(internalServerDBPath);
428
429 return QDir::cleanPath(fileInfo.filePath());
430 }
431
setCoreDatabasePath(const QString & folderOrFileOrName)432 void DbEngineParameters::setCoreDatabasePath(const QString& folderOrFileOrName)
433 {
434 if (isSQLite())
435 {
436 databaseNameCore = coreDatabaseFileSQLite(folderOrFileOrName);
437 }
438 else
439 {
440 databaseNameCore = folderOrFileOrName;
441 }
442 }
443
setThumbsDatabasePath(const QString & folderOrFileOrName)444 void DbEngineParameters::setThumbsDatabasePath(const QString& folderOrFileOrName)
445 {
446 if (isSQLite())
447 {
448 databaseNameThumbnails = thumbnailDatabaseFileSQLite(folderOrFileOrName);
449 }
450 else
451 {
452 databaseNameThumbnails = folderOrFileOrName;
453 }
454 }
455
setFaceDatabasePath(const QString & folderOrFileOrName)456 void DbEngineParameters::setFaceDatabasePath(const QString& folderOrFileOrName)
457 {
458 if (isSQLite())
459 {
460 databaseNameFace = faceDatabaseFileSQLite(folderOrFileOrName);
461 }
462 else
463 {
464 databaseNameFace = folderOrFileOrName;
465 }
466 }
467
setSimilarityDatabasePath(const QString & folderOrFileOrName)468 void DbEngineParameters::setSimilarityDatabasePath(const QString& folderOrFileOrName)
469 {
470 if (isSQLite())
471 {
472 databaseNameSimilarity = similarityDatabaseFileSQLite(folderOrFileOrName);
473 }
474 else
475 {
476 databaseNameSimilarity = folderOrFileOrName;
477 }
478 }
479
coreDatabaseFileSQLite(const QString & folderOrFile)480 QString DbEngineParameters::coreDatabaseFileSQLite(const QString& folderOrFile)
481 {
482 QFileInfo fileInfo(folderOrFile);
483
484 if (fileInfo.isDir())
485 {
486 return (QDir::cleanPath(fileInfo.filePath() + QLatin1Char('/') + QLatin1String(digikam4db)));
487 }
488
489 return QDir::cleanPath(folderOrFile);
490 }
491
thumbnailDatabaseFileSQLite(const QString & folderOrFile)492 QString DbEngineParameters::thumbnailDatabaseFileSQLite(const QString& folderOrFile)
493 {
494 QFileInfo fileInfo(folderOrFile);
495
496 if (fileInfo.isDir())
497 {
498 return (QDir::cleanPath(fileInfo.filePath() + QLatin1Char('/') + QLatin1String(thumbnails_digikamdb)));
499 }
500
501 return QDir::cleanPath(folderOrFile);
502 }
503
faceDatabaseFileSQLite(const QString & folderOrFile)504 QString DbEngineParameters::faceDatabaseFileSQLite(const QString& folderOrFile)
505 {
506 QFileInfo fileInfo(folderOrFile);
507
508 if (fileInfo.isDir())
509 {
510 return (QDir::cleanPath(fileInfo.filePath() + QLatin1Char('/') + QLatin1String(face_digikamdb)));
511 }
512
513 return QDir::cleanPath(folderOrFile);
514 }
515
similarityDatabaseFileSQLite(const QString & folderOrFile)516 QString DbEngineParameters::similarityDatabaseFileSQLite(const QString& folderOrFile)
517 {
518 QFileInfo fileInfo(folderOrFile);
519
520 if (fileInfo.isDir())
521 {
522 return (QDir::cleanPath(fileInfo.filePath() + QLatin1Char('/') + QLatin1String(similarity_digikamdb)));
523 }
524
525 return QDir::cleanPath(folderOrFile);
526 }
527
legacyAndDefaultChecks(const QString & suggestedPath)528 void DbEngineParameters::legacyAndDefaultChecks(const QString& suggestedPath)
529 {
530 KSharedConfig::Ptr config = KSharedConfig::openConfig();
531
532 // Additional semantic checks for the database section.
533 // If the internal server should be started, then the connection options must be reset
534
535 if ((databaseType == QLatin1String("QMYSQL")) && internalServer)
536 {
537 const QString miscDir = internalServerPrivatePath() + QLatin1String("db_misc");
538 databaseNameCore = QLatin1String("digikam");
539 databaseNameThumbnails = QLatin1String("digikam");
540 databaseNameFace = QLatin1String("digikam");
541 databaseNameSimilarity = QLatin1String("digikam");
542 internalServer = true;
543 userName = QLatin1String("root");
544 password.clear();
545
546 #ifdef Q_OS_WIN
547
548 hostName = QLatin1String("localhost");
549 port = 3307;
550 connectOptions.clear();
551
552 #else
553
554 hostName.clear();
555 port = -1;
556 connectOptions = QString::fromLatin1("UNIX_SOCKET=%1/mysql.socket").arg(miscDir);
557
558 #endif
559
560 }
561
562 if (databaseType.isEmpty())
563 {
564 // Empty 1.3 config: migration from older versions
565
566 KConfigGroup group = config->group("Album Settings");
567
568 QString databaseFilePath;
569
570 if (group.hasKey(configDatabaseFilePathEntry))
571 {
572 // 1.0 - 1.2 style database file path?
573
574 databaseFilePath = group.readEntry(configDatabaseFilePathEntry, QString());
575 }
576 else if (group.hasKey(configAlbumPathEntry))
577 {
578 // <= 0.9 style album path entry?
579
580 databaseFilePath = group.readEntry(configAlbumPathEntry, QString());
581 }
582 else if (!suggestedPath.isNull())
583 {
584 databaseFilePath = suggestedPath;
585 }
586
587 if (!databaseFilePath.isEmpty())
588 {
589 *this = parametersForSQLite(coreDatabaseFileSQLite(databaseFilePath));
590 }
591
592 // Be aware that schema updating from version <= 0.9 requires reading the "Album Path", so do not remove it here
593 }
594 }
595
removeLegacyConfig()596 void DbEngineParameters::removeLegacyConfig()
597 {
598 KSharedConfig::Ptr config = KSharedConfig::openConfig();
599 KConfigGroup group = config->group("Album Settings");
600
601 if (group.hasKey(configDatabaseFilePathEntry))
602 {
603 group.deleteEntry(configDatabaseFilePathEntry);
604 }
605
606 if (group.hasKey(configAlbumPathEntry))
607 {
608 group.deleteEntry(configAlbumPathEntry);
609 }
610 }
611
writeToConfig(const QString & configGroup) const612 void DbEngineParameters::writeToConfig(const QString& configGroup) const
613 {
614 KSharedConfig::Ptr config = KSharedConfig::openConfig();
615 KConfigGroup group;
616
617 if (configGroup.isNull())
618 {
619 group = config->group(configGroupDatabase);
620 }
621 else
622 {
623 group = config->group(configGroup);
624 }
625
626 QString dbName = getCoreDatabaseNameOrDir();
627 QString dbNameThumbs = getThumbsDatabaseNameOrDir();
628 QString dbNameFace = getFaceDatabaseNameOrDir();
629 QString dbNameSimilarity = getSimilarityDatabaseNameOrDir();
630
631 group.writeEntry(configDatabaseType, databaseType);
632 group.writeEntry(configDatabaseName, dbName);
633 group.writeEntry(configDatabaseNameThumbnails, dbNameThumbs);
634 group.writeEntry(configDatabaseNameFace, dbNameFace);
635 group.writeEntry(configDatabaseNameSimilarity, dbNameSimilarity);
636 group.writeEntry(configDatabaseHostName, hostName);
637 group.writeEntry(configDatabasePort, port);
638 group.writeEntry(configDatabaseUsername, userName);
639
640 O0SimpleCrypt crypto(QCryptographicHash::hash(configDatabaseEncryptedPassword, QCryptographicHash::Sha1).toULongLong());
641 group.writeEntry(configDatabaseEncryptedPassword, crypto.encryptToString(password));
642
643 group.writeEntry(configDatabaseConnectOptions, connectOptions);
644 group.writeEntry(configInternalDatabaseServer, internalServer);
645 group.writeEntry(configInternalDatabaseServerPath, internalServerDBPath);
646 group.writeEntry(configInternalDatabaseServerMysqlAdminCmd, internalServerMysqlAdminCmd);
647 group.writeEntry(configInternalDatabaseServerMysqlServCmd, internalServerMysqlServCmd);
648 group.writeEntry(configInternalDatabaseServerMysqlInitCmd, internalServerMysqlInitCmd);
649
650 group.deleteEntry(configDatabasePassword); // Remove non encrypted password
651 }
652
getCoreDatabaseNameOrDir() const653 QString DbEngineParameters::getCoreDatabaseNameOrDir() const
654 {
655 if (isSQLite())
656 {
657 return coreDatabaseDirectorySQLite(databaseNameCore);
658 }
659
660 return databaseNameCore;
661 }
662
getThumbsDatabaseNameOrDir() const663 QString DbEngineParameters::getThumbsDatabaseNameOrDir() const
664 {
665 if (isSQLite())
666 {
667 return thumbnailDatabaseDirectorySQLite(databaseNameThumbnails);
668 }
669
670 return databaseNameThumbnails;
671 }
672
getFaceDatabaseNameOrDir() const673 QString DbEngineParameters::getFaceDatabaseNameOrDir() const
674 {
675 if (isSQLite())
676 {
677 return faceDatabaseDirectorySQLite(databaseNameFace);
678 }
679
680 return databaseNameFace;
681 }
682
getSimilarityDatabaseNameOrDir() const683 QString DbEngineParameters::getSimilarityDatabaseNameOrDir() const
684 {
685 if (isSQLite())
686 {
687 return similarityDatabaseDirectorySQLite(databaseNameSimilarity);
688 }
689
690 return databaseNameSimilarity;
691 }
692
coreDatabaseDirectorySQLite(const QString & path)693 QString DbEngineParameters::coreDatabaseDirectorySQLite(const QString& path)
694 {
695 if (path.endsWith(QLatin1String(digikam4db)))
696 {
697 QString chopped(path);
698 chopped.chop(QString(QLatin1String(digikam4db)).length());
699
700 return chopped;
701 }
702
703 return path;
704 }
705
thumbnailDatabaseDirectorySQLite(const QString & path)706 QString DbEngineParameters::thumbnailDatabaseDirectorySQLite(const QString& path)
707 {
708 if (path.endsWith(QLatin1String(thumbnails_digikamdb)))
709 {
710 QString chopped(path);
711 chopped.chop(QString(QLatin1String(thumbnails_digikamdb)).length());
712
713 return chopped;
714 }
715
716 return path;
717 }
718
faceDatabaseDirectorySQLite(const QString & path)719 QString DbEngineParameters::faceDatabaseDirectorySQLite(const QString& path)
720 {
721 if (path.endsWith(QLatin1String(face_digikamdb)))
722 {
723 QString chopped(path);
724 chopped.chop(QString(QLatin1String(face_digikamdb)).length());
725
726 return chopped;
727 }
728
729 return path;
730 }
731
similarityDatabaseDirectorySQLite(const QString & path)732 QString DbEngineParameters::similarityDatabaseDirectorySQLite(const QString& path)
733 {
734 if (path.endsWith(QLatin1String(similarity_digikamdb)))
735 {
736 QString chopped(path);
737 chopped.chop(QString(QLatin1String(similarity_digikamdb)).length());
738
739 return chopped;
740 }
741
742 return path;
743 }
744
745
defaultParameters(const QString & databaseType)746 DbEngineParameters DbEngineParameters::defaultParameters(const QString& databaseType)
747 {
748 DbEngineParameters parameters;
749
750 // only the database name is needed
751
752 DbEngineConfigSettings config = DbEngineConfig::element(databaseType);
753 parameters.databaseType = databaseType;
754 parameters.databaseNameCore = config.databaseName;
755 parameters.databaseNameThumbnails = config.databaseName;
756 parameters.databaseNameFace = config.databaseName;
757 parameters.databaseNameSimilarity = config.databaseName;
758 parameters.userName = config.userName;
759 parameters.password = config.password;
760 parameters.internalServer = (databaseType == QLatin1String("QMYSQL"));
761 parameters.internalServerDBPath = (databaseType == QLatin1String("QMYSQL")) ? internalServerPrivatePath() : QString();
762 parameters.internalServerMysqlAdminCmd = (databaseType == QLatin1String("QMYSQL")) ? defaultMysqlAdminCmd() : QString();
763 parameters.internalServerMysqlServCmd = (databaseType == QLatin1String("QMYSQL")) ? defaultMysqlServerCmd() : QString();
764 parameters.internalServerMysqlInitCmd = (databaseType == QLatin1String("QMYSQL")) ? defaultMysqlInitCmd() : QString();
765
766 QString hostName = config.hostName;
767 QString port = config.port;
768 QString connectOptions = config.connectOptions;
769
770 #ifdef Q_OS_WIN
771
772 hostName.replace(QLatin1String("$$DBHOSTNAME$$"), (databaseType == QLatin1String("QMYSQL"))
773 ? QLatin1String("localhost")
774 : QString());
775
776 port.replace(QLatin1String("$$DBPORT$$"), (databaseType == QLatin1String("QMYSQL"))
777 ? QLatin1String("3307")
778 : QLatin1String("-1"));
779
780 connectOptions.replace(QLatin1String("$$DBOPTIONS$$"), QString());
781
782 #else
783
784 hostName.replace(QLatin1String("$$DBHOSTNAME$$"), QString());
785
786 port.replace(QLatin1String("$$DBPORT$$"), QLatin1String("-1"));
787
788 const QString miscDir = internalServerPrivatePath() + QLatin1String("db_misc");
789 connectOptions.replace(QLatin1String("$$DBOPTIONS$$"), (databaseType == QLatin1String("QMYSQL"))
790 ? QString::fromLatin1("UNIX_SOCKET=%1/mysql.socket").arg(miscDir)
791 : QString());
792 #endif
793
794 parameters.hostName = hostName;
795 parameters.port = port.toInt();
796 parameters.connectOptions = connectOptions;
797
798 qCDebug(DIGIKAM_DBENGINE_LOG) << "ConnectOptions " << parameters.connectOptions;
799
800 return parameters;
801 }
802
thumbnailParameters() const803 DbEngineParameters DbEngineParameters::thumbnailParameters() const
804 {
805 DbEngineParameters params = *this;
806 params.databaseNameCore = databaseNameThumbnails;
807
808 return params;
809 }
810
faceParameters() const811 DbEngineParameters DbEngineParameters::faceParameters() const
812 {
813 DbEngineParameters params = *this;
814 params.databaseNameCore = databaseNameFace;
815
816 return params;
817 }
818
similarityParameters() const819 DbEngineParameters DbEngineParameters::similarityParameters() const
820 {
821 DbEngineParameters params = *this;
822 params.databaseNameCore = databaseNameSimilarity;
823
824 return params;
825 }
826
parametersForSQLite(const QString & databaseFile)827 DbEngineParameters DbEngineParameters::parametersForSQLite(const QString& databaseFile)
828 {
829 // only the database name is needed
830
831 DbEngineParameters params(QLatin1String("QSQLITE"), databaseFile);
832 params.setCoreDatabasePath(databaseFile);
833 params.setThumbsDatabasePath(params.getCoreDatabaseNameOrDir());
834 params.setFaceDatabasePath(params.getCoreDatabaseNameOrDir());
835 params.setSimilarityDatabasePath(params.getCoreDatabaseNameOrDir());
836
837 return params;
838 }
839
parametersForSQLiteDefaultFile(const QString & directory)840 DbEngineParameters DbEngineParameters::parametersForSQLiteDefaultFile(const QString& directory)
841 {
842 return parametersForSQLite(QDir::cleanPath(directory + QLatin1Char('/') + QLatin1String(digikam4db)));
843 }
844
defaultMysqlServerCmd()845 QString DbEngineParameters::defaultMysqlServerCmd()
846 {
847 return QLatin1String("mysqld"); // For Linux, Windows and OSX
848 }
849
defaultMysqlAdminCmd()850 QString DbEngineParameters::defaultMysqlAdminCmd()
851 {
852 return QLatin1String("mysqladmin"); // For Linux, Windows and OSX
853 }
854
defaultMysqlInitCmd()855 QString DbEngineParameters::defaultMysqlInitCmd()
856 {
857 return QLatin1String("mysql_install_db"); // For Linux, Windows and OSX
858 }
859
860 // --------------------------------
861
operator <<(QDebug dbg,const DbEngineParameters & p)862 QDebug operator<<(QDebug dbg, const DbEngineParameters& p)
863 {
864 dbg.nospace() << "Database Parameters:" << endl;
865 dbg.nospace() << " Type: " << p.databaseType << endl;
866 dbg.nospace() << " DB Core Name: " << p.databaseNameCore << endl;
867 dbg.nospace() << " DB Thumbs Name: " << p.databaseNameThumbnails << endl;
868 dbg.nospace() << " DB Face Name: " << p.databaseNameFace << endl;
869 dbg.nospace() << " DB Similarity Name: " << p.databaseNameSimilarity << endl;
870 dbg.nospace() << " Connect Options: " << p.connectOptions << endl;
871 dbg.nospace() << " Host Name: " << p.hostName << endl;
872 dbg.nospace() << " Host port: " << p.port << endl;
873 dbg.nospace() << " Internal Server: " << p.internalServer << endl;
874 dbg.nospace() << " Internal Server Path: " << p.internalServerDBPath << endl;
875 dbg.nospace() << " Internal Server Admin Cmd: " << p.internalServerMysqlAdminCmd << endl;
876 dbg.nospace() << " Internal Server Serv Cmd: " << p.internalServerMysqlServCmd << endl;
877 dbg.nospace() << " Internal Server Init Cmd: " << p.internalServerMysqlInitCmd << endl;
878 dbg.nospace() << " Username: " << p.userName << endl;
879 dbg.nospace() << " Password: " << QString().fill(QLatin1Char('X'), p.password.size()) << endl;
880
881 return dbg.space();
882 }
883
884 } // namespace Digikam
885