- Make saving/restoring accounts work.

- Prepare for fetching quota
This commit is contained in:
Daniel Molkentin 2013-11-04 16:36:23 +01:00
parent 86af2848dd
commit 85d5b82811
23 changed files with 365 additions and 181 deletions

View file

@ -19,9 +19,9 @@
#include <csync.h>
class QNetworkAccessManager;
namespace Mirall
{
class Account;
class AbstractCredentials : public QObject
{
@ -35,8 +35,9 @@ public:
virtual QString authType() const = 0;
virtual QNetworkAccessManager* getQNAM() const = 0;
virtual bool ready() const = 0;
virtual void fetch() = 0;
virtual void persistForUrl(const QString& url) = 0;
virtual void fetch(Account *account) = 0;
virtual void persist(Account *account) = 0;
Q_SIGNALS:
void fetched();

View file

@ -45,12 +45,12 @@ bool DummyCredentials::ready() const
return true;
}
void DummyCredentials::fetch()
void DummyCredentials::fetch(Account*)
{
Q_EMIT(fetched());
}
void DummyCredentials::persistForUrl(const QString&)
void DummyCredentials::persist(Account*)
{}
} // ns Mirall

View file

@ -30,8 +30,8 @@ public:
QString authType() const;
QNetworkAccessManager* getQNAM() const;
bool ready() const;
void fetch();
void persistForUrl(const QString& url);
void fetch(Account*);
void persist(Account*);
};
} // ns Mirall

View file

@ -60,8 +60,9 @@ void CredentialStore::fetchCredentials()
bool ok = false;
QString pwd;
_user = cfgFile.user();
_url = cfgFile.ownCloudUrl();
// ###
// _url = url;
// _user = user;
QString key = keyChainKey(_url);

View file

@ -60,6 +60,7 @@ public:
KeyChain
};
explicit CredentialStore(QObject *parent = 0);
QString password( ) const;
QString user( ) const;
@ -109,7 +110,6 @@ protected slots:
void slotKeyChainWriteFinished( QKeychain::Job* );
private:
explicit CredentialStore(QObject *parent = 0);
void deleteKeyChainCredential( const QString& );
QString keyChainKey( const QString& ) const;

View file

@ -17,14 +17,19 @@
#include <QMutex>
#include <QDebug>
#include <QNetworkReply>
#include <QSettings>
#include <qtkeychain/keychain.h>
#include "mirall/account.h"
#include "mirall/mirallaccessmanager.h"
#include "mirall/utility.h"
#include "mirall/theme.h"
#include "creds/credentialscommon.h"
#include "creds/http/credentialstore.h"
#include "creds/httpcredentials.h"
using namespace QKeychain;
namespace Mirall
{
@ -66,6 +71,8 @@ int getauth(const char *prompt,
return re;
}
const char userC[] = "user";
} // ns
class HttpCredentialsAccessManager : public MirallAccessManager {
@ -77,7 +84,7 @@ protected:
QByteArray credHash = QByteArray(_cred->user().toUtf8()+":"+_cred->password().toUtf8()).toBase64();
QNetworkRequest req(request);
req.setRawHeader(QByteArray("Authorization"), QByteArray("Basic ") + credHash);
return MirallAccessManager::createRequest(op, req, outgoingData);\
return MirallAccessManager::createRequest(op, req, outgoingData);
}
private:
const HttpCredentials *_cred;
@ -94,9 +101,6 @@ HttpCredentials::HttpCredentials(const QString& user, const QString& password)
_password(password),
_ready(true)
{
_store = new CredentialStore(this);
connect(store, SIGNAL(fetchCredentialsFinished(bool)),
this, SLOT(slotCredentialsFetched(bool)));
}
void HttpCredentials::syncContextPreInit (CSYNC* ctx)
@ -166,30 +170,60 @@ bool HttpCredentials::ready() const
return _ready;
}
void HttpCredentials::fetch()
void HttpCredentials::fetch(Account *account)
{
_user = account->credentialSetting(QLatin1String(userC)).toString();
if (_ready) {
Q_EMIT fetched();
} else {
// TODO: merge CredentialStore into HttpCredentials?
_store->fetchCredentials();
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
job->setSettings(account->settingsWithGroup(Theme::instance()->appName()));
job->setInsecureFallback(true);
job->setKey(keychainKey(account->url().toString(), _user));
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
job->start();
}
}
void HttpCredentials::persistForUrl(const QString& url)
void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
{
_store->setCredentials(url, _user, _password);
_store->saveCredentials();
ReadPasswordJob *readJob = static_cast<ReadPasswordJob*>(job);
delete readJob->settings();
_password = readJob->textData();
QKeychain::Error error = job->error();
switch (error) {
case NoError:
Q_EMIT fetched();
break;
default:
// ### retry with insecure storage
qDebug() << "Error while reading password" << job->errorString();
}
}
void HttpCredentials::slotCredentialsFetched(bool ok)
void HttpCredentials::persist(Account *account)
{
_ready = ok;
if (_ready) {
_user = _store->user();
_password = _store->password();
QString user = account->credentialSetting(QLatin1String(userC)).toString();
account->setCredentialSetting(QLatin1String(userC), _user);
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
job->setSettings(account->settingsWithGroup(Theme::instance()->appName()));
job->setInsecureFallback(true);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotWriteJobDone(QKeychain::Job*)));
job->setKey(keychainKey(account->url().toString(), user));
job->setTextData(_password);
job->start();
}
void HttpCredentials::slotWriteJobDone(QKeychain::Job *job)
{
delete job->settings();
switch (job->error()) {
case NoError:
break;
default:
qDebug() << "Error while writing password" << job->errorString();
}
Q_EMIT fetched();
}
void HttpCredentials::slotAuthentication(QNetworkReply* reply, QAuthenticator* authenticator)
@ -202,12 +236,24 @@ void HttpCredentials::slotAuthentication(QNetworkReply* reply, QAuthenticator* a
reply->close();
}
void HttpCredentials::slotReplyFinished()
QString HttpCredentials::keychainKey(const QString &url, const QString &user)
{
QNetworkReply* reply = qobject_cast< QNetworkReply* >(sender());
QString u(url);
if( u.isEmpty() ) {
qDebug() << "Empty url in keyChain, error!";
return QString::null;
}
if( user.isEmpty() ) {
qDebug() << "Error: User is emty!";
return QString::null;
}
disconnect(reply, SIGNAL(finished()),
this, SLOT(slotReplyFinished()));
if( !u.endsWith(QChar('/')) ) {
u.append(QChar('/'));
}
QString key = user+QLatin1Char(':')+u;
return key;
}
} // ns Mirall

