diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b54b07560..a865dad9d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -212,14 +212,14 @@ set(mirall_SRCS mirall/folderwizard.cpp mirall/folderstatusmodel.cpp mirall/protocolwidget.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 + 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 mirall/sslerrordialog.cpp @@ -237,14 +237,14 @@ set(mirall_HEADERS mirall/application.h mirall/systray.h mirall/folderwizard.h -# mirall/owncloudsetupwizard.h -# wizard/owncloudwizard.h -# wizard/owncloudsetuppage.h -# wizard/owncloudhttpcredspage.h -# wizard/owncloudwizardresultpage.h -# wizard/owncloudwizardcommon.h -# wizard/owncloudshibbolethcredspage.h -# wizard/owncloudadvancedsetuppage.h + mirall/owncloudsetupwizard.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 diff --git a/src/mirall/account.cpp b/src/mirall/account.cpp index 2f00173d5..29e47c1f8 100644 --- a/src/mirall/account.cpp +++ b/src/mirall/account.cpp @@ -48,13 +48,14 @@ AccountManager *AccountManager::instance() } -Account::Account(QObject *parent) +Account::Account(AbstractSslErrorHandler *sslErrorHandler, QObject *parent) : QObject(parent) , _am(0) , _credentials(0) , _treatSslErrorsAsFailure(false) , _sslErrorHandler(0) { + setSslErrorHandler(sslErrorHandler); } void Account::save(QSettings &settings) @@ -112,11 +113,9 @@ void Account::setCredentials(AbstractCredentials *cred) SLOT(slotHandleErrors(QNetworkReply*,QList))); } -static const char WEBDAV_PATH[] = "remote.php/webdav/"; - QUrl Account::davUrl() const { - return concatUrlPath(url(), WEBDAV_PATH); + return concatUrlPath(url(), davPath()); } QList Account::lastAuthCookies() const @@ -124,17 +123,36 @@ QList Account::lastAuthCookies() const return _am->cookieJar()->cookiesForUrl(_url); } +QNetworkReply *Account::headRequest(const QString &relPath) +{ + return headRequest(concatUrlPath(url(), relPath)); +} + +QNetworkReply *Account::headRequest(const QUrl &url) +{ + QNetworkRequest request(url); + return _am->head(request); +} + QNetworkReply *Account::getRequest(const QString &relPath) { - QNetworkRequest request(concatUrlPath(url(), relPath)); - // ### error handling + return getRequest(concatUrlPath(url(), relPath)); +} + +QNetworkReply *Account::getRequest(const QUrl &url) +{ + QNetworkRequest request(url); return _am->get(request); } QNetworkReply *Account::davRequest(const QByteArray &verb, const QString &relPath, QNetworkRequest req, QIODevice *data) { - req.setUrl(concatUrlPath(davUrl(), relPath)); - // ### error handling + return davRequest(verb, concatUrlPath(davUrl(), relPath), req, data); +} + +QNetworkReply *Account::davRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data) +{ + req.setUrl(url); return _am->sendCustomRequest(req, verb, data); } @@ -167,7 +185,7 @@ QUrl Account::concatUrlPath(const QUrl &url, const QString &concatPath) { QUrl tmpUrl = url; QString path = tmpUrl.path(); - if (!path.endsWith('/')) { + if (!path.endsWith('/') || !concatPath.startsWith('/')) { path += QLatin1Char('/'); } path += concatPath; diff --git a/src/mirall/account.h b/src/mirall/account.h index a1b70a744..0e297bfa7 100644 --- a/src/mirall/account.h +++ b/src/mirall/account.h @@ -41,7 +41,7 @@ public: Account *account() { return _account; } private: - AccountManager() {} + AccountManager() : _account(0) {} Account *_account; static AccountManager *_instance; }; @@ -59,7 +59,9 @@ public: class Account : public QObject { Q_OBJECT public: - Account(QObject *parent = 0); + static QString davPath() { return "remote.php/webdav/"; } + + Account(AbstractSslErrorHandler *sslErrorHandler = 0, QObject *parent = 0); /** * Saves the account to a given settings file */ @@ -69,6 +71,14 @@ public: * Creates an account object from from a given settings file. */ static Account* restore(QSettings &settings); + /** + * @brief Creates a minimal account object + * + * This will set up a ssl error handler + * + * @return A new Account object + */ + static Account* create(const QUrl &url); /** Holds the accounts credentials */ AbstractCredentials* credentials() const; @@ -87,8 +97,12 @@ public: QList lastAuthCookies() const; + QNetworkReply* headRequest(const QString &relPath); + QNetworkReply* headRequest(const QUrl &url); QNetworkReply* getRequest(const QString &relPath); + QNetworkReply* getRequest(const QUrl &url); QNetworkReply* davRequest(const QByteArray &verb, const QString &relPath, QNetworkRequest req, QIODevice *data = 0); + QNetworkReply* davRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data = 0); /** The certificates of the account */ QList certificateChain() const { return _certificateChain; } @@ -101,7 +115,7 @@ public: static QUrl concatUrlPath(const QUrl &url, const QString &concatPath); -private slots: +protected slots: void slotHandleErrors(QNetworkReply*,QList); private: diff --git a/src/mirall/accountsettings.cpp b/src/mirall/accountsettings.cpp index f2ea7f9a8..5d9495b69 100644 --- a/src/mirall/accountsettings.cpp +++ b/src/mirall/accountsettings.cpp @@ -174,8 +174,7 @@ void AccountSettings::slotFolderWizardRejected() void AccountSettings::slotOpenAccountWizard() { this->topLevelWidget()->close(); - // ### TODO - //OwncloudSetupWizard::runWizard(qApp, SLOT(slotownCloudWizardDone(int)), 0); + OwncloudSetupWizard::runWizard(qApp, SLOT(slotownCloudWizardDone(int)), 0); } void AccountSettings::slotAddFolder( Folder *folder ) diff --git a/src/mirall/application.cpp b/src/mirall/application.cpp index e8500ba5e..cbbe6461c 100644 --- a/src/mirall/application.cpp +++ b/src/mirall/application.cpp @@ -117,8 +117,10 @@ Application::Application(int &argc, char **argv) : MirallConfigFile cfg; QSettings settings(cfg.configFile(), QSettings::IniFormat); Account *account = Account::restore(settings); - account->setSslErrorHandler(new SslDialogErrorHandler); - AccountManager::instance()->setAccount(account); + if (account) { + account->setSslErrorHandler(new SslDialogErrorHandler); + AccountManager::instance()->setAccount(account); + } FolderMan::instance()->setSyncEnabled(false); diff --git a/src/mirall/connectionvalidator.cpp b/src/mirall/connectionvalidator.cpp index 4c240e8b8..414f2dba1 100644 --- a/src/mirall/connectionvalidator.cpp +++ b/src/mirall/connectionvalidator.cpp @@ -88,20 +88,19 @@ void ConnectionValidator::checkConnection() { if( AccountManager::instance()->account() ) { CheckServerJob *checkJob = new CheckServerJob(_account, false, this); - connect(checkJob, SIGNAL(instanceFound(QVariantMap)), SLOT(slotStatusFound(QVariantMap))); - connect(checkJob, SIGNAL(networkError(QNetworkReply::NetworkError,QString)), - SLOT(slotNoStatusFound(QNetworkReply::NetworkError,QString))); + connect(checkJob, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotStatusFound(QUrl,QVariantMap))); + connect(checkJob, SIGNAL(networkError(QNetworkReply*)), SLOT(slotNoStatusFound(QNetworkReply*))); } else { _errors << tr("No ownCloud account configured"); emit connectionResult( NotConfigured ); } } -void ConnectionValidator::slotStatusFound( const QVariantMap &info ) +void ConnectionValidator::slotStatusFound(const QUrl&url, const QVariantMap &info) { // status.php was found. qDebug() << "** Application: ownCloud found: " - << _account->url() << " with version " + << url << " with version " << CheckServerJob::versionString(info) << "(" << CheckServerJob::version(info) << ")"; // now check the authentication @@ -117,12 +116,12 @@ void ConnectionValidator::slotStatusFound( const QVariantMap &info ) } // status.php could not be loaded. -void ConnectionValidator::slotNoStatusFound(QNetworkReply::NetworkError error, const QString &errStr) +void ConnectionValidator::slotNoStatusFound(QNetworkReply *reply) { // ### TODO _errors.append(tr("Unable to connect to %1").arg(_account->url().toString())); - _errors.append( errStr ); - _networkError = (error != QNetworkReply::NoError); + _errors.append( reply->errorString() ); + _networkError = (reply->error() != QNetworkReply::NoError); emit connectionResult( StatusNotFound ); } @@ -133,22 +132,21 @@ void ConnectionValidator::slotCheckAuthentication() // continue in slotAuthCheck here :-) PropfindJob *propFind = new PropfindJob(_account, "/", QList() << "getlastmodified", this); connect(propFind, SIGNAL(result(QVariantMap)), SLOT(slotAuthSuccess())); - connect(propFind, SIGNAL(networkError(QNetworkReply::NetworkError, QString)), - SLOT(slotAuthFailed(QNetworkReply::NetworkError, QString))); + connect(propFind, SIGNAL(networkError(QNetworkReply*)), SLOT(slotAuthFailed(QNetworkReply*))); qDebug() << "# checking for authentication settings."; } -void ConnectionValidator::slotAuthFailed(QNetworkReply::NetworkError error, const QString& errString) +void ConnectionValidator::slotAuthFailed(QNetworkReply *reply) { Status stat = StatusNotFound; - if( error == QNetworkReply::AuthenticationRequiredError || - error == QNetworkReply::OperationCanceledError ) { // returned if the user is wrong. + if( reply->error() == QNetworkReply::AuthenticationRequiredError || + reply->error() == QNetworkReply::OperationCanceledError ) { // returned if the user is wrong. qDebug() << "******** Password is wrong!"; _errors << tr("The provided credentials are not correct"); stat = CredentialsWrong; - } else if( error != QNetworkReply::NoError ) { - _errors << errString; + } else if( reply->error() != QNetworkReply::NoError ) { + _errors << reply->errorString(); } emit connectionResult( stat ); diff --git a/src/mirall/connectionvalidator.h b/src/mirall/connectionvalidator.h index 3ac935c66..abd84d742 100644 --- a/src/mirall/connectionvalidator.h +++ b/src/mirall/connectionvalidator.h @@ -58,11 +58,11 @@ signals: public slots: protected slots: - void slotStatusFound( const QVariantMap &info ); - void slotNoStatusFound(QNetworkReply::NetworkError error, const QString& errString); + void slotStatusFound(const QUrl&url, const QVariantMap &info); + void slotNoStatusFound(QNetworkReply *reply); void slotCheckAuthentication(); - void slotAuthFailed(QNetworkReply::NetworkError error, const QString& errString); + void slotAuthFailed(QNetworkReply *reply); void slotAuthSuccess(); private: diff --git a/src/mirall/folderwizard.cpp b/src/mirall/folderwizard.cpp index 62b92e12a..b297c68b7 100644 --- a/src/mirall/folderwizard.cpp +++ b/src/mirall/folderwizard.cpp @@ -206,8 +206,7 @@ void FolderWizardTargetPage::slotCreateRemoteFolder(QString folder) MkColJob *job = new MkColJob(AccountManager::instance()->account(), folder, this); /* check the owncloud configuration file and query the ownCloud */ connect(job, SIGNAL(finished()), SLOT(slotCreateRemoteFolderFinished())); - connect(job, SIGNAL(networkError(QNetworkReply::NetworkError,QString)), - SLOT(slotHandleNetworkError(QNetworkReply::NetworkError,QString))); + connect(job, SIGNAL(networkError(QNetworkReply*)), SLOT(slotHandleNetworkError(QNetworkReply*))); } void FolderWizardTargetPage::slotCreateRemoteFolderFinished() @@ -217,9 +216,9 @@ void FolderWizardTargetPage::slotCreateRemoteFolderFinished() slotRefreshFolders(); } -void FolderWizardTargetPage::slotHandleNetworkError(QNetworkReply::NetworkError, const QString& error) +void FolderWizardTargetPage::slotHandleNetworkError(QNetworkReply *reply) { - qDebug() << "** webdav mkdir request failed:" << error; + qDebug() << "** webdav mkdir request failed:" << reply->error(); showWarn(tr("Failed to create the folder on %1.
Please check manually.") .arg(Theme::instance()->appNameGUI())); } diff --git a/src/mirall/folderwizard.h b/src/mirall/folderwizard.h index 6d44c60c1..3a740e2ca 100644 --- a/src/mirall/folderwizard.h +++ b/src/mirall/folderwizard.h @@ -77,7 +77,7 @@ protected slots: void slotAddRemoteFolder(); void slotCreateRemoteFolder(QString); void slotCreateRemoteFolderFinished(); - void slotHandleNetworkError(QNetworkReply::NetworkError, const QString& error); + void slotHandleNetworkError(QNetworkReply*); void slotUpdateDirectories(QStringList); void slotRefreshFolders(); void slotItemExpanded(QTreeWidgetItem*); diff --git a/src/mirall/networkjobs.cpp b/src/mirall/networkjobs.cpp index 9f7204782..5e76852f3 100644 --- a/src/mirall/networkjobs.cpp +++ b/src/mirall/networkjobs.cpp @@ -15,6 +15,8 @@ #include #include +#include +#include #include #include #include @@ -28,6 +30,8 @@ #include "mirall/networkjobs.h" #include "mirall/account.h" +#include "creds/credentialsfactory.h" + namespace Mirall { AbstractNetworkJob::AbstractNetworkJob(Account *account, const QString &path, QObject *parent) @@ -40,16 +44,12 @@ AbstractNetworkJob::AbstractNetworkJob(Account *account, const QString &path, QO void AbstractNetworkJob::setReply(QNetworkReply *reply) { + if (_reply) { + _reply->deleteLater(); + } _reply = reply; } -QNetworkReply *AbstractNetworkJob::takeReply() -{ - QNetworkReply *reply = _reply; - _reply = 0; - return reply; -} - void AbstractNetworkJob::setAccount(Account *account) { _account = account; @@ -63,18 +63,15 @@ void AbstractNetworkJob::setPath(const QString &path) void AbstractNetworkJob::slotError() { qDebug() << metaObject()->className() << "Error:" << _reply->errorString(); - emit networkError(_reply->error(), _reply->errorString()); + emit networkError(_reply); deleteLater(); } void AbstractNetworkJob::setupConnections(QNetworkReply *reply) { - connect( reply, SIGNAL( finished()), SLOT(slotFinished()) ); - connect( reply, SIGNAL(error(QNetworkReply::NetworkError)), - this, SLOT(slotError())); - -// connect( reply, SIGNAL(error(QNetworkReply::NetworkError)), -// ownCloudInfo::instance(), SLOT(slotError(QNetworkReply::NetworkError))); + connect(reply, SIGNAL(finished()), SLOT(slotFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(slotError())); } QNetworkReply* AbstractNetworkJob::davRequest(const QByteArray &verb, const QString &relPath, @@ -83,11 +80,31 @@ QNetworkReply* AbstractNetworkJob::davRequest(const QByteArray &verb, const QStr return _account->davRequest(verb, relPath, req, data); } +QNetworkReply *AbstractNetworkJob::davRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data) +{ + return _account->davRequest(verb, url, req, data); +} + QNetworkReply* AbstractNetworkJob::getRequest(const QString &relPath) { return _account->getRequest(relPath); } +QNetworkReply *AbstractNetworkJob::getRequest(const QUrl &url) +{ + return _account->getRequest(url); +} + +QNetworkReply *AbstractNetworkJob::headRequest(const QString &relPath) +{ + return _account->headRequest(relPath); +} + +QNetworkReply *AbstractNetworkJob::headRequest(const QUrl &url) +{ + return _account->headRequest(url); +} + AbstractNetworkJob::~AbstractNetworkJob() { _reply->deleteLater(); } @@ -161,9 +178,7 @@ MkColJob::MkColJob(Account *account, const QString &path, QObject *parent) void MkColJob::slotFinished() { - // ### useful error handling? - // QNetworkReply *reply = qobject_cast(sender()); - emit finished(); + emit finished(reply()->error()); deleteLater(); } @@ -222,7 +237,7 @@ void LsColJob::slotFinished() /*********************************************************************************************/ CheckServerJob::CheckServerJob(Account *account, bool followRedirect, QObject *parent) - : AbstractNetworkJob(account, QLatin1String("/status.php") , parent) + : AbstractNetworkJob(account, QLatin1String("status.php") , parent) , _followRedirects(followRedirect) , _redirectCount(0) { @@ -251,7 +266,7 @@ void CheckServerJob::slotFinished() // ### this should no longer be needed if( reply()->error() == QNetworkReply::NoError && reply()->size() == 0 ) { // This seems to be a bit strange behaviour of QNetworkAccessManager. - // It calls the finised slot multiple times but only the first read wins. + // It calls the finished slot multiple times but only the first read wins. // That happend when the code connected the finished signal of the manager. // It did not happen when the code connected to the reply finish signal. qDebug() << "WRN: NetworkReply with not content but also no error! " << reply(); @@ -270,12 +285,10 @@ void CheckServerJob::slotFinished() if (requestedUrl.scheme() == QLatin1String("https") && redirectUrl.scheme() == QLatin1String("http")) { qDebug() << Q_FUNC_INFO << "HTTPS->HTTP downgrade detected!"; - } else if (requestedUrl == redirectUrl || _redirectCount >= MAX_REDIRECTS) { + } else if (requestedUrl == redirectUrl || _redirectCount >= maxRedirects()) { qDebug() << Q_FUNC_INFO << "Redirect loop detected!"; } else { - takeReply()->deleteLater(); - // ### FIXME - //setReply(getRequest(redirectUrl)); + setReply(getRequest(redirectUrl)); setupConnections(reply()); return; } @@ -292,7 +305,7 @@ void CheckServerJob::slotFinished() if( status.contains("installed") && status.contains("version") && status.contains("versionstring") ) { - emit instanceFound(status); + emit instanceFound(reply()->url(), status); } else { qDebug() << "No proper answer on " << requestedUrl; } @@ -366,4 +379,16 @@ void PropfindJob::slotFinished() deleteLater(); } +EntityExistsJob::EntityExistsJob(Account *account, const QString &path, QObject *parent) + : AbstractNetworkJob(account, path, parent) +{ + setReply(headRequest(path)); + setupConnections(reply()); +} + +void EntityExistsJob::slotFinished() +{ + emit exists(reply()); +} + } // namespace Mirall diff --git a/src/mirall/networkjobs.h b/src/mirall/networkjobs.h index 4d850abab..796584143 100644 --- a/src/mirall/networkjobs.h +++ b/src/mirall/networkjobs.h @@ -17,14 +17,15 @@ #define NETWORKJOBS_H #include +#include #include -class QNetworkReply; class QUrl; namespace Mirall { class Account; +class AbstractSslErrorHandler; /** * @brief The AbstractNetworkJob class @@ -42,17 +43,23 @@ public: void setReply(QNetworkReply *reply); QNetworkReply* reply() const { return _reply; } - QNetworkReply* takeReply(); // for redirect handling signals: - void networkError(QNetworkReply::NetworkError, const QString& errorString); - + void networkError(QNetworkReply *reply); protected: void setupConnections(QNetworkReply *reply); QNetworkReply* davRequest(const QByteArray& verb, const QString &relPath, QNetworkRequest req = QNetworkRequest(), QIODevice *data = 0); + QNetworkReply* davRequest(const QByteArray& verb, const QUrl &url, + QNetworkRequest req = QNetworkRequest(), + QIODevice *data = 0); QNetworkReply* getRequest(const QString &relPath); + QNetworkReply* getRequest(const QUrl &url); + QNetworkReply* headRequest(const QString &relPath); + QNetworkReply* headRequest(const QUrl &url); + + int maxRedirects() const { return 10; } private slots: virtual void slotFinished() = 0; @@ -64,6 +71,20 @@ private: QString _path; }; +/** + * @brief The EntityExistsJob class + */ +class EntityExistsJob : public AbstractNetworkJob { + Q_OBJECT +public: + explicit EntityExistsJob(Account *account, const QString &path, QObject* parent = 0); +signals: + void exists(QNetworkReply*); + +private slots: + virtual void slotFinished(); +}; + /** * @brief The LsColJob class */ @@ -74,7 +95,6 @@ public: signals: void directoryListing(const QStringList &items); - void networkError(); private slots: virtual void slotFinished(); @@ -106,8 +126,7 @@ public: explicit MkColJob(Account *account, const QString &path, QObject *parent = 0); signals: - void finished(); - void networkError(); + void finished(QNetworkReply::NetworkError); private slots: virtual void slotFinished(); @@ -126,8 +145,7 @@ public: static bool installed(const QVariantMap &info); signals: - void instanceFound(const QVariantMap &info); - void networkError(); + void instanceFound(const QUrl&url, const QVariantMap &info); private slots: virtual void slotFinished(); @@ -135,8 +153,6 @@ private slots: private: bool _followRedirects; bool _redirectCount; - - static const int MAX_REDIRECTS = 10; }; diff --git a/src/mirall/owncloudgui.cpp b/src/mirall/owncloudgui.cpp index 0e2d78aba..d60fe8c3f 100644 --- a/src/mirall/owncloudgui.cpp +++ b/src/mirall/owncloudgui.cpp @@ -91,8 +91,7 @@ bool ownCloudGui::checkConfigExists(bool openSettings) return true; } else { qDebug() << "No configured folders yet, starting setup wizard"; - //### TODO - //OwncloudSetupWizard::runWizard(this, SLOT(slotownCloudWizardDone(int))); + OwncloudSetupWizard::runWizard(this, SLOT(slotownCloudWizardDone(int))); return false; } } diff --git a/src/mirall/owncloudsetupwizard.cpp b/src/mirall/owncloudsetupwizard.cpp index 6413d3aa2..e6fa8f5f1 100644 --- a/src/mirall/owncloudsetupwizard.cpp +++ b/src/mirall/owncloudsetupwizard.cpp @@ -28,7 +28,9 @@ #include "mirall/mirallaccessmanager.h" #include "mirall/account.h" #include "mirall/networkjobs.h" +#include "mirall/sslerrordialog.h" +#include "creds/credentialsfactory.h" #include "creds/abstractcredentials.h" #include "creds/dummycredentials.h" @@ -36,11 +38,8 @@ namespace Mirall { OwncloudSetupWizard::OwncloudSetupWizard(QObject* parent) : QObject( parent ), + _account(0), _ocWizard(new OwncloudWizard), - _mkdirRequestReply(), - _checkInstallationRequest(), - _checkRemoteFolderRequest(), - _configHandle(), _remoteFolder() { connect( _ocWizard, SIGNAL(determineAuthType(const QString&)), @@ -80,24 +79,15 @@ void OwncloudSetupWizard::runWizard(QObject* obj, const char* amember, QWidget * void OwncloudSetupWizard::startWizard() { - // Set useful default values. - MirallConfigFile cfgFile; - Account *account = AccountManager::instance()->account(); - - _ocWizard->setConfigExists( account != 0 ); - // Fill the entry fields with existing values. - QString url = account->url(); - //QString user = cfgFile.ownCloudUser(); - bool configExists = !( url.isEmpty()/* || user.isEmpty()*/ ); - - if( !url.isEmpty() ) { - _ocWizard->setOCUrl( url ); + if (!account) { + account = new Account(new SslDialogErrorHandler); + account->setCredentials(CredentialsFactory::create("dummy")); } + _ocWizard->setAccount(account); _remoteFolder = Theme::instance()->defaultServerFolder(); // remoteFolder may be empty, which means / - QString localFolder = Theme::instance()->defaultClientFolder(); // if its a relative path, prepend with users home dir, otherwise use as absolute path @@ -118,184 +108,62 @@ void OwncloudSetupWizard::startWizard() _ocWizard->raise(); } -void OwncloudSetupWizard::slotDetermineAuthType(const QString& serverUrl) +// also checks if an installation is valid and determines auth type in a second step +void OwncloudSetupWizard::slotDetermineAuthType(const QString &urlString) { - 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(); - - // remove a possibly existing custom config. - if( ! _configHandle.isEmpty() ) { - // remove the old config file. - MirallConfigFile oldConfig( _configHandle ); - oldConfig.cleanupCustomConfig(); - } - - _configHandle = now.toString(QLatin1String("MMddyyhhmmss")); - - MirallConfigFile cfgFile( _configHandle, true ); - 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(); - 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."; + QString fixedUrl = urlString; + QUrl url = QUrl::fromUserInput(fixedUrl); + // fromUserInput defaults to http, not http if no scheme is specified + if (!fixedUrl.startsWith("http://") || !fixedUrl.startsWith("https://")) { + url.setScheme("https"); } + Account *account = _ocWizard->account(); + account->setUrl(url); + CheckServerJob *job = new CheckServerJob(_ocWizard->account(), false, this); + connect(job, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotOwnCloudFoundAuth(QUrl,QVariantMap))); + connect(job, SIGNAL(networkError(QNetworkReply*)), SLOT(slotNoOwnCloudFoundAuth(QNetworkReply*))); } -void OwncloudSetupWizard::slotOwnCloudFoundAuth( const QString& url, const QString& infoString, const QString& version, const QString& ) +void OwncloudSetupWizard::slotOwnCloudFoundAuth(const QUrl& url, const QVariantMap &info) { - 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("Successfully connected to %1: %2 version %3 (%4)

") - .arg( url ).arg(Theme::instance()->appNameGUI()).arg(infoString).arg(version)); + .arg(url.toString()) + .arg(Theme::instance()->appNameGUI()) + .arg(CheckServerJob::versionString(info)) + .arg(CheckServerJob::version(info))); - 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)); + DetermineAuthTypeJob *job = new DetermineAuthTypeJob(_ocWizard->account(), this); + connect(job, SIGNAL(authType(WizardCommon::AuthType)), + _ocWizard, SLOT(setAuthType(WizardCommon::AuthType))); } -void OwncloudSetupWizard::slotAuthCheckReplyFinished() +void OwncloudSetupWizard::slotNoOwnCloudFoundAuth(QNetworkReply *reply) { - 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:
%2"). - arg(Theme::instance()->appNameGUI()).arg(err->errorString())); - - // remove the config file again - MirallConfigFile cfgFile( _configHandle ); - cfgFile.cleanupCustomConfig(); + _ocWizard->displayError(tr("Failed to connect to %1 at %2:
%3") + .arg(Theme::instance()->appNameGUI()) + .arg(reply->url().toString()) + .arg(reply->errorString())); } void OwncloudSetupWizard::slotConnectToOCUrl( const QString& url ) { qDebug() << "Connect to url: " << url; + _ocWizard->account()->setCredentials(_ocWizard->getCredentials()); _ocWizard->setField(QLatin1String("OCUrl"), url ); _ocWizard->appendToConfigurationLog(tr("Trying to connect to %1 at %2...") .arg( Theme::instance()->appNameGUI() ).arg(url) ); + testOwnCloudConnect(); } void OwncloudSetupWizard::testOwnCloudConnect() { - // write a temporary config. - QDateTime now = QDateTime::currentDateTime(); - - if( _configHandle.isEmpty() ) { - _configHandle = now.toString(QLatin1String("MMddyyhhmmss")); - } - - MirallConfigFile cfgFile( _configHandle, true ); - QString url = _ocWizard->field(QLatin1String("OCUrl")).toString(); - 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, - _ocWizard->getCredentials()); - - ownCloudInfo* info(ownCloudInfo::instance()); - info->setCustomConfigHandle( _configHandle ); - // 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() ); - } - - 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 + ValidateDavAuthJob *job = new ValidateDavAuthJob(_ocWizard->account(), this); + connect(job, SIGNAL(authResult(QNetworkReply*)), SLOT(slotConnectionCheck(QNetworkReply*))); } -void OwncloudSetupWizard::slotConnectionCheck(const QString&, QNetworkReply* reply) +void OwncloudSetupWizard::slotConnectionCheck(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: @@ -312,8 +180,6 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFo { qDebug() << "Setup local sync folder for new oC connection " << 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 @@ -325,38 +191,20 @@ void OwncloudSetupWizard::slotCreateLocalAndRemoteFolders(const QString& localFo Utility::setupFavLink( localFolder ); // FIXME: Create a local sync folder. res += tr("ok"); + EntityExistsJob *job = new EntityExistsJob(_ocWizard->account(), remoteFolder, this); + connect(job, SIGNAL(exists(QNetworkReply*)), SLOT(slotAuthCheckReply(QNetworkReply*))); } else { res += tr("failed."); qDebug() << "Failed to create " << fi.path(); - localFolderOk = false; _ocWizard->displayError(tr("Could not create local folder %1").arg(localFolder)); } _ocWizard->appendToConfigurationLog( res ); } - - if( localFolderOk ) { - checkRemoteFolder(remoteFolder); - } } -void OwncloudSetupWizard::checkRemoteFolder(const QString& remoteFolder) +// ### TODO move into EntityExistsJob once we decide if/how to return gui strings from jobs +void OwncloudSetupWizard::slotAuthCheckReply(QNetworkReply *reply) { - ownCloudInfo* info(ownCloudInfo::instance()); - connect( info,SIGNAL(ownCloudDirExists(QString,QNetworkReply*)), - this,SLOT(slotAuthCheckReply(QString,QNetworkReply*))); - - qDebug() << "# checking for existence of remote folder."; - info->setCustomConfigHandle(_configHandle); - _checkRemoteFolderRequest = info->getWebDAVPath(remoteFolder); // this call needs to be authenticated. - // continue in slotAuthCheckReply -} - -void OwncloudSetupWizard::slotAuthCheckReply( const QString&, QNetworkReply *reply ) -{ - // disconnect from ownCloud Info signals - disconnect( ownCloudInfo::instance(),SIGNAL(ownCloudDirExists(QString,QNetworkReply*)), - this,SLOT(slotAuthCheckReply(QString,QNetworkReply*))); - bool ok = true; QString error; QNetworkReply::NetworkError errId = reply->error(); @@ -364,11 +212,11 @@ void OwncloudSetupWizard::slotAuthCheckReply( const QString&, QNetworkReply *rep if( errId == QNetworkReply::NoError ) { qDebug() << "******** Remote folder found, all cool!"; } else if( errId == QNetworkReply::ContentNotFoundError ) { - if( createRemoteFolder() ) { - return; // Finish here, the mkdir request will go on. - } else { - error = tr("The remote folder could not be accessed!"); + if( _remoteFolder.isEmpty() ) { + error = tr("No remote folder specified!"); ok = false; + } else { + createRemoteFolder(); } } else { error = tr("Error: %1").arg(reply->errorString()); @@ -382,25 +230,19 @@ void OwncloudSetupWizard::slotAuthCheckReply( const QString&, QNetworkReply *rep finalizeSetup( ok ); } -bool OwncloudSetupWizard::createRemoteFolder() +void OwncloudSetupWizard::createRemoteFolder() { - if( _remoteFolder.isEmpty() ) return false; - _ocWizard->appendToConfigurationLog( tr("creating folder on ownCloud: %1" ).arg( _remoteFolder )); - ownCloudInfo* info(ownCloudInfo::instance()); - connect(info, SIGNAL(webdavColCreated(QNetworkReply::NetworkError)), - this, SLOT(slotCreateRemoteFolderFinished(QNetworkReply::NetworkError))); - _mkdirRequestReply = info->mkdirRequest( _remoteFolder ); - - return (_mkdirRequestReply != NULL); + MkColJob *job = new MkColJob(_ocWizard->account(), _remoteFolder, this); + connect(job, SIGNAL(finished(QNetworkReply::NetworkError)), SLOT(slotCreateRemoteFolderFinished(QNetworkReply::NetworkError))); } void OwncloudSetupWizard::slotCreateRemoteFolderFinished( QNetworkReply::NetworkError error ) { qDebug() << "** webdav mkdir request finished " << error; - disconnect(ownCloudInfo::instance(), SIGNAL(webdavColCreated(QNetworkReply::NetworkError)), - this, SLOT(slotCreateRemoteFolderFinished(QNetworkReply::NetworkError))); +// disconnect(ownCloudInfo::instance(), SIGNAL(webdavColCreated(QNetworkReply::NetworkError)), +// this, SLOT(slotCreateRemoteFolderFinished(QNetworkReply::NetworkError))); bool success = true; @@ -459,7 +301,7 @@ void OwncloudSetupWizard::finalizeSetup( bool success ) // accept the custom config to be the main one if Accepted. void OwncloudSetupWizard::slotAssistantFinished( int result ) { - MirallConfigFile cfg( _configHandle ); + MirallConfigFile cfg; FolderMan *folderMan = FolderMan::instance(); if( result == QDialog::Rejected ) { @@ -535,29 +377,63 @@ void OwncloudSetupWizard::slotAssistantFinished( int result ) } } - // clear the custom config handle - _configHandle.clear(); - ownCloudInfo::instance()->setCustomConfigHandle( QString::null ); +// // clear the custom config handle +// _configHandle.clear(); +// ownCloudInfo::instance()->setCustomConfigHandle( QString::null ); // notify others. emit ownCloudWizardDone( result ); } -void OwncloudSetupWizard::slotClearPendingRequests() +DetermineAuthTypeJob::DetermineAuthTypeJob(Account *account, QObject *parent) + : AbstractNetworkJob(account, QString(), parent) + , _redirects(0) { - qDebug() << "Pending request: " << _mkdirRequestReply; - if( _mkdirRequestReply && _mkdirRequestReply->isRunning() ) { - qDebug() << "ABORTing pending mkdir request."; - _mkdirRequestReply->abort(); + QNetworkReply *reply = getRequest(Account::davPath()); + setReply(reply); + setupConnections(reply); +} + +void DetermineAuthTypeJob::slotFinished() +{ + QUrl redirection = reply()->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); + if (_redirects >= maxRedirects()) { + redirection.clear(); } - 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(); + if ((reply()->error() == QNetworkReply::AuthenticationRequiredError) || redirection.isEmpty()) { + emit authType(WizardCommon::HttpCreds); + } else if (redirection.toString().endsWith(Account::davPath())) { + // do a new run + _redirects++; + setReply(getRequest(redirection)); + setupConnections(reply()); + } else { + QRegExp shibbolethyWords("SAML|wayf"); + + shibbolethyWords.setCaseSensitivity(Qt::CaseInsensitive); + if (redirection.toString().contains(shibbolethyWords)) { + emit authType(WizardCommon::Shibboleth); + } else { + // TODO: Send an error. + // eh? + emit authType(WizardCommon::HttpCreds); + } } + deleteLater(); +} + +ValidateDavAuthJob::ValidateDavAuthJob(Account *account, QObject *parent) + : AbstractNetworkJob(account, QString(), parent) +{ + QNetworkReply *reply = getRequest(Account::davPath()); + setReply(reply); + setupConnections(reply); +} + +void ValidateDavAuthJob::slotFinished() +{ + emit authResult(reply()); + deleteLater(); } } // ns Mirall diff --git a/src/mirall/owncloudsetupwizard.h b/src/mirall/owncloudsetupwizard.h index 2fe1acf4b..440f32a79 100644 --- a/src/mirall/owncloudsetupwizard.h +++ b/src/mirall/owncloudsetupwizard.h @@ -22,10 +22,37 @@ #include #include "mirall/theme.h" +#include "mirall/networkjobs.h" + +#include "wizard/owncloudwizardcommon.h" namespace Mirall { class OwncloudWizard; +class Account; + +class ValidateDavAuthJob : public AbstractNetworkJob { + Q_OBJECT +public: + ValidateDavAuthJob(Account* account, QObject *parent = 0); +signals: + void authResult(QNetworkReply*); +private slots: + void slotFinished(); +}; + +class DetermineAuthTypeJob : public AbstractNetworkJob { + Q_OBJECT +public: + explicit DetermineAuthTypeJob(Account *account, QObject *parent = 0); +signals: + void authType(WizardCommon::AuthType); +private slots: + void slotFinished(); +private: + int _redirects; +}; + class OwncloudSetupWizard : public QObject { @@ -40,18 +67,16 @@ signals: private slots: void slotDetermineAuthType(const QString&); - void slotOwnCloudFoundAuth(const QString&, const QString&, const QString&, const QString&); - void slotAuthCheckReplyFinished(); - void slotNoOwnCloudFoundAuth(QNetworkReply*); + void slotOwnCloudFoundAuth(const QUrl&, const QVariantMap&); + void slotNoOwnCloudFoundAuth(QNetworkReply *reply); void slotConnectToOCUrl(const QString&); - void slotConnectionCheck(const QString&, QNetworkReply*); + void slotConnectionCheck(QNetworkReply*); void slotCreateLocalAndRemoteFolders(const QString&, const QString&); - void slotAuthCheckReply(const QString&, QNetworkReply*); + void slotAuthCheckReply(QNetworkReply*); void slotCreateRemoteFolderFinished(QNetworkReply::NetworkError); void slotAssistantFinished( int ); - void slotClearPendingRequests(); private: explicit OwncloudSetupWizard(QObject *parent = 0 ); @@ -59,16 +84,13 @@ private: void startWizard(); void testOwnCloudConnect(); - void checkRemoteFolder(const QString& remoteFolder); - bool createRemoteFolder(); + void createRemoteFolder(); void finalizeSetup( bool ); + Account* _account; OwncloudWizard* _ocWizard; - QPointer _mkdirRequestReply; - QPointer _checkInstallationRequest; - QPointer _checkRemoteFolderRequest; - QString _configHandle; QString _remoteFolder; + }; } diff --git a/src/wizard/owncloudwizard.cpp b/src/wizard/owncloudwizard.cpp index 75927dd24..1202240a6 100644 --- a/src/wizard/owncloudwizard.cpp +++ b/src/wizard/owncloudwizard.cpp @@ -14,9 +14,11 @@ * for more details. */ -#include "wizard/owncloudwizard.h" +#include "mirall/account.h" #include "mirall/mirallconfigfile.h" #include "mirall/theme.h" + +#include "wizard/owncloudwizard.h" #include "wizard/owncloudsetuppage.h" #include "wizard/owncloudhttpcredspage.h" #include "wizard/owncloudshibbolethcredspage.h" @@ -77,6 +79,16 @@ OwncloudWizard::OwncloudWizard(QWidget *parent) setSubTitleFormat(Qt::RichText); } +void OwncloudWizard::setAccount(Account *account) +{ + _account = account; +} + +Account *OwncloudWizard::account() const +{ + return _account; +} + void OwncloudWizard::setMultipleFoldersExist(bool exist) { _advancedSetupPage->setMultipleFoldersExist(exist); diff --git a/src/wizard/owncloudwizard.h b/src/wizard/owncloudwizard.h index 81e006cdf..890fec473 100644 --- a/src/wizard/owncloudwizard.h +++ b/src/wizard/owncloudwizard.h @@ -23,6 +23,7 @@ namespace Mirall { +class Account; class OwncloudSetupPage; class OwncloudHttpCredsPage; class OwncloudShibbolethCredsPage; @@ -43,6 +44,8 @@ public: OwncloudWizard(QWidget *parent = 0); + void setAccount(Account *account); + Account* account() const; void setOCUrl( const QString& ); void setupCustomMedia( QVariant, QLabel* ); @@ -56,10 +59,10 @@ public: void setConfigExists( bool ); bool configExists(); void successfulStep(); - void setAuthType(WizardCommon::AuthType type); AbstractCredentials* getCredentials() const; public slots: + void setAuthType(WizardCommon::AuthType type); void setRemoteFolder( const QString& ); void appendToConfigurationLog( const QString& msg, LogType type = LogParagraph ); void slotCurrentPageChanged( int ); @@ -73,6 +76,7 @@ signals: void basicSetupFinished( int ); private: + Account* _account; OwncloudSetupPage* _setupPage; OwncloudHttpCredsPage* _httpCredsPage; OwncloudShibbolethCredsPage* _shibbolethCredsPage;