2015-04-09 17:19:17 +03:00
|
|
|
/*
|
|
|
|
* Copyright (C) by Olivier Goffart <ogoffart@woboq.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
2016-10-25 12:00:07 +03:00
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
2015-04-09 17:19:17 +03:00
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
|
|
* for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "accountmanager.h"
|
2015-04-17 18:56:17 +03:00
|
|
|
#include "sslerrordialog.h"
|
2015-07-16 15:21:51 +03:00
|
|
|
#include "proxyauthhandler.h"
|
2015-04-09 17:19:17 +03:00
|
|
|
#include <theme.h>
|
|
|
|
#include <creds/credentialsfactory.h>
|
|
|
|
#include <creds/abstractcredentials.h>
|
|
|
|
#include <cookiejar.h>
|
|
|
|
#include <QSettings>
|
|
|
|
#include <QDir>
|
|
|
|
#include <QNetworkAccessManager>
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
static const char urlC[] = "url";
|
|
|
|
static const char authTypeC[] = "authType";
|
|
|
|
static const char userC[] = "user";
|
|
|
|
static const char httpUserC[] = "http_user";
|
|
|
|
static const char caCertsKeyC[] = "CaCertificates";
|
2015-04-24 11:18:33 +03:00
|
|
|
static const char accountsC[] = "Accounts";
|
2015-09-03 07:23:19 +03:00
|
|
|
static const char versionC[] = "version";
|
2016-03-02 13:59:36 +03:00
|
|
|
static const char serverVersionC[] = "serverVersion";
|
2015-04-09 17:19:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace OCC {
|
|
|
|
|
|
|
|
AccountManager *AccountManager::instance()
|
|
|
|
{
|
|
|
|
static AccountManager instance;
|
|
|
|
return &instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AccountManager::restore()
|
2015-04-23 16:42:18 +03:00
|
|
|
{
|
2016-10-25 13:04:22 +03:00
|
|
|
auto settings = Utility::settingsWithGroup(QLatin1String(accountsC));
|
2015-04-23 16:42:18 +03:00
|
|
|
|
|
|
|
// If there are no accounts, check the old format.
|
2015-09-03 07:23:19 +03:00
|
|
|
if (settings->childGroups().isEmpty()
|
|
|
|
&& !settings->contains(QLatin1String(versionC))) {
|
2015-04-23 16:42:18 +03:00
|
|
|
return restoreFromLegacySettings();
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (const auto& accountId, settings->childGroups()) {
|
|
|
|
settings->beginGroup(accountId);
|
2016-03-01 18:08:23 +03:00
|
|
|
if (auto acc = loadAccountHelper(*settings)) {
|
2015-04-23 16:42:18 +03:00
|
|
|
acc->_id = accountId;
|
2016-03-01 18:08:23 +03:00
|
|
|
if (auto accState = AccountState::loadFromSettings(acc, *settings)) {
|
|
|
|
addAccountState(accState);
|
|
|
|
}
|
2015-04-23 16:42:18 +03:00
|
|
|
}
|
|
|
|
settings->endGroup();
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AccountManager::restoreFromLegacySettings()
|
2015-04-09 17:19:17 +03:00
|
|
|
{
|
|
|
|
// try to open the correctly themed settings
|
2016-10-25 13:04:22 +03:00
|
|
|
auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
|
2015-04-09 17:19:17 +03:00
|
|
|
|
|
|
|
// if the settings file could not be opened, the childKeys list is empty
|
2015-04-23 16:42:18 +03:00
|
|
|
// then try to load settings from a very old place
|
2015-04-09 17:19:17 +03:00
|
|
|
if( settings->childKeys().isEmpty() ) {
|
|
|
|
// Now try to open the original ownCloud settings to see if they exist.
|
|
|
|
QString 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("/ownCloud/owncloud.cfg");
|
|
|
|
|
|
|
|
qDebug() << "Migrate: checking old config " << oCCfgFile;
|
|
|
|
|
|
|
|
QFileInfo fi( oCCfgFile );
|
|
|
|
if( fi.isReadable() ) {
|
2017-02-08 14:30:32 +03:00
|
|
|
std::unique_ptr<QSettings> oCSettings(new QSettings(oCCfgFile, QSettings::IniFormat));
|
2015-04-09 17:19:17 +03:00
|
|
|
oCSettings->beginGroup(QLatin1String("ownCloud"));
|
|
|
|
|
|
|
|
// Check the theme url to see if it is the same url that the oC config was for
|
|
|
|
QString overrideUrl = Theme::instance()->overrideServerUrl();
|
|
|
|
if( !overrideUrl.isEmpty() ) {
|
|
|
|
if (overrideUrl.endsWith('/')) { overrideUrl.chop(1); }
|
|
|
|
QString 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
|
|
|
|
qDebug() << "Migrate oC config if " << oCUrl << " == " << overrideUrl << ":"
|
2015-04-23 16:42:18 +03:00
|
|
|
<< (oCUrl == overrideUrl ? "Yes" : "No");
|
2015-04-09 17:19:17 +03:00
|
|
|
if( oCUrl == overrideUrl ) {
|
2017-02-08 14:30:32 +03:00
|
|
|
settings = std::move(oCSettings);
|
2015-04-09 17:19:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-23 16:42:18 +03:00
|
|
|
// Try to load the single account.
|
2015-04-09 17:19:17 +03:00
|
|
|
if (!settings->childKeys().isEmpty()) {
|
2016-03-01 18:08:23 +03:00
|
|
|
if (auto acc = loadAccountHelper(*settings)) {
|
2015-04-23 16:42:18 +03:00
|
|
|
addAccount(acc);
|
|
|
|
return true;
|
2015-04-09 17:19:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-08-06 13:49:18 +03:00
|
|
|
void AccountManager::save(bool saveCredentials)
|
2015-04-09 17:19:17 +03:00
|
|
|
{
|
2016-10-25 13:04:22 +03:00
|
|
|
auto settings = Utility::settingsWithGroup(QLatin1String(accountsC));
|
2015-09-03 07:23:19 +03:00
|
|
|
settings->setValue(QLatin1String(versionC), 2);
|
2015-04-23 16:42:18 +03:00
|
|
|
foreach (const auto &acc, _accounts) {
|
|
|
|
settings->beginGroup(acc->account()->id());
|
2016-03-01 18:08:23 +03:00
|
|
|
saveAccountHelper(acc->account().data(), *settings, saveCredentials);
|
|
|
|
acc->writeToSettings(*settings);
|
2015-04-23 16:42:18 +03:00
|
|
|
settings->endGroup();
|
2015-04-17 18:56:17 +03:00
|
|
|
}
|
2015-09-17 14:48:05 +03:00
|
|
|
|
|
|
|
settings->sync();
|
|
|
|
qDebug() << "Saved all account settings, status:" << settings->status();
|
2015-04-17 18:56:17 +03:00
|
|
|
}
|
|
|
|
|
2016-03-01 18:08:23 +03:00
|
|
|
void AccountManager::saveAccount(Account* a)
|
2015-08-14 12:31:01 +03:00
|
|
|
{
|
2015-08-14 13:37:19 +03:00
|
|
|
qDebug() << "Saving account" << a->url().toString();
|
2016-10-25 13:04:22 +03:00
|
|
|
auto settings = Utility::settingsWithGroup(QLatin1String(accountsC));
|
2015-08-14 12:31:01 +03:00
|
|
|
settings->beginGroup(a->id());
|
2016-03-01 18:08:23 +03:00
|
|
|
saveAccountHelper(a, *settings, false); // don't save credentials they might not have been loaded yet
|
2015-08-14 12:31:01 +03:00
|
|
|
settings->endGroup();
|
2015-09-17 14:48:05 +03:00
|
|
|
|
|
|
|
settings->sync();
|
|
|
|
qDebug() << "Saved account settings, status:" << settings->status();
|
2015-08-14 12:31:01 +03:00
|
|
|
}
|
|
|
|
|
2016-03-01 18:08:23 +03:00
|
|
|
void AccountManager::saveAccountState(AccountState* a)
|
|
|
|
{
|
|
|
|
qDebug() << "Saving account state" << a->account()->url().toString();
|
2016-10-25 13:04:22 +03:00
|
|
|
auto settings = Utility::settingsWithGroup(QLatin1String(accountsC));
|
2016-03-01 18:08:23 +03:00
|
|
|
settings->beginGroup(a->account()->id());
|
|
|
|
a->writeToSettings(*settings);
|
|
|
|
settings->endGroup();
|
|
|
|
|
|
|
|
settings->sync();
|
|
|
|
qDebug() << "Saved account state settings, status:" << settings->status();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AccountManager::saveAccountHelper(Account* acc, QSettings& settings, bool saveCredentials)
|
2015-04-17 18:56:17 +03:00
|
|
|
{
|
2015-04-24 11:18:33 +03:00
|
|
|
settings.setValue(QLatin1String(urlC), acc->_url.toString());
|
2016-03-02 13:59:36 +03:00
|
|
|
settings.setValue(QLatin1String(serverVersionC), acc->_serverVersion);
|
2015-04-09 17:19:17 +03:00
|
|
|
if (acc->_credentials) {
|
2015-08-06 13:49:18 +03:00
|
|
|
if (saveCredentials) {
|
|
|
|
// Only persist the credentials if the parameter is set, on migration from 1.8.x
|
|
|
|
// we want to save the accounts but not overwrite the credentials
|
|
|
|
// (This is easier than asynchronously fetching the credentials from keychain and then
|
|
|
|
// re-persisting them)
|
|
|
|
acc->_credentials->persist();
|
|
|
|
}
|
2015-04-09 17:19:17 +03:00
|
|
|
Q_FOREACH(QString key, acc->_settingsMap.keys()) {
|
2015-04-24 11:18:33 +03:00
|
|
|
settings.setValue(key, acc->_settingsMap.value(key));
|
2015-04-09 17:19:17 +03:00
|
|
|
}
|
2015-04-24 11:18:33 +03:00
|
|
|
settings.setValue(QLatin1String(authTypeC), acc->_credentials->authType());
|
2015-04-09 17:19:17 +03:00
|
|
|
|
|
|
|
// HACK: Save http_user also as user
|
|
|
|
if (acc->_settingsMap.contains(httpUserC))
|
2015-04-24 11:18:33 +03:00
|
|
|
settings.setValue(userC, acc->_settingsMap.value(httpUserC));
|
2015-04-09 17:19:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Save accepted certificates.
|
2015-04-24 11:18:33 +03:00
|
|
|
settings.beginGroup(QLatin1String("General"));
|
2015-04-09 17:19:17 +03:00
|
|
|
qDebug() << "Saving " << acc->approvedCerts().count() << " unknown certs.";
|
|
|
|
QByteArray certs;
|
|
|
|
Q_FOREACH( const QSslCertificate& cert, acc->approvedCerts() ) {
|
|
|
|
certs += cert.toPem() + '\n';
|
|
|
|
}
|
|
|
|
if (!certs.isEmpty()) {
|
2015-04-24 11:18:33 +03:00
|
|
|
settings.setValue( QLatin1String(caCertsKeyC), certs );
|
2015-04-09 17:19:17 +03:00
|
|
|
}
|
2015-04-24 11:18:33 +03:00
|
|
|
settings.endGroup();
|
2015-04-09 17:19:17 +03:00
|
|
|
|
|
|
|
// Save cookies.
|
|
|
|
if (acc->_am) {
|
|
|
|
CookieJar* jar = qobject_cast<CookieJar*>(acc->_am->cookieJar());
|
|
|
|
if (jar) {
|
2017-01-26 12:54:03 +03:00
|
|
|
qDebug() << "Saving cookies." << acc->cookieJarPath();
|
|
|
|
jar->save(acc->cookieJarPath());
|
2015-04-09 17:19:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-01 18:08:23 +03:00
|
|
|
AccountPtr AccountManager::loadAccountHelper(QSettings& settings)
|
2015-04-23 16:42:18 +03:00
|
|
|
{
|
2016-10-11 12:46:51 +03:00
|
|
|
auto urlConfig = settings.value(QLatin1String(urlC));
|
|
|
|
if (!urlConfig.isValid()) {
|
|
|
|
// No URL probably means a corrupted entry in the account settings
|
|
|
|
qDebug() << "No URL for account " << settings.group();
|
|
|
|
return AccountPtr();
|
|
|
|
}
|
|
|
|
|
2015-07-16 15:21:51 +03:00
|
|
|
auto acc = createAccount();
|
2015-04-23 16:42:18 +03:00
|
|
|
|
2016-04-15 14:16:49 +03:00
|
|
|
QString authType = settings.value(QLatin1String(authTypeC)).toString();
|
2017-01-03 12:37:42 +03:00
|
|
|
|
|
|
|
// There was an account-type saving bug when 'skip folder config' was used
|
|
|
|
// See #5408. This attempts to fix up the "dummy" authType
|
|
|
|
if (authType == QLatin1String("dummy")) {
|
|
|
|
if (settings.contains(QLatin1String("http_user"))) {
|
|
|
|
authType = "http";
|
|
|
|
} else if (settings.contains(QLatin1String("shibboleth_shib_user"))) {
|
|
|
|
authType = "shibboleth";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-15 14:16:49 +03:00
|
|
|
QString overrideUrl = Theme::instance()->overrideServerUrl();
|
2016-06-28 15:27:00 +03:00
|
|
|
QString forceAuth = Theme::instance()->forceConfigAuthType();
|
|
|
|
if(!forceAuth.isEmpty() && !overrideUrl.isEmpty() ) {
|
|
|
|
// If forceAuth is set, this might also mean the overrideURL has changed.
|
|
|
|
// See enterprise issues #1126
|
2016-04-15 14:16:49 +03:00
|
|
|
acc->setUrl(overrideUrl);
|
2016-06-28 15:27:00 +03:00
|
|
|
authType = forceAuth;
|
2016-04-15 14:16:49 +03:00
|
|
|
} else {
|
2016-10-11 12:46:51 +03:00
|
|
|
acc->setUrl(urlConfig.toUrl());
|
2016-04-15 14:16:49 +03:00
|
|
|
}
|
2017-01-11 11:30:59 +03:00
|
|
|
|
|
|
|
qDebug() << "Account for" << acc->url() << "using auth type" << authType;
|
|
|
|
|
2016-03-02 13:59:36 +03:00
|
|
|
acc->_serverVersion = settings.value(QLatin1String(serverVersionC)).toString();
|
2015-04-23 16:42:18 +03:00
|
|
|
|
|
|
|
// We want to only restore settings for that auth type and the user value
|
2015-04-24 11:18:33 +03:00
|
|
|
acc->_settingsMap.insert(QLatin1String(userC), settings.value(userC));
|
2016-04-15 14:16:49 +03:00
|
|
|
QString authTypePrefix = authType + "_";
|
2015-04-24 11:18:33 +03:00
|
|
|
Q_FOREACH(QString key, settings.childKeys()) {
|
2015-04-23 16:42:18 +03:00
|
|
|
if (!key.startsWith(authTypePrefix))
|
|
|
|
continue;
|
2015-04-24 11:18:33 +03:00
|
|
|
acc->_settingsMap.insert(key, settings.value(key));
|
2015-04-23 16:42:18 +03:00
|
|
|
}
|
|
|
|
|
2016-04-15 14:16:49 +03:00
|
|
|
acc->setCredentials(CredentialsFactory::create(authType));
|
2015-04-23 16:42:18 +03:00
|
|
|
|
2017-01-02 10:34:02 +03:00
|
|
|
// now the server cert, it is in the general group
|
2015-04-24 11:18:33 +03:00
|
|
|
settings.beginGroup(QLatin1String("General"));
|
|
|
|
acc->setApprovedCerts(QSslCertificate::fromData(settings.value(caCertsKeyC).toByteArray()));
|
|
|
|
settings.endGroup();
|
|
|
|
|
2015-04-23 16:42:18 +03:00
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
|
2015-11-12 19:50:00 +03:00
|
|
|
AccountStatePtr AccountManager::account(const QString& name)
|
|
|
|
{
|
|
|
|
foreach (const auto& acc, _accounts) {
|
|
|
|
if (acc->account()->displayName() == name) {
|
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return AccountStatePtr();
|
|
|
|
}
|
|
|
|
|
2015-04-27 18:43:07 +03:00
|
|
|
AccountState *AccountManager::addAccount(const AccountPtr& newAccount)
|
2015-04-17 18:56:17 +03:00
|
|
|
{
|
2015-04-24 08:02:51 +03:00
|
|
|
auto id = newAccount->id();
|
|
|
|
if (id.isEmpty() || !isAccountIdAvailable(id)) {
|
|
|
|
id = generateFreeAccountId();
|
|
|
|
}
|
|
|
|
newAccount->_id = id;
|
|
|
|
|
2016-03-01 18:08:23 +03:00
|
|
|
auto newAccountState = new AccountState(newAccount);
|
|
|
|
addAccountState(newAccountState);
|
|
|
|
return newAccountState;
|
2015-04-17 18:56:17 +03:00
|
|
|
}
|
|
|
|
|
2015-05-12 16:16:32 +03:00
|
|
|
void AccountManager::deleteAccount(AccountState* account)
|
|
|
|
{
|
|
|
|
auto it = std::find(_accounts.begin(), _accounts.end(), account);
|
|
|
|
if (it == _accounts.end()) { return; }
|
|
|
|
auto copy = *it; // keep a reference to the shared pointer so it does not delete it just yet
|
|
|
|
_accounts.erase(it);
|
2015-05-12 16:37:16 +03:00
|
|
|
|
2017-01-26 12:54:03 +03:00
|
|
|
QFile::remove(account->account()->cookieJarPath());
|
|
|
|
|
2016-10-25 13:04:22 +03:00
|
|
|
auto settings = Utility::settingsWithGroup(QLatin1String(accountsC));
|
2015-05-12 16:37:16 +03:00
|
|
|
settings->remove(account->account()->id());
|
|
|
|
|
2015-07-03 12:13:19 +03:00
|
|
|
emit accountRemoved(account);
|
2015-05-12 16:16:32 +03:00
|
|
|
}
|
|
|
|
|
2015-07-16 15:21:51 +03:00
|
|
|
AccountPtr AccountManager::createAccount()
|
|
|
|
{
|
|
|
|
AccountPtr acc = Account::create();
|
|
|
|
acc->setSslErrorHandler(new SslDialogErrorHandler);
|
|
|
|
connect(acc.data(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy, QAuthenticator*)),
|
|
|
|
ProxyAuthHandler::instance(), SLOT(handleProxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
|
|
|
|
return acc;
|
|
|
|
}
|
|
|
|
|
2015-05-12 16:16:32 +03:00
|
|
|
|
2015-04-17 18:56:17 +03:00
|
|
|
void AccountManager::shutdown()
|
|
|
|
{
|
|
|
|
auto accountsCopy = _accounts;
|
|
|
|
_accounts.clear();
|
|
|
|
foreach (const auto &acc, accountsCopy) {
|
|
|
|
emit accountRemoved(acc.data());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-24 08:02:51 +03:00
|
|
|
bool AccountManager::isAccountIdAvailable(const QString& id) const
|
|
|
|
{
|
|
|
|
foreach (const auto& acc, _accounts) {
|
|
|
|
if (acc->account()->id() == id) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString AccountManager::generateFreeAccountId() const
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
forever {
|
|
|
|
QString id = QString::number(i);
|
|
|
|
if (isAccountIdAvailable(id)) {
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
2015-04-09 17:19:17 +03:00
|
|
|
|
2016-03-01 18:08:23 +03:00
|
|
|
void AccountManager::addAccountState(AccountState* accountState)
|
|
|
|
{
|
|
|
|
QObject::connect(accountState->account().data(),
|
|
|
|
SIGNAL(wantsAccountSaved(Account*)),
|
|
|
|
SLOT(saveAccount(Account*)));
|
|
|
|
|
|
|
|
AccountStatePtr ptr(accountState);
|
|
|
|
_accounts << ptr;
|
|
|
|
emit accountAdded(accountState);
|
|
|
|
}
|
|
|
|
|
2015-04-23 15:47:31 +03:00
|
|
|
}
|