View file

@ -24,11 +24,13 @@
class QNetworkReply;
class QAuthenticator;
namespace QKeychain {
class Job;
}
namespace Mirall
{
class CredentialStore;
class HttpCredentials : public AbstractCredentials
{
Q_OBJECT
@ -43,19 +45,19 @@ public:
QString authType() const;
QNetworkAccessManager* getQNAM() const;
bool ready() const;
void fetch();
void persistForUrl(const QString& url);
void fetch(Account *account);
void persist(Account *account);
QString user() const;
QString password() const;
private Q_SLOTS:
void slotCredentialsFetched(bool);
void slotAuthentication(QNetworkReply*, QAuthenticator*);
void slotReplyFinished();
void slotReadJobDone(QKeychain::Job*);
void slotWriteJobDone(QKeychain::Job*);
private:
CredentialStore *_store;
static QString keychainKey(const QString &url, const QString &user);
QString _user;
QString _password;
bool _ready;

View file

@ -65,7 +65,9 @@ int shibboleth_redirect_callback(CSYNC* csync_ctx,
} // ns
ShibbolethCredentials::ShibbolethCredentials()
: _shibCookie(),
: AbstractCredentials(),
_url(),
_shibCookie(),
_ready(false),
_browser(0),
_otherCookies()
@ -163,14 +165,16 @@ bool ShibbolethCredentials::ready() const
return _ready;
}
void ShibbolethCredentials::fetch()
void ShibbolethCredentials::fetch(Account *account)
{
if (_ready) {
Q_EMIT fetched();
} else {
ShibbolethConfigFile cfg;
_browser = new ShibbolethWebView(QUrl(cfg.ownCloudUrl()), cfg.createCookieJar());
if (account) {
_url = account->url();
}
_browser = new ShibbolethWebView(_url, cfg.createCookieJar());
connect(_browser, SIGNAL(shibbolethCookieReceived(QNetworkCookie)),
this, SLOT(onShibbolethCookieReceived(QNetworkCookie)));
connect(_browser, SIGNAL(viewHidden()),
@ -179,7 +183,7 @@ void ShibbolethCredentials::fetch()
}
}
void ShibbolethCredentials::persistForUrl(const QString& /*url*/)
void ShibbolethCredentials::persist(Account* /*account*/)
{
ShibbolethConfigFile cfg;
@ -219,7 +223,10 @@ void ShibbolethCredentials::invalidateAndFetch()
_ready = false;
connect (this, SIGNAL(fetched()),
this, SLOT(onFetched()));
fetch();
// small hack to support the ShibbolethRefresher hack
// we already rand fetch() with a valid account object,
// and hence know the url on refresh
fetch(0);
}
void ShibbolethCredentials::onFetched()

View file

@ -40,8 +40,8 @@ public:
QString authType() const;
QNetworkAccessManager* getQNAM() const;
bool ready() const;
void fetch();
void persistForUrl(const QString& url);
void fetch(Account *account);
void persist(Account *account);
QNetworkCookie cookie() const;
@ -58,6 +58,7 @@ Q_SIGNALS:
void invalidatedAndFetched(const QByteArray& cookieData);
private:
QUrl _url;
QByteArray prepareCookieData() const;
void disposeBrowser();

View file

@ -14,6 +14,7 @@
#include "mirall/account.h"
#include "mirall/theme.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/networkjobs.h"
#include "creds/abstractcredentials.h"
#include "creds/credentialsfactory.h"
@ -58,22 +59,32 @@ Account::Account(AbstractSslErrorHandler *sslErrorHandler, QObject *parent)
, _credentials(0)
, _treatSslErrorsAsFailure(false)
, _sslErrorHandler(0)
, _lastQuotaTotalBytes(0)
, _lastQuotaUsedBytes(0)
{
setSslErrorHandler(sslErrorHandler);
}
void Account::save(QSettings &settings)
Account::~Account()
{
settings.beginGroup(Theme::instance()->appName());
settings.setValue(QLatin1String(urlC), _url);
}
void Account::save()
{
QScopedPointer<QSettings> settings(settingsWithGroup(Theme::instance()->appName()));
settings->setValue(QLatin1String(urlC), _url.toString());
if (_credentials) {
settings.setValue(QLatin1String(authTypeC), _credentials->authType());
_credentials->persist(this);
Q_FOREACH(QString key, _settingsMap.keys()) {
settings->setValue(key, _settingsMap.value(key));
}
settings->setValue(QLatin1String(authTypeC), _credentials->authType());
}
// ### TODO port away from ConfigFile
MirallConfigFile cfg;
qDebug() << "Saving " << approvedCerts().count() << " unknown certs.";
QByteArray certs;
foreach( const QSslCertificate& cert, approvedCerts() ) {
Q_FOREACH( const QSslCertificate& cert, approvedCerts() ) {
certs += cert.toPem() + '\n';
}
if (!certs.isEmpty()) {
@ -81,24 +92,23 @@ void Account::save(QSettings &settings)
}
}
Account* Account::restore(QSettings &settings)
Account* Account::restore()
{
QString groupName = Theme::instance()->appName();
if (settings.childGroups().contains(groupName)) {
MirallConfigFile cfg;
QScopedPointer<QSettings> settings(settingsWithGroup(Theme::instance()->appName()));
if (!settings->childKeys().isEmpty()) {
Account *acc = new Account;
MirallConfigFile cfg;
acc->setApprovedCerts(QSslCertificate::fromData(cfg.caCerts()));
settings.beginGroup(groupName);
acc->setUrl(settings.value(QLatin1String(urlC)).toUrl());
acc->setCredentials(CredentialsFactory::create(QLatin1String(urlC)));
acc->setUrl(settings->value(QLatin1String(urlC)).toUrl());
acc->setCredentials(CredentialsFactory::create(settings->value(QLatin1String(authTypeC)).toString()));
Q_FOREACH(QString key, settings->childKeys()) {
acc->_settingsMap.insert(key, settings->value(key));
}
return acc;
} else {
return 0;
}
return 0;
}
static bool isEqualExceptProtocol(const QUrl &url1, const QUrl &url2)
{
return (url1.host() != url2.host() ||
@ -215,6 +225,35 @@ QUrl Account::concatUrlPath(const QUrl &url, const QString &concatPath)
return tmpUrl;
}
QSettings *Account::settingsWithGroup(const QString& group)
{
MirallConfigFile cfg;
QSettings *settings = new QSettings(cfg.configFile(), QSettings::IniFormat);
settings->beginGroup(group);
return settings;
}
QVariant Account::credentialSetting(const QString &key) const
{
if (_credentials) {
QString prefix = _credentials->authType();
QString value = _settingsMap.value(prefix+"_"+key).toString();
if (value.isEmpty()) {
value = _settingsMap.value(key).toString();
}
return value;
}
return QVariant();
}
void Account::setCredentialSetting(const QString &key, const QVariant &value)
{
if (_credentials) {
QString prefix = _credentials->authType();
_settingsMap.insert(prefix+"_"+key, value);
}
}
void Account::slotHandleErrors(QNetworkReply *reply , QList<QSslError> errors)
{
qDebug() << "SSL-Warnings happened for url " << reply->url().toString();
@ -238,4 +277,17 @@ void Account::slotHandleErrors(QNetworkReply *reply , QList<QSslError> errors)
}
}
void Account::slotCheckQuota()
{
CheckQuotaJob *job = new CheckQuotaJob(this, "/", this);
connect(job, SIGNAL(quotaRetrieved(qint64,qint64)), SLOT(slotUpdateLastQuota(qint64,qint64)));
connect(job, SIGNAL(quotaRetrieved(qint64,qint64)), SIGNAL(q(qint64,qint64)));
}
void Account::slotUpdateLastQuota(qint64 total, qint64 used)
{
_lastQuotaTotalBytes = total;
_lastQuotaUsedBytes = used;
}
} // namespace Mirall

View file

@ -62,15 +62,17 @@ public:
static QString davPath() { return "remote.php/webdav/"; }
Account(AbstractSslErrorHandler *sslErrorHandler = 0, QObject *parent = 0);
~Account();
/**
* Saves the account to a given settings file
*/
void save(QSettings &settings);
void save();
/**
* Creates an account object from from a given settings file.
*/
static Account* restore(QSettings &settings);
static Account* restore();
/**
* @brief Creates a minimal account object
*
@ -114,14 +116,30 @@ public:
QList<QSslCertificate> approvedCerts() const { return _approvedCerts; }
void setApprovedCerts(const QList<QSslCertificate> certs);
// pluggable handler
void setSslErrorHandler(AbstractSslErrorHandler *handler);
// static helper function
static QUrl concatUrlPath(const QUrl &url, const QString &concatPath);
static QSettings* settingsWithGroup(const QString &group);
// to be called by credentials only
QVariant credentialSetting(const QString& key) const;
void setCredentialSetting(const QString& key, const QVariant &value);
qint64 lastQuotaTotalBytes() const { return _lastQuotaTotalBytes; }
qint64 lastQuotaUsedBytes() const { return _lastQuotaUsedBytes; }
protected slots:
void slotHandleErrors(QNetworkReply*,QList<QSslError>);
void slotCheckQuota();
void slotUpdateLastQuota(qint64 total, qint64 used);
signals:
void quotaUpdated(qint64 total, qint64 used);
private:
QMap<QString, QVariant> _settingsMap;
QNetworkAccessManager *_am;
QList<QSslCertificate> _caCerts;
QUrl _url;
@ -130,6 +148,8 @@ private:
QList<QSslCertificate> _certificateChain;
bool _treatSslErrorsAsFailure;
QScopedPointer<AbstractSslErrorHandler> _sslErrorHandler;
qint64 _lastQuotaTotalBytes;
qint64 _lastQuotaUsedBytes;
};
}

View file

@ -38,6 +38,8 @@
#include <QIcon>
#include <QVariant>
#include "mirall/account.h"
namespace Mirall {
static const char progressBarStyleC[] =
@ -53,7 +55,8 @@ static const char progressBarStyleC[] =
AccountSettings::AccountSettings(QWidget *parent) :
QWidget(parent),
ui(new Ui::AccountSettings),
_wasDisabledBefore(false)
_wasDisabledBefore(false),
_account(AccountManager::instance()->account())
{
ui->setupUi(this);
@ -90,18 +93,13 @@ AccountSettings::AccountSettings(QWidget *parent) :
QColor color = palette().highlight().color();
ui->quotaProgressBar->setStyleSheet(QString::fromLatin1(progressBarStyleC).arg(color.name()));
// ### TODO: merge with etag job when porting?
// ownCloudInfo *ocInfo = ownCloudInfo::instance();
// slotUpdateQuota(ocInfo->lastQuotaTotalBytes(), ocInfo->lastQuotaUsedBytes());
// connect(ocInfo, SIGNAL(quotaUpdated(qint64,qint64)), SLOT(slotUpdateQuota(qint64,qint64)));
ui->connectLabel->setWordWrap( true );
ui->quotaLabel->setWordWrap( true );
// ### TODO:
slotOnlineStateChanged();
setFolderList(FolderMan::instance()->map());
// ### TODO
//slotCheckConnection();
}
void AccountSettings::slotFolderActivated( const QModelIndex& indx )
@ -358,24 +356,6 @@ void AccountSettings::showConnectionLabel( const QString& message, const QString
}
}
// void AccountSettings::slotCheckConnection()
// {
// if( ownCloudInfo::instance()->isConfigured() ) {
// connect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(const QString&, const QString&, const QString&, const QString&)),
// this, SLOT(slotOCInfo( const QString&, const QString&, const QString&, const QString& )));
// connect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
// this, SLOT(slotOCInfoFail(QNetworkReply*)));
//
// showConnectionLabel( tr("Checking %1 connection...").arg(Theme::instance()->appNameGUI()));
// qDebug() << "Check status.php from statusdialog.";
// ownCloudInfo::instance()->checkInstallation();
// } else {
// // ownCloud is not yet configured.
// showConnectionLabel( tr("No %1 connection configured.").arg(Theme::instance()->appNameGUI()) );
// ui->_buttonAdd->setEnabled( false);
// }
// }
void AccountSettings::setFolderList( const Folder::Map &folders )
{
_model->clear();
@ -503,56 +483,51 @@ void AccountSettings::slotUpdateFolderState( Folder *folder )
} else {
// the dialog is not visible.
}
<<<<<<< HEAD
// ### TODO
//slotCheckConnection();
}
// showConnectionLabel( tr("Connected to <a href=\"%1\">%2</a>.").arg(url, safeUrl.toString()),
// tr("Version: %1 (%2)").arg(versionStr).arg(version) );
// ui->_ButtonAdd->setEnabled(true);
=======
slotCheckConnection();
// ### TODO
// slotCheckConnection();
}
void AccountSettings::slotOCInfo( const QString& url, const QString& versionStr, const QString& version, const QString& )
{
#ifdef Q_OS_WIN32
// work around a bug in QDesktopServices on Win32, see i-net
QString filePath = url;
//void AccountSettings::slotOCInfo( const QString& url, const QString& versionStr, const QString& version, const QString& )
//{
//#ifdef Q_OS_WIN32
// // work around a bug in QDesktopServices on Win32, see i-net
// QString filePath = url;
if (filePath.startsWith("\\\\") || filePath.startsWith("//"))
_OCUrl.setUrl(QDir::toNativeSeparators(filePath));
else
_OCUrl = QUrl::fromLocalFile(filePath);
#else
_OCUrl = QUrl::fromLocalFile(url);
#endif
// if (filePath.startsWith("\\\\") || filePath.startsWith("//"))
// _OCUrl.setUrl(QDir::toNativeSeparators(filePath));
// else
// _OCUrl = QUrl::fromLocalFile(filePath);
//#else
// _OCUrl = QUrl::fromLocalFile(url);
//#endif
qDebug() << "#-------# oC found on " << url;
/* enable the open button */
ui->connectLabel->setOpenExternalLinks(true);
QUrl safeUrl(url);
safeUrl.setPassword(QString()); // Remove the password from the URL to avoid showing it in the UI
showConnectionLabel( tr("Connected to <a href=\"%1\">%2</a>.").arg(url, safeUrl.toString()),
tr("Version: %1 (%2)").arg(versionStr).arg(version) );
ui->_buttonAdd->setEnabled(true);
// qDebug() << "#-------# oC found on " << url;
// /* enable the open button */
// ui->connectLabel->setOpenExternalLinks(true);
// QUrl safeUrl(url);
// safeUrl.setPassword(QString()); // Remove the password from the URL to avoid showing it in the UI
// showConnectionLabel( tr("Connected to <a href=\"%1\">%2</a>.").arg(url, safeUrl.toString()),
// tr("Version: %1 (%2)").arg(versionStr).arg(version) );
// ui->_buttonAdd->setEnabled(true);
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(const QString&, const QString&, const QString&, const QString&)),
this, SLOT(slotOCInfo( const QString&, const QString&, const QString&, const QString& )));
disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotOCInfoFail(QNetworkReply*)));
}
// disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(const QString&, const QString&, const QString&, const QString&)),
// this, SLOT(slotOCInfo( const QString&, const QString&, const QString&, const QString& )));
// disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
// this, SLOT(slotOCInfoFail(QNetworkReply*)));
//}
void AccountSettings::slotOCInfoFail( QNetworkReply *reply)
{
QString errStr = tr("unknown problem.");
if( reply ) errStr = reply->errorString();
showConnectionLabel( tr("<p>Failed to connect to %1: <tt>%2</tt></p>").arg(Theme::instance()->appNameGUI()).arg(errStr) );
ui->_buttonAdd->setEnabled( false);
>>>>>>> origin/master
//void AccountSettings::slotOCInfoFail( QNetworkReply *reply)
//{
// QString errStr = tr("unknown problem.");
// if( reply ) errStr = reply->errorString();
// showConnectionLabel( tr("<p>Failed to connect to %1: <tt>%2</tt></p>").arg(Theme::instance()->appNameGUI()).arg(errStr) );
// ui->_buttonAdd->setEnabled( false);
//}
void AccountSettings::slotOpenOC()
{
@ -793,6 +768,27 @@ void AccountSettings::slotIgnoreFilesEditor()
}
}
void AccountSettings::slotOnlineStateChanged(bool online)
{
if (_account) {
connect(_account, SIGNAL(quotaUpdated(qint64,qint64)), SLOT(slotUpdateQuota(qint64,qint64)), Qt::UniqueConnection);
slotUpdateQuota(_account->lastQuotaTotalBytes(), _account->lastQuotaUsedBytes());
if (online) {
QUrl safeUrl(_account->url());
safeUrl.setPassword(QString()); // Remove the password from the URL to avoid showing it in the UI
showConnectionLabel( tr("Connected to <a href=\"%1\">%2</a>.").arg(_account->url().toString(), safeUrl.toString())
/*, tr("Version: %1 (%2)").arg(versionStr).arg(version) */ );
ui->_buttonAdd->setEnabled(true);
} else {
showConnectionLabel( tr("Checking %1 connection...").arg(Theme::instance()->appNameGUI()));
}
} else {
// ownCloud is not yet configured.
showConnectionLabel( tr("No %1 connection configured.").arg(Theme::instance()->appNameGUI()) );
ui->_buttonAdd->setEnabled( false);
}
}
void AccountSettings::slotInfoAboutCurrentFolder()
{
emit(openProtocol());

View file

@ -38,6 +38,7 @@ class AccountSettings;
class FolderMan;
class IgnoreListEditor;
class Account;
class AccountSettings : public QWidget
{
@ -67,6 +68,7 @@ public slots:
void slotUpdateQuota( qint64,qint64 );
void slotIgnoreFilesEditor();
void slotOnlineStateChanged(bool online = true);
void setGeneralErrors( const QStringList& errors );
@ -97,6 +99,7 @@ private:
QString _kindContext;
QStringList _generalErrors;
bool _wasDisabledBefore;
Account *_account;
};
} // namespace Mirall

