~ubuntu-branches/ubuntu/oneiric/arora/oneiric

« back to all changes in this revision

Viewing changes to src/networkaccessmanager.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Roderick B. Greening
  • Date: 2009-09-10 15:24:04 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20090910152404-668k22ux3mfap6g0
Tags: 0.9.0-0ubuntu1
* New upstream release
* Update patches:
  - kubuntu_02_default_bookmarks.diff
* Remove patches:
  - kubuntu_04_startpage_spacing.diff (fixed upstream)
  - kubuntu_05_manpages.diff (fixed upstream)
  - kubuntu_07_adblock.diff (unstable/unsuitable)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2008 Benjamin C. Meyer <ben@meyerhome.net>
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or modify
5
 
 * it under the terms of the GNU General Public License as published by
6
 
 * the Free Software Foundation; either version 2 of the License, or
7
 
 * (at your option) any later version.
8
 
 *
9
 
 * This program is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
 * GNU General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU General Public License
15
 
 * along with this program; if not, write to the Free Software
16
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17
 
 * Boston, MA  02110-1301  USA
18
 
 */
19
 
 
20
 
/****************************************************************************
21
 
**
22
 
** Copyright (C) 2007-2008 Trolltech ASA. All rights reserved.
23
 
**
24
 
** This file is part of the demonstration applications of the Qt Toolkit.
25
 
**
26
 
** This file may be used under the terms of the GNU General Public
27
 
** License versions 2.0 or 3.0 as published by the Free Software
28
 
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
29
 
** included in the packaging of this file.  Alternatively you may (at
30
 
** your option) use any later version of the GNU General Public
31
 
** License if such license has been publicly approved by Trolltech ASA
32
 
** (or its successors, if any) and the KDE Free Qt Foundation. In
33
 
** addition, as a special exception, Trolltech gives you certain
34
 
** additional rights. These rights are described in the Trolltech GPL
35
 
** Exception version 1.2, which can be found at
36
 
** http://www.trolltech.com/products/qt/gplexception/ and in the file
37
 
** GPL_EXCEPTION.txt in this package.
38
 
**
39
 
** Please review the following information to ensure GNU General
40
 
** Public Licensing requirements will be met:
41
 
** http://trolltech.com/products/qt/licenses/licensing/opensource/. If
42
 
** you are unsure which license is appropriate for your use, please
43
 
** review the following information:
44
 
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
45
 
** or contact the sales department at sales@trolltech.com.
46
 
**
47
 
** In addition, as a special exception, Trolltech, as the sole
48
 
** copyright holder for Qt Designer, grants users of the Qt/Eclipse
49
 
** Integration plug-in the right for the Qt/Eclipse Integration to
50
 
** link to functionality provided by Qt Designer and its related
51
 
** libraries.
52
 
**
53
 
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
54
 
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
55
 
** A PARTICULAR PURPOSE. Trolltech reserves all rights not expressly
56
 
** granted herein.
57
 
**
58
 
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
59
 
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
60
 
**
61
 
****************************************************************************/
62
 
 
63
 
#include "networkaccessmanager.h"
64
 
 
65
 
#include "acceptlanguagedialog.h"
66
 
#include "browserapplication.h"
67
 
#include "browsermainwindow.h"
68
 
#include "schemeaccesshandler.h"
69
 
#include "ui_passworddialog.h"
70
 
#include "ui_proxy.h"
71
 
 
72
 
#include <qdialog.h>
73
 
#include <qmessagebox.h>
74
 
#include <qsettings.h>
75
 
#include <qstyle.h>
76
 
#include <qtextdocument.h>
77
 
 
78
 
#include <qauthenticator.h>
79
 
#include <qnetworkproxy.h>
80
 
#include <qnetworkreply.h>
81
 
#include <qsslconfiguration.h>
82
 
#include <qsslerror.h>
83
 
#include <qdatetime.h>
84
 
 
85
 
#if QT_VERSION >= 0x040500
86
 
#include <qnetworkdiskcache.h>
87
 
#include <qdesktopservices.h>
88
 
#endif
89
 
 
90
 
#if QT_VERSION >= 0x040500
91
 
NetworkProxyFactory::NetworkProxyFactory()
92
 
    : QNetworkProxyFactory()
93
 
{
94
 
}
95
 
 
96
 
void NetworkProxyFactory::setHttpProxy(const QNetworkProxy &proxy)
97
 
{
98
 
    m_httpProxy = proxy;
99
 
}
100
 
 
101
 
void NetworkProxyFactory::setGlobalProxy(const QNetworkProxy &proxy)
102
 
{
103
 
    m_globalProxy = proxy;
104
 
}
105
 
 
106
 
QList<QNetworkProxy> NetworkProxyFactory::queryProxy(const QNetworkProxyQuery &query)
107
 
{
108
 
    QList<QNetworkProxy> ret;
109
 
 
110
 
    if (query.protocolTag() == QLatin1String("http") && m_httpProxy.type() != QNetworkProxy::DefaultProxy)
111
 
        ret << m_httpProxy;
112
 
    ret << m_globalProxy;
113
 
 
114
 
    return ret;
115
 
}
116
 
#endif
117
 
 
118
 
NetworkAccessManager::NetworkAccessManager(QObject *parent)
119
 
    : QNetworkAccessManager(parent)
120
 
{
121
 
    connect(this, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)),
122
 
            SLOT(authenticationRequired(QNetworkReply*, QAuthenticator*)));
123
 
    connect(this, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)),
124
 
            SLOT(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)));
125
 
#ifndef QT_NO_OPENSSL
126
 
    connect(this, SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError>&)),
127
 
            SLOT(sslErrors(QNetworkReply*, const QList<QSslError>&)));
128
 
#endif
129
 
    connect(BrowserApplication::instance(), SIGNAL(privacyChanged(bool)),
130
 
            this, SLOT(privacyChanged(bool)));
131
 
    loadSettings();
132
 
 
133
 
    // Register custom scheme handlers
134
 
    setSchemeHandler(QLatin1String("file"), new FileAccessHandler(this));
135
 
}
136
 
 
137
 
void NetworkAccessManager::setSchemeHandler(const QString &scheme, SchemeAccessHandler *handler)
138
 
{
139
 
    m_schemeHandlers.insert(scheme, handler);
140
 
}
141
 
 
142
 
void NetworkAccessManager::loadSettings()
143
 
{
144
 
    QSettings settings;
145
 
    settings.beginGroup(QLatin1String("proxy"));
146
 
    QNetworkProxy proxy;
147
 
    if (settings.value(QLatin1String("enabled"), false).toBool()) {
148
 
        int proxyType = settings.value(QLatin1String("type"), 0).toInt();
149
 
        if (proxyType == 0)
150
 
            proxy = QNetworkProxy::Socks5Proxy;
151
 
        else if (proxyType == 1)
152
 
            proxy = QNetworkProxy::HttpProxy;
153
 
        else { // 2
154
 
            proxy.setType(QNetworkProxy::HttpCachingProxy);
155
 
#if QT_VERSION >= 0x040500
156
 
            proxy.setCapabilities(QNetworkProxy::CachingCapability | QNetworkProxy::HostNameLookupCapability);
157
 
#endif
158
 
        }
159
 
        proxy.setHostName(settings.value(QLatin1String("hostName")).toString());
160
 
        proxy.setPort(settings.value(QLatin1String("port"), 1080).toInt());
161
 
        proxy.setUser(settings.value(QLatin1String("userName")).toString());
162
 
        proxy.setPassword(settings.value(QLatin1String("password")).toString());
163
 
    }
164
 
#if QT_VERSION >= 0x040500
165
 
    NetworkProxyFactory *proxyFactory = new NetworkProxyFactory;
166
 
    if (proxy.type() == QNetworkProxy::HttpCachingProxy) {
167
 
        proxyFactory->setHttpProxy(proxy);
168
 
        proxyFactory->setGlobalProxy(QNetworkProxy::DefaultProxy);
169
 
    } else {
170
 
        proxyFactory->setHttpProxy(QNetworkProxy::DefaultProxy);
171
 
        proxyFactory->setGlobalProxy(proxy);
172
 
    }
173
 
    setProxyFactory(proxyFactory);
174
 
#else
175
 
    setProxy(proxy);
176
 
#endif
177
 
    settings.endGroup();
178
 
 
179
 
#ifndef QT_NO_OPENSSL
180
 
    QSslConfiguration sslCfg = QSslConfiguration::defaultConfiguration();
181
 
    QList<QSslCertificate> ca_list = sslCfg.caCertificates();
182
 
    QList<QSslCertificate> ca_new = QSslCertificate::fromData(settings.value(QLatin1String("CaCertificates")).toByteArray());
183
 
    ca_list += ca_new;
184
 
 
185
 
    sslCfg.setCaCertificates(ca_list);
186
 
    QSslConfiguration::setDefaultConfiguration(sslCfg);
187
 
#endif
188
 
 
189
 
    settings.beginGroup(QLatin1String("network"));
190
 
    QStringList acceptList = settings.value(QLatin1String("acceptLanguages"),
191
 
            AcceptLanguageDialog::defaultAcceptList()).toStringList();
192
 
    m_acceptLanguage = AcceptLanguageDialog::httpString(acceptList);
193
 
 
194
 
#if QT_VERSION >= 0x040500
195
 
    bool cacheEnabled = settings.value(QLatin1String("cacheEnabled"), true).toBool();
196
 
    if (QLatin1String(qVersion()) == QLatin1String("4.5.1"))
197
 
        cacheEnabled = false;
198
 
 
199
 
    if (cacheEnabled) {
200
 
        int maximumCacheSize = settings.value(QLatin1String("maximumCacheSize"), 50).toInt() * 1024 * 1024;
201
 
 
202
 
        QNetworkDiskCache *diskCache;
203
 
        if (cache())
204
 
            diskCache = qobject_cast<QNetworkDiskCache*>(cache());
205
 
        else
206
 
            diskCache = new QNetworkDiskCache(this);
207
 
 
208
 
        QString location = QDesktopServices::storageLocation(QDesktopServices::CacheLocation)
209
 
                                + QLatin1String("/browser");
210
 
        diskCache->setCacheDirectory(location);
211
 
        diskCache->setMaximumCacheSize(maximumCacheSize);
212
 
        setCache(diskCache);
213
 
    } else {
214
 
        if (QLatin1String(qVersion()) > QLatin1String("4.5.1"))
215
 
            setCache(0);
216
 
    }
217
 
#endif
218
 
    settings.endGroup();
219
 
}
220
 
 
221
 
void NetworkAccessManager::privacyChanged(bool isPrivate)
222
 
{
223
 
    if (isPrivate) {
224
 
#if QT_VERSION >= 0x040500
225
 
        if (QLatin1String(qVersion()) > QLatin1String("4.5.1"))
226
 
            setCache(0);
227
 
#endif
228
 
    } else {
229
 
        loadSettings();
230
 
    }
231
 
}
232
 
 
233
 
 
234
 
void NetworkAccessManager::authenticationRequired(QNetworkReply *reply, QAuthenticator *auth)
235
 
{
236
 
    BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow();
237
 
 
238
 
    QDialog dialog(mainWindow);
239
 
    dialog.setWindowFlags(Qt::Sheet);
240
 
 
241
 
    Ui::PasswordDialog passwordDialog;
242
 
    passwordDialog.setupUi(&dialog);
243
 
 
244
 
    passwordDialog.iconLabel->setText(QString());
245
 
    passwordDialog.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, mainWindow).pixmap(32, 32));
246
 
 
247
 
    QString introMessage = tr("<qt>Enter username and password for \"%1\" at %2</qt>");
248
 
    introMessage = introMessage.arg(Qt::escape(auth->realm())).arg(Qt::escape(reply->url().toString()));
249
 
    passwordDialog.introLabel->setText(introMessage);
250
 
    passwordDialog.introLabel->setWordWrap(true);
251
 
 
252
 
    if (dialog.exec() == QDialog::Accepted) {
253
 
        auth->setUser(passwordDialog.userNameLineEdit->text());
254
 
        auth->setPassword(passwordDialog.passwordLineEdit->text());
255
 
    }
256
 
}
257
 
 
258
 
void NetworkAccessManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth)
259
 
{
260
 
    BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow();
261
 
 
262
 
    QDialog dialog(mainWindow);
263
 
    dialog.setWindowFlags(Qt::Sheet);
264
 
 
265
 
    Ui::ProxyDialog proxyDialog;
266
 
    proxyDialog.setupUi(&dialog);
267
 
 
268
 
    proxyDialog.iconLabel->setText(QString());
269
 
    proxyDialog.iconLabel->setPixmap(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, 0, mainWindow).pixmap(32, 32));
270
 
 
271
 
    QString introMessage = tr("<qt>Connect to proxy \"%1\" using:</qt>");
272
 
    introMessage = introMessage.arg(Qt::escape(proxy.hostName()));
273
 
    proxyDialog.introLabel->setText(introMessage);
274
 
    proxyDialog.introLabel->setWordWrap(true);
275
 
 
276
 
    if (dialog.exec() == QDialog::Accepted) {
277
 
        auth->setUser(proxyDialog.userNameLineEdit->text());
278
 
        auth->setPassword(proxyDialog.passwordLineEdit->text());
279
 
    }
280
 
}
281
 
 
282
 
#ifndef QT_NO_OPENSSL
283
 
QString NetworkAccessManager::certToFormattedString(QSslCertificate cert)
284
 
{
285
 
    QStringList message;
286
 
    message << cert.subjectInfo(QSslCertificate::CommonName);
287
 
    message << tr("Issuer: %1").arg(cert.issuerInfo(QSslCertificate::CommonName));
288
 
    message << tr("Not valid before: %1").arg(cert.effectiveDate().toString());
289
 
    message << tr("Valid until: %1").arg(cert.expiryDate().toString());
290
 
 
291
 
    QMultiMap<QSsl::AlternateNameEntryType, QString> names = cert.alternateSubjectNames();
292
 
    if (names.count() > 0) {
293
 
        QString list;
294
 
        list += QLatin1String("<br />");
295
 
        list += tr("Alternate Names:");
296
 
        list += QLatin1String("<ul><li>");
297
 
        list += QStringList(names.values(QSsl::DnsEntry)).join(QLatin1String("</li><li>"));
298
 
        list += QLatin1String("</li></ul>");
299
 
        message << list;
300
 
    }
301
 
 
302
 
    QString result = QLatin1String("<p>") + message.join(QLatin1String("<br />")) + QLatin1String("</p>");
303
 
 
304
 
    return result;
305
 
}
306
 
 
307
 
void NetworkAccessManager::sslErrors(QNetworkReply *reply, const QList<QSslError> &error)
308
 
{
309
 
    BrowserMainWindow *mainWindow = BrowserApplication::instance()->mainWindow();
310
 
 
311
 
    QSettings settings;
312
 
    QList<QSslCertificate> ca_merge = QSslCertificate::fromData(settings.value(QLatin1String("CaCertificates")).toByteArray());
313
 
 
314
 
    QList<QSslCertificate> ca_new;
315
 
    QStringList errorStrings;
316
 
    for (int i = 0; i < error.count(); ++i) {
317
 
        if (ca_merge.contains(error.at(i).certificate()))
318
 
            continue;
319
 
        errorStrings += error.at(i).errorString();
320
 
        if (!error.at(i).certificate().isNull()) {
321
 
            ca_new.append(error.at(i).certificate());
322
 
        }
323
 
    }
324
 
    if (errorStrings.isEmpty()) {
325
 
        reply->ignoreSslErrors();
326
 
        return;
327
 
    }
328
 
 
329
 
    QString errors = errorStrings.join(QLatin1String("</li><li>"));
330
 
    int ret = QMessageBox::warning(mainWindow,
331
 
                           QCoreApplication::applicationName() + tr(" - SSL Errors"),
332
 
                           tr("<qt>SSL Errors:"
333
 
                              "<br/><br/>for: <tt>%1</tt>"
334
 
                              "<ul><li>%2</li></ul>\n\n"
335
 
                              "Do you want to ignore these errors?</qt>").arg(reply->url().toString()).arg(errors),
336
 
                           QMessageBox::Yes | QMessageBox::No,
337
 
                           QMessageBox::No);
338
 
 
339
 
    if (ret == QMessageBox::Yes) {
340
 
        if (ca_new.count() > 0) {
341
 
            QStringList certinfos;
342
 
            for (int i = 0; i < ca_new.count(); ++i)
343
 
                certinfos += certToFormattedString(ca_new.at(i));
344
 
            ret = QMessageBox::question(mainWindow, QCoreApplication::applicationName(),
345
 
                tr("<qt>Certificates:<br/>"
346
 
                   "%1<br/>"
347
 
                   "Do you want to accept all these certificates?</qt>")
348
 
                    .arg(certinfos.join(QString())),
349
 
                QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
350
 
            if (ret == QMessageBox::Yes) {
351
 
                ca_merge += ca_new;
352
 
 
353
 
                QSslConfiguration sslCfg = QSslConfiguration::defaultConfiguration();
354
 
                QList<QSslCertificate> ca_list = sslCfg.caCertificates();
355
 
                ca_list += ca_new;
356
 
                sslCfg.setCaCertificates(ca_list);
357
 
                QSslConfiguration::setDefaultConfiguration(sslCfg);
358
 
                reply->setSslConfiguration(sslCfg);
359
 
 
360
 
                QByteArray pems;
361
 
                for (int i = 0; i < ca_merge.count(); ++i)
362
 
                    pems += ca_merge.at(i).toPem() + '\n';
363
 
                settings.setValue(QLatin1String("CaCertificates"), pems);
364
 
            }
365
 
        }
366
 
        reply->ignoreSslErrors();
367
 
    }
368
 
}
369
 
#endif
370
 
 
371
 
QNetworkReply *NetworkAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData)
372
 
{
373
 
    QNetworkReply *reply = 0;
374
 
 
375
 
    // Check if there is a valid handler registered for the requested URL scheme
376
 
    if (m_schemeHandlers.contains(request.url().scheme()))
377
 
        reply = m_schemeHandlers[request.url().scheme()]->createRequest(op, request, outgoingData);
378
 
    if (reply)
379
 
        return reply;
380
 
 
381
 
    if (!m_acceptLanguage.isEmpty()) {
382
 
        QNetworkRequest req = request;
383
 
        req.setRawHeader("Accept-Language", m_acceptLanguage);
384
 
        reply = QNetworkAccessManager::createRequest(op, req, outgoingData);
385
 
        emit requestCreated(op, req, reply);
386
 
    } else {
387
 
        reply = QNetworkAccessManager::createRequest(op, request, outgoingData);
388
 
        emit requestCreated(op, request, reply);
389
 
    }
390
 
 
391
 
    return reply;
392
 
}