diff options
author | Pasi Pentikainen <ext-pasi.a.pentikainen@nokia.com> | 2012-01-12 22:41:28 +0200 |
---|---|---|
committer | Pasi Pentikainen <ext-pasi.a.pentikainen@nokia.com> | 2012-01-12 22:41:28 +0200 |
commit | b902cccfab0ad8b87b4edcc479c266132ae267e0 (patch) | |
tree | 7a5b25dd85bd4dcff033655734268b1902f78579 | |
parent | 443f2df750ac01b3c598d833d5c067798c1e670d (diff) | |
parent | c5ddcb3387f968ce0c2ac6420a05c5ebc528b260 (diff) | |
download | qt4-tools-b902cccfab0ad8b87b4edcc479c266132ae267e0.tar.gz |
Merge commit 'c5ddcb33' into 4.8.0-symbian
* commit 'c5ddcb33':
Fix http authentication to a different realm on the same server
Fix race in http connection channel
Don't fetch credentials from cache following a failed proxy authentication
Handle plain socket write errors in SSL
Fix for assertion failure
Fix faulty logic in http connection pipelining
Test case for QTBUG-22875
QThreads on Symbian are named to allow them to be opened externally
Symbian: Fix exporting and importing of some functions for autotests
Symbian: Fix SRCDIR usage in qlayout autotest.
Symbian: Fix qcssparser autotest
Symbian: Fix qscriptextensionplugin autotest
Fix missing part from commit dae052cb11c0018121f2c4028aed9db17769fd77
Fix m_longTapDetector causing crash.
Fix to incorrect ApplicationActivate event in QtOpenGL
Symbian - Fix QFile::map with non page aligned offsets
Symbian: fix tst_QMenuBar::task256322_highlight() regression
Default to QDir::homePath() in Symbian native file dialogs
Fix NTLM authentication with email address
Fix null pointer dereference in NTLM authentication
Change-Id: Ie087fce22bb0c6605de308975eba483885708bb3
43 files changed, 439 insertions, 94 deletions
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 4961722194..781a5f0130 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -1058,22 +1058,24 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla TInt nativeMapError = KErrNone; RFileMap mapping; TUint mode(EFileMapRemovableMedia); + TUint64 nativeOffset = offset & ~(mapping.PageSizeInBytes() - 1); + //If the file was opened for write or read/write, then open the map for read/write if (openMode & QIODevice::WriteOnly) mode |= EFileMapWrite; if (symbianFile.SubSessionHandle()) { - nativeMapError = mapping.Open(symbianFile, offset, size, mode); + nativeMapError = mapping.Open(symbianFile, nativeOffset, size, mode); } else { //map file by name if we don't have a native handle QString fn = QFileSystemEngine::absoluteName(fileEntry).nativeFilePath(); TUint filemode = EFileShareReadersOrWriters | EFileRead; if (openMode & QIODevice::WriteOnly) filemode |= EFileWrite; - nativeMapError = mapping.Open(qt_s60GetRFs(), qt_QString2TPtrC(fn), filemode, offset, size, mode); + nativeMapError = mapping.Open(qt_s60GetRFs(), qt_QString2TPtrC(fn), filemode, nativeOffset, size, mode); } if (nativeMapError == KErrNone) { QScopedResource<RFileMap> ptr(mapping); //will call Close if adding to mapping throws an exception - uchar *address = mapping.Base(); + uchar *address = mapping.Base() + (offset - nativeOffset); maps[address] = mapping; ptr.take(); return address; diff --git a/src/corelib/thread/qthread_symbian.cpp b/src/corelib/thread/qthread_symbian.cpp index 2ea1b447b8..78bb293c75 100644 --- a/src/corelib/thread/qthread_symbian.cpp +++ b/src/corelib/thread/qthread_symbian.cpp @@ -46,10 +46,12 @@ #include "qthreadstorage.h" #include "qthread_p.h" #include <private/qsystemerror_p.h> +#include <private/qcore_symbian_p.h> #include <sched.h> #include <hal.h> #include <hal_data.h> +#include <e32math.h> // You only find these enumerations on Symbian^3 onwards, so we need to provide our own // to remain compatible with older releases. They won't be called by pre-Sym^3 SDKs. @@ -509,7 +511,21 @@ void QThread::start(Priority priority) // operations like file I/O fail, so we increase it by default. d->stackSize = 0x14000; // Maximum stack size on Symbian. - int code = d->data->symbian_thread_handle.Create(KNullDesC, (TThreadFunction) QThreadPrivate::start, d->stackSize, NULL, this); + int code = KErrAlreadyExists; + QString objName = objectName(); + TPtrC objNamePtr(qt_QString2TPtrC(objName)); + TName name; + objNamePtr.Set(objNamePtr.Left(qMin(objNamePtr.Length(), name.MaxLength() - 16))); + const int MaxRetries = 10; + for (int i=0; i<MaxRetries && code == KErrAlreadyExists; i++) { + // generate a thread name using a similar method to libpthread in Symbian + // a named thread can be opened from another process + name.Zero(); + name.Append(objNamePtr); + name.AppendNumFixedWidth(int(this), EHex, 8); + name.AppendNumFixedWidth(Math::Random(), EHex, 8); + code = d->data->symbian_thread_handle.Create(name, (TThreadFunction) QThreadPrivate::start, d->stackSize, NULL, this); + } if (code == KErrNone) { d->thread_id = d->data->symbian_thread_handle.Id(); TThreadPriority symPriority = calculateSymbianPriority(priority); diff --git a/src/gui/dialogs/qfiledialog_symbian.cpp b/src/gui/dialogs/qfiledialog_symbian.cpp index 1ffbf1dfe2..01c7b9b7db 100644 --- a/src/gui/dialogs/qfiledialog_symbian.cpp +++ b/src/gui/dialogs/qfiledialog_symbian.cpp @@ -143,8 +143,8 @@ static QString launchSymbianDialog(const QString dialogCaption, const QString st tryCount = 0; } else { // Symbian native file dialog doesn't allow accessing files outside C:/Data - // It will always leave in that case, so default into QDir::rootPath() in error cases. - QString dir = QDir::toNativeSeparators(QDir::rootPath()); + // It will always leave in that case, so default into QDir::homePath() in error cases. + QString dir = QDir::toNativeSeparators(QDir::homePath()); startFolder = qt_QString2TPtrC(dir); } } diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 9ea0b8387f..532af247da 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -9509,7 +9509,7 @@ QVariant QGraphicsLineItem::extension(const QVariant &variant) const QPixmap::createHeuristicMask(). The performance and memory consumption is similar to MaskShape. */ -extern QPainterPath qt_regionToPath(const QRegion ®ion); +extern Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion); class QGraphicsPixmapItemPrivate : public QGraphicsItemPrivate { diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index d2e21fba89..4e6f91637a 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1023,7 +1023,7 @@ void QGraphicsViewPrivate::freeStyleOptionsArray(QStyleOptionGraphicsItem *array delete [] array; } -extern QPainterPath qt_regionToPath(const QRegion ®ion); +extern Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion); /*! ### Adjustments in findItems: mapToScene(QRect) forces us to adjust the diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 587c0f2d31..1518d2ddf4 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -552,11 +552,13 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) // the control's window qwidget->d_func()->createExtra(); - SetFocusing(true); - m_longTapDetector = QLongTapTimer::NewL(this); - m_doubleClickTimer.invalidate(); + if (!qwidget->d_func()->isGLGlobalShareWidget) { + SetFocusing(true); + m_longTapDetector = QLongTapTimer::NewL(this); + m_doubleClickTimer.invalidate(); - DrawableWindow()->SetPointerGrab(ETrue); + DrawableWindow()->SetPointerGrab(ETrue); + } } #ifdef Q_SYMBIAN_TRANSITION_EFFECTS @@ -590,25 +592,27 @@ void QSymbianControl::ConstructL(bool isWindowOwning, bool desktop) QSymbianControl::~QSymbianControl() { - // Ensure backing store is deleted before the top-level - // window is destroyed - QT_TRY { - qt_widget_private(qwidget)->topData()->backingStore.destroy(); - } QT_CATCH(const std::exception&) { - // ignore exceptions, nothing can be done - } - - if (S60->curWin == this) - S60->curWin = 0; - if (!QApplicationPrivate::is_app_closing) { + if (!qwidget->d_func()->isGLGlobalShareWidget) { // GLGlobalShareWidget doesn't interact with scene + // Ensure backing store is deleted before the top-level + // window is destroyed QT_TRY { - setFocusSafely(false); + qt_widget_private(qwidget)->topData()->backingStore.destroy(); } QT_CATCH(const std::exception&) { // ignore exceptions, nothing can be done } + + if (S60->curWin == this) + S60->curWin = 0; + if (!QApplicationPrivate::is_app_closing) { + QT_TRY { + setFocusSafely(false); + } QT_CATCH(const std::exception&) { + // ignore exceptions, nothing can be done + } + } + S60->appUi()->RemoveFromStack(this); + delete m_longTapDetector; } - S60->appUi()->RemoveFromStack(this); - delete m_longTapDetector; } void QSymbianControl::setWidget(QWidget *w) @@ -826,7 +830,8 @@ void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent) const TPointerEvent *pointerEvent = eventData.Pointer(i); const TAdvancedPointerEvent *advEvent = pointerEvent->AdvancedPointerEvent(); if (!advEvent || advEvent->PointerNumber() == 0) { - m_longTapDetector->PointerEventL(*pointerEvent); + if (m_longTapDetector) + m_longTapDetector->PointerEventL(*pointerEvent); QT_TRYCATCH_LEAVING(HandlePointerEvent(*pointerEvent)); } } @@ -843,8 +848,8 @@ void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent) } } #endif - - m_longTapDetector->PointerEventL(pEvent); + if (m_longTapDetector) + m_longTapDetector->PointerEventL(pEvent); QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent)); } @@ -1535,6 +1540,10 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) if (m_ignoreFocusChanged || (qwidget->windowType() & Qt::WindowType_Mask) == Qt::Desktop) return; + // just in case + if (qwidget->d_func()->isGLGlobalShareWidget) + return; + #ifdef Q_WS_S60 if (S60->splitViewLastWidget) return; @@ -1710,7 +1719,8 @@ void QSymbianControl::HandleResourceChange(int resourceType) } void QSymbianControl::CancelLongTapTimer() { - m_longTapDetector->Cancel(); + if (m_longTapDetector) + m_longTapDetector->Cancel(); } TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id) @@ -1723,6 +1733,9 @@ TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id) void QSymbianControl::setFocusSafely(bool focus) { + if (qwidget->d_func()->isGLGlobalShareWidget) + return; + // The stack hack in here is very unfortunate, but it is the only way to ensure proper // focus in Symbian. If this is not executed, the control which happens to be on // the top of the stack may randomly be assigned focus by Symbian, for example diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 7055c6b4b7..bceda662f0 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -314,6 +314,7 @@ QWidgetPrivate::QWidgetPrivate(int version) #elif defined(Q_OS_SYMBIAN) , symbianScreenNumber(0) , fixNativeOrientationCalled(false) + , isGLGlobalShareWidget(0) #endif { if (!qApp) { diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 9ac94795d5..94c1d630b1 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -916,6 +916,7 @@ public: void reparentChildren(); void registerTouchWindow(); QList<WId> widCleanupList; + uint isGLGlobalShareWidget : 1; #endif }; diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index a37c265f8e..fefa781fb5 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -393,16 +393,18 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de stackingFlags = ECoeStackFlagStandard; } control->MakeVisible(false); - QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags)); - // Avoid keyboard focus to a hidden window. - control->setFocusSafely(false); - RDrawableWindow *const drawableWindow = control->DrawableWindow(); - // Request mouse move events. - drawableWindow->PointerFilter(EPointerFilterEnterExit - | EPointerFilterMove | EPointerFilterDrag, 0); - drawableWindow->EnableVisibilityChangeEvents(); + if (!isGLGlobalShareWidget) { + QT_TRAP_THROWING(control->ControlEnv()->AppUi()->AddToStackL(control.data(), ECoeStackPriorityDefault, stackingFlags)); + // Avoid keyboard focus to a hidden window. + control->setFocusSafely(false); + RDrawableWindow *const drawableWindow = control->DrawableWindow(); + // Request mouse move events. + drawableWindow->PointerFilter(EPointerFilterEnterExit + | EPointerFilterMove | EPointerFilterDrag, 0); + drawableWindow->EnableVisibilityChangeEvents(); + } } q->setAttribute(Qt::WA_WState_Created); diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp index 6209e66a7b..2c91f1d417 100644 --- a/src/gui/painting/qmatrix.cpp +++ b/src/gui/painting/qmatrix.cpp @@ -654,7 +654,7 @@ QPolygonF QMatrix::map(const QPolygonF &a) const \sa QMatrix::map() */ -extern QPainterPath qt_regionToPath(const QRegion ®ion); +extern Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion); /*! \fn QRegion QMatrix::map(const QRegion ®ion) const diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 72357a6869..619dbdd1b3 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -2663,7 +2663,7 @@ QRegion QPainter::clipRegion() const return region; } -extern QPainterPath qt_regionToPath(const QRegion ®ion); +extern Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion); /*! Returns the currently clip as a path. Note that the clip path is diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 958e49907b..2954190012 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1231,7 +1231,7 @@ void QPdfBaseEngine::setupGraphicsState(QPaintEngine::DirtyFlags flags) setPen(); } -extern QPainterPath qt_regionToPath(const QRegion ®ion); +extern Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion); void QPdfBaseEngine::updateClipPath(const QPainterPath &p, Qt::ClipOperation op) { diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index 4d7b3391a6..be263bb23e 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -1454,7 +1454,7 @@ QPolygon QTransform::map(const QPolygon &a) const \sa QTransform::map() */ -extern QPainterPath qt_regionToPath(const QRegion ®ion); +extern Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion); /*! \fn QRegion QTransform::map(const QRegion ®ion) const diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index 3e5365c7a7..ec7923773e 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -1111,8 +1111,10 @@ void QMenuBar::setVisible(bool visible) #else #if defined(Q_WS_MAC) || defined(Q_OS_WINCE) || defined(Q_WS_S60) if (isNativeMenuBar()) { +#ifndef Q_WS_S60 if (!visible) QWidget::setVisible(false); +#endif return; } #endif diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 0365703f9c..33e3be9802 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -375,9 +375,23 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket if (priv->phase == QAuthenticatorPrivate::Done) { pauseConnection(); if (!isProxy) { + if (channels[i].authenticationCredentialsSent) { + auth->detach(); + priv = QAuthenticatorPrivate::getPrivate(*auth); + priv->hasFailed = true; + priv->phase = QAuthenticatorPrivate::Done; + channels[i].authenticationCredentialsSent = false; + } emit reply->authenticationRequired(reply->request(), auth); #ifndef QT_NO_NETWORKPROXY } else { + if (channels[i].proxyCredentialsSent) { + auth->detach(); + priv = QAuthenticatorPrivate::getPrivate(*auth); + priv->hasFailed = true; + priv->phase = QAuthenticatorPrivate::Done; + channels[i].proxyCredentialsSent = false; + } emit reply->proxyAuthenticationRequired(networkProxy, auth); #endif } @@ -415,7 +429,6 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket reply->d_func()->errorString = errorDetail(errorCode, socket); emit reply->finishedWithError(errorCode, reply->d_func()->errorString); // ### at this point the reply could be deleted - socket->close(); return true; } //resend the request @@ -438,6 +451,7 @@ void QHttpNetworkConnectionPrivate::createAuthorization(QAbstractSocket *socket, if (priv && priv->method != QAuthenticatorPrivate::None) { QByteArray response = priv->calculateResponse(request.d->methodName(), request.d->uri(false)); request.setHeaderField("Authorization", response); + channels[i].authenticationCredentialsSent = true; } } } @@ -449,6 +463,7 @@ void QHttpNetworkConnectionPrivate::createAuthorization(QAbstractSocket *socket, if (priv && priv->method != QAuthenticatorPrivate::None) { QByteArray response = priv->calculateResponse(request.d->methodName(), request.d->uri(false)); request.setHeaderField("Proxy-Authorization", response); + channels[i].proxyCredentialsSent = true; } } } @@ -582,9 +597,13 @@ void QHttpNetworkConnectionPrivate::fillPipeline(QAbstractSocket *socket) // we do not like authentication stuff // ### make sure to be OK with this in later releases - if (!channels[i].authenticator.isNull() || !channels[i].authenticator.user().isEmpty()) + if (!channels[i].authenticator.isNull() + && (!channels[i].authenticator.user().isEmpty() + || !channels[i].authenticator.password().isEmpty())) return; - if (!channels[i].proxyAuthenticator.isNull() || !channels[i].proxyAuthenticator.user().isEmpty()) + if (!channels[i].proxyAuthenticator.isNull() + && (!channels[i].proxyAuthenticator.user().isEmpty() + || !channels[i].proxyAuthenticator.password().isEmpty())) return; // must be in ReadingState or WaitingState diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index b9db7fe7ec..628114ae2a 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -73,6 +73,8 @@ QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel() , lastStatus(0) , pendingEncrypt(false) , reconnectAttempts(2) + , authenticationCredentialsSent(false) + , proxyCredentialsSent(false) , authMethod(QAuthenticatorPrivate::None) , proxyAuthMethod(QAuthenticatorPrivate::None) #ifndef QT_NO_OPENSSL @@ -555,6 +557,14 @@ bool QHttpNetworkConnectionChannel::ensureConnection() // reset state pipeliningSupported = PipeliningSupportUnknown; + authenticationCredentialsSent = false; + proxyCredentialsSent = false; + authenticator.detach(); + QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(authenticator); + priv->hasFailed = false; + proxyAuthenticator.detach(); + priv = QAuthenticatorPrivate::getPrivate(proxyAuthenticator); + priv->hasFailed = false; // This workaround is needed since we use QAuthenticator for NTLM authentication. The "phase == Done" // is the usual criteria for emitting authentication signals. The "phase" is set to "Done" when the @@ -562,7 +572,7 @@ bool QHttpNetworkConnectionChannel::ensureConnection() // check the "phase" for generating the Authorization header. NTLM authentication is a two stage // process & needs the "phase". To make sure the QAuthenticator uses the current username/password // the phase is reset to Start. - QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(authenticator); + priv = QAuthenticatorPrivate::getPrivate(authenticator); if (priv && priv->phase == QAuthenticatorPrivate::Done) priv->phase = QAuthenticatorPrivate::Start; priv = QAuthenticatorPrivate::getPrivate(proxyAuthenticator); @@ -837,6 +847,9 @@ void QHttpNetworkConnectionChannel::handleStatus() closeAndResendCurrentRequest(); QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } + } else { + //authentication cancelled, close the channel. + close(); } } else { emit reply->headerChanged(); diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index f635cc9557..31a286b3c8 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -113,6 +113,8 @@ public: QAuthenticatorPrivate::Method proxyAuthMethod; QAuthenticator authenticator; QAuthenticator proxyAuthenticator; + bool authenticationCredentialsSent; + bool proxyCredentialsSent; #ifndef QT_NO_OPENSSL bool ignoreAllSslErrors; QList<QSslError> ignoreSslErrorsList; diff --git a/src/network/access/qnetworkaccessauthenticationmanager.cpp b/src/network/access/qnetworkaccessauthenticationmanager.cpp index 1b15cf9cdf..9551b767df 100644 --- a/src/network/access/qnetworkaccessauthenticationmanager.cpp +++ b/src/network/access/qnetworkaccessauthenticationmanager.cpp @@ -159,6 +159,11 @@ void QNetworkAccessAuthenticationManager::cacheProxyCredentials(const QNetworkPr QString realm = authenticator->realm(); QNetworkProxy proxy = p; proxy.setUser(authenticator->user()); + + // don't cache null passwords, empty password may be valid though + if (authenticator->password().isNull()) + return; + // Set two credentials: one with the username and one without do { // Set two credentials actually: one with and one without the realm @@ -283,9 +288,12 @@ QNetworkAccessAuthenticationManager::fetchCachedCredentials(const QUrl &url, QNetworkAuthenticationCache *auth = static_cast<QNetworkAuthenticationCache *>(authenticationCache.requestEntryNow(cacheKey)); - QNetworkAuthenticationCredential cred = *auth->findClosestMatch(url.path()); + QNetworkAuthenticationCredential *cred = auth->findClosestMatch(url.path()); + QNetworkAuthenticationCredential ret; + if (cred) + ret = *cred; authenticationCache.releaseEntry(cacheKey); - return cred; + return ret; } void QNetworkAccessAuthenticationManager::clearCache() diff --git a/src/network/access/qnetworkaccessauthenticationmanager_p.h b/src/network/access/qnetworkaccessauthenticationmanager_p.h index ddfc11606d..718c58fc8d 100644 --- a/src/network/access/qnetworkaccessauthenticationmanager_p.h +++ b/src/network/access/qnetworkaccessauthenticationmanager_p.h @@ -73,7 +73,7 @@ public: QString user; QString password; bool isNull() { - return domain.isNull(); + return domain.isNull() && user.isNull() && password.isNull(); } }; Q_DECLARE_TYPEINFO(QNetworkAuthenticationCredential, Q_MOVABLE_TYPE); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 8fc8eb768d..689441eebf 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -61,7 +61,7 @@ #include "QtCore/qbuffer.h" #include "QtCore/qurl.h" #include "QtCore/qvector.h" -#include "QtNetwork/qauthenticator.h" +#include "QtNetwork/private/qauthenticator_p.h" #include "QtNetwork/qsslconfiguration.h" #include "QtNetwork/qnetworkconfigmanager.h" #include "QtNetwork/qhttpmultipart.h" @@ -1093,14 +1093,8 @@ void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(QNetworkAccessBac QAuthenticator *authenticator) { Q_Q(QNetworkAccessManager); - // ### FIXME Tracking of successful authentications - // This code is a bit broken right now for SOCKS authentication - // first request: proxyAuthenticationRequired gets emitted, credentials gets saved - // second request: (proxy != backend->reply->lastProxyAuthentication) does not evaluate to true, - // proxyAuthenticationRequired gets emitted again - // possible solution: some tracking inside the authenticator - // or a new function proxyAuthenticationSucceeded(true|false) - if (proxy != backend->reply->lastProxyAuthentication) { + QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(*authenticator); + if (proxy != backend->reply->lastProxyAuthentication && (!priv || !priv->hasFailed)) { QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy); if (!cred.isNull()) { authenticator->setUser(cred.user); diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index 0423e2224d..d0524eec64 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -220,12 +220,6 @@ void QAuthenticator::setUser(const QString &user) d->userDomain = user.left(separatorPosn); d->extractedUser = user.mid(separatorPosn + 1); d->user = user; - } else if((separatorPosn = user.indexOf(QLatin1String("@"))) != -1) { - //domain name is present - d->realm.clear(); - d->userDomain = user.mid(separatorPosn + 1); - d->extractedUser = user.left(separatorPosn); - d->user = user; } else { d->extractedUser = user; d->user = user; @@ -332,6 +326,7 @@ bool QAuthenticator::isNull() const QAuthenticatorPrivate::QAuthenticatorPrivate() : ref(0) , method(None) + , hasFailed(false) , phase(Start) , nonceCount(0) { @@ -393,8 +388,7 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt switch(method) { case Basic: - if(realm.isEmpty()) - this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm")); + this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm")); if (user.isEmpty() && password.isEmpty()) phase = Done; break; @@ -402,8 +396,7 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt // #### extract from header break; case DigestMd5: { - if(realm.isEmpty()) - this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm")); + this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm")); if (options.value("stale").toLower() == "true") phase = Start; if (user.isEmpty() && password.isEmpty()) @@ -1381,8 +1374,9 @@ static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phas int offset = QNtlmPhase3BlockBase::Size; Q_ASSERT(QNtlmPhase3BlockBase::Size == sizeof(QNtlmPhase3BlockBase)); - - if(ctx->userDomain.isEmpty()) { + + // for kerberos style user@domain logins, NTLM domain string should be left empty + if (ctx->userDomain.isEmpty() && !ctx->extractedUser.contains(QLatin1Char('@'))) { offset = qEncodeNtlmString(pb.domain, offset, ch.targetNameStr, unicode); pb.domainStr = ch.targetNameStr; } else { diff --git a/src/network/kernel/qauthenticator_p.h b/src/network/kernel/qauthenticator_p.h index 88a30511b1..937f4e0f04 100644 --- a/src/network/kernel/qauthenticator_p.h +++ b/src/network/kernel/qauthenticator_p.h @@ -77,6 +77,7 @@ public: Method method; QString realm; QByteArray challenge; + bool hasFailed; //credentials have been tried but rejected by server. enum Phase { Start, diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index b62bc05d22..c582c57a7f 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -136,6 +136,8 @@ bool QHttpSocketEngine::connectInternal() { Q_D(QHttpSocketEngine); + d->credentialsSent = false; + // If the handshake is done, enter ConnectedState state and return true. if (d->state == Connected) { qWarning("QHttpSocketEngine::connectToHost: called when already connected"); @@ -514,6 +516,7 @@ void QHttpSocketEngine::slotSocketConnected() QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(d->authenticator); //qDebug() << "slotSocketConnected: priv=" << priv << (priv ? (int)priv->method : -1); if (priv && priv->method != QAuthenticatorPrivate::None) { + d->credentialsSent = true; data += "Proxy-Authorization: " + priv->calculateResponse(method, path); data += "\r\n"; } @@ -591,15 +594,26 @@ void QHttpSocketEngine::slotSocketReadNotification() d->readBuffer.clear(); // we parsed the proxy protocol response. from now on direct socket reading will be done int statusCode = responseHeader.statusCode(); + QAuthenticatorPrivate *priv = 0; if (statusCode == 200) { d->state = Connected; setLocalAddress(d->socket->localAddress()); setLocalPort(d->socket->localPort()); setState(QAbstractSocket::ConnectedState); + d->authenticator.detach(); + priv = QAuthenticatorPrivate::getPrivate(d->authenticator); + priv->hasFailed = false; } else if (statusCode == 407) { - if (d->authenticator.isNull()) + if (d->credentialsSent) { + //407 response again means the provided username/password were invalid. + d->authenticator = QAuthenticator(); //this is needed otherwise parseHttpResponse won't set the state, and then signal isn't emitted. + d->authenticator.detach(); + priv = QAuthenticatorPrivate::getPrivate(d->authenticator); + priv->hasFailed = true; + } + else if (d->authenticator.isNull()) d->authenticator.detach(); - QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(d->authenticator); + priv = QAuthenticatorPrivate::getPrivate(d->authenticator); priv->parseHttpResponse(responseHeader, true); @@ -639,7 +653,6 @@ void QHttpSocketEngine::slotSocketReadNotification() if (priv->phase == QAuthenticatorPrivate::Done) emit proxyAuthenticationRequired(d->proxy, &d->authenticator); - // priv->phase will get reset to QAuthenticatorPrivate::Start if the authenticator got modified in the signal above. if (priv->phase == QAuthenticatorPrivate::Done) { setError(QAbstractSocket::ProxyAuthenticationRequiredError, tr("Authentication required")); @@ -796,6 +809,7 @@ QHttpSocketEnginePrivate::QHttpSocketEnginePrivate() , readNotificationPending(false) , writeNotificationPending(false) , connectionNotificationPending(false) + , credentialsSent(false) , pendingResponseData(0) { socket = 0; diff --git a/src/network/socket/qhttpsocketengine_p.h b/src/network/socket/qhttpsocketengine_p.h index d7cc7c1604..476d689c11 100644 --- a/src/network/socket/qhttpsocketengine_p.h +++ b/src/network/socket/qhttpsocketengine_p.h @@ -182,6 +182,7 @@ public: bool readNotificationPending; bool writeNotificationPending; bool connectionNotificationPending; + bool credentialsSent; uint pendingResponseData; }; diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 872b19cc68..900bfdb2e9 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1044,10 +1044,17 @@ void QSslSocketBackendPrivate::transmit() int encryptedBytesRead = q_BIO_read(writeBio, data.data(), pendingBytes); // Write encrypted data from the buffer to the socket. - plainSocket->write(data.constData(), encryptedBytesRead); + qint64 actualWritten = plainSocket->write(data.constData(), encryptedBytesRead); #ifdef QSSLSOCKET_DEBUG - qDebug() << "QSslSocketBackendPrivate::transmit: wrote" << encryptedBytesRead << "encrypted bytes to the socket"; + qDebug() << "QSslSocketBackendPrivate::transmit: wrote" << encryptedBytesRead << "encrypted bytes to the socket" << actualWritten << "actual."; #endif + if (actualWritten < 0) { + //plain socket write fails if it was in the pending close state. + q->setErrorString(plainSocket->errorString()); + q->setSocketError(plainSocket->error()); + emit q->error(plainSocket->error()); + return; + } transmitting = true; } diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index df09dfdf6d..89153d9398 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -106,6 +106,10 @@ class QMacWindowChangeEvent; class QWSGLWindowSurface; #endif +#ifdef Q_OS_SYMBIAN +extern bool qt_initializing_gl_share_widget(); +#endif + #ifndef QT_NO_EGL class QEglContext; #endif @@ -183,6 +187,10 @@ public: #endif { isGLWidget = 1; +#if defined(Q_OS_SYMBIAN) + if (qt_initializing_gl_share_widget()) + isGLGlobalShareWidget = 1; +#endif } ~QGLWidgetPrivate() {} diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index a15084b0c9..d512946c01 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -184,28 +184,29 @@ QGLGraphicsSystem::QGLGraphicsSystem(bool useX11GL) class QGLGlobalShareWidget { public: - QGLGlobalShareWidget() : widget(0), initializing(false) { + QGLGlobalShareWidget() : widget(0), init(false) { created = true; } QGLWidget *shareWidget() { - if (!initializing && !widget && !cleanedUp) { - initializing = true; + if (!init && !widget && !cleanedUp) { + init = true; widget = new QGLWidget(QGLFormat(QGL::SingleBuffer | QGL::NoDepthBuffer | QGL::NoStencilBuffer)); #ifdef Q_OS_SYMBIAN if (!widget->context()->isValid()) { delete widget; widget = 0; - initializing = false; + init = false; return 0; } #endif + widget->resize(1, 1); // We don't need this internal widget to appear in QApplication::topLevelWidgets() if (QWidgetPrivate::allWidgets) QWidgetPrivate::allWidgets->remove(widget); - initializing = false; + init = false; } return widget; } @@ -232,12 +233,17 @@ public: cleanedUp = false; } + bool initializing() + { + return init; + } + static bool cleanedUp; static bool created; private: QGLWidget *widget; - bool initializing; + bool init; }; bool QGLGlobalShareWidget::cleanedUp = false; @@ -268,6 +274,13 @@ void qt_destroy_gl_share_widget() _qt_gl_share_widget()->destroy(); } +bool qt_initializing_gl_share_widget() +{ + if (QGLGlobalShareWidget::created) + return _qt_gl_share_widget()->initializing(); + return false; +} + const QGLContext *qt_gl_share_context() { QGLWidget *widget = qt_gl_share_widget(); diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h index 91d1f9e245..6c8b71fe6b 100644 --- a/src/opengl/qwindowsurface_gl_p.h +++ b/src/opengl/qwindowsurface_gl_p.h @@ -68,6 +68,7 @@ struct QGLWindowSurfacePrivate; Q_OPENGL_EXPORT QGLWidget* qt_gl_share_widget(); Q_OPENGL_EXPORT void qt_destroy_gl_share_widget(); +bool qt_initializing_gl_share_widget(); class QGLWindowSurfaceGLPaintDevice : public QGLPaintDevice { diff --git a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp index aa4c014d99..cb6b2f6605 100644 --- a/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp +++ b/tests/auto/declarative/qdeclarativevaluetypes/tst_qdeclarativevaluetypes.cpp @@ -52,7 +52,7 @@ #endif QT_BEGIN_NAMESPACE -extern int qt_defaultDpi(); +extern Q_GUI_EXPORT int qt_defaultDpi(); QT_END_NAMESPACE class tst_qdeclarativevaluetypes : public QObject diff --git a/tests/auto/qcssparser/qcssparser.pro b/tests/auto/qcssparser/qcssparser.pro index fc3daa3af6..0600860ce6 100644 --- a/tests/auto/qcssparser/qcssparser.pro +++ b/tests/auto/qcssparser/qcssparser.pro @@ -10,8 +10,11 @@ requires(contains(QT_CONFIG,private_tests)) wince*|symbian: { addFiles.files = testdata addFiles.path = . + DEPLOYMENT += addFiles +} +wince* { timesFont.files = c:/windows/fonts/times.ttf timesFont.path = . - DEPLOYMENT += addFiles timesFont + DEPLOYMENT += timesFont } diff --git a/tests/auto/qgl/tst_qgl.cpp b/tests/auto/qgl/tst_qgl.cpp index 9c51e026d2..27c8ced106 100644 --- a/tests/auto/qgl/tst_qgl.cpp +++ b/tests/auto/qgl/tst_qgl.cpp @@ -648,7 +648,7 @@ void tst_QGL::getSetCheck() #ifdef QT_BUILD_INTERNAL QT_BEGIN_NAMESPACE -extern QGLFormat::OpenGLVersionFlags qOpenGLVersionFlagsFromString(const QString &versionString); +extern Q_AUTOTEST_EXPORT QGLFormat::OpenGLVersionFlags qOpenGLVersionFlagsFromString(const QString &versionString); QT_END_NAMESPACE #endif diff --git a/tests/auto/qlayout/tst_qlayout.cpp b/tests/auto/qlayout/tst_qlayout.cpp index 96f88634bc..be3998f911 100644 --- a/tests/auto/qlayout/tst_qlayout.cpp +++ b/tests/auto/qlayout/tst_qlayout.cpp @@ -60,6 +60,10 @@ # include <QtGui/QMacStyle> #endif +#if defined(Q_OS_SYMBIAN) +# define SRCDIR "." +#endif + //TESTED_CLASS= //TESTED_FILES= diff --git a/tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp b/tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp index 7296f3433b..148f35516e 100644 --- a/tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp +++ b/tests/auto/qmdisubwindow/tst_qmdisubwindow.cpp @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE extern void qt_x11_wait_for_window_manager(QWidget *w); #endif #if !defined(Q_WS_WIN) -extern bool qt_tab_all_widgets; +extern Q_GUI_EXPORT bool qt_tab_all_widgets; #endif QT_END_NAMESPACE diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index 371ac5785e..6760b73ef7 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -380,6 +380,9 @@ private Q_SLOTS: void httpAbort(); void dontInsertPartialContentIntoTheCache(); + void authenticationCacheAfterCancel_data(); + void authenticationCacheAfterCancel(); + void authenticationWithDifferentRealm(); void synchronousAuthenticationCache(); void pipelining(); @@ -6026,6 +6029,221 @@ void tst_QNetworkReply::qtbug4121unknownAuthentication() QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError); } +void tst_QNetworkReply::authenticationCacheAfterCancel_data() +{ + QTest::addColumn<QNetworkProxy>("proxy"); + QTest::addColumn<bool>("proxyAuth"); + QTest::addColumn<QUrl>("url"); + for (int i = 0; i < proxies.count(); ++i) { + QTest::newRow("http" + proxies.at(i).tag) << proxies.at(i).proxy << proxies.at(i).requiresAuthentication << QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt"); +#ifndef QT_NO_OPENSSL + QTest::newRow("https" + proxies.at(i).tag) << proxies.at(i).proxy << proxies.at(i).requiresAuthentication << QUrl("https://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt"); +#endif + } +} + +class AuthenticationCacheHelper : public QObject +{ + Q_OBJECT +public: + AuthenticationCacheHelper() + {} +public slots: + void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth) + { + if (!proxyPassword.isNull()) { + auth->setUser(proxyUserName); + auth->setPassword(proxyPassword); + //clear credentials, if they are asked again, they were bad + proxyUserName.clear(); + proxyPassword.clear(); + } + } + void authenticationRequired(QNetworkReply*,QAuthenticator *auth) + { + if (!httpPassword.isNull()) { + auth->setUser(httpUserName); + auth->setPassword(httpPassword); + //clear credentials, if they are asked again, they were bad + httpUserName.clear(); + httpPassword.clear(); + } + } +public: + QString httpUserName; + QString httpPassword; + QString proxyUserName; + QString proxyPassword; +}; + +/* Purpose of this test is to check credentials are cached correctly. + - If user cancels authentication dialog (i.e. nothing is set to the QAuthenticator by the callback) then this is not cached + - if user supplies a wrong password, then this is not cached + - if user supplies a correct user/password combination then this is cached + + Test is checking both the proxyAuthenticationRequired and authenticationRequired signals. + */ +void tst_QNetworkReply::authenticationCacheAfterCancel() +{ + QFETCH(QNetworkProxy, proxy); + QFETCH(bool, proxyAuth); + QFETCH(QUrl, url); + QNetworkAccessManager manager; +#ifndef QT_NO_OPENSSL + connect(&manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), + SLOT(sslErrors(QNetworkReply*,QList<QSslError>))); +#endif + manager.setProxy(proxy); + QSignalSpy authSpy(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*))); + QSignalSpy proxyAuthSpy(&manager, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *))); + + AuthenticationCacheHelper helper; + connect(&manager, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), &helper, SLOT(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *))); + connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), &helper, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + + QNetworkRequest request(url); + QNetworkReplyPtr reply; + if (proxyAuth) { + //should fail due to no credentials + reply = manager.get(request); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(reply->error(), QNetworkReply::ProxyAuthenticationRequiredError); + QCOMPARE(authSpy.count(), 0); + QCOMPARE(proxyAuthSpy.count(), 1); + proxyAuthSpy.clear(); + + //should fail due to bad credentials + helper.proxyUserName = "qsockstest"; + helper.proxyPassword = "badpassword"; + reply = manager.get(request); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QEXPECT_FAIL("http+socksauth", "QTBUG-23136 - danted accepts bad authentication but blocks the connection", Continue); + QEXPECT_FAIL("https+socksauth", "QTBUG-23136 - danted accepts bad authentication but blocks the connection", Continue); + + QCOMPARE(reply->error(), QNetworkReply::ProxyAuthenticationRequiredError); + QCOMPARE(authSpy.count(), 0); + QVERIFY(proxyAuthSpy.count() > 0); + proxyAuthSpy.clear(); + + //QTBUG-23136 workaround + if (proxy.port() == 1081) { +#ifdef QT_BUILD_INTERNAL + QNetworkAccessManagerPrivate::clearCache(&manager); +#else + return; //XFAIL result above +#endif + } + + //next proxy auth should succeed, due to correct credentials + helper.proxyUserName = "qsockstest"; + helper.proxyPassword = "password"; + } + + //should fail due to no credentials + reply = manager.get(request); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError); + QVERIFY(authSpy.count() > 0); + authSpy.clear(); + if (proxyAuth) { + QVERIFY(proxyAuthSpy.count() > 0); + proxyAuthSpy.clear(); + } + + //should fail due to bad credentials + helper.httpUserName = "baduser"; + helper.httpPassword = "badpassword"; + reply = manager.get(request); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(reply->error(), QNetworkReply::AuthenticationRequiredError); + QVERIFY(authSpy.count() > 0); + authSpy.clear(); + if (proxyAuth) { + //should be supplied from cache + QCOMPARE(proxyAuthSpy.count(), 0); + proxyAuthSpy.clear(); + } + + //next auth should succeed, due to correct credentials + helper.httpUserName = "httptest"; + helper.httpPassword = "httptest"; + + reply = manager.get(request); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(reply->error(), QNetworkReply::NoError); + QVERIFY(authSpy.count() > 0); + authSpy.clear(); + if (proxyAuth) { + //should be supplied from cache + QCOMPARE(proxyAuthSpy.count(), 0); + proxyAuthSpy.clear(); + } + + //next auth should use cached credentials + reply = manager.get(request); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(reply->error(), QNetworkReply::NoError); + //should be supplied from cache + QCOMPARE(authSpy.count(), 0); + authSpy.clear(); + if (proxyAuth) { + //should be supplied from cache + QCOMPARE(proxyAuthSpy.count(), 0); + proxyAuthSpy.clear(); + } + +} + +void tst_QNetworkReply::authenticationWithDifferentRealm() +{ + AuthenticationCacheHelper helper; + QNetworkAccessManager manager; +#ifndef QT_NO_OPENSSL + connect(&manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), + SLOT(sslErrors(QNetworkReply*,QList<QSslError>))); +#endif + connect(&manager, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), &helper, SLOT(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *))); + connect(&manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), &helper, SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*))); + + helper.httpUserName = "httptest"; + helper.httpPassword = "httptest"; + + QNetworkRequest request(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/rfcs-auth/rfc3252.txt")); + QNetworkReply* reply = manager.get(request); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(reply->error(), QNetworkReply::NoError); + + helper.httpUserName = "httptest"; + helper.httpPassword = "httptest"; + + request.setUrl(QUrl("http://" + QtNetworkSettings::serverName() + "/qtest/auth-digest/")); + reply = manager.get(request); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()), Qt::QueuedConnection); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + QCOMPARE(reply->error(), QNetworkReply::NoError); +} + class QtBug13431Helper : public QObject { Q_OBJECT public: diff --git a/tests/auto/qpixmapcache/tst_qpixmapcache.cpp b/tests/auto/qpixmapcache/tst_qpixmapcache.cpp index b36cf9891a..b5d8887f14 100644 --- a/tests/auto/qpixmapcache/tst_qpixmapcache.cpp +++ b/tests/auto/qpixmapcache/tst_qpixmapcache.cpp @@ -499,7 +499,7 @@ void tst_QPixmapCache::pixmapKey() } QT_BEGIN_NAMESPACE -extern int q_QPixmapCache_keyHashSize(); +extern Q_AUTOTEST_EXPORT int q_QPixmapCache_keyHashSize(); QT_END_NAMESPACE void tst_QPixmapCache::noLeak() diff --git a/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp b/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp index 5634285ad4..7b7784c78c 100644 --- a/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp +++ b/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp @@ -425,7 +425,7 @@ void tst_QPixmapFilter::dropShadowBoundingRectFor() } QT_BEGIN_NAMESPACE -void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed); +Q_GUI_EXPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed); QT_END_NAMESPACE void tst_QPixmapFilter::blurIndexed8() diff --git a/tests/auto/qregion/tst_qregion.cpp b/tests/auto/qregion/tst_qregion.cpp index bbc09c9b57..f06d848477 100644 --- a/tests/auto/qregion/tst_qregion.cpp +++ b/tests/auto/qregion/tst_qregion.cpp @@ -977,7 +977,7 @@ void tst_QRegion::regionToPath_data() #ifdef QT_BUILD_INTERNAL QT_BEGIN_NAMESPACE -extern QPainterPath qt_regionToPath(const QRegion ®ion); +extern Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion); QT_END_NAMESPACE #endif diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index 14c204e6af..435b5e2f6e 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -53,7 +53,7 @@ Q_DECLARE_METATYPE(QScriptValueList) Q_DECLARE_METATYPE(QScriptContext::Error) QT_BEGIN_NAMESPACE -extern bool qt_script_isJITEnabled(); +extern Q_AUTOTEST_EXPORT bool qt_script_isJITEnabled(); QT_END_NAMESPACE class tst_QScriptContext : public QObject diff --git a/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.pro b/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.pro index e184ca4ee5..e1701e3f01 100644 --- a/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.pro +++ b/tests/auto/qscriptextensionplugin/simpleplugin/simpleplugin.pro @@ -7,4 +7,5 @@ DESTDIR = ../plugins/script symbian { TARGET.EPOCALLOWDLLDATA=1 + TARGET = qscriptextension_simpleplugin # Too generic target causes conflict on Symbian } diff --git a/tests/auto/qscriptextensionplugin/test/test.pro b/tests/auto/qscriptextensionplugin/test/test.pro index 549bac266c..223dafa356 100644 --- a/tests/auto/qscriptextensionplugin/test/test.pro +++ b/tests/auto/qscriptextensionplugin/test/test.pro @@ -3,7 +3,14 @@ load(qttest_p4) QT = core script SOURCES = ../tst_qscriptextensionplugin.cpp CONFIG -= app_bundle -LIBS += -L../plugins/script -lstaticplugin +symbian { + LIBS += -lstaticplugin.lib + simplePlugin.files = qscriptextension_simpleplugin.dll + simplePlugin.path = plugins/script + DEPLOYMENT += simplePlugin +} else { + LIBS += -L../plugins/script -lstaticplugin +} TARGET = tst_qscriptextensionplugin CONFIG(debug_and_release) { diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index e350d1e749..fc14dbcf60 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -666,7 +666,7 @@ void tst_QSvgRenderer::testGzLoading() #ifdef QT_BUILD_INTERNAL QT_BEGIN_NAMESPACE -QByteArray qt_inflateGZipDataFrom(QIODevice *device); +Q_AUTOTEST_EXPORT QByteArray qt_inflateGZipDataFrom(QIODevice *device); QT_END_NAMESPACE #endif diff --git a/tests/auto/qtextedit/tst_qtextedit.cpp b/tests/auto/qtextedit/tst_qtextedit.cpp index 73d09f4371..186623b91e 100644 --- a/tests/auto/qtextedit/tst_qtextedit.cpp +++ b/tests/auto/qtextedit/tst_qtextedit.cpp @@ -1968,7 +1968,7 @@ void tst_QTextEdit::setText() } QT_BEGIN_NAMESPACE -extern void qt_setQtEnableTestFont(bool value); +extern Q_AUTOTEST_EXPORT void qt_setQtEnableTestFont(bool value); QT_END_NAMESPACE void tst_QTextEdit::fullWidthSelection_data() diff --git a/tests/auto/qtextlayout/tst_qtextlayout.cpp b/tests/auto/qtextlayout/tst_qtextlayout.cpp index 67d8269d79..68f93e1037 100644 --- a/tests/auto/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/qtextlayout/tst_qtextlayout.cpp @@ -174,7 +174,7 @@ void tst_QTextLayout::getSetCheck() } QT_BEGIN_NAMESPACE -extern void qt_setQtEnableTestFont(bool value); +extern Q_AUTOTEST_EXPORT void qt_setQtEnableTestFont(bool value); QT_END_NAMESPACE tst_QTextLayout::tst_QTextLayout() @@ -1109,7 +1109,7 @@ void tst_QTextLayout::tabsForRtl() } QT_BEGIN_NAMESPACE -extern int qt_defaultDpiY(); +extern Q_GUI_EXPORT int qt_defaultDpiY(); QT_END_NAMESPACE void tst_QTextLayout::testTabDPIScale() |