diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libs/installer/downloadfiletask.cpp | 23 | ||||
-rw-r--r-- | src/libs/installer/downloadfiletask.h | 16 | ||||
-rw-r--r-- | src/libs/installer/downloadfiletask_p.h | 1 | ||||
-rw-r--r-- | src/libs/installer/installer.pro | 8 | ||||
-rw-r--r-- | src/libs/installer/metadatajob.cpp | 20 | ||||
-rw-r--r-- | src/libs/installer/packagemanagerproxyfactory.cpp | 54 | ||||
-rw-r--r-- | src/libs/installer/packagemanagerproxyfactory.h | 11 | ||||
-rw-r--r-- | src/libs/installer/proxycredentialsdialog.cpp | 79 | ||||
-rw-r--r-- | src/libs/installer/proxycredentialsdialog.h | 66 | ||||
-rw-r--r-- | src/libs/installer/proxycredentialsdialog.ui | 106 |
10 files changed, 376 insertions, 8 deletions
diff --git a/src/libs/installer/downloadfiletask.cpp b/src/libs/installer/downloadfiletask.cpp index bbb3cc4e3..0bd38615e 100644 --- a/src/libs/installer/downloadfiletask.cpp +++ b/src/libs/installer/downloadfiletask.cpp @@ -36,6 +36,7 @@ #include "downloadfiletask_p.h" #include "observer.h" +#include <QCoreApplication> #include <QEventLoop> #include <QFile> #include <QFileInfo> @@ -46,6 +47,13 @@ namespace QInstaller { +ProxyAuthenticationRequiredException::ProxyAuthenticationRequiredException(const QNetworkProxy &proxy) + : FileTaskException(QCoreApplication::translate("ProxyAuthenticationRequiredException", + "Proxy requires authentication.")), + m_proxy(proxy) +{ +} + Downloader::Downloader() : m_finished(0) { @@ -80,6 +88,8 @@ void Downloader::download(QFutureInterface<FileTaskResult> &fi, const QList<File m_nam.setProxyFactory(networkProxyFactory); connect(&m_nam, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), this, SLOT(onAuthenticationRequired(QNetworkReply*, QAuthenticator*))); + connect(&m_nam, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), this, + SLOT(onProxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); QTimer::singleShot(0, this, SLOT(doDownload())); } @@ -224,6 +234,12 @@ void Downloader::onFinished(QNetworkReply *reply) void Downloader::onError(QNetworkReply::NetworkError error) { QNetworkReply *const reply = qobject_cast<QNetworkReply *>(sender()); + + if (error == QNetworkReply::ProxyAuthenticationRequiredError) { + // already handled by onProxyAuthenticationRequired + return; + } + if (reply) { const Data &data = m_downloads[reply]; //: %2 is a sentence describing the error @@ -275,6 +291,13 @@ void Downloader::onAuthenticationRequired(QNetworkReply *reply, QAuthenticator * } } +void Downloader::onProxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *) +{ + // Report to GUI thread. + // (MetadataJob will ask for username/password, and restart the download ...) + m_futureInterface->reportException(ProxyAuthenticationRequiredException(proxy)); +} + // -- private diff --git a/src/libs/installer/downloadfiletask.h b/src/libs/installer/downloadfiletask.h index 3ad972763..6b3ddf24e 100644 --- a/src/libs/installer/downloadfiletask.h +++ b/src/libs/installer/downloadfiletask.h @@ -50,6 +50,22 @@ enum }; } +class ProxyAuthenticationRequiredException : public FileTaskException +{ +public: + ProxyAuthenticationRequiredException(const QNetworkProxy &proxy); + ~ProxyAuthenticationRequiredException() throw() {} + + QNetworkProxy proxy() const { return m_proxy; } + + void raise() const { throw *this; } + ProxyAuthenticationRequiredException *clone() const { + return new ProxyAuthenticationRequiredException(*this); } + +private: + QNetworkProxy m_proxy; +}; + class INSTALLER_EXPORT DownloadFileTask : public AbstractFileTask { Q_OBJECT diff --git a/src/libs/installer/downloadfiletask_p.h b/src/libs/installer/downloadfiletask_p.h index d4a2c8ea5..16c38cba5 100644 --- a/src/libs/installer/downloadfiletask_p.h +++ b/src/libs/installer/downloadfiletask_p.h @@ -85,6 +85,7 @@ private slots: void onSslErrors(const QList<QSslError> &sslErrors); void onDownloadProgress(qint64 bytesReceived, qint64 bytesTotal); void onAuthenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator); + void onProxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator); private: diff --git a/src/libs/installer/installer.pro b/src/libs/installer/installer.pro index 448b4acc4..445a2a05b 100644 --- a/src/libs/installer/installer.pro +++ b/src/libs/installer/installer.pro @@ -122,7 +122,8 @@ HEADERS += packagemanagercore.h \ binarycontent.h \ binarylayout.h \ installercalculator.h \ - uninstallercalculator.h + uninstallercalculator.h \ + proxycredentialsdialog.h SOURCES += packagemanagercore.cpp \ packagemanagercore_p.cpp \ @@ -193,7 +194,10 @@ SOURCES += packagemanagercore.cpp \ binarycontent.cpp \ binarylayout.cpp \ installercalculator.cpp \ - uninstallercalculator.cpp + uninstallercalculator.cpp \ + proxycredentialsdialog.cpp + +FORMS += proxycredentialsdialog.ui RESOURCES += resources/patch_file_lists.qrc \ resources/installer.qrc diff --git a/src/libs/installer/metadatajob.cpp b/src/libs/installer/metadatajob.cpp index 5e5a27416..6cb5652c2 100644 --- a/src/libs/installer/metadatajob.cpp +++ b/src/libs/installer/metadatajob.cpp @@ -37,6 +37,7 @@ #include "packagemanagercore.h" #include "packagemanagerproxyfactory.h" #include "productkeycheck.h" +#include "proxycredentialsdialog.h" #include "settings.h" #include <QTemporaryDir> @@ -116,6 +117,25 @@ void MetadataJob::xmlTaskFinished() try { m_xmlTask.waitForFinished(); status = parseUpdatesXml(m_xmlTask.future().results()); + } catch (const ProxyAuthenticationRequiredException &e) { + //! will be shown as title in the UI dialog + + const QNetworkProxy proxy = e.proxy(); + ProxyCredentialsDialog proxyCredentials(proxy); + qDebug() << e.message(); + + if (proxyCredentials.exec() == QDialog::Accepted) { + qDebug() << "Retrying with new credentials ..."; + PackageManagerProxyFactory *factory = m_core->proxyFactory(); + + factory->setProxyCredentials(proxy, proxyCredentials.userName(), + proxyCredentials.password()); + m_core->setProxyFactory(factory); + status = XmlDownloadRetry; + } else { + reset(); + emitFinishedWithError(QInstaller::DownloadError, tr("Missing proxy credentials.")); + } } catch (const FileTaskException &e) { reset(); emitFinishedWithError(QInstaller::DownloadError, e.message()); diff --git a/src/libs/installer/packagemanagerproxyfactory.cpp b/src/libs/installer/packagemanagerproxyfactory.cpp index 9456a7015..317b3257f 100644 --- a/src/libs/installer/packagemanagerproxyfactory.cpp +++ b/src/libs/installer/packagemanagerproxyfactory.cpp @@ -37,6 +37,8 @@ #include "packagemanagercore.h" #include "settings.h" +#include <QNetworkProxy> + namespace QInstaller { PackageManagerProxyFactory::PackageManagerProxyFactory(const PackageManagerCore *const core) @@ -46,9 +48,20 @@ PackageManagerProxyFactory::PackageManagerProxyFactory(const PackageManagerCore PackageManagerProxyFactory *PackageManagerProxyFactory::clone() const { - return new PackageManagerProxyFactory(m_core); + PackageManagerProxyFactory *factory = new PackageManagerProxyFactory(m_core); + factory->m_proxyCredentials = m_proxyCredentials; + return factory; } +struct FindProxyCredential { + FindProxyCredential(const QString &host, int port) : host(host), port(port) {} + + bool operator()(const ProxyCredential &c) { return c.host == host && c.port == port; } +private: + QString host; + int port; +}; + QList<QNetworkProxy> PackageManagerProxyFactory::queryProxy(const QNetworkProxyQuery &query) { const Settings &settings = m_core->settings(); @@ -69,15 +82,44 @@ QList<QNetworkProxy> PackageManagerProxyFactory::queryProxy(const QNetworkProxyQ return list << QNetworkProxy(QNetworkProxy::NoProxy); if (query.queryType() == QNetworkProxyQuery::UrlRequest) { - if (query.url().scheme() == QLatin1String("ftp")) - return list << settings.ftpProxy(); + QNetworkProxy proxy; + if (query.url().scheme() == QLatin1String("ftp")) { + proxy = settings.ftpProxy(); + } else if (query.url().scheme() == QLatin1String("http") + || query.url().scheme() == QLatin1String("https")) { + proxy = settings.httpProxy(); + } + - if ((query.url().scheme() == QLatin1String("http")) - || (query.url().scheme() == QLatin1String("https"))) { - return list << settings.httpProxy(); + auto p = std::find_if(m_proxyCredentials.constBegin(), m_proxyCredentials.constEnd(), + FindProxyCredential(proxy.hostName(), proxy.port())); + if (p != m_proxyCredentials.constEnd()) { + proxy.setUser(p->user); + proxy.setPassword(p->password); } + return list << proxy; } return list << QNetworkProxy(QNetworkProxy::DefaultProxy); } +void PackageManagerProxyFactory::setProxyCredentials(const QNetworkProxy &proxy, + const QString &user, + const QString &password) +{ + auto p = std::find_if(m_proxyCredentials.begin(), m_proxyCredentials.end(), + FindProxyCredential(proxy.hostName(), proxy.port())); + + if (p == m_proxyCredentials.constEnd()) { + ProxyCredential proxyCredential; + proxyCredential.host = proxy.hostName(); + proxyCredential.port = proxy.port(); + proxyCredential.user = user; + proxyCredential.password = password; + m_proxyCredentials.append(proxyCredential); + } else { + p->user = user; + p->password = password; + } +} + } // QInstaller diff --git a/src/libs/installer/packagemanagerproxyfactory.h b/src/libs/installer/packagemanagerproxyfactory.h index b64183a7e..3d3439bd9 100644 --- a/src/libs/installer/packagemanagerproxyfactory.h +++ b/src/libs/installer/packagemanagerproxyfactory.h @@ -41,6 +41,13 @@ namespace QInstaller { class PackageManagerCore; +struct ProxyCredential { + QString host; + QString user; + QString password; + int port; +}; + class PackageManagerProxyFactory : public KDUpdater::FileDownloaderProxyFactory { public: @@ -49,7 +56,11 @@ public: PackageManagerProxyFactory *clone() const; QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery()); + void setProxyCredentials(const QNetworkProxy &proxy, const QString &user, const QString &password); + private: + + QList<ProxyCredential> m_proxyCredentials; const PackageManagerCore *const m_core; }; diff --git a/src/libs/installer/proxycredentialsdialog.cpp b/src/libs/installer/proxycredentialsdialog.cpp new file mode 100644 index 000000000..689849e48 --- /dev/null +++ b/src/libs/installer/proxycredentialsdialog.cpp @@ -0,0 +1,79 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ +#include "proxycredentialsdialog.h" +#include "ui_proxycredentialsdialog.h" + +#include <QNetworkProxy> + +namespace QInstaller { + +ProxyCredentialsDialog::ProxyCredentialsDialog(const QNetworkProxy &proxy, QWidget *parent) : + QDialog(parent), + ui(new Ui::ProxyCredentialsDialog) +{ + ui->setupUi(this); + + setUserName(proxy.user()); + setPassword(proxy.password()); + + const QString proxyString = QString::fromLatin1("%1:%2").arg(proxy.hostName()).arg(proxy.port()); + ui->infotext->setText(ui->infotext->text().arg(proxyString)); +} + +ProxyCredentialsDialog::~ProxyCredentialsDialog() +{ + delete ui; +} + +QString ProxyCredentialsDialog::userName() const +{ + return ui->usernameLineEdit->text(); +} + +void ProxyCredentialsDialog::setUserName(const QString &username) +{ + ui->usernameLineEdit->setText(username); +} + +QString ProxyCredentialsDialog::password() const +{ + return ui->passwordLineEdit->text(); +} + +void ProxyCredentialsDialog::setPassword(const QString &passwd) +{ + ui->passwordLineEdit->setText(passwd); +} + +} // namespace QInstaller diff --git a/src/libs/installer/proxycredentialsdialog.h b/src/libs/installer/proxycredentialsdialog.h new file mode 100644 index 000000000..5d5d4583e --- /dev/null +++ b/src/libs/installer/proxycredentialsdialog.h @@ -0,0 +1,66 @@ +/************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt Installer Framework. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** +** $QT_END_LICENSE$ +** +**************************************************************************/ +#ifndef PROXYCREDENTIALSDIALOG_H +#define PROXYCREDENTIALSDIALOG_H + +#include <QDialog> + +class QNetworkProxy; + +namespace QInstaller { + +namespace Ui { +class ProxyCredentialsDialog; +} + +class ProxyCredentialsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ProxyCredentialsDialog(const QNetworkProxy &proxy, QWidget *parent = 0); + ~ProxyCredentialsDialog(); + + QString userName() const; + void setUserName(const QString &username); + QString password() const; + void setPassword(const QString &passwd); + +private: + Ui::ProxyCredentialsDialog *ui; +}; + +} // QInstaller + +#endif // PROXYCREDENTIALSDIALOG_H diff --git a/src/libs/installer/proxycredentialsdialog.ui b/src/libs/installer/proxycredentialsdialog.ui new file mode 100644 index 000000000..e6edf03e8 --- /dev/null +++ b/src/libs/installer/proxycredentialsdialog.ui @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QInstaller::ProxyCredentialsDialog</class> + <widget class="QDialog" name="QInstaller::ProxyCredentialsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>262</width> + <height>114</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="infotext"> + <property name="text"> + <string>The proxy %1 requires a username and password.</string> + </property> + </widget> + </item> + <item> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="usernameLabel"> + <property name="text"> + <string>Username:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="usernameLineEdit"> + <property name="placeholderText"> + <string>Username</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="passwordLabel"> + <property name="text"> + <string>Password:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="passwordLineEdit"> + <property name="echoMode"> + <enum>QLineEdit::Password</enum> + </property> + <property name="placeholderText"> + <string>Password</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <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> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>QInstaller::ProxyCredentialsDialog</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>QInstaller::ProxyCredentialsDialog</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> |