From 72b52935948ef252e6e2d2242b8ba0d90ed8a983 Mon Sep 17 00:00:00 2001 From: Julien Wadel Date: Thu, 11 Jun 2020 10:19:07 +0200 Subject: [PATCH] Flatpak migration and account security Flatpak: - Rewrite chat message deprecated logs : no more ensuring that this file must exists - If a message history file exists in the application folder, let the SDK migrate data and remove the file - Copy recursively all data from Flatpak installation, if files doesn't exist - Split 2 migrations : old GTK and Flatpak --- linphone-app/src/app/paths/Paths.cpp | 21 ++++++++--- .../components/assistant/AssistantModel.cpp | 10 ++++-- .../src/components/core/CoreManager.cpp | 6 +++- .../sip-addresses/SipAddressesModel.cpp | 35 +++++++++++-------- .../sip-addresses/SipAddressesModel.hpp | 5 ++- .../src/components/timeline/TimelineModel.cpp | 3 ++ linphone-app/src/utils/Utils.cpp | 19 ++++++++++ linphone-app/src/utils/Utils.hpp | 1 + 8 files changed, 76 insertions(+), 24 deletions(-) diff --git a/linphone-app/src/app/paths/Paths.cpp b/linphone-app/src/app/paths/Paths.cpp index 4e39aabe6..7bb3a61b1 100644 --- a/linphone-app/src/app/paths/Paths.cpp +++ b/linphone-app/src/app/paths/Paths.cpp @@ -240,7 +240,7 @@ string Paths::getLogsDirPath () { } string Paths::getMessageHistoryFilePath () { - return getWritableFilePath(getAppMessageHistoryFilePath()); + return getReadableFilePath(getAppMessageHistoryFilePath());// No need to ensure that the file exists as this DB is deprecated } string Paths::getPackageDataDirPath () { @@ -300,10 +300,19 @@ static void migrateConfigurationFile (const QString &oldPath, const QString &new qWarning() << "Failed migration of" << oldPath << "to" << newPath; } } - -void Paths::migrate () { +void migrateFlatpakVersionFiles(){ +#ifdef Q_OS_LINUX +// Copy all files + QString flatpakPath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation)+"/.var/app/com.belledonnecommunications.linphone/data/linphone"; + if( QDir().exists(flatpakPath)){ + qInfo() << "Migrating data from Flatpak."; + Utils::copyDir(flatpakPath, QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)); + } +#endif +} +void migrateGTKVersionFiles(){ QString newPath = getAppConfigFilePath(); - QString oldBaseDir = QSysInfo::productType() == QLatin1String("windows") + QString oldBaseDir = QSysInfo::productType() == QLatin1String("windows") ? QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) : QStandardPaths::writableLocation(QStandardPaths::HomeLocation); QString oldPath = oldBaseDir + "/.linphonerc"; @@ -329,3 +338,7 @@ void Paths::migrate () { if (!filePathExists(newPath) && filePathExists(oldPath)) migrateFile(oldPath, newPath); } +void Paths::migrate () { + migrateFlatpakVersionFiles(); // First, check Flatpak version as it is the earlier version + migrateGTKVersionFiles();// Then check old version for migration +} diff --git a/linphone-app/src/components/assistant/AssistantModel.cpp b/linphone-app/src/components/assistant/AssistantModel.cpp index 4bc0aac2c..fb7051403 100644 --- a/linphone-app/src/components/assistant/AssistantModel.cpp +++ b/linphone-app/src/components/assistant/AssistantModel.cpp @@ -22,6 +22,7 @@ #include "components/core/CoreManager.hpp" #include "components/settings/AccountSettingsModel.hpp" #include "components/settings/SettingsModel.hpp" +#include "components/sip-addresses/SipAddressesModel.hpp" #include "utils/LinphoneUtils.hpp" #include "utils/Utils.hpp" @@ -55,9 +56,9 @@ private: linphone::AccountCreator::Status status, const string & ) override { - if (status == linphone::AccountCreator::Status::AccountCreated) + if (status == linphone::AccountCreator::Status::AccountCreated){ emit mAssistant->createStatusChanged(QString("")); - else { + }else { if (status == linphone::AccountCreator::Status::RequestFailed) emit mAssistant->createStatusChanged(tr("requestFailed")); else if (status == linphone::AccountCreator::Status::ServerError) @@ -74,6 +75,7 @@ private: ) override { if (status == linphone::AccountCreator::Status::AccountExist || status == linphone::AccountCreator::Status::AccountExistWithAlias) { createProxyConfig(creator); + CoreManager::getInstance()->getSipAddressesModel()->reset(); emit mAssistant->loginStatusChanged(QString("")); } else { if (status == linphone::AccountCreator::Status::RequestFailed) @@ -94,7 +96,7 @@ private: ) { if (creator->getEmail().empty()) createProxyConfig(creator); - + CoreManager::getInstance()->getSipAddressesModel()->reset(); emit mAssistant->activateStatusChanged(QString("")); } else { if (status == linphone::AccountCreator::Status::RequestFailed) @@ -111,6 +113,7 @@ private: ) override { if (status == linphone::AccountCreator::Status::AccountActivated) { createProxyConfig(creator); + CoreManager::getInstance()->getSipAddressesModel()->reset(); emit mAssistant->activateStatusChanged(QString("")); } else { if (status == linphone::AccountCreator::Status::RequestFailed) @@ -126,6 +129,7 @@ private: const string & ) override { if (status == linphone::AccountCreator::Status::RequestOk) { + CoreManager::getInstance()->getSipAddressesModel()->reset(); emit mAssistant->recoverStatusChanged(QString("")); } else { if (status == linphone::AccountCreator::Status::RequestFailed) diff --git a/linphone-app/src/components/core/CoreManager.cpp b/linphone-app/src/components/core/CoreManager.cpp index 9bd5452df..fa2a35c42 100644 --- a/linphone-app/src/components/core/CoreManager.cpp +++ b/linphone-app/src/components/core/CoreManager.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "config.h" @@ -210,7 +211,10 @@ void CoreManager::cleanLogs () const { void CoreManager::setDatabasesPaths () { SET_DATABASE_PATH(Friends, Paths::getFriendsListFilePath()); SET_DATABASE_PATH(CallLogs, Paths::getCallHistoryFilePath()); - SET_DATABASE_PATH(Chat, Paths::getMessageHistoryFilePath()); + if(QFile::exists(Utils::coreStringToAppString(Paths::getMessageHistoryFilePath()))){ + SET_DATABASE_PATH(Chat, Paths::getMessageHistoryFilePath());// Setting the message database let SDK to migrate data + QFile::remove(Utils::coreStringToAppString(Paths::getMessageHistoryFilePath())); + } } #undef SET_DATABASE_PATH diff --git a/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp b/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp index 822db8783..4f1e72d48 100644 --- a/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp +++ b/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp @@ -74,7 +74,13 @@ SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(pare } // ----------------------------------------------------------------------------- - +void SipAddressesModel::reset(){ + mPeerAddressToSipAddressEntry.clear(); + mRefs.clear(); + resetInternalData(); + initSipAddresses(); + emit sipAddressReset(); +} int SipAddressesModel::rowCount (const QModelIndex &) const { return mRefs.count(); } @@ -433,7 +439,6 @@ void SipAddressesModel::handleIsComposingChanged (const shared_ptrgetCore()->getChatRooms()) { list> history(chatRoom->getHistory(1)); if (history.empty()) @@ -571,19 +577,18 @@ void SipAddressesModel::initSipAddressesFromCalls () { for (const auto &callLog : CoreManager::getInstance()->getCore()->getCallLogs()) { const QString peerAddress(Utils::coreStringToAppString(callLog->getRemoteAddress()->asStringUriOnly())); const QString localAddress(Utils::coreStringToAppString(callLog->getLocalAddress()->asStringUriOnly())); - switch (callLog->getStatus()) { - case linphone::Call::Status::Aborted: - case linphone::Call::Status::EarlyAborted: - return; // Ignore aborted calls. - case linphone::Call::Status::AcceptedElsewhere: - case linphone::Call::Status::DeclinedElsewhere: - return; // Ignore accepted calls on other device. - case linphone::Call::Status::Success: - case linphone::Call::Status::Declined: + case linphone::Call::Status::Aborted: + case linphone::Call::Status::EarlyAborted: + return; // Ignore aborted calls. + case linphone::Call::Status::AcceptedElsewhere: + case linphone::Call::Status::DeclinedElsewhere: + return; // Ignore accepted calls on other device. + case linphone::Call::Status::Success: + case linphone::Call::Status::Declined: - case linphone::Call::Status::Missed: - break; + case linphone::Call::Status::Missed: + break; } ConferenceId conferenceId{ peerAddress, localAddress }; @@ -593,8 +598,8 @@ void SipAddressesModel::initSipAddressesFromCalls () { // The duration can be wrong if status is not success. QDateTime timestamp(callLog->getStatus() == linphone::Call::Status::Success - ? QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000) - : QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000)); + ? QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000) + : QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000)); auto &localToConferenceEntry = getSipAddressEntry(peerAddress)->localAddressToConferenceEntry; auto it = localToConferenceEntry.find(localAddress); diff --git a/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp b/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp index bd66688ce..2c0200dfa 100644 --- a/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp +++ b/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp @@ -52,6 +52,8 @@ public: }; SipAddressesModel (QObject *parent = Q_NULLPTR); + + void reset(); int rowCount (const QModelIndex &index = QModelIndex()) const override; @@ -78,6 +80,8 @@ public: Q_INVOKABLE static QString cleanSipAddress (const QString &sipAddress); // --------------------------------------------------------------------------- +signals: + void sipAddressReset();// The model has been reset private: bool removeRow (int row, const QModelIndex &parent = QModelIndex()); @@ -143,7 +147,6 @@ private: it = mPeerAddressToSipAddressEntry.insert(peerAddress, { peerAddress, nullptr, Presence::Offline, {} }); return &(*it); } - QHash mPeerAddressToSipAddressEntry; QList mRefs; diff --git a/linphone-app/src/components/timeline/TimelineModel.cpp b/linphone-app/src/components/timeline/TimelineModel.cpp index c24881b19..a93351cea 100644 --- a/linphone-app/src/components/timeline/TimelineModel.cpp +++ b/linphone-app/src/components/timeline/TimelineModel.cpp @@ -33,6 +33,9 @@ TimelineModel::TimelineModel (QObject *parent) : QSortFilterProxyModel(parent) { QObject::connect(accountSettingsModel, &AccountSettingsModel::accountSettingsUpdated, this, [this]() { handleLocalAddressChanged(CoreManager::getInstance()->getAccountSettingsModel()->getUsedSipAddressAsStringUriOnly()); }); + QObject::connect(coreManager->getSipAddressesModel(), &SipAddressesModel::sipAddressReset, this, [this]() { + invalidate();// Invalidate and reload GUI if the model has been reset + }); mLocalAddress = accountSettingsModel->getUsedSipAddressAsStringUriOnly(); setSourceModel(coreManager->getSipAddressesModel()); diff --git a/linphone-app/src/utils/Utils.cpp b/linphone-app/src/utils/Utils.cpp index 5a9cf11a0..b8cc27fed 100644 --- a/linphone-app/src/utils/Utils.cpp +++ b/linphone-app/src/utils/Utils.cpp @@ -20,6 +20,8 @@ #include #include +#include +#include #include "Utils.hpp" @@ -355,3 +357,20 @@ QString Utils::getCountryName(const QLocale::Country& p_country) countryName = QLocale::countryToString(p_country); return countryName; } +// Copy a folder recursively without erasing old file +void Utils::copyDir(QString from, QString to) { + QDir dir; + dir.setPath(from); + from += QDir::separator(); + to += QDir::separator(); + foreach (QString copyFile, dir.entryList(QDir::Files)) {// Copy each files + QString toFile = to + copyFile; + if (!QFile::exists(toFile)) + QFile::copy(from+copyFile, toFile); + } + foreach (QString nextDir, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {// Copy folder + QString toDir = to + nextDir; + QDir().mkpath(toDir);// no need to check if dir exists + copyDir(from + nextDir, toDir);//Go up + } +} diff --git a/linphone-app/src/utils/Utils.hpp b/linphone-app/src/utils/Utils.hpp index 88e134846..cdc4b6044 100644 --- a/linphone-app/src/utils/Utils.hpp +++ b/linphone-app/src/utils/Utils.hpp @@ -98,6 +98,7 @@ namespace Utils { return connection; } QString getCountryName(const QLocale::Country& country); + void copyDir(QString from, QString to);// Copy a folder recursively without erasing old file } #endif // UTILS_H_