System proxy: Ask for credentials if needed.

The proxyAuthenticationRequired() signal now goes to the
ProxyAuthHandler class. That class will try to read the proxy settings
from the keychain or ask the user about them.

We won't ask the user for credentials for explicitly configured proxies.
It also does not change how the credentials for explicitly configured
proxies are stored. (see #261)
This commit is contained in:
Christian Kamm 2015-07-16 14:21:51 +02:00
parent 944564258c
commit 2124098f84
16 changed files with 602 additions and 43 deletions

View file

@ -26,6 +26,7 @@ set(client_UI
sslerrordialog.ui sslerrordialog.ui
owncloudsetuppage.ui owncloudsetuppage.ui
addcertificatedialog.ui addcertificatedialog.ui
proxyauthdialog.ui
wizard/owncloudadvancedsetuppage.ui wizard/owncloudadvancedsetuppage.ui
wizard/owncloudconnectionmethoddialog.ui wizard/owncloudconnectionmethoddialog.ui
wizard/owncloudhttpcredspage.ui wizard/owncloudhttpcredspage.ui
@ -66,6 +67,8 @@ set(client_SRCS
accountstate.cpp accountstate.cpp
addcertificatedialog.cpp addcertificatedialog.cpp
authenticationdialog.cpp authenticationdialog.cpp
proxyauthhandler.cpp
proxyauthdialog.cpp
creds/credentialsfactory.cpp creds/credentialsfactory.cpp
creds/httpcredentialsgui.cpp creds/httpcredentialsgui.cpp
creds/shibbolethcredentials.cpp creds/shibbolethcredentials.cpp

View file

@ -13,6 +13,7 @@
#include "accountmanager.h" #include "accountmanager.h"
#include "sslerrordialog.h" #include "sslerrordialog.h"
#include "proxyauthhandler.h"
#include <theme.h> #include <theme.h>
#include <creds/credentialsfactory.h> #include <creds/credentialsfactory.h>
#include <creds/abstractcredentials.h> #include <creds/abstractcredentials.h>
@ -168,7 +169,7 @@ void AccountManager::save(const AccountPtr& acc, QSettings& settings)
AccountPtr AccountManager::load(QSettings& settings) AccountPtr AccountManager::load(QSettings& settings)
{ {
auto acc = Account::create(); auto acc = createAccount();
acc->setUrl(settings.value(QLatin1String(urlC)).toUrl()); acc->setUrl(settings.value(QLatin1String(urlC)).toUrl());
@ -186,7 +187,6 @@ AccountPtr AccountManager::load(QSettings& settings)
// now the cert, it is in the general group // now the cert, it is in the general group
settings.beginGroup(QLatin1String("General")); settings.beginGroup(QLatin1String("General"));
acc->setApprovedCerts(QSslCertificate::fromData(settings.value(caCertsKeyC).toByteArray())); acc->setApprovedCerts(QSslCertificate::fromData(settings.value(caCertsKeyC).toByteArray()));
acc->setSslErrorHandler(new SslDialogErrorHandler);
settings.endGroup(); settings.endGroup();
return acc; return acc;
@ -219,6 +219,15 @@ void AccountManager::deleteAccount(AccountState* account)
emit accountRemoved(account); emit accountRemoved(account);
} }
AccountPtr AccountManager::createAccount()
{
AccountPtr acc = Account::create();
acc->setSslErrorHandler(new SslDialogErrorHandler);
connect(acc.data(), SIGNAL(proxyAuthenticationRequired(QNetworkProxy, QAuthenticator*)),
ProxyAuthHandler::instance(), SLOT(handleProxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
return acc;
}
void AccountManager::shutdown() void AccountManager::shutdown()
{ {

View file

@ -64,6 +64,12 @@ public:
void deleteAccount(AccountState *account); void deleteAccount(AccountState *account);
/**
* Creates an account and sets up some basic handlers.
* Does *not* add the account to the account manager just yet.
*/
static AccountPtr createAccount();
private: private:
void save(const AccountPtr& account, QSettings& settings); void save(const AccountPtr& account, QSettings& settings);
AccountPtr load(QSettings& settings); AccountPtr load(QSettings& settings);

View file

@ -63,6 +63,7 @@ NetworkSettings::NetworkSettings(QWidget *parent) :
connect(_ui->userLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings())); connect(_ui->userLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
connect(_ui->passwordLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings())); connect(_ui->passwordLineEdit, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
connect(_ui->portSpinBox, SIGNAL(editingFinished()), SLOT(saveProxySettings())); connect(_ui->portSpinBox, SIGNAL(editingFinished()), SLOT(saveProxySettings()));
connect(_ui->authRequiredcheckBox, SIGNAL(toggled(bool)), SLOT(saveProxySettings()));
connect(_ui->uploadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings())); connect(_ui->uploadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
connect(_ui->noUploadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings())); connect(_ui->noUploadLimitRadioButton, SIGNAL(clicked()), SLOT(saveBWLimitSettings()));
@ -105,13 +106,10 @@ void NetworkSettings::loadProxySettings()
if (port == 0) if (port == 0)
port = 8080; port = 8080;
_ui->portSpinBox->setValue(port); _ui->portSpinBox->setValue(port);
if (!cfgFile.proxyUser().isEmpty()) _ui->authRequiredcheckBox->setChecked(cfgFile.proxyNeedsAuth());
{
_ui->authRequiredcheckBox->setChecked(true);
_ui->userLineEdit->setText(cfgFile.proxyUser()); _ui->userLineEdit->setText(cfgFile.proxyUser());
_ui->passwordLineEdit->setText(cfgFile.proxyPassword()); _ui->passwordLineEdit->setText(cfgFile.proxyPassword());
} }
}
void NetworkSettings::loadBWLimitSettings() void NetworkSettings::loadBWLimitSettings()
{ {

View file

@ -103,9 +103,6 @@
</item> </item>
<item> <item>
<widget class="QSpinBox" name="portSpinBox"> <widget class="QSpinBox" name="portSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed"> <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -155,9 +152,6 @@
</property> </property>
<item> <item>
<widget class="QLineEdit" name="userLineEdit"> <widget class="QLineEdit" name="userLineEdit">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -165,9 +159,6 @@
</item> </item>
<item> <item>
<widget class="QLineEdit" name="passwordLineEdit"> <widget class="QLineEdit" name="passwordLineEdit">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>

View file

@ -78,10 +78,8 @@ void OwncloudSetupWizard::runWizard(QObject* obj, const char* amember, QWidget *
void OwncloudSetupWizard::startWizard() void OwncloudSetupWizard::startWizard()
{ {
FolderMan *folderMan = FolderMan::instance(); AccountPtr account = AccountManager::createAccount();
AccountPtr account = Account::create();
account->setCredentials(CredentialsFactory::create("dummy")); account->setCredentials(CredentialsFactory::create("dummy"));
account->setSslErrorHandler(new SslDialogErrorHandler);
_ocWizard->setAccount(account); _ocWizard->setAccount(account);
_ocWizard->setOCUrl(account->url().toString()); _ocWizard->setOCUrl(account->url().toString());

View file

@ -0,0 +1,52 @@
/*
* Copyright (C) 2015 by Christian Kamm <kamm@incasoftware.de>
*
* 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 "proxyauthdialog.h"
#include "ui_proxyauthdialog.h"
namespace OCC {
ProxyAuthDialog::ProxyAuthDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ProxyAuthDialog)
{
ui->setupUi(this);
}
ProxyAuthDialog::~ProxyAuthDialog()
{
delete ui;
}
void ProxyAuthDialog::setProxyAddress(const QString &address)
{
ui->proxyAddress->setText(address);
}
QString ProxyAuthDialog::username() const
{
return ui->usernameEdit->text();
}
QString ProxyAuthDialog::password() const
{
return ui->passwordEdit->text();
}
void ProxyAuthDialog::reset()
{
ui->usernameEdit->clear();
ui->passwordEdit->clear();
}
} // namespace OCC

52
src/gui/proxyauthdialog.h Normal file
View file

@ -0,0 +1,52 @@
/*
* Copyright (C) 2015 by Christian Kamm <kamm@incasoftware.de>
*
* 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 OCC_PROXYAUTHDIALOG_H
#define OCC_PROXYAUTHDIALOG_H
#include <QDialog>
namespace OCC {
namespace Ui {
class ProxyAuthDialog;
}
/**
* @brief Ask for username and password for a given proxy.
*
* Used by ProxyAuthHandler.
*/
class ProxyAuthDialog : public QDialog
{
Q_OBJECT
public:
explicit ProxyAuthDialog(QWidget *parent = 0);
~ProxyAuthDialog();
void setProxyAddress(const QString& address);
QString username() const;
QString password() const;
/// Resets the username and password.
void reset();
private:
Ui::ProxyAuthDialog *ui;
};
} // namespace OCC
#endif // OCC_PROXYAUTHDIALOG_H

115
src/gui/proxyauthdialog.ui Normal file
View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OCC::ProxyAuthDialog</class>
<widget class="QDialog" name="OCC::ProxyAuthDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>351</width>
<height>141</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Proxy authentication required</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Username:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="usernameEdit"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Proxy:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label">
<property name="text">
<string>The proxy server needs a username and password.</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Password:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="passwordEdit">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="proxyAddress">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>OCC::ProxyAuthDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>OCC::ProxyAuthDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -0,0 +1,236 @@
/*
* Copyright (C) 2015 by Christian Kamm <kamm@incasoftware.de>
*
* 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 "proxyauthhandler.h"
#include "proxyauthdialog.h"
#include "theme.h"
#include "configfile.h"
#include <QApplication>
#include <keychain.h>
using namespace OCC;
ProxyAuthHandler* ProxyAuthHandler::instance()
{
static ProxyAuthHandler inst;
return &inst;
}
ProxyAuthHandler::ProxyAuthHandler()
: _blocked(false)
, _waitingForDialog(0)
, _waitingForKeychain(0)
, _keychainJobRunning(false)
{
_dialog = new ProxyAuthDialog();
_configFile.reset(new ConfigFile);
_settings.reset(new QSettings(_configFile->configFile(), QSettings::IniFormat));
_settings->beginGroup(QLatin1String("Proxy"));
_settings->beginGroup(QLatin1String("Credentials"));
}
ProxyAuthHandler::~ProxyAuthHandler()
{
delete _dialog;
}
void ProxyAuthHandler::handleProxyAuthenticationRequired(
const QNetworkProxy& proxy,
QAuthenticator* authenticator)
{
if (!_dialog) {
return;
}
QString key = QString::fromLatin1("%1:%2").arg(
proxy.hostName(), QString::number(proxy.port()));
// If the proxy server has changed, forget what we know.
if (key != _proxy) {
_proxy = key;
_username.clear();
_password.clear();
_blocked = false;
// If the user explicitly configured the proxy in the
// network settings, don't ask about it.
if (_configFile->proxyType() == QNetworkProxy::HttpProxy
|| _configFile->proxyType() == QNetworkProxy::Socks5Proxy) {
_blocked = true;
}
}
if (_blocked) {
return;
}
qDebug() << Q_FUNC_INFO << key << proxy.type() << authenticator->user();
// If we already had a username but auth still failed,
// invalidate the old credentials!
bool invalidated = false;
if (!authenticator->user().isEmpty() && !_waitingForDialog && !_waitingForKeychain) {
qDebug() << "invalidating old creds" << key;
_username.clear();
_password.clear();
invalidated = true;
}
if (_username.isEmpty() || _waitingForKeychain) {
if (invalidated || !getCredsFromKeychain()) {
if (getCredsFromDialog()) {
storeCredsInKeychain();
} else {
// dialog was cancelled, never ask for that proxy again
_blocked = true;
return;
}
}
}
qDebug() << "got creds for" << _proxy;
authenticator->setUser(_username);
authenticator->setPassword(_password);
}
void ProxyAuthHandler::slotKeychainJobDone()
{
_keychainJobRunning = false;
}
bool ProxyAuthHandler::getCredsFromDialog()
{
// Open the credentials dialog
if (!_waitingForDialog) {
_dialog->reset();
_dialog->setProxyAddress(_proxy);
_dialog->open();
}
// This function can be reentered while the dialog is open.
// If that's the case, continue processing the dialog until
// it's done.
++_waitingForDialog;
while (_dialog && _dialog->isVisible()) {
QApplication::processEvents(QEventLoop::ExcludeSocketNotifiers, 200);
}
--_waitingForDialog;
if (_dialog && _dialog->result() == QDialog::Accepted) {
qDebug() << "got creds for" << _proxy << "from dialog";
_username = _dialog->username();
_password = _dialog->password();
return true;
}
return false;
}
bool ProxyAuthHandler::getCredsFromKeychain()
{
using namespace QKeychain;
if (_waitingForDialog) {
return false;
}
qDebug() << "trying to load" << _proxy;
if (!_waitingForKeychain) {
_username = _settings->value(keychainUsernameKey()).toString();
if (_username.isEmpty()) {
return false;
}
_readPasswordJob.reset(new ReadPasswordJob(Theme::instance()->appName()));
_readPasswordJob->setSettings(_settings.data());
_readPasswordJob->setInsecureFallback(false);
_readPasswordJob->setKey(keychainPasswordKey());
_readPasswordJob->setAutoDelete(false);
connect(_readPasswordJob.data(), SIGNAL(finished(QKeychain::Job*)),
SLOT(slotKeychainJobDone()));
_keychainJobRunning = true;
_readPasswordJob->start();
}
// While we wait for the password job to be done, this code may be reentered.
// This really needs the counter and the flag here, because otherwise we get
// bad behavior when we reenter this code after the flag has been switched
// but before the while loop has finished.
++_waitingForKeychain;
_keychainJobRunning = true;
while (_keychainJobRunning) {
QApplication::processEvents(QEventLoop::AllEvents, 200);
}
--_waitingForKeychain;
if (_readPasswordJob->error() == NoError) {
qDebug() << "got creds for" << _proxy << "from keychain";
_password = _readPasswordJob->textData();
return true;
}
_username.clear();
if (_readPasswordJob->error() != EntryNotFound) {
qDebug() << "ReadPasswordJob failed with" << _readPasswordJob->errorString();
}
return false;
}
void ProxyAuthHandler::storeCredsInKeychain()
{
using namespace QKeychain;
if (_waitingForKeychain) {
return;
}
qDebug() << "storing" << _proxy;
_settings->setValue(keychainUsernameKey(), _username);
WritePasswordJob* job = new WritePasswordJob(Theme::instance()->appName(), this);
job->setSettings(_settings.data());
job->setInsecureFallback(false);
job->setKey(keychainPasswordKey());
job->setTextData(_password);
job->setAutoDelete(false);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotKeychainJobDone()));
_keychainJobRunning = true;
job->start();
++_waitingForKeychain;
_keychainJobRunning = true;
while (_keychainJobRunning) {
QApplication::processEvents(QEventLoop::AllEvents, 200);
}
--_waitingForKeychain;
job->deleteLater();
if (job->error() != NoError) {
qDebug() << "WritePasswordJob failed with" << job->errorString();
}
}
QString ProxyAuthHandler::keychainUsernameKey() const
{
return QString::fromLatin1("%1/username").arg(_proxy);
}
QString ProxyAuthHandler::keychainPasswordKey() const
{
return QString::fromLatin1("%1/password").arg(_proxy);
}

105
src/gui/proxyauthhandler.h Normal file
View file

@ -0,0 +1,105 @@
/*
* Copyright (C) 2015 by Christian Kamm <kamm@incasoftware.de>
*
* 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.
*/
#pragma once
#include "owncloudgui.h"
#include <QObject>
#include <QString>
#include <QNetworkProxy>
#include <QAuthenticator>
#include <QPointer>
#include <QScopedPointer>
#include <QSettings>
namespace QKeychain {
class Job;
class ReadPasswordJob;
}
namespace OCC {
class ConfigFile;
class ProxyAuthDialog;
/**
* @brief Handle proxyAuthenticationRequired signals from our QNetworkAccessManagers.
*
* The main complication here is that the slot needs to return credential information
* synchronously - but running a dialog or getting password data from synchronous
* storage are asynchronous operations. This leads to reentrant calls that are
* fairly complicated to handle.
*/
class ProxyAuthHandler : public QObject
{
Q_OBJECT
public:
static ProxyAuthHandler* instance();
virtual ~ProxyAuthHandler();
public slots:
/// Intended for QNetworkAccessManager::proxyAuthenticationRequired()
void handleProxyAuthenticationRequired(const QNetworkProxy& proxy,
QAuthenticator* authenticator);
private slots:
void slotKeychainJobDone();
private:
ProxyAuthHandler();
/// Runs the ProxyAuthDialog and returns true if new credentials were entered.
bool getCredsFromDialog();
/// Checks the keychain for credentials of the current proxy.
bool getCredsFromKeychain();
/// Stores the current credentials in the keychain.
void storeCredsInKeychain();
QString keychainUsernameKey() const;
QString keychainPasswordKey() const;
/// The hostname:port of the current proxy, used for detetcting switches
/// to a different proxy.
QString _proxy;
QString _username;
QString _password;
/// If the user cancels the credential dialog, blocked will be set to
/// true and we won't bother him again.
bool _blocked;
/// In several instances handleProxyAuthenticationRequired() can be called
/// while it is still running. These counters detect what we're currently
/// waiting for.
int _waitingForDialog;
int _waitingForKeychain;
bool _keychainJobRunning;
QPointer<ProxyAuthDialog> _dialog;
/// The QSettings instance to securely store username/password in the keychain.
QScopedPointer<QSettings> _settings;
/// Pointer to the most-recently-run ReadPasswordJob, needed due to reentrancy.
QScopedPointer<QKeychain::ReadPasswordJob> _readPasswordJob;
/// For checking the proxy config settings.
QScopedPointer<ConfigFile> _configFile;
};
} // namespace OCC

View file

@ -157,7 +157,8 @@ void AbstractNetworkJob::slotFinished()
} }
if( _reply->error() != QNetworkReply::NoError ) { if( _reply->error() != QNetworkReply::NoError ) {
qDebug() << Q_FUNC_INFO << _reply->error() << _reply->errorString(); qDebug() << Q_FUNC_INFO << _reply->error() << _reply->errorString()
<< _reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
if (_reply->error() == QNetworkReply::ProxyAuthenticationRequiredError) { if (_reply->error() == QNetworkReply::ProxyAuthenticationRequiredError) {
qDebug() << Q_FUNC_INFO << _reply->rawHeader("Proxy-Authenticate"); qDebug() << Q_FUNC_INFO << _reply->rawHeader("Proxy-Authenticate");
} }

View file

@ -23,6 +23,10 @@
#include "accessmanager.h" #include "accessmanager.h"
#include "utility.h" #include "utility.h"
#include <QInputDialog>
#include <QMutexLocker>
#include <QApplication>
namespace OCC namespace OCC
{ {
@ -36,9 +40,6 @@ AccessManager::AccessManager(QObject* parent)
setProxy(proxy); setProxy(proxy);
#endif #endif
setCookieJar(new CookieJar); setCookieJar(new CookieJar);
connect(this, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
this, SLOT(slotProxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
} }
void AccessManager::setRawCookie(const QByteArray &rawCookie, const QUrl &url) void AccessManager::setRawCookie(const QByteArray &rawCookie, const QUrl &url)
@ -72,16 +73,4 @@ QNetworkReply* AccessManager::createRequest(QNetworkAccessManager::Operation op,
return QNetworkAccessManager::createRequest(op, newRequest, outgoingData); return QNetworkAccessManager::createRequest(op, newRequest, outgoingData);
} }
void AccessManager::slotProxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
{
Q_UNUSED(authenticator);
qDebug() << Q_FUNC_INFO << proxy.type();
// We put in the password here and in ClientProxy in the proxy itself.
if (!proxy.user().isEmpty() || !proxy.password().isEmpty()) {
authenticator->setUser(proxy.user());
authenticator->setPassword(proxy.password());
}
}
} // namespace OCC } // namespace OCC

View file

@ -38,8 +38,6 @@ public:
protected: protected:
QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData = 0) Q_DECL_OVERRIDE; QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& request, QIODevice* outgoingData = 0) Q_DECL_OVERRIDE;
protected slots:
void slotProxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator);
}; };
} // namespace OCC } // namespace OCC

View file

@ -134,7 +134,9 @@ void Account::setCredentials(AbstractCredentials *cred)
_am->setCookieJar(jar); _am->setCookieJar(jar);
} }
connect(_am, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), connect(_am, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
SLOT(slotHandleErrors(QNetworkReply*,QList<QSslError>))); SLOT(slotHandleSslErrors(QNetworkReply*,QList<QSslError>)));
connect(_am, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
connect(_credentials, SIGNAL(fetched()), connect(_credentials, SIGNAL(fetched()),
SLOT(slotCredentialsFetched())); SLOT(slotCredentialsFetched()));
} }
@ -178,7 +180,9 @@ void Account::resetNetworkAccessManager()
_am = _credentials->getQNAM(); _am = _credentials->getQNAM();
_am->setCookieJar(jar); // takes ownership of the old cookie jar _am->setCookieJar(jar); // takes ownership of the old cookie jar
connect(_am, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), connect(_am, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
SLOT(slotHandleErrors(QNetworkReply*,QList<QSslError>))); SLOT(slotHandleSslErrors(QNetworkReply*,QList<QSslError>)));
connect(_am, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
} }
QNetworkAccessManager *Account::networkAccessManager() QNetworkAccessManager *Account::networkAccessManager()
@ -368,7 +372,7 @@ void Account::setCredentialSetting(const QString &key, const QVariant &value)
} }
} }
void Account::slotHandleErrors(QNetworkReply *reply , QList<QSslError> errors) void Account::slotHandleSslErrors(QNetworkReply *reply , QList<QSslError> errors)
{ {
NetworkJobTimeoutPauser pauser(reply); NetworkJobTimeoutPauser pauser(reply);
QString out; QString out;

View file

@ -51,7 +51,6 @@ public:
virtual bool handleErrors(QList<QSslError>, const QSslConfiguration &conf, QList<QSslCertificate>*, AccountPtr) = 0; virtual bool handleErrors(QList<QSslError>, const QSslConfiguration &conf, QList<QSslCertificate>*, AccountPtr) = 0;
}; };
/** /**
* @brief The Account class represents an account on an ownCloud Server * @brief The Account class represents an account on an ownCloud Server
* @ingroup libsync * @ingroup libsync
@ -157,8 +156,11 @@ signals:
void invalidCredentials(); void invalidCredentials();
void credentialsFetched(AbstractCredentials* credentials); void credentialsFetched(AbstractCredentials* credentials);
/// Forwards from QNetworkAccessManager::proxyAuthenticationRequired().
void proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*);
protected Q_SLOTS: protected Q_SLOTS:
void slotHandleErrors(QNetworkReply*,QList<QSslError>); void slotHandleSslErrors(QNetworkReply*,QList<QSslError>);
void slotCredentialsFetched(); void slotCredentialsFetched();
private: private: