diff --git a/src/gui/accountmanager.cpp b/src/gui/accountmanager.cpp index b755a37b1..90924bbec 100644 --- a/src/gui/accountmanager.cpp +++ b/src/gui/accountmanager.cpp @@ -30,6 +30,7 @@ static const char httpUserC[] = "http_user"; static const char caCertsKeyC[] = "CaCertificates"; static const char accountsC[] = "Accounts"; static const char versionC[] = "version"; +static const char serverVersionC[] = "serverVersion"; } @@ -165,6 +166,7 @@ void AccountManager::saveAccountState(AccountState* a) void AccountManager::saveAccountHelper(Account* acc, QSettings& settings, bool saveCredentials) { settings.setValue(QLatin1String(urlC), acc->_url.toString()); + settings.setValue(QLatin1String(serverVersionC), acc->_serverVersion); if (acc->_credentials) { if (saveCredentials) { // Only persist the credentials if the parameter is set, on migration from 1.8.x @@ -210,6 +212,7 @@ AccountPtr AccountManager::loadAccountHelper(QSettings& settings) auto acc = createAccount(); acc->setUrl(settings.value(QLatin1String(urlC)).toUrl()); + acc->_serverVersion = settings.value(QLatin1String(serverVersionC)).toString(); // We want to only restore settings for that auth type and the user value acc->_settingsMap.insert(QLatin1String(userC), settings.value(userC)); diff --git a/src/gui/accountsettings.cpp b/src/gui/accountsettings.cpp index 9cf0fe3aa..383751bc3 100644 --- a/src/gui/accountsettings.cpp +++ b/src/gui/accountsettings.cpp @@ -512,7 +512,11 @@ void AccountSettings::slotAccountStateChanged(int state) } if (state == AccountState::Connected) { - showConnectionLabel( tr("Connected to %1.").arg(serverWithUser) ); + QStringList errors; + if (account->serverVersionUnsupported()) { + errors << tr("The server version %1 is old and unsupported! Proceed at your own risk.").arg(account->serverVersion()); + } + showConnectionLabel( tr("Connected to %1.").arg(serverWithUser), errors ); } else if (state == AccountState::ServiceUnavailable) { showConnectionLabel( tr("Server %1 is temporarily unavailable.").arg(server) ); } else if (state == AccountState::SignedOut) { diff --git a/src/gui/application.cpp b/src/gui/application.cpp index 6d3b6cd39..702cdbcfb 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -219,10 +219,14 @@ void Application::slotAccountStateRemoved(AccountState *accountState) if (_gui) { disconnect(accountState, SIGNAL(stateChanged(int)), _gui, SLOT(slotAccountStateChanged())); + disconnect(accountState->account().data(), SIGNAL(serverVersionChanged(Account*,QString,QString)), + _gui, SLOT(slotTrayMessageIfServerUnsupported(Account*))); } if (_folderManager) { disconnect(accountState, SIGNAL(stateChanged(int)), _folderManager.data(), SLOT(slotAccountStateChanged())); + disconnect(accountState->account().data(), SIGNAL(serverVersionChanged(Account*,QString,QString)), + _folderManager.data(), SLOT(slotServerVersionChanged(Account*))); } // if there is no more account, show the wizard. @@ -237,8 +241,14 @@ void Application::slotAccountStateAdded(AccountState *accountState) { connect(accountState, SIGNAL(stateChanged(int)), _gui, SLOT(slotAccountStateChanged())); + connect(accountState->account().data(), SIGNAL(serverVersionChanged(Account*,QString,QString)), + _gui, SLOT(slotTrayMessageIfServerUnsupported(Account*))); connect(accountState, SIGNAL(stateChanged(int)), _folderManager.data(), SLOT(slotAccountStateChanged())); + connect(accountState->account().data(), SIGNAL(serverVersionChanged(Account*,QString,QString)), + _folderManager.data(), SLOT(slotServerVersionChanged(Account*))); + + _gui->slotTrayMessageIfServerUnsupported(accountState->account().data()); } void Application::slotCleanup() diff --git a/src/gui/folderman.cpp b/src/gui/folderman.cpp index 50659bf72..85bb94a47 100644 --- a/src/gui/folderman.cpp +++ b/src/gui/folderman.cpp @@ -744,6 +744,21 @@ void FolderMan::slotForwardFolderSyncStateChange() } } +void FolderMan::slotServerVersionChanged(Account *account) +{ + // Pause folders if the server version is unsupported + if (account->serverVersionUnsupported()) { + qDebug() << "The server version is unsupported:" << account->serverVersion() + << "pausing all folders on the account"; + + foreach (auto& f, _folderMap) { + if (f->accountState()->account().data() == account) { + f->setSyncPaused(true); + } + } + } +} + void FolderMan::slotFolderSyncStarted( ) { qDebug() << ">===================================== sync started for " << _currentSyncFolder->remoteUrl().toString(); diff --git a/src/gui/folderman.h b/src/gui/folderman.h index 7eca2919a..c8fe41374 100644 --- a/src/gui/folderman.h +++ b/src/gui/folderman.h @@ -196,6 +196,8 @@ private slots: // FolderMan::folderSyncStateChange(Folder*) signal. void slotForwardFolderSyncStateChange(); + void slotServerVersionChanged(Account* account); + private: /** Adds a new folder, does not add it to the account settings and * does not set an account on the new folder. diff --git a/src/gui/owncloudgui.cpp b/src/gui/owncloudgui.cpp index a2b01ff91..d5005cc9c 100644 --- a/src/gui/owncloudgui.cpp +++ b/src/gui/owncloudgui.cpp @@ -228,6 +228,18 @@ void ownCloudGui::slotAccountStateChanged() slotComputeOverallSyncStatus(); } +void ownCloudGui::slotTrayMessageIfServerUnsupported(Account* account) +{ + if (account->serverVersionUnsupported()) { + slotShowTrayMessage( + tr("Unsupported Server Version"), + tr("The server on account %1 runs an old and unsupported version %2. " + "Using this client with unsupported server versions is untested and " + "potentially dangerous. Proceed at your own risk.") + .arg(account->displayName(), account->serverVersion())); + } +} + void ownCloudGui::slotComputeOverallSyncStatus() { bool allSignedOut = true; diff --git a/src/gui/owncloudgui.h b/src/gui/owncloudgui.h index e5c8f2013..9405fa577 100644 --- a/src/gui/owncloudgui.h +++ b/src/gui/owncloudgui.h @@ -77,6 +77,7 @@ public slots: void slotHelp(); void slotOpenPath(const QString& path); void slotAccountStateChanged(); + void slotTrayMessageIfServerUnsupported(Account *account); void slotShowShareDialog(const QString &sharePath, const QString &localPath, bool resharingAllowed); void slotRemoveDestroyedShareDialogs(); diff --git a/src/libsync/account.cpp b/src/libsync/account.cpp index f0d947478..4f920b259 100644 --- a/src/libsync/account.cpp +++ b/src/libsync/account.cpp @@ -472,23 +472,34 @@ void Account::setCapabilities(const QVariantMap &caps) _capabilities = Capabilities(caps); } -QString Account::serverVersion() +QString Account::serverVersion() const { return _serverVersion; } -int Account::serverVersionInt() +int Account::serverVersionInt() const { // FIXME: Use Qt 5.5 QVersionNumber auto components = serverVersion().split('.'); return (components.value(0).toInt() << 16) + (components.value(1).toInt() << 8) - + components.value(2).toInt(); + + components.value(2).toInt(); +} + +bool Account::serverVersionUnsupported() const +{ + return serverVersionInt() < 0x070000; } void Account::setServerVersion(const QString& version) { + if (version == _serverVersion) { + return; + } + + auto oldServerVersion = _serverVersion; _serverVersion = version; + emit serverVersionChanged(this, oldServerVersion, version); } bool Account::rootEtagChangesNotOnlySubFolderEtags() diff --git a/src/libsync/account.h b/src/libsync/account.h index d87988c58..bc586c4ed 100644 --- a/src/libsync/account.h +++ b/src/libsync/account.h @@ -154,8 +154,20 @@ public: void setCapabilities(const QVariantMap &caps); const Capabilities &capabilities() const; void setServerVersion(const QString &version); - QString serverVersion(); - int serverVersionInt(); + QString serverVersion() const; + int serverVersionInt() const; + + /** Whether the server is too old. + * + * Not supporting server versions is a gradual process. There's a hard + * compatibility limit (see ConnectionValidator) that forbids connecting + * to extremely old servers. And there's a weak "untested, not + * recommended, potentially dangerous" limit, that users might want + * to go beyond. + * + * This function returns true if the server is beyond the weak limit. + */ + bool serverVersionUnsupported() const; // Fixed from 8.1 https://github.com/owncloud/client/issues/3730 bool rootEtagChangesNotOnlySubFolderEtags(); @@ -181,6 +193,8 @@ signals: // e.g. when the approved SSL certificates changed void wantsAccountSaved(Account* acc); + void serverVersionChanged(Account* account, const QString& newVersion, const QString& oldVersion); + protected Q_SLOTS: void slotHandleSslErrors(QNetworkReply*,QList); void slotCredentialsFetched(); diff --git a/src/libsync/connectionvalidator.cpp b/src/libsync/connectionvalidator.cpp index 48252cb8b..83019dc42 100644 --- a/src/libsync/connectionvalidator.cpp +++ b/src/libsync/connectionvalidator.cpp @@ -122,6 +122,7 @@ void ConnectionValidator::slotStatusFound(const QUrl&url, const QVariantMap &inf QString version = CheckServerJob::version(info); _account->setServerVersion(version); + // We cannot deal with servers < 5.0.0 if (version.contains('.') && version.split('.')[0].toInt() < 5) { _errors.append( tr("The configured server for this client is too old") ); _errors.append( tr("Please update to the latest server and restart the client.") ); @@ -129,6 +130,9 @@ void ConnectionValidator::slotStatusFound(const QUrl&url, const QVariantMap &inf return; } + // We attempt to work with servers >= 5.0.0 but warn users. + // Check usages of Account::serverVersionUnsupported() for details. + // now check the authentication if (_account->credentials()->ready()) QTimer::singleShot( 0, this, SLOT( checkAuthentication() ));