mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-17 11:28:07 +00:00
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 Account: - Show logs only if the current proxy has been authentifiate for this session - Update in realtime logs when this proxy has been registered - Ensure to not refresh logs if the account has already been registered
This commit is contained in:
parent
0ac9f08b9f
commit
12f717b853
8 changed files with 123 additions and 46 deletions
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <QSysInfo>
|
||||
#include <QtConcurrent>
|
||||
#include <QTimer>
|
||||
#include <QFile>
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -71,10 +71,17 @@ SipAddressesModel::SipAddressesModel (QObject *parent) : QAbstractListModel(pare
|
|||
QObject::connect(coreHandlers, &CoreHandlers::callStateChanged, this, &SipAddressesModel::handleCallStateChanged);
|
||||
QObject::connect(coreHandlers, &CoreHandlers::presenceReceived, this, &SipAddressesModel::handlePresenceReceived);
|
||||
QObject::connect(coreHandlers, &CoreHandlers::isComposingChanged, this, &SipAddressesModel::handleIsComposingChanged);
|
||||
QObject::connect(coreHandlers, &CoreHandlers::registrationStateChanged, this, &SipAddressesModel::handleRegistrationStateChanged);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void SipAddressesModel::reset(){
|
||||
mPeerAddressToSipAddressEntry.clear();
|
||||
mRefs.clear();
|
||||
resetInternalData();
|
||||
initSipAddresses();
|
||||
emit sipAddressReset();
|
||||
}
|
||||
int SipAddressesModel::rowCount (const QModelIndex &) const {
|
||||
return mRefs.count();
|
||||
}
|
||||
|
|
@ -433,7 +440,15 @@ void SipAddressesModel::handleIsComposingChanged (const shared_ptr<linphone::Cha
|
|||
Q_ASSERT(row != -1);
|
||||
emit dataChanged(index(row, 0), index(row, 0));
|
||||
}
|
||||
|
||||
void SipAddressesModel::handleRegistrationStateChanged( const std::shared_ptr<linphone::ProxyConfig> &proxyConfig, linphone::RegistrationState state){
|
||||
QString address = Utils::coreStringToAppString(proxyConfig->getIdentityAddress()->asStringUriOnly());
|
||||
if(!mRegistredProxies.contains(address) && state == linphone::RegistrationState::Ok)// This is a new state.
|
||||
reset();
|
||||
else if( state == linphone::RegistrationState::Cleared){
|
||||
mRegistredProxies.removeAll(address);
|
||||
reset();
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void SipAddressesModel::addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, ContactModel *contact) {
|
||||
|
|
@ -538,16 +553,25 @@ void SipAddressesModel::removeContactOfSipAddress (const QString &sipAddress) {
|
|||
void SipAddressesModel::initSipAddresses () {
|
||||
QElapsedTimer timer;
|
||||
timer.start();
|
||||
|
||||
auto proxies = CoreManager::getInstance()->getCore()->getProxyConfigList();
|
||||
foreach( auto proxy, proxies){
|
||||
QString address = Utils::coreStringToAppString(proxy->getIdentityAddress()->asStringUriOnly());
|
||||
if(proxy->getState() == linphone::RegistrationState::Ok && !mRegistredProxies.contains(address)){
|
||||
mRegistredProxies.push_back(address);
|
||||
}
|
||||
}
|
||||
|
||||
initSipAddressesFromChat();
|
||||
initSipAddressesFromCalls();
|
||||
initSipAddressesFromChat(mRegistredProxies);
|
||||
initSipAddressesFromCalls(mRegistredProxies);
|
||||
initRefs();
|
||||
initSipAddressesFromContacts();
|
||||
|
||||
qInfo() << "Sip addresses model initialized in:" << timer.elapsed() << "ms.";
|
||||
}
|
||||
|
||||
void SipAddressesModel::initSipAddressesFromChat () {
|
||||
void SipAddressesModel::initSipAddressesFromChat (const QStringList &pRegistredProxies) {
|
||||
|
||||
for (const auto &chatRoom : CoreManager::getInstance()->getCore()->getChatRooms()) {
|
||||
list<shared_ptr<linphone::ChatMessage>> history(chatRoom->getHistory(1));
|
||||
if (history.empty())
|
||||
|
|
@ -556,52 +580,55 @@ void SipAddressesModel::initSipAddressesFromChat () {
|
|||
QString peerAddress(Utils::coreStringToAppString(chatRoom->getPeerAddress()->asStringUriOnly()));
|
||||
QString localAddress(Utils::coreStringToAppString(chatRoom->getLocalAddress()->asStringUriOnly()));
|
||||
|
||||
getSipAddressEntry(peerAddress)->localAddressToConferenceEntry[localAddress] = {
|
||||
chatRoom->getUnreadMessagesCount(),
|
||||
CoreManager::getInstance()->getMissedCallCount(peerAddress, localAddress),
|
||||
false,
|
||||
QDateTime::fromMSecsSinceEpoch(history.back()->getTime() * 1000)
|
||||
};
|
||||
if(pRegistredProxies.contains(localAddress)){
|
||||
getSipAddressEntry(peerAddress)->localAddressToConferenceEntry[localAddress] = {
|
||||
chatRoom->getUnreadMessagesCount(),
|
||||
CoreManager::getInstance()->getMissedCallCount(peerAddress, localAddress),
|
||||
false,
|
||||
QDateTime::fromMSecsSinceEpoch(history.back()->getTime() * 1000)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SipAddressesModel::initSipAddressesFromCalls () {
|
||||
void SipAddressesModel::initSipAddressesFromCalls (const QStringList &pRegistredProxies) {
|
||||
using ConferenceId = QPair<QString, QString>;
|
||||
QSet<ConferenceId> conferenceDone;
|
||||
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:
|
||||
if(pRegistredProxies.contains(localAddress)){
|
||||
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:
|
||||
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::Success:
|
||||
case linphone::Call::Status::Declined:
|
||||
|
||||
case linphone::Call::Status::Missed:
|
||||
case linphone::Call::Status::Missed:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ConferenceId conferenceId{ peerAddress, localAddress };
|
||||
if (conferenceDone.contains(conferenceId))
|
||||
continue; // Already used.
|
||||
conferenceDone << conferenceId;
|
||||
ConferenceId conferenceId{ peerAddress, localAddress };
|
||||
if (conferenceDone.contains(conferenceId))
|
||||
continue; // Already used.
|
||||
conferenceDone << conferenceId;
|
||||
|
||||
// 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 timestamp(callLog->getStatus() == linphone::Call::Status::Success
|
||||
? QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000)
|
||||
: QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000));
|
||||
|
||||
auto &localToConferenceEntry = getSipAddressEntry(peerAddress)->localAddressToConferenceEntry;
|
||||
auto it = localToConferenceEntry.find(localAddress);
|
||||
if (it == localToConferenceEntry.end())
|
||||
localToConferenceEntry[localAddress] = { 0,0, false, move(timestamp) };
|
||||
else if (it->timestamp.isNull() || timestamp > it->timestamp)
|
||||
it->timestamp = move(timestamp);
|
||||
auto &localToConferenceEntry = getSipAddressEntry(peerAddress)->localAddressToConferenceEntry;
|
||||
auto it = localToConferenceEntry.find(localAddress);
|
||||
if (it == localToConferenceEntry.end())
|
||||
localToConferenceEntry[localAddress] = { 0,0, false, move(timestamp) };
|
||||
else if (it->timestamp.isNull() || timestamp > it->timestamp)
|
||||
it->timestamp = move(timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
@ -104,6 +108,8 @@ private:
|
|||
void handleMessageSent (const std::shared_ptr<linphone::ChatMessage> &message);
|
||||
|
||||
void handleIsComposingChanged (const std::shared_ptr<linphone::ChatRoom> &chatRoom);
|
||||
|
||||
void handleRegistrationStateChanged( const std::shared_ptr<linphone::ProxyConfig> &proxyConfig, linphone::RegistrationState state);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -125,8 +131,8 @@ private:
|
|||
|
||||
void initSipAddresses ();
|
||||
|
||||
void initSipAddressesFromChat ();
|
||||
void initSipAddressesFromCalls ();
|
||||
void initSipAddressesFromChat (const QStringList &pRegistredProxies);// Read chat logs and keep only for registred proxies
|
||||
void initSipAddressesFromCalls (const QStringList &pRegistredProxies);// Read call logs and keep only for registred proxies
|
||||
void initSipAddressesFromContacts ();
|
||||
|
||||
void initRefs ();
|
||||
|
|
@ -143,7 +149,7 @@ private:
|
|||
it = mPeerAddressToSipAddressEntry.insert(peerAddress, { peerAddress, nullptr, Presence::Offline, {} });
|
||||
return &(*it);
|
||||
}
|
||||
|
||||
QStringList mRegistredProxies;// Storing registred proxies is used to avoid loosing logs when disconnected
|
||||
QHash<QString, SipAddressEntry> mPeerAddressToSipAddressEntry;
|
||||
QList<const SipAddressEntry *> mRefs;
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include <QFileInfo>
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue