Merge branch 'shibboleth'

Conflicts:
	src/CMakeLists.txt
	src/mirall/application.h
This commit is contained in:
Daniel Molkentin 2013-08-05 19:54:06 +02:00
commit 0932ee6051
71 changed files with 4314 additions and 1532 deletions

View file

@ -62,7 +62,7 @@ endif()
####
#### find libs
find_package(Qt4 4.7.0 COMPONENTS QtCore QtGui QtXml QtNetwork QtTest REQUIRED )
find_package(Qt4 4.7.0 COMPONENTS QtCore QtGui QtXml QtNetwork QtTest QtWebkit REQUIRED )
if( UNIX AND NOT APPLE ) # Fdo notifications
find_package(Qt4 4.7.0 COMPONENTS QtDBus REQUIRED )
endif()

View file

@ -16,8 +16,6 @@ set(synclib_NAME ${APPLICATION_SHORTNAME}sync)
set(mirall_UI
mirall/folderwizardsourcepage.ui
mirall/folderwizardtargetpage.ui
mirall/owncloudsetuppage_ng.ui
mirall/owncloudwizardresultpage.ui
mirall/sslerrordialog.ui
mirall/settingsdialog.ui
mirall/generalsettings.ui
@ -26,6 +24,11 @@ mirall/accountsettings.ui
mirall/ignorelisteditor.ui
mirall/fileitemdialog.ui
mirall/itemprogressdialog.ui
wizard/owncloudsetupnocredspage.ui
wizard/owncloudhttpcredspage.ui
wizard/owncloudwizardresultpage.ui
wizard/owncloudshibbolethcredspage.ui
wizard/owncloudadvancedsetuppage.ui
)
set(3rdparty_SRC
@ -68,7 +71,6 @@ set(libsync_SRCS
mirall/syncresult.cpp
mirall/networklocation.cpp
mirall/mirallconfigfile.cpp
mirall/credentialstore.cpp
mirall/csyncthread.cpp
mirall/fileutils.cpp
mirall/theme.cpp
@ -78,8 +80,20 @@ set(libsync_SRCS
mirall/utility.cpp
mirall/connectionvalidator.cpp
mirall/progressdispatcher.cpp
mirall/mirallaccessmanager.cpp
creds/dummycredentials.cpp
creds/httpcredentials.cpp
creds/credentialsfactory.cpp
creds/http/credentialstore.cpp
creds/http/httpconfigfile.cpp
creds/shibbolethcredentials.cpp
creds/shibboleth/shibbolethaccessmanager.cpp
creds/shibboleth/shibbolethcookiejar.cpp
creds/shibboleth/shibbolethwebview.cpp
creds/shibboleth/shibbolethrefresher.cpp
)
set(libsync_HEADERS
set(libsync_HEADERS
mirall/folderman.h
mirall/folder.h
mirall/folderwatcher.h
@ -87,10 +101,21 @@ set(libsync_HEADERS
mirall/theme.h
mirall/owncloudtheme.h
mirall/owncloudinfo.h
mirall/credentialstore.h
mirall/logger.h
mirall/connectionvalidator.h
mirall/progressdispatcher.h
mirall/mirallaccessmanager.h
creds/abstractcredentials.h
creds/dummycredentials.h
creds/httpcredentials.h
creds/credentialsfactory.h
creds/http/credentialstore.h
creds/http/httpconfigfile.h
creds/shibbolethcredentials.h
creds/shibboleth/shibbolethaccessmanager.h
creds/shibboleth/shibbolethcookiejar.h
creds/shibboleth/shibbolethwebview.h
creds/shibboleth/shibbolethrefresher.h
)
IF( INOTIFY_FOUND )
@ -153,7 +178,13 @@ set(mirall_SRCS
mirall/systray.cpp
mirall/folderwizard.cpp
mirall/folderstatusmodel.cpp
mirall/owncloudwizard.cpp
wizard/owncloudwizard.cpp
wizard/owncloudsetuppage.cpp
wizard/owncloudhttpcredspage.cpp
wizard/owncloudwizardresultpage.cpp
wizard/owncloudwizardcommon.cpp
wizard/owncloudshibbolethcredspage.cpp
wizard/owncloudadvancedsetuppage.cpp
mirall/owncloudsetupwizard.cpp
mirall/updatedetector.cpp
mirall/occinfo.cpp
@ -173,7 +204,13 @@ set(mirall_HEADERS
mirall/systray.h
mirall/folderwizard.h
mirall/owncloudsetupwizard.h
mirall/owncloudwizard.h
wizard/owncloudwizard.h
wizard/owncloudsetuppage.h
wizard/owncloudhttpcredspage.h
wizard/owncloudwizardresultpage.h
wizard/owncloudwizardcommon.h
wizard/owncloudshibbolethcredspage.h
wizard/owncloudadvancedsetuppage.h
mirall/folderstatusmodel.h
mirall/updatedetector.h
mirall/sslerrordialog.h

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_CREDS_ABSTRACT_CREDENTIALS_H
#define MIRALL_CREDS_ABSTRACT_CREDENTIALS_H
#include <QObject>
#include <csync.h>
class QNetworkAccessManager;
namespace Mirall
{
class AbstractCredentials : public QObject
{
Q_OBJECT
public:
// No need for virtual destructor - QObject already has one.
virtual void syncContextPreInit(CSYNC* ctx) = 0;
virtual void syncContextPreStart(CSYNC* ctx) = 0;
virtual bool changed(AbstractCredentials* credentials) const = 0;
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;
Q_SIGNALS:
void fetched();
};
} // ns Mirall
#endif

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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 <QString>
#include "creds/httpcredentials.h"
#include "creds/dummycredentials.h"
#include "creds/shibbolethcredentials.h"
namespace Mirall
{
namespace CredentialsFactory
{
AbstractCredentials* create(const QString& type)
{
// empty string might happen for old version of configuration
if (type == "http" || type == "") {
return new HttpCredentials;
} else if (type == "dummy") {
return new DummyCredentials;
} else if (type == "shibboleth") {
return new ShibbolethCredentials;
} else {
qWarning("Unknown credentials type: %s", qPrintable(type));
return new DummyCredentials;
}
}
} // ns CredentialsFactory
} // ns Mirall

View file

@ -0,0 +1,32 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_CREDS_CREDENTIALS_FACTORY_H
#define MIRALL_CREDS_CREDENTIALS_FACTORY_H
class AbstractCredentials;
class QString;
namespace Mirall
{
namespace CredentialsFactory
{
AbstractCredentials* create(const QString& type);
} // ns CredentialsFactory
} // ns Mirall
#endif

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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 "creds/dummycredentials.h"
#include "mirall/mirallaccessmanager.h"
namespace Mirall
{
void DummyCredentials::syncContextPreInit(CSYNC*)
{}
void DummyCredentials::syncContextPreStart(CSYNC*)
{}
bool DummyCredentials::changed(AbstractCredentials* credentials) const
{
DummyCredentials* dummy(dynamic_cast< DummyCredentials* >(credentials));
return dummy == 0;
}
QString DummyCredentials::authType() const
{
return QString::fromLatin1("dummy");
}
QNetworkAccessManager* DummyCredentials::getQNAM() const
{
return new MirallAccessManager;
}
bool DummyCredentials::ready() const
{
return true;
}
void DummyCredentials::fetch()
{
Q_EMIT(fetched());
}
void DummyCredentials::persistForUrl(const QString&)
{}
} // ns Mirall

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_CREDS_DUMMY_CREDENTIALS_H
#define MIRALL_CREDS_DUMMY_CREDENTIALS_H
#include "creds/abstractcredentials.h"
namespace Mirall
{
class DummyCredentials : public AbstractCredentials
{
Q_OBJECT
public:
void syncContextPreInit(CSYNC* ctx);
void syncContextPreStart(CSYNC* ctx);
bool changed(AbstractCredentials* credentials) const;
QString authType() const;
QNetworkAccessManager* getQNAM() const;
bool ready() const;
void fetch();
void persistForUrl(const QString& url);
};
} // ns Mirall
#endif

View file

@ -16,8 +16,8 @@
#include "config.h"
#include "mirall/credentialstore.h"
#include "mirall/mirallconfigfile.h"
#include "creds/http/credentialstore.h"
#include "creds/http/httpconfigfile.h"
#include "mirall/theme.h"
#ifdef WITH_QTKEYCHAIN
@ -68,11 +68,11 @@ CredentialStore::CredState CredentialStore::state()
void CredentialStore::fetchCredentials()
{
MirallConfigFile cfgFile;
HttpConfigFile cfgFile;
bool ok = false;
QString pwd;
_user = cfgFile.ownCloudUser();
_user = cfgFile.user();
_url = cfgFile.ownCloudUrl();
QString key = keyChainKey(_url);
@ -88,8 +88,9 @@ void CredentialStore::fetchCredentials()
case CredentialStore::Settings: {
/* Read from config file. */
_state = Fetching;
if( cfgFile.ownCloudPasswordExists() ) {
pwd = cfgFile.ownCloudPasswd();
cfgFile.fixupOldPassword();
if( cfgFile.passwordExists() ) {
pwd = cfgFile.password();
ok = true;
} else {
ok = false;
@ -255,21 +256,21 @@ void CredentialStore::setCredentials( const QString& url, const QString& user,
void CredentialStore::saveCredentials( )
{
MirallConfigFile cfgFile;
HttpConfigFile cfgFile;
QString key = keyChainKey(_url);
if( key.isNull() ) {
qDebug() << "Error: Can not save credentials, URL is zero!";
return;
}
#ifdef WITH_QTKEYCHAIN
WritePasswordJob *job = NULL;
#endif
cfgFile.setUser(_user);
switch( _type ) {
case CredentialStore::KeyChain:
case CredentialStore::KeyChain: {
#ifdef WITH_QTKEYCHAIN
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
// Set password in KeyChain
job = new WritePasswordJob(Theme::instance()->appName());
job->setKey( key );
job->setTextData(_passwd);
@ -278,9 +279,10 @@ void CredentialStore::saveCredentials( )
_state = AsyncWriting;
job->start();
#endif
}
break;
case CredentialStore::Settings:
cfgFile.writePassword( _passwd );
cfgFile.setPassword( _passwd );
reset();
break;
default:
@ -309,8 +311,8 @@ void CredentialStore::slotKeyChainWriteFinished( QKeychain::Job *job )
} else {
qDebug() << "Successfully stored password for user " << _user;
// Try to remove password formerly stored in the config file.
MirallConfigFile cfgFile;
cfgFile.clearPasswordFromConfig();
HttpConfigFile cfgFile;
cfgFile.removePassword();
_state = NotFetched;
}
} else {

View file

@ -0,0 +1,81 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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 "creds/http/httpconfigfile.h"
namespace Mirall
{
namespace
{
const char userC[] = "user";
const char passwdC[] = "passwd";
const char oldPasswdC[] = "password";
} // ns
QString HttpConfigFile::user() const
{
return retrieveData(QString(), QLatin1String(userC)).toString();
}
void HttpConfigFile::setUser(const QString& user)
{
storeData(QString(), QLatin1String(userC), QVariant(user));
}
QString HttpConfigFile::password() const
{
const QVariant passwd(retrieveData(QString(), QLatin1String(passwdC)));
if (passwd.isValid()) {
return QString::fromUtf8(QByteArray::fromBase64(passwd.toByteArray()));
}
return QString();
}
void HttpConfigFile::setPassword(const QString& password)
{
QByteArray pwdba = password.toUtf8();
storeData( QString(), QLatin1String(passwdC), QVariant(pwdba.toBase64()) );
removeOldPassword();
}
bool HttpConfigFile::passwordExists() const
{
return dataExists(QString(), QLatin1String(passwdC));
}
void HttpConfigFile::removePassword()
{
removeOldPassword();
removeData(QString(), QLatin1String(passwdC));
}
void HttpConfigFile::fixupOldPassword()
{
const QString old(QString::fromLatin1(oldPasswdC));
if (dataExists(QString(), old)) {
setPassword(retrieveData(QString(), old).toString());
}
}
void HttpConfigFile::removeOldPassword()
{
removeData(QString(), QLatin1String(oldPasswdC));
}
} // ns Mirall

View file

@ -0,0 +1,40 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_CREDS_HTTP_CONFIG_FILE_H
#define MIRALL_CREDS_HTTP_CONFIG_FILE_H
#include "mirall/mirallconfigfile.h"
namespace Mirall
{
class HttpConfigFile : public MirallConfigFile
{
public:
QString user() const;
void setUser(const QString& user);
QString password() const;
void setPassword(const QString& password);
bool passwordExists() const;
void removePassword();
void fixupOldPassword();
private:
void removeOldPassword();
};
} // ns Mirall
#endif

View file

@ -0,0 +1,252 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@kde.org>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <QMutex>
#include "creds/httpcredentials.h"
#include "mirall/owncloudinfo.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/mirallaccessmanager.h"
#include "mirall/utility.h"
#include "creds/http/credentialstore.h"
namespace Mirall
{
namespace
{
int getauth(const char *prompt,
char *buf,
size_t len,
int /*echo*/,
int /*verify*/,
void */*userdata*/)
{
int re = 0;
QMutex mutex;
MirallConfigFile cfg;
HttpCredentials* http_credentials = dynamic_cast< HttpCredentials* > (cfg.getCredentials());
if (!http_credentials) {
qDebug() << "Not a HTTP creds instance!";
return -1;
}
QString qPrompt = QString::fromLatin1( prompt ).trimmed();
QString user = http_credentials->user();
QString pwd = http_credentials->password();
if( qPrompt == QLatin1String("Enter your username:") ) {
// qDebug() << "OOO Username requested!";
QMutexLocker locker( &mutex );
qstrncpy( buf, user.toUtf8().constData(), len );
} else if( qPrompt == QLatin1String("Enter your password:") ) {
QMutexLocker locker( &mutex );
// qDebug() << "OOO Password requested!";
qstrncpy( buf, pwd.toUtf8().constData(), len );
} else {
if( qPrompt.startsWith( QLatin1String("There are problems with the SSL certificate:"))) {
// SSL is requested. If the program came here, the SSL check was done by mirall
// It needs to be checked if the chain is still equal to the one which
// was verified by the user.
QRegExp regexp("fingerprint: ([\\w\\d:]+)");
bool certOk = false;
int pos = 0;
// This is the set of certificates which QNAM accepted, so we should accept
// them as well
QList<QSslCertificate> certs = ownCloudInfo::instance()->certificateChain();
while (!certOk && (pos = regexp.indexIn(qPrompt, 1+pos)) != -1) {
QString neon_fingerprint = regexp.cap(1);
foreach( const QSslCertificate& c, certs ) {
QString verified_shasum = Utility::formatFingerprint(c.digest(QCryptographicHash::Sha1).toHex());
qDebug() << "SSL Fingerprint from neon: " << neon_fingerprint << " compared to verified: " << verified_shasum;
if( verified_shasum == neon_fingerprint ) {
certOk = true;
break;
}
}
}
// certOk = false; DEBUG setting, keep disabled!
if( !certOk ) { // Problem!
qstrcpy( buf, "no" );
re = -1;
} else {
qstrcpy( buf, "yes" ); // Certificate is fine!
}
} else {
qDebug() << "Unknown prompt: <" << prompt << ">";
re = -1;
}
}
return re;
}
} // ns
HttpCredentials::HttpCredentials()
: _user(),
_password(),
_ready(false),
_attempts()
{}
HttpCredentials::HttpCredentials(const QString& user, const QString& password)
: _user(user),
_password(password),
_ready(true)
{}
void HttpCredentials::syncContextPreInit (CSYNC* ctx)
{
csync_set_auth_callback (ctx, getauth);
}
void HttpCredentials::syncContextPreStart (CSYNC* ctx)
{
// TODO: This should not be a part of this method, but we don't have
// any way to get "session_key" module property from csync. Had we
// have it, then we could remove this code and keep it in
// csyncthread code (or folder code, git remembers).
QList<QNetworkCookie> cookies(ownCloudInfo::instance()->getLastAuthCookies());
QString cookiesAsString;
// Stuff cookies inside csync, then we can avoid the intermediate HTTP 401 reply
// when https://github.com/owncloud/core/pull/4042 is merged.
foreach(QNetworkCookie c, cookies) {
cookiesAsString += c.name();
cookiesAsString += '=';
cookiesAsString += c.value();
cookiesAsString += "; ";
}
csync_set_module_property(ctx, "session_key", cookiesAsString.toLatin1().data());
}
bool HttpCredentials::changed(AbstractCredentials* credentials) const
{
HttpCredentials* other(dynamic_cast< HttpCredentials* >(credentials));
if (!other || other->user() != this->user()) {
return true;
}
return false;
}
QString HttpCredentials::authType() const
{
return QString::fromLatin1("http");
}
QString HttpCredentials::user() const
{
return _user;
}
QString HttpCredentials::password() const
{
return _password;
}
QNetworkAccessManager* HttpCredentials::getQNAM() const
{
MirallAccessManager* qnam = new MirallAccessManager;
connect( qnam, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
this, SLOT(slotAuthentication(QNetworkReply*,QAuthenticator*)));
return qnam;
}
bool HttpCredentials::ready() const
{
return _ready;
}
void HttpCredentials::fetch()
{
if (_ready) {
Q_EMIT fetched();
} else {
// TODO: merge CredentialStore into HttpCredentials?
CredentialStore* store(CredentialStore::instance());
connect(store, SIGNAL(fetchCredentialsFinished(bool)),
this, SLOT(slotCredentialsFetched(bool)));
store->fetchCredentials();
}
}
void HttpCredentials::persistForUrl(const QString& url)
{
CredentialStore* store(CredentialStore::instance());
store->setCredentials(url, _user, _password);
store->saveCredentials();
}
void HttpCredentials::slotCredentialsFetched(bool ok)
{
_ready = ok;
if (_ready) {
CredentialStore* store(CredentialStore::instance());
_user = store->user();
_password = store->password();
}
Q_EMIT fetched();
}
void HttpCredentials::slotAuthentication(QNetworkReply* reply, QAuthenticator* authenticator)
{
if( !(authenticator && reply) ) return;
qDebug() << "Authenticating request for " << reply->url();
if (_attempts.contains(reply)) {
++_attempts[reply];
} else {
connect(reply, SIGNAL(finished()),
this, SLOT(slotReplyFinished()));
_attempts[reply] = 1;
}
// TODO: Replace it with something meaningful...
//if( reply->url().toString().startsWith( webdavUrl( _connection ) ) ) {
if (_attempts[reply] > 1) {
qDebug() << "Too many attempts to authenticate. Stop request.";
reply->close();
} else {
authenticator->setUser( _user );
authenticator->setPassword( _password );
}
//} else {
// qDebug() << "WRN: attempt to authenticate to different url - closing.";
// reply->close();
//}
}
void HttpCredentials::slotReplyFinished()
{
QNetworkReply* reply = qobject_cast< QNetworkReply* >(sender());
disconnect(reply, SIGNAL(finished()),
this, SLOT(slotReplyFinished()));
_attempts.remove (reply);
}
} // ns Mirall

View file

@ -0,0 +1,64 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@kde.org>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifndef MIRALL_CREDS_HTTP_CREDENTIALS_H
#define MIRALL_CREDS_HTTP_CREDENTIALS_H
#include <QMap>
#include "creds/abstractcredentials.h"
class QNetworkReply;
class QAuthenticator;
namespace Mirall
{
class HttpCredentials : public AbstractCredentials
{
Q_OBJECT
public:
HttpCredentials();
HttpCredentials(const QString& user, const QString& password);
void syncContextPreInit(CSYNC* ctx);
void syncContextPreStart(CSYNC* ctx);
bool changed(AbstractCredentials* credentials) const;
QString authType() const;
QNetworkAccessManager* getQNAM() const;
bool ready() const;
void fetch();
void persistForUrl(const QString& url);
QString user() const;
QString password() const;
private Q_SLOTS:
void slotCredentialsFetched(bool);
void slotAuthentication(QNetworkReply*, QAuthenticator*);
void slotReplyFinished();
private:
QString _user;
QString _password;
bool _ready;
QMap<QNetworkReply*, int> _attempts;
};
} // ns Mirall
#endif

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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 <QDebug>
#include <QNetworkRequest>
#include "creds/shibboleth/shibbolethaccessmanager.h"
namespace Mirall
{
ShibbolethAccessManager::ShibbolethAccessManager(const QNetworkCookie& cookie, QObject* parent)
: MirallAccessManager (parent),
_cookie(cookie)
{}
QNetworkReply* ShibbolethAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData)
{
if (!_cookie.name().isEmpty()) {
QNetworkCookieJar* jar(cookieJar());
QUrl url(request.url());
QList<QNetworkCookie> cookies;
Q_FOREACH(const QNetworkCookie& cookie, jar->cookiesForUrl(url)) {
if (!cookie.name().startsWith("_shibsession_")) {
cookies << cookie;
}
}
cookies << _cookie;
jar->setCookiesFromUrl(cookies, url);
}
qDebug() << "Creating a request to " << request.url().toString() << " with shibboleth cookie:" << _cookie.name();
return MirallAccessManager::createRequest (op, request, outgoingData);
}
void ShibbolethAccessManager::setCookie(const QNetworkCookie& cookie)
{
qDebug() << "Got new shibboleth cookie:" << cookie.name();
_cookie = cookie;
}
} // ns Mirall

View file

@ -0,0 +1,43 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_WIZARD_SHIBBOLETH_ACCESS_MANAGER_H
#define MIRALL_WIZARD_SHIBBOLETH_ACCESS_MANAGER_H
#include <QNetworkCookie>
#include "mirall/mirallaccessmanager.h"
namespace Mirall
{
class ShibbolethAccessManager : public MirallAccessManager
{
Q_OBJECT
public:
ShibbolethAccessManager(const QNetworkCookie& cookie, QObject* parent = 0);
public Q_SLOTS:
void setCookie(const QNetworkCookie& cookie);
protected:
QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData = 0);
private:
QNetworkCookie _cookie;
};
} // ns Mirall
#endif

View file

@ -0,0 +1,34 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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 "creds/shibboleth/shibbolethcookiejar.h"
namespace Mirall
{
ShibbolethCookieJar::ShibbolethCookieJar (QObject* parent)
: QNetworkCookieJar (parent)
{}
bool ShibbolethCookieJar::setCookiesFromUrl (const QList<QNetworkCookie>& cookieList, const QUrl& url)
{
if (QNetworkCookieJar::setCookiesFromUrl (cookieList, url)) {
Q_EMIT newCookiesForUrl (cookieList, url);
return true;
}
return false;
}
} // ns Mirall

View file

@ -0,0 +1,41 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_WIZARD_SHIBBOLETH_COOKIE_JAR_H
#define MIRALL_WIZARD_SHIBBOLETH_COOKIE_JAR_H
#include <QNetworkCookieJar>
#include <QList>
class QUrl;
class QNetworkCookie;
namespace Mirall
{
class ShibbolethCookieJar : public QNetworkCookieJar
{
Q_OBJECT
public:
ShibbolethCookieJar (QObject* parent = 0);
virtual bool setCookiesFromUrl (const QList<QNetworkCookie>& cookieList, const QUrl& url);
Q_SIGNALS:
void newCookiesForUrl (const QList<QNetworkCookie>& cookieList, const QUrl& url);
};
} // ns Mirall
#endif

View file

@ -0,0 +1,52 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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 <QEventLoop>
#include "creds/shibboleth/shibbolethrefresher.h"
#include "creds/shibbolethcredentials.h"
namespace Mirall
{
ShibbolethRefresher::ShibbolethRefresher(ShibbolethCredentials* creds, CSYNC* csync_ctx, QObject* parent)
: QObject(parent),
_creds(creds),
_csync_ctx(csync_ctx)
{}
void ShibbolethRefresher::refresh()
{
QEventLoop loop;
connect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
this, SLOT(onInvalidatedAndFetched(QByteArray)));
connect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
&loop, SLOT(quit()));
QMetaObject::invokeMethod(_creds, "invalidateAndFetch", Qt::QueuedConnection);
loop.exec();
disconnect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
&loop, SLOT(quit()));
}
void ShibbolethRefresher::onInvalidatedAndFetched(const QByteArray& cookies)
{
// "cookies" is const and its data() return const void*. We want just void*.
QByteArray myCookies(cookies);
disconnect(_creds, SIGNAL(invalidatedAndFetched(QByteArray)),
this, SLOT(onInvalidatedAndFetched(QByteArray)));
csync_set_module_property(_csync_ctx, "session_key", myCookies.data());
}
} // ns Mirall

View file

@ -0,0 +1,47 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_CREDS_SHIBBOLETH_REFRESHER_H
#define MIRALL_CREDS_SHIBBOLETH_REFRESHER_H
#include <QObject>
#include <csync.h>
class QByteArray;
namespace Mirall
{
class ShibbolethCredentials;
class ShibbolethRefresher : public QObject
{
Q_OBJECT
public:
ShibbolethRefresher(ShibbolethCredentials* creds, CSYNC* csync_ctx, QObject* parent = 0);
void refresh();
private Q_SLOTS:
void onInvalidatedAndFetched(const QByteArray& cookieData);
private:
ShibbolethCredentials* _creds;
CSYNC* _csync_ctx;
};
} // ns Mirall
#endif

View file

@ -0,0 +1,52 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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 <QNetworkCookie>
#include <QWebFrame>
#include <QWebPage>
#include "creds/shibboleth/shibbolethcookiejar.h"
#include "creds/shibboleth/shibbolethwebview.h"
#include "mirall/mirallaccessmanager.h"
namespace Mirall
{
ShibbolethWebView::ShibbolethWebView(const QUrl& url, QWidget* parent)
: QWebView(parent)
{
MirallAccessManager* nm = new MirallAccessManager(this);
ShibbolethCookieJar* jar = new ShibbolethCookieJar(this);
QWebPage* page = new QWebPage(this);
connect (jar, SIGNAL (newCookiesForUrl (QList<QNetworkCookie>, QUrl)),
this, SLOT (onNewCookiesForUrl (QList<QNetworkCookie>, QUrl)));
nm->setCookieJar(jar);
page->setNetworkAccessManager(nm);
page->mainFrame ()->load (url);
this->setPage (page);
}
void ShibbolethWebView::onNewCookiesForUrl (const QList<QNetworkCookie>& cookieList, const QUrl& /*url*/)
{
Q_FOREACH (const QNetworkCookie& cookie, cookieList) {
if (cookie.name().startsWith ("_shibsession_")) {
Q_EMIT shibbolethCookieReceived (cookie);
return;
}
}
}
} // ns Mirall

View file

@ -0,0 +1,42 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_WIZARD_SHIBBOLETH_WEB_VIEW_H
#define MIRALL_WIZARD_SHIBBOLETH_WEB_VIEW_H
#include <QList>
#include <QWebView>
class QNetworkCookie;
class QUrl;
namespace Mirall
{
class ShibbolethWebView : public QWebView
{
Q_OBJECT
public:
ShibbolethWebView(const QUrl& url, QWidget* parent = 0);
Q_SIGNALS:
void shibbolethCookieReceived (const QNetworkCookie& cookie);
private Q_SLOTS:
void onNewCookiesForUrl (const QList<QNetworkCookie>& cookieList, const QUrl& url);
};
} // ns Mirall
#endif

View file

@ -0,0 +1,205 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
* Copyright (C) by Klaas Freitag <freitag@owncloud.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
* the Free Software Foundation; version 2 of the License.
*
* 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 "creds/shibbolethcredentials.h"
#include "creds/shibboleth/shibbolethaccessmanager.h"
#include "creds/shibboleth/shibbolethwebview.h"
#include "creds/shibboleth/shibbolethrefresher.h"
#include "mirall/owncloudinfo.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/csyncthread.h"
namespace Mirall
{
namespace
{
int shibboleth_redirect_callback(CSYNC* csync_ctx,
const char* uri)
{
if (!csync_ctx || !uri) {
return 1;
}
const QString qurl(QString::fromLatin1(uri));
QRegExp shibbolethyWords ("SAML|wayf");
shibbolethyWords.setCaseSensitivity (Qt::CaseInsensitive);
if (!qurl.contains(shibbolethyWords)) {
return 1;
}
QMutex mutex;
QMutexLocker locker(&mutex);
MirallConfigFile cfg;
ShibbolethCredentials* creds = dynamic_cast< ShibbolethCredentials* > (cfg.getCredentials());
if (!creds) {
qDebug() << "Not a Shibboleth creds instance!";
return 1;
}
ShibbolethRefresher refresher(creds, csync_ctx);
// blocks
refresher.refresh();
return 0;
}
} // ns
ShibbolethCredentials::ShibbolethCredentials()
: _shibCookie(),
_ready(false),
_browser(0)
{}
ShibbolethCredentials::ShibbolethCredentials(const QNetworkCookie& cookie)
: _shibCookie(cookie),
_ready(true),
_browser(0)
{}
void ShibbolethCredentials::syncContextPreInit(CSYNC*)
{}
QByteArray ShibbolethCredentials::prepareCookieData() const
{
QString cookiesAsString;
// TODO: This should not be a part of this method, but we don't
// have any way to get "session_key" module property from
// csync. Had we have it, then we could just append shibboleth
// cookies to the "session_key" value and set it in csync module.
QList<QNetworkCookie> cookies(ownCloudInfo::instance()->getLastAuthCookies());
QMap<QString, QString> uniqueCookies;
cookies << _shibCookie;
// Stuff cookies inside csync, then we can avoid the intermediate HTTP 401 reply
// when https://github.com/owncloud/core/pull/4042 is merged.
foreach(QNetworkCookie c, cookies) {
const QString cookieName(c.name());
if (cookieName.startsWith("_shibsession_")) {
continue;
}
uniqueCookies.insert(cookieName, c.value());
}
uniqueCookies.insert(_shibCookie.name(), _shibCookie.value());
foreach(const QString& cookieName, uniqueCookies.keys()) {
cookiesAsString += cookieName;
cookiesAsString += '=';
cookiesAsString += uniqueCookies[cookieName];
cookiesAsString += "; ";
}
return cookiesAsString.toLatin1();
}
void ShibbolethCredentials::syncContextPreStart (CSYNC* ctx)
{
typedef int (*csync_owncloud_redirect_callback_t)(CSYNC* ctx, const char* uri);
csync_owncloud_redirect_callback_t cb = shibboleth_redirect_callback;
csync_set_module_property(ctx, "session_key", prepareCookieData().data());
csync_set_module_property(ctx, "redirect_callback", &cb);
}
bool ShibbolethCredentials::changed(AbstractCredentials* credentials) const
{
ShibbolethCredentials* other(dynamic_cast< ShibbolethCredentials* >(credentials));
if (!other || other->cookie() != this->cookie()) {
return true;
}
return false;
}
QString ShibbolethCredentials::authType() const
{
return QString::fromLatin1("shibboleth");
}
QNetworkCookie ShibbolethCredentials::cookie() const
{
return _shibCookie;
}
QNetworkAccessManager* ShibbolethCredentials::getQNAM() const
{
ShibbolethAccessManager* qnam(new ShibbolethAccessManager(_shibCookie));
connect(this, SIGNAL(newCookie(QNetworkCookie)),
qnam, SLOT(setCookie(QNetworkCookie)));
return qnam;
}
bool ShibbolethCredentials::ready() const
{
return _ready;
}
void ShibbolethCredentials::fetch()
{
if (_ready) {
Q_EMIT fetched();
} else {
MirallConfigFile cfg;
_browser = new ShibbolethWebView(QUrl(cfg.ownCloudUrl()));
connect(_browser, SIGNAL(shibbolethCookieReceived(QNetworkCookie)),
this, SLOT(onShibbolethCookieReceived(QNetworkCookie)));
_browser->show ();
}
}
void ShibbolethCredentials::persistForUrl(const QString& /*url*/)
{
// nothing to do here, we don't store session cookies.
}
void ShibbolethCredentials::onShibbolethCookieReceived(const QNetworkCookie& cookie)
{
_browser->hide();
disconnect(_browser, SIGNAL(shibbolethCookieReceived(QNetworkCookie)),
this, SLOT(onShibbolethCookieReceived(QNetworkCookie)));
_browser->deleteLater();
_browser = 0;
_ready = true;
_shibCookie = cookie;
Q_EMIT newCookie(_shibCookie);
Q_EMIT fetched();
}
void ShibbolethCredentials::invalidateAndFetch()
{
_ready = false;
connect (this, SIGNAL(fetched()),
this, SLOT(onFetched()));
fetch();
}
void ShibbolethCredentials::onFetched()
{
disconnect (this, SIGNAL(fetched()),
this, SLOT(onFetched()));
Q_EMIT invalidatedAndFetched(prepareCookieData());
}
} // ns Mirall

View file

@ -0,0 +1,66 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_CREDS_SHIBBOLETH_CREDENTIALS_H
#define MIRALL_CREDS_SHIBBOLETH_CREDENTIALS_H
#include <QNetworkCookie>
#include "creds/abstractcredentials.h"
namespace Mirall
{
class ShibbolethWebView;
class ShibbolethCredentials : public AbstractCredentials
{
Q_OBJECT
public:
ShibbolethCredentials();
ShibbolethCredentials(const QNetworkCookie& cookie);
void syncContextPreInit(CSYNC* ctx);
void syncContextPreStart(CSYNC* ctx);
bool changed(AbstractCredentials* credentials) const;
QString authType() const;
QNetworkAccessManager* getQNAM() const;
bool ready() const;
void fetch();
void persistForUrl(const QString& url);
QNetworkCookie cookie() const;
public Q_SLOTS:
void invalidateAndFetch();
private Q_SLOTS:
void onShibbolethCookieReceived(const QNetworkCookie& cookie);
void onFetched();
Q_SIGNALS:
void newCookie(const QNetworkCookie& cookie);
void invalidatedAndFetched(const QByteArray& cookieData);
private:
QByteArray prepareCookieData() const;
QNetworkCookie _shibCookie;
bool _ready;
ShibbolethWebView* _browser;
};
} // ns Mirall
#endif

View file

@ -18,7 +18,6 @@
#include "mirall/theme.h"
#include "mirall/folderman.h"
#include "mirall/owncloudinfo.h"
#include "mirall/credentialstore.h"
#include "mirall/folderwizard.h"
#include "mirall/folderstatusmodel.h"
#include "mirall/utility.h"
@ -426,8 +425,7 @@ void AccountSettings::slotOCInfo( const QString& url, const QString& versionStr,
qDebug() << "#-------# oC found on " << url;
/* enable the open button */
ui->connectLabel->setOpenExternalLinks(true);
ui->connectLabel->setText( tr("Connected to <a href=\"%1\">%1</a> as <i>%2</i>.")
.arg(url).arg( CredentialStore::instance()->user()) );
ui->connectLabel->setText( tr("Connected to <a href=\"%1\">%1</a>.").arg(url) );
ui->connectLabel->setToolTip( tr("Version: %1 (%2)").arg(versionStr).arg(version));
ui->_ButtonAdd->setEnabled(true);
@ -576,6 +574,12 @@ void AccountSettings::slotSetProgress(const QString& folder, const Progress::Inf
}
timer->start(5000);
break;
case Progress::Invalid:
case Progress::Download:
case Progress::Upload:
case Progress::Inactive:
case Progress::Error:
break;
}
QString fileProgressString;

View file

@ -30,7 +30,6 @@
#include "mirall/theme.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/updatedetector.h"
#include "mirall/credentialstore.h"
#include "mirall/logger.h"
#include "mirall/settingsdialog.h"
#include "mirall/itemprogressdialog.h"
@ -38,6 +37,8 @@
#include "mirall/inotify.h"
#include "mirall/connectionvalidator.h"
#include "creds/abstractcredentials.h"
#if defined(Q_OS_WIN)
#include <windows.h>
#endif
@ -160,7 +161,7 @@ Application::Application(int &argc, char **argv) :
setupSystemTray();
slotSetupProxy();
int cnt = folderMan->setupFolders();
folderMan->setupFolders();
// startup procedure.
QTimer::singleShot( 0, this, SLOT( slotCheckConnection() ));
@ -192,6 +193,35 @@ void Application::slotStartUpdateDetector()
}
void Application::slotCheckConnection()
{
if( checkConfigExists(false) ) {
MirallConfigFile cfg;
AbstractCredentials* credentials(cfg.getCredentials());
if (! credentials->ready()) {
connect( credentials, SIGNAL(fetched()),
this, SLOT(slotCredentialsFetched()));
credentials->fetch();
} else {
runValidator();
}
} else {
// the call to checkConfigExists opens the setup wizard
// if the config does not exist. Nothing to do here.
}
}
void Application::slotCredentialsFetched()
{
MirallConfigFile cfg;
AbstractCredentials* credentials(cfg.getCredentials());
disconnect(credentials, SIGNAL(fetched()),
this, SLOT(slotCredentialsFetched()));
runValidator();
}
void Application::runValidator()
{
_conValidator = new ConnectionValidator();
connect( _conValidator, SIGNAL(connectionResult(ConnectionValidator::Status)),
@ -199,7 +229,6 @@ void Application::slotCheckConnection()
_conValidator->checkConnection();
}
void Application::slotConnectionValidatorResult(ConnectionValidator::Status status)
{
qDebug() << "Connection Validator Result: " << _conValidator->statusString(status);
@ -221,6 +250,8 @@ void Application::slotConnectionValidatorResult(ConnectionValidator::Status stat
computeOverallSyncStatus();
setupContextMenu();
} else if( status == ConnectionValidator::NotConfigured ) {
// this can not happen, it should be caught in first step of startup.
} else {
// What else?
}
@ -608,21 +639,25 @@ void Application::slotTrayClicked( QSystemTrayIcon::ActivationReason reason )
// Linux, not on Mac. They want a menu entry.
#if defined Q_WS_WIN || defined Q_WS_X11
if( reason == QSystemTrayIcon::Trigger ) {
slotCheckConfig();
checkConfigExists(true); // start settings if config is existing.
}
#endif
}
void Application::slotCheckConfig()
bool Application::checkConfigExists(bool openSettings)
{
// if no config file is there, start the configuration wizard.
MirallConfigFile cfgFile;
if( cfgFile.exists() ) {
slotSettings();
if( openSettings ) {
slotSettings();
}
return true;
} else {
qDebug() << "No configured folders yet, starting setup wizard";
OwncloudSetupWizard::runWizard(this, SLOT(slotownCloudWizardDone(int)));
return false;
}
}
@ -706,7 +741,7 @@ void Application::parseOptions(const QStringList &options)
//parse options; if help or bad option exit
while (it.hasNext()) {
QString option = it.next();
if (option == QLatin1String("--help") || option == QLatin1String("-h")) {
if (option == QLatin1String("--help") || option == QLatin1String("-h")) {
setHelp();
break;
} else if (option == QLatin1String("--logwindow") ||
@ -743,7 +778,7 @@ void Application::parseOptions(const QStringList &options)
setHelp();
break;
}
}
}
}
void Application::computeOverallSyncStatus()

View file

@ -68,6 +68,7 @@ protected:
void setupContextMenu();
void setupLogBrowser();
void enterNextLogFile();
bool checkConfigExists(bool openSettings);
//folders have to be disabled while making config changes
void computeOverallSyncStatus();
@ -83,7 +84,6 @@ signals:
protected slots:
void slotFoldersChanged();
void slotCheckConfig();
void slotSettings();
void slotItemProgressDialog();
void slotParseOptions( const QString& );
@ -105,10 +105,13 @@ protected slots:
void slotProgressSyncProblem(const QString& folder, const Progress::SyncProblem &problem);
void slotDisplayIdle();
void slotHelp();
void slotShowRecentChanges();
void slotCredentialsFetched();
private:
void setHelp();
void raiseDialog( QWidget* );
void rebuildRecentMenus();
void runValidator();
Systray *_tray;
QAction *_actionOpenoC;

View file

@ -17,7 +17,6 @@
#include "mirall/owncloudinfo.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/theme.h"
#include "mirall/credentialstore.h"
namespace Mirall {
@ -28,7 +27,8 @@ ConnectionValidator::ConnectionValidator(QObject *parent) :
}
ConnectionValidator::ConnectionValidator(const QString& connection, QObject *parent)
:_connection(connection)
: QObject(parent),
_connection(connection)
{
ownCloudInfo::instance()->setCustomConfigHandle(_connection);
}
@ -93,7 +93,7 @@ void ConnectionValidator::checkConnection()
}
}
void ConnectionValidator::slotStatusFound( const QString& url, const QString& versionStr, const QString& version, const QString& edition)
void ConnectionValidator::slotStatusFound( const QString& url, const QString& versionStr, const QString& version, const QString& /*edition*/)
{
// status.php was found.
qDebug() << "** Application: ownCloud found: " << url << " with version " << versionStr << "(" << version << ")";
@ -115,7 +115,7 @@ void ConnectionValidator::slotStatusFound( const QString& url, const QString& ve
return;
}
QTimer::singleShot( 0, this, SLOT( slotFetchCredentials() ));
QTimer::singleShot( 0, this, SLOT( slotCheckAuthentication() ));
}
// status.php could not be loaded.
@ -133,50 +133,6 @@ void ConnectionValidator::slotNoStatusFound(QNetworkReply *reply)
}
void ConnectionValidator::slotFetchCredentials()
{
if( _connection.isEmpty() ) {
connect( CredentialStore::instance(), SIGNAL(fetchCredentialsFinished(bool)),
this, SLOT(slotCredentialsFetched(bool)) );
CredentialStore::instance()->fetchCredentials();
} else {
// Pull credentials from Mirall config.
slotCredentialsFetched( true );
}
}
void ConnectionValidator::slotCredentialsFetched( bool ok )
{
qDebug() << "Credentials successfully fetched: " << ok;
disconnect( CredentialStore::instance(), SIGNAL(fetchCredentialsFinished(bool)) );
if( ! ok ) {
Status stat;
_errors << tr("Error: Could not retrieve the password!");
_errors << CredentialStore::instance()->errorMessage();
stat = CredentialError;
qDebug() << "Could not fetch credentials" << _errors;
emit connectionResult( stat );
} else {
QString user, pwd;
if( _connection.isEmpty() ) {
user = CredentialStore::instance()->user();
pwd = CredentialStore::instance()->password();
} else {
// in case of reconfiguration, the _connection is set.
MirallConfigFile cfg(_connection);
user = cfg.ownCloudUser();
pwd = cfg.ownCloudPasswd();
}
ownCloudInfo::instance()->setCredentials( user, pwd );
// Credential fetched ok.
QTimer::singleShot( 0, this, SLOT( slotCheckAuthentication() ));
}
}
void ConnectionValidator::slotCheckAuthentication()
{
connect( ownCloudInfo::instance(), SIGNAL(ownCloudDirExists(QString,QNetworkReply*)),
@ -190,7 +146,6 @@ void ConnectionValidator::slotCheckAuthentication()
void ConnectionValidator::slotAuthCheck( const QString& ,QNetworkReply *reply )
{
bool ok = true;
Status stat = Connected;
if( reply->error() == QNetworkReply::AuthenticationRequiredError ||
@ -198,7 +153,6 @@ void ConnectionValidator::slotAuthCheck( const QString& ,QNetworkReply *reply )
qDebug() << "******** Password is wrong!";
_errors << "The provided credentials are wrong.";
stat = CredentialsWrong;
ok = false;
}
// disconnect from ownCloud Info signals
@ -206,7 +160,6 @@ void ConnectionValidator::slotAuthCheck( const QString& ,QNetworkReply *reply )
this,SLOT(slotAuthCheck(QString,QNetworkReply*)));
emit connectionResult( stat );
}

View file

@ -58,8 +58,6 @@ protected slots:
void slotStatusFound( const QString&, const QString&, const QString&, const QString& );
void slotNoStatusFound(QNetworkReply *);
void slotFetchCredentials();
void slotCredentialsFetched( bool );
void slotCheckAuthentication();
void slotAuthCheck( const QString& ,QNetworkReply * );

View file

@ -18,6 +18,7 @@
#include "mirall/theme.h"
#include "mirall/logger.h"
#include "mirall/owncloudinfo.h"
#include "creds/abstractcredentials.h"
#ifdef Q_OS_WIN
#include <windows.h>
@ -338,21 +339,28 @@ void CSyncThread::startSync()
csync_set_module_property(_csync_ctx, "csync_context", _csync_ctx);
csync_set_userdata(_csync_ctx, this);
if (_lastAuthCookies.length() > 0) {
// Stuff cookies inside csync, then we can avoid the intermediate HTTP 401 reply
// when https://github.com/owncloud/core/pull/4042 is merged.
QString cookiesAsString;
foreach(QNetworkCookie c, _lastAuthCookies) {
cookiesAsString += c.name();
cookiesAsString += '=';
cookiesAsString += c.value();
cookiesAsString += "; ";
}
csync_set_module_property(_csync_ctx, "session_key", cookiesAsString.toAscii().data());
}
// TODO: This should be a part of this method, but we don't have
// any way to get "session_key" module property from csync. Had we
// have it, then we could keep this code and remove it from
// AbstractCredentials implementations.
cfg.getCredentials()->syncContextPreStart(_csync_ctx);
// if (_lastAuthCookies.length() > 0) {
// // Stuff cookies inside csync, then we can avoid the intermediate HTTP 401 reply
// // when https://github.com/owncloud/core/pull/4042 is merged.
// QString cookiesAsString;
// foreach(QNetworkCookie c, _lastAuthCookies) {
// cookiesAsString += c.name();
// cookiesAsString += '=';
// cookiesAsString += c.value();
// cookiesAsString += "; ";
// }
// csync_set_module_property(_csync_ctx, "session_key", cookiesAsString.to
// }
// csync_set_auth_callback( _csync_ctx, getauth );
qDebug() << "#### Update start #################################################### >>";
if( csync_update(_csync_ctx) < 0 ) {
handleSyncError(_csync_ctx, "csync_update");
@ -361,7 +369,7 @@ void CSyncThread::startSync()
qDebug() << "<<#### Update end ###########################################################";
if( csync_reconcile(_csync_ctx) < 0 ) {
handleSyncError(_csync_ctx, "cysnc_reconcile");
handleSyncError(_csync_ctx, "csync_reconcile");
return;
}
@ -481,10 +489,4 @@ void CSyncThread::cb_progress( CSYNC_PROGRESS *progress, void *userdata )
}
void CSyncThread::setLastAuthCookies(QList<QNetworkCookie> c)
{
_lastAuthCookies = c;
}
}
} // ns Mirall

View file

@ -44,8 +44,6 @@ public:
Q_INVOKABLE void startSync();
void setLastAuthCookies(QList<QNetworkCookie> c);
signals:
void fileReceived( const QString& );
void fileRemoved( const QString& );
@ -87,9 +85,7 @@ private:
bool _hasFiles; // true if there is at least one file that is not ignored or removed
QList<QNetworkCookie> _lastAuthCookies;
friend class CSyncRunScopeHelper;
friend struct CSyncRunScopeHelper;
};
}

View file

@ -25,7 +25,7 @@ class FileUtils
public:
enum SubFolderListOption {
SubFolderNoOptions = 0x0,
SubFolderRecursive = 0x1,
SubFolderRecursive = 0x1
};
Q_DECLARE_FLAGS(SubFolderListOptions, SubFolderListOption)

View file

@ -21,8 +21,7 @@
#include "mirall/syncresult.h"
#include "mirall/logger.h"
#include "mirall/owncloudinfo.h"
#include "mirall/credentialstore.h"
#include "mirall/utility.h"
#include "creds/abstractcredentials.h"
#include <QDebug>
#include <QTimer>
@ -34,17 +33,18 @@
namespace Mirall {
void csyncLogCatcher(CSYNC *ctx,
int verbosity,
const char *function,
void csyncLogCatcher(CSYNC */*ctx*/,
int /*verbosity*/,
const char */*function*/,
const char *buffer,
void *userdata)
void */*userdata*/)
{
Logger::instance()->csyncLog( QString::fromUtf8(buffer) );
}
Folder::Folder(const QString &alias, const QString &path, const QString& secondPath, QObject *parent)
: QObject(parent)
, _pollTimer(new QTimer(this))
, _path(path)
, _secondPath(secondPath)
, _alias(alias)
@ -95,7 +95,7 @@ bool Folder::init()
csync_enable_conflictcopys(_csync_ctx);
setIgnoredFiles();
csync_set_auth_callback( _csync_ctx, getauth );
cfgFile.getCredentials()->syncContextPreInit(_csync_ctx);
if( csync_init( _csync_ctx ) < 0 ) {
qDebug() << "Could not initialize csync!" << csync_get_error(_csync_ctx) << csync_get_error_string(_csync_ctx);
@ -214,7 +214,7 @@ SyncResult Folder::syncResult() const
return _syncResult;
}
void Folder::evaluateSync(const QStringList &pathList)
void Folder::evaluateSync(const QStringList &/*pathList*/)
{
if( !_enabled ) {
qDebug() << "*" << alias() << "sync skipped, disabled!";
@ -402,70 +402,6 @@ const char* Folder::proxyTypeToCStr(QNetworkProxy::ProxyType type)
}
}
int Folder::getauth(const char *prompt,
char *buf,
size_t len,
int echo,
int verify,
void *userdata
)
{
int re = 0;
QMutex mutex;
QString qPrompt = QString::fromLatin1( prompt ).trimmed();
QString user = CredentialStore::instance()->user();
QString pwd = CredentialStore::instance()->password();
if( qPrompt == QLatin1String("Enter your username:") ) {
// qDebug() << "OOO Username requested!";
QMutexLocker locker( &mutex );
qstrncpy( buf, user.toUtf8().constData(), len );
} else if( qPrompt == QLatin1String("Enter your password:") ) {
QMutexLocker locker( &mutex );
// qDebug() << "OOO Password requested!";
qstrncpy( buf, pwd.toUtf8().constData(), len );
} else {
if( qPrompt.startsWith( QLatin1String("There are problems with the SSL certificate:"))) {
// SSL is requested. If the program came here, the SSL check was done by mirall
// It needs to be checked if the chain is still equal to the one which
// was verified by the user.
QRegExp regexp("fingerprint: ([\\w\\d:]+)");
bool certOk = false;
int pos = 0;
// This is the set of certificates which QNAM accepted, so we should accept
// them as well
QList<QSslCertificate> certs = ownCloudInfo::instance()->certificateChain();
while (!certOk && (pos = regexp.indexIn(qPrompt, 1+pos)) != -1) {
QString neon_fingerprint = regexp.cap(1);
foreach( const QSslCertificate& c, certs ) {
QString verified_shasum = Utility::formatFingerprint(c.digest(QCryptographicHash::Sha1).toHex());
qDebug() << "SSL Fingerprint from neon: " << neon_fingerprint << " compared to verified: " << verified_shasum;
if( verified_shasum == neon_fingerprint ) {
certOk = true;
break;
}
}
}
// certOk = false; DEBUG setting, keep disabled!
if( !certOk ) { // Problem!
qstrcpy( buf, "no" );
re = -1;
} else {
qstrcpy( buf, "yes" ); // Certificate is fine!
}
} else {
qDebug() << "Unknown prompt: <" << prompt << ">";
re = -1;
}
}
return re;
}
void Folder::startSync(const QStringList &pathList)
{
Q_UNUSED(pathList)
@ -503,7 +439,6 @@ void Folder::startSync(const QStringList &pathList)
_thread->setPriority(QThread::LowPriority);
setIgnoredFiles();
_csync = new CSyncThread( _csync_ctx );
_csync->setLastAuthCookies(ownCloudInfo::instance()->getLastAuthCookies());
_csync->moveToThread(_thread);

View file

@ -185,13 +185,6 @@ protected:
void setIgnoredFiles();
void setProxy();
static int getauth(const char *prompt,
char *buf,
size_t len,
int echo,
int verify,
void *userdata
);
const char* proxyTypeToCStr(QNetworkProxy::ProxyType type);
/**

View file

@ -26,9 +26,9 @@ FolderStatusModel::FolderStatusModel()
}
Qt::ItemFlags FolderStatusModel::flags ( const QModelIndex& )
Qt::ItemFlags FolderStatusModel::flags ( const QModelIndex& ) const
{
return Qt::ItemIsSelectable;
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}
QVariant FolderStatusModel::data(const QModelIndex &index, int role) const
@ -296,7 +296,7 @@ void FolderStatusDelegate::paint(QPainter *painter, const QStyleOptionViewItem &
painter->restore();
}
bool FolderStatusDelegate::editorEvent ( QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index )
bool FolderStatusDelegate::editorEvent ( QEvent * /*event*/, QAbstractItemModel * /*model*/, const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/ )
{
return false;
}

View file

@ -24,7 +24,7 @@ class FolderStatusModel : public QStandardItemModel
{
public:
FolderStatusModel();
virtual Qt::ItemFlags flags( const QModelIndex& );
virtual Qt::ItemFlags flags( const QModelIndex& ) const;
QVariant data(const QModelIndex &index, int role) const;
};

View file

@ -78,7 +78,7 @@ void FolderWatcherPrivate::slotAddFolderRecursive(const QString &path)
qDebug() << " `-> and" << subdirs << "subdirectories";
}
void FolderWatcherPrivate::slotINotifyEvent(int mask, int cookie, const QString &path)
void FolderWatcherPrivate::slotINotifyEvent(int mask, int /*cookie*/, const QString &path)
{
int lastMask = _lastMask;
QString lastPath = _lastPath;

View file

@ -47,7 +47,7 @@ INotify::INotify(QObject *parent, int mask)
_buffer = (char *) malloc(_buffer_size);
}
void INotify::slotActivated(int fd)
void INotify::slotActivated(int /*fd*/)
{
int len;
struct inotify_event* event;
@ -82,7 +82,7 @@ void INotify::slotActivated(int fd)
// reset counter
i = 0;
// while there are enough events in the buffer
while(i + sizeof(struct inotify_event) < len) {
while(i + sizeof(struct inotify_event) < static_cast<unsigned int>(len)) {
// cast an inotify_event
event = (struct inotify_event*)&_buffer[i];
// with the help of watch descriptor, retrieve, corresponding INotify

View file

@ -57,8 +57,8 @@ LogWidget::LogWidget(QWidget *parent)
LogBrowser::LogBrowser(QWidget *parent) :
QDialog(parent),
_logWidget( new LogWidget(parent) ),
_logstream(0),
_doFileFlush(false)
_doFileFlush(false),
_logstream(0)
{
setObjectName("LogBrowser"); // for save/restoreGeometry()
setWindowTitle(tr("Log Output"));

View file

@ -0,0 +1,34 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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 <QNetworkRequest>
#include "mirall/mirallaccessmanager.h"
#include "mirall/utility.h"
namespace Mirall
{
MirallAccessManager::MirallAccessManager(QObject* parent)
: QNetworkAccessManager (parent)
{}
QNetworkReply* MirallAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData)
{
QNetworkRequest newRequest(request);
newRequest.setRawHeader( QByteArray("User-Agent"), Utility::userAgentString());
return QNetworkAccessManager::createRequest (op, newRequest, outgoingData);
}
} // ns Mirall

View file

@ -0,0 +1,35 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_ACCESS_MANAGER_H
#define MIRALL_ACCESS_MANAGER_H
#include <QNetworkAccessManager>
namespace Mirall
{
class MirallAccessManager : public QNetworkAccessManager
{
Q_OBJECT
public:
MirallAccessManager(QObject* parent = 0);
protected:
QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData = 0);
};
} // ns Mirall
#endif

View file

@ -18,8 +18,8 @@
#include "mirall/owncloudinfo.h"
#include "mirall/owncloudtheme.h"
#include "mirall/theme.h"
#include "mirall/credentialstore.h"
#include "creds/abstractcredentials.h"
#include "creds/credentialsfactory.h"
#include <QtCore>
#include <QtGui>
@ -29,8 +29,7 @@
namespace Mirall {
static const char urlC[] = "url";
static const char userC[] = "user";
static const char passwdC[] = "passwd";
static const char authTypeC[] = "authType";
static const char caCertsKeyC[] = "CaCertificates";
static const char remotePollIntervalC[] = "remotePollInterval";
@ -57,11 +56,29 @@ static const char maxLogLinesC[] = "Logging/maxLogLines";
QString MirallConfigFile::_oCVersion;
QString MirallConfigFile::_confDir = QString::null;
bool MirallConfigFile::_askedUser = false;
QMap< QString, MirallConfigFile::SharedCreds > MirallConfigFile::credentialsPerConfig;
MirallConfigFile::MirallConfigFile( const QString& appendix )
:_customHandle(appendix)
{
QSettings::setDefaultFormat(QSettings::IniFormat);
if (! credentialsPerConfig.contains(_customHandle)) {
QString con( _customHandle );
if( _customHandle.isEmpty() ) con = defaultConnection();
const QString config = configFile();
qDebug() << "Loading config: " << config;
QSettings settings(config, QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup( con );
QString type = settings.value( QLatin1String(authTypeC) ).toString();
qDebug() << "Getting credentials of type " << type << " for " << _customHandle;
credentialsPerConfig.insert(_customHandle, SharedCreds(CredentialsFactory::create (type)));
}
}
void MirallConfigFile::setConfDir(const QString &value)
@ -77,30 +94,30 @@ void MirallConfigFile::setConfDir(const QString &value)
bool MirallConfigFile::optionalDesktopNotifications() const
{
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
return settings.value(QLatin1String(optionalDesktopNoficationsC), true).toBool();
}
void MirallConfigFile::setOptionalDesktopNotifications(bool show)
{
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.setValue(QLatin1String(optionalDesktopNoficationsC), show);
settings.sync();
}
QString MirallConfigFile::seenVersion() const
{
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
return settings.value(QLatin1String(seenVersionC)).toString();
}
void MirallConfigFile::setSeenVersion(const QString &version)
{
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.setValue(QLatin1String(seenVersionC), version);
settings.sync();
}
@ -108,8 +125,8 @@ void MirallConfigFile::setSeenVersion(const QString &version)
void MirallConfigFile::saveGeometry(QWidget *w)
{
Q_ASSERT(!w->objectName().isNull());
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup(w->objectName());
settings.setValue(QLatin1String(geometryC), w->saveGeometry());
settings.sync();
@ -122,9 +139,10 @@ void MirallConfigFile::restoreGeometry(QWidget *w)
QString MirallConfigFile::configPath() const
{
QString dir = _confDir;
if( _confDir.isEmpty() )
if( _confDir.isEmpty() ) {
_confDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
}
QString dir = _confDir;
if( !dir.endsWith(QLatin1Char('/')) ) dir.append(QLatin1Char('/'));
return dir;
@ -176,13 +194,13 @@ QString MirallConfigFile::configFile() const
if( qApp->applicationName().isEmpty() ) {
qApp->setApplicationName( Theme::instance()->appNameGUI() );
}
QString dir = configPath() + Theme::instance()->configFileName();
QString file = configPath() + Theme::instance()->configFileName();
if( !_customHandle.isEmpty() ) {
dir.append( QLatin1Char('_'));
dir.append( _customHandle );
qDebug() << " OO Custom config file in use: " << dir;
file.append( QLatin1Char('_'));
file.append( _customHandle );
qDebug() << __PRETTY_FUNCTION__ << " OO Custom config file in use: " << file;
}
return dir;
return file;
}
bool MirallConfigFile::exists()
@ -201,8 +219,8 @@ bool MirallConfigFile::connectionExists( const QString& conn )
QString con = conn;
if( conn.isEmpty() ) con = defaultConnection();
QSettings settings( configFile(), QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup(conn);
return settings.contains( QLatin1String(urlC) );
@ -211,87 +229,80 @@ bool MirallConfigFile::connectionExists( const QString& conn )
void MirallConfigFile::writeOwncloudConfig( const QString& connection,
const QString& url,
const QString& user,
const QString& passwd )
AbstractCredentials* credentials)
{
const QString file = configFile();
qDebug() << "*** writing mirall config to " << file;
QSettings settings( file, QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup( connection );
settings.setValue( QLatin1String(urlC), url );
settings.setValue( QLatin1String(userC), user );
#ifdef WITH_QTKEYCHAIN
// Password is stored to QtKeyChain now by default in CredentialStore
// The CredentialStore calls clearPasswordFromConfig after the creds
// were successfully wiritten to delete the passwd entry from config.
qDebug() << "Going to delete the password from settings file.";
#endif
writePassword( passwd );
settings.setValue(QLatin1String(authTypeC), credentials->authType());
credentialsPerConfig.insert(_customHandle, SharedCreds(credentials));
settings.sync();
// check the perms, only read-write for the owner.
QFile::setPermissions( file, QFile::ReadOwner|QFile::WriteOwner );
// Store credentials temporar until the config is finalized.
ownCloudInfo::instance()->setCredentials( user, passwd, _customHandle );
//ownCloudInfo::instance()->setCredentials( user, passwd, _customHandle );
}
// This method is called after the password was successfully stored into the
// QKeyChain in CredentialStore.
void MirallConfigFile::clearPasswordFromConfig( const QString& connection )
void MirallConfigFile::storeData(const QString& group, const QString& key, const QVariant& value)
{
const QString file = configFile();
QString con( defaultConnection() );
if( !connection.isEmpty() )
con = connection;
const QString con(group.isEmpty() ? defaultConnection() : group);
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( file, QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
settings.remove(QLatin1String(passwdC));
// old key name
settings.remove(QLatin1String("password"));
settings.beginGroup(con);
settings.setValue(key, value);
settings.sync();
}
bool MirallConfigFile::writePassword( const QString& passwd, const QString& connection )
QVariant MirallConfigFile::retrieveData(const QString& group, const QString& key) const
{
const QString file = configFile();
QString pwd( passwd );
QString con( defaultConnection() );
if( !connection.isEmpty() )
con = connection;
const QString con(group.isEmpty() ? defaultConnection() : group);
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( file, QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
settings.beginGroup(con);
return settings.value(key);
}
// store password into settings file.
settings.beginGroup( con );
QByteArray pwdba = pwd.toUtf8();
settings.setValue( QLatin1String(passwdC), QVariant(pwdba.toBase64()) );
settings.sync();
void MirallConfigFile::removeData(const QString& group, const QString& key)
{
const QString con(group.isEmpty() ? defaultConnection() : group);
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
return true;
settings.beginGroup(con);
settings.remove(key);
}
bool MirallConfigFile::dataExists(const QString& group, const QString& key) const
{
const QString con(group.isEmpty() ? defaultConnection() : group);
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup(con);
return settings.contains(key);
}
QByteArray MirallConfigFile::caCerts( )
{
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
return settings.value( QLatin1String(caCertsKeyC) ).toByteArray();
}
void MirallConfigFile::setCaCerts( const QByteArray & certs )
{
const QString file = configFile();
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QSettings settings( file, QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
settings.setValue( QLatin1String(caCertsKeyC), certs );
settings.sync();
@ -306,6 +317,7 @@ void MirallConfigFile::removeConnection( const QString& connection )
qDebug() << " removing the config file for connection " << con;
// Currently its just removing the entire config file
// TODO: Eh? Shouldn't it try to load a file under configFile() and set it to INI?
QSettings settings;
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
@ -323,8 +335,8 @@ QString MirallConfigFile::ownCloudUrl( const QString& connection) const
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup( con );
QString url = settings.value( QLatin1String(urlC) ).toString();
@ -332,22 +344,7 @@ QString MirallConfigFile::ownCloudUrl( const QString& connection) const
if( ! url.endsWith(QLatin1Char('/'))) url.append(QLatin1String("/"));
}
return url;
}
QString MirallConfigFile::ownCloudUser( const QString& connection ) const
{
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
QString user = settings.value( QLatin1String("user") ).toString();
// qDebug() << "Returning configured owncloud user: " << user;
return user;
return url;
}
int MirallConfigFile::remotePollInterval( const QString& connection ) const
@ -355,8 +352,8 @@ int MirallConfigFile::remotePollInterval( const QString& connection ) const
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup( con );
int remoteInterval = settings.value( QLatin1String(remotePollIntervalC), DEFAULT_REMOTE_POLL_INTERVAL ).toInt();
@ -376,57 +373,13 @@ void MirallConfigFile::setRemotePollInterval(int interval, const QString &connec
qDebug() << "Remote Poll interval of " << interval << " is below fife seconds.";
return;
}
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup( con );
settings.setValue(QLatin1String(remotePollIntervalC), interval );
settings.sync();
}
bool MirallConfigFile::ownCloudPasswordExists( const QString& connection ) const
{
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
bool rc = false;
if( settings.contains(QLatin1String(passwdC)) ) {
rc = true;
}
return rc;
}
QString MirallConfigFile::ownCloudPasswd( const QString& connection ) const
{
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con );
QByteArray pwdba = settings.value(QLatin1String(passwdC)).toByteArray();
if( !pwdba.isEmpty() ) {
return QString::fromUtf8( QByteArray::fromBase64(pwdba) );
}
// check the password entry, cleartext from before
// read it and convert to base64, delete the cleartext entry.
QString p = settings.value(QLatin1String("password")).toString();
if( ! p.isEmpty() ) {
// its there, save base64-encoded and delete.
pwdba = p.toUtf8();
settings.setValue( QLatin1String(passwdC), QVariant(pwdba.toBase64()) );
settings.remove( QLatin1String("password") );
settings.sync();
}
return p;
}
QString MirallConfigFile::ownCloudVersion() const
{
return _oCVersion;
@ -444,8 +397,8 @@ bool MirallConfigFile::ownCloudSkipUpdateCheck( const QString& connection ) cons
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup( con );
bool skipIt = settings.value( QLatin1String(skipUpdateCheckC), false ).toBool();
@ -458,8 +411,8 @@ void MirallConfigFile::setOwnCloudSkipUpdateCheck( bool skip, const QString& con
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.beginGroup( con );
settings.setValue( QLatin1String(skipUpdateCheckC), QVariant(skip) );
@ -469,15 +422,15 @@ void MirallConfigFile::setOwnCloudSkipUpdateCheck( bool skip, const QString& con
int MirallConfigFile::maxLogLines() const
{
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
return settings.value( QLatin1String(maxLogLinesC), DEFAULT_MAX_LOG_LINES ).toInt();
}
void MirallConfigFile::setMaxLogLines( int lines )
{
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.setValue(QLatin1String(maxLogLinesC), lines);
settings.sync();
}
@ -505,6 +458,8 @@ void MirallConfigFile::acceptCustomConfig()
QString srcConfig = configFile(); // this considers the custom handle
credentialsPerConfig.insert(QString(), credentialsPerConfig[_customHandle]);
credentialsPerConfig.remove(_customHandle);
_customHandle.clear();
QString targetConfig = configFile();
QString targetBak = targetConfig + QLatin1String(".bak");
@ -526,17 +481,7 @@ void MirallConfigFile::acceptCustomConfig()
}
QFile::remove( targetBak );
// inform the credential store about the password change.
QString url = ownCloudUrl();
QString user = ownCloudUser();
QString pwd = ownCloudPasswd();
if( pwd.isEmpty() ) {
qDebug() << "Password is empty, skipping to write cred store.";
} else {
CredentialStore::instance()->setCredentials(url, user, pwd);
CredentialStore::instance()->saveCredentials();
}
credentialsPerConfig[QString()]->persistForUrl(ownCloudUrl());
}
void MirallConfigFile::setProxyType(int proxyType,
@ -545,8 +490,8 @@ void MirallConfigFile::setProxyType(int proxyType,
const QString& user,
const QString& pass)
{
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.setValue(QLatin1String(proxyTypeC), proxyType);
@ -564,8 +509,8 @@ void MirallConfigFile::setProxyType(int proxyType,
QVariant MirallConfigFile::getValue(const QString& param, const QString& group,
const QVariant& defaultValue) const
{
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
if (!group.isEmpty())
settings.beginGroup(group);
@ -574,8 +519,8 @@ QVariant MirallConfigFile::getValue(const QString& param, const QString& group,
void MirallConfigFile::setValue(const QString& key, const QVariant &value)
{
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.setValue(key, value);
}
@ -653,14 +598,21 @@ void MirallConfigFile::setDownloadLimit(int kbytes)
bool MirallConfigFile::monoIcons() const
{
QSettings settings( configFile(), QSettings::IniFormat );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
return settings.value(QLatin1String(monoIconsC), false).toBool();
}
void MirallConfigFile::setMonoIcons(bool useMonoIcons)
{
QSettings settings( configFile(), QSettings::IniFormat );
QSettings settings(configFile(), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
settings.setValue(QLatin1String(monoIconsC), useMonoIcons);
}
AbstractCredentials* MirallConfigFile::getCredentials() const
{
return credentialsPerConfig[_customHandle].data();
}
}

View file

@ -15,6 +15,7 @@
#ifndef MIRALLCONFIGFILE_H
#define MIRALLCONFIGFILE_H
#include <QSharedPointer>
#include <QString>
#include <QVariant>
@ -22,12 +23,10 @@ class QWidget;
namespace Mirall {
class AbstractCredentials;
class MirallConfigFile
{
/* let only CredentialStore read the password from the file. All other classes
* should work with CredentialStore to get the credentials. */
friend class CredentialStore;
friend class ConnectionValidator;
public:
MirallConfigFile( const QString& appendix = QString() );
@ -44,12 +43,12 @@ public:
void writeOwncloudConfig( const QString& connection,
const QString& url,
const QString& user,
const QString& passwd );
AbstractCredentials* credentials);
AbstractCredentials* getCredentials() const;
void removeConnection( const QString& connection = QString() );
QString ownCloudUser( const QString& connection = QString() ) const;
QString ownCloudUrl( const QString& connection = QString() ) const;
// the certs do not depend on a connection.
@ -117,11 +116,10 @@ public:
void restoreGeometry(QWidget *w);
protected:
// these classes can only be access from CredentialStore as a friend class.
bool ownCloudPasswordExists( const QString& connection = QString() ) const;
QString ownCloudPasswd( const QString& connection = QString() ) const;
void clearPasswordFromConfig( const QString& connect = QString() );
bool writePassword( const QString& passwd, const QString& connection = QString() );
void storeData(const QString& group, const QString& key, const QVariant& value);
QVariant retrieveData(const QString& group, const QString& key) const;
void removeData(const QString& group, const QString& key);
bool dataExists(const QString& group, const QString& key) const;
private:
QVariant getValue(const QString& param, const QString& group = QString::null,
@ -129,9 +127,12 @@ private:
void setValue(const QString& key, const QVariant &value);
private:
typedef QSharedPointer< AbstractCredentials > SharedCreds;
static bool _askedUser;
static QString _oCVersion;
static QString _confDir;
static QMap< QString, SharedCreds > credentialsPerConfig;
QString _customHandle;
};

View file

@ -15,8 +15,8 @@
#include "mirall/owncloudinfo.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/theme.h"
#include "mirall/utility.h"
#include "mirall/logger.h"
#include "creds/abstractcredentials.h"
#include <QtCore>
#include <QtGui>
@ -50,14 +50,14 @@ ownCloudInfo::ownCloudInfo() :
QObject(0),
_manager(0),
_authAttempts(0),
_lastQuotaTotalBytes(0),
_lastQuotaUsedBytes(0)
_lastQuotaUsedBytes(0),
_lastQuotaTotalBytes(0)
{
_connection = Theme::instance()->appName();
connect(this, SIGNAL(guiLog(QString,QString)),
Logger::instance(), SIGNAL(guiLog(QString,QString)));
setNetworkAccessManager( new QNetworkAccessManager( this ) );
// this will set credentials specific qnam
setCustomConfigHandle(QString());
}
void ownCloudInfo::setNetworkAccessManager( QNetworkAccessManager* qnam )
@ -72,13 +72,7 @@ void ownCloudInfo::setNetworkAccessManager( QNetworkAccessManager* qnam )
connect( _manager, SIGNAL( sslErrors(QNetworkReply*, QList<QSslError>)),
this, SIGNAL(sslFailed(QNetworkReply*, QList<QSslError>)) );
// The authenticationRequired signal is not handled because the creds are set
// in the request header.
connect( _manager, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
this, SLOT(slotAuthentication(QNetworkReply*,QAuthenticator*)));
_certsUntrusted = false;
}
ownCloudInfo::~ownCloudInfo()
@ -90,6 +84,8 @@ void ownCloudInfo::setCustomConfigHandle( const QString& handle )
_configHandle = handle;
_authAttempts = 0; // allow a couple of tries again.
resetSSLUntrust();
MirallConfigFile cfg(_configHandle);
setNetworkAccessManager (cfg.getCredentials()->getQNAM());
}
bool ownCloudInfo::isConfigured()
@ -311,42 +307,6 @@ void ownCloudInfo::slotGetDirectoryListingFinished()
reply->deleteLater();
}
// FIXME: remove this later, once the new connection dialog has settled.
void ownCloudInfo::slotAuthentication( QNetworkReply *reply, QAuthenticator *auth )
{
if( !(auth && reply) ) return;
QString configHandle;
// an empty config handle is ok for the default config.
if( _configHandleMap.contains(reply) ) {
configHandle = _configHandleMap[reply];
qDebug() << "Auth: Have a custom config handle: " << configHandle;
}
qDebug() << "Auth request to me and I am " << this;
_authAttempts++;
qDebug() << "Authenticating request for " << reply->url();
if( reply->url().toString().startsWith( webdavUrl( _connection ) ) ) {
QString con = configHandle;
if( con.isEmpty() ) con = DEFAULT_CONNECTION;
if( _credentials.contains(con)) {
oCICredentials creds = _credentials.value(con);
auth->setUser( creds.user );
auth->setPassword( creds.passwd );
} else {
qDebug() << "Unable to get Credentials, not set!";
reply->close();
}
} else {
qDebug() << "WRN: attempt to authenticate to different url - attempt " <<_authAttempts;
}
if( _authAttempts > 1) {
qDebug() << "Too many attempts to authenticate. Stop request.";
reply->close();
}
}
QList<QNetworkCookie> ownCloudInfo::getLastAuthCookies()
{
QUrl url = QUrl( webdavUrl(_connection));
@ -483,8 +443,8 @@ void ownCloudInfo::slotReplyFinished()
// get version out
edition = val;
} else if(key == QLatin1String("installed")) {
// Silently ignoring "installed = true" information
} else {
// Silently ignoring "installed = true" information
} else {
qDebug() << "Unknown info from ownCloud status.php: "<< key << "=" << val;
}
}
@ -560,30 +520,11 @@ void ownCloudInfo::slotError( QNetworkReply::NetworkError err)
}
}
void ownCloudInfo::setCredentials( const QString& user, const QString& passwd,
const QString& configHandle )
{
QString con( configHandle );
if( configHandle.isEmpty() )
con = DEFAULT_CONNECTION;
if( _credentials.contains(con) ) {
qDebug() << "Overwriting credentials for connection " << con;
}
oCICredentials creds;
creds.user = user;
creds.passwd = passwd;
creds.connection = con;
_credentials[con] = creds;
}
// ============================================================================
void ownCloudInfo::setupHeaders( QNetworkRequest & req, quint64 size )
{
QUrl url( req.url() );
qDebug() << "Setting up host header: " << url.host();
req.setRawHeader( QByteArray("User-Agent"), Utility::userAgentString());
if (size) {
req.setHeader( QNetworkRequest::ContentLengthHeader, size);
@ -612,4 +553,4 @@ QString ownCloudInfo::webdavUrl(const QString &connection)
return url;
}
}
} // ns Mirall

View file

@ -21,12 +21,6 @@
namespace Mirall
{
typedef struct {
QString user;
QString passwd;
QString connection;
} oCICredentials;
class ownCloudInfo : public QObject
{
Q_OBJECT
@ -101,13 +95,6 @@ public:
*/
QList<QSslCertificate> certificateChain() const;
/**
* Store credentials for a given connection. Empty connection parameter
* means "default connection".
*/
void setCredentials( const QString&, const QString&,
const QString& configHandle = QString::null );
/**
* returns the owncloud webdav url.
* It may be different from the one in the config if there was a HTTP redirection
@ -136,7 +123,6 @@ signals:
protected slots:
void slotReplyFinished( );
void slotError( QNetworkReply::NetworkError );
void slotAuthentication( QNetworkReply*, QAuthenticator *);
void slotMkdirFinished();
void slotGetQuotaFinished();
@ -166,7 +152,6 @@ private:
QList<QSslCertificate> _certificateChain;
bool _certsUntrusted;
int _authAttempts;
QMap<QString, oCICredentials> _credentials;
QMutex _certChainMutex;
int _redirectCount;
qint64 _lastQuotaUsedBytes;
@ -174,6 +159,6 @@ private:
QString _lastEtag;
};
};
} // ns Mirall
#endif // OWNCLOUDINFO_H

View file

@ -1,5 +1,6 @@
/*
* Copyright (C) by Klaas Freitag <freitag@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
@ -12,36 +13,44 @@
* for more details.
*/
#include <QAbstractButton>
#include <QtCore>
#include <QProcess>
#include <QMessageBox>
#include <QDesktopServices>
#include "wizard/owncloudwizardcommon.h"
#include "wizard/owncloudwizard.h"
#include "mirall/owncloudsetupwizard.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/owncloudinfo.h"
#include "mirall/folderman.h"
#include "mirall/credentialstore.h"
#include "mirall/utility.h"
#include "mirall/mirallaccessmanager.h"
#include "creds/abstractcredentials.h"
#include "creds/dummycredentials.h"
namespace Mirall {
OwncloudSetupWizard::OwncloudSetupWizard(QObject *parent ) :
OwncloudSetupWizard::OwncloudSetupWizard(QObject* parent) :
QObject( parent ),
_mkdirRequestReply(0),
_checkInstallationRequest(0)
_ocWizard(new OwncloudWizard),
_mkdirRequestReply(),
_checkInstallationRequest(),
_checkRemoteFolderRequest(),
_configHandle(),
_remoteFolder()
{
_ocWizard = new OwncloudWizard();
connect( _ocWizard, SIGNAL(determineAuthType(const QString&)),
this, SLOT(slotDetermineAuthType(const QString&)));
connect( _ocWizard, SIGNAL(connectToOCUrl( const QString& ) ),
this, SLOT(slotConnectToOCUrl( const QString& )));
connect( _ocWizard, SIGNAL(createLocalAndRemoteFolders(QString, QString)),
this, SLOT(slotCreateLocalAndRemoteFolders(QString, QString)));
connect( _ocWizard, SIGNAL(finished(int)),this,SLOT(slotAssistantFinished(int)));
connect( _ocWizard, SIGNAL(clearPendingRequests()),
this, SLOT(slotClearPendingRequests()));
_ocWizard->setWindowTitle( tr("%1 Connection Wizard").arg( Theme::instance()->appNameGUI() ) );
}
OwncloudSetupWizard::~OwncloudSetupWizard()
@ -49,10 +58,6 @@ OwncloudSetupWizard::~OwncloudSetupWizard()
_ocWizard->deleteLater();
}
OwncloudWizard *OwncloudSetupWizard::wizard() {
return _ocWizard;
}
void OwncloudSetupWizard::runWizard(QObject* obj, const char* amember, QWidget *parent)
{
OwncloudSetupWizard *wiz = new OwncloudSetupWizard(parent);
@ -67,14 +72,10 @@ void OwncloudSetupWizard::startWizard()
MirallConfigFile cfgFile;
// Fill the entry fields with existing values.
QString url = cfgFile.ownCloudUrl();
QString user = cfgFile.ownCloudUser();
bool configExists = !( url.isEmpty() || user.isEmpty() );
//QString user = cfgFile.ownCloudUser();
bool configExists = !( url.isEmpty()/* || user.isEmpty()*/ );
_ocWizard->setConfigExists( configExists );
if( !user.isEmpty() ) {
_ocWizard->setOCUser( user );
}
if( !url.isEmpty() ) {
_ocWizard->setOCUrl( url );
}
@ -85,13 +86,13 @@ void OwncloudSetupWizard::startWizard()
QString localFolder = Theme::instance()->defaultClientFolder();
// if its a relative path, prepend with users home dir, otherwise use as absolute path
if( !localFolder.startsWith(QLatin1Char('/')) ) {
localFolder = QDir::homePath() + QDir::separator() + Theme::instance()->defaultClientFolder();
if( !QDir(localFolder).isAbsolute() ) {
localFolder = QDir::homePath() + QDir::separator() + localFolder;
}
_ocWizard->setProperty("localFolder", localFolder);
_ocWizard->setRemoteFolder(_remoteFolder);
_ocWizard->setStartId(OwncloudWizard::Page_oCSetup);
_ocWizard->setStartId(WizardCommon::Page_ServerSetup);
_ocWizard->restart();
@ -102,91 +103,135 @@ void OwncloudSetupWizard::startWizard()
_ocWizard->raise();
}
// Method executed when the user ends the wizard, either with 'accept' or 'reject'.
// accept the custom config to be the main one if Accepted.
void OwncloudSetupWizard::slotAssistantFinished( int result )
void OwncloudSetupWizard::slotDetermineAuthType(const QString& serverUrl)
{
MirallConfigFile cfg( _configHandle );
FolderMan *folderMan = FolderMan::instance();
QString url(serverUrl);
qDebug() << "Connect to url: " << url;
_ocWizard->setField(QLatin1String("OCUrl"), url );
_ocWizard->appendToConfigurationLog(tr("Trying to connect to %1 at %2 to determine authentication type...")
.arg( Theme::instance()->appNameGUI() ).arg(url) );
// write a temporary config.
QDateTime now = QDateTime::currentDateTime();
if( result == QDialog::Rejected ) {
// the old config remains valid. Remove the temporary one.
cfg.cleanupCustomConfig();
qDebug() << "Rejected the new config, use the old!";
} else if( result == QDialog::Accepted ) {
qDebug() << "Config Changes were accepted!";
// go through all folders and remove the journals if the server changed.
MirallConfigFile prevCfg;
QUrl prevUrl( prevCfg.ownCloudUrl() );
QUrl newUrl( cfg.ownCloudUrl() );
bool urlHasChanged = (prevUrl.host() != newUrl.host() ||
prevUrl.port() != newUrl.port() ||
prevUrl.path() != newUrl.path());
// if the user changed, its also a changed url.
if( prevCfg.ownCloudUser() != cfg.ownCloudUser() ) {
urlHasChanged = true;
qDebug() << "The User has changed, same as url change.";
}
const QString localFolder = _ocWizard->localFolder();
bool acceptCfg = true;
if( urlHasChanged ) {
// first terminate sync jobs.
folderMan->terminateSyncProcess();
folderMan->unloadAllFolders();
bool startFromScratch = _ocWizard->field( "OCSyncFromScratch" ).toBool();
if( startFromScratch ) {
// first try to rename (backup) the current local dir.
bool renameOk = false;
while( !renameOk ) {
renameOk = folderMan->startFromScratch(localFolder);
if( ! renameOk ) {
QMessageBox::StandardButton but;
but = QMessageBox::question( 0, tr("Folder rename failed"),
tr("Can't remove and back up the folder because the folder or a file in it is open in another program."
"Please close the folder or file and hit retry or cancel the setup."), QMessageBox::Retry | QMessageBox::Abort, QMessageBox::Retry);
if( but == QMessageBox::Abort ) {
renameOk = true;
acceptCfg = false;
}
}
}
}
}
// save the user credentials and afterwards clear the cred store.
if( acceptCfg ) {
cfg.acceptCustomConfig();
}
// Now write the resulting folder definition if folder names are set.
if( acceptCfg && urlHasChanged ) {
folderMan->removeAllFolderDefinitions();
folderMan->addFolderDefinition(Theme::instance()->appName(),
localFolder, _remoteFolder );
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\"><b>Local sync folder %1 successfully created!</b></font>").arg(localFolder));
} else {
// url is unchanged. Only the password was changed.
if( acceptCfg ) {
qDebug() << "Only password was changed, no changes to folder configuration.";
} else {
qDebug() << "User interrupted change of configuration.";
}
}
// remove a possibly existing custom config.
if( ! _configHandle.isEmpty() ) {
// remove the old config file.
MirallConfigFile oldConfig( _configHandle );
oldConfig.cleanupCustomConfig();
}
// clear the custom config handle
_configHandle.clear();
ownCloudInfo::instance()->setCustomConfigHandle( QString::null );
_configHandle = now.toString(QLatin1String("MMddyyhhmmss"));
// notify others.
emit ownCloudWizardDone( result );
MirallConfigFile cfgFile( _configHandle );
if( url.isEmpty() ) return;
if( !( url.startsWith(QLatin1String("https://")) || url.startsWith(QLatin1String("http://"))) ) {
qDebug() << "url does not start with a valid protocol, assuming https.";
url.prepend(QLatin1String("https://"));
// FIXME: give a hint about the auto completion
_ocWizard->setOCUrl(url);
}
cfgFile.writeOwncloudConfig( Theme::instance()->appName(),
url,
new DummyCredentials);
ownCloudInfo* info(ownCloudInfo::instance());
// If there is already a config, take its proxy config.
if( info->isConfigured() ) {
MirallConfigFile prevCfg;
cfgFile.setProxyType( prevCfg.proxyType(), prevCfg.proxyHostName(), prevCfg.proxyPort(),
prevCfg.proxyNeedsAuth(), prevCfg.proxyUser(), prevCfg.proxyPassword() );
}
info->setCustomConfigHandle( _configHandle );
if( info->isConfigured() ) {
// reset the SSL Untrust flag to let the SSL dialog appear again.
info->resetSSLUntrust();
connect(info, SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
SLOT(slotOwnCloudFoundAuth(QString,QString,QString,QString)));
connect(info, SIGNAL(noOwncloudFound(QNetworkReply*)),
SLOT(slotNoOwnCloudFoundAuth(QNetworkReply*)));
_checkInstallationRequest = info->checkInstallation();
} else {
qDebug() << " ownCloud seems not to be configured, can not start test connect.";
}
}
void OwncloudSetupWizard::slotOwnCloudFoundAuth( const QString& url, const QString& infoString, const QString& version, const QString& )
{
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
this, SLOT(slotOwnCloudFoundAuth(QString,QString,QString,QString)));
disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotNoOwnCloudFoundAuth(QNetworkReply*)));
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\">Successfully connected to %1: %2 version %3 (%4)</font><br/><br/>")
.arg( url ).arg(Theme::instance()->appNameGUI()).arg(infoString).arg(version));
MirallAccessManager* nm = new MirallAccessManager(this);
// TODO: We should get this path from owncloud info.
QNetworkReply* reply = nm->get (QNetworkRequest (url + "/remote.php/webdav/"));
connect (reply, SIGNAL(finished()),
this, SLOT(slotAuthCheckReplyFinished()));
nm->setProperty ("mirallRedirs", QVariant (0));
}
void OwncloudSetupWizard::slotAuthCheckReplyFinished()
{
QNetworkReply* reply = qobject_cast< QNetworkReply* > (sender ());
QUrl redirection = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
QNetworkAccessManager* nm = reply->manager ();
const int redirCount = nm->property ("mirallRedirs").toInt();
if (redirCount > 10) {
redirection.clear ();
}
disconnect (reply, SIGNAL(finished()),
this, SLOT(slotAuthCheckReplyFinished()));
if ((reply->error () == QNetworkReply::AuthenticationRequiredError) || redirection.isEmpty()) {
reply->deleteLater();
nm->deleteLater();
_ocWizard->setAuthType (WizardCommon::HttpCreds);
} else if (redirection.toString().endsWith ("/remote.php/webdav/")) {
QNetworkReply* newReply = nm->get (QNetworkRequest(redirection));
connect (newReply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotAuthCheckReplyError(QNetworkReply::NetworkError)));
connect (newReply, SIGNAL(finished()),
this, SLOT(slotAuthCheckReplyFinished(QNetworkReply::NetworkError)));
reply->deleteLater();
nm->setProperty ("mirallRedirs", QVariant(redirCount + 1));
} else {
QRegExp shibbolethyWords ("SAML|wayf");
shibbolethyWords.setCaseSensitivity (Qt::CaseInsensitive);
if (redirection.toString ().contains (shibbolethyWords)) {
_ocWizard->setAuthType(WizardCommon::Shibboleth);
} else {
// TODO: Send an error.
// eh?
_ocWizard->setAuthType (WizardCommon::HttpCreds);
}
reply->deleteLater();
nm->deleteLater();
}
}
void OwncloudSetupWizard::slotNoOwnCloudFoundAuth( QNetworkReply *err )
{
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
this, SLOT(slotOwnCloudFound(QString,QString,QString,QString)));
disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotNoOwnCloudFound(QNetworkReply*)));
_ocWizard->displayError(tr("Failed to connect to %1:<br/>%2").
arg(Theme::instance()->appNameGUI()).arg(err->errorString()));
// remove the config file again
MirallConfigFile cfgFile( _configHandle );
cfgFile.cleanupCustomConfig();
}
void OwncloudSetupWizard::slotConnectToOCUrl( const QString& url )
@ -198,23 +243,6 @@ void OwncloudSetupWizard::slotConnectToOCUrl( const QString& url )
testOwnCloudConnect();
}
void OwncloudSetupWizard::slotClearPendingRequests()
{
qDebug() << "Pending request: " << _mkdirRequestReply;
if( _mkdirRequestReply && _mkdirRequestReply->isRunning() ) {
qDebug() << "ABORTing pending mkdir request.";
_mkdirRequestReply->abort();
}
if( _checkInstallationRequest && _checkInstallationRequest->isRunning() ) {
qDebug() << "ABORTing pending check installation request.";
_checkInstallationRequest->abort();
}
if( _checkRemoteFolderRequest && _checkRemoteFolderRequest->isRunning() ) {
qDebug() << "ABORTing pending remote folder check request.";
_checkRemoteFolderRequest->abort();
}
}
void OwncloudSetupWizard::testOwnCloudConnect()
{
// write a temporary config.
@ -240,73 +268,50 @@ void OwncloudSetupWizard::testOwnCloudConnect()
}
cfgFile.writeOwncloudConfig( Theme::instance()->appName(),
url,
_ocWizard->field(QLatin1String("OCUser")).toString(),
_ocWizard->field(QLatin1String("OCPasswd")).toString() );
_ocWizard->getCredentials());
ownCloudInfo* info(ownCloudInfo::instance());
info->setCustomConfigHandle( _configHandle );
// If there is already a config, take its proxy config.
if( ownCloudInfo::instance()->isConfigured() ) {
if( info->isConfigured() ) {
MirallConfigFile prevCfg;
cfgFile.setProxyType( prevCfg.proxyType(), prevCfg.proxyHostName(), prevCfg.proxyPort(),
prevCfg.proxyNeedsAuth(), prevCfg.proxyUser(), prevCfg.proxyPassword() );
}
// now start ownCloudInfo to check the connection.
ownCloudInfo* info = ownCloudInfo::instance();
info->setCustomConfigHandle( _configHandle );
if( info->isConfigured() ) {
// reset the SSL Untrust flag to let the SSL dialog appear again.
info->resetSSLUntrust();
connect(info, SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
SLOT(slotOwnCloudFound(QString,QString,QString,QString)));
connect(info, SIGNAL(noOwncloudFound(QNetworkReply*)),
SLOT(slotNoOwnCloudFound(QNetworkReply*)));
_checkInstallationRequest = info->checkInstallation();
} else {
qDebug() << " ownCloud seems not to be configured, can not start test connect.";
connect( info,SIGNAL(ownCloudDirExists(QString,QNetworkReply*)),
this,SLOT(slotConnectionCheck(QString,QNetworkReply*)));
qDebug() << "# checking for authentication settings.";
_checkRemoteFolderRequest = info->getWebDAVPath(_remoteFolder ); // this call needs to be authenticated.
// continue in slotConnectionCheck
}
void OwncloudSetupWizard::slotConnectionCheck(const QString&, QNetworkReply* reply)
{
// disconnect from ownCloud Info signals
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudDirExists(QString,QNetworkReply*)),
this, SLOT(slotConnectionCheck(QString,QNetworkReply*)));
switch (reply->error()) {
case QNetworkReply::NoError:
case QNetworkReply::ContentNotFoundError:
_ocWizard->successfulStep();
break;
default:
_ocWizard->displayError(tr("Error: Wrong credentials."));
break;
}
}
void OwncloudSetupWizard::slotOwnCloudFound( const QString& url, const QString& infoString, const QString& version, const QString& )
void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFolder, const QString& remoteFolder)
{
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
this, SLOT(slotOwnCloudFound(QString,QString,QString,QString)));
disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotNoOwnCloudFound(QNetworkReply*)));
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\">Successfully connected to %1: %2 version %3 (%4)</font><br/><br/>")
.arg( url ).arg(Theme::instance()->appNameGUI()).arg(infoString).arg(version));
// enable the finish button.
_ocWizard->button( QWizard::FinishButton )->setEnabled( true );
// start the local folder creation
setupLocalSyncFolder();
}
void OwncloudSetupWizard::slotNoOwnCloudFound( QNetworkReply *err )
{
disconnect(ownCloudInfo::instance(), SIGNAL(ownCloudInfoFound(QString,QString,QString,QString)),
this, SLOT(slotOwnCloudFound(QString,QString,QString,QString)));
disconnect(ownCloudInfo::instance(), SIGNAL(noOwncloudFound(QNetworkReply*)),
this, SLOT(slotNoOwnCloudFound(QNetworkReply*)));
_ocWizard->displayError(tr("Failed to connect to %1:<br/>%2").
arg(Theme::instance()->appNameGUI()).arg(err->errorString()));
// remove the config file again
MirallConfigFile cfgFile( _configHandle );
cfgFile.cleanupCustomConfig();
finalizeSetup( false );
}
void OwncloudSetupWizard::setupLocalSyncFolder()
{
const QString localFolder = _ocWizard->property("localFolder").toString();
qDebug() << "Setup local sync folder for new oC connection " << localFolder;
QDir fi( localFolder );
const QDir fi( localFolder );
// FIXME: Show problems with local folder properly.
bool localFolderOk = true;
if( fi.exists() ) {
// there is an existing local folder. If its non empty, it can only be synced if the
// ownCloud is newly created.
@ -327,18 +332,19 @@ void OwncloudSetupWizard::setupLocalSyncFolder()
}
if( localFolderOk ) {
checkRemoteFolder();
checkRemoteFolder(remoteFolder);
}
}
void OwncloudSetupWizard::checkRemoteFolder()
void OwncloudSetupWizard::checkRemoteFolder(const QString& remoteFolder)
{
connect( ownCloudInfo::instance(),SIGNAL(ownCloudDirExists(QString,QNetworkReply*)),
ownCloudInfo* info(ownCloudInfo::instance());
connect( info,SIGNAL(ownCloudDirExists(QString,QNetworkReply*)),
this,SLOT(slotAuthCheckReply(QString,QNetworkReply*)));
qDebug() << "# checking for authentication settings.";
ownCloudInfo::instance()->setCustomConfigHandle(_configHandle);
_checkRemoteFolderRequest = ownCloudInfo::instance()->getWebDAVPath(_remoteFolder ); // this call needs to be authenticated.
qDebug() << "# checking for existence of remote folder.";
info->setCustomConfigHandle(_configHandle);
_checkRemoteFolderRequest = info->getWebDAVPath(remoteFolder); // this call needs to be authenticated.
// continue in slotAuthCheckReply
}
@ -354,22 +360,12 @@ void OwncloudSetupWizard::slotAuthCheckReply( const QString&, QNetworkReply *rep
if( errId == QNetworkReply::NoError ) {
qDebug() << "******** Remote folder found, all cool!";
} else if( errId == QNetworkReply::AuthenticationRequiredError ) { // returned if the user is wrong.
qDebug() << "******** Password is wrong!";
error = tr("The given credentials do not authenticate.");
ok = false;
} else if( errId == QNetworkReply::OperationCanceledError ) {
// the username was wrong and ownCloudInfo was closing the request after a couple of auth tries.
qDebug() << "******** Username or password is wrong!";
error = tr("Username or password is wrong!");
ok = false;
} else if( errId == QNetworkReply::ContentNotFoundError ) {
// FIXME try to create the remote folder!
if( !createRemoteFolder() ) {
if( createRemoteFolder() ) {
return; // Finish here, the mkdir request will go on.
} else {
error = tr("The remote folder could not be accessed!");
ok = false;
} else {
return; // Finish here, the mkdir request will go on.
}
} else {
error = tr("Error: %1").arg(reply->errorString());
@ -378,8 +374,6 @@ void OwncloudSetupWizard::slotAuthCheckReply( const QString&, QNetworkReply *rep
if( !ok ) {
_ocWizard->displayError(error);
} else {
_ocWizard->setRemoteFolder( _remoteFolder );
}
finalizeSetup( ok );
@ -390,10 +384,11 @@ bool OwncloudSetupWizard::createRemoteFolder()
if( _remoteFolder.isEmpty() ) return false;
_ocWizard->appendToConfigurationLog( tr("creating folder on ownCloud: %1" ).arg( _remoteFolder ));
connect(ownCloudInfo::instance(), SIGNAL(webdavColCreated(QNetworkReply::NetworkError)),
ownCloudInfo* info(ownCloudInfo::instance());
connect(info, SIGNAL(webdavColCreated(QNetworkReply::NetworkError)),
this, SLOT(slotCreateRemoteFolderFinished(QNetworkReply::NetworkError)));
_mkdirRequestReply = ownCloudInfo::instance()->mkdirRequest( _remoteFolder );
_mkdirRequestReply = info->mkdirRequest( _remoteFolder );
return (_mkdirRequestReply != NULL);
}
@ -448,13 +443,119 @@ void OwncloudSetupWizard::finalizeSetup( bool success )
+ tr("Successfully connected to %1!")
.arg(Theme::instance()->appNameGUI())
+ QLatin1String("</b></font></p>"));
_ocWizard->successfulStep();
} else {
_ocWizard->appendToConfigurationLog(QLatin1String("<p><font color=\"red\">")
+ tr("Connection to %1 could not be established. Please check again.")
.arg(Theme::instance()->appNameGUI())
+ QLatin1String("</font></p>"));
}
_ocWizard->successfullyConnected(success);
}
// Method executed when the user ends the wizard, either with 'accept' or 'reject'.
// accept the custom config to be the main one if Accepted.
void OwncloudSetupWizard::slotAssistantFinished( int result )
{
MirallConfigFile cfg( _configHandle );
FolderMan *folderMan = FolderMan::instance();
if( result == QDialog::Rejected ) {
// the old config remains valid. Remove the temporary one.
cfg.cleanupCustomConfig();
qDebug() << "Rejected the new config, use the old!";
} else if( result == QDialog::Accepted ) {
AbstractCredentials* credentials(_ocWizard->getCredentials());
qDebug() << "Config Changes were accepted!";
// go through all folders and remove the journals if the server changed.
MirallConfigFile prevCfg;
QUrl prevUrl( prevCfg.ownCloudUrl() );
QUrl newUrl( cfg.ownCloudUrl() );
AbstractCredentials* oldCredentials(prevCfg.getCredentials());
bool urlHasChanged = (prevUrl.host() != newUrl.host() ||
prevUrl.port() != newUrl.port() ||
prevUrl.path() != newUrl.path());
// if the user changed, its also a changed url.
if(credentials->changed(oldCredentials)) {
urlHasChanged = true;
qDebug() << "The User has changed, same as url change.";
}
const QString localFolder = _ocWizard->localFolder();
bool acceptCfg = true;
if( urlHasChanged ) {
// first terminate sync jobs.
folderMan->terminateSyncProcess();
folderMan->unloadAllFolders();
bool startFromScratch = _ocWizard->field( "OCSyncFromScratch" ).toBool();
if( startFromScratch ) {
// first try to rename (backup) the current local dir.
bool renameOk = false;
while( !renameOk ) {
renameOk = folderMan->startFromScratch(localFolder);
if( ! renameOk ) {
QMessageBox::StandardButton but;
but = QMessageBox::question( 0, tr("Folder rename failed"),
tr("Can't remove and back up the folder because the folder or a file in it is open in another program."
"Please close the folder or file and hit retry or cancel the setup."), QMessageBox::Retry | QMessageBox::Abort, QMessageBox::Retry);
if( but == QMessageBox::Abort ) {
renameOk = true;
acceptCfg = false;
}
}
}
}
}
// save the user credentials and afterwards clear the cred store.
if( acceptCfg ) {
cfg.acceptCustomConfig();
}
// Now write the resulting folder definition if folder names are set.
if( acceptCfg && urlHasChanged ) {
folderMan->removeAllFolderDefinitions();
folderMan->addFolderDefinition(Theme::instance()->appName(),
localFolder, _remoteFolder );
_ocWizard->appendToConfigurationLog(tr("<font color=\"green\"><b>Local sync folder %1 successfully created!</b></font>").arg(localFolder));
} else {
// url is unchanged. Only the password was changed.
if( acceptCfg ) {
qDebug() << "Only password was changed, no changes to folder configuration.";
} else {
qDebug() << "User interrupted change of configuration.";
}
}
}
// clear the custom config handle
_configHandle.clear();
ownCloudInfo::instance()->setCustomConfigHandle( QString::null );
// notify others.
emit ownCloudWizardDone( result );
}
void OwncloudSetupWizard::slotClearPendingRequests()
{
qDebug() << "Pending request: " << _mkdirRequestReply;
if( _mkdirRequestReply && _mkdirRequestReply->isRunning() ) {
qDebug() << "ABORTing pending mkdir request.";
_mkdirRequestReply->abort();
}
if( _checkInstallationRequest && _checkInstallationRequest->isRunning() ) {
qDebug() << "ABORTing pending check installation request.";
_checkInstallationRequest->abort();
}
if( _checkRemoteFolderRequest && _checkRemoteFolderRequest->isRunning() ) {
qDebug() << "ABORTing pending remote folder check request.";
_checkRemoteFolderRequest->abort();
}
}
} // ns Mirall

View file

@ -21,81 +21,54 @@
#include <QNetworkReply>
#include <QPointer>
#include "mirall/owncloudwizard.h"
#include "mirall/theme.h"
namespace Mirall {
class SiteCopyFolder;
class SyncResult;
class ownCloudInfo;
class OwncloudWizard;
class OwncloudSetupWizard : public QObject
{
Q_OBJECT
public:
explicit OwncloudSetupWizard(QObject *parent = 0 );
~OwncloudSetupWizard();
/**
* @intro wether or not to show the intro wizard page
*/
void startWizard();
void installServer();
bool isBusy();
void writeOwncloudConfig();
/**
* returns the configured owncloud url if its already configured, otherwise an empty
* string.
*/
void setupLocalSyncFolder();
OwncloudWizard *wizard();
/** Run the wizard */
static void runWizard(QObject *obj, const char* amember, QWidget *parent = 0 );
signals:
// issued if the oC Setup process (owncloud-admin) is finished.
void ownCloudSetupFinished( bool );
// overall dialog close signal.
void ownCloudWizardDone( int );
public slots:
protected slots:
// wizard dialog signals
void slotConnectToOCUrl( const QString& );
void ownCloudWizardDone( int );
private slots:
void slotOwnCloudFound( const QString&, const QString&, const QString&, const QString& );
void slotNoOwnCloudFound( QNetworkReply* );
void slotCreateRemoteFolderFinished( QNetworkReply::NetworkError );
void slotDetermineAuthType(const QString&);
void slotOwnCloudFoundAuth(const QString&, const QString&, const QString&, const QString&);
void slotAuthCheckReplyFinished();
void slotNoOwnCloudFoundAuth(QNetworkReply*);
void slotConnectToOCUrl(const QString&);
void slotConnectionCheck(const QString&, QNetworkReply*);
void slotCreateLocalAndRemoteFolders(const QString&, const QString&);
void slotAuthCheckReply(const QString&, QNetworkReply*);
void slotCreateRemoteFolderFinished(QNetworkReply::NetworkError);
void slotAssistantFinished( int );
void slotClearPendingRequests();
void slotAuthCheckReply( const QString&, QNetworkReply * );
private:
bool createRemoteFolder();
void checkRemoteFolder();
private:
explicit OwncloudSetupWizard(QObject *parent = 0 );
~OwncloudSetupWizard();
void startWizard();
void testOwnCloudConnect();
void checkRemoteFolder(const QString& remoteFolder);
bool createRemoteFolder();
void finalizeSetup( bool );
/* Start a request to the newly installed ownCloud to check the connection */
void testOwnCloudConnect();
OwncloudWizard *_ocWizard;
OwncloudWizard* _ocWizard;
QPointer<QNetworkReply> _mkdirRequestReply;
QPointer<QNetworkReply> _checkInstallationRequest;
QPointer<QNetworkReply> _checkRemoteFolderRequest;
QString _configHandle;
QString _remoteFolder;
QString _configHandle;
QString _remoteFolder;
};
}

View file

@ -1,627 +0,0 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@kde.org>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "mirall/owncloudwizard.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/theme.h"
#include "QProgressIndicator.h"
#include <QtCore>
#include <QtGui>
#include <stdlib.h>
namespace Mirall
{
void setupCustomMedia( QVariant variant, QLabel *label )
{
if( !label ) return;
QPixmap pix = variant.value<QPixmap>();
if( !pix.isNull() ) {
label->setPixmap(pix);
label->setAlignment( Qt::AlignTop | Qt::AlignRight );
label->setVisible(true);
} else {
QString str = variant.toString();
if( !str.isEmpty() ) {
label->setText( str );
label->setTextFormat( Qt::RichText );
label->setVisible(true);
label->setOpenExternalLinks(true);
}
}
}
// ======================================================================
OwncloudSetupPage::OwncloudSetupPage()
{
_ui.setupUi(this);
Theme *theme = Theme::instance();
setTitle( tr("<font color=\"%1\" size=\"5\">Connect to %2</font>")
.arg(theme->wizardHeaderTitleColor().name()).arg( theme->appNameGUI()));
setSubTitle( tr("<font color=\"%1\">Enter user credentials</font>")
.arg(theme->wizardHeaderTitleColor().name()));
registerField( QLatin1String("OCUrl"), _ui.leUrl );
registerField( QLatin1String("OCUser"), _ui.leUsername );
registerField( QLatin1String("OCPasswd"), _ui.lePassword);
registerField( QLatin1String("OCSyncFromScratch"), _ui.cbSyncFromScratch);
_ui.errorLabel->setVisible(true);
_ui.advancedBox->setVisible(false);
_progressIndi = new QProgressIndicator;
_ui.resultLayout->addWidget( _progressIndi );
_progressIndi->setVisible(false);
_ui.resultLayout->setEnabled(false);
// Error label
QString style = QLatin1String("border: 1px solid #eed3d7; border-radius: 5px; padding: 3px;"
"background-color: #f2dede; color: #b94a48;");
_ui.errorLabel->setStyleSheet( style );
_ui.errorLabel->setWordWrap(true);
_ui.errorLabel->setVisible(false);
_checking = false;
setupCustomization();
connect(_ui.leUrl, SIGNAL(textChanged(QString)), SLOT(slotUrlChanged(QString)));
connect( _ui.leUsername, SIGNAL(textChanged(QString)), this, SLOT(slotUserChanged(QString)));
connect( _ui.lePassword, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged()));
connect( _ui.leUsername, SIGNAL(textChanged(QString)), this, SIGNAL(completeChanged()));
connect( _ui.cbAdvanced, SIGNAL(stateChanged (int)), SLOT(slotToggleAdvanced(int)));
connect( _ui.pbSelectLocalFolder, SIGNAL(clicked()), SLOT(slotSelectFolder()));
}
OwncloudSetupPage::~OwncloudSetupPage()
{
delete _progressIndi;
}
void OwncloudSetupPage::slotToggleAdvanced(int state)
{
_ui.advancedBox->setVisible( state == Qt::Checked );
slotHandleUserInput();
QSize size = wizard()->sizeHint();
// need to substract header for some reason
size -= QSize(0, 63);
wizard()->setMinimumSize(size);
wizard()->resize(size);
}
void OwncloudSetupPage::setOCUser( const QString & user )
{
_ocUser = user;
_ui.leUsername->setText(user);
}
void OwncloudSetupPage::setServerUrl( const QString& newUrl )
{
_oCUrl = newUrl;
if( _oCUrl.isEmpty() ) {
_ui.leUrl->clear();
return;
}
_ui.leUrl->setText( _oCUrl );
}
void OwncloudSetupPage::setupCustomization()
{
// set defaults for the customize labels.
_ui.topLabel->hide();
_ui.bottomLabel->hide();
Theme *theme = Theme::instance();
QVariant variant = theme->customMedia( Theme::oCSetupTop );
if( !variant.isNull() ) {
setupCustomMedia( variant, _ui.topLabel );
}
variant = theme->customMedia( Theme::oCSetupBottom );
setupCustomMedia( variant, _ui.bottomLabel );
QString fixUrl = theme->overrideServerUrl();
if( !fixUrl.isEmpty() ) {
_ui.label_2->hide();
setServerUrl( fixUrl );
_ui.leUrl->setEnabled( false );
_ui.leUrl->hide();
}
}
void OwncloudSetupPage::slotUserChanged(const QString& user )
{
slotHandleUserInput();
}
// slot hit from textChanged of the url entry field.
void OwncloudSetupPage::slotUrlChanged(const QString& ocUrl)
{
slotHandleUserInput();
#if 0
QString url = ocUrl;
bool visible = false;
if (url.startsWith(QLatin1String("https://"))) {
_ui.urlLabel->setPixmap( QPixmap(":/mirall/resources/security-high.png"));
_ui.urlLabel->setToolTip(tr("This url is secure. You can use it."));
visible = true;
}
if (url.startsWith(QLatin1String("http://"))) {
_ui.urlLabel->setPixmap( QPixmap(":/mirall/resources/security-low.png"));
_ui.urlLabel->setToolTip(tr("This url is NOT secure. You should not use it."));
visible = true;
}
#endif
}
bool OwncloudSetupPage::isComplete() const
{
if( _ui.leUrl->text().isEmpty() ) return false;
if( _checking ) return false;
return !( _ui.lePassword->text().isEmpty() || _ui.leUsername->text().isEmpty() );
}
void OwncloudSetupPage::initializePage()
{
_connected = false;
_checking = false;
_multipleFoldersExist = false;
// call to init label
slotHandleUserInput();
if( _configExists ) {
_ui.lePassword->setFocus();
} else {
_ui.leUrl->setFocus();
}
}
bool OwncloudSetupPage::urlHasChanged()
{
bool change = false;
const QChar slash('/');
QUrl currentUrl( url() );
QUrl initialUrl( _oCUrl );
QString currentPath = currentUrl.path();
QString initialPath = initialUrl.path();
// add a trailing slash.
if( ! currentPath.endsWith( slash )) currentPath += slash;
if( ! initialPath.endsWith( slash )) initialPath += slash;
if( currentUrl.host() != initialUrl.host() ||
currentUrl.port() != initialUrl.port() ||
currentPath != initialPath ) {
change = true;
}
if( !change) { // no change yet, check the user.
QString user = _ui.leUsername->text().simplified();
if( user != _ocUser ) change = true;
}
return change;
}
// Called if the user changes the user- or url field. Adjust the texts and
// evtl. warnings on the dialog.
void OwncloudSetupPage::slotHandleUserInput()
{
// if the url has not changed, return.
if( ! urlHasChanged() ) {
// disable the advanced button as nothing has changed.
_ui.cbAdvanced->setEnabled(false);
_ui.advancedBox->setEnabled(false);
} else {
// Enable advanced stuff for new connection configuration.
_ui.cbAdvanced->setEnabled(true);
_ui.advancedBox->setEnabled(true);
}
const QString locFolder = localFolder();
// check if the local folder exists. If so, and if its not empty, show a warning.
QDir dir( locFolder );
QStringList entries = dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
QString t;
if( !urlHasChanged() && _configExists ) {
// This is the password change mode: No change to the url and a config
// to an ownCloud exists.
t = tr("Change the Password for your configured account.");
} else {
// Complete new setup.
_ui.pbSelectLocalFolder->setText(QDir::toNativeSeparators(locFolder));
if( _remoteFolder.isEmpty() || _remoteFolder == QLatin1String("/") ) {
t = tr("Your entire account will be synced to the local folder '%1'.")
.arg(QDir::toNativeSeparators(locFolder));
} else {
t = tr("%1 folder '%2' is synced to local folder '%3'")
.arg(Theme::instance()->appName()).arg(_remoteFolder)
.arg(QDir::toNativeSeparators(locFolder));
}
if ( _multipleFoldersExist ) {
t += tr("<p><small><strong>Warning:</strong> You currently have multiple folders "
"configured. If you continue with the current settings, the folder configurations "
"will be discarded and a single root folder sync will be created!</small></p>");
}
if( entries.count() > 0) {
// the directory is not empty
if (!_ui.cbAdvanced->isChecked()) {
t += tr("<p><small><strong>Warning:</strong> The local directory is not empty. "
"Pick a resolution in the advanced settings!</small></p>");
}
_ui.resolutionWidget->setVisible(true);
} else {
// the dir is empty, which means that there is no problem.
_ui.resolutionWidget->setVisible(false);
}
}
_ui.syncModeLabel->setText(t);
_ui.syncModeLabel->setFixedHeight(_ui.syncModeLabel->sizeHint().height());
}
int OwncloudSetupPage::nextId() const
{
return OwncloudWizard::Page_Result;
}
QString OwncloudSetupPage::url() const
{
QString url = _ui.leUrl->text().simplified();
return url;
}
QString OwncloudSetupPage::localFolder() const
{
QString folder = wizard()->property("localFolder").toString();
return folder;
}
void OwncloudSetupPage::setConnected( bool comp )
{
_connected = comp;
_ui.resultLayout->setEnabled(true);
_progressIndi->setVisible(false);
_progressIndi->stopAnimation();
}
bool OwncloudSetupPage::validatePage()
{
bool re = false;
if( ! _connected) {
setErrorString(QString::null);
_checking = true;
_ui.resultLayout->setEnabled(true);
_progressIndi->setVisible(true);
_progressIndi->startAnimation();
emit completeChanged();
emit connectToOCUrl( url() );
return false;
} else {
// connecting is running
stopSpinner();
_checking = false;
emit completeChanged();
return true;
}
}
void OwncloudSetupPage::setErrorString( const QString& err )
{
if( err.isEmpty()) {
_ui.errorLabel->setVisible(false);
} else {
_ui.errorLabel->setVisible(true);
_ui.errorLabel->setText(err);
}
_checking = false;
emit completeChanged();
stopSpinner();
}
void OwncloudSetupPage::stopSpinner()
{
_ui.resultLayout->setEnabled(false);
_progressIndi->setVisible(false);
_progressIndi->stopAnimation();
}
OwncloudSetupPage::SyncMode OwncloudSetupPage::syncMode()
{
return BoxMode;
}
void OwncloudSetupPage::setRemoteFolder( const QString& remoteFolder )
{
if( !remoteFolder.isEmpty() ) {
_remoteFolder = remoteFolder;
}
}
void OwncloudSetupPage::setMultipleFoldersExist(bool exist)
{
_multipleFoldersExist = exist;
}
void OwncloudSetupPage::slotSelectFolder()
{
QString dir = QFileDialog::getExistingDirectory(0, tr("Local Sync Folder"), QDir::homePath());
if( !dir.isEmpty() ) {
_ui.pbSelectLocalFolder->setText(dir);
wizard()->setProperty("localFolder", dir);
slotHandleUserInput();
}
}
OwncloudSetupPage::SyncMode OwncloudWizard::syncMode()
{
return _setupPage->syncMode();
return OwncloudSetupPage::BoxMode;
}
void OwncloudWizard::setMultipleFoldersExist(bool exist)
{
_setupPage->setMultipleFoldersExist(exist);
}
void OwncloudSetupPage::setConfigExists( bool config )
{
_configExists = config;
if (config == true) {
setSubTitle( tr("<font color=\"%1\">Change your user credentials</font>")
.arg(Theme::instance()->wizardHeaderTitleColor().name()));
}
}
// ======================================================================
OwncloudWizardResultPage::OwncloudWizardResultPage()
{
_ui.setupUi(this);
// no fields to register.
Theme *theme = Theme::instance();
setTitle( tr("<font color=\"%1\" size=\"5\">Everything set up!</font>")
.arg(theme->wizardHeaderTitleColor().name()));
// required to show header in QWizard's modern style
setSubTitle( QLatin1String(" ") );
_ui.pbOpenLocal->setText("Open local folder");
_ui.pbOpenServer->setText(tr("Open %1").arg(Theme::instance()->appNameGUI()));
_ui.pbOpenLocal->setIcon(QIcon(":/mirall/resources/folder-sync.png"));
_ui.pbOpenLocal->setText(tr("Open Local Folder"));
_ui.pbOpenLocal->setIconSize(QSize(48, 48));
connect(_ui.pbOpenLocal, SIGNAL(clicked()), SLOT(slotOpenLocal()));
_ui.pbOpenLocal->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
QIcon appIcon = theme->applicationIcon();
_ui.pbOpenServer->setIcon(appIcon.pixmap(48));
_ui.pbOpenServer->setText(tr("Open %1").arg(theme->appNameGUI()));
_ui.pbOpenServer->setIconSize(QSize(48, 48));
_ui.pbOpenServer->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
connect(_ui.pbOpenServer, SIGNAL(clicked()), SLOT(slotOpenServer()));
setupCustomization();
}
OwncloudWizardResultPage::~OwncloudWizardResultPage()
{
}
void OwncloudWizardResultPage::setComplete(bool complete)
{
_complete = complete;
emit completeChanged();
}
bool OwncloudWizardResultPage::isComplete() const
{
return _complete;
}
void OwncloudWizardResultPage::initializePage()
{
const QString localFolder = wizard()->property("localFolder").toString();
QString text;
if( _remoteFolder == QLatin1String("/") || _remoteFolder.isEmpty() ) {
text = tr("Your entire account is synced to the local folder <i>%1</i>")
.arg(QDir::toNativeSeparators(localFolder));
} else {
text = tr("ownCloud folder <i>%1</i> is synced to local folder <i>%2</i>")
.arg(_remoteFolder).arg(QDir::toNativeSeparators(localFolder));
}
_ui.localFolderLabel->setText( text );
}
void OwncloudWizardResultPage::setRemoteFolder(const QString &remoteFolder)
{
_remoteFolder = remoteFolder;
}
void OwncloudWizardResultPage::setupCustomization()
{
// set defaults for the customize labels.
_ui.topLabel->setText( QString::null );
_ui.topLabel->hide();
QVariant variant = Theme::instance()->customMedia( Theme::oCSetupResultTop );
setupCustomMedia( variant, _ui.topLabel );
}
// ======================================================================
/**
* Folder wizard itself
*/
OwncloudWizard::OwncloudWizard(QWidget *parent)
: QWizard(parent),
_configExists(false)
{
_setupPage = new OwncloudSetupPage;
_resultPage = new OwncloudWizardResultPage;
setPage(Page_oCSetup, _setupPage );
setPage(Page_Result, _resultPage );
// note: start Id is set by the calling class depending on if the
// welcome text is to be shown or not.
setWizardStyle( QWizard::ModernStyle );
connect( this, SIGNAL(currentIdChanged(int)), SLOT(slotCurrentPageChanged(int)));
connect( _setupPage, SIGNAL(connectToOCUrl(QString)), SIGNAL(connectToOCUrl(QString)));
Theme *theme = Theme::instance();
setWizardStyle(QWizard::ModernStyle);
setPixmap( QWizard::BannerPixmap, theme->wizardHeaderBanner() );
setPixmap( QWizard::LogoPixmap, theme->wizardHeaderLogo() );
setOption( QWizard::NoBackButtonOnStartPage );
setOption( QWizard::NoBackButtonOnLastPage );
setOption( QWizard::NoCancelButton );
setTitleFormat(Qt::RichText);
setSubTitleFormat(Qt::RichText);
}
QString OwncloudWizard::localFolder() const
{
return(_setupPage->localFolder());
}
QString OwncloudWizard::ocUrl() const
{
QString url = field("OCUrl").toString().simplified();
return url;
}
void OwncloudWizard::enableFinishOnResultWidget(bool enable)
{
_resultPage->setComplete(enable);
}
void OwncloudWizard::setRemoteFolder( const QString& remoteFolder )
{
_setupPage->setRemoteFolder( remoteFolder );
_resultPage->setRemoteFolder( remoteFolder );
}
void OwncloudWizard::showConnectInfo( const QString& msg )
{
if( _setupPage ) {
_setupPage->setErrorString( msg );
}
}
void OwncloudWizard::successfullyConnected(bool enable)
{
_setupPage->setConnected( enable );
if( enable ) {
next();
}
}
void OwncloudWizard::slotCurrentPageChanged( int id )
{
qDebug() << "Current Wizard page changed to " << id;
if( id == Page_oCSetup ) {
setButtonText( QWizard::NextButton, tr("Connect...") );
emit clearPendingRequests();
_setupPage->initializePage();
}
if( id == Page_Result ) {
appendToConfigurationLog( QString::null );
}
}
void OwncloudWizard::displayError( const QString& msg )
{
_setupPage->setErrorString( msg );
}
void OwncloudWizard::appendToConfigurationLog( const QString& msg, LogType type )
{
_setupLog << msg;
qDebug() << "Setup-Log: " << msg;
}
void OwncloudWizard::setOCUrl( const QString& url )
{
_setupPage->setServerUrl( url );
}
void OwncloudWizard::setOCUser( const QString& user )
{
_oCUser = user;
_setupPage->setOCUser( user );
}
void OwncloudWizard::setConfigExists( bool config )
{
_configExists = config;
_setupPage->setConfigExists( config );
}
bool OwncloudWizard::configExists()
{
return _configExists;
}
void OwncloudWizardResultPage::slotOpenLocal()
{
const QString localFolder = wizard()->property("localFolder").toString();
QDesktopServices::openUrl(QUrl::fromLocalFile(localFolder));
}
void OwncloudWizardResultPage::slotOpenServer()
{
QUrl url = field("OCUrl").toUrl();
qDebug() << Q_FUNC_INFO << url;
QDesktopServices::openUrl(url);
}
} // end namespace

View file

@ -1,191 +0,0 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@kde.org>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifndef MIRALL_OWNCLOUDWIZARD_H
#define MIRALL_OWNCLOUDWIZARD_H
#include <QWizard>
#include "ui_owncloudsetuppage_ng.h"
#include "ui_owncloudwizardresultpage.h"
class QLabel;
class QVariant;
class QProgressIndicator;
namespace Mirall {
class OwncloudSetupPage;
class OwncloudWizardResultPage;
class OwncloudSetupPage: public QWizardPage
{
Q_OBJECT
public:
OwncloudSetupPage();
~OwncloudSetupPage();
enum SyncMode {
SelectiveMode,
BoxMode
};
virtual bool isComplete() const;
virtual void initializePage();
virtual int nextId() const;
void setServerUrl( const QString& );
void setOCUser( const QString& );
void setAllowPasswordStorage( bool );
bool validatePage();
QString url() const;
QString localFolder() const;
void setConnected(bool complete);
void setRemoteFolder( const QString& remoteFolder);
void setMultipleFoldersExist( bool exist );
SyncMode syncMode();
public slots:
void setErrorString( const QString& );
void setConfigExists( bool );
void stopSpinner();
protected slots:
void slotUrlChanged(const QString&);
void slotUserChanged(const QString&);
void setupCustomization();
void slotToggleAdvanced(int state);
void slotSelectFolder();
signals:
void connectToOCUrl( const QString& );
protected:
void updateFoldersInfo();
private slots:
void slotHandleUserInput();
private:
bool urlHasChanged();
Ui_OwncloudSetupPage _ui;
QString _oCUrl;
QString _ocUser;
bool _connected;
bool _checking;
bool _configExists;
bool _multipleFoldersExist;
QProgressIndicator *_progressIndi;
QButtonGroup *_selectiveSyncButtons;
QString _remoteFolder;
};
class OwncloudWizard: public QWizard
{
Q_OBJECT
public:
enum {
Page_oCSetup,
Page_Result
};
enum LogType {
LogPlain,
LogParagraph
};
OwncloudWizard(QWidget *parent = 0);
void setOCUrl( const QString& );
void setOCUser( const QString& );
void setupCustomMedia( QVariant, QLabel* );
QString ocUrl() const;
QString localFolder() const;
void enableFinishOnResultWidget(bool enable);
void displayError( const QString& );
OwncloudSetupPage::SyncMode syncMode();
void setMultipleFoldersExist( bool );
void setConfigExists( bool );
bool configExists();
public slots:
void setRemoteFolder( const QString& );
void appendToConfigurationLog( const QString& msg, LogType type = LogParagraph );
void slotCurrentPageChanged( int );
void showConnectInfo( const QString& );
void successfullyConnected(bool);
signals:
void clearPendingRequests();
void connectToOCUrl( const QString& );
private:
OwncloudSetupPage *_setupPage;
OwncloudWizardResultPage *_resultPage;
QString _configFile;
QString _oCUser;
QStringList _setupLog;
bool _configExists;
};
/**
* page to ask for the type of Owncloud to connect to
*/
/**
* page to display the install result
*/
class OwncloudWizardResultPage : public QWizardPage
{
Q_OBJECT
public:
OwncloudWizardResultPage();
~OwncloudWizardResultPage();
bool isComplete() const;
void initializePage();
void setRemoteFolder( const QString& remoteFolder);
public slots:
void setComplete(bool complete);
protected slots:
void slotOpenLocal();
void slotOpenServer();
protected:
void setupCustomization();
private:
QString _localFolder;
QString _remoteFolder;
bool _complete;
Ui_OwncloudWizardResultPage _ui;
};
} // ns Mirall
#endif

View file

@ -58,9 +58,9 @@ QString SyncResult::statusString() const
case SetupError:
re = QLatin1String("SetupError");
break;
case SyncPrepare:
re = QLatin1String("SyncPrepare");
break;
case SyncPrepare:
re = QLatin1String("SyncPrepare");
break;
case Unavailable:
re = QLatin1String("Not availabe");
break;

View file

@ -26,4 +26,4 @@ public:
void showMessage(const QString & title, const QString & message, MessageIcon icon = Information, int millisecondsTimeoutHint = 10000);
};
#endif //SYSTRAY_H
#endif //SYSTRAY_H

View file

@ -18,6 +18,7 @@
#include "mirall/mirallconfigfile.h"
#include "mirall/occinfo.h"
#include "mirall/utility.h"
#include "mirall/mirallaccessmanager.h"
#include <QtCore>
#include <QtNetwork>
@ -28,7 +29,7 @@ namespace Mirall {
UpdateDetector::UpdateDetector(QObject *parent) :
QObject(parent)
, _accessManager( new QNetworkAccessManager(this))
, _accessManager(new MirallAccessManager(this))
{
}

View file

@ -0,0 +1,32 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_WIZARD_ABSTRACT_CREDS_WIZARD_PAGE_H
#define MIRALL_WIZARD_ABSTRACT_CREDS_WIZARD_PAGE_H
#include <QWizardPage>
namespace Mirall
{
class AbstractCredentials;
class AbstractCredentialsWizardPage : public QWizardPage
{
public:
virtual AbstractCredentials* getCredentials() const = 0;
};
} // ns Mirall
#endif

View file

@ -0,0 +1,249 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <QDir>
#include <QFileDialog>
#include <QUrl>
#include "QProgressIndicator.h"
#include "wizard/owncloudwizard.h"
#include "wizard/owncloudwizardcommon.h"
#include "wizard/owncloudadvancedsetuppage.h"
#include "mirall/theme.h"
#include "mirall/mirallconfigfile.h"
#include "creds/abstractcredentials.h"
namespace Mirall
{
OwncloudAdvancedSetupPage::OwncloudAdvancedSetupPage()
: QWizardPage(),
_ui(),
_checking(false),
_created(false),
_configExists(false),
_multipleFoldersExist(false),
_progressIndi(new QProgressIndicator (this)),
_oldLocalFolder(),
_remoteFolder()
{
_ui.setupUi(this);
Theme *theme = Theme::instance();
setTitle(WizardCommon::titleTemplate().arg(tr("Connect to %1").arg(theme->appNameGUI())));
setSubTitle(WizardCommon::subTitleTemplate().arg(tr("Setup local folder options")));
registerField( QLatin1String("OCSyncFromScratch"), _ui.cbSyncFromScratch);
_ui.resultLayout->addWidget( _progressIndi );
stopSpinner();
setupCustomization();
connect( _ui.pbSelectLocalFolder, SIGNAL(clicked()), SLOT(slotSelectFolder()));
}
void OwncloudAdvancedSetupPage::setupCustomization()
{
// set defaults for the customize labels.
_ui.topLabel->hide();
_ui.bottomLabel->hide();
Theme *theme = Theme::instance();
QVariant variant = theme->customMedia( Theme::oCSetupTop );
if( !variant.isNull() ) {
WizardCommon::setupCustomMedia( variant, _ui.topLabel );
}
variant = theme->customMedia( Theme::oCSetupBottom );
WizardCommon::setupCustomMedia( variant, _ui.bottomLabel );
}
bool OwncloudAdvancedSetupPage::isComplete() const
{
return !_checking;
}
void OwncloudAdvancedSetupPage::initializePage()
{
WizardCommon::initErrorLabel(_ui.errorLabel);
_checking = false;
_multipleFoldersExist = false;
_oldLocalFolder = localFolder();
// call to init label
updateStatus();
// TODO: focus
_ui.pbSelectLocalFolder->setFocus();
}
// Called if the user changes the user- or url field. Adjust the texts and
// evtl. warnings on the dialog.
void OwncloudAdvancedSetupPage::updateStatus()
{
const QString locFolder = localFolder();
// check if the local folder exists. If so, and if its not empty, show a warning.
QString t;
_ui.pbSelectLocalFolder->setText(QDir::toNativeSeparators(locFolder));
if (dataChanged()) {
if( _remoteFolder.isEmpty() || _remoteFolder == QLatin1String("/") ) {
t = tr("Your entire account will be synced to the local folder '%1'.")
.arg(QDir::toNativeSeparators(locFolder));
} else {
t = tr("%1 folder '%2' is synced to local folder '%3'")
.arg(Theme::instance()->appName()).arg(_remoteFolder)
.arg(QDir::toNativeSeparators(locFolder));
}
if ( _multipleFoldersExist ) {
t += tr("<p><small><strong>Warning:</strong> You currently have multiple folders "
"configured. If you continue with the current settings, the folder configurations "
"will be discarded and a single root folder sync will be created!</small></p>");
}
const bool dirNotEmpty(QDir(locFolder).entryList(QDir::AllEntries | QDir::NoDotAndDotDot).count() > 0);
if(dirNotEmpty) {
t += tr("<p><small><strong>Warning:</strong> The local directory is not empty. "
"Pick a resolution!</small></p>");
}
_ui.resolutionWidget->setVisible(dirNotEmpty);
} else {
_ui.resolutionWidget->setVisible(false);
}
_ui.syncModeLabel->setText(t);
_ui.syncModeLabel->setFixedHeight(_ui.syncModeLabel->sizeHint().height());
}
bool OwncloudAdvancedSetupPage::dataChanged()
{
OwncloudWizard* ocWizard(dynamic_cast< OwncloudWizard* >(wizard()));
if (!ocWizard) {
return false;
}
MirallConfigFile cfgFile;
const QString url(field("OCUrl").toString());
AbstractCredentials* newCredentials(ocWizard->getCredentials());
AbstractCredentials* oldCredentials(cfgFile.getCredentials());
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));
}
void OwncloudAdvancedSetupPage::startSpinner()
{
_ui.resultLayout->setEnabled(true);
_progressIndi->setVisible(true);
_progressIndi->startAnimation();
}
void OwncloudAdvancedSetupPage::stopSpinner()
{
_ui.resultLayout->setEnabled(false);
_progressIndi->setVisible(false);
_progressIndi->stopAnimation();
}
int OwncloudAdvancedSetupPage::nextId() const
{
return WizardCommon::Page_Result;
}
QString OwncloudAdvancedSetupPage::localFolder() const
{
QString folder = wizard()->property("localFolder").toString();
return folder;
}
bool OwncloudAdvancedSetupPage::validatePage()
{
if(!_created) {
setErrorString(QString::null);
_checking = true;
startSpinner();
emit completeChanged();
emit createLocalAndRemoteFolders(localFolder(), _remoteFolder);
return false;
} else {
// connecting is running
_checking = false;
emit completeChanged();
stopSpinner();
return true;
}
}
void OwncloudAdvancedSetupPage::setErrorString( const QString& err )
{
if( err.isEmpty()) {
_ui.errorLabel->setVisible(false);
} else {
_ui.errorLabel->setVisible(true);
_ui.errorLabel->setText(err);
}
_checking = false;
emit completeChanged();
}
void OwncloudAdvancedSetupPage::directoriesCreated()
{
_checking = false;
_created = true;
stopSpinner();
emit completeChanged();
}
void OwncloudAdvancedSetupPage::setRemoteFolder( const QString& remoteFolder )
{
if( !remoteFolder.isEmpty() ) {
_remoteFolder = remoteFolder;
}
}
void OwncloudAdvancedSetupPage::setMultipleFoldersExist(bool exist)
{
_multipleFoldersExist = exist;
}
void OwncloudAdvancedSetupPage::slotSelectFolder()
{
QString dir = QFileDialog::getExistingDirectory(0, tr("Local Sync Folder"), QDir::homePath());
if( !dir.isEmpty() ) {
_ui.pbSelectLocalFolder->setText(dir);
wizard()->setProperty("localFolder", dir);
updateStatus();
}
}
void OwncloudAdvancedSetupPage::setConfigExists(bool config)
{
_configExists = config;
if (config == true) {
setSubTitle(WizardCommon::subTitleTemplate().arg(tr("Update advanced setup")));
}
}
} // ns Mirall

View file

@ -0,0 +1,73 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifndef MIRALL_OWNCLOUD_ADVANCED_SETUP_PAGE_H
#define MIRALL_OWNCLOUD_ADVANCED_SETUP_PAGE_H
#include <QWizard>
#include "wizard/owncloudwizardcommon.h"
#include "ui_owncloudadvancedsetuppage.h"
class QProgressIndicator;
namespace Mirall {
class OwncloudAdvancedSetupPage: public QWizardPage
{
Q_OBJECT
public:
OwncloudAdvancedSetupPage();
virtual bool isComplete() const;
virtual void initializePage();
virtual int nextId() const;
bool validatePage();
QString localFolder() const;
void setRemoteFolder( const QString& remoteFolder);
void setMultipleFoldersExist( bool exist );
void directoriesCreated();
void setConfigExists(bool config);
signals:
void createLocalAndRemoteFolders(const QString&, const QString&);
public slots:
void setErrorString( const QString& );
private slots:
void slotSelectFolder();
private:
void setupCustomization();
void updateStatus();
bool dataChanged();
void startSpinner();
void stopSpinner();
Ui_OwncloudAdvancedSetupPage _ui;
bool _checking;
bool _created;
bool _configExists;
bool _multipleFoldersExist;
QProgressIndicator* _progressIndi;
QString _oldLocalFolder;
QString _remoteFolder;
};
} // ns Mirall
#endif

View file

@ -0,0 +1,267 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OwncloudAdvancedSetupPage</class>
<widget class="QWidget" name="OwncloudAdvancedSetupPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>821</width>
<height>647</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="topLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QFormLayout" name="advancedBox">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&amp;Local Folder</string>
</property>
<property name="buddy">
<cstring>pbSelectLocalFolder</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pbSelectLocalFolder">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>pbSelectLocalFolder</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QWidget" name="resolutionWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="0" column="0" colspan="2">
<widget class="QRadioButton" name="radioButton">
<property name="text">
<string>&amp;Keep local data</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;small&gt;Syncs your existing data to new location.&lt;/small&gt;</string>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="indent">
<number>0</number>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QRadioButton" name="cbSyncFromScratch">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If this box is checked, existing content in the local directory will be erased to start a clean sync from the server.&lt;/p&gt;&lt;p&gt;Do not check this if the local content should be uploaded to the servers directory.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>&amp;Start a clean sync</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>&lt;small&gt;Erases the contents of the local folder before syncing using the new settings.&lt;/small&gt;</string>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="indent">
<number>0</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="errorLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="syncModeLabel">
<property name="text">
<string>Status message</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="resultLayout"/>
</item>
<item>
<widget class="QLabel" name="bottomLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,162 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "QProgressIndicator.h"
#include "wizard/owncloudhttpcredspage.h"
#include "mirall/theme.h"
#include "wizard/owncloudwizardcommon.h"
#include "creds/httpcredentials.h"
#include "mirall/mirallconfigfile.h"
namespace Mirall
{
OwncloudHttpCredsPage::OwncloudHttpCredsPage()
: AbstractCredentialsWizardPage(),
_ui(),
_connected(false),
_checking(false),
_configExists(false),
_progressIndi(new QProgressIndicator (this))
{
_ui.setupUi(this);
registerField( QLatin1String("OCUser*"), _ui.leUsername);
registerField( QLatin1String("OCPasswd*"), _ui.lePassword);
setTitle(WizardCommon::titleTemplate().arg(tr("Connect to %1").arg(Theme::instance()->appNameGUI())));
setSubTitle(WizardCommon::subTitleTemplate().arg(tr("Enter user credentials")));
_ui.resultLayout->addWidget( _progressIndi );
stopSpinner();
setupCustomization();
}
void OwncloudHttpCredsPage::setupCustomization()
{
// set defaults for the customize labels.
_ui.topLabel->hide();
_ui.bottomLabel->hide();
Theme *theme = Theme::instance();
QVariant variant = theme->customMedia( Theme::oCSetupTop );
if( !variant.isNull() ) {
WizardCommon::setupCustomMedia( variant, _ui.topLabel );
}
variant = theme->customMedia( Theme::oCSetupBottom );
WizardCommon::setupCustomMedia( variant, _ui.bottomLabel );
}
void OwncloudHttpCredsPage::initializePage()
{
WizardCommon::initErrorLabel(_ui.errorLabel);
MirallConfigFile cfgFile;
HttpCredentials* httpCreds(dynamic_cast< HttpCredentials* >(cfgFile.getCredentials()));
if (httpCreds) {
const QString user = httpCreds->user();
if (!user.isEmpty()) {
_ui.leUsername->setText(user);
}
}
_ui.leUsername->setFocus();
}
void OwncloudHttpCredsPage::cleanupPage()
{
_ui.leUsername->clear();
_ui.lePassword->clear();
}
bool OwncloudHttpCredsPage::validatePage()
{
if (_ui.leUsername->text().isEmpty() || _ui.lePassword->text().isEmpty()) {
return false;
}
if (!_connected) {
_ui.errorLabel->setVisible(false);
_checking = true;
startSpinner();
emit completeChanged();
emit connectToOCUrl(field("OCUrl").toString().simplified());
return false;
} else {
_checking = false;
emit completeChanged();
stopSpinner();
return true;
}
return true;
}
int OwncloudHttpCredsPage::nextId() const
{
return WizardCommon::Page_AdvancedSetup;
}
void OwncloudHttpCredsPage::setConnected( bool comp )
{
_connected = comp;
stopSpinner ();
}
void OwncloudHttpCredsPage::startSpinner()
{
_ui.resultLayout->setEnabled(true);
_progressIndi->setVisible(true);
_progressIndi->startAnimation();
}
void OwncloudHttpCredsPage::stopSpinner()
{
_ui.resultLayout->setEnabled(false);
_progressIndi->setVisible(false);
_progressIndi->stopAnimation();
}
void OwncloudHttpCredsPage::setErrorString(const QString& err)
{
if( err.isEmpty()) {
_ui.errorLabel->setVisible(false);
} else {
_ui.errorLabel->setVisible(true);
_ui.errorLabel->setText(err);
}
_checking = false;
emit completeChanged();
stopSpinner();
}
AbstractCredentials* OwncloudHttpCredsPage::getCredentials() const
{
return new HttpCredentials(_ui.leUsername->text(), _ui.lePassword->text());
}
void OwncloudHttpCredsPage::setConfigExists(bool config)
{
_configExists = config;
if (config == true) {
setSubTitle(WizardCommon::subTitleTemplate().arg(tr("Update user credentials")));
}
}
} // ns Mirall

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifndef MIRALL_OWNCLOUD_HTTP_CREDS_PAGE_H
#define MIRALL_OWNCLOUD_HTTP_CREDS_PAGE_H
#include "wizard/abstractcredswizardpage.h"
#include "ui_owncloudhttpcredspage.h"
class QProgressIndicator;
namespace Mirall {
class OwncloudHttpCredsPage : public AbstractCredentialsWizardPage
{
Q_OBJECT
public:
OwncloudHttpCredsPage();
AbstractCredentials* getCredentials() const;
void initializePage();
void cleanupPage();
bool validatePage();
int nextId() const;
void setConnected(bool connected);
void setErrorString( const QString& err );
void setConfigExists(bool config);
Q_SIGNALS:
void connectToOCUrl(const QString&);
private:
void startSpinner();
void stopSpinner();
void setupCustomization();
Ui_OwncloudHttpCredsPage _ui;
bool _connected;
bool _checking;
bool _configExists;
QProgressIndicator* _progressIndi;
};
} // ns Mirall
#endif

View file

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OwncloudHttpCredsPage</class>
<widget class="QWidget" name="OwncloudHttpCredsPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>196</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>48</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;Username</string>
</property>
<property name="buddy">
<cstring>leUsername</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>&amp;Password</string>
</property>
<property name="buddy">
<cstring>lePassword</cstring>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="errorLabel">
<property name="text">
<string>Error Label</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="leUsername"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="lePassword">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>68</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>48</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
<layout class="QHBoxLayout" name="resultLayout"/>
</item>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="topLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QLabel" name="bottomLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
<zorder>horizontalSpacer</zorder>
<zorder>verticalSpacer</zorder>
<zorder>horizontalSpacer_2</zorder>
<zorder>horizontalLayoutWidget</zorder>
<zorder>topLabel</zorder>
<zorder>bottomLabel</zorder>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OwncloudSetupPage</class>
<widget class="QWidget" name="OwncloudSetupPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>478</width>
<height>461</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="topLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Server &amp;Address</string>
</property>
<property name="buddy">
<cstring>leUrl</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Utils::FancyLineEdit" name="leUrl">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Enter the url of the ownCloud you want to connect to (without http or https).</string>
</property>
<property name="placeholderText">
<string>https://...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="errorLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Error Label</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="resultLayout">
<property name="spacing">
<number>0</number>
</property>
</layout>
</item>
<item>
<widget class="QLabel" name="bottomLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Utils::FancyLineEdit</class>
<extends>QLineEdit</extends>
<header location="global">fancylineedit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,234 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <QDir>
#include <QFileDialog>
#include <QUrl>
#include "QProgressIndicator.h"
#include "wizard/owncloudwizardcommon.h"
#include "wizard/owncloudsetuppage.h"
#include "mirall/theme.h"
namespace Mirall
{
OwncloudSetupPage::OwncloudSetupPage()
: QWizardPage(),
_ui(),
_oCUrl(),
_ocUser(),
_authTypeKnown(false),
_checking(false),
_authType(WizardCommon::HttpCreds),
_progressIndi(new QProgressIndicator (this))
{
_ui.setupUi(this);
Theme *theme = Theme::instance();
setTitle(WizardCommon::titleTemplate().arg(tr("Connect to %1").arg(theme->appNameGUI())));
setSubTitle(WizardCommon::subTitleTemplate().arg(tr("Setup ownCloud server")));
registerField( QLatin1String("OCUrl*"), _ui.leUrl );
_ui.resultLayout->addWidget( _progressIndi );
stopSpinner();
setupCustomization();
connect(_ui.leUrl, SIGNAL(textChanged(QString)), SLOT(slotUrlChanged(QString)));
}
void OwncloudSetupPage::setServerUrl( const QString& newUrl )
{
_oCUrl = newUrl;
if( _oCUrl.isEmpty() ) {
_ui.leUrl->clear();
return;
}
_ui.leUrl->setText( _oCUrl );
}
void OwncloudSetupPage::setupCustomization()
{
// set defaults for the customize labels.
_ui.topLabel->hide();
_ui.bottomLabel->hide();
Theme *theme = Theme::instance();
QVariant variant = theme->customMedia( Theme::oCSetupTop );
if( !variant.isNull() ) {
WizardCommon::setupCustomMedia( variant, _ui.topLabel );
}
variant = theme->customMedia( Theme::oCSetupBottom );
WizardCommon::setupCustomMedia( variant, _ui.bottomLabel );
QString fixUrl = theme->overrideServerUrl();
if( !fixUrl.isEmpty() ) {
_ui.label_2->hide();
setServerUrl( fixUrl );
_ui.leUrl->setEnabled( false );
_ui.leUrl->hide();
}
}
// slot hit from textChanged of the url entry field.
void OwncloudSetupPage::slotUrlChanged(const QString& /*ocUrl*/)
{
#if 0
QString url = ocUrl;
bool visible = false;
if (url.startsWith(QLatin1String("https://"))) {
_ui.urlLabel->setPixmap( QPixmap(":/mirall/resources/security-high.png"));
_ui.urlLabel->setToolTip(tr("This url is secure. You can use it."));
visible = true;
}
if (url.startsWith(QLatin1String("http://"))) {
_ui.urlLabel->setPixmap( QPixmap(":/mirall/resources/security-low.png"));
_ui.urlLabel->setToolTip(tr("This url is NOT secure. You should not use it."));
visible = true;
}
#endif
}
bool OwncloudSetupPage::isComplete() const
{
return !_ui.leUrl->text().isEmpty() && !_checking;
}
void OwncloudSetupPage::initializePage()
{
WizardCommon::initErrorLabel(_ui.errorLabel);
_authTypeKnown = false;
_checking = false;
// URL entry is disabled when url is overriden by theme. In that
// case we just check the server type and switch to second page
// immediately.
if (_ui.leUrl->isEnabled()) {
_ui.leUrl->setFocus();
} else {
validatePage();
}
}
bool OwncloudSetupPage::urlHasChanged()
{
bool change = false;
const QChar slash('/');
QUrl currentUrl( url() );
QUrl initialUrl( _oCUrl );
QString currentPath = currentUrl.path();
QString initialPath = initialUrl.path();
// add a trailing slash.
if( ! currentPath.endsWith( slash )) currentPath += slash;
if( ! initialPath.endsWith( slash )) initialPath += slash;
if( currentUrl.host() != initialUrl.host() ||
currentUrl.port() != initialUrl.port() ||
currentPath != initialPath ) {
change = true;
}
return change;
}
int OwncloudSetupPage::nextId() const
{
if (_authType == WizardCommon::HttpCreds) {
return WizardCommon::Page_HttpCreds;
} else {
return WizardCommon::Page_ShibbolethCreds;
}
}
QString OwncloudSetupPage::url() const
{
QString url = _ui.leUrl->text().simplified();
return url;
}
bool OwncloudSetupPage::validatePage()
{
if( ! _authTypeKnown) {
setErrorString(QString::null);
_checking = true;
startSpinner ();
emit completeChanged();
emit determineAuthType(url());
return false;
} else {
// connecting is running
stopSpinner();
_checking = false;
emit completeChanged();
return true;
}
}
void OwncloudSetupPage::setAuthType (WizardCommon::AuthType type)
{
_authTypeKnown = true;
_authType = type;
stopSpinner();
}
void OwncloudSetupPage::setErrorString( const QString& err )
{
if( err.isEmpty()) {
_ui.errorLabel->setVisible(false);
} else {
_ui.errorLabel->setVisible(true);
_ui.errorLabel->setText(err);
}
_checking = false;
emit completeChanged();
stopSpinner();
}
void OwncloudSetupPage::startSpinner()
{
_ui.resultLayout->setEnabled(true);
_progressIndi->setVisible(true);
_progressIndi->startAnimation();
}
void OwncloudSetupPage::stopSpinner()
{
_ui.resultLayout->setEnabled(false);
_progressIndi->setVisible(false);
_progressIndi->stopAnimation();
}
void OwncloudSetupPage::setConfigExists( bool config )
{
_configExists = config;
if (config == true) {
setSubTitle(WizardCommon::subTitleTemplate().arg(tr("Update ownCloud server")));
}
}
} // ns Mirall

View file

@ -0,0 +1,82 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifndef MIRALL_OWNCLOUD_SETUP_PAGE_H
#define MIRALL_OWNCLOUD_SETUP_PAGE_H
#include <QWizard>
#include "wizard/owncloudwizardcommon.h"
#include "ui_owncloudsetupnocredspage.h"
class QLabel;
class QVariant;
class QProgressIndicator;
namespace Mirall {
class OwncloudSetupPage: public QWizardPage
{
Q_OBJECT
public:
OwncloudSetupPage();
virtual bool isComplete() const;
virtual void initializePage();
virtual int nextId() const;
void setServerUrl( const QString& );
void setAllowPasswordStorage( bool );
bool validatePage();
QString url() const;
QString localFolder() const;
void setRemoteFolder( const QString& remoteFolder);
void setMultipleFoldersExist( bool exist );
void setAuthType(WizardCommon::AuthType type);
public slots:
void setErrorString( const QString& );
void setConfigExists( bool );
void startSpinner();
void stopSpinner();
protected slots:
void slotUrlChanged(const QString&);
void setupCustomization();
signals:
void determineAuthType(const QString&);
private:
bool urlHasChanged();
Ui_OwncloudSetupPage _ui;
QString _oCUrl;
QString _ocUser;
bool _authTypeKnown;
bool _checking;
bool _configExists;
bool _multipleFoldersExist;
WizardCommon::AuthType _authType;
QProgressIndicator* _progressIndi;
QButtonGroup* _selectiveSyncButtons;
QString _remoteFolder;
};
} // ns Mirall
#endif

View file

@ -0,0 +1,164 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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 "wizard/owncloudshibbolethcredspage.h"
#include "mirall/theme.h"
#include "wizard/owncloudwizardcommon.h"
#include "creds/shibbolethcredentials.h"
#include "creds/shibboleth/shibbolethwebview.h"
namespace Mirall
{
OwncloudShibbolethCredsPage::OwncloudShibbolethCredsPage()
: AbstractCredentialsWizardPage(),
_ui(),
_stage(INITIAL_STEP),
_browser(0),
_cookie()
{
_ui.setupUi(this);
setTitle(WizardCommon::titleTemplate().arg(tr("Connect to %1").arg(Theme::instance()->appNameGUI())));
setSubTitle(WizardCommon::subTitleTemplate().arg(tr("Process through Shibboleth form")));
setupCustomization();
}
void OwncloudShibbolethCredsPage::setupCustomization()
{
// set defaults for the customize labels.
_ui.topLabel->hide();
_ui.bottomLabel->hide();
Theme *theme = Theme::instance();
QVariant variant = theme->customMedia( Theme::oCSetupTop );
if( !variant.isNull() ) {
WizardCommon::setupCustomMedia( variant, _ui.topLabel );
}
variant = theme->customMedia( Theme::oCSetupBottom );
WizardCommon::setupCustomMedia( variant, _ui.bottomLabel );
}
bool OwncloudShibbolethCredsPage::isComplete() const
{
return _stage == GOT_COOKIE;
}
void OwncloudShibbolethCredsPage::initializePage()
{
WizardCommon::initErrorLabel(_ui.errorLabel);
_browser = new ShibbolethWebView(QUrl(field("OCUrl").toString().simplified()));
_browser->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
connect(_browser, SIGNAL(shibbolethCookieReceived(QNetworkCookie)),
this, SLOT(onShibbolethCookieReceived(QNetworkCookie)));
//_ui.contentLayout->insertWidget(0, _browser);
_browser->show();
_browser->setFocus();
wizard()->hide();
_ui.infoLabel->show();
_ui.infoLabel->setText(tr("Please follow the steps on displayed page above"));
_stage = INITIAL_STEP;
_cookie = QNetworkCookie();
}
void OwncloudShibbolethCredsPage::disposeBrowser(bool later)
{
if (_browser) {
_browser->hide();
disconnect(_browser, SIGNAL(shibbolethCookieReceived(QNetworkCookie)),
this, SLOT(onShibbolethCookieReceived(QNetworkCookie)));
if (later) {
_browser->deleteLater();
} else {
delete _browser;
}
_browser = 0;
}
}
void OwncloudShibbolethCredsPage::cleanupPage()
{
disposeBrowser(false);
}
bool OwncloudShibbolethCredsPage::validatePage()
{
switch (_stage) {
case INITIAL_STEP:
return false;
case GOT_COOKIE:
_stage = CHECKING;
emit completeChanged();
emit connectToOCUrl(field("OCUrl").toString().simplified());
return false;
case CHECKING:
return false;
case CONNECTED:
return true;
}
return false;
}
int OwncloudShibbolethCredsPage::nextId() const
{
return WizardCommon::Page_AdvancedSetup;
}
void OwncloudShibbolethCredsPage::setConnected( bool comp )
{
if (comp) {
_stage = CONNECTED;
} else {
// sets stage to INITIAL
initializePage();
}
emit completeChanged();
wizard()->show();
}
void OwncloudShibbolethCredsPage::setErrorString(const QString& err)
{
if( err.isEmpty()) {
_ui.errorLabel->setVisible(false);
} else {
initializePage();
_ui.errorLabel->setVisible(true);
_ui.errorLabel->setText(err);
}
emit completeChanged();
}
AbstractCredentials* OwncloudShibbolethCredsPage::getCredentials() const
{
return new ShibbolethCredentials(_cookie);
}
void OwncloudShibbolethCredsPage::onShibbolethCookieReceived(const QNetworkCookie& cookie)
{
disposeBrowser(true);
_stage = GOT_COOKIE;
_cookie = cookie;
_ui.infoLabel->setText("Please click \"Connect\" to check received Shibboleth session.");
emit completeChanged();
validatePage();
}
} // ns Mirall

View file

@ -0,0 +1,68 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; version 2 of the License.
*
* 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.
*/
#ifndef MIRALL_OWNCLOUD_SHIBBOLETH_CREDS_PAGE_H
#define MIRALL_OWNCLOUD_SHIBBOLETH_CREDS_PAGE_H
#include <QNetworkCookie>
#include "wizard/abstractcredswizardpage.h"
#include "ui_owncloudshibbolethcredspage.h"
namespace Mirall {
class ShibbolethWebView;
class OwncloudShibbolethCredsPage : public AbstractCredentialsWizardPage
{
Q_OBJECT
public:
OwncloudShibbolethCredsPage();
AbstractCredentials* getCredentials() const;
bool isComplete() const;
void initializePage();
void cleanupPage();
bool validatePage();
int nextId() const;
void setConnected(bool connected);
void setErrorString(const QString& err);
Q_SIGNALS:
void connectToOCUrl(const QString&);
private Q_SLOTS:
void onShibbolethCookieReceived(const QNetworkCookie& cookie);
private:
enum Stage {
INITIAL_STEP,
GOT_COOKIE,
CHECKING,
CONNECTED
};
void setupCustomization();
void disposeBrowser(bool later);
Ui_OwncloudShibbolethCredsPage _ui;
Stage _stage;
ShibbolethWebView* _browser;
QNetworkCookie _cookie;
};
} // ns Mirall
#endif

View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OwncloudShibbolethCredsPage</class>
<widget class="QWidget" name="OwncloudShibbolethCredsPage">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>451</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<item>
<widget class="QLabel" name="topLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="contentLayout">
<item>
<widget class="QLabel" name="errorLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Error Label</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="infoLabel">
<property name="text">
<string>info label</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>17</width>
<height>38</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="bottomLabel">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,213 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 "wizard/owncloudwizard.h"
#include "mirall/mirallconfigfile.h"
#include "mirall/theme.h"
#include "wizard/owncloudsetuppage.h"
#include "wizard/owncloudhttpcredspage.h"
#include "wizard/owncloudshibbolethcredspage.h"
#include "wizard/owncloudadvancedsetuppage.h"
#include "wizard/owncloudwizardresultpage.h"
#include "QProgressIndicator.h"
#include <QtCore>
#include <QtGui>
#include <stdlib.h>
namespace Mirall
{
OwncloudWizard::OwncloudWizard(QWidget *parent)
: QWizard(parent),
_setupPage(new OwncloudSetupPage),
_httpCredsPage(new OwncloudHttpCredsPage),
_shibbolethCredsPage(new OwncloudShibbolethCredsPage),
_advancedSetupPage(new OwncloudAdvancedSetupPage),
_resultPage(new OwncloudWizardResultPage),
_credentialsPage(0),
_configFile(),
_oCUser(),
_setupLog(),
_configExists(false)
{
setPage(WizardCommon::Page_ServerSetup, _setupPage );
setPage(WizardCommon::Page_HttpCreds, _httpCredsPage);
setPage(WizardCommon::Page_ShibbolethCreds, _shibbolethCredsPage);
setPage(WizardCommon::Page_AdvancedSetup, _advancedSetupPage);
setPage(WizardCommon::Page_Result, _resultPage );
// note: start Id is set by the calling class depending on if the
// welcome text is to be shown or not.
setWizardStyle( QWizard::ModernStyle );
connect( this, SIGNAL(currentIdChanged(int)), SLOT(slotCurrentPageChanged(int)));
connect( _setupPage, SIGNAL(determineAuthType(QString)), SIGNAL(determineAuthType(QString)));
connect( _httpCredsPage, SIGNAL(connectToOCUrl(QString)), SIGNAL(connectToOCUrl(QString)));
connect( _shibbolethCredsPage, SIGNAL(connectToOCUrl(QString)), SIGNAL(connectToOCUrl(QString)));
connect( _advancedSetupPage, SIGNAL(createLocalAndRemoteFolders(QString, QString)),
SIGNAL(createLocalAndRemoteFolders(QString, QString)));
Theme *theme = Theme::instance();
setWindowTitle( tr("%1 Connection Wizard").arg(theme->appNameGUI()));
setWizardStyle(QWizard::ModernStyle);
setPixmap( QWizard::BannerPixmap, theme->wizardHeaderBanner() );
setPixmap( QWizard::LogoPixmap, theme->wizardHeaderLogo() );
setOption( QWizard::NoBackButtonOnStartPage );
setOption( QWizard::NoBackButtonOnLastPage );
setOption( QWizard::NoCancelButton );
setTitleFormat(Qt::RichText);
setSubTitleFormat(Qt::RichText);
}
void OwncloudWizard::setMultipleFoldersExist(bool exist)
{
_advancedSetupPage->setMultipleFoldersExist(exist);
}
QString OwncloudWizard::localFolder() const
{
return(_advancedSetupPage->localFolder());
}
QString OwncloudWizard::ocUrl() const
{
QString url = field("OCUrl").toString().simplified();
return url;
}
void OwncloudWizard::enableFinishOnResultWidget(bool enable)
{
_resultPage->setComplete(enable);
}
void OwncloudWizard::setRemoteFolder( const QString& remoteFolder )
{
_advancedSetupPage->setRemoteFolder( remoteFolder );
_resultPage->setRemoteFolder( remoteFolder );
}
void OwncloudWizard::successfulStep()
{
const int id(currentId());
switch (id) {
case WizardCommon::Page_HttpCreds:
_httpCredsPage->setConnected(true);
break;
case WizardCommon::Page_ShibbolethCreds:
_shibbolethCredsPage->setConnected(true);
break;
case WizardCommon::Page_AdvancedSetup:
_advancedSetupPage->directoriesCreated();
break;
case WizardCommon::Page_ServerSetup:
case WizardCommon::Page_Result:
qWarning("Should not happen at this stage.");
break;
}
next();
}
void OwncloudWizard::setAuthType(WizardCommon::AuthType type)
{
_setupPage->setAuthType(type);
if (type == WizardCommon::Shibboleth) {
_credentialsPage = _shibbolethCredsPage;
} else {
_credentialsPage = _httpCredsPage;
}
next();
}
// TODO: update this function
void OwncloudWizard::slotCurrentPageChanged( int id )
{
qDebug() << "Current Wizard page changed to " << id;
if( id == WizardCommon::Page_ServerSetup ) {
setButtonText( QWizard::NextButton, tr("Connect...") );
emit clearPendingRequests();
_setupPage->initializePage();
}
if( id == WizardCommon::Page_Result ) {
appendToConfigurationLog( QString::null );
}
}
void OwncloudWizard::displayError( const QString& msg )
{
switch (currentId()) {
case WizardCommon::Page_ServerSetup:
_setupPage->setErrorString( msg );
break;
case WizardCommon::Page_HttpCreds:
_httpCredsPage->setErrorString(msg);
break;
case WizardCommon::Page_ShibbolethCreds:
_shibbolethCredsPage->setErrorString(msg);
break;
case WizardCommon::Page_AdvancedSetup:
_advancedSetupPage->setErrorString(msg);
break;
}
}
void OwncloudWizard::appendToConfigurationLog( const QString& msg, LogType /*type*/ )
{
_setupLog << msg;
qDebug() << "Setup-Log: " << msg;
}
void OwncloudWizard::setOCUrl( const QString& url )
{
_setupPage->setServerUrl( url );
}
void OwncloudWizard::setConfigExists( bool config )
{
_configExists = config;
_setupPage->setConfigExists( config );
_httpCredsPage->setConfigExists(config);
_advancedSetupPage->setConfigExists(config);
}
bool OwncloudWizard::configExists()
{
return _configExists;
}
AbstractCredentials* OwncloudWizard::getCredentials() const
{
if (_credentialsPage) {
return _credentialsPage->getCredentials();
}
return 0;
}
} // end namespace

View file

@ -0,0 +1,89 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifndef MIRALL_OWNCLOUD_WIZARD_H
#define MIRALL_OWNCLOUD_WIZARD_H
#include <QWizard>
#include "wizard/owncloudwizardcommon.h"
namespace Mirall {
class OwncloudSetupPage;
class OwncloudHttpCredsPage;
class OwncloudShibbolethCredsPage;
class OwncloudAdvancedSetupPage;
class OwncloudWizardResultPage;
class AbstractCredentials;
class AbstractCredentialsWizardPage;
class OwncloudWizard: public QWizard
{
Q_OBJECT
public:
enum LogType {
LogPlain,
LogParagraph
};
OwncloudWizard(QWidget *parent = 0);
void setOCUrl( const QString& );
void setupCustomMedia( QVariant, QLabel* );
QString ocUrl() const;
QString localFolder() const;
void enableFinishOnResultWidget(bool enable);
void displayError( const QString& );
void setMultipleFoldersExist( bool );
void setConfigExists( bool );
bool configExists();
void successfulStep();
void setAuthType(WizardCommon::AuthType type);
AbstractCredentials* getCredentials() const;
public slots:
void setRemoteFolder( const QString& );
void appendToConfigurationLog( const QString& msg, LogType type = LogParagraph );
void slotCurrentPageChanged( int );
signals:
void clearPendingRequests();
void determineAuthType(const QString&);
void connectToOCUrl( const QString& );
void createLocalAndRemoteFolders(const QString&, const QString&);
private:
OwncloudSetupPage* _setupPage;
OwncloudHttpCredsPage* _httpCredsPage;
OwncloudShibbolethCredsPage* _shibbolethCredsPage;
OwncloudAdvancedSetupPage* _advancedSetupPage;
OwncloudWizardResultPage* _resultPage;
AbstractCredentialsWizardPage* _credentialsPage;
QString _configFile;
QString _oCUser;
QStringList _setupLog;
bool _configExists;
};
} // ns Mirall
#endif

View file

@ -0,0 +1,72 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <QLabel>
#include <QPixmap>
#include <QVariant>
#include "wizard/owncloudwizardcommon.h"
#include "mirall/theme.h"
namespace Mirall
{
namespace WizardCommon
{
void setupCustomMedia( const QVariant& variant, QLabel *label )
{
if( !label ) return;
QPixmap pix = variant.value<QPixmap>();
if( !pix.isNull() ) {
label->setPixmap(pix);
label->setAlignment( Qt::AlignTop | Qt::AlignRight );
label->setVisible(true);
} else {
QString str = variant.toString();
if( !str.isEmpty() ) {
label->setText( str );
label->setTextFormat( Qt::RichText );
label->setVisible(true);
label->setOpenExternalLinks(true);
}
}
}
QString titleTemplate()
{
return QString::fromLatin1("<font color=\"%1\" size=\"5\">").arg(Theme::instance()->wizardHeaderTitleColor().name()) + QString::fromLatin1("%1</font>");
}
QString subTitleTemplate()
{
return QString::fromLatin1("<font color=\"%1\">").arg(Theme::instance()->wizardHeaderTitleColor().name()) + QString::fromLatin1("%1</font>");
}
void initErrorLabel(QLabel* errorLabel)
{
QString style = QLatin1String("border: 1px solid #eed3d7; border-radius: 5px; padding: 3px;"
"background-color: #f2dede; color: #b94a48;");
errorLabel->setStyleSheet(style);
errorLabel->setWordWrap(true);
errorLabel->setVisible(false);
}
} // ns WizardCommon
} // ns Mirall

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifndef MIRALL_OWNCLOUD_WIZARD_COMMON_H
#define MIRALL_OWNCLOUD_WIZARD_COMMON_H
class QVariant;
class QLabel;
namespace Mirall
{
namespace WizardCommon
{
void setupCustomMedia( const QVariant& variant, QLabel *label );
QString titleTemplate();
QString subTitleTemplate();
void initErrorLabel(QLabel* errorLabel);
enum AuthType {
HttpCreds,
Shibboleth
};
enum SyncMode {
SelectiveMode,
BoxMode
};
enum Pages {
Page_ServerSetup,
Page_HttpCreds,
Page_ShibbolethCreds,
Page_AdvancedSetup,
Page_Result
};
} // ns WizardCommon
} // ns Mirall
#endif // MIRALL_OWNCLOUD_WIZARD_COMMON_H

View file

@ -0,0 +1,116 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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 <QDebug>
#include <QDesktopServices>
#include <QDir>
#include <QUrl>
#include "wizard/owncloudwizardresultpage.h"
#include "wizard/owncloudwizardcommon.h"
#include "mirall/theme.h"
namespace Mirall
{
OwncloudWizardResultPage::OwncloudWizardResultPage()
: QWizardPage(),
_localFolder(),
_remoteFolder(),
_complete(false),
_ui()
{
_ui.setupUi(this);
// no fields to register.
setTitle(WizardCommon::subTitleTemplate().arg(tr("Everything set up!")));
// required to show header in QWizard's modern style
setSubTitle( QLatin1String(" ") );
_ui.pbOpenLocal->setText(tr("Open Local Folder"));
_ui.pbOpenLocal->setIcon(QIcon(":/mirall/resources/folder-sync.png"));
_ui.pbOpenLocal->setIconSize(QSize(48, 48));
_ui.pbOpenLocal->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
connect(_ui.pbOpenLocal, SIGNAL(clicked()), SLOT(slotOpenLocal()));
Theme* theme = Theme::instance();
QIcon appIcon = theme->applicationIcon();
_ui.pbOpenServer->setText(tr("Open %1").arg(theme->appNameGUI()));
_ui.pbOpenServer->setIcon(appIcon.pixmap(48));
_ui.pbOpenServer->setIconSize(QSize(48, 48));
_ui.pbOpenServer->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
connect(_ui.pbOpenServer, SIGNAL(clicked()), SLOT(slotOpenServer()));
setupCustomization();
}
OwncloudWizardResultPage::~OwncloudWizardResultPage()
{}
void OwncloudWizardResultPage::setComplete(bool complete)
{
_complete = complete;
emit completeChanged();
}
bool OwncloudWizardResultPage::isComplete() const
{
return _complete;
}
void OwncloudWizardResultPage::initializePage()
{
const QString localFolder = wizard()->property("localFolder").toString();
QString text;
if( _remoteFolder == QLatin1String("/") || _remoteFolder.isEmpty() ) {
text = tr("Your entire account is synced to the local folder <i>%1</i>")
.arg(QDir::toNativeSeparators(localFolder));
} else {
text = tr("ownCloud folder <i>%1</i> is synced to local folder <i>%2</i>")
.arg(_remoteFolder).arg(QDir::toNativeSeparators(localFolder));
}
_ui.localFolderLabel->setText( text );
}
void OwncloudWizardResultPage::setRemoteFolder(const QString &remoteFolder)
{
_remoteFolder = remoteFolder;
}
void OwncloudWizardResultPage::setupCustomization()
{
// set defaults for the customize labels.
_ui.topLabel->setText( QString::null );
_ui.topLabel->hide();
QVariant variant = Theme::instance()->customMedia( Theme::oCSetupResultTop );
WizardCommon::setupCustomMedia( variant, _ui.topLabel );
}
void OwncloudWizardResultPage::slotOpenLocal()
{
const QString localFolder = wizard()->property("localFolder").toString();
QDesktopServices::openUrl(QUrl::fromLocalFile(localFolder));
}
void OwncloudWizardResultPage::slotOpenServer()
{
QUrl url = field("OCUrl").toUrl();
qDebug() << Q_FUNC_INFO << url;
QDesktopServices::openUrl(url);
}
} // ns Mirall

View file

@ -0,0 +1,57 @@
/*
* Copyright (C) by Duncan Mac-Vicar P. <duncan@kde.org>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#ifndef MIRALL_OWNCLOUD_WIZARD_RESULT_PAGE_H
#define MIRALL_OWNCLOUD_WIZARD_RESULT_PAGE_H
#include <QWizardPage>
#include "ui_owncloudwizardresultpage.h"
namespace Mirall {
class OwncloudWizardResultPage : public QWizardPage
{
Q_OBJECT
public:
OwncloudWizardResultPage();
~OwncloudWizardResultPage();
bool isComplete() const;
void initializePage();
void setRemoteFolder( const QString& remoteFolder);
public slots:
void setComplete(bool complete);
protected slots:
void slotOpenLocal();
void slotOpenServer();
protected:
void setupCustomization();
private:
QString _localFolder;
QString _remoteFolder;
bool _complete;
Ui_OwncloudWizardResultPage _ui;
};
} // ns Mirall
#endif