From 370357a97c839fef42ab5a44c09f355e097eac0f Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Mon, 13 Mar 2017 11:33:06 +0100 Subject: [PATCH] Respect freedesktop standards for configuration and user data files, and handle migration from old location to the new one. The migration is deactivated for the moment and needs to be enabled when the app is ready to be used. --- linphone-desktop/src/app/App.cpp | 3 + linphone-desktop/src/app/Paths.cpp | 159 ++++++++++++++---- linphone-desktop/src/app/Paths.hpp | 10 +- .../src/app/ThumbnailProvider.cpp | 2 +- .../src/components/chat/ChatModel.cpp | 4 +- .../src/components/core/CoreManager.cpp | 9 + .../src/components/core/CoreManager.hpp | 1 + .../src/components/settings/SettingsModel.cpp | 4 +- linphone-desktop/src/main.cpp | 2 - 9 files changed, 147 insertions(+), 47 deletions(-) diff --git a/linphone-desktop/src/app/App.cpp b/linphone-desktop/src/app/App.cpp index 442315b30..02d4d0f7e 100644 --- a/linphone-desktop/src/app/App.cpp +++ b/linphone-desktop/src/app/App.cpp @@ -205,6 +205,9 @@ void App::parseArgs () { m_parser.process(*this); + // Initialise logger (do not do this before this point because the application has to be created + // for the logs to be put in the correct directory + Logger::init(); if (m_parser.isSet("verbose")) { Logger::instance()->setVerbose(true); } diff --git a/linphone-desktop/src/app/Paths.cpp b/linphone-desktop/src/app/Paths.cpp index 665a9a27b..88808c09a 100644 --- a/linphone-desktop/src/app/Paths.cpp +++ b/linphone-desktop/src/app/Paths.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "../utils.hpp" @@ -30,37 +31,40 @@ // ============================================================================= -#ifdef _WIN32 - -#define MAIN_PATH \ - (QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/") -#define PATH_CONFIG "linphonerc" - -#define LINPHONE_FOLDER "linphone/" - -#else - -#define MAIN_PATH \ - (QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/") -#define PATH_CONFIG ".linphonerc" - -#define LINPHONE_FOLDER ".linphone/" - -#endif // ifdef _WIN32 - -#define PATH_AVATARS (LINPHONE_FOLDER "avatars/") -#define PATH_CAPTURES (LINPHONE_FOLDER "captures/") -#define PATH_LOGS (LINPHONE_FOLDER "logs/") -#define PATH_THUMBNAILS (LINPHONE_FOLDER "thumbnails/") - -#define PATH_CALL_HISTORY_LIST ".linphone-call-history.db" -#define PATH_FRIENDS_LIST ".linphone-friends.db" -#define PATH_MESSAGE_HISTORY_LIST ".linphone-history.db" - using namespace std; +#define PATH_AVATARS "/avatars/" +#define PATH_CAPTURES "/captures/" +#define PATH_LOGS "/logs/" +#define PATH_THUMBNAILS "/thumbnails/" + +#define PATH_CONFIG "/linphonerc" +#define PATH_CALL_HISTORY_LIST "/call-history.db" +#define PATH_FRIENDS_LIST "/friends.db" +#define PATH_MESSAGE_HISTORY_LIST "/message-history.db" + +#define PATH_ZRTP_SECRETS "/zidcache" +#define PATH_USER_CERTIFICATES "/usr-crt/" + // ============================================================================= +inline bool directoryPathExists (const QString &path) { + QDir dir(path); + return dir.exists(); +} + +inline bool filePathExists (const QString &path) { + QFileInfo info(path); + if (!directoryPathExists(info.path())) return false; + + QFile file(path); + return file.exists(); +} + +inline bool filePathExists (const string &path) { + return filePathExists(Utils::linphoneStringToQString(path)); +} + inline void ensureDirectoryPathExists (const QString &path) { QDir dir(path); if (!dir.exists() && !dir.mkpath(path)) @@ -86,39 +90,120 @@ inline string getFilePath (const QString &filename) { return Utils::qStringToLinphoneString(QDir::toNativeSeparators(filename)); } +static QString getAppConfigFilepath () { + if (QSysInfo::productType() == "macos") { + return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PATH_CONFIG; + } else { + return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation) + PATH_CONFIG; + } +} + +static QString getAppCallHistoryFilepath () { + return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PATH_CALL_HISTORY_LIST; +} + +static QString getAppFriendsFilepath () { + return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PATH_FRIENDS_LIST; +} + +static QString getAppMessageHistoryFilepath () { + return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PATH_MESSAGE_HISTORY_LIST; +} + // ----------------------------------------------------------------------------- string Paths::getAvatarsDirpath () { - return getDirectoryPath(MAIN_PATH + PATH_AVATARS); + return getDirectoryPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PATH_AVATARS); } string Paths::getCallHistoryFilepath () { - return getFilePath(MAIN_PATH + PATH_CALL_HISTORY_LIST); + return getFilePath(getAppCallHistoryFilepath()); } string Paths::getConfigFilepath (const QString &configPath) { if (!configPath.isEmpty()) { return getFilePath(QFileInfo(configPath).absoluteFilePath()); } - return getFilePath(MAIN_PATH + PATH_CONFIG); + return getFilePath(getAppConfigFilepath()); } string Paths::getFriendsListFilepath () { - return getFilePath(MAIN_PATH + PATH_FRIENDS_LIST); + return getFilePath(getAppFriendsFilepath()); } string Paths::getLogsDirpath () { - return getDirectoryPath(MAIN_PATH + PATH_LOGS); + return getDirectoryPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PATH_LOGS); } string Paths::getMessageHistoryFilepath () { - return getFilePath(MAIN_PATH + PATH_MESSAGE_HISTORY_LIST); + return getFilePath(getAppMessageHistoryFilepath()); } -string Paths::getThumbnailsDirPath () { - return getDirectoryPath(MAIN_PATH + PATH_THUMBNAILS); +string Paths::getThumbnailsDirpath () { + return getDirectoryPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PATH_THUMBNAILS); } -string Paths::getCapturesDirPath () { - return getDirectoryPath(MAIN_PATH + PATH_CAPTURES); +string Paths::getCapturesDirpath () { + return getDirectoryPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PATH_CAPTURES); +} + +string Paths::getZrtpSecretsFilepath () { + return getFilePath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + PATH_ZRTP_SECRETS); +} + +string Paths::getUserCertificatesDirpath () { + return getDirectoryPath(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + PATH_USER_CERTIFICATES); +} + +// ----------------------------------------------------------------------------- + +static void migrateFile (const QString &oldPath, const QString &newPath) { + QFileInfo info(newPath); + ensureDirectoryPathExists(info.path()); + if (QFile::copy(oldPath, newPath)) { + QFile::remove(oldPath); + qInfo() << "Migrated" << oldPath << "to" << newPath; + } else { + qWarning() << "Failed migration of" << oldPath << "to" << newPath; + } +} + +static void migrateConfigurationFile (const QString &oldPath, const QString &newPath) { + QFileInfo info(newPath); + ensureDirectoryPathExists(info.path()); + if (QFile::copy(oldPath, newPath)) { + QFile oldFile(oldPath); + if (oldFile.open(QIODevice::WriteOnly)) { + QTextStream stream(&oldFile); + stream << "This file has been migrated to " << newPath; + } + QFile::setPermissions(oldPath, QFileDevice::ReadOwner); + qInfo() << "Migrated" << oldPath << "to" << newPath; + } else { + qWarning() << "Failed migration of" << oldPath << "to" << newPath; + } +} + +void Paths::migrate () { + QString newPath; + QString oldPath; + QString oldBaseDir; + + if (QSysInfo::productType() == "windows") { + oldBaseDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation); + } else { + oldBaseDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); + } + newPath = getAppConfigFilepath(); + oldPath = oldBaseDir + "/.linphonerc"; + if (!filePathExists(newPath) && filePathExists(oldPath)) migrateConfigurationFile(oldPath, newPath); + newPath = getAppCallHistoryFilepath(); + oldPath = oldBaseDir + "/.linphone-call-history.db"; + if (!filePathExists(newPath) && filePathExists(oldPath)) migrateFile(oldPath, newPath); + newPath = getAppFriendsFilepath(); + oldPath = oldBaseDir + "/.linphone-friends.db"; + if (!filePathExists(newPath) && filePathExists(oldPath)) migrateFile(oldPath, newPath); + newPath = getAppMessageHistoryFilepath(); + oldPath = oldBaseDir + "/.linphone-history.db"; + if (!filePathExists(newPath) && filePathExists(oldPath)) migrateFile(oldPath, newPath); } diff --git a/linphone-desktop/src/app/Paths.hpp b/linphone-desktop/src/app/Paths.hpp index 968418f32..1eca4512d 100644 --- a/linphone-desktop/src/app/Paths.hpp +++ b/linphone-desktop/src/app/Paths.hpp @@ -31,12 +31,16 @@ namespace Paths { std::string getAvatarsDirpath (); std::string getCallHistoryFilepath (); - std::string getConfigFilepath (const QString &configPath); + std::string getConfigFilepath (const QString &configPath = QString()); std::string getFriendsListFilepath (); - std::string getCapturesDirPath (); + std::string getCapturesDirpath (); std::string getLogsDirpath (); std::string getMessageHistoryFilepath (); - std::string getThumbnailsDirPath (); + std::string getThumbnailsDirpath (); + std::string getZrtpSecretsFilepath (); + std::string getUserCertificatesDirpath (); + + void migrate (); } #endif // PATHS_H_ diff --git a/linphone-desktop/src/app/ThumbnailProvider.cpp b/linphone-desktop/src/app/ThumbnailProvider.cpp index 0398936e4..26db9f4a2 100644 --- a/linphone-desktop/src/app/ThumbnailProvider.cpp +++ b/linphone-desktop/src/app/ThumbnailProvider.cpp @@ -33,7 +33,7 @@ ThumbnailProvider::ThumbnailProvider () : QQuickImageProvider( QQmlImageProviderBase::Image, QQmlImageProviderBase::ForceAsynchronousImageLoading ) { - m_thumbnails_path = Utils::linphoneStringToQString(Paths::getThumbnailsDirPath()); + m_thumbnails_path = Utils::linphoneStringToQString(Paths::getThumbnailsDirpath()); } QImage ThumbnailProvider::requestImage (const QString &id, QSize *, const QSize &) { diff --git a/linphone-desktop/src/components/chat/ChatModel.cpp b/linphone-desktop/src/components/chat/ChatModel.cpp index e6d8c86c0..c3bc23781 100644 --- a/linphone-desktop/src/components/chat/ChatModel.cpp +++ b/linphone-desktop/src/components/chat/ChatModel.cpp @@ -70,7 +70,7 @@ inline void createThumbnail (const shared_ptr &message) { QString uuid = QUuid::createUuid().toString(); QString file_id = QStringLiteral("%1.jpg").arg(uuid.mid(1, uuid.length() - 2)); - if (!thumbnail.save(::Utils::linphoneStringToQString(Paths::getThumbnailsDirPath()) + file_id, "jpg", 100)) { + if (!thumbnail.save(::Utils::linphoneStringToQString(Paths::getThumbnailsDirpath()) + file_id, "jpg", 100)) { qWarning() << QStringLiteral("Unable to create thumbnail of: `%1`.").arg(thumbnail_path); return; } @@ -84,7 +84,7 @@ inline void removeFileMessageThumbnail (const shared_ptr string file_id = message->getAppdata(); if (!file_id.empty()) { - QString thumbnail_path = ::Utils::linphoneStringToQString(Paths::getThumbnailsDirPath() + file_id); + QString thumbnail_path = ::Utils::linphoneStringToQString(Paths::getThumbnailsDirpath() + file_id); if (!QFile::remove(thumbnail_path)) qWarning() << QStringLiteral("Unable to remove `%1`.").arg(thumbnail_path); } diff --git a/linphone-desktop/src/components/core/CoreManager.cpp b/linphone-desktop/src/components/core/CoreManager.cpp index 13a27a11a..ccf556a86 100644 --- a/linphone-desktop/src/components/core/CoreManager.cpp +++ b/linphone-desktop/src/components/core/CoreManager.cpp @@ -36,6 +36,9 @@ using namespace std; CoreManager *CoreManager::m_instance = nullptr; CoreManager::CoreManager (QObject *parent, const QString &config_path) : QObject(parent), m_handlers(make_shared()) { + // TODO: activate migration when ready to switch to this new version + //Paths::migrate(); + setResourcesPaths(); m_core = linphone::Factory::get()->createCore(m_handlers, Paths::getConfigFilepath(config_path), ""); @@ -44,6 +47,7 @@ CoreManager::CoreManager (QObject *parent, const QString &config_path) : QObject m_core->usePreviewWindow(true); setDatabasesPaths(); + setOtherPaths(); } void CoreManager::enableHandlers () { @@ -80,6 +84,11 @@ void CoreManager::setDatabasesPaths () { m_core->setChatDatabasePath(Paths::getMessageHistoryFilepath()); } +void CoreManager::setOtherPaths () { + m_core->setZrtpSecretsFile(Paths::getZrtpSecretsFilepath()); + m_core->setUserCertificatesPath(Paths::getUserCertificatesDirpath()); +} + void CoreManager::setResourcesPaths () { QDir dir(QCoreApplication::applicationDirPath()); if (dir.dirName() == "MacOS") { diff --git a/linphone-desktop/src/components/core/CoreManager.hpp b/linphone-desktop/src/components/core/CoreManager.hpp index ca1129b5b..745c21ed4 100644 --- a/linphone-desktop/src/components/core/CoreManager.hpp +++ b/linphone-desktop/src/components/core/CoreManager.hpp @@ -89,6 +89,7 @@ private: CoreManager (QObject *parent, const QString &config_path); void setDatabasesPaths (); + void setOtherPaths (); void setResourcesPaths (); std::shared_ptr m_core; diff --git a/linphone-desktop/src/components/settings/SettingsModel.cpp b/linphone-desktop/src/components/settings/SettingsModel.cpp index 3fc9bd874..70b6b465f 100644 --- a/linphone-desktop/src/components/settings/SettingsModel.cpp +++ b/linphone-desktop/src/components/settings/SettingsModel.cpp @@ -572,7 +572,7 @@ void SettingsModel::setDscpVideo (int dscp) { QString SettingsModel::getSavedScreenshotsFolder () const { return QDir::cleanPath( ::Utils::linphoneStringToQString( - m_config->getString(UI_SECTION, "saved_screenshots_folder", Paths::getCapturesDirPath()) + m_config->getString(UI_SECTION, "saved_screenshots_folder", Paths::getCapturesDirpath()) ) ) + QDir::separator(); } @@ -589,7 +589,7 @@ void SettingsModel::setSavedScreenshotsFolder (const QString &folder) { QString SettingsModel::getSavedVideosFolder () const { return QDir::cleanPath( ::Utils::linphoneStringToQString( - m_config->getString(UI_SECTION, "saved_videos_folder", Paths::getCapturesDirPath()) + m_config->getString(UI_SECTION, "saved_videos_folder", Paths::getCapturesDirpath()) ) ) + QDir::separator(); } diff --git a/linphone-desktop/src/main.cpp b/linphone-desktop/src/main.cpp index 7b972ab8e..03f77219d 100644 --- a/linphone-desktop/src/main.cpp +++ b/linphone-desktop/src/main.cpp @@ -30,8 +30,6 @@ using namespace std; // ============================================================================= int main (int argc, char *argv[]) { - Logger::init(); - // Force OpenGLES & shader version 2.0. QCoreApplication::setAttribute(Qt::AA_UseOpenGLES, true);