mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-21 12:35:52 +03:00
Merge pull request #5141 from nextcloud/bugfix/upgradeFromOldClients
fix migration from old settings configuration files
This commit is contained in:
commit
c03e6cca61
3 changed files with 154 additions and 86 deletions
|
@ -13,19 +13,21 @@
|
|||
*/
|
||||
|
||||
#include "accountmanager.h"
|
||||
#include "configfile.h"
|
||||
|
||||
#include "sslerrordialog.h"
|
||||
#include "proxyauthhandler.h"
|
||||
#include "common/asserts.h"
|
||||
#include <theme.h>
|
||||
#include <creds/credentialsfactory.h>
|
||||
#include <creds/abstractcredentials.h>
|
||||
#include <cookiejar.h>
|
||||
#include "creds/credentialsfactory.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
#include "libsync/clientsideencryption.h"
|
||||
#include "libsync/configfile.h"
|
||||
#include "libsync/cookiejar.h"
|
||||
#include "libsync/theme.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QDir>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QMessageBox>
|
||||
#include "clientsideencryption.h"
|
||||
|
||||
namespace {
|
||||
constexpr auto urlC = "url";
|
||||
|
@ -49,7 +51,7 @@ constexpr auto httpAuthPrefix = "http_";
|
|||
constexpr auto webflowAuthPrefix = "webflow_";
|
||||
|
||||
constexpr auto legacyRelativeConfigLocationC = "/ownCloud/owncloud.cfg";
|
||||
constexpr auto legacyOcSettingsC = "ownCloud";
|
||||
constexpr auto legacyCfgFileNameC = "owncloud.cfg";
|
||||
|
||||
// The maximum versions that this client can read
|
||||
constexpr auto maxAccountsVersion = 2;
|
||||
|
@ -148,47 +150,81 @@ bool AccountManager::restoreFromLegacySettings()
|
|||
// if the settings file could not be opened, the childKeys list is empty
|
||||
// then try to load settings from a very old place
|
||||
if (settings->childKeys().isEmpty()) {
|
||||
// Now try to open the original ownCloud settings to see if they exist.
|
||||
auto oCCfgFile = QDir::fromNativeSeparators(settings->fileName());
|
||||
// replace the last two segments with ownCloud/owncloud.cfg
|
||||
oCCfgFile = oCCfgFile.left(oCCfgFile.lastIndexOf('/'));
|
||||
oCCfgFile = oCCfgFile.left(oCCfgFile.lastIndexOf('/'));
|
||||
oCCfgFile += QLatin1String(legacyRelativeConfigLocationC);
|
||||
// Legacy settings used QDesktopServices to get the location for the config folder in 2.4 and before
|
||||
const auto legacy2_4CfgSettingsLocation = QString(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/data"));
|
||||
const auto legacy2_4CfgFileParentFolder = legacy2_4CfgSettingsLocation.left(legacy2_4CfgSettingsLocation.lastIndexOf('/'));
|
||||
|
||||
qCInfo(lcAccountManager) << "Migrate: checking old config " << oCCfgFile;
|
||||
// 2.5+ (rest of 2.x series)
|
||||
const auto legacy2_5CfgSettingsLocation = QStandardPaths::writableLocation(Utility::isWindows() ? QStandardPaths::AppDataLocation : QStandardPaths::AppConfigLocation);
|
||||
const auto legacy2_5CfgFileParentFolder = legacy2_5CfgSettingsLocation.left(legacy2_5CfgSettingsLocation.lastIndexOf('/'));
|
||||
|
||||
QFileInfo fi(oCCfgFile);
|
||||
if (fi.isReadable()) {
|
||||
std::unique_ptr<QSettings> oCSettings(new QSettings(oCCfgFile, QSettings::IniFormat));
|
||||
oCSettings->beginGroup(QLatin1String(legacyOcSettingsC));
|
||||
// Now try the locations we use today
|
||||
const auto fullLegacyCfgFile = QDir::fromNativeSeparators(settings->fileName());
|
||||
const auto legacyCfgFileParentFolder = fullLegacyCfgFile.left(fullLegacyCfgFile.lastIndexOf('/'));
|
||||
const auto legacyCfgFileGrandParentFolder = legacyCfgFileParentFolder.left(legacyCfgFileParentFolder.lastIndexOf('/'));
|
||||
|
||||
// Check the theme url to see if it is the same url that the oC config was for
|
||||
auto overrideUrl = Theme::instance()->overrideServerUrl();
|
||||
if (!overrideUrl.isEmpty()) {
|
||||
if (overrideUrl.endsWith('/')) {
|
||||
overrideUrl.chop(1);
|
||||
}
|
||||
auto oCUrl = oCSettings->value(QLatin1String(urlC)).toString();
|
||||
if (oCUrl.endsWith('/')) {
|
||||
oCUrl.chop(1);
|
||||
const auto legacyCfgFileNamePath = QString(QStringLiteral("/") + legacyCfgFileNameC);
|
||||
const auto legacyCfgFileRelativePath = QString(legacyRelativeConfigLocationC);
|
||||
|
||||
const auto legacyLocations = QVector<QString>{legacy2_4CfgFileParentFolder + legacyCfgFileRelativePath,
|
||||
legacy2_5CfgFileParentFolder + legacyCfgFileRelativePath,
|
||||
legacyCfgFileParentFolder + legacyCfgFileNamePath,
|
||||
legacyCfgFileGrandParentFolder + legacyCfgFileRelativePath};
|
||||
|
||||
for (const auto &configFile : legacyLocations) {
|
||||
if (const QFileInfo configFileInfo(configFile);
|
||||
configFileInfo.exists() && configFileInfo.isReadable()) {
|
||||
|
||||
qCInfo(lcAccountManager) << "Migrate: checking old config " << configFile;
|
||||
|
||||
auto oCSettings = std::make_unique<QSettings>(configFile, QSettings::IniFormat);
|
||||
if (oCSettings->status() != QSettings::Status::NoError) {
|
||||
qCInfo(lcAccountManager) << "Error reading legacy configuration file" << oCSettings->status();
|
||||
}
|
||||
|
||||
// in case the urls are equal reset the settings object to read from
|
||||
// the ownCloud settings object
|
||||
qCInfo(lcAccountManager) << "Migrate oC config if " << oCUrl << " == " << overrideUrl << ":"
|
||||
<< (oCUrl == overrideUrl ? "Yes" : "No");
|
||||
if (oCUrl == overrideUrl) {
|
||||
// Check the theme url to see if it is the same url that the oC config was for
|
||||
auto overrideUrl = Theme::instance()->overrideServerUrl();
|
||||
qCInfo(lcAccountManager) << "Migrate: overrideUrl" << overrideUrl;
|
||||
if (!overrideUrl.isEmpty()) {
|
||||
if (overrideUrl.endsWith('/')) {
|
||||
overrideUrl.chop(1);
|
||||
}
|
||||
auto oCUrl = oCSettings->value(QLatin1String(urlC)).toString();
|
||||
if (oCUrl.endsWith('/')) {
|
||||
oCUrl.chop(1);
|
||||
}
|
||||
|
||||
// in case the urls are equal reset the settings object to read from
|
||||
// the ownCloud settings object
|
||||
qCInfo(lcAccountManager) << "Migrate oC config if " << oCUrl << " == " << overrideUrl << ":"
|
||||
<< (oCUrl == overrideUrl ? "Yes" : "No");
|
||||
if (oCUrl == overrideUrl) {
|
||||
qCInfo(lcAccountManager) << "Copy settings" << oCSettings->allKeys().join(", ");
|
||||
settings = std::move(oCSettings);
|
||||
}
|
||||
} else {
|
||||
qCInfo(lcAccountManager) << "Copy settings" << oCSettings->allKeys().join(", ");
|
||||
settings = std::move(oCSettings);
|
||||
}
|
||||
|
||||
break;
|
||||
} else {
|
||||
qCInfo(lcAccountManager) << "Migrate: could not read old config " << configFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to load the single account.
|
||||
if (!settings->childKeys().isEmpty()) {
|
||||
if (const auto acc = loadAccountHelper(*settings)) {
|
||||
addAccount(acc);
|
||||
return true;
|
||||
settings->beginGroup(accountsC);
|
||||
const auto childGroups = settings->childGroups();
|
||||
for (const auto &accountId : childGroups) {
|
||||
settings->beginGroup(accountId);
|
||||
if (const auto acc = loadAccountHelper(*settings)) {
|
||||
addAccount(acc);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
namespace {
|
||||
#ifndef VERSION_C
|
||||
#define VERSION_C
|
||||
constexpr auto versionC= "version";
|
||||
constexpr auto versionC = "version";
|
||||
#endif
|
||||
}
|
||||
namespace OCC {
|
||||
|
|
|
@ -39,12 +39,11 @@
|
|||
#include <QNetworkProxy>
|
||||
|
||||
namespace {
|
||||
#ifndef VERSION_C
|
||||
#define VERSION_C
|
||||
constexpr auto versionC= "version";
|
||||
#endif
|
||||
constexpr auto settingsAccountsC = "Accounts";
|
||||
constexpr auto settingsFoldersC = "Folders";
|
||||
constexpr auto settingsVersionC = "version";
|
||||
constexpr auto maxFoldersVersion = 1;
|
||||
}
|
||||
static const int maxFoldersVersion = 1;
|
||||
|
||||
namespace OCC {
|
||||
|
||||
|
@ -323,7 +322,7 @@ void FolderMan::setupFoldersHelper(QSettings &settings, AccountStatePtr account,
|
|||
f->switchToVirtualFiles();
|
||||
}
|
||||
// Migrate the old "usePlaceholders" setting to the root folder pin state
|
||||
if (settings.value(QLatin1String(versionC), 1).toInt() == 1
|
||||
if (settings.value(QLatin1String(settingsVersionC), 1).toInt() == 1
|
||||
&& settings.value(QLatin1String("usePlaceholders"), false).toBool()) {
|
||||
qCInfo(lcFolderMan) << "Migrate: From usePlaceholders to PinState::OnlineOnly";
|
||||
f->setRootPinState(PinState::OnlineOnly);
|
||||
|
@ -347,7 +346,7 @@ int FolderMan::setupFoldersMigration()
|
|||
{
|
||||
ConfigFile cfg;
|
||||
QDir storageDir(cfg.configPath());
|
||||
_folderConfigPath = cfg.configPath() + QLatin1String("folders");
|
||||
_folderConfigPath = cfg.configPath();
|
||||
|
||||
qCInfo(lcFolderMan) << "Setup folders from " << _folderConfigPath << "(migration)";
|
||||
|
||||
|
@ -378,11 +377,11 @@ void FolderMan::backwardMigrationSettingsKeys(QStringList *deleteKeys, QStringLi
|
|||
|
||||
auto processSubgroup = [&](const QString &name) {
|
||||
settings->beginGroup(name);
|
||||
const int foldersVersion = settings->value(QLatin1String(versionC), 1).toInt();
|
||||
const int foldersVersion = settings->value(QLatin1String(settingsVersionC), 1).toInt();
|
||||
if (foldersVersion <= maxFoldersVersion) {
|
||||
foreach (const auto &folderAlias, settings->childGroups()) {
|
||||
settings->beginGroup(folderAlias);
|
||||
const int folderVersion = settings->value(QLatin1String(versionC), 1).toInt();
|
||||
const int folderVersion = settings->value(QLatin1String(settingsVersionC), 1).toInt();
|
||||
if (folderVersion > FolderDefinition::maxSettingsVersion()) {
|
||||
ignoreKeys->append(settings->group());
|
||||
}
|
||||
|
@ -508,29 +507,10 @@ Folder *FolderMan::setupFolderFromOldConfigFile(const QString &file, AccountStat
|
|||
|
||||
// Check if the filename is equal to the group setting. If not, use the group
|
||||
// name as an alias.
|
||||
QStringList groups = settings.childGroups();
|
||||
|
||||
if (!groups.contains(escapedAlias) && groups.count() > 0) {
|
||||
escapedAlias = groups.first();
|
||||
}
|
||||
|
||||
settings.beginGroup(escapedAlias); // read the group with the same name as the file which is the folder alias
|
||||
|
||||
QString path = settings.value(QLatin1String("localPath")).toString();
|
||||
QString backend = settings.value(QLatin1String("backend")).toString();
|
||||
QString targetPath = settings.value(QLatin1String("targetPath")).toString();
|
||||
bool paused = settings.value(QLatin1String("paused"), false).toBool();
|
||||
// QString connection = settings.value( QLatin1String("connection") ).toString();
|
||||
QString alias = unescapeAlias(escapedAlias);
|
||||
|
||||
if (backend.isEmpty() || backend != QLatin1String("owncloud")) {
|
||||
qCWarning(lcFolderMan) << "obsolete configuration of type" << backend;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// cut off the leading slash, oCUrl always has a trailing.
|
||||
if (targetPath.startsWith(QLatin1Char('/'))) {
|
||||
targetPath.remove(0, 1);
|
||||
const auto groups = settings.childGroups();
|
||||
if (groups.isEmpty()) {
|
||||
qCWarning(lcFolderMan) << "empty file:" << cfgFile.filePath();
|
||||
return folder;
|
||||
}
|
||||
|
||||
if (!accountState) {
|
||||
|
@ -538,28 +518,80 @@ Folder *FolderMan::setupFolderFromOldConfigFile(const QString &file, AccountStat
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
FolderDefinition folderDefinition;
|
||||
folderDefinition.alias = alias;
|
||||
folderDefinition.localPath = path;
|
||||
folderDefinition.targetPath = targetPath;
|
||||
folderDefinition.paused = paused;
|
||||
folderDefinition.ignoreHiddenFiles = ignoreHiddenFiles();
|
||||
settings.beginGroup(settingsAccountsC);
|
||||
const auto rootChildGroups = settings.childGroups();
|
||||
for (const auto &accountId : rootChildGroups) {
|
||||
qCDebug(lcFolderMan) << "try to migrate accountId:" << accountId;
|
||||
settings.beginGroup(accountId);
|
||||
settings.beginGroup(settingsFoldersC);
|
||||
|
||||
folder = addFolderInternal(folderDefinition, accountState, std::make_unique<VfsOff>());
|
||||
if (folder) {
|
||||
QStringList blackList = settings.value(QLatin1String("blackList")).toStringList();
|
||||
if (!blackList.empty()) {
|
||||
//migrate settings
|
||||
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, blackList);
|
||||
settings.remove(QLatin1String("blackList"));
|
||||
// FIXME: If you remove this codepath, you need to provide another way to do
|
||||
// this via theme.h or the normal FolderMan::setupFolders
|
||||
if (settings.childGroups().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
folder->saveToSettings();
|
||||
const auto childGroups = settings.childGroups();
|
||||
for (const auto &alias : childGroups) {
|
||||
settings.beginGroup(alias);
|
||||
qCDebug(lcFolderMan) << "try to migrate folder alias:" << alias;
|
||||
|
||||
const auto path = settings.value(QLatin1String("localPath")).toString();
|
||||
const auto targetPath = settings.value(QLatin1String("targetPath")).toString();
|
||||
const auto journalPath = settings.value(QLatin1String("journalPath")).toString();
|
||||
const auto paused = settings.value(QLatin1String("paused"), false).toBool();
|
||||
const auto ignoreHiddenFiles = settings.value(QLatin1String("ignoreHiddenFiles"), false).toBool();
|
||||
|
||||
if (path.isEmpty()) {
|
||||
qCDebug(lcFolderMan) << "localPath is empty";
|
||||
settings.endGroup();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (targetPath.isEmpty()) {
|
||||
qCDebug(lcFolderMan) << "targetPath is empty";
|
||||
settings.endGroup();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (journalPath.isEmpty()) {
|
||||
qCDebug(lcFolderMan) << "journalPath is empty";
|
||||
settings.endGroup();
|
||||
continue;
|
||||
}
|
||||
|
||||
FolderDefinition folderDefinition;
|
||||
folderDefinition.alias = alias;
|
||||
folderDefinition.localPath = path;
|
||||
folderDefinition.targetPath = targetPath;
|
||||
folderDefinition.journalPath = journalPath;
|
||||
folderDefinition.paused = paused;
|
||||
folderDefinition.ignoreHiddenFiles = ignoreHiddenFiles;
|
||||
|
||||
folder = addFolderInternal(folderDefinition, accountState, std::make_unique<VfsOff>());
|
||||
if (folder) {
|
||||
const auto blackList = settings.value(QLatin1String("blackList")).toStringList();
|
||||
if (!blackList.empty()) {
|
||||
//migrate settings
|
||||
folder->journalDb()->setSelectiveSyncList(SyncJournalDb::SelectiveSyncBlackList, blackList);
|
||||
settings.remove(QLatin1String("blackList"));
|
||||
// FIXME: If you remove this codepath, you need to provide another way to do
|
||||
// this via theme.h or the normal FolderMan::setupFolders
|
||||
}
|
||||
|
||||
folder->saveToSettings();
|
||||
}
|
||||
qCInfo(lcFolderMan) << "Migrated!" << folder;
|
||||
settings.sync();
|
||||
|
||||
if (folder) {
|
||||
return folder;
|
||||
}
|
||||
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
settings.endGroup();
|
||||
settings.endGroup();
|
||||
}
|
||||
qCInfo(lcFolderMan) << "Migrated!" << folder;
|
||||
settings.sync();
|
||||
return folder;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue