diff options
author | Liang Qi <liang.qi@qt.io> | 2017-08-31 13:10:18 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2017-08-31 14:31:31 +0200 |
commit | 112a4af10741409b3d8503cb77852a777b607ce0 (patch) | |
tree | fa99f0f37fc1505522fe9368e95484c7732ccda8 /src/network | |
parent | 29ef0d2bccd1874e20de94485ee05777c3a95c5d (diff) | |
parent | e938150412d22e61926fe16791158805b71268bb (diff) |
Merge remote-tracking branch 'origin/5.9' into dev
Conflicts:
examples/examples.pro
qmake/library/qmakebuiltins.cpp
src/corelib/global/qglobal.cpp
Re-apply b525ec2 to qrandom.cpp(code movement in 030782e)
src/corelib/global/qnamespace.qdoc
src/corelib/global/qrandom.cpp
src/gui/kernel/qwindow.cpp
Re-apply a3d59c7 to QWindowPrivate::setVisible() (code movement in d7a9e08)
src/network/ssl/qsslkey_openssl.cpp
src/plugins/platforms/android/androidjniinput.cpp
src/plugins/platforms/xcb/qxcbconnection.cpp
src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
src/widgets/widgets/qmenu.cpp
tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
Change-Id: If7ab427804408877a93cbe02079fca58e568bfd3
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qnetworkaccessmanager.cpp | 14 | ||||
-rw-r--r-- | src/network/configure.json | 3 | ||||
-rw-r--r-- | src/network/kernel/kernel.pri | 2 | ||||
-rw-r--r-- | src/network/kernel/qhostinfo_unix.cpp | 3 | ||||
-rw-r--r-- | src/network/kernel/qnetworkinterface_unix.cpp | 5 | ||||
-rw-r--r-- | src/network/kernel/qnetworkproxy_libproxy.cpp | 143 | ||||
-rw-r--r-- | src/network/ssl/qsslkey_openssl.cpp | 3 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl.cpp | 2 |
8 files changed, 138 insertions, 37 deletions
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index eeee82a87c..15a0359391 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -71,6 +71,8 @@ #include "qthread.h" +#include <QHostInfo> + QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QNetworkAccessFileBackendFactory, fileBackend) @@ -689,7 +691,7 @@ void QNetworkAccessManager::setCookieJar(QNetworkCookieJar *cookieJar) if (d->cookieJar && d->cookieJar->parent() == this) delete d->cookieJar; d->cookieJar = cookieJar; - if (thread() == cookieJar->thread()) + if (cookieJar && thread() == cookieJar->thread()) d->cookieJar->setParent(this); } } @@ -1366,10 +1368,16 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera } #ifndef QT_NO_BEARERMANAGEMENT + // Return a disabled network reply if network access is disabled. - // Except if the scheme is empty or file://. + // Except if the scheme is empty or file:// or if the host resolves to a loopback address. if (d->networkAccessible == NotAccessible && !isLocalFile) { - return new QDisabledNetworkReply(this, req, op); + QHostAddress dest; + QString host = req.url().host().toLower(); + if (!(dest.setAddress(host) && dest.isLoopback()) && host != QLatin1String("localhost") + && host != QHostInfo::localHostName().toLower()) { + return new QDisabledNetworkReply(this, req, op); + } } if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.identifier().isEmpty())) { diff --git a/src/network/configure.json b/src/network/configure.json index de40872e16..b1c943de6f 100644 --- a/src/network/configure.json +++ b/src/network/configure.json @@ -135,7 +135,8 @@ "main": [ "char buf[IFNAMSIZ];", "if_nametoindex(\"eth0\");", - "if_indextoname(1, buf);" + "if_indextoname(1, buf);", + "if_freenameindex(if_nameindex());" ] }, "use": "network" diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index c3fcf25233..ac6bebbfae 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -63,6 +63,6 @@ osx:SOURCES += kernel/qnetworkproxy_mac.cpp else:win32:!winrt: SOURCES += kernel/qnetworkproxy_win.cpp else: qtConfig(libproxy) { SOURCES += kernel/qnetworkproxy_libproxy.cpp - QMAKE_USE_PRIVATE += libproxy + QMAKE_USE_PRIVATE += libproxy libdl } else:SOURCES += kernel/qnetworkproxy_generic.cpp diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index cf08a15f96..9a24938284 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -150,8 +150,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QHostAddress address; if (address.setAddress(hostName)) { // Reverse lookup -// Reverse lookups using getnameinfo are broken on darwin, use gethostbyaddr instead. -#if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN) +#if !defined (QT_NO_GETADDRINFO) sockaddr_in sa4; sockaddr_in6 sa6; sockaddr *sa = 0; diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index 4f4615d4d0..afa6b4296e 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -60,11 +60,6 @@ # define QT_NO_GETIFADDRS #endif -#ifdef Q_OS_ANDROID -// android lacks if_nameindex -# define QT_NO_IPV6IFNAME -#endif - #ifdef Q_OS_HAIKU # include <sys/sockio.h> # define IFF_RUNNING 0x0001 diff --git a/src/network/kernel/qnetworkproxy_libproxy.cpp b/src/network/kernel/qnetworkproxy_libproxy.cpp index 184dc6469d..29d2a0bd3b 100644 --- a/src/network/kernel/qnetworkproxy_libproxy.cpp +++ b/src/network/kernel/qnetworkproxy_libproxy.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtNetwork module of the Qt Toolkit. @@ -42,57 +43,149 @@ #ifndef QT_NO_NETWORKPROXY #include <QtCore/QByteArray> +#include <QtCore/QMutex> +#include <QtCore/QSemaphore> #include <QtCore/QUrl> +#include <QtCore/private/qeventdispatcher_unix_p.h> +#include <QtCore/private/qthread_p.h> #include <proxy.h> +#include <dlfcn.h> QT_BEGIN_NAMESPACE -class QLibProxyWrapper +static bool isThreadingNeeded() { -public: - QLibProxyWrapper() - : factory(px_proxy_factory_new()) - { - if (!factory) - qWarning("libproxy initialization failed."); - } + // Try to guess if the libproxy we linked to is from the libproxy project + // or if it is from pacrunner. Neither library is thread-safe, but the one + // from libproxy is worse, since it may launch JS engines that don't take + // kindly to being executed from multiple threads (even if at different + // times). The pacrunner implementation doesn't suffer from this because + // the JS execution is out of process, in the pacrunner daemon. - ~QLibProxyWrapper() - { - px_proxy_factory_free(factory); - } + void *sym; + +#ifdef Q_CC_GNU + // Search for the mangled name of the virtual table of the pacrunner + // extension. Even if libproxy begins using -fvisibility=hidden, this + // symbol can't be hidden. + sym = dlsym(RTLD_DEFAULT, "_ZTVN8libproxy19pacrunner_extensionE"); +#else + // The default libproxy one uses libmodman for its module management and + // leaks symbols because it doesn't use -fvisibility=hidden (as of + // v0.4.15). + sym = dlsym(RTLD_DEFAULT, "mm_info_ignore_hostname"); +#endif + + return sym != nullptr; +} + +class QLibProxyWrapper : public QDaemonThread +{ + Q_OBJECT +public: + QLibProxyWrapper(); + ~QLibProxyWrapper(); QList<QUrl> getProxies(const QUrl &url); private: - pxProxyFactory *factory; + struct Data { + // we leave the conversion to/from QUrl to the calling thread + const char *url; + char **proxies; + QSemaphore replyReady; + }; + + void run() override; + + pxProxyFactory *factory; // not subject to the mutex + + QMutex mutex; + QSemaphore requestReady; + Data *request; }; Q_GLOBAL_STATIC(QLibProxyWrapper, libProxyWrapper); +QLibProxyWrapper::QLibProxyWrapper() +{ + if (isThreadingNeeded()) { + setEventDispatcher(new QEventDispatcherUNIX); // don't allow the Glib one + start(); + } else { + factory = px_proxy_factory_new(); + Q_CHECK_PTR(factory); + } +} + +QLibProxyWrapper::~QLibProxyWrapper() +{ + if (isRunning()) { + requestInterruption(); + requestReady.release(); + wait(); + } else { + px_proxy_factory_free(factory); + } +} + /* - Gets the list of proxies from libproxy, converted to QUrl list. - Thread safe, according to libproxy documentation. + Gets the list of proxies from libproxy, converted to QUrl list. Apply + thread-safety, though its documentation says otherwise, libproxy isn't + thread-safe. */ QList<QUrl> QLibProxyWrapper::getProxies(const QUrl &url) { - QList<QUrl> ret; + QByteArray encodedUrl = url.toEncoded(); + Data data; + data.url = encodedUrl.constData(); + + { + QMutexLocker locker(&mutex); + if (isRunning()) { + // threaded mode + // it's safe to write to request because we hold the mutex: + // our aux thread is blocked waiting for work and no other thread + // could have got here + request = &data; + requestReady.release(); - if (factory) { - char **proxies = px_proxy_factory_get_proxies(factory, url.toEncoded()); - if (proxies) { - for (int i = 0; proxies[i]; i++) { - ret.append(QUrl::fromEncoded(proxies[i])); - free(proxies[i]); - } - free(proxies); + // wait for the reply + data.replyReady.acquire(); + } else { + // non-threaded mode + data.proxies = px_proxy_factory_get_proxies(factory, data.url); } } + QList<QUrl> ret; + if (data.proxies) { + for (int i = 0; data.proxies[i]; i++) { + ret.append(QUrl::fromEncoded(data.proxies[i])); + free(data.proxies[i]); + } + free(data.proxies); + } return ret; } +void QLibProxyWrapper::run() +{ + factory = px_proxy_factory_new(); + Q_CHECK_PTR(factory); + + forever { + requestReady.acquire(); + if (isInterruptionRequested()) + break; + request->proxies = px_proxy_factory_get_proxies(factory, request->url); + request->replyReady.release(); + } + + px_proxy_factory_free(factory); +} + QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &query) { QList<QNetworkProxy> proxyList; @@ -161,4 +254,6 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro QT_END_NAMESPACE +#include "qnetworkproxy_libproxy.moc" + #endif diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp index be7033c8aa..aa81b735b9 100644 --- a/src/network/ssl/qsslkey_openssl.cpp +++ b/src/network/ssl/qsslkey_openssl.cpp @@ -85,6 +85,9 @@ void QSslKeyPrivate::clear(bool deep) bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey) { + if (pkey == nullptr) + return false; + #if QT_CONFIG(opensslv11) const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey)); #else diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index fbfeb00017..23a63ed063 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1499,7 +1499,7 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device, } // Extract the data - EVP_PKEY *pkey; + EVP_PKEY *pkey = nullptr; X509 *x509; STACK_OF(X509) *ca = 0; |