View file

@ -114,9 +114,7 @@ Application::Application(int &argc, char **argv) :
connect( this, SIGNAL(messageReceived(QString)), SLOT(slotParseOptions(QString)));
MirallConfigFile cfg;
QSettings settings(cfg.configFile(), QSettings::IniFormat);
Account *account = Account::restore(settings);
Account *account = Account::restore();
if (account) {
account->setSslErrorHandler(new SslDialogErrorHandler);
AccountManager::instance()->setAccount(account);
@ -137,6 +135,7 @@ Application::Application(int &argc, char **argv) :
// connect(_networkMgr, SIGNAL(onlineStateChanged(bool)), SLOT(slotCheckConnection()));
MirallConfigFile cfg;
_theme->setSystrayUseMonoIcons(cfg.monoIcons());
connect (_theme, SIGNAL(systrayUseMonoIconsChanged(bool)), SLOT(slotUseMonoIconsChanged(bool)));
@ -167,10 +166,8 @@ void Application::slotCleanup()
// explicitly close windows. This is somewhat of a hack to ensure
// that saving the geometries happens ASAP during a OS shutdown
Account *account = AccountManager::instance()->account();
MirallConfigFile cfg;
QSettings settings(cfg.configFile(), QSettings::IniFormat);
if (account) {
account->save(settings);
account->save();
}
_gui->slotShutdown();
_gui->deleteLater();
@ -184,14 +181,14 @@ void Application::slotStartUpdateDetector()
void Application::slotCheckConnection()
{
if( _gui->checkConfigExists(false) ) {
MirallConfigFile cfg;
AbstractCredentials* credentials(cfg.getCredentials());
if( _gui->checkAccountExists(false) ) {
Account *account = AccountManager::instance()->account();
AbstractCredentials* credentials(account->credentials());
if (! credentials->ready()) {
connect( credentials, SIGNAL(fetched()),
this, SLOT(slotCredentialsFetched()));
credentials->fetch();
credentials->fetch(account);
} else {
runValidator();
}
@ -203,10 +200,8 @@ void Application::slotCheckConnection()
void Application::slotCredentialsFetched()
{
MirallConfigFile cfg;
AbstractCredentials* credentials(cfg.getCredentials());
disconnect(credentials, SIGNAL(fetched()),
Account *account = AccountManager::instance()->account();
disconnect(account->credentials(), SIGNAL(fetched()),
this, SLOT(slotCredentialsFetched()));
runValidator();
}

View file

@ -22,12 +22,6 @@
namespace Mirall {
ConnectionValidator::ConnectionValidator(QObject *parent) :
QObject(parent)
{
}
ConnectionValidator::ConnectionValidator(Account *account, QObject *parent)
: QObject(parent),
_account(account),
@ -86,7 +80,7 @@ QString ConnectionValidator::statusString( Status stat ) const
void ConnectionValidator::checkConnection()
{
if( AccountManager::instance()->account() ) {
if( _account ) {
CheckServerJob *checkJob = new CheckServerJob(_account, false, this);
connect(checkJob, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotStatusFound(QUrl,QVariantMap)));
connect(checkJob, SIGNAL(networkError(QNetworkReply*)), SLOT(slotNoStatusFound(QNetworkReply*)));

View file

@ -27,7 +27,6 @@ class ConnectionValidator : public QObject
{
Q_OBJECT
public:
explicit ConnectionValidator(QObject *parent = 0);
explicit ConnectionValidator(Account *account, QObject *parent = 0);
enum Status {

View file

@ -60,8 +60,11 @@ void AbstractNetworkJob::setPath(const QString &path)
_path = path;
}
void AbstractNetworkJob::slotError()
void AbstractNetworkJob::slotError(QNetworkReply::NetworkError error)
{
if (error == QNetworkReply::ContentAccessDenied) {
// ### ask for password, retry job, needs refactoring to use start()
}
qDebug() << metaObject()->className() << "Error:" << _reply->errorString();
emit networkError(_reply);
deleteLater();
@ -71,7 +74,7 @@ void AbstractNetworkJob::setupConnections(QNetworkReply *reply)
{
connect(reply, SIGNAL(finished()), SLOT(slotFinished()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError()));
this, SLOT(slotError(QNetworkReply::NetworkError)));
}
QNetworkReply* AbstractNetworkJob::davRequest(const QByteArray &verb, const QString &relPath,
@ -140,7 +143,6 @@ RequestEtagJob::RequestEtagJob(Account *account, const QString &path, QObject *p
if( reply()->error() != QNetworkReply::NoError ) {
qDebug() << "getting etag: request network error: " << reply()->errorString();
}
}
void RequestEtagJob::slotFinished()
@ -312,6 +314,8 @@ void CheckServerJob::slotFinished()
deleteLater();
}
/*********************************************************************************************/
PropfindJob::PropfindJob(Account *account, const QString &path,
QList<QByteArray> properties,
QObject *parent)
@ -379,6 +383,8 @@ void PropfindJob::slotFinished()
deleteLater();
}
/*********************************************************************************************/
EntityExistsJob::EntityExistsJob(Account *account, const QString &path, QObject *parent)
: AbstractNetworkJob(account, path, parent)
{
@ -391,4 +397,53 @@ void EntityExistsJob::slotFinished()
emit exists(reply());
}
/*********************************************************************************************/
CheckQuotaJob::CheckQuotaJob(Account *account, const QString &path, QObject *parent)
: AbstractNetworkJob(account, path, parent)
{
QNetworkRequest req;
req.setRawHeader("Depth", "0");
QByteArray xml("<?xml version=\"1.0\" ?>\n"
"<d:propfind xmlns:d=\"DAV:\">\n"
" <d:prop>\n"
" <d:quota-available-bytes/>\n"
" <d:quota-used-bytes/>\n"
" </d:prop>\n"
"</d:propfind>\n");
QBuffer *buf = new QBuffer;
buf->setData(xml);
buf->open(QIODevice::ReadOnly);
// assumes ownership
setReply(davRequest("PROPFIND", path, req, buf));
buf->setParent(reply());
setupConnections(reply());
}
void CheckQuotaJob::slotFinished()
{
if (reply()->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 207) {
// Parse DAV response
QXmlStreamReader reader(reply());
reader.addExtraNamespaceDeclaration(QXmlStreamNamespaceDeclaration("d", "DAV:"));
qint64 quotaAvailableBytes = 0;
qint64 quotaUsedBytes = 0;
while (!reader.atEnd()) {
QXmlStreamReader::TokenType type = reader.readNext();
if (type == QXmlStreamReader::StartElement &&
reader.namespaceUri() == QLatin1String("DAV:")) {
QString name = reader.name().toString();
if (name == QLatin1String("quota-available-bytes")) {
quotaAvailableBytes = reader.readElementText().toLongLong();
} else if (name == QLatin1String("quota-used-bytes")) {
quotaUsedBytes = reader.readElementText().toLongLong();
}
}
}
qint64 total = quotaUsedBytes + quotaAvailableBytes;
emit quotaRetrieved(total, quotaUsedBytes);
}
deleteLater();
}
} // namespace Mirall

View file

@ -63,7 +63,7 @@ protected:
private slots:
virtual void slotFinished() = 0;
void slotError();
void slotError(QNetworkReply::NetworkError);
private:
QNetworkReply *_reply;
@ -101,7 +101,7 @@ private slots:
};
/**
* @brief The CheckQuotaJob class
* @brief The PropfindJob class
*/
class PropfindJob : public AbstractNetworkJob {
Q_OBJECT
@ -171,6 +171,21 @@ private slots:
virtual void slotFinished();
};
/**
* @brief The CheckQuota class
*/
class CheckQuotaJob : public AbstractNetworkJob {
Q_OBJECT
public:
explicit CheckQuotaJob(Account *account, const QString &path, QObject *parent = 0);
signals:
void quotaRetrieved(qint64 totalBytes, qint64 availableBytes);
private slots:
virtual void slotFinished();
};
} // namespace Mirall
#endif // NETWORKJOBS_H

View file

@ -79,7 +79,7 @@ ownCloudGui::ownCloudGui(Application *parent) :
}
// This should rather be in application.... or rather in MirallConfigFile?
bool ownCloudGui::checkConfigExists(bool openSettings)
bool ownCloudGui::checkAccountExists(bool openSettings)
{
// if account is set up, start the configuration wizard.
if( AccountManager::instance()->account() ) {
@ -100,7 +100,7 @@ void ownCloudGui::slotTrayClicked( QSystemTrayIcon::ActivationReason reason )
// Linux, not on Mac. They want a menu entry.
#if !defined Q_OS_MAC
if( reason == QSystemTrayIcon::Trigger ) {
checkConfigExists(true); // start settings if config is existing.
checkAccountExists(true); // start settings if config is existing.
}
#endif
}
@ -477,8 +477,7 @@ void ownCloudGui::slotToggleLogBrowser()
void ownCloudGui::slotOpenOwnCloud()
{
if (Account *account = AccountManager::instance()->account()) {
QString url = account->url();
QDesktopServices::openUrl( url );
QDesktopServices::openUrl(account->url());
}
}

View file

@ -39,7 +39,7 @@ public:
void setupContextMenu();
void startupConnected(bool connected , const QStringList &fails);
bool checkConfigExists(bool openSettings);
bool checkAccountExists(bool openSettings);
signals:
void setupProxy();

View file

@ -53,8 +53,6 @@ OwncloudSetupWizard::OwncloudSetupWizard(QObject* parent) :
Therefore Qt::QueuedConnection is required */
connect( _ocWizard, SIGNAL(basicSetupFinished(int)),
this, SLOT(slotAssistantFinished(int)), Qt::QueuedConnection);
connect( _ocWizard, SIGNAL(clearPendingRequests()),
this, SLOT(slotClearPendingRequests()));
}
OwncloudSetupWizard::~OwncloudSetupWizard()
@ -80,14 +78,13 @@ void OwncloudSetupWizard::runWizard(QObject* obj, const char* amember, QWidget *
void OwncloudSetupWizard::startWizard()
{
// ###
MirallConfigFile cfg;
QSettings settings(cfg.configFile(), QSettings::IniFormat);
Account *account = Account::restore(settings);
Account *account = Account::restore();
if (!account) {
account = new Account(new SslDialogErrorHandler);
account->setCredentials(CredentialsFactory::create("dummy"));
}
_ocWizard->setAccount(account);
_ocWizard->setOCUrl(account->url().toString());
_remoteFolder = Theme::instance()->defaultServerFolder();
// remoteFolder may be empty, which means /
@ -333,9 +330,7 @@ void OwncloudSetupWizard::replaceDefaultAccountWith(Account *newAccount)
mgr->account()->deleteLater();
}
mgr->setAccount(newAccount);
MirallConfigFile cfg;
QSettings settings(cfg.configFile(), QSettings::IniFormat);
newAccount->save(settings);
newAccount->save();
}
// Method executed when the user ends the wizard, either with 'accept' or 'reject'.

View file

@ -24,9 +24,11 @@
#include "wizard/owncloudwizard.h"
#include "wizard/owncloudwizardcommon.h"
#include "wizard/owncloudadvancedsetuppage.h"
#include "mirall/account.h"
#include "mirall/theme.h"
#include "mirall/mirallconfigfile.h"
#include "creds/abstractcredentials.h"
namespace Mirall
{
@ -135,21 +137,21 @@ void OwncloudAdvancedSetupPage::updateStatus()
bool OwncloudAdvancedSetupPage::dataChanged()
{
OwncloudWizard* ocWizard(dynamic_cast< OwncloudWizard* >(wizard()));
Account *oldAccount = AccountManager::instance()->account();
if (!ocWizard) {
if (!ocWizard || !oldAccount) {
return false;
}
MirallConfigFile cfgFile;
const QString url(field("OCUrl").toString());
AbstractCredentials* newCredentials(ocWizard->getCredentials());
AbstractCredentials* oldCredentials(cfgFile.getCredentials());
AbstractCredentials* oldCredentials(oldAccount->credentials());
const bool differentCreds(oldCredentials->changed(newCredentials));
delete newCredentials;
const QString newLocalFolder(QDir::toNativeSeparators(_ui.pbSelectLocalFolder->text()));
const QString oldLocalFolder(QDir::toNativeSeparators(_oldLocalFolder));
return ((url != cfgFile.ownCloudUrl()) || differentCreds || (oldLocalFolder != newLocalFolder));
return ((url != oldAccount->url().toString()) || differentCreds || (oldLocalFolder != newLocalFolder));
}
void OwncloudAdvancedSetupPage::startSpinner()

View file

@ -16,11 +16,13 @@
#include "QProgressIndicator.h"
#include "wizard/owncloudhttpcredspage.h"
#include "mirall/theme.h"
#include "wizard/owncloudwizardcommon.h"
#include "creds/httpcredentials.h"
#include "mirall/theme.h"
#include "mirall/account.h"
#include "mirall/mirallconfigfile.h"
#include "wizard/owncloudhttpcredspage.h"
#include "wizard/owncloudwizardcommon.h"
#include "wizard/owncloudwizard.h"
namespace Mirall
{
@ -65,12 +67,11 @@ void OwncloudHttpCredsPage::setupCustomization()
void OwncloudHttpCredsPage::initializePage()
{
WizardCommon::initErrorLabel(_ui.errorLabel);
MirallConfigFile cfgFile;
HttpCredentials* httpCreds(dynamic_cast< HttpCredentials* >(cfgFile.getCredentials()));
OwncloudWizard* ocWizard = qobject_cast< OwncloudWizard* >(wizard());
HttpCredentials *httpCreds = qobject_cast<HttpCredentials*>(ocWizard->account()->credentials());
if (httpCreds) {
const QString user = httpCreds->user();
if (!user.isEmpty()) {
_ui.leUsername->setText(user);
}