Changeset 846 for trunk/src/network


Ignore:
Timestamp:
May 5, 2011, 5:36:53 AM (14 years ago)
Author:
Dmitry A. Kuminov
Message:

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

Location:
trunk
Files:
2 deleted
141 edited
21 copied

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/network/access/access.pri

    r561 r846  
    11# Qt network access module
    22
    3 HEADERS += access/qftp.h \
    4            access/qhttp.h \
    5            access/qhttpnetworkheader_p.h \
    6            access/qhttpnetworkrequest_p.h \
    7            access/qhttpnetworkreply_p.h \
    8            access/qhttpnetworkconnection_p.h \
    9            access/qhttpnetworkconnectionchannel_p.h \
    10            access/qfilenetworkreply_p.h \
    11            access/qnetworkaccessmanager.h \
    12            access/qnetworkaccessmanager_p.h \
    13            access/qnetworkaccesscache_p.h \
    14            access/qnetworkaccessbackend_p.h \
    15            access/qnetworkaccessdatabackend_p.h \
    16            access/qnetworkaccessdebugpipebackend_p.h \
    17            access/qnetworkaccesshttpbackend_p.h \
    18            access/qnetworkaccessfilebackend_p.h \
    19            access/qnetworkaccesscachebackend_p.h \
    20            access/qnetworkaccessftpbackend_p.h \
    21            access/qnetworkcookie.h \
    22            access/qnetworkcookie_p.h \
    23            access/qnetworkcookiejar.h \
    24            access/qnetworkcookiejar_p.h \
    25            access/qnetworkrequest.h \
    26            access/qnetworkrequest_p.h \
    27            access/qnetworkreply.h \
    28            access/qnetworkreply_p.h \
    29            access/qnetworkreplyimpl_p.h \
    30            access/qabstractnetworkcache_p.h \
    31            access/qabstractnetworkcache.h \
    32            access/qnetworkdiskcache_p.h \
    33            access/qnetworkdiskcache.h
     3HEADERS += \
     4    access/qftp.h \
     5    access/qhttp.h \
     6    access/qhttpnetworkheader_p.h \
     7    access/qhttpnetworkrequest_p.h \
     8    access/qhttpnetworkreply_p.h \
     9    access/qhttpnetworkconnection_p.h \
     10    access/qhttpnetworkconnectionchannel_p.h \
     11    access/qfilenetworkreply_p.h \
     12    access/qnetworkaccessmanager.h \
     13    access/qnetworkaccessmanager_p.h \
     14    access/qnetworkaccesscache_p.h \
     15    access/qnetworkaccessbackend_p.h \
     16    access/qnetworkaccessdatabackend_p.h \
     17    access/qnetworkaccessdebugpipebackend_p.h \
     18    access/qnetworkaccesshttpbackend_p.h \
     19    access/qnetworkaccessfilebackend_p.h \
     20    access/qnetworkaccesscachebackend_p.h \
     21    access/qnetworkaccessftpbackend_p.h \
     22    access/qnetworkcookie.h \
     23    access/qnetworkcookie_p.h \
     24    access/qnetworkcookiejar.h \
     25    access/qnetworkcookiejar_p.h \
     26    access/qnetworkcookiejartlds_p.h \
     27    access/qnetworkrequest.h \
     28    access/qnetworkrequest_p.h \
     29    access/qnetworkreply.h \
     30    access/qnetworkreply_p.h \
     31    access/qnetworkreplyimpl_p.h \
     32    access/qabstractnetworkcache_p.h \
     33    access/qabstractnetworkcache.h \
     34    access/qnetworkdiskcache_p.h \
     35    access/qnetworkdiskcache.h
    3436
    35 SOURCES += access/qftp.cpp \
    36            access/qhttp.cpp \
    37            access/qhttpnetworkheader.cpp \
    38            access/qhttpnetworkrequest.cpp \
    39            access/qhttpnetworkreply.cpp \
    40            access/qhttpnetworkconnection.cpp \
    41            access/qhttpnetworkconnectionchannel.cpp \
    42            access/qfilenetworkreply.cpp \
    43            access/qnetworkaccessmanager.cpp \
    44            access/qnetworkaccesscache.cpp \
    45            access/qnetworkaccessbackend.cpp \
    46            access/qnetworkaccessdatabackend.cpp \
    47            access/qnetworkaccessdebugpipebackend.cpp \
    48            access/qnetworkaccessfilebackend.cpp \
    49            access/qnetworkaccesscachebackend.cpp \
    50            access/qnetworkaccessftpbackend.cpp \
    51            access/qnetworkaccesshttpbackend.cpp \
    52            access/qnetworkcookie.cpp \
    53            access/qnetworkcookiejar.cpp \
    54            access/qnetworkrequest.cpp \
    55            access/qnetworkreply.cpp \
    56            access/qnetworkreplyimpl.cpp \
    57            access/qabstractnetworkcache.cpp \
    58            access/qnetworkdiskcache.cpp
     37SOURCES += \
     38    access/qftp.cpp \
     39    access/qhttp.cpp \
     40    access/qhttpnetworkheader.cpp \
     41    access/qhttpnetworkrequest.cpp \
     42    access/qhttpnetworkreply.cpp \
     43    access/qhttpnetworkconnection.cpp \
     44    access/qhttpnetworkconnectionchannel.cpp \
     45    access/qfilenetworkreply.cpp \
     46    access/qnetworkaccessmanager.cpp \
     47    access/qnetworkaccesscache.cpp \
     48    access/qnetworkaccessbackend.cpp \
     49    access/qnetworkaccessdatabackend.cpp \
     50    access/qnetworkaccessdebugpipebackend.cpp \
     51    access/qnetworkaccessfilebackend.cpp \
     52    access/qnetworkaccesscachebackend.cpp \
     53    access/qnetworkaccessftpbackend.cpp \
     54    access/qnetworkaccesshttpbackend.cpp \
     55    access/qnetworkcookie.cpp \
     56    access/qnetworkcookiejar.cpp \
     57    access/qnetworkrequest.cpp \
     58    access/qnetworkreply.cpp \
     59    access/qnetworkreplyimpl.cpp \
     60    access/qabstractnetworkcache.cpp \
     61    access/qnetworkdiskcache.cpp
    5962
    60 #zlib support
    61 contains(QT_CONFIG, zlib) {
    62    INCLUDEPATH += ../3rdparty/zlib
    63 } else:!contains(QT_CONFIG, no-zlib) {
    64    unix:LIBS_PRIVATE += -lz
    65 #  win32:LIBS += libz.lib
    66 }
     63include($$PWD/../../3rdparty/zlib_dependency.pri)
  • trunk/src/network/access/qabstractnetworkcache.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    313313    Writes \a metaData to the \a out stream.
    314314
    315     \sa {Format of the QDataStream operators}
     315    \sa {Serializing Qt Data Types}
    316316*/
    317317QDataStream &operator<<(QDataStream &out, const QNetworkCacheMetaData &metaData)
     
    351351    Reads a QNetworkCacheMetaData from the stream \a in into \a metaData.
    352352
    353     \sa {Format of the QDataStream operators}
     353    \sa {Serializing Qt Data Types}
    354354*/
    355355QDataStream &operator>>(QDataStream &in, QNetworkCacheMetaData &metaData)
  • trunk/src/network/access/qabstractnetworkcache.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qabstractnetworkcache_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qfilenetworkreply.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9898    QString fileName = url.toLocalFile();
    9999    if (fileName.isEmpty()) {
    100         fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery);
     100        if (url.scheme() == QLatin1String("qrc"))
     101            fileName = QLatin1Char(':') + url.path();
     102        else
     103            fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery);
    101104    }
    102105
  • trunk/src/network/access/qfilenetworkreply_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qftp.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    23122312
    23132313    if (pending.isEmpty()) {
    2314         qWarning() << "QFtpPrivate::_q_piError was called without pending command!";
     2314        qWarning("QFtpPrivate::_q_piError was called without pending command!");
    23152315        return;
    23162316    }
  • trunk/src/network/access/qftp.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qhttp.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    24432443            proxy.setType(QNetworkProxy::NoProxy);
    24442444        } else if (sslInUse) {
    2445             // Disallow use of cacheing proxy with HTTPS; instead fall back to
     2445            // Disallow use of caching proxy with HTTPS; instead fall back to
    24462446            // transparent HTTP CONNECT proxying.
    24472447            transparentProxyInUse = true;
  • trunk/src/network/access/qhttp.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qhttpnetworkconnection.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4040****************************************************************************/
    4141
     42#include <private/qabstractsocket_p.h>
    4243#include "qhttpnetworkconnection_p.h"
    4344#include "qhttpnetworkconnectionchannel_p.h"
     
    5758
    5859#ifndef QT_NO_OPENSSL
     60#    include <private/qsslsocket_p.h>
    5961#    include <QtNetwork/qsslkey.h>
    6062#    include <QtNetwork/qsslcipher.h>
     
    8082
    8183QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt)
    82 : hostName(hostName), port(port), encrypt(encrypt),
    83   channelCount(defaultChannelCount),
    84   pendingAuthSignal(false), pendingProxyAuthSignal(false)
     84: state(RunningState),
     85  hostName(hostName), port(port), encrypt(encrypt),
     86  channelCount(defaultChannelCount)
    8587#ifndef QT_NO_NETWORKPROXY
    8688  , networkProxy(QNetworkProxy::NoProxy)
     
    9193
    9294QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt)
    93 : hostName(hostName), port(port), encrypt(encrypt),
    94   channelCount(channelCount),
    95   pendingAuthSignal(false), pendingProxyAuthSignal(false)
     95: state(RunningState),
     96  hostName(hostName), port(port), encrypt(encrypt),
     97  channelCount(channelCount)
    9698#ifndef QT_NO_NETWORKPROXY
    9799  , networkProxy(QNetworkProxy::NoProxy)
     
    120122        channels[i].init();
    121123    }
     124}
     125
     126void QHttpNetworkConnectionPrivate::pauseConnection()
     127{
     128    state = PausedState;
     129
     130    // Disable all socket notifiers
     131    for (int i = 0; i < channelCount; i++) {
     132#ifndef QT_NO_OPENSSL
     133        if (encrypt)
     134            QSslSocketPrivate::pauseSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
     135        else
     136#endif
     137            QAbstractSocketPrivate::pauseSocketNotifiers(channels[i].socket);
     138    }
     139}
     140
     141void QHttpNetworkConnectionPrivate::resumeConnection()
     142{
     143    state = RunningState;
     144    // Enable all socket notifiers
     145    for (int i = 0; i < channelCount; i++) {
     146#ifndef QT_NO_OPENSSL
     147        if (encrypt)
     148            QSslSocketPrivate::resumeSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
     149        else
     150#endif
     151            QAbstractSocketPrivate::resumeSocketNotifiers(channels[i].socket);
     152
     153        // Resume pending upload if needed
     154        if (channels[i].state == QHttpNetworkConnectionChannel::WritingState)
     155            QMetaObject::invokeMethod(&channels[i], "_q_uploadDataReadyRead", Qt::QueuedConnection);
     156    }
     157
     158    // queue _q_startNextRequest
     159    QMetaObject::invokeMethod(this->q_func(), "_q_startNextRequest", Qt::QueuedConnection);
    122160}
    123161
     
    258296    Q_ASSERT(auth);
    259297
     298    // NTLM is a multi phase authentication. Copying credentials between authenticators would mess things up.
     299    if (!isProxy && channels[fromChannel].authMethod == QAuthenticatorPrivate::Ntlm)
     300        return;
     301    if (isProxy && channels[fromChannel].proxyAuthMethod == QAuthenticatorPrivate::Ntlm)
     302        return;
     303
     304
    260305    // select another channel
    261306    QAuthenticator* otherAuth = 0;
     
    283328    Q_ASSERT(reply);
    284329
    285     Q_Q(QHttpNetworkConnection);
    286 
    287330    resend = false;
    288331    //create the response header to be used with QAuthenticatorPrivate.
    289     QHttpResponseHeader responseHeader;
    290332    QList<QPair<QByteArray, QByteArray> > fields = reply->header();
    291     QList<QPair<QByteArray, QByteArray> >::const_iterator it = fields.constBegin();
    292     while (it != fields.constEnd()) {
    293         responseHeader.addValue(QString::fromLatin1(it->first), QString::fromUtf8(it->second));
    294         it++;
    295     }
     333
    296334    //find out the type of authentication protocol requested.
    297335    QAuthenticatorPrivate::Method authMethod = reply->d_func()->authenticationMethod(isProxy);
     
    302340        if (isProxy) {
    303341            auth = &channels[i].proxyAuthenticator;
    304             channels[i].proxyAuthMehtod = authMethod;
     342            channels[i].proxyAuthMethod = authMethod;
    305343        } else {
    306344            auth = &channels[i].authenticator;
    307             channels[i].authMehtod = authMethod;
     345            channels[i].authMethod = authMethod;
    308346        }
    309347        //proceed with the authentication.
     
    311349            auth->detach();
    312350        QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(*auth);
    313         priv->parseHttpResponse(responseHeader, isProxy);
     351        priv->parseHttpResponse(fields, isProxy);
    314352
    315353        if (priv->phase == QAuthenticatorPrivate::Done) {
    316             if ((isProxy && pendingProxyAuthSignal) ||(!isProxy && pendingAuthSignal)) {
    317                 // drop the request
    318                 reply->d_func()->eraseData();
    319                 channels[i].close();
    320                 channels[i].lastStatus = 0;
    321                 channels[i].state =  QHttpNetworkConnectionChannel::Wait4AuthState;
    322                 return false;
    323             }
    324             // cannot use this socket until the slot returns
    325             channels[i].state = QHttpNetworkConnectionChannel::WaitingState;
    326             socket->blockSignals(true);
     354            pauseConnection();
    327355            if (!isProxy) {
    328                 pendingAuthSignal = true;
    329                 emit q->authenticationRequired(reply->request(), auth, q);
    330                 pendingAuthSignal = false;
     356                emit reply->authenticationRequired(reply->request(), auth);
    331357#ifndef QT_NO_NETWORKPROXY
    332358            } else {
    333                 pendingProxyAuthSignal = true;
    334                 emit q->proxyAuthenticationRequired(networkProxy, auth, q);
    335                 pendingProxyAuthSignal = false;
     359                emit reply->proxyAuthenticationRequired(networkProxy, auth);
    336360#endif
    337361            }
    338             socket->blockSignals(false);
    339             // socket free to use
    340             channels[i].state = QHttpNetworkConnectionChannel::IdleState;
     362            resumeConnection();
     363
    341364            if (priv->phase != QAuthenticatorPrivate::Done) {
    342365                // send any pending requests
    343366                copyCredentials(i,  auth, isProxy);
    344                 QMetaObject::invokeMethod(q, "_q_restartAuthPendingRequests", Qt::QueuedConnection);
    345367            }
    346368        }
    347         // changing values in QAuthenticator will reset the 'phase'
    348         if (priv->phase == QAuthenticatorPrivate::Done) {
     369        // - Changing values in QAuthenticator will reset the 'phase'. Therefore if it is still "Done"
     370        //   then nothing was filled in by the user or the cache
     371        // - If withCredentials has been set to false (e.g. by QtWebKit for a cross-origin XMLHttpRequest) then
     372        //   we need to bail out if authentication is required.
     373        if (priv->phase == QAuthenticatorPrivate::Done || !reply->request().withCredentials()) {
     374            // Reset authenticator so the next request on that channel does not get messed up
     375            auth = 0;
     376            if (isProxy)
     377                channels[i].proxyAuthenticator = QAuthenticator();
     378            else
     379                channels[i].authenticator = QAuthenticator();
     380
    349381            // authentication is cancelled, send the current contents to the user.
    350382            emit channels[i].reply->headerChanged();
     
    355387                : QNetworkReply::AuthenticationRequiredError;
    356388            reply->d_func()->errorString = errorDetail(errorCode, socket);
    357             emit q->error(errorCode, reply->d_func()->errorString);
    358             emit channels[i].reply->finished();
     389            emit reply->finishedWithError(errorCode, reply->d_func()->errorString);
    359390            // ### at this point the reply could be deleted
    360391            socket->close();
    361             // remove pending request on the other channels
    362             for (int j = 0; j < channelCount; ++j) {
    363                 if (j != i && channels[j].state ==  QHttpNetworkConnectionChannel::Wait4AuthState)
    364                     channels[j].state = QHttpNetworkConnectionChannel::IdleState;
    365             }
    366392            return true;
    367393        }
     
    379405    int i = indexOf(socket);
    380406
    381     if (channels[i].authMehtod != QAuthenticatorPrivate::None) {
    382         if (!(channels[i].authMehtod == QAuthenticatorPrivate::Ntlm && channels[i].lastStatus != 401)) {
     407    // Send "Authorization" header, but not if it's NTLM and the socket is already authenticated.
     408    if (channels[i].authMethod != QAuthenticatorPrivate::None) {
     409        if (!(channels[i].authMethod == QAuthenticatorPrivate::Ntlm && channels[i].lastStatus != 401)) {
    383410            QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(channels[i].authenticator);
    384411            if (priv && priv->method != QAuthenticatorPrivate::None) {
     
    388415        }
    389416    }
    390     if (channels[i].proxyAuthMehtod != QAuthenticatorPrivate::None) {
    391         if (!(channels[i].proxyAuthMehtod == QAuthenticatorPrivate::Ntlm && channels[i].lastStatus != 407)) {
     417
     418    // Send "Proxy-Authorization" header, but not if it's NTLM and the socket is already authenticated.
     419    if (channels[i].proxyAuthMethod != QAuthenticatorPrivate::None) {
     420        if (!(channels[i].proxyAuthMethod == QAuthenticatorPrivate::Ntlm && channels[i].lastStatus != 407)) {
    392421            QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(channels[i].proxyAuthenticator);
    393422            if (priv && priv->method != QAuthenticatorPrivate::None) {
     
    652681        if (channels[i].reply == reply) {
    653682            channels[i].reply = 0;
     683            channels[i].request = QHttpNetworkRequest();
     684            channels[i].resendCurrent = false;
    654685
    655686            if (!reply->isFinished() && !channels[i].alreadyPipelinedRequests.isEmpty()) {
     
    720751void QHttpNetworkConnectionPrivate::_q_startNextRequest()
    721752{
     753    // If the QHttpNetworkConnection is currently paused then bail out immediately
     754    if (state == PausedState)
     755        return;
     756
    722757    //resend the necessary ones.
    723758    for (int i = 0; i < channelCount; ++i) {
     
    740775    // try to get a free AND connected socket
    741776    for (int i = 0; i < channelCount; ++i) {
    742         if (!channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) {
     777        if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) {
    743778            dequeueAndSendRequest(channels[i].socket);
    744779        }
     
    750785    // try to get a free unconnected socket
    751786    for (int i = 0; i < channelCount; ++i) {
    752         if (!channels[i].isSocketBusy()) {
     787        if (!channels[i].reply && !channels[i].isSocketBusy()) {
    753788            dequeueAndSendRequest(channels[i].socket);
    754789        }
     
    770805}
    771806
    772 void QHttpNetworkConnectionPrivate::_q_restartAuthPendingRequests()
    773 {
    774     // send the request using the idle socket
    775     for (int i = 0 ; i < channelCount; ++i) {
    776         if (channels[i].state ==  QHttpNetworkConnectionChannel::Wait4AuthState) {
    777             channels[i].state = QHttpNetworkConnectionChannel::IdleState;
    778             if (channels[i].reply)
    779                 channels[i].sendRequest();
    780         }
    781     }
    782 }
    783807
    784808void QHttpNetworkConnectionPrivate::readMoreLater(QHttpNetworkReply *reply)
     
    829853}
    830854
    831 void QHttpNetworkConnection::enableEncryption()
    832 {
    833     Q_D(QHttpNetworkConnection);
    834     d->encrypt = true;
    835 }
    836 
    837 bool QHttpNetworkConnection::isEncrypted() const
     855bool QHttpNetworkConnection::isSsl() const
    838856{
    839857    Q_D(const QHttpNetworkConnection);
     
    841859}
    842860
    843 void QHttpNetworkConnection::setProxyAuthentication(QAuthenticator *authenticator)
    844 {
    845     Q_D(QHttpNetworkConnection);
    846     for (int i = 0; i < d->channelCount; ++i)
    847         d->channels[i].proxyAuthenticator = *authenticator;
    848 }
    849 
    850 void QHttpNetworkConnection::setAuthentication(const QString &domain, QAuthenticator *authenticator)
    851 {
    852     Q_UNUSED(domain); // ### domain ?
    853     Q_D(QHttpNetworkConnection);
    854     for (int i = 0; i < d->channelCount; ++i)
    855         d->channels[i].authenticator = *authenticator;
     861QHttpNetworkConnectionChannel *QHttpNetworkConnection::channels() const
     862{
     863    return d_func()->channels;
    856864}
    857865
     
    948956void QHttpNetworkConnectionPrivate::emitProxyAuthenticationRequired(const QHttpNetworkConnectionChannel *chan, const QNetworkProxy &proxy, QAuthenticator* auth)
    949957{
    950     Q_Q(QHttpNetworkConnection);
    951     emit q->proxyAuthenticationRequired(proxy, auth, q);
     958    // Also pause the connection because socket notifiers may fire while an user
     959    // dialog is displaying
     960    pauseConnection();
     961    emit chan->reply->proxyAuthenticationRequired(proxy, auth);
     962    resumeConnection();
    952963    int i = indexOf(chan->socket);
    953964    copyCredentials(i, auth, true);
  • trunk/src/network/access/qhttpnetworkconnection_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    109109#endif
    110110
    111     //enable encryption
    112     void enableEncryption();
    113     bool isEncrypted() const;
    114 
    115     //authentication parameters
    116     void setProxyAuthentication(QAuthenticator *authenticator);
    117     void setAuthentication(const QString &domain, QAuthenticator *authenticator);
     111    bool isSsl() const;
     112
     113    QHttpNetworkConnectionChannel *channels() const;
    118114
    119115#ifndef QT_NO_OPENSSL
     
    121117    void ignoreSslErrors(int channel = -1);
    122118    void ignoreSslErrors(const QList<QSslError> &errors, int channel = -1);
    123 
    124 Q_SIGNALS:
    125     void sslErrors(const QList<QSslError> &errors);
    126 #endif
    127 
    128 Q_SIGNALS:
    129 #ifndef QT_NO_NETWORKPROXY
    130     //cannot be used with queued connection.
    131     void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator,
    132                                      const QHttpNetworkConnection *connection = 0);
    133 #endif
    134     void authenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *authenticator,
    135                                 const QHttpNetworkConnection *connection = 0);
    136     void error(QNetworkReply::NetworkError errorCode, const QString &detail = QString());
     119#endif
    137120
    138121private:
     
    140123    Q_DISABLE_COPY(QHttpNetworkConnection)
    141124    friend class QHttpNetworkReply;
     125    friend class QHttpNetworkReplyPrivate;
    142126    friend class QHttpNetworkConnectionChannel;
    143127
    144128    Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest())
    145     Q_PRIVATE_SLOT(d_func(), void _q_restartAuthPendingRequests())
    146129};
    147130
     
    159142    static const int defaultRePipelineLength;
    160143
     144    enum ConnectionState {
     145        RunningState = 0,
     146        PausedState = 1,
     147    };
     148
    161149    QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt);
    162150    QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt);
     
    164152    void init();
    165153
     154    void pauseConnection();
     155    void resumeConnection();
     156    ConnectionState state;
     157
    166158    enum { ChunkSize = 4096 };
    167159
     
    183175    // private slots
    184176    void _q_startNextRequest(); // send the next request from the queue
    185     void _q_restartAuthPendingRequests(); // send the currently blocked request
    186177
    187178    void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request);
     
    202193    QHttpNetworkConnectionChannel *channels; // parallel connections to the server
    203194
    204     bool pendingAuthSignal; // there is an incomplete authentication signal
    205     bool pendingProxyAuthSignal; // there is an incomplete proxy authentication signal
    206 
    207195    qint64 uncompressedBytesAvailable(const QHttpNetworkReply &reply) const;
    208196    qint64 uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const;
  • trunk/src/network/access/qhttpnetworkconnectionchannel.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6969    , pendingEncrypt(false)
    7070    , reconnectAttempts(2)
    71     , authMehtod(QAuthenticatorPrivate::None)
    72     , proxyAuthMehtod(QAuthenticatorPrivate::None)
     71    , authMethod(QAuthenticatorPrivate::None)
     72    , proxyAuthMethod(QAuthenticatorPrivate::None)
    7373#ifndef QT_NO_OPENSSL
    7474    , ignoreAllSslErrors(false)
     
    106106                     this, SLOT(_q_readyRead()),
    107107                     Qt::DirectConnection);
     108
     109    // The disconnected() and error() signals may already come
     110    // while calling connectToHost().
     111    // In case of a cached hostname or an IP this
     112    // will then emit a signal to the user of QNetworkReply
     113    // but cannot be caught because the user did not have a chance yet
     114    // to connect to QNetworkReply's signals.
     115    qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
    108116    QObject::connect(socket, SIGNAL(disconnected()),
    109117                     this, SLOT(_q_disconnected()),
    110                      Qt::DirectConnection);
     118                     Qt::QueuedConnection);
    111119    QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
    112120                     this, SLOT(_q_error(QAbstractSocket::SocketError)),
    113                      Qt::DirectConnection);
     121                     Qt::QueuedConnection);
     122
     123
    114124#ifndef QT_NO_NETWORKPROXY
    115125    QObject::connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
     
    171181        reply->d_func()->pipeliningUsed = false;
    172182
    173         pendingEncrypt = false;
    174183        // if the url contains authentication parameters, use the new ones
    175184        // both channels will use the new authentication parameters
    176         if (!request.url().userInfo().isEmpty()) {
     185        if (!request.url().userInfo().isEmpty() && request.withCredentials()) {
    177186            QUrl url = request.url();
    178187            QAuthenticator &auth = authenticator;
     
    181190                auth.setUser(url.userName());
    182191                auth.setPassword(url.password());
     192                emit reply->cacheCredentials(request, &auth);
    183193                connection->d_func()->copyCredentials(connection->d_func()->indexOf(socket), &auth, false);
    184194            }
     
    188198            request.setUrl(url);
    189199        }
    190         connection->d_func()->createAuthorization(socket, request);
     200        // Will only be false if QtWebKit is performing a cross-origin XMLHttpRequest
     201        // and withCredentials has not been set to true.
     202        if (request.withCredentials())
     203            connection->d_func()->createAuthorization(socket, request);
    191204#ifndef QT_NO_NETWORKPROXY
    192205        QByteArray header = QHttpNetworkRequestPrivate::header(request,
     
    297310    }
    298311    case QHttpNetworkConnectionChannel::ReadingState:
    299     case QHttpNetworkConnectionChannel::Wait4AuthState:
    300312        // ignore _q_bytesWritten in these states
    301313        // fall through
     
    400412        case QHttpNetworkReplyPrivate::ReadingDataState: {
    401413           QHttpNetworkReplyPrivate *replyPrivate = reply->d_func();
    402            if (replyPrivate->downstreamLimited && !replyPrivate->responseData.isEmpty() && replyPrivate->shouldEmitSignals()) {
     414           if (socket->state() == QAbstractSocket::ConnectedState &&
     415               replyPrivate->downstreamLimited && !replyPrivate->responseData.isEmpty() && replyPrivate->shouldEmitSignals()) {
     416               // (only do the following when still connected, not when we have already been disconnected and there is still data)
    403417               // We already have some HTTP body data. We don't read more from the socket until
    404418               // this is fetched by QHttpNetworkAccessHttpBackend. If we would read more,
     
    409423               return;
    410424           }
    411 
    412425            if (!replyPrivate->isChunked() && !replyPrivate->autoDecompress
    413426                && replyPrivate->bodyLength > 0) {
     
    645658    // Note that this may trigger a segfault at some other point. But then we can fix the underlying
    646659    // problem.
    647     if (!resendCurrent)
     660    if (!resendCurrent) {
     661        request = QHttpNetworkRequest();
    648662        reply = 0;
     663    }
    649664
    650665    // move next from pipeline to current request
     
    680695        QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
    681696    } else if (alreadyPipelinedRequests.isEmpty()) {
    682         QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
     697        if (qobject_cast<QHttpNetworkConnection*>(connection))
     698            QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
    683699    }
    684700}
     
    782798                : QNetworkReply::AuthenticationRequiredError;
    783799            reply->d_func()->errorString = connection->d_func()->errorDetail(errorCode, socket);
    784             emit connection->error(errorCode, reply->d_func()->errorString);
    785             emit reply->finished();
     800            emit reply->finishedWithError(errorCode, reply->d_func()->errorString);
    786801        }
    787802        break;
    788803    default:
    789         QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
     804        if (qobject_cast<QHttpNetworkConnection*>(connection))
     805            QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
    790806    }
    791807}
     
    835851    close();
    836852    resendCurrent = true;
    837     QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
     853    if (qobject_cast<QHttpNetworkConnection*>(connection))
     854        QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
    838855}
    839856
     
    928945    if (!socket)
    929946        return;
    930     bool send2Reply = false;
    931947    QNetworkReply::NetworkError errorCode = QNetworkReply::UnknownNetworkError;
    932948
     
    946962                return;
    947963            } else {
    948                 send2Reply = true;
    949964                errorCode = QNetworkReply::RemoteHostClosedError;
    950965            }
     
    959974            return;
    960975        }
    961         send2Reply = true;
    962976        errorCode = QNetworkReply::TimeoutError;
    963977        break;
     
    975989    QPointer<QHttpNetworkConnection> that = connection;
    976990    QString errorString = connection->d_func()->errorDetail(errorCode, socket, socket->errorString());
    977     if (send2Reply) {
    978         if (reply) {
    979             reply->d_func()->errorString = errorString;
    980             // this error matters only to this reply
    981             emit reply->finishedWithError(errorCode, errorString);
    982         }
    983         // send the next request
    984         QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection);
    985     } else {
    986         // the failure affects all requests.
    987         emit connection->error(errorCode, errorString);
    988     }
     991
     992    if (reply) {
     993        reply->d_func()->errorString = errorString;
     994        emit reply->finishedWithError(errorCode, errorString);
     995    }
     996    // send the next request
     997    QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection);
     998
    989999    if (that) //signal emission triggered event loop
    9901000        close();
     
    10091019        return; // ### error
    10101020    state = QHttpNetworkConnectionChannel::IdleState;
     1021    pendingEncrypt = false;
    10111022    sendRequest();
    10121023}
     
    10171028        return;
    10181029    //QNetworkReply::NetworkError errorCode = QNetworkReply::ProtocolFailure;
    1019     emit connection->sslErrors(errors);
     1030    // Also pause the connection because socket notifiers may fire while an user
     1031    // dialog is displaying
     1032    connection->d_func()->pauseConnection();
     1033    emit reply->sslErrors(errors);
     1034    connection->d_func()->resumeConnection();
    10201035}
    10211036
  • trunk/src/network/access/qhttpnetworkconnectionchannel_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9696        WaitingState = 4,       // waiting for reply
    9797        ReadingState = 8,       // reading the reply
    98         Wait4AuthState = 0x10,  // blocked for send till the current authentication slot is done
    99         BusyState = (ConnectingState|WritingState|WaitingState|ReadingState|Wait4AuthState)
     98        BusyState = (ConnectingState|WritingState|WaitingState|ReadingState)
    10099    };
    101100    QAbstractSocket *socket;
     
    109108    bool pendingEncrypt; // for https (send after encrypted)
    110109    int reconnectAttempts; // maximum 2 reconnection attempts
    111     QAuthenticatorPrivate::Method authMehtod;
    112     QAuthenticatorPrivate::Method proxyAuthMehtod;
     110    QAuthenticatorPrivate::Method authMethod;
     111    QAuthenticatorPrivate::Method proxyAuthMethod;
    113112    QAuthenticator authenticator;
    114113    QAuthenticator proxyAuthenticator;
     
    160159    bool isSocketReading() const;
    161160
     161    friend class QNetworkAccessHttpBackend;
     162
    162163    protected slots:
    163164    void _q_receiveReply();
  • trunk/src/network/access/qhttpnetworkheader.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6161{
    6262    bool ok = false;
    63     QByteArray value = headerField("content-length");
     63    // We are not using the headerField() method here because servers might send us multiple content-length
     64    // headers which is crap (see QTBUG-15311). Therefore just take the first content-length header field.
     65    QByteArray value;
     66    QList<QPair<QByteArray, QByteArray> >::ConstIterator it = fields.constBegin(),
     67                                                        end = fields.constEnd();
     68    for ( ; it != end; ++it)
     69        if (qstricmp("content-length", it->first) == 0) {
     70            value = it->second;
     71            break;
     72        }
     73
    6474    qint64 length = value.toULongLong(&ok);
    6575    if (ok)
  • trunk/src/network/access/qhttpnetworkheader_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qhttpnetworkreply.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    189189}
    190190
     191QByteArray QHttpNetworkReply::readAll()
     192{
     193    Q_D(QHttpNetworkReply);
     194    return d->responseData.readAll();
     195}
     196
    191197void QHttpNetworkReply::setDownstreamLimited(bool dsl)
    192198{
     
    204210{
    205211    return d_func()->pipeliningUsed;
     212}
     213
     214QHttpNetworkConnection* QHttpNetworkReply::connection()
     215{
     216    return d_func()->connection;
    206217}
    207218
  • trunk/src/network/access/qhttpnetworkreply_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    127127    qint64 bytesAvailableNextBlock() const;
    128128    QByteArray readAny();
     129    QByteArray readAll();
    129130    void setDownstreamLimited(bool t);
    130131
     
    132133
    133134    bool isPipeliningUsed() const;
     135
     136    QHttpNetworkConnection* connection();
    134137
    135138#ifndef QT_NO_OPENSSL
     
    150153    void dataReadProgress(int done, int total);
    151154    void dataSendProgress(qint64 done, qint64 total);
    152 
     155    void cacheCredentials(const QHttpNetworkRequest &request, QAuthenticator *authenticator);
     156#ifndef QT_NO_NETWORKPROXY
     157    void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator);
     158#endif
     159    void authenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *authenticator);
    153160private:
    154161    Q_DECLARE_PRIVATE(QHttpNetworkReply)
  • trunk/src/network/access/qhttpnetworkrequest.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5050        QHttpNetworkRequest::Priority pri, const QUrl &newUrl)
    5151    : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0),
    52       autoDecompress(false), pipeliningAllowed(false)
     52      autoDecompress(false), pipeliningAllowed(false), withCredentials(true)
    5353{
    5454}
     
    6262    autoDecompress = other.autoDecompress;
    6363    pipeliningAllowed = other.pipeliningAllowed;
     64    customVerb = other.customVerb;
     65    withCredentials = other.withCredentials;
    6466}
    6567
     
    7779QByteArray QHttpNetworkRequestPrivate::methodName() const
    7880{
    79     QByteArray ba;
    8081    switch (operation) {
     82    case QHttpNetworkRequest::Get:
     83        return "GET";
     84        break;
     85    case QHttpNetworkRequest::Head:
     86        return "HEAD";
     87        break;
     88    case QHttpNetworkRequest::Post:
     89        return "POST";
     90        break;
    8191    case QHttpNetworkRequest::Options:
    82         ba += "OPTIONS";
    83         break;
    84     case QHttpNetworkRequest::Get:
    85         ba += "GET";
    86         break;
    87     case QHttpNetworkRequest::Head:
    88         ba += "HEAD";
    89         break;
    90     case QHttpNetworkRequest::Post:
    91         ba += "POST";
     92        return "OPTIONS";
    9293        break;
    9394    case QHttpNetworkRequest::Put:
    94         ba += "PUT";
     95        return "PUT";
    9596        break;
    9697    case QHttpNetworkRequest::Delete:
    97         ba += "DELETE";
     98        return "DELETE";
    9899        break;
    99100    case QHttpNetworkRequest::Trace:
    100         ba += "TRACE";
     101        return "TRACE";
    101102        break;
    102103    case QHttpNetworkRequest::Connect:
    103         ba += "CONNECT";
     104        return "CONNECT";
     105        break;
     106    case QHttpNetworkRequest::Custom:
     107        return customVerb;
    104108        break;
    105109    default:
    106110        break;
    107111    }
    108     return ba;
     112    return QByteArray();
    109113}
    110114
     
    129133QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request, bool throughProxy)
    130134{
    131     QByteArray ba = request.d->methodName();
    132     QByteArray uri = request.d->uri(throughProxy);
    133     ba += ' ' + uri;
    134 
    135     QString majorVersion = QString::number(request.majorVersion());
    136     QString minorVersion = QString::number(request.minorVersion());
    137     ba += " HTTP/" + majorVersion.toLatin1() + '.' + minorVersion.toLatin1() + "\r\n";
    138 
    139135    QList<QPair<QByteArray, QByteArray> > fields = request.header();
     136    QByteArray ba;
     137    ba.reserve(40 + fields.length()*25); // very rough lower bound estimation
     138
     139    ba += request.d->methodName();
     140    ba += ' ';
     141    ba += request.d->uri(throughProxy);
     142
     143    ba += " HTTP/";
     144    ba += QByteArray::number(request.majorVersion());
     145    ba += '.';
     146    ba += QByteArray::number(request.minorVersion());
     147    ba += "\r\n";
     148
    140149    QList<QPair<QByteArray, QByteArray> >::const_iterator it = fields.constBegin();
    141     for (; it != fields.constEnd(); ++it)
    142         ba += it->first + ": " + it->second + "\r\n";
     150    QList<QPair<QByteArray, QByteArray> >::const_iterator endIt = fields.constEnd();
     151    for (; it != endIt; ++it) {
     152        ba += it->first;
     153        ba += ": ";
     154        ba += it->second;
     155        ba += "\r\n";
     156    }
    143157    if (request.d->operation == QHttpNetworkRequest::Post) {
    144158        // add content type, if not set in the request
     
    147161        if (!request.d->uploadByteDevice && request.d->url.hasQuery()) {
    148162            QByteArray query = request.d->url.encodedQuery();
    149             ba += "Content-Length: "+ QByteArray::number(query.size()) + "\r\n";
    150             ba += "\r\n";
     163            ba += "Content-Length: ";
     164            ba += QByteArray::number(query.size());
     165            ba += "\r\n\r\n";
    151166            ba += query;
    152167        } else {
     
    231246}
    232247
     248QByteArray QHttpNetworkRequest::customVerb() const
     249{
     250    return d->customVerb;
     251}
     252
     253void QHttpNetworkRequest::setCustomVerb(const QByteArray &customVerb)
     254{
     255    d->customVerb = customVerb;
     256}
     257
    233258QHttpNetworkRequest::Priority QHttpNetworkRequest::priority() const
    234259{
     
    251276}
    252277
     278bool QHttpNetworkRequest::withCredentials() const
     279{
     280    return d->withCredentials;
     281}
     282
     283void QHttpNetworkRequest::setWithCredentials(bool b)
     284{
     285    d->withCredentials = b;
     286}
     287
    253288void QHttpNetworkRequest::setUploadByteDevice(QNonContiguousByteDevice *bd)
    254289{
  • trunk/src/network/access/qhttpnetworkrequest_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7373        Delete,
    7474        Trace,
    75         Connect
     75        Connect,
     76        Custom
    7677    };
    7778
     
    104105    void setOperation(Operation operation);
    105106
     107    QByteArray customVerb() const;
     108    void setCustomVerb(const QByteArray &customOperation);
     109
    106110    Priority priority() const;
    107111    void setPriority(Priority priority);
     
    109113    bool isPipeliningAllowed() const;
    110114    void setPipeliningAllowed(bool b);
     115
     116    bool withCredentials() const;
     117    void setWithCredentials(bool b);
    111118
    112119    void setUploadByteDevice(QNonContiguousByteDevice *bd);
     
    134141
    135142    QHttpNetworkRequest::Operation operation;
     143    QByteArray customVerb;
    136144    QHttpNetworkRequest::Priority priority;
    137145    mutable QNonContiguousByteDevice* uploadByteDevice;
    138146    bool autoDecompress;
    139147    bool pipeliningAllowed;
     148    bool withCredentials;
    140149};
    141150
  • trunk/src/network/access/qnetworkaccessbackend.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4747#include "QtCore/qhash.h"
    4848#include "QtCore/qmutex.h"
     49#include "QtNetwork/qnetworksession.h"
    4950
    5051#include "qnetworkaccesscachebackend_p.h"
    5152#include "qabstractnetworkcache.h"
     53#include "qhostinfo.h"
    5254
    5355#include "private/qnoncontiguousbytedevice_p.h"
     
    8789                                                                 const QNetworkRequest &request)
    8890{
    89     QNetworkRequest::CacheLoadControl mode =
    90         static_cast<QNetworkRequest::CacheLoadControl>(
    91             request.attribute(QNetworkRequest::CacheLoadControlAttribute,
    92                               QNetworkRequest::PreferNetwork).toInt());
    93     if (mode == QNetworkRequest::AlwaysCache
    94         && (op == QNetworkAccessManager::GetOperation
    95         || op == QNetworkAccessManager::HeadOperation)) {
    96         QNetworkAccessBackend *backend = new QNetworkAccessCacheBackend;
    97         backend->manager = this;
    98         return backend;
    99     }
    100 
    10191    if (!factoryDataShutdown) {
    10292        QMutexLocker locker(&factoryData()->mutex);
     
    121111    if (reply->outgoingDataBuffer)
    122112        device = QNonContiguousByteDeviceFactory::create(reply->outgoingDataBuffer);
    123     else
     113    else if (reply->outgoingData) {
    124114        device = QNonContiguousByteDeviceFactory::create(reply->outgoingData);
     115    } else {
     116        return 0;
     117    }
    125118
    126119    bool bufferDisallowed =
     
    150143    : manager(0)
    151144    , reply(0)
     145    , synchronous(false)
    152146{
    153147}
     
    321315{
    322316    manager->authenticationRequired(this, authenticator);
     317}
     318
     319void QNetworkAccessBackend::cacheCredentials(QAuthenticator *authenticator)
     320{
     321    manager->cacheCredentials(this->reply->url, authenticator);
    323322}
    324323
     
    342341}
    343342
     343#ifndef QT_NO_BEARERMANAGEMENT
     344
     345/*!
     346    Starts the backend.  Returns true if the backend is started.  Returns false if the backend
     347    could not be started due to an unopened or roaming session.  The caller should recall this
     348    function once the session has been opened or the roaming process has finished.
     349*/
     350bool QNetworkAccessBackend::start()
     351{
     352    if (!manager->networkSession) {
     353        open();
     354        return true;
     355    }
     356
     357    // This is not ideal.
     358    const QString host = reply->url.host();
     359    if (host == QLatin1String("localhost") ||
     360        QHostAddress(host) == QHostAddress::LocalHost ||
     361        QHostAddress(host) == QHostAddress::LocalHostIPv6) {
     362        // Don't need an open session for localhost access.
     363        open();
     364        return true;
     365    }
     366
     367    if (manager->networkSession->isOpen() &&
     368        manager->networkSession->state() == QNetworkSession::Connected) {
     369        open();
     370        return true;
     371    }
     372
     373    return false;
     374}
     375#endif
     376
    344377QT_END_NAMESPACE
  • trunk/src/network/access/qnetworkaccessbackend_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    112112
    113113    virtual void open() = 0;
     114#ifndef QT_NO_BEARERMANAGEMENT
     115    virtual bool start();
     116#endif
    114117    virtual void closeDownstreamChannel() = 0;
    115     virtual bool waitForDownstreamReadyRead(int msecs) = 0;
    116118
    117119    // slot-like:
     
    156158    void setAttribute(QNetworkRequest::Attribute code, const QVariant &value);
    157159
     160    bool isSynchronous() { return synchronous; }
     161    void setSynchronous(bool sync) { synchronous = sync; }
     162
    158163    // return true if the QNonContiguousByteDevice of the upload
    159164    // data needs to support reset(). Currently needed for HTTP.
    160165    // This will possibly enable buffering of the upload data.
    161166    virtual bool needsResetableUploadData() { return false; }
     167
     168    // Returns true if backend is able to resume downloads.
     169    virtual bool canResume() const { return false; }
     170    virtual void setResumeOffset(quint64 offset) { Q_UNUSED(offset); }
     171
     172    virtual bool processRequestSynchronously() { return false; }
    162173
    163174protected:
     
    182193#endif
    183194    void authenticationRequired(QAuthenticator *auth);
     195    void cacheCredentials(QAuthenticator *auth);
    184196    void metaDataChanged();
    185197    void redirectionRequested(const QUrl &destination);
     
    191203    friend class QNetworkAccessManagerPrivate;
    192204    friend class QNetworkAccessBackendUploadIODevice;
     205    friend class QNetworkReplyImplPrivate;
    193206    QNetworkAccessManagerPrivate *manager;
    194207    QNetworkReplyImplPrivate *reply;
     208    bool synchronous;
    195209};
    196210
  • trunk/src/network/access/qnetworkaccesscache.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qnetworkaccesscache_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qnetworkaccesscachebackend.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    133133}
    134134
    135 bool QNetworkAccessCacheBackend::waitForDownstreamReadyRead(int)
    136 {
    137     Q_ASSERT_X(false, Q_FUNC_INFO , "This function show not have been called!");
    138     return false;
    139 }
    140 
    141 bool QNetworkAccessCacheBackend::waitForUpstreamBytesWritten(int)
    142 {
    143     Q_ASSERT_X(false, Q_FUNC_INFO, "This function show not have been called!");
    144     return false;
    145 }
    146 
    147135void QNetworkAccessCacheBackend::upstreamReadyRead()
    148136{
  • trunk/src/network/access/qnetworkaccesscachebackend_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7070    void closeDownstreamChannel();
    7171    void closeUpstreamChannel();
    72     bool waitForDownstreamReadyRead(int msecs);
    73     bool waitForUpstreamBytesWritten(int msecs);
    7472
    7573    void upstreamReadyRead();
  • trunk/src/network/access/qnetworkaccessdatabackend.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4444#include "qnetworkreply.h"
    4545#include "qurlinfo.h"
     46#include "private/qdataurl_p.h"
     47#include <qcoreapplication.h>
    4648
    4749QT_BEGIN_NAMESPACE
     
    7274        operation() != QNetworkAccessManager::HeadOperation) {
    7375        // data: doesn't support anything but GET
    74         QString msg = QObject::tr("Operation not supported on %1")
     76        const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend",
     77                                                        "Operation not supported on %1")
    7578                      .arg(uri.toString());
    7679        error(QNetworkReply::ContentOperationNotPermittedError, msg);
     
    7982    }
    8083
    81     if (uri.host().isEmpty()) {
    82         setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("text/plain;charset=US-ASCII"));
     84    QPair<QString, QByteArray> decoded = qDecodeDataUrl(uri);
    8385
    84         // the following would have been the correct thing, but
    85         // reality often differs from the specification. People have
    86         // data: URIs with ? and #
    87         //QByteArray data = QByteArray::fromPercentEncoding(uri.encodedPath());
    88         QByteArray data = QByteArray::fromPercentEncoding(uri.toEncoded());
     86    if (! decoded.first.isNull()) {
     87        setHeader(QNetworkRequest::ContentTypeHeader, decoded.first);
     88        setHeader(QNetworkRequest::ContentLengthHeader, decoded.second.size());
     89        emit metaDataChanged();
    8990
    90         // remove the data: scheme
    91         data.remove(0, 5);
     91        QByteDataBuffer list;
     92        list.append(decoded.second);
     93        decoded.second.clear(); // important because of implicit sharing!
     94        writeDownstreamData(list);
    9295
    93         // parse it:
    94         int pos = data.indexOf(',');
    95         if (pos != -1) {
    96             QByteArray payload = data.mid(pos + 1);
    97             data.truncate(pos);
    98             data = data.trimmed();
    99 
    100             // find out if the payload is encoded in Base64
    101             if (data.endsWith(";base64")) {
    102                 payload = QByteArray::fromBase64(payload);
    103                 data.chop(7);
    104             }
    105 
    106             if (data.toLower().startsWith("charset")) {
    107                 int i = 7;      // strlen("charset")
    108                 while (data.at(i) == ' ')
    109                     ++i;
    110                 if (data.at(i) == '=')
    111                     data.prepend("text/plain;");
    112             }
    113 
    114             if (!data.isEmpty())
    115                 setHeader(QNetworkRequest::ContentTypeHeader, data.trimmed());
    116 
    117             setHeader(QNetworkRequest::ContentLengthHeader, payload.size());
    118             emit metaDataChanged();
    119 
    120             QByteDataBuffer list;
    121             list.append(payload);
    122             payload.clear(); // important because of implicit sharing!
    123             writeDownstreamData(list);
    124 
    125             finished();
    126             return;
    127         }
     96        finished();
     97        return;
    12898    }
    12999
    130100    // something wrong with this URI
    131     QString msg = QObject::tr("Invalid URI: %1").arg(uri.toString());
     101    const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend",
     102                                                    "Invalid URI: %1").arg(uri.toString());
    132103    error(QNetworkReply::ProtocolFailure, msg);
    133104    finished();
     
    152123}
    153124
     125bool QNetworkAccessDataBackend::processRequestSynchronously()
     126{
     127#ifndef QT_NO_BEARERMANAGEMENT
     128    start();
     129#else
     130    open();
     131#endif
     132    return true;
     133}
     134
    154135QT_END_NAMESPACE
  • trunk/src/network/access/qnetworkaccessdatabackend_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6969    virtual bool waitForDownstreamReadyRead(int msecs);
    7070    virtual bool waitForUpstreamBytesWritten(int msecs);
     71
     72    virtual bool processRequestSynchronously();
    7173};
    7274
  • trunk/src/network/access/qnetworkaccessdebugpipebackend.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    253253    }
    254254
    255     error(code, QObject::tr("Socket error on %1: %2")
     255    error(code, QNetworkAccessDebugPipeBackend::tr("Socket error on %1: %2")
    256256          .arg(url().toString(), socket.errorString()));
    257257    finished();
     
    268268    } else {
    269269        // abnormal close
    270         QString msg = QObject::tr("Remote host closed the connection prematurely on %1")
     270        QString msg = QNetworkAccessDebugPipeBackend::tr("Remote host closed the connection prematurely on %1")
    271271                             .arg(url().toString());
    272272        error(QNetworkReply::RemoteHostClosedError, msg);
     
    279279}
    280280
    281 bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms)
    282 {
    283     Q_UNUSED(ms);
    284     qCritical("QNetworkAccess: Debug pipe backend does not support waitForReadyRead()");
    285     return false;
    286 }
    287281
    288282#endif
  • trunk/src/network/access/qnetworkaccessdebugpipebackend_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7272    virtual void open();
    7373    virtual void closeDownstreamChannel();
    74     virtual bool waitForDownstreamReadyRead(int msecs);
    7574
    7675    virtual void downstreamReadyWrite();
  • trunk/src/network/access/qnetworkaccessfilebackend.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    204204}
    205205
    206 bool QNetworkAccessFileBackend::waitForDownstreamReadyRead(int)
    207 {
    208     Q_ASSERT(operation() == QNetworkAccessManager::GetOperation);
    209     return readMoreFromFile();
    210 }
    211 
    212206void QNetworkAccessFileBackend::downstreamReadyWrite()
    213207{
  • trunk/src/network/access/qnetworkaccessfilebackend_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7070    virtual void open();
    7171    virtual void closeDownstreamChannel();
    72     virtual bool waitForDownstreamReadyRead(int msecs);
    7372
    7473    virtual void downstreamReadyWrite();
  • trunk/src/network/access/qnetworkaccessftpbackend.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    181181        exit(3);
    182182#endif
    183 }
    184 
    185 bool QNetworkAccessFtpBackend::waitForDownstreamReadyRead(int ms)
    186 {
    187     if (!ftp)
    188         return false;
    189 
    190     if (ftp->bytesAvailable()) {
    191         ftpReadyRead();
    192         return true;
    193     }
    194 
    195     if (ms == 0)
    196         return false;
    197 
    198     qCritical("QNetworkAccess: FTP backend does not support waitForReadyRead()");
    199     return false;
    200183}
    201184
  • trunk/src/network/access/qnetworkaccessftpbackend_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8888    virtual void open();
    8989    virtual void closeDownstreamChannel();
    90     virtual bool waitForDownstreamReadyRead(int msecs);
    9190
    9291    virtual void downstreamReadyWrite();
  • trunk/src/network/access/qnetworkaccesshttpbackend.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5151#include "qnetworkcookie_p.h"
    5252#include "QtCore/qdatetime.h"
     53#include "QtCore/qelapsedtimer.h"
    5354#include "QtNetwork/qsslconfiguration.h"
    5455
     
    214215    case QNetworkAccessManager::PutOperation:
    215216    case QNetworkAccessManager::DeleteOperation:
     217    case QNetworkAccessManager::CustomOperation:
    216218        break;
    217219
     
    297299    , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false)
    298300#endif
     301    , resumeOffset(0)
    299302{
    300303}
     
    317320        // Get the object cache that stores our QHttpNetworkConnection objects
    318321        QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getObjectCache(this);
    319         cache->releaseEntry(cacheKey);
     322
     323        // synchronous calls are not put into the cache, so for them the key is empty
     324        if (!cacheKey.isEmpty())
     325            cache->releaseEntry(cacheKey);
    320326    }
    321327
     
    335341    // call parent
    336342    QNetworkAccessBackend::finished();
    337 }
    338 
    339 void QNetworkAccessHttpBackend::setupConnection()
    340 {
    341 #ifndef QT_NO_NETWORKPROXY
    342     connect(http, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
    343             SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
    344 #endif
    345     connect(http, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)),
    346             SLOT(httpAuthenticationRequired(QHttpNetworkRequest,QAuthenticator*)));
    347     connect(http, SIGNAL(error(QNetworkReply::NetworkError,QString)),
    348             SLOT(httpError(QNetworkReply::NetworkError,QString)));
    349 #ifndef QT_NO_OPENSSL
    350     connect(http, SIGNAL(sslErrors(QList<QSslError>)),
    351             SLOT(sslErrors(QList<QSslError>)));
    352 #endif
    353343}
    354344
     
    481471}
    482472
     473static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio)
     474{
     475    switch (prio) {
     476    case QNetworkRequest::LowPriority:
     477        return QHttpNetworkRequest::LowPriority;
     478    case QNetworkRequest::HighPriority:
     479        return QHttpNetworkRequest::HighPriority;
     480    case QNetworkRequest::NormalPriority:
     481    default:
     482        return QHttpNetworkRequest::NormalPriority;
     483    }
     484}
     485
    483486void QNetworkAccessHttpBackend::postRequest()
    484487{
    485488    bool loadedFromCache = false;
    486489    QHttpNetworkRequest httpRequest;
     490    httpRequest.setPriority(convert(request().priority()));
    487491    switch (operation()) {
    488492    case QNetworkAccessManager::GetOperation:
     
    513517        break;
    514518
     519    case QNetworkAccessManager::CustomOperation:
     520        invalidateCache(); // for safety reasons, we don't know what the operation does
     521        httpRequest.setOperation(QHttpNetworkRequest::Custom);
     522        httpRequest.setUploadByteDevice(createUploadByteDevice());
     523        httpRequest.setCustomVerb(request().attribute(
     524                QNetworkRequest::CustomVerbAttribute).toByteArray());
     525        break;
     526
    515527    default:
    516528        break;                  // can't happen
     
    520532
    521533    QList<QByteArray> headers = request().rawHeaderList();
     534    if (resumeOffset != 0) {
     535        if (headers.contains("Range")) {
     536            // Need to adjust resume offset for user specified range
     537
     538            headers.removeOne("Range");
     539
     540            // We've already verified that requestRange starts with "bytes=", see canResume.
     541            QByteArray requestRange = request().rawHeader("Range").mid(6);
     542
     543            int index = requestRange.indexOf('-');
     544
     545            quint64 requestStartOffset = requestRange.left(index).toULongLong();
     546            quint64 requestEndOffset = requestRange.mid(index + 1).toULongLong();
     547
     548            requestRange = "bytes=" + QByteArray::number(resumeOffset + requestStartOffset) +
     549                           '-' + QByteArray::number(requestEndOffset);
     550
     551            httpRequest.setHeaderField("Range", requestRange);
     552        } else {
     553            httpRequest.setHeaderField("Range", "bytes=" + QByteArray::number(resumeOffset) + '-');
     554        }
     555    }
    522556    foreach (const QByteArray &header, headers)
    523557        httpRequest.setHeaderField(header, request().rawHeader(header));
     
    532566    if (request().attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true)
    533567        httpRequest.setPipeliningAllowed(true);
     568
     569    if (static_cast<QNetworkRequest::LoadControl>
     570        (request().attribute(QNetworkRequest::AuthenticationReuseAttribute,
     571                             QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Manual)
     572        httpRequest.setWithCredentials(false);
    534573
    535574    httpReply = http->sendRequest(httpRequest);
     
    541580        httpReply->ignoreSslErrors();
    542581    httpReply->ignoreSslErrors(pendingIgnoreSslErrorsList);
     582    connect(httpReply, SIGNAL(sslErrors(QList<QSslError>)),
     583            SLOT(sslErrors(QList<QSslError>)));
    543584#endif
    544585
     
    548589            SLOT(httpError(QNetworkReply::NetworkError,QString)));
    549590    connect(httpReply, SIGNAL(headerChanged()), SLOT(replyHeaderChanged()));
     591    connect(httpReply, SIGNAL(cacheCredentials(QHttpNetworkRequest,QAuthenticator*)),
     592            SLOT(httpCacheCredentials(QHttpNetworkRequest,QAuthenticator*)));
     593#ifndef QT_NO_NETWORKPROXY
     594    connect(httpReply, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
     595            SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
     596#endif
     597    connect(httpReply, SIGNAL(authenticationRequired(const QHttpNetworkRequest,QAuthenticator*)),
     598                SLOT(httpAuthenticationRequired(const QHttpNetworkRequest,QAuthenticator*)));
    550599}
    551600
     
    595644        cacheProxy.type() == QNetworkProxy::DefaultProxy) {
    596645        // unsuitable proxies
    597         QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
    598                                   Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProxyNotFoundError),
    599                                   Q_ARG(QString, tr("No suitable proxy found")));
    600         QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
    601         return;
    602     }
    603 #endif
    604 
    605     // check if we have an open connection to this host
    606     cacheKey = makeCacheKey(this, theProxy);
    607     QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getObjectCache(this);
    608     // the http object is actually a QHttpNetworkConnection
    609     http = static_cast<QNetworkAccessCachedHttpConnection *>(cache->requestEntryNow(cacheKey));
    610     if (http == 0) {
    611         // no entry in cache; create an object
    612         // the http object is actually a QHttpNetworkConnection
    613         http = new QNetworkAccessCachedHttpConnection(url.host(), url.port(), encrypt);
    614 
     646        if (isSynchronous()) {
     647            error(QNetworkReply::ProxyNotFoundError, tr("No suitable proxy found"));
     648            finished();
     649        } else {
     650            QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
     651                                      Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProxyNotFoundError),
     652                                      Q_ARG(QString, tr("No suitable proxy found")));
     653            QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
     654        }
     655            return;
     656    }
     657#endif
     658
     659    if (isSynchronous()) {
     660        // for synchronous requests, we just create a new connection
     661        http = new QHttpNetworkConnection(1, url.host(), url.port(), encrypt, this);
    615662#ifndef QT_NO_NETWORKPROXY
    616663        http->setTransparentProxy(transparentProxy);
    617664        http->setCacheProxy(cacheProxy);
    618665#endif
    619 
    620         // cache the QHttpNetworkConnection corresponding to this cache key
    621         cache->addEntry(cacheKey, http);
    622     }
    623 
    624     setupConnection();
    625     postRequest();
     666        postRequest();
     667        processRequestSynchronously();
     668    } else {
     669        // check if we have an open connection to this host
     670        cacheKey = makeCacheKey(this, theProxy);
     671        QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getObjectCache(this);
     672        // the http object is actually a QHttpNetworkConnection
     673        http = static_cast<QNetworkAccessCachedHttpConnection *>(cache->requestEntryNow(cacheKey));
     674        if (http == 0) {
     675            // no entry in cache; create an object
     676            // the http object is actually a QHttpNetworkConnection
     677            http = new QNetworkAccessCachedHttpConnection(url.host(), url.port(), encrypt);
     678
     679#ifndef QT_NO_NETWORKPROXY
     680            http->setTransparentProxy(transparentProxy);
     681            http->setCacheProxy(cacheProxy);
     682#endif
     683
     684            // cache the QHttpNetworkConnection corresponding to this cache key
     685            cache->addEntry(cacheKey, static_cast<QNetworkAccessCachedHttpConnection *>(http.data()));
     686        }
     687        postRequest();
     688    }
    626689}
    627690
     
    630693    // this indicates that the user closed the stream while the reply isn't finished yet
    631694}
    632 
    633 bool QNetworkAccessHttpBackend::waitForDownstreamReadyRead(int msecs)
    634 {
    635     Q_ASSERT(http);
    636 
    637     if (httpReply->bytesAvailable()) {
    638         readFromHttp();
    639         return true;
    640     }
    641 
    642     if (msecs == 0) {
    643         // no bytes available in the socket and no waiting
    644         return false;
    645     }
    646 
    647     // ### FIXME
    648     qCritical("QNetworkAccess: HTTP backend does not support waitForReadyRead()");
    649     return false;
    650 }
    651 
    652695
    653696void QNetworkAccessHttpBackend::downstreamReadyWrite()
     
    816859}
    817860
     861void QNetworkAccessHttpBackend::httpCacheCredentials(const QHttpNetworkRequest &,
     862                                                 QAuthenticator *auth)
     863{
     864    cacheCredentials(auth);
     865}
     866
    818867void QNetworkAccessHttpBackend::httpError(QNetworkReply::NetworkError errorCode,
    819868                                          const QString &errorString)
     
    821870#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
    822871    qDebug() << "http error!" << errorCode << errorString;
    823 #endif
    824 #if 0
    825     static const QNetworkReply::NetworkError conversionTable[] = {
    826         QNetworkReply::ConnectionRefusedError,
    827         QNetworkReply::RemoteHostClosedError,
    828         QNetworkReply::HostNotFoundError,
    829         QNetworkReply::UnknownNetworkError, // SocketAccessError
    830         QNetworkReply::UnknownNetworkError, // SocketResourceError
    831         QNetworkReply::TimeoutError,        // SocketTimeoutError
    832         QNetworkReply::UnknownNetworkError, // DatagramTooLargeError
    833         QNetworkReply::UnknownNetworkError, // NetworkError
    834         QNetworkReply::UnknownNetworkError, // AddressInUseError
    835         QNetworkReply::UnknownNetworkError, // SocketAddressNotAvailableError
    836         QNetworkReply::UnknownNetworkError, // UnsupportedSocketOperationError
    837         QNetworkReply::UnknownNetworkError, // UnfinishedSocketOperationError
    838         QNetworkReply::ProxyAuthenticationRequiredError
    839     };
    840     QNetworkReply::NetworkError code;
    841     if (int(errorCode) >= 0 &&
    842         uint(errorCode) < (sizeof conversionTable / sizeof conversionTable[0]))
    843         code = conversionTable[errorCode];
    844     else
    845         code = QNetworkReply::UnknownNetworkError;
    846872#endif
    847873    error(errorCode, errorString);
     
    886912    checkForRedirect(status);
    887913
    888     emit metaDataChanged();
    889 
    890     // invoke this asynchronously, else Arora/QtDemoBrowser don't like cached downloads
    891     // see task 250221 / 251801
     914    // This needs to be emitted in the event loop because it can be reached at
     915    // the direct code path of qnam.get(...) before the user has a chance
     916    // to connect any signals.
     917    QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection);
    892918    qRegisterMetaType<QIODevice*>("QIODevice*");
    893919    QMetaObject::invokeMethod(this, "writeDownstreamData", Qt::QueuedConnection, Q_ARG(QIODevice*, contents));
     
    10941120}
    10951121
     1122bool QNetworkAccessHttpBackend::canResume() const
     1123{
     1124    // Only GET operation supports resuming.
     1125    if (operation() != QNetworkAccessManager::GetOperation)
     1126        return false;
     1127
     1128    // Can only resume if server/resource supports Range header.
     1129    if (httpReply->headerField("Accept-Ranges", "none") == "none")
     1130        return false;
     1131
     1132    // We only support resuming for byte ranges.
     1133    if (request().hasRawHeader("Range")) {
     1134        QByteArray range = request().rawHeader("Range");
     1135        if (!range.startsWith("bytes="))
     1136            return false;
     1137    }
     1138
     1139    return true;
     1140}
     1141
     1142void QNetworkAccessHttpBackend::setResumeOffset(quint64 offset)
     1143{
     1144    resumeOffset = offset;
     1145}
     1146
     1147bool QNetworkAccessHttpBackend::processRequestSynchronously()
     1148{
     1149    QHttpNetworkConnectionChannel *channel = &http->channels()[0];
     1150
     1151    // Disconnect all socket signals. They will only confuse us when using waitFor*
     1152    QObject::disconnect(channel->socket, 0, 0, 0);
     1153
     1154    qint64 timeout = 20*1000; // 20 sec
     1155    QElapsedTimer timeoutTimer;
     1156
     1157    bool waitResult = channel->socket->waitForConnected(timeout);
     1158    timeoutTimer.start();
     1159
     1160    if (!waitResult || channel->socket->state() != QAbstractSocket::ConnectedState) {
     1161        error(QNetworkReply::UnknownNetworkError, QLatin1String("could not connect"));
     1162        return false;
     1163    }
     1164    channel->_q_connected(); // this will send the request (via sendRequest())
     1165
     1166#ifndef QT_NO_OPENSSL
     1167    if (http->isSsl()) {
     1168        qint64 remainingTimeEncrypted = timeout - timeoutTimer.elapsed();
     1169        if (!static_cast<QSslSocket *>(channel->socket)->waitForEncrypted(remainingTimeEncrypted)) {
     1170            error(QNetworkReply::SslHandshakeFailedError,
     1171                  QLatin1String("could not encrypt or timeout while encrypting"));
     1172            return false;
     1173        }
     1174        channel->_q_encrypted();
     1175    }
     1176#endif
     1177
     1178    // if we get a 401 or 407, we might need to send the request twice, see below
     1179    bool authenticating = false;
     1180
     1181    do {
     1182        channel->sendRequest();
     1183
     1184        qint64 remainingTimeBytesWritten;
     1185        while(channel->socket->bytesToWrite() > 0 ||
     1186              channel->state == QHttpNetworkConnectionChannel::WritingState) {
     1187            remainingTimeBytesWritten = timeout - timeoutTimer.elapsed();
     1188            channel->sendRequest(); // triggers channel->socket->write()
     1189            if (!channel->socket->waitForBytesWritten(remainingTimeBytesWritten)) {
     1190                error(QNetworkReply::TimeoutError,
     1191                      QLatin1String("could not write bytes to socket or timeout while writing"));
     1192                return false;
     1193            }
     1194        }
     1195
     1196        qint64 remainingTimeBytesRead = timeout - timeoutTimer.elapsed();
     1197        // Loop for at most remainingTime until either the socket disconnects
     1198        // or the reply is finished
     1199        do {
     1200            waitResult = channel->socket->waitForReadyRead(remainingTimeBytesRead);
     1201            remainingTimeBytesRead = timeout - timeoutTimer.elapsed();
     1202            if (!waitResult || remainingTimeBytesRead <= 0
     1203                || channel->socket->state() != QAbstractSocket::ConnectedState) {
     1204                error(QNetworkReply::TimeoutError,
     1205                      QLatin1String("could not read from socket or timeout while reading"));
     1206                return false;
     1207            }
     1208
     1209            if (channel->socket->bytesAvailable())
     1210                channel->_q_readyRead();
     1211
     1212            if (!httpReply)
     1213                return false; // we got a 401 or 407 and cannot handle it (it might happen that
     1214                              // disconnectFromHttp() was called, in that case the reply is zero)
     1215            // ### I am quite sure this does not work for NTLM
     1216            // ### how about uploading to an auth / proxyAuth site?
     1217
     1218            authenticating = (httpReply->statusCode() == 401 || httpReply->statusCode() == 407);
     1219
     1220            if (httpReply->isFinished())
     1221                break;
     1222        } while (remainingTimeBytesRead > 0);
     1223    } while (authenticating);
     1224
     1225    return true;
     1226}
     1227
    10961228QT_END_NAMESPACE
    10971229
  • trunk/src/network/access/qnetworkaccesshttpbackend_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8080    virtual void open();
    8181    virtual void closeDownstreamChannel();
    82     virtual bool waitForDownstreamReadyRead(int msecs);
    8382
    8483    virtual void downstreamReadyWrite();
     
    9897    bool needsResetableUploadData() { return true; }
    9998
     99    bool canResume() const;
     100    void setResumeOffset(quint64 offset);
     101
     102    virtual bool processRequestSynchronously();
     103
    100104private slots:
    101105    void replyReadyRead();
     
    103107    void replyHeaderChanged();
    104108    void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth);
     109    void httpCacheCredentials(const QHttpNetworkRequest &request, QAuthenticator *auth);
    105110    void httpError(QNetworkReply::NetworkError error, const QString &errorString);
    106111    bool sendCacheContents(const QNetworkCacheMetaData &metaData);
     
    109114private:
    110115    QHttpNetworkReply *httpReply;
    111     QPointer<QNetworkAccessCachedHttpConnection> http;
     116    QPointer<QHttpNetworkConnection> http;
    112117    QByteArray cacheKey;
    113118    QNetworkAccessBackendUploadIODevice *uploadDevice;
     
    119124#endif
    120125
     126    quint64 resumeOffset;
     127
    121128    void disconnectFromHttp();
    122     void setupConnection();
    123129    void validateCache(QHttpNetworkRequest &httpRequest, bool &loadedFromCache);
    124130    void invalidateCache();
  • trunk/src/network/access/qnetworkaccessmanager.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4848#include "qabstractnetworkcache.h"
    4949
     50#include "QtNetwork/qnetworksession.h"
     51#include "QtNetwork/private/qsharednetworksession_p.h"
     52
    5053#include "qnetworkaccesshttpbackend_p.h"
    5154#include "qnetworkaccessftpbackend_p.h"
     
    5356#include "qnetworkaccessdatabackend_p.h"
    5457#include "qnetworkaccessdebugpipebackend_p.h"
     58#include "qnetworkaccesscachebackend_p.h"
    5559#include "qfilenetworkreply_p.h"
    5660
     
    6064#include "QtNetwork/qauthenticator.h"
    6165#include "QtNetwork/qsslconfiguration.h"
     66#include "QtNetwork/qnetworkconfigmanager.h"
    6267
    6368QT_BEGIN_NAMESPACE
     
    139144    \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 1
    140145
     146    \section1 Network and Roaming support
     147
     148    With the addition of the \l {Bearer Management} API to Qt 4.7
     149    QNetworkAccessManager gained the ability to manage network connections.
     150    QNetworkAccessManager can start the network interface if the device is
     151    offline and terminates the interface if the current process is the last
     152    one to use the uplink. Note that some platform utilize grace periods from
     153    when the last application stops using a uplink until the system actually
     154    terminates the connectivity link. Roaming is equally transparent. Any
     155    queued/pending network requests are automatically transferred to new
     156    access point.
     157
     158    Clients wanting to utilize this feature should not require any changes. In fact
     159    it is likely that existing platform specific connection code can simply be
     160    removed from the application.
     161
     162    \note The network and roaming support in QNetworkAccessManager is conditional
     163    upon the platform supporting connection management. The
     164    \l QNetworkConfigurationManager::NetworkSessionRequired can be used to
     165    detect whether QNetworkAccessManager utilizes this feature. Currently only
     166    Meego/Harmattan and Symbian platforms provide connection management support.
     167
     168    \note This feature cannot be used in combination with the Bearer Management
     169    API as provided by QtMobility. Applications have to migrate to the Qt version
     170    of Bearer Management.
     171
    141172    \section1 Symbian Platform Security Requirements
    142173
     
    172203    deleteResource())
    173204
     205    \value CustomOperation      custom operation (created with
     206    sendCustomRequest())    \since 4.7
     207
    174208    \omitvalue UnknownOperation
    175209
    176210    \sa QNetworkReply::operation()
     211*/
     212
     213/*!
     214    \enum QNetworkAccessManager::NetworkAccessibility
     215
     216    Indicates whether the network is accessible via this network access manager.
     217
     218    \value UnknownAccessibility     The network accessibility cannot be determined.
     219    \value NotAccessible            The network is not currently accessible, either because there
     220                                    is currently no network coverage or network access has been
     221                                    explicitly disabled by a call to setNetworkAccessible().
     222    \value Accessible               The network is accessible.
     223
     224    \sa networkAccessible
     225*/
     226
     227/*!
     228    \property QNetworkAccessManager::networkAccessible
     229    \brief whether the network is currently accessible via this network access manager.
     230
     231    \since 4.7
     232
     233    If the network is \l {NotAccessible}{not accessible} the network access manager will not
     234    process any new network requests, all such requests will fail with an error.  Requests with
     235    URLs with the file:// scheme will still be processed.
     236
     237    By default the value of this property reflects the physical state of the device.  Applications
     238    may override it to disable all network requests via this network access manager by calling
     239
     240    \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 4
     241
     242    Network requests can be reenabled again by calling
     243
     244    \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 5
     245
     246    \note Calling setNetworkAccessible() does not change the network state.
     247*/
     248
     249/*!
     250    \fn void QNetworkAccessManager::networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible)
     251
     252    This signal is emitted when the value of the \l networkAccessible property changes.
     253    \a accessible is the new network accessibility.
     254*/
     255
     256/*!
     257    \fn void QNetworkAccessManager::networkSessionConnected()
     258
     259    \since 4.7
     260
     261    \internal
     262
     263    This signal is emitted when the status of the network session changes into a usable (Connected)
     264    state. It is used to signal to QNetworkReplys to start or migrate their network operation once
     265    the network session has been opened or finished roaming.
    177266*/
    178267
     
    378467    delete d_func()->proxyFactory;
    379468#endif
     469
     470    // Delete the QNetworkReply children first.
     471    // Else a QAbstractNetworkCache might get deleted in ~QObject
     472    // before a QNetworkReply that accesses the QAbstractNetworkCache
     473    // object in its destructor.
     474    qDeleteAll(findChildren<QNetworkReply *>());
     475    // The other children will be deleted in this ~QObject
     476    // FIXME instead of this "hack" make the QNetworkReplyImpl
     477    // properly watch the cache deletion, e.g. via a QWeakPointer.
    380478}
    381479
     
    535633    \note QNetworkAccessManager takes ownership of the \a cookieJar object.
    536634
    537     QNetworkAccessManager will set the parent of the \a cookieJar
    538     passed to itself, so that the cookie jar is deleted when this
     635    If \a cookieJar is in the same thread as this QNetworkAccessManager,
     636    it will set the parent of the \a cookieJar
     637    so that the cookie jar is deleted when this
    539638    object is deleted as well. If you want to share cookie jars
    540639    between different QNetworkAccessManager objects, you may want to
     
    561660            delete d->cookieJar;
    562661        d->cookieJar = cookieJar;
    563         d->cookieJar->setParent(this);
     662        if (thread() == cookieJar->thread())
     663            d->cookieJar->setParent(this);
    564664    }
    565665}
     
    584684    The contents as well as associated headers will be downloaded.
    585685
    586     \sa post(), put(), deleteResource()
     686    \sa post(), put(), deleteResource(), sendCustomRequest()
    587687*/
    588688QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
     
    603703    HTTPS is undefined and will probably fail.
    604704
    605     \sa get(), put(), deleteResource()
     705    \sa get(), put(), deleteResource(), sendCustomRequest()
    606706*/
    607707QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data)
     
    644744    files through HTML forms, use the POST mechanism.
    645745
    646     \sa get(), post()
     746    \sa get(), post(), deleteResource(), sendCustomRequest()
    647747*/
    648748QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QIODevice *data)
     
    675775    HTTP DELETE request.
    676776
    677     \sa get(), post(), put()
     777    \sa get(), post(), put(), sendCustomRequest()
    678778*/
    679779QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &request)
    680780{
    681781    return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
     782}
     783
     784#ifndef QT_NO_BEARERMANAGEMENT
     785
     786/*!
     787    \since 4.7
     788
     789    Sets the network configuration that will be used when creating the
     790    \l {QNetworkSession}{network session} to \a config.
     791
     792    The network configuration is used to create and open a network session before any request that
     793    requires network access is process.  If no network configuration is explicitly set via this
     794    function the network configuration returned by
     795    QNetworkConfigurationManager::defaultConfiguration() will be used.
     796
     797    To restore the default network configuration set the network configuration to the value
     798    returned from QNetworkConfigurationManager::defaultConfiguration().
     799
     800    \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 2
     801
     802    If an invalid network configuration is set, a network session will not be created.  In this
     803    case network requests will be processed regardless, but may fail.  For example:
     804
     805    \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 3
     806
     807    \sa configuration(), QNetworkSession
     808*/
     809void QNetworkAccessManager::setConfiguration(const QNetworkConfiguration &config)
     810{
     811    d_func()->createSession(config);
     812}
     813
     814/*!
     815    \since 4.7
     816
     817    Returns the network configuration that will be used to create the
     818    \l {QNetworkSession}{network session} which will be used when processing network requests.
     819
     820    \sa setConfiguration(), activeConfiguration()
     821*/
     822QNetworkConfiguration QNetworkAccessManager::configuration() const
     823{
     824    Q_D(const QNetworkAccessManager);
     825
     826    if (d->networkSession)
     827        return d->networkSession->configuration();
     828    else
     829        return QNetworkConfiguration();
     830}
     831
     832/*!
     833    \since 4.7
     834
     835    Returns the current active network configuration.
     836
     837    If the network configuration returned by configuration() is of type
     838    QNetworkConfiguration::ServiceNetwork this function will return the current active child
     839    network configuration of that configuration.  Otherwise returns the same network configuration
     840    as configuration().
     841
     842    Use this function to return the actual network configuration currently in use by the network
     843    session.
     844
     845    \sa configuration()
     846*/
     847QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
     848{
     849    Q_D(const QNetworkAccessManager);
     850
     851    if (d->networkSession) {
     852        QNetworkConfigurationManager manager;
     853
     854        return manager.configurationFromIdentifier(
     855            d->networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString());
     856    } else {
     857        return QNetworkConfiguration();
     858    }
     859}
     860
     861/*!
     862    \since 4.7
     863
     864    Overrides the reported network accessibility.  If \a accessible is NotAccessible the reported
     865    network accessiblity will always be NotAccessible.  Otherwise the reported network
     866    accessibility will reflect the actual device state.
     867*/
     868void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible)
     869{
     870    Q_D(QNetworkAccessManager);
     871
     872    if (d->networkAccessible != accessible) {
     873        NetworkAccessibility previous = networkAccessible();
     874        d->networkAccessible = accessible;
     875        NetworkAccessibility current = networkAccessible();
     876        if (previous != current)
     877            emit networkAccessibleChanged(current);
     878    }
     879}
     880
     881/*!
     882    \since 4.7
     883
     884    Returns the current network accessibility.
     885*/
     886QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const
     887{
     888    Q_D(const QNetworkAccessManager);
     889
     890    if (d->networkSession) {
     891        // d->online holds online/offline state of this network session.
     892        if (d->online)
     893            return d->networkAccessible;
     894        else
     895            return NotAccessible;
     896    } else {
     897        // Network accessibility is either disabled or unknown.
     898        return (d->networkAccessible == NotAccessible) ? NotAccessible : UnknownAccessibility;
     899    }
     900}
     901
     902#endif // QT_NO_BEARERMANAGEMENT
     903
     904/*!
     905    \since 4.7
     906
     907    Sends a custom request to the server identified by the URL of \a request.
     908
     909    It is the user's responsibility to send a \a verb to the server that is valid
     910    according to the HTTP specification.
     911
     912    This method provides means to send verbs other than the common ones provided
     913    via get() or post() etc., for instance sending an HTTP OPTIONS command.
     914
     915    If \a data is not empty, the contents of the \a data
     916    device will be uploaded to the server; in that case, data must be open for
     917    reading and must remain valid until the finished() signal is emitted for this reply.
     918
     919    \note This feature is currently available for HTTP only.
     920
     921    \sa get(), post(), put(), deleteResource()
     922*/
     923QNetworkReply *QNetworkAccessManager::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data)
     924{
     925    QNetworkRequest newRequest(request);
     926    newRequest.setAttribute(QNetworkRequest::CustomVerbAttribute, verb);
     927    return d_func()->postProcess(createRequest(QNetworkAccessManager::CustomOperation, newRequest, data));
    682928}
    683929
     
    701947    Q_D(QNetworkAccessManager);
    702948
     949    // 4.7 only hotfix fast path for data:// URLs
     950    // In 4.8 this is solved with QNetworkReplyDataImpl and will work there
     951    // This hotfix is done for not needing a QNetworkSession for data://
     952    if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation)
     953             && (req.url().scheme() == QLatin1String("data"))) {
     954        QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
     955        QNetworkReplyImplPrivate *priv = reply->d_func();
     956        priv->manager = this;
     957        priv->backend = new QNetworkAccessDataBackend();
     958        priv->backend->manager = this->d_func();
     959        priv->backend->setParent(reply);
     960        priv->backend->reply = priv;
     961        priv->setup(op, req, outgoingData);
     962        return reply;
     963    }
     964
    703965    // fast path for GET on file:// URLs
    704966    // Also if the scheme is empty we consider it a file.
    705     // The QNetworkAccessFileBackend will right now only be used
    706     // for PUT or qrc://
     967    // The QNetworkAccessFileBackend will right now only be used for PUT
    707968    if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation)
    708969         && (req.url().scheme() == QLatin1String("file")
     970             || req.url().scheme() == QLatin1String("qrc")
    709971             || req.url().scheme().isEmpty())) {
    710972        return new QFileNetworkReply(this, req, op);
    711973    }
     974
     975    // A request with QNetworkRequest::AlwaysCache does not need any bearer management
     976    QNetworkRequest::CacheLoadControl mode =
     977        static_cast<QNetworkRequest::CacheLoadControl>(
     978            req.attribute(QNetworkRequest::CacheLoadControlAttribute,
     979                              QNetworkRequest::PreferNetwork).toInt());
     980    if (mode == QNetworkRequest::AlwaysCache
     981        && (op == QNetworkAccessManager::GetOperation
     982        || op == QNetworkAccessManager::HeadOperation)) {
     983        // FIXME Implement a QNetworkReplyCacheImpl instead, see QTBUG-15106
     984        QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
     985        QNetworkReplyImplPrivate *priv = reply->d_func();
     986        priv->manager = this;
     987        priv->backend = new QNetworkAccessCacheBackend();
     988        priv->backend->manager = this->d_func();
     989        priv->backend->setParent(reply);
     990        priv->backend->reply = priv;
     991        priv->setup(op, req, outgoingData);
     992        return reply;
     993    }
     994
     995#ifndef QT_NO_BEARERMANAGEMENT
     996    // Return a disabled network reply if network access is disabled.
     997    // Except if the scheme is empty or file://.
     998    if (!d->networkAccessible && !(req.url().scheme() == QLatin1String("file") ||
     999                                      req.url().scheme().isEmpty())) {
     1000        return new QDisabledNetworkReply(this, req, op);
     1001    }
     1002
     1003    if (!d->networkSession && (d->initializeSession || !d->networkConfiguration.isEmpty())) {
     1004        QNetworkConfigurationManager manager;
     1005        if (!d->networkConfiguration.isEmpty()) {
     1006            d->createSession(manager.configurationFromIdentifier(d->networkConfiguration));
     1007        } else {
     1008            if (manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired)
     1009                d->createSession(manager.defaultConfiguration());
     1010            else
     1011                d->initializeSession = false;
     1012        }
     1013    }
     1014
     1015    if (d->networkSession)
     1016        d->networkSession->setSessionProperty(QLatin1String("AutoCloseSessionTimeout"), -1);
     1017#endif
    7121018
    7131019    QNetworkRequest request = req;
     
    7181024        request.setHeader(QNetworkRequest::ContentLengthHeader, outgoingData->size());
    7191025    }
    720     if (d->cookieJar) {
    721         QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url());
    722         if (!cookies.isEmpty())
    723             request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies));
     1026
     1027    if (static_cast<QNetworkRequest::LoadControl>
     1028        (request.attribute(QNetworkRequest::CookieLoadControlAttribute,
     1029                           QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Automatic) {
     1030        if (d->cookieJar) {
     1031            QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url());
     1032            if (!cookies.isEmpty())
     1033                request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies));
     1034        }
    7241035    }
    7251036
     
    7271038    QUrl url = request.url();
    7281039    QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
     1040#ifndef QT_NO_BEARERMANAGEMENT
     1041    if (req.url().scheme() != QLatin1String("file") && !req.url().scheme().isEmpty()) {
     1042        connect(this, SIGNAL(networkSessionConnected()),
     1043                reply, SLOT(_q_networkSessionConnected()));
     1044    }
     1045#endif
    7291046    QNetworkReplyImplPrivate *priv = reply->d_func();
    7301047    priv->manager = this;
    7311048
    7321049    // second step: fetch cached credentials
    733     QNetworkAuthenticationCredential *cred = d->fetchCachedCredentials(url);
    734     if (cred) {
    735         url.setUserName(cred->user);
    736         url.setPassword(cred->password);
    737         priv->urlForLastAuthentication = url;
    738     }
     1050    // This is not done for the time being, we should use signal emissions to request
     1051    // the credentials from cache.
    7391052
    7401053    // third step: find a backend
     
    7491062        priv->backend->reply = priv;
    7501063    }
    751     // fourth step: setup the reply
    752     priv->setup(op, request, outgoingData);
    7531064
    7541065#ifndef QT_NO_OPENSSL
    7551066    reply->setSslConfiguration(request.sslConfiguration());
    7561067#endif
     1068
     1069    // fourth step: setup the reply
     1070    priv->setup(op, request, outgoingData);
     1071
    7571072    return reply;
    7581073}
     
    7611076{
    7621077    Q_Q(QNetworkAccessManager);
     1078
    7631079    QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
    7641080    if (reply)
    7651081        emit q->finished(reply);
     1082
     1083#ifndef QT_NO_BEARERMANAGEMENT
     1084    if (networkSession && q->findChildren<QNetworkReply *>().count() == 1)
     1085        networkSession->setSessionProperty(QLatin1String("AutoCloseSessionTimeout"), 120000);
     1086#endif
    7661087}
    7671088
     
    8121133    // don't try the cache for the same URL twice in a row
    8131134    // being called twice for the same URL means the authentication failed
    814     if (url != backend->reply->urlForLastAuthentication) {
     1135    // also called when last URL is empty, e.g. on first call
     1136    if (backend->reply->urlForLastAuthentication.isEmpty()
     1137            || url != backend->reply->urlForLastAuthentication) {
    8151138        QNetworkAuthenticationCredential *cred = fetchCachedCredentials(url, authenticator);
    8161139        if (cred) {
     
    8221145    }
    8231146
     1147    // if we emit a signal here in synchronous mode, the user might spin
     1148    // an event loop, which might recurse and lead to problems
     1149    if (backend->isSynchronous())
     1150        return;
     1151
    8241152    backend->reply->urlForLastAuthentication = url;
    8251153    emit q->authenticationRequired(backend->reply->q_func(), authenticator);
    826     addCredentials(url, authenticator);
     1154    cacheCredentials(url, authenticator);
    8271155}
    8281156
     
    8411169    //      or a new function proxyAuthenticationSucceeded(true|false)
    8421170    if (proxy != backend->reply->lastProxyAuthentication) {
    843         QNetworkAuthenticationCredential *cred = fetchCachedCredentials(proxy);
     1171        QNetworkAuthenticationCredential *cred = fetchCachedProxyCredentials(proxy);
    8441172        if (cred) {
    8451173            authenticator->setUser(cred->user);
     
    8491177    }
    8501178
     1179    // if we emit a signal here in synchronous mode, the user might spin
     1180    // an event loop, which might recurse and lead to problems
     1181    if (backend->isSynchronous())
     1182        return;
     1183
    8511184    backend->reply->lastProxyAuthentication = proxy;
    8521185    emit q->proxyAuthenticationRequired(proxy, authenticator);
    853     addCredentials(proxy, authenticator);
    854 }
    855 
    856 void QNetworkAccessManagerPrivate::addCredentials(const QNetworkProxy &p,
     1186    cacheProxyCredentials(proxy, authenticator);
     1187}
     1188
     1189void QNetworkAccessManagerPrivate::cacheProxyCredentials(const QNetworkProxy &p,
    8571190                                                  const QAuthenticator *authenticator)
    8581191{
     
    8911224
    8921225QNetworkAuthenticationCredential *
    893 QNetworkAccessManagerPrivate::fetchCachedCredentials(const QNetworkProxy &p,
     1226QNetworkAccessManagerPrivate::fetchCachedProxyCredentials(const QNetworkProxy &p,
    8941227                                                     const QAuthenticator *authenticator)
    8951228{
     
    9431276#endif
    9441277
    945 void QNetworkAccessManagerPrivate::addCredentials(const QUrl &url,
     1278void QNetworkAccessManagerPrivate::cacheCredentials(const QUrl &url,
    9461279                                                  const QAuthenticator *authenticator)
    9471280{
     
    10161349}
    10171350
     1351#ifndef QT_NO_BEARERMANAGEMENT
     1352void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &config)
     1353{
     1354    Q_Q(QNetworkAccessManager);
     1355
     1356    initializeSession = false;
     1357
     1358    if (!config.isValid()) {
     1359        networkSession.clear();
     1360        online = false;
     1361
     1362        if (networkAccessible == QNetworkAccessManager::NotAccessible)
     1363            emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible);
     1364        else
     1365            emit q->networkAccessibleChanged(QNetworkAccessManager::UnknownAccessibility);
     1366
     1367        return;
     1368    }
     1369
     1370    networkSession = QSharedNetworkSessionManager::getSession(config);
     1371
     1372    QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()), Qt::QueuedConnection);
     1373    //QueuedConnection is used to avoid deleting the networkSession inside its closed signal
     1374    QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection);
     1375    QObject::connect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)),
     1376                     q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection);
     1377
     1378    _q_networkSessionStateChanged(networkSession->state());
     1379}
     1380
     1381void QNetworkAccessManagerPrivate::_q_networkSessionClosed()
     1382{
     1383    if (networkSession) {
     1384        networkConfiguration = networkSession->configuration().identifier();
     1385
     1386        networkSession.clear();
     1387    }
     1388}
     1389
     1390void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession::State state)
     1391{
     1392    Q_Q(QNetworkAccessManager);
     1393
     1394    if (state == QNetworkSession::Connected)
     1395        emit q->networkSessionConnected();
     1396    if (online) {
     1397        if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) {
     1398            online = false;
     1399            emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible);
     1400        }
     1401    } else {
     1402        if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) {
     1403            online = true;
     1404            emit q->networkAccessibleChanged(networkAccessible);
     1405        }
     1406    }
     1407}
     1408#endif // QT_NO_BEARERMANAGEMENT
     1409
    10181410QT_END_NAMESPACE
    10191411
  • trunk/src/network/access/qnetworkaccessmanager.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6363class QNetworkProxyFactory;
    6464class QSslError;
     65#if !defined(QT_NO_BEARERMANAGEMENT) && !defined(QT_MOBILITY_BEARER)
     66class QNetworkConfiguration;
     67#endif
    6568
    6669class QNetworkReplyImplPrivate;
     
    6972{
    7073    Q_OBJECT
     74
     75#ifndef QT_NO_BEARERMANAGEMENT
     76    Q_PROPERTY(NetworkAccessibility networkAccessible READ networkAccessible WRITE setNetworkAccessible NOTIFY networkAccessibleChanged)
     77#endif
     78
    7179public:
    7280    enum Operation {
     
    7684        PostOperation,
    7785        DeleteOperation,
     86        CustomOperation,
    7887
    7988        UnknownOperation = 0
    8089    };
     90
     91#ifndef QT_NO_BEARERMANAGEMENT
     92    enum NetworkAccessibility {
     93        UnknownAccessibility = -1,
     94        NotAccessible = 0,
     95        Accessible = 1
     96    };
     97#endif
    8198
    8299    explicit QNetworkAccessManager(QObject *parent = 0);
     
    103120    QNetworkReply *put(const QNetworkRequest &request, const QByteArray &data);
    104121    QNetworkReply *deleteResource(const QNetworkRequest &request);
     122    QNetworkReply *sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data = 0);
     123
     124#if !defined(QT_NO_BEARERMANAGEMENT) && !defined(QT_MOBILITY_BEARER)
     125    void setConfiguration(const QNetworkConfiguration &config);
     126    QNetworkConfiguration configuration() const;
     127    QNetworkConfiguration activeConfiguration() const;
     128#endif
     129
     130#ifndef QT_NO_BEARERMANAGEMENT
     131    void setNetworkAccessible(NetworkAccessibility accessible);
     132    NetworkAccessibility networkAccessible() const;
     133#endif
    105134
    106135Q_SIGNALS:
     
    114143#endif
    115144
     145#if !defined(QT_NO_BEARERMANAGEMENT) && !defined(QT_MOBILITY_BEARER)
     146    void networkSessionConnected();
     147#endif
     148
     149#ifndef QT_NO_BEARERMANAGEMENT
     150    void networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible);
     151#endif
     152
    116153protected:
    117154    virtual QNetworkReply *createRequest(Operation op, const QNetworkRequest &request,
     
    123160    Q_PRIVATE_SLOT(d_func(), void _q_replyFinished())
    124161    Q_PRIVATE_SLOT(d_func(), void _q_replySslErrors(QList<QSslError>))
     162#if !defined(QT_NO_BEARERMANAGEMENT) && !defined(QT_MOBILITY_BEARER)
     163    Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed())
     164    Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State))
     165#endif
    125166};
    126167
  • trunk/src/network/access/qnetworkaccessmanager_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5959#include "private/qobject_p.h"
    6060#include "QtNetwork/qnetworkproxy.h"
     61#include "QtNetwork/qnetworksession.h"
    6162
    6263QT_BEGIN_NAMESPACE
     
    7576          proxyFactory(0),
    7677#endif
     78#ifndef QT_NO_BEARERMANAGEMENT
     79          networkSession(0),
     80          networkAccessible(QNetworkAccessManager::Accessible),
     81          online(false),
     82          initializeSession(true),
     83#endif
    7784          cookieJarCreated(false)
    7885    { }
     
    8592
    8693    void authenticationRequired(QNetworkAccessBackend *backend, QAuthenticator *authenticator);
    87     void addCredentials(const QUrl &url, const QAuthenticator *auth);
     94    void cacheCredentials(const QUrl &url, const QAuthenticator *auth);
    8895    QNetworkAuthenticationCredential *fetchCachedCredentials(const QUrl &url,
    8996                                                             const QAuthenticator *auth = 0);
     
    9299    void proxyAuthenticationRequired(QNetworkAccessBackend *backend, const QNetworkProxy &proxy,
    93100                                     QAuthenticator *authenticator);
    94     void addCredentials(const QNetworkProxy &proxy, const QAuthenticator *auth);
    95     QNetworkAuthenticationCredential *fetchCachedCredentials(const QNetworkProxy &proxy,
     101    void cacheProxyCredentials(const QNetworkProxy &proxy, const QAuthenticator *auth);
     102    QNetworkAuthenticationCredential *fetchCachedProxyCredentials(const QNetworkProxy &proxy,
    96103                                                             const QAuthenticator *auth = 0);
    97104    QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query);
     
    99106
    100107    QNetworkAccessBackend *findBackend(QNetworkAccessManager::Operation op, const QNetworkRequest &request);
     108
     109#ifndef QT_NO_BEARERMANAGEMENT
     110    void createSession(const QNetworkConfiguration &config);
     111
     112    void _q_networkSessionClosed();
     113    void _q_networkSessionNewConfigurationActivated();
     114    void _q_networkSessionPreferredConfigurationChanged(const QNetworkConfiguration &config,
     115                                                        bool isSeamless);
     116    void _q_networkSessionStateChanged(QNetworkSession::State state);
     117#endif
    101118
    102119    // this is the cache for storing downloaded files
     
    111128#endif
    112129
     130#ifndef QT_NO_BEARERMANAGEMENT
     131    QSharedPointer<QNetworkSession> networkSession;
     132    QString networkConfiguration;
     133    QNetworkAccessManager::NetworkAccessibility networkAccessible;
     134    bool online;
     135    bool initializeSession;
     136#endif
     137
    113138    bool cookieJarCreated;
    114 
    115139
    116140    // this cache can be used by individual backends to cache e.g. their TCP connections to a server
  • trunk/src/network/access/qnetworkcookie.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    992992
    993993                    QString normalizedDomain = QUrl::fromAce(QUrl::toAce(QString::fromUtf8(rawDomain)));
     994                    if (normalizedDomain.isEmpty() && !rawDomain.isEmpty())
     995                        return result;
    994996                    cookie.setDomain(maybeLeadingDot + normalizedDomain);
    995997                } else if (field.first == "max-age") {
  • trunk/src/network/access/qnetworkcookie.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qnetworkcookie_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qnetworkcookiejar.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4141
    4242#include "qnetworkcookiejar.h"
     43#include "qnetworkcookiejartlds_p.h"
    4344#include "qnetworkcookiejar_p.h"
    4445
     
    158159    url object.
    159160
    160     Returns true if one or more cookes are set for url otherwise false.
     161    Returns true if one or more cookies are set for \a url,
     162    otherwise false.
    161163
    162164    If a cookie already exists in the cookie jar, it will be
     
    209211            QString domain = cookie.domain();
    210212            if (!(isParentDomain(domain, defaultDomain)
    211                 || isParentDomain(defaultDomain, domain))) {
    212                     continue;           // not accepted
    213             }
    214 
    215             // reject if domain is like ".com"
    216             // (i.e., reject if domain does not contain embedded dots, see RFC 2109 section 4.3.2)
    217             // this is just a rudimentary check and does not cover all cases
    218             if (domain.lastIndexOf(QLatin1Char('.')) == 0)
    219                 continue;           // not accepted
    220 
     213                || isParentDomain(defaultDomain, domain)))
     214                continue; // not accepted
     215
     216            // the check for effective TLDs makes the "embedded dot" rule from RFC 2109 section 4.3.2
     217            // redundant; the "leading dot" rule has been relaxed anyway, see above
     218            // we remove the leading dot for this check
     219            if (QNetworkCookieJarPrivate::isEffectiveTLD(domain.remove(0, 1)))
     220                continue; // not accepted
    221221        }
    222222
     
    251251    differing paths, the one with longer path is returned before the
    252252    one with shorter path. In other words, this function returns
    253     cookies sorted by path length.
     253    cookies sorted decreasingly by path length.
    254254
    255255    The default QNetworkCookieJar class implements only a very basic
     
    270270    QDateTime now = QDateTime::currentDateTime();
    271271    QList<QNetworkCookie> result;
     272    bool isEncrypted = url.scheme().toLower() == QLatin1String("https");
    272273
    273274    // scan our cookies for something that matches
     
    280281            continue;
    281282        if (!(*it).isSessionCookie() && (*it).expirationDate() < now)
     283            continue;
     284        if ((*it).isSecure() && !isEncrypted)
    282285            continue;
    283286
     
    302305}
    303306
     307bool QNetworkCookieJarPrivate::isEffectiveTLD(const QString &domain)
     308{
     309    // for domain 'foo.bar.com':
     310    // 1. return if TLD table contains 'foo.bar.com'
     311    if (containsTLDEntry(domain))
     312        return true;
     313
     314    if (domain.contains(QLatin1Char('.'))) {
     315        int count = domain.size() - domain.indexOf(QLatin1Char('.'));
     316        QString wildCardDomain;
     317        wildCardDomain.reserve(count + 1);
     318        wildCardDomain.append(QLatin1Char('*'));
     319        wildCardDomain.append(domain.right(count));
     320        // 2. if table contains '*.bar.com',
     321        // test if table contains '!foo.bar.com'
     322        if (containsTLDEntry(wildCardDomain)) {
     323            QString exceptionDomain;
     324            exceptionDomain.reserve(domain.size() + 1);
     325            exceptionDomain.append(QLatin1Char('!'));
     326            exceptionDomain.append(domain);
     327            return (! containsTLDEntry(exceptionDomain));
     328        }
     329    }
     330    return false;
     331}
     332
     333bool QNetworkCookieJarPrivate::containsTLDEntry(const QString &entry)
     334{
     335    int index = qHash(entry) % tldCount;
     336    int currentDomainIndex = tldIndices[index];
     337    while (currentDomainIndex < tldIndices[index+1]) {
     338        QString currentEntry = QString::fromUtf8(tldData + currentDomainIndex);
     339        if (currentEntry == entry)
     340            return true;
     341        currentDomainIndex += qstrlen(tldData + currentDomainIndex) + 1; // +1 for the ending \0
     342    }
     343    return false;
     344}
     345
    304346QT_END_NAMESPACE
  • trunk/src/network/access/qnetworkcookiejar.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qnetworkcookiejar_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6464    QList<QNetworkCookie> allCookies;
    6565
     66    static bool Q_AUTOTEST_EXPORT isEffectiveTLD(const QString &domain);
     67    static bool containsTLDEntry(const QString &entry);
     68
    6669    Q_DECLARE_PUBLIC(QNetworkCookieJar)
    6770};
  • trunk/src/network/access/qnetworkdiskcache.cpp

    r774 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    512512    QDirIterator it(cacheDirectory(), filters, QDirIterator::Subdirectories);
    513513
    514     // performance tweak: we store the size together with the name in
    515     // order to avoid querying the size again before the file is deleted
    516     typedef QPair<QString, qint64> ExpireInfo;
    517 
    518     QMultiMap<QDateTime, ExpireInfo> cacheItems;
     514    QMultiMap<QDateTime, QString> cacheItems;
    519515    qint64 totalSize = 0;
    520516    while (it.hasNext()) {
     
    523519        QString fileName = info.fileName();
    524520        if (fileName.endsWith(CACHE_POSTFIX) && fileName.startsWith(CACHE_PREFIX)) {
    525             ExpireInfo item = qMakePair(path, info.size());
    526             cacheItems.insert(info.created(), item);
    527             totalSize += item.second;
     521            cacheItems.insert(info.created(), path);
     522            totalSize += info.size();
    528523        }
    529524    }
     
    531526    int removedFiles = 0;
    532527    qint64 goal = (maximumCacheSize() * 9) / 10;
    533     QMultiMap<QDateTime, ExpireInfo>::const_iterator i = cacheItems.constBegin();
     528    QMultiMap<QDateTime, QString>::const_iterator i = cacheItems.constBegin();
    534529    while (i != cacheItems.constEnd()) {
    535530        if (totalSize < goal)
    536531            break;
    537         const ExpireInfo &item = i.value();
    538         QFile::remove(item.first);
    539         totalSize -= item.second;
     532        QString name = i.value();
     533        QFile file(name);
     534        qint64 size = file.size();
     535        file.remove();
     536        totalSize -= size;
    540537        ++removedFiles;
    541538        ++i;
  • trunk/src/network/access/qnetworkdiskcache.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qnetworkdiskcache_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qnetworkreply.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    126126    should have been emitted.
    127127
     128    \value TemporaryNetworkFailureError the connection was broken due
     129    to disconnection from the network, however the system has initiated
     130    roaming to another access point. The request should be resubmitted
     131    and will be processed as soon as the connection is re-established.
     132
    128133    \value ProxyConnectionRefusedError the connection to the proxy
    129134    server was refused (the proxy server is not accepting requests)
     
    279284    bytesTotal. At that time, \a bytesTotal will not be -1.
    280285
    281     This signal is suitable to connecting to QProgressBar::setValue()
    282     to update the QProgressBar that provides user feedback.
    283 
    284286    \sa downloadProgress()
    285287*/
     
    301303    The download is finished when \a bytesReceived is equal to \a
    302304    bytesTotal. At that time, \a bytesTotal will not be -1.
    303 
    304     This signal is suitable to connecting to QProgressBar::setValue()
    305     to update the QProgressBar that provides user feedback.
    306305
    307306    Note that the values of both \a bytesReceived and \a bytesTotal
     
    532531        return it->second;
    533532    return QByteArray();
     533}
     534
     535/*! \typedef QNetworkReply::RawHeaderPair
     536
     537  RawHeaderPair is a QPair<QByteArray, QByteArray> where the first
     538  QByteArray is the header name and the second is the header.
     539 */
     540
     541/*!
     542  Returns a list of raw header pairs.
     543 */
     544const QList<QNetworkReply::RawHeaderPair>& QNetworkReply::rawHeaderPairs() const
     545{
     546    Q_D(const QNetworkReply);
     547    return d->rawHeaders;
    534548}
    535549
  • trunk/src/network/access/qnetworkreply.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7878        OperationCanceledError,
    7979        SslHandshakeFailedError,
     80        TemporaryNetworkFailureError,
    8081        UnknownNetworkError = 99,
    8182
     
    129130    QByteArray rawHeader(const QByteArray &headerName) const;
    130131
     132    typedef QPair<QByteArray, QByteArray> RawHeaderPair;
     133    const QList<RawHeaderPair>& rawHeaderPairs() const;
     134
    131135    // attributes
    132136    QVariant attribute(QNetworkRequest::Attribute code) const;
  • trunk/src/network/access/qnetworkreply_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/access/qnetworkreplyimpl.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4747#include "QtCore/qdatetime.h"
    4848#include "QtNetwork/qsslconfiguration.h"
     49#include "QtNetwork/qnetworksession.h"
    4950#include "qnetworkaccesshttpbackend_p.h"
     51#include "qnetworkaccessmanager_p.h"
    5052
    5153#include <QtCore/QCoreApplication>
     
    5860      cacheEnabled(false), cacheSaveDevice(0),
    5961      notificationHandlingPaused(false),
    60       bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1),
     62      bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1), preMigrationDownloaded(-1),
    6163      httpStatusCode(0),
    6264      state(Idle)
     
    8385    }
    8486
    85     backend->open();
    86     if (state != Finished) {
    87         if (operation == QNetworkAccessManager::GetOperation)
    88             pendingNotifications.append(NotifyDownstreamReadyWrite);
    89 
    90         handleNotifications();
     87#ifndef QT_NO_BEARERMANAGEMENT
     88    if (!backend->start()) { // ### we should call that method even if bearer is not used
     89        // backend failed to start because the session state is not Connected.
     90        // QNetworkAccessManager will call reply->backend->start() again for us when the session
     91        // state changes.
     92        state = WaitingForSession;
     93
     94        QNetworkSession *session = manager->d_func()->networkSession.data();
     95
     96        if (session) {
     97            Q_Q(QNetworkReplyImpl);
     98
     99            QObject::connect(session, SIGNAL(error(QNetworkSession::SessionError)),
     100                             q, SLOT(_q_networkSessionFailed()));
     101
     102            if (!session->isOpen())
     103                session->open();
     104        } else {
     105            qWarning("Backend is waiting for QNetworkSession to connect, but there is none!");
     106        }
     107
     108        return;
     109    }
     110#endif
     111
     112    if (backend && backend->isSynchronous()) {
     113        state = Finished;
     114    } else {
     115        if (state != Finished) {
     116            if (operation == QNetworkAccessManager::GetOperation)
     117                pendingNotifications.append(NotifyDownstreamReadyWrite);
     118
     119            handleNotifications();
     120        }
    91121    }
    92122}
     
    135165    lastBytesDownloaded = bytesDownloaded;
    136166    QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
     167    if (preMigrationDownloaded != Q_INT64_C(-1))
     168        totalSize = totalSize.toLongLong() + preMigrationDownloaded;
    137169    pauseNotificationHandling();
    138170    emit q->downloadProgress(bytesDownloaded,
     
    207239}
    208240
     241#ifndef QT_NO_BEARERMANAGEMENT
     242void QNetworkReplyImplPrivate::_q_networkSessionConnected()
     243{
     244    Q_Q(QNetworkReplyImpl);
     245
     246    if (manager.isNull())
     247        return;
     248
     249    QNetworkSession *session = manager->d_func()->networkSession.data();
     250    if (!session)
     251        return;
     252
     253    if (session->state() != QNetworkSession::Connected)
     254        return;
     255
     256    switch (state) {
     257    case QNetworkReplyImplPrivate::Buffering:
     258    case QNetworkReplyImplPrivate::Working:
     259    case QNetworkReplyImplPrivate::Reconnecting:
     260        // Migrate existing downloads to new network connection.
     261        migrateBackend();
     262        break;
     263    case QNetworkReplyImplPrivate::WaitingForSession:
     264        // Start waiting requests.
     265        QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
     266        break;
     267    default:
     268        ;
     269    }
     270}
     271
     272void QNetworkReplyImplPrivate::_q_networkSessionFailed()
     273{
     274    // Abort waiting and working replies.
     275    if (state == WaitingForSession || state == Working) {
     276        state = Working;
     277        error(QNetworkReplyImpl::UnknownNetworkError,
     278              QCoreApplication::translate("QNetworkReply", "Network session error."));
     279        finished();
     280    }
     281}
     282#endif
     283
    209284void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req,
    210285                                     QIODevice *data)
     
    217292    operation = op;
    218293
    219     if (outgoingData && backend) {
     294    q->QIODevice::open(QIODevice::ReadOnly);
     295    // Internal code that does a HTTP reply for the synchronous Ajax
     296    // in QtWebKit.
     297    QVariant synchronousHttpAttribute = req.attribute(
     298            static_cast<QNetworkRequest::Attribute>(QNetworkRequest::DownloadBufferAttribute + 1));
     299    if (backend && synchronousHttpAttribute.toBool()) {
     300        backend->setSynchronous(true);
     301        if (outgoingData && outgoingData->isSequential()) {
     302            outgoingDataBuffer = new QRingBuffer();
     303            QByteArray data;
     304            do {
     305                data = outgoingData->readAll();
     306                if (data.isEmpty())
     307                    break;
     308                outgoingDataBuffer->append(data);
     309            } while (1);
     310        }
     311    }
     312    if (outgoingData && backend && !backend->isSynchronous()) {
    220313        // there is data to be uploaded, e.g. HTTP POST.
    221314
     
    228321            bool bufferingDisallowed =
    229322                    req.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute,
    230                                              false).toBool();
     323                                  false).toBool();
    231324
    232325            if (bufferingDisallowed) {
     
    252345        // for HTTP, we want to send out the request as fast as possible to the network, without
    253346        // invoking methods in a QueuedConnection
    254         if (qobject_cast<QNetworkAccessHttpBackend *>(backend)) {
     347#ifndef QT_NO_HTTP
     348        if (qobject_cast<QNetworkAccessHttpBackend *>(backend) || (backend && backend->isSynchronous())) {
    255349            _q_startOperation();
    256350        } else {
    257351            QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
    258352        }
    259     }
    260 
    261     q->QIODevice::open(QIODevice::ReadOnly);
     353#else
     354        if (backend && backend->isSynchronous())
     355            _q_startOperation();
     356        else
     357            QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
     358#endif // QT_NO_HTTP
     359        }
    262360}
    263361
     
    472570
    473571    QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
     572    if (preMigrationDownloaded != Q_INT64_C(-1))
     573        totalSize = totalSize.toLongLong() + preMigrationDownloaded;
    474574    pauseNotificationHandling();
    475575    emit q->downloadProgress(bytesDownloaded,
     
    512612void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data)
    513613{
     614    Q_UNUSED(data)
    514615    // TODO implement
    515616
     
    522623{
    523624    Q_Q(QNetworkReplyImpl);
    524     if (state == Finished || state == Aborted)
    525         return;
     625
     626    if (state == Finished || state == Aborted || state == WaitingForSession)
     627        return;
     628
     629    pauseNotificationHandling();
     630    QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
     631    if (preMigrationDownloaded != Q_INT64_C(-1))
     632        totalSize = totalSize.toLongLong() + preMigrationDownloaded;
     633
     634    if (!manager.isNull()) {
     635#ifndef QT_NO_BEARERMANAGEMENT
     636        QNetworkSession *session = manager->d_func()->networkSession.data();
     637        if (session && session->state() == QNetworkSession::Roaming &&
     638            state == Working && errorCode != QNetworkReply::OperationCanceledError) {
     639            // only content with a known size will fail with a temporary network failure error
     640            if (!totalSize.isNull()) {
     641                if (bytesDownloaded != totalSize) {
     642                    if (migrateBackend()) {
     643                        // either we are migrating or the request is finished/aborted
     644                        if (state == Reconnecting || state == WaitingForSession) {
     645                            resumeNotificationHandling();
     646                            return; // exit early if we are migrating.
     647                        }
     648                    } else {
     649                        error(QNetworkReply::TemporaryNetworkFailureError,
     650                              QNetworkReply::tr("Temporary network failure."));
     651                    }
     652                }
     653            }
     654        }
     655#endif
     656    }
     657    resumeNotificationHandling();
    526658
    527659    state = Finished;
     
    529661
    530662    pauseNotificationHandling();
    531     QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
    532663    if (totalSize.isNull() || totalSize == -1) {
    533664        emit q->downloadProgress(bytesDownloaded, bytesDownloaded);
     
    538669    resumeNotificationHandling();
    539670
    540     completeCacheSave();
     671    // if we don't know the total size of or we received everything save the cache
     672    if (totalSize.isNull() || totalSize == -1 || bytesDownloaded == totalSize)
     673        completeCacheSave();
    541674
    542675    // note: might not be a good idea, since users could decide to delete us
     
    565698{
    566699    Q_Q(QNetworkReplyImpl);
    567     // do we have cookies?
    568     if (cookedHeaders.contains(QNetworkRequest::SetCookieHeader) && !manager.isNull()) {
     700    // 1. do we have cookies?
     701    // 2. are we allowed to set them?
     702    if (cookedHeaders.contains(QNetworkRequest::SetCookieHeader) && !manager.isNull()
     703        && (static_cast<QNetworkRequest::LoadControl>
     704            (request.attribute(QNetworkRequest::CookieSaveControlAttribute,
     705                               QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Automatic)) {
    569706        QList<QNetworkCookie> cookies =
    570707            qvariant_cast<QList<QNetworkCookie> >(cookedHeaders.value(QNetworkRequest::SetCookieHeader));
     
    662799    d->finished();
    663800}
     801
     802bool QNetworkReplyImpl::canReadLine () const
     803{
     804    Q_D(const QNetworkReplyImpl);
     805    return QNetworkReply::canReadLine() || d->readBuffer.canReadLine();
     806}
     807
    664808
    665809/*!
     
    751895}
    752896
     897/*
     898    Migrates the backend of the QNetworkReply to a new network connection if required.  Returns
     899    true if the reply is migrated or it is not required; otherwise returns false.
     900*/
     901bool QNetworkReplyImplPrivate::migrateBackend()
     902{
     903    Q_Q(QNetworkReplyImpl);
     904
     905    // Network reply is already finished or aborted, don't need to migrate.
     906    if (state == Finished || state == Aborted)
     907        return true;
     908
     909    // Backend does not support resuming download.
     910    if (!backend->canResume())
     911        return false;
     912
     913    // Request has outgoing data, not migrating.
     914    if (outgoingData)
     915        return false;
     916
     917    // Request is serviced from the cache, don't need to migrate.
     918    if (copyDevice)
     919        return true;
     920
     921    state = QNetworkReplyImplPrivate::Reconnecting;
     922
     923    if (backend) {
     924        delete backend;
     925        backend = 0;
     926    }
     927
     928    cookedHeaders.clear();
     929    rawHeaders.clear();
     930
     931    preMigrationDownloaded = bytesDownloaded;
     932
     933    backend = manager->d_func()->findBackend(operation, request);
     934
     935    if (backend) {
     936        backend->setParent(q);
     937        backend->reply = this;
     938        backend->setResumeOffset(bytesDownloaded);
     939    }
     940
     941#ifndef QT_NO_HTTP
     942    if (qobject_cast<QNetworkAccessHttpBackend *>(backend)) {
     943        _q_startOperation();
     944    } else {
     945        QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
     946    }
     947#else
     948    QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
     949#endif // QT_NO_HTTP
     950
     951    return true;
     952}
     953
     954#ifndef QT_NO_BEARERMANAGEMENT
     955QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent,
     956                                             const QNetworkRequest &req,
     957                                             QNetworkAccessManager::Operation op)
     958:   QNetworkReply(parent)
     959{
     960    setRequest(req);
     961    setUrl(req.url());
     962    setOperation(op);
     963
     964    qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
     965
     966    QString msg = QCoreApplication::translate("QNetworkAccessManager",
     967                                              "Network access is disabled.");
     968    setError(UnknownNetworkError, msg);
     969
     970    QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
     971        Q_ARG(QNetworkReply::NetworkError, UnknownNetworkError));
     972    QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
     973}
     974
     975QDisabledNetworkReply::~QDisabledNetworkReply()
     976{
     977}
     978#endif
     979
    753980QT_END_NAMESPACE
    754981
  • trunk/src/network/access/qnetworkreplyimpl_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7878    virtual void abort();
    7979
    80     // reimplemented from QNetworkReply
     80    // reimplemented from QNetworkReply / QIODevice
    8181    virtual void close();
    8282    virtual qint64 bytesAvailable() const;
    8383    virtual void setReadBufferSize(qint64 size);
     84    virtual bool canReadLine () const;
    8485
    8586    virtual qint64 readData(char *data, qint64 maxlen);
     
    99100    Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData())
    100101    Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished())
     102#ifndef QT_NO_BEARERMANAGEMENT
     103    Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
     104    Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
     105#endif
    101106};
    102107
     
    111116
    112117    enum State {
    113         Idle,
    114         Buffering,
    115         Working,
    116         Finished,
    117         Aborted
     118        Idle,               // The reply is idle.
     119        Buffering,          // The reply is buffering outgoing data.
     120        Working,            // The reply is uploading/downloading data.
     121        Finished,           // The reply has finished.
     122        Aborted,            // The reply has been aborted.
     123        WaitingForSession,  // The reply is waiting for the session to open before connecting.
     124        Reconnecting        // The reply will reconnect to once roaming has completed.
    118125    };
    119126
     
    129136    void _q_bufferOutgoingData();
    130137    void _q_bufferOutgoingDataFinished();
     138#ifndef QT_NO_BEARERMANAGEMENT
     139    void _q_networkSessionConnected();
     140    void _q_networkSessionFailed();
     141#endif
    131142
    132143    void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
     
    167178    QAbstractNetworkCache *networkCache() const;
    168179
     180    bool migrateBackend();
     181
    169182    bool cacheEnabled;
    170183    QIODevice *cacheSaveDevice;
     
    183196    qint64 lastBytesDownloaded;
    184197    qint64 bytesUploaded;
     198    qint64 preMigrationDownloaded;
    185199
    186200    QString httpReasonPhrase;
     
    192206};
    193207
     208#ifndef QT_NO_BEARERMANAGEMENT
     209class QDisabledNetworkReply : public QNetworkReply
     210{
     211    Q_OBJECT
     212
     213public:
     214    QDisabledNetworkReply(QObject *parent, const QNetworkRequest &req,
     215                          QNetworkAccessManager::Operation op);
     216    ~QDisabledNetworkReply();
     217
     218    void abort() { }
     219protected:
     220    qint64 readData(char *, qint64) { return -1; }
     221};
     222#endif
     223
    194224QT_END_NAMESPACE
    195225
  • trunk/src/network/access/qnetworkrequest.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    106106/*!
    107107    \enum QNetworkRequest::Attribute
    108 
     108    \since 4.7
     109   
    109110    Attribute codes for the QNetworkRequest and QNetworkReply.
    110111
     
    175176        header must be set.
    176177
    177      \value HttpPipeliningAllowedAttribute
     178    \value HttpPipeliningAllowedAttribute
    178179        Requests only, type: QVariant::Bool (default: false)
    179180        Indicates whether the QNetworkAccessManager code is
    180181        allowed to use HTTP pipelining with this request.
    181182
    182      \value HttpPipeliningWasUsedAttribute
     183    \value HttpPipeliningWasUsedAttribute
    183184        Replies only, type: QVariant::Bool
    184185        Indicates whether the HTTP pipelining was used for receiving
    185186        this reply.
     187
     188    \value CustomVerbAttribute
     189       Requests only, type: QVariant::ByteArray
     190       Holds the value for the custom HTTP verb to send (destined for usage
     191       of other verbs than GET, POST, PUT and DELETE). This verb is set
     192       when calling QNetworkAccessManager::sendCustomRequest().
     193
     194    \value CookieLoadControlAttribute
     195        Requests only, type: QVariant::Int (default: QNetworkRequest::Automatic)
     196        Indicates whether to send 'Cookie' headers in the request.
     197        This attribute is set to false by QtWebKit when creating a cross-origin
     198        XMLHttpRequest where withCredentials has not been set explicitly to true by the
     199        Javascript that created the request.
     200        See \l{http://www.w3.org/TR/XMLHttpRequest2/#credentials-flag}{here} for more information.
     201        (This value was introduced in 4.7.)
     202
     203    \value CookieSaveControlAttribute
     204        Requests only, type: QVariant::Int (default: QNetworkRequest::Automatic)
     205        Indicates whether to save 'Cookie' headers received from the server in reply
     206        to the request.
     207        This attribute is set to false by QtWebKit when creating a cross-origin
     208        XMLHttpRequest where withCredentials has not been set explicitly to true by the
     209        Javascript that created the request.
     210        See \l{http://www.w3.org/TR/XMLHttpRequest2/#credentials-flag} {here} for more information.
     211        (This value was introduced in 4.7.)
     212
     213    \value AuthenticationReuseAttribute
     214        Requests only, type: QVariant::Int (default: QNetworkRequest::Automatic)
     215        Indicates whether to use cached authorization credentials in the request,
     216        if available. If this is set to QNetworkRequest::Manual and the authentication
     217        mechanism is 'Basic' or 'Digest', Qt will not send an an 'Authorization' HTTP
     218        header with any cached credentials it may have for the request's URL.
     219        This attribute is set to QNetworkRequest::Manual by QtWebKit when creating a cross-origin
     220        XMLHttpRequest where withCredentials has not been set explicitly to true by the
     221        Javascript that created the request.
     222        See \l{http://www.w3.org/TR/XMLHttpRequest2/#credentials-flag} {here} for more information.
     223        (This value was introduced in 4.7.)
     224
     225    \omitvalue MaximumDownloadBufferSizeAttribute
     226
     227    \omitvalue DownloadBufferAttribute
    186228
    187229    \value User
     
    217259*/
    218260
     261/*!
     262    \enum QNetworkRequest::LoadControl
     263    \since 4.7
     264
     265    Indicates if an aspect of the request's loading mechanism has been
     266    manually overridden, e.g. by QtWebKit.
     267
     268    \value Automatic            default value: indicates default behaviour.
     269
     270    \value Manual               indicates behaviour has been manually overridden.
     271*/
     272
    219273class QNetworkRequestPrivate: public QSharedData, public QNetworkHeadersPrivate
    220274{
    221275public:
    222276    inline QNetworkRequestPrivate()
     277        : priority(QNetworkRequest::NormalPriority)
    223278#ifndef QT_NO_OPENSSL
    224         : sslConfiguration(0)
     279        , sslConfiguration(0)
    225280#endif
    226281    { qRegisterMetaType<QNetworkRequest>(); }
     
    237292    {
    238293        url = other.url;
     294        priority = other.priority;
    239295
    240296#ifndef QT_NO_OPENSSL
     
    248304    {
    249305        return url == other.url &&
     306            priority == other.priority &&
    250307            rawHeaders == other.rawHeaders &&
    251308            attributes == other.attributes;
     
    254311
    255312    QUrl url;
     313    QNetworkRequest::Priority priority;
    256314#ifndef QT_NO_OPENSSL
    257315    mutable QSslConfiguration *sslConfiguration;
     
    517575{
    518576    return d->originatingObject.data();
     577}
     578
     579/*!
     580    \since 4.7
     581
     582    Return the priority of this request.
     583
     584    \sa setPriority()
     585*/
     586QNetworkRequest::Priority QNetworkRequest::priority() const
     587{
     588    return d->priority;
     589}
     590
     591/*! \enum QNetworkRequest::Priority
     592
     593  \since 4.7
     594 
     595  This enum lists the possible network request priorities.
     596
     597  \value HighPriority   High priority
     598  \value NormalPriority Normal priority
     599  \value LowPriority    Low priority
     600 */
     601
     602/*!
     603    \since 4.7
     604
     605    Set the priority of this request to \a priority.
     606
     607    \note The \a priority is only a hint to the network access
     608    manager.  It can use it or not. Currently it is used for HTTP to
     609    decide which request should be sent first to a server.
     610
     611    \sa priority()
     612*/
     613void QNetworkRequest::setPriority(Priority priority)
     614{
     615    d->priority = priority;
    519616}
    520617
     
    803900    QNetworkRequest::KnownHeaders parsedKey = parseHeaderName(key);
    804901    if (parsedKey != QNetworkRequest::KnownHeaders(-1)) {
    805         if (value.isNull())
     902        if (value.isNull()) {
    806903            cookedHeaders.remove(parsedKey);
    807         else
     904        } else if (parsedKey == QNetworkRequest::ContentLengthHeader
     905                 && cookedHeaders.contains(QNetworkRequest::ContentLengthHeader)) {
     906            // Only set the cooked header "Content-Length" once.
     907            // See bug QTBUG-15311
     908        } else {
    808909            cookedHeaders.insert(parsedKey, parseHeaderValue(parsedKey, value));
     910        }
     911
    809912    }
    810913}
  • trunk/src/network/access/qnetworkrequest.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    7979        HttpPipeliningAllowedAttribute,
    8080        HttpPipeliningWasUsedAttribute,
     81        CustomVerbAttribute,
     82        CookieLoadControlAttribute,
     83        AuthenticationReuseAttribute,
     84        CookieSaveControlAttribute,
     85        MaximumDownloadBufferSizeAttribute, // internal
     86        DownloadBufferAttribute, // internal
     87
     88        // (DownloadBufferAttribute + 1) is reserved internal for QSynchronousHttpNetworkReply
     89        // add the enum in 4.8
    8190
    8291        User = 1000,
     
    8897        PreferCache,
    8998        AlwaysCache
     99    };
     100    enum LoadControl {
     101        Automatic = 0,
     102        Manual
     103    };
     104
     105    enum Priority {
     106        HighPriority = 1,
     107        NormalPriority = 3,
     108        LowPriority = 5
    90109    };
    91110
     
    124143    QObject *originatingObject() const;
    125144
     145    Priority priority() const;
     146    void setPriority(Priority priority);
     147
    126148private:
    127149    QSharedDataPointer<QNetworkRequestPrivate> d;
  • trunk/src/network/access/qnetworkrequest_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/kernel.pri

    r561 r846  
    2929mac:SOURCES += kernel/qnetworkproxy_mac.cpp
    3030else:win32:SOURCES += kernel/qnetworkproxy_win.cpp
     31else:symbian:SOURCES += kernel/qnetworkproxy_symbian.cpp
    3132else:SOURCES += kernel/qnetworkproxy_generic.cpp
    3233
     34symbian: LIBS += -lcommsdat
  • trunk/src/network/kernel/qauthenticator.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5151#include <qendian.h>
    5252#include <qstring.h>
     53#include <qdatetime.h>
     54
     55//#define NTLMV1_CLIENT
    5356
    5457QT_BEGIN_NAMESPACE
    5558
     59#ifdef NTLMV1_CLIENT
    5660#include "../../3rdparty/des/des.cpp"
     61#endif
    5762
    5863static QByteArray qNtlmPhase1();
     
    8489  Note that, in particular, NTLM version 2 is not supported.
    8590
     91  \section1 Options
     92
     93  In addition to the username and password required for authentication, a
     94  QAuthenticator object can also contain additional options. The
     95  options() function can be used to query incoming options sent by
     96  the server; the setOption() function can
     97  be used to set outgoing options, to be processed by the authenticator
     98  calculation. The options accepted and provided depend on the authentication
     99  type (see method()).
     100
     101  The following tables list known incoming options as well as accepted
     102  outgoing options. The list of incoming options is not exhaustive, since
     103  servers may include additional information at any time. The list of
     104  outgoing options is exhaustive, however, and no unknown options will be
     105  treated or sent back to the server.
     106
     107  \section2 Basic
     108
     109  \table
     110    \header \o Option \o Direction \o Description
     111    \row \o \tt{realm} \o Incoming \o Contains the realm of the authentication, the same as realm()
     112  \endtable
     113
     114  The Basic authentication mechanism supports no outgoing options.
     115
     116  \section2 NTLM version 1
     117
     118  The NTLM authentication mechanism currently supports no incoming or outgoing options.
     119
     120  \section2 Digest-MD5
     121
     122  \table
     123    \header \o Option \o Direction \o Description
     124    \row \o \tt{realm} \o Incoming \o Contains the realm of the authentication, the same as realm()
     125  \endtable
     126
     127  The Digest-MD5 authentication mechanism supports no outgoing options.
     128
    86129  \sa QSslSocket
    87130*/
     
    122165    if (d == other.d)
    123166        return *this;
    124     detach();
    125     d->user = other.d->user;
    126     d->password = other.d->password;
     167
     168    if (d && !d->ref.deref())
     169        delete d;
     170
     171    d = other.d;
     172    if (d)
     173        d->ref.ref();
    127174    return *this;
    128175}
     
    139186        && d->password == other.d->password
    140187        && d->realm == other.d->realm
    141         && d->method == other.d->method;
     188        && d->method == other.d->method
     189        && d->options == other.d->options;
    142190}
    143191
     
    163211{
    164212    detach();
    165     d->user = user;
     213    int separatorPosn = 0;
     214
     215    switch(d->method) {
     216    case QAuthenticatorPrivate::Ntlm:
     217        if((separatorPosn = user.indexOf(QLatin1String("\\"))) != -1) {
     218            //domain name is present
     219            d->realm.clear();
     220            d->userDomain = user.left(separatorPosn);
     221            d->extractedUser = user.mid(separatorPosn + 1);
     222            d->user = user;
     223        } else if((separatorPosn = user.indexOf(QLatin1String("@"))) != -1) {
     224            //domain name is present
     225            d->realm.clear();
     226            d->userDomain = user.left(separatorPosn);
     227            d->extractedUser = user.left(separatorPosn);
     228            d->user = user;
     229        } else {
     230            d->extractedUser = user;
     231            d->user = user;
     232            d->realm.clear();
     233            d->userDomain.clear();
     234        }
     235        break;
     236    default:
     237        d->user = user;
     238        d->userDomain.clear();
     239        break;
     240    }
    166241}
    167242
     
    206281}
    207282
    208 
    209 /*!
    210   returns true if the authenticator is null.
     283/*!
     284    \since 4.7
     285    Returns the value related to option \a opt if it was set by the server.
     286    See \l{QAuthenticator#Options} for more information on incoming options.
     287    If option \a opt isn't found, an invalid QVariant will be returned.
     288
     289    \sa options(), QAuthenticator#Options
     290*/
     291QVariant QAuthenticator::option(const QString &opt) const
     292{
     293    return d ? d->options.value(opt) : QVariant();
     294}
     295
     296/*!
     297    \since 4.7
     298    Returns all incoming options set in this QAuthenticator object by parsing
     299    the server reply. See \l{QAuthenticator#Options} for more information
     300    on incoming options.
     301
     302    \sa option(), QAuthenticator#Options
     303*/
     304QVariantHash QAuthenticator::options() const
     305{
     306    return d ? d->options : QVariantHash();
     307}
     308
     309/*!
     310    \since 4.7
     311
     312    Sets the outgoing option \a opt to value \a value.
     313    See \l{QAuthenticator#Options} for more information on outgoing options.
     314
     315    \sa options(), option(), QAuthenticator#Options
     316*/
     317void QAuthenticator::setOption(const QString &opt, const QVariant &value)
     318{
     319    detach();
     320    d->options.insert(opt, value);
     321}
     322
     323
     324/*!
     325    Returns true if the authenticator is null.
    211326*/
    212327bool QAuthenticator::isNull() const
     
    229344void QAuthenticatorPrivate::parseHttpResponse(const QHttpResponseHeader &header, bool isProxy)
    230345{
    231     QList<QPair<QString, QString> > values = header.values();
     346    const QList<QPair<QString, QString> > values = header.values();
     347    QList<QPair<QByteArray, QByteArray> > rawValues;
     348
     349    QList<QPair<QString, QString> >::const_iterator it, end;
     350    for (it = values.constBegin(), end = values.constEnd(); it != end; ++it)
     351        rawValues.append(qMakePair(it->first.toLatin1(), it->second.toUtf8()));
     352
     353    // continue in byte array form
     354    parseHttpResponse(rawValues, isProxy);
     355}
     356#endif
     357
     358void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByteArray> > &values, bool isProxy)
     359{
    232360    const char *search = isProxy ? "proxy-authenticate" : "www-authenticate";
    233361
     
    243371    */
    244372
    245     QString headerVal;
     373    QByteArray headerVal;
    246374    for (int i = 0; i < values.size(); ++i) {
    247         const QPair<QString, QString> &current = values.at(i);
    248         if (current.first.toLower() != QLatin1String(search))
     375        const QPair<QByteArray, QByteArray> &current = values.at(i);
     376        if (current.first.toLower() != search)
    249377            continue;
    250         QString str = current.second;
    251         if (method < Basic && str.startsWith(QLatin1String("Basic"), Qt::CaseInsensitive)) {
    252             method = Basic; headerVal = str.mid(6);
    253         } else if (method < Ntlm && str.startsWith(QLatin1String("NTLM"), Qt::CaseInsensitive)) {
     378        QByteArray str = current.second.toLower();
     379        if (method < Basic && str.startsWith("basic")) {
     380            method = Basic;
     381            headerVal = current.second.mid(6);
     382        } else if (method < Ntlm && str.startsWith("ntlm")) {
    254383            method = Ntlm;
    255             headerVal = str.mid(5);
    256         } else if (method < DigestMd5 && str.startsWith(QLatin1String("Digest"), Qt::CaseInsensitive)) {
     384            headerVal = current.second.mid(5);
     385        } else if (method < DigestMd5 && str.startsWith("digest")) {
    257386            method = DigestMd5;
    258             headerVal = str.mid(7);
     387            headerVal = current.second.mid(7);
    259388        }
    260389    }
    261390
    262     challenge = headerVal.trimmed().toLatin1();
     391    challenge = headerVal.trimmed();
    263392    QHash<QByteArray, QByteArray> options = parseDigestAuthenticationChallenge(challenge);
    264393
    265394    switch(method) {
    266395    case Basic:
    267         realm = QString::fromLatin1(options.value("realm"));
     396        if(realm.isEmpty())
     397            this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm"));
    268398        if (user.isEmpty())
    269399            phase = Done;
     
    271401    case Ntlm:
    272402        // #### extract from header
    273         realm.clear();
    274403        break;
    275404    case DigestMd5: {
    276         realm = QString::fromLatin1(options.value("realm"));
     405        if(realm.isEmpty())
     406            this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm"));
    277407        if (options.value("stale").toLower() == "true")
    278408            phase = Start;
     
    287417    }
    288418}
    289 #endif
    290419
    291420QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMethod, const QByteArray &path)
     
    662791#define NTLMSSP_NEGOTIATE_56 0x80000000
    663792
     793/*
     794 * AvId values
     795 */
     796#define AVTIMESTAMP 7
     797
     798//#define NTLMV1_CLIENT
     799
     800
     801//************************Global variables***************************
     802
     803const int blockSize = 64; //As per RFC2104 Block-size is 512 bits
     804const int nDigestLen = 16; //Trunctaion Length of the Hmac-Md5 digest
     805const quint8 respversion = 1;
     806const quint8 hirespversion = 1;
    664807
    665808/* usage:
     
    804947    // extracted
    805948    QString targetNameStr, targetInfoStr;
     949    QByteArray targetInfoBuff;
    806950};
    807951
     
    819963    QByteArray lmResponseBuf, ntlmResponseBuf;
    820964    QString domainStr, userStr, workstationStr, sessionKeyStr;
     965    QByteArray v2Hash;
    821966};
    822967
     
    9001045}
    9011046
    902 
     1047#ifdef NTLMV1_CLIENT
    9031048static QByteArray qEncodeNtlmResponse(const QAuthenticatorPrivate *ctx, const QNtlmPhase2Block& ch)
    9041049{
     
    9421087    return rc;
    9431088}
    944 
     1089#endif
     1090
     1091/*********************************************************************
     1092* Function Name: qEncodeHmacMd5
     1093* Params:
     1094*    key:   Type - QByteArray
     1095*         - It is the Authentication key
     1096*    message:   Type - QByteArray
     1097*         - This is the actual message which will be encoded
     1098*           using HMacMd5 hash algorithm
     1099*
     1100* Return Value:
     1101*    hmacDigest:   Type - QByteArray
     1102*
     1103* Description:
     1104*    This function will be used to encode the input message using
     1105*    HMacMd5 hash algorithm.
     1106*
     1107*    As per the RFC2104 the HMacMd5 algorithm can be specified
     1108*        ---------------------------------------
     1109*         MD5(K XOR opad, MD5(K XOR ipad, text))
     1110*        ---------------------------------------
     1111*
     1112*********************************************************************/
     1113QByteArray qEncodeHmacMd5(QByteArray &key, const QByteArray &message)
     1114{
     1115    Q_ASSERT_X(!(message.isEmpty()),"qEncodeHmacMd5", "Empty message check");
     1116    Q_ASSERT_X(!(key.isEmpty()),"qEncodeHmacMd5", "Empty key check");
     1117
     1118    QCryptographicHash hash(QCryptographicHash::Md5);
     1119    QByteArray hMsg;
     1120
     1121    QByteArray iKeyPad(blockSize, 0x36);
     1122    QByteArray oKeyPad(blockSize, 0x5c);
     1123
     1124    hash.reset();
     1125    // Adjust the key length to blockSize
     1126
     1127    if(blockSize < key.length()) {
     1128        hash.addData(key);
     1129        key = hash.result(); //MD5 will always return 16 bytes length output
     1130    }
     1131
     1132    //Key will be <= 16 or 20 bytes as hash function (MD5 or SHA hash algorithms)
     1133    //key size can be max of Block size only
     1134    key = key.leftJustified(blockSize,0,true);
     1135
     1136    //iKeyPad, oKeyPad and key are all of same size "blockSize"
     1137
     1138    //xor of iKeyPad with Key and store the result into iKeyPad
     1139    for(int i = 0; i<key.size();i++) {
     1140        iKeyPad[i] = key[i]^iKeyPad[i];
     1141    }
     1142
     1143    //xor of oKeyPad with Key and store the result into oKeyPad
     1144    for(int i = 0; i<key.size();i++) {
     1145        oKeyPad[i] = key[i]^oKeyPad[i];
     1146    }
     1147
     1148    iKeyPad.append(message); // (K0 xor ipad) || text
     1149
     1150    hash.reset();
     1151    hash.addData(iKeyPad);
     1152    hMsg = hash.result();
     1153                    //Digest gen after pass-1: H((K0 xor ipad)||text)
     1154
     1155    QByteArray hmacDigest;
     1156    oKeyPad.append(hMsg);
     1157    hash.reset();
     1158    hash.addData(oKeyPad);
     1159    hmacDigest = hash.result();
     1160                    // H((K0 xor opad )|| H((K0 xor ipad) || text))
     1161
     1162    /*hmacDigest should not be less than half the length of the HMAC output
     1163      (to match the birthday attack bound) and not less than 80 bits
     1164      (a suitable lower bound on the number of bits that need to be
     1165      predicted by an attacker).
     1166      Refer RFC 2104 for more details on truncation part */
     1167
     1168    /*MD5 hash always returns 16 byte digest only and HMAC-MD5 spec
     1169      (RFC 2104) also says digest length should be 16 bytes*/
     1170    return hmacDigest;
     1171}
     1172
     1173static QByteArray qCreatev2Hash(const QAuthenticatorPrivate *ctx,
     1174                                QNtlmPhase3Block *phase3)
     1175{
     1176    Q_ASSERT(phase3 != 0);
     1177    // since v2 Hash is need for both NTLMv2 and LMv2 it is calculated
     1178    // only once and stored and reused
     1179    if(phase3->v2Hash.size() == 0) {
     1180        QCryptographicHash md4(QCryptographicHash::Md4);
     1181        QByteArray passUnicode = qStringAsUcs2Le(ctx->password);
     1182        md4.addData(passUnicode.data(), passUnicode.size());
     1183
     1184        QByteArray hashKey = md4.result();
     1185        Q_ASSERT(hashKey.size() == 16);
     1186        // Assuming the user and domain is always unicode in challenge
     1187        QByteArray message =
     1188                qStringAsUcs2Le(ctx->extractedUser.toUpper()) +
     1189                qStringAsUcs2Le(phase3->domainStr);
     1190
     1191        phase3->v2Hash = qEncodeHmacMd5(hashKey, message);
     1192    }
     1193    return phase3->v2Hash;
     1194}
     1195
     1196static QByteArray clientChallenge(const QAuthenticatorPrivate *ctx)
     1197{
     1198    Q_ASSERT(ctx->cnonce.size() >= 8);
     1199    QByteArray clientCh = ctx->cnonce.right(8);
     1200    return clientCh;
     1201}
     1202
     1203// caller has to ensure a valid targetInfoBuff
     1204static QByteArray qExtractServerTime(const QByteArray& targetInfoBuff)
     1205{
     1206    QByteArray timeArray;
     1207    QDataStream ds(targetInfoBuff);
     1208    ds.setByteOrder(QDataStream::LittleEndian);
     1209
     1210    quint16 avId;
     1211    quint16 avLen;
     1212
     1213    ds >> avId;
     1214    ds >> avLen;
     1215    while(avId != 0) {
     1216        if(avId == AVTIMESTAMP) {
     1217            timeArray.resize(avLen);
     1218            //avLen size of QByteArray is allocated
     1219            ds.readRawData(timeArray.data(), avLen);
     1220            break;
     1221        }
     1222        ds.skipRawData(avLen);
     1223        ds >> avId;
     1224        ds >> avLen;
     1225    }
     1226    return timeArray;
     1227}
     1228
     1229static QByteArray qEncodeNtlmv2Response(const QAuthenticatorPrivate *ctx,
     1230                                        const QNtlmPhase2Block& ch,
     1231                                        QNtlmPhase3Block *phase3)
     1232{
     1233    Q_ASSERT(phase3 != 0);
     1234    // return value stored in phase3
     1235    qCreatev2Hash(ctx, phase3);
     1236
     1237    QByteArray temp;
     1238    QDataStream ds(&temp, QIODevice::WriteOnly);
     1239    ds.setByteOrder(QDataStream::LittleEndian);
     1240
     1241    ds << respversion;
     1242    ds << hirespversion;
     1243
     1244    //Reserved
     1245    QByteArray reserved1(6, 0);
     1246    ds.writeRawData(reserved1.constData(), reserved1.size());
     1247
     1248    quint64 time = 0;
     1249    QByteArray timeArray;
     1250
     1251    if(ch.targetInfo.len)
     1252    {
     1253        timeArray = qExtractServerTime(ch.targetInfoBuff);
     1254    }
     1255
     1256    //if server sends time, use it instead of current time
     1257    if(timeArray.size()) {
     1258        ds.writeRawData(timeArray.constData(), timeArray.size());
     1259    } else {
     1260        QDateTime currentTime(QDate::currentDate(),
     1261                              QTime::currentTime(), Qt::UTC);
     1262
     1263        // number of seconds between 1601 and epoc(1970)
     1264        // 369 years, 89 leap years
     1265        // ((369 * 365) + 89) * 24 * 3600 = 11644473600
     1266
     1267        time = Q_UINT64_C(currentTime.toTime_t() + 11644473600);
     1268
     1269        // represented as 100 nano seconds
     1270        time = Q_UINT64_C(time * 10000000);
     1271        ds << time;
     1272    }
     1273
     1274    //8 byte client challenge
     1275    QByteArray clientCh = clientChallenge(ctx);
     1276    ds.writeRawData(clientCh.constData(), clientCh.size());
     1277
     1278    //Reserved
     1279    QByteArray reserved2(4, 0);
     1280    ds.writeRawData(reserved2.constData(), reserved2.size());
     1281
     1282    if (ch.targetInfo.len > 0) {
     1283        ds.writeRawData(ch.targetInfoBuff.constData(),
     1284                        ch.targetInfoBuff.size());
     1285    }
     1286
     1287    //Reserved
     1288    QByteArray reserved3(4, 0);
     1289    ds.writeRawData(reserved3.constData(), reserved3.size());
     1290
     1291    QByteArray message((const char*)ch.challenge, sizeof(ch.challenge));
     1292    message.append(temp);
     1293
     1294    QByteArray ntChallengeResp = qEncodeHmacMd5(phase3->v2Hash, message);
     1295    ntChallengeResp.append(temp);
     1296
     1297    return ntChallengeResp;
     1298}
     1299
     1300static QByteArray qEncodeLmv2Response(const QAuthenticatorPrivate *ctx,
     1301                                      const QNtlmPhase2Block& ch,
     1302                                      QNtlmPhase3Block *phase3)
     1303{
     1304    Q_ASSERT(phase3 != 0);
     1305    // return value stored in phase3
     1306    qCreatev2Hash(ctx, phase3);
     1307
     1308    QByteArray message((const char*)ch.challenge, sizeof(ch.challenge));
     1309    QByteArray clientCh = clientChallenge(ctx);
     1310
     1311    message.append(clientCh);
     1312
     1313    QByteArray lmChallengeResp = qEncodeHmacMd5(phase3->v2Hash, message);
     1314    lmChallengeResp.append(clientCh);
     1315
     1316    return lmChallengeResp;
     1317}
    9451318
    9461319static bool qNtlmDecodePhase2(const QByteArray& data, QNtlmPhase2Block& ch)
     
    9771350
    9781351    if (ch.targetInfo.len > 0) {
    979         // UNUSED right now
     1352        if (ch.targetInfo.len + ch.targetInfo.offset > (unsigned)data.size())
     1353            return false;
     1354
     1355        ch.targetInfoBuff = data.mid(ch.targetInfo.offset, ch.targetInfo.len);
    9801356    }
    9811357
     
    9961372
    9971373    bool unicode = ch.flags & NTLMSSP_NEGOTIATE_UNICODE;
    998 
    999     ctx->realm = ch.targetNameStr;
    10001374
    10011375    pb.flags = NTLMSSP_NEGOTIATE_NTLM;
     
    10091383    Q_ASSERT(QNtlmPhase3BlockBase::Size == sizeof(QNtlmPhase3BlockBase));
    10101384   
    1011     offset = qEncodeNtlmString(pb.domain, offset, ctx->realm, unicode);
    1012     pb.domainStr = ctx->realm;
    1013     offset = qEncodeNtlmString(pb.user, offset, ctx->user, unicode);
    1014     pb.userStr = ctx->user;
     1385    if(ctx->userDomain.isEmpty()) {
     1386        offset = qEncodeNtlmString(pb.domain, offset, ch.targetNameStr, unicode);
     1387        pb.domainStr = ch.targetNameStr;
     1388    } else {
     1389        offset = qEncodeNtlmString(pb.domain, offset, ctx->userDomain, unicode);
     1390        pb.domainStr = ctx->userDomain;
     1391    }
     1392
     1393    offset = qEncodeNtlmString(pb.user, offset, ctx->extractedUser, unicode);
     1394    pb.userStr = ctx->extractedUser;
    10151395
    10161396    offset = qEncodeNtlmString(pb.workstation, offset, ctx->workstation, unicode);
     
    10181398
    10191399    // Get LM response
     1400#ifdef NTLMV1_CLIENT
    10201401    pb.lmResponseBuf = qEncodeLmResponse(ctx, ch);
     1402#else
     1403    if (ch.targetInfo.len > 0) {
     1404        pb.lmResponseBuf = QByteArray();
     1405    } else {
     1406        pb.lmResponseBuf = qEncodeLmv2Response(ctx, ch, &pb);
     1407    }
     1408#endif
    10211409    offset = qEncodeNtlmBuffer(pb.lmResponse, offset, pb.lmResponseBuf);
    10221410
    10231411    // Get NTLM response
     1412#ifdef NTLMV1_CLIENT
    10241413    pb.ntlmResponseBuf = qEncodeNtlmResponse(ctx, ch);
     1414#else
     1415    pb.ntlmResponseBuf = qEncodeNtlmv2Response(ctx, ch, &pb);
     1416#endif
    10251417    offset = qEncodeNtlmBuffer(pb.ntlmResponse, offset, pb.ntlmResponseBuf);
    10261418
  • trunk/src/network/kernel/qauthenticator.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4444
    4545#include <QtCore/qstring.h>
     46#include <QtCore/qvariant.h>
    4647
    4748QT_BEGIN_HEADER
     
    7475    QString realm() const;
    7576
     77    QVariant option(const QString &opt) const;
     78    QVariantHash options() const;
     79    void setOption(const QString &opt, const QVariant &value);
     80
    7681    bool isNull() const;
    7782    void detach();
  • trunk/src/network/kernel/qauthenticator_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5858#include <qstring.h>
    5959#include <qauthenticator.h>
     60#include <qvariant.h>
    6061
    6162QT_BEGIN_NAMESPACE
     
    6364class QHttpResponseHeader;
    6465
    65 class QAuthenticatorPrivate
     66class Q_AUTOTEST_EXPORT QAuthenticatorPrivate
    6667{
    6768public:
     
    7172    QAtomicInt ref;
    7273    QString user;
     74    QString extractedUser;
    7375    QString password;
    74     QHash<QByteArray, QByteArray> options;
     76    QVariantHash options;
    7577    Method method;
    7678    QString realm;
     
    9193    // ntlm specific
    9294    QString workstation;
     95    QString userDomain;
    9396
    9497    QByteArray calculateResponse(const QByteArray &method, const QByteArray &path);
     
    103106    void parseHttpResponse(const QHttpResponseHeader &, bool isProxy);
    104107#endif
     108    void parseHttpResponse(const QList<QPair<QByteArray, QByteArray> >&, bool isProxy);
    105109
    106110};
  • trunk/src/network/kernel/qhostaddress.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    429429    and QUdpSocket to connect to a host or to set up a server.
    430430
    431     A host address is set with setAddress(), checked for its type
    432     using isIPv4Address() or isIPv6Address(), and retrieved with
    433     toIPv4Address(), toIPv6Address(), or toString().
     431    A host address is set with setAddress(), and retrieved with
     432    toIPv4Address(), toIPv6Address(), or toString(). You can check the
     433    type with protocol().
    434434
    435435    \note Please note that QHostAddress does not do DNS lookups.
     
    680680    2130706433 (i.e. 0x7f000001).
    681681
    682     This value is only valid if isIp4Addr() returns true.
     682    This value is only valid if the Protocol() is
     683    \l{QAbstractSocket::}{IPv4Protocol}.
    683684
    684685    \sa toString()
     
    705706    \snippet doc/src/snippets/code/src_network_kernel_qhostaddress.cpp 0
    706707
    707     This value is only valid if isIPv6Address() returns true.
     708    This value is only valid if the protocol() is
     709    \l{QAbstractSocket::}{IPv6Protocol}.
    708710
    709711    \sa toString()
     
    10981100    to the stream.
    10991101
    1100     \sa {Format of the QDataStream operators}
     1102    \sa {Serializing Qt Data Types}
    11011103*/
    11021104QDataStream &operator<<(QDataStream &out, const QHostAddress &address)
     
    11281130    reference to the stream.
    11291131
    1130     \sa {Format of the QDataStream operators}
     1132    \sa {Serializing Qt Data Types}
    11311133*/
    11321134QDataStream &operator>>(QDataStream &in, QHostAddress &address)
  • trunk/src/network/kernel/qhostaddress.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qhostaddress_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qhostinfo.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    169169        QHostInfo hostInfo(id);
    170170        hostInfo.setError(QHostInfo::HostNotFound);
    171         hostInfo.setErrorString(QObject::tr("No host name given"));
     171        hostInfo.setErrorString(QCoreApplication::translate("QHostInfo", "No host name given"));
    172172        QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
    173173        QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
     
    244244#endif
    245245
    246     return QHostInfoAgent::fromName(name);
     246    QHostInfo hostInfo = QHostInfoAgent::fromName(name);
     247    QHostInfoLookupManager *manager = theHostInfoLookupManager();
     248    manager->cache.put(name, hostInfo);
     249    return hostInfo;
    247250}
    248251
     
    468471    resultEmitter.emitResultsReady(hostInfo);
    469472
     473    // now also iterate through the postponed ones
     474    {
     475        QMutexLocker locker(&manager->mutex);
     476        QMutableListIterator<QHostInfoRunnable*> iterator(manager->postponedLookups);
     477        while (iterator.hasNext()) {
     478            QHostInfoRunnable* postponed = iterator.next();
     479            if (toBeLookedUp == postponed->toBeLookedUp) {
     480                // we can now emit
     481                iterator.remove();
     482                hostInfo.setLookupId(postponed->id);
     483                postponed->resultEmitter.emitResultsReady(hostInfo);
     484            }
     485        }
     486    }
     487
    470488    manager->lookupFinished(this);
    471489
     
    485503
    486504    // don't qDeleteAll currentLookups, the QThreadPool has ownership
    487     qDeleteAll(postponedLookups);
    488     qDeleteAll(scheduledLookups);
    489     qDeleteAll(finishedLookups);
     505    clear();
     506}
     507
     508void QHostInfoLookupManager::clear()
     509{
     510    {
     511        QMutexLocker locker(&mutex);
     512        qDeleteAll(postponedLookups);
     513        qDeleteAll(scheduledLookups);
     514        qDeleteAll(finishedLookups);
     515        postponedLookups.clear();
     516        scheduledLookups.clear();
     517        finishedLookups.clear();
     518    }
     519
     520    threadPool.waitForDone();
     521    cache.clear();
    490522}
    491523
     
    579611
    580612    QMutexLocker locker(&this->mutex);
     613
     614    // is postponed? delete and return
     615    for (int i = 0; i < postponedLookups.length(); i++) {
     616        if (postponedLookups.at(i)->id == id) {
     617            delete postponedLookups.takeAt(i);
     618            return;
     619        }
     620    }
     621
     622    // is scheduled? delete and return
     623    for (int i = 0; i < scheduledLookups.length(); i++) {
     624        if (scheduledLookups.at(i)->id == id) {
     625            delete scheduledLookups.takeAt(i);
     626            return;
     627        }
     628    }
     629
    581630    if (!abortedLookups.contains(id))
    582631        abortedLookups.append(id);
     
    605654}
    606655
    607 // This function returns immediatly when we had a result in the cache, else it will later emit a signal
     656// This function returns immediately when we had a result in the cache, else it will later emit a signal
    608657QHostInfo qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id)
    609658{
     
    631680    QHostInfoLookupManager* manager = theHostInfoLookupManager();
    632681    if (manager) {
    633         manager->cache.clear();
     682        manager->clear();
    634683    }
    635684}
  • trunk/src/network/kernel/qhostinfo.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qhostinfo_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    8585
    8686Q_SIGNALS:
    87     void resultsReady(const QHostInfo info);
     87    void resultsReady(const QHostInfo &info);
    8888};
    8989
     
    117117// Do NOT use them outside of QAbstractSocket.
    118118QHostInfo Q_NETWORK_EXPORT qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id);
    119 void Q_NETWORK_EXPORT qt_qhostinfo_clear_cache();
     119void Q_AUTOTEST_EXPORT qt_qhostinfo_clear_cache();
    120120void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e);
    121121
     
    162162    ~QHostInfoLookupManager();
    163163
     164    void clear();
    164165    void work();
    165166
     
    173174
    174175    QHostInfoCache cache;
     176
     177    friend class QHostInfoRunnable;
    175178protected:
    176179    QList<QHostInfoRunnable*> currentLookups; // in progress
  • trunk/src/network/kernel/qhostinfo_unix.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    195195    if (aceHostname.isEmpty()) {
    196196        results.setError(QHostInfo::HostNotFound);
    197         results.setErrorString(hostName.isEmpty() ? QObject::tr("No host name given") : QObject::tr("Invalid hostname"));
     197        results.setErrorString(hostName.isEmpty() ?
     198                               QCoreApplication::translate("QHostInfoAgent", "No host name given") :
     199                               QCoreApplication::translate("QHostInfoAgent", "Invalid hostname"));
    198200        return results;
    199201    }
     
    209211    hints.ai_flags = Q_ADDRCONFIG;
    210212#endif
     213#ifdef Q_OS_SYMBIAN
     214#   ifdef QHOSTINFO_DEBUG
     215        qDebug() << "Setting flags: 'hints.ai_flags &= AI_V4MAPPED | AI_ALL'";
     216#   endif
     217#endif
    211218
    212219    int result = getaddrinfo(aceHostname.constData(), 0, &hints, &res);
     
    215222        // if the lookup failed with AI_ADDRCONFIG set, try again without it
    216223        hints.ai_flags = 0;
     224#ifdef Q_OS_SYMBIAN
     225#   ifdef QHOSTINFO_DEBUG
     226        qDebug() << "Setting flags: 'hints.ai_flags &= AI_V4MAPPED | AI_ALL'";
     227#   endif
     228        hints.ai_flags &= AI_V4MAPPED | AI_ALL;
     229#endif
    217230        result = getaddrinfo(aceHostname.constData(), 0, &hints, &res);
    218231    }
     
    223236        QList<QHostAddress> addresses;
    224237        while (node) {
     238#ifdef QHOSTINFO_DEBUG
     239                qDebug() << "getaddrinfo node: flags:" << node->ai_flags << "family:" << node->ai_family << "ai_socktype:" << node->ai_socktype << "ai_protocol:" << node->ai_protocol << "ai_addrlen:" << node->ai_addrlen;
     240#endif
    225241            if (node->ai_family == AF_INET) {
    226242                QHostAddress addr;
     
    232248            else if (node->ai_family == AF_INET6) {
    233249                QHostAddress addr;
    234                 addr.setAddress(((sockaddr_in6 *) node->ai_addr)->sin6_addr.s6_addr);
     250                sockaddr_in6 *sa6 = (sockaddr_in6 *) node->ai_addr;
     251                addr.setAddress(sa6->sin6_addr.s6_addr);
     252                if (sa6->sin6_scope_id)
     253                    addr.setScopeId(QString::number(sa6->sin6_scope_id));
    235254                if (!addresses.contains(addr))
    236255                    addresses.append(addr);
  • trunk/src/network/kernel/qhostinfo_win.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5050#include "private/qnativesocketengine_p.h"
    5151#include <ws2tcpip.h>
    52 #include <qlibrary.h>
     52#include <private/qsystemlibrary_p.h>
    5353#include <qmutex.h>
    5454#include <qurl.h>
     
    9191    // back to gethostbyname(), which has no IPv6 support.
    9292#if !defined(Q_OS_WINCE)
    93     local_getaddrinfo = (getaddrinfoProto) QLibrary::resolve(QLatin1String("ws2_32.dll"), "getaddrinfo");
    94     local_freeaddrinfo = (freeaddrinfoProto) QLibrary::resolve(QLatin1String("ws2_32.dll"), "freeaddrinfo");
    95     local_getnameinfo = (getnameinfoProto) QLibrary::resolve(QLatin1String("ws2_32.dll"), "getnameinfo");
     93    local_getaddrinfo = (getaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getaddrinfo");
     94    local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "freeaddrinfo");
     95    local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2_32"), "getnameinfo");
    9696#else
    97     local_getaddrinfo = (getaddrinfoProto) QLibrary::resolve(QLatin1String("ws2.dll"), "getaddrinfo");
    98     local_freeaddrinfo = (freeaddrinfoProto) QLibrary::resolve(QLatin1String("ws2.dll"), "freeaddrinfo");
    99     local_getnameinfo = (getnameinfoProto) QLibrary::resolve(QLatin1String("ws2.dll"), "getnameinfo");
     97    local_getaddrinfo = (getaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "getaddrinfo");
     98    local_freeaddrinfo = (freeaddrinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "freeaddrinfo");
     99    local_getnameinfo = (getnameinfoProto) QSystemLibrary::resolve(QLatin1String("ws2"), "getnameinfo");
    100100#endif
    101101}
  • trunk/src/network/kernel/qnetworkinterface.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qnetworkinterface.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qnetworkinterface_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qnetworkinterface_symbian.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qnetworkinterface_unix.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qnetworkinterface_win.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4949#include <qhash.h>
    5050#include <qurl.h>
     51#include <private/qsystemlibrary_p.h>
    5152
    5253QT_BEGIN_NAMESPACE
     
    6768        done = true;
    6869
    69         HINSTANCE iphlpapiHnd = LoadLibrary(L"iphlpapi");
     70        HINSTANCE iphlpapiHnd = QSystemLibrary::load(L"iphlpapi");
    7071        if (iphlpapiHnd == NULL)
    7172            return;
  • trunk/src/network/kernel/qnetworkinterface_win_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qnetworkproxy.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    427427    : d(0)
    428428{
    429     globalNetworkProxy()->init();
     429    if (QGlobalNetworkProxy *globalProxy = globalNetworkProxy())
     430        globalProxy->init();
    430431}
    431432
     
    442443    : d(new QNetworkProxyPrivate(type, hostName, port, user, password))
    443444{
    444     globalNetworkProxy()->init();
     445    if (QGlobalNetworkProxy *globalProxy = globalNetworkProxy())
     446        globalProxy->init();
    445447}
    446448
     
    11391141    such object, the factory will be queried for sockets created by
    11401142    that framework only.
     1143
     1144    \section1 System Proxies
     1145
     1146    You can configure a factory to use the system proxy's settings.
     1147    Call the setUseSystemConfiguration() function with true to enable
     1148    this behavior, or false to disable it.
     1149
     1150    Similarly, you can use a factory to make queries directly to the
     1151    system proxy by calling its systemProxyForQuery() function.
     1152
     1153    \warning Depending on the configuration of the user's system, the
     1154    use of system proxy features on certain platforms may be subject
     1155    to limitations. The systemProxyForQuery() documentation contains a
     1156    list of these limitations for those platforms that are affected.
    11411157*/
    11421158
     
    11601176
    11611177/*!
     1178    \since 4.6
     1179
    11621180    Enables the use of the platform-specific proxy settings, and only those.
    11631181    See systemProxyForQuery() for more information.
     
    11651183    Internally, this method (when called with \a enable set to true)
    11661184    sets an application-wide proxy factory. For this reason, this method
    1167     is mutually exclusive with setApplicationProxyFactory: calling
    1168     setApplicationProxyFactory overrides the use of the system-wide proxy,
    1169     and calling setUseSystemConfiguration overrides any
     1185    is mutually exclusive with setApplicationProxyFactory(): calling
     1186    setApplicationProxyFactory() overrides the use of the system-wide proxy,
     1187    and calling setUseSystemConfiguration() overrides any
    11701188    application proxy or proxy factory that was previously set.
    11711189
    1172     \since 4.6
     1190    \note See the systemProxyForQuery() documentation for a list of
     1191    limitations related to the use of system proxies.
    11731192*/
    11741193void QNetworkProxyFactory::setUseSystemConfiguration(bool enable)
     
    12651284    listed here.
    12661285
    1267     On MacOS X, this function will ignore the Proxy Auto Configuration
     1286    \list
     1287    \o On MacOS X, this function will ignore the Proxy Auto Configuration
    12681288    settings, since it cannot execute the associated ECMAScript code.
     1289
     1290    \o On Windows platforms, this function may take several seconds to
     1291    execute depending on the configuration of the user's system.
     1292    \endlist
    12691293*/
    12701294
  • trunk/src/network/kernel/qnetworkproxy.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qnetworkproxy_generic.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qnetworkproxy_mac.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    158158    }
    159159
    160     if (isHostExcluded(dict, query.peerHostName()))
     160    if (isHostExcluded(dict, query.peerHostName())) {
     161        CFRelease(dict);
    161162        return result;          // no proxy for this host
     163    }
    162164
    163165    // is there a PAC enabled? If so, use it first.
     
    223225    }
    224226
     227    CFRelease(dict);
    225228    return result;
    226229}
  • trunk/src/network/kernel/qnetworkproxy_win.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5252#include <qt_windows.h>
    5353#include <wininet.h>
     54#include <private/qsystemlibrary_p.h>
    5455
    5556/*
     
    100101#define WINHTTP_NO_PROXY_NAME     NULL
    101102#define WINHTTP_NO_PROXY_BYPASS   NULL
     103
     104#define WINHTTP_ERROR_BASE                      12000
     105#define ERROR_WINHTTP_LOGIN_FAILURE             (WINHTTP_ERROR_BASE + 15)
     106#define ERROR_WINHTTP_AUTODETECTION_FAILED      (WINHTTP_ERROR_BASE + 180)
    102107
    103108QT_BEGIN_NAMESPACE
     
    274279#else
    275280    // load the winhttp.dll library
    276     HINSTANCE winhttpHnd = LoadLibrary(L"winhttp");
    277     if (!winhttpHnd)
     281    QSystemLibrary lib(L"winhttp");
     282    if (!lib.load())
    278283        return;                 // failed to load
    279284
    280     ptrWinHttpOpen = (PtrWinHttpOpen)GetProcAddress(winhttpHnd, "WinHttpOpen");
    281     ptrWinHttpCloseHandle = (PtrWinHttpCloseHandle)GetProcAddress(winhttpHnd, "WinHttpCloseHandle");
    282     ptrWinHttpGetProxyForUrl = (PtrWinHttpGetProxyForUrl)GetProcAddress(winhttpHnd, "WinHttpGetProxyForUrl");
    283     ptrWinHttpGetDefaultProxyConfiguration = (PtrWinHttpGetDefaultProxyConfiguration)GetProcAddress(winhttpHnd, "WinHttpGetDefaultProxyConfiguration");
    284     ptrWinHttpGetIEProxyConfigForCurrentUser = (PtrWinHttpGetIEProxyConfigForCurrentUser)GetProcAddress(winhttpHnd, "WinHttpGetIEProxyConfigForCurrentUser");
     285    ptrWinHttpOpen = (PtrWinHttpOpen)lib.resolve("WinHttpOpen");
     286    ptrWinHttpCloseHandle = (PtrWinHttpCloseHandle)lib.resolve("WinHttpCloseHandle");
     287    ptrWinHttpGetProxyForUrl = (PtrWinHttpGetProxyForUrl)lib.resolve("WinHttpGetProxyForUrl");
     288    ptrWinHttpGetDefaultProxyConfiguration = (PtrWinHttpGetDefaultProxyConfiguration)lib.resolve("WinHttpGetDefaultProxyConfiguration");
     289    ptrWinHttpGetIEProxyConfigForCurrentUser = (PtrWinHttpGetIEProxyConfigForCurrentUser)lib.resolve("WinHttpGetIEProxyConfigForCurrentUser");
    285290
    286291    // Try to obtain the Internet Explorer configuration.
     
    321326        isAutoConfig = true;
    322327        memset(&autoProxyOptions, 0, sizeof autoProxyOptions);
    323         autoProxyOptions.fAutoLogonIfChallenged = true;
     328        autoProxyOptions.fAutoLogonIfChallenged = false;
    324329        if (ieProxyConfig.fAutoDetect) {
    325330            autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
     
    378383            url.setScheme(QLatin1String("https"));
    379384        }
    380         if (ptrWinHttpGetProxyForUrl(sp->hHttpSession,
    381                                      (LPCWSTR)url.toString().utf16(),
    382                                      &sp->autoProxyOptions,
    383                                      &proxyInfo)) {
     385
     386        bool getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession,
     387                                                (LPCWSTR)url.toString().utf16(),
     388                                                &sp->autoProxyOptions,
     389                                                &proxyInfo);
     390        DWORD getProxyError = GetLastError();
     391
     392        if (!getProxySucceeded
     393            && (ERROR_WINHTTP_LOGIN_FAILURE == getProxyError)) {
     394            // We first tried without AutoLogon, because this might prevent caching the result.
     395            // But now we've to enable it (http://msdn.microsoft.com/en-us/library/aa383153%28v=VS.85%29.aspx)
     396            sp->autoProxyOptions.fAutoLogonIfChallenged = TRUE;
     397            getProxySucceeded = ptrWinHttpGetProxyForUrl(sp->hHttpSession,
     398                                               (LPCWSTR)url.toString().utf16(),
     399                                                &sp->autoProxyOptions,
     400                                                &proxyInfo);
     401            getProxyError = GetLastError();
     402        }
     403
     404        if (getProxySucceeded) {
    384405            // yes, we got a config for this URL
    385406            QString proxyBypass = QString::fromWCharArray(proxyInfo.lpszProxyBypass);
     
    396417
    397418        // GetProxyForUrl failed
     419
     420        if (ERROR_WINHTTP_AUTODETECTION_FAILED == getProxyError) {
     421            //No config file could be retrieved on the network.
     422            //Don't search for it next time again.
     423            sp->isAutoConfig = false;
     424        }
     425
    398426        return sp->defaultResult;
    399427    }
  • trunk/src/network/kernel/qurlinfo.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/kernel/qurlinfo.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/network.pro

    r561 r846  
    2121include(../qbase.pri)
    2222include(access/access.pri)
     23include(bearer/bearer.pri)
    2324include(kernel/kernel.pri)
    2425include(socket/socket.pri)
     
    3031symbian {
    3132   TARGET.UID3=0x2001B2DE
    32    LIBS += -lesock -linsock
     33   LIBS += -lesock -linsock -lcertstore -lefsrv -lctframework
    3334}
  • trunk/src/network/socket/qabstractsocket.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    366366
    367367#include <qabstracteventdispatcher.h>
    368 #include <qdatetime.h>
    369368#include <qhostaddress.h>
    370369#include <qhostinfo.h>
     
    372371#include <qpointer.h>
    373372#include <qtimer.h>
     373#include <qelapsedtimer.h>
    374374
    375375#ifndef QT_NO_OPENSSL
     
    12131213}
    12141214
     1215
     1216void QAbstractSocketPrivate::pauseSocketNotifiers(QAbstractSocket *socket)
     1217{
     1218    QAbstractSocketEngine *socketEngine = socket->d_func()->socketEngine;
     1219    if (!socketEngine)
     1220        return;
     1221    socket->d_func()->prePauseReadSocketNotifierState = socketEngine->isReadNotificationEnabled();
     1222    socket->d_func()->prePauseWriteSocketNotifierState = socketEngine->isWriteNotificationEnabled();
     1223    socket->d_func()->prePauseExceptionSocketNotifierState = socketEngine->isExceptionNotificationEnabled();
     1224    socketEngine->setReadNotificationEnabled(false);
     1225    socketEngine->setWriteNotificationEnabled(false);
     1226    socketEngine->setExceptionNotificationEnabled(false);
     1227}
     1228
     1229void QAbstractSocketPrivate::resumeSocketNotifiers(QAbstractSocket *socket)
     1230{
     1231    QAbstractSocketEngine *socketEngine = socket->d_func()->socketEngine;
     1232    if (!socketEngine)
     1233        return;
     1234    socketEngine->setReadNotificationEnabled(socket->d_func()->prePauseReadSocketNotifierState);
     1235    socketEngine->setWriteNotificationEnabled(socket->d_func()->prePauseWriteSocketNotifierState);
     1236    socketEngine->setExceptionNotificationEnabled(socket->d_func()->prePauseExceptionSocketNotifierState);
     1237}
     1238
     1239QAbstractSocketEngine* QAbstractSocketPrivate::getSocketEngine(QAbstractSocket *socket)
     1240{
     1241    return socket->d_func()->socketEngine;
     1242}
     1243
     1244
    12151245/*! \internal
    12161246
     
    13811411    } else {
    13821412        if (d->threadData->eventDispatcher) {
    1383             // this internal API for QHostInfo either immediatly gives us the desired
     1413            // this internal API for QHostInfo either immediately gives us the desired
    13841414            // QHostInfo from cache or later calls the _q_startConnecting slot.
    13851415            bool immediateResultValid = false;
     
    17391769    bool wasPendingClose = d->pendingClose;
    17401770    d->pendingClose = false;
    1741     QTime stopWatch;
     1771    QElapsedTimer stopWatch;
    17421772    stopWatch.start();
    17431773
     
    18201850    }
    18211851
    1822     QTime stopWatch;
     1852    QElapsedTimer stopWatch;
    18231853    stopWatch.start();
    18241854
     
    18791909        return false;
    18801910
    1881     QTime stopWatch;
     1911    QElapsedTimer stopWatch;
    18821912    stopWatch.start();
    18831913
     
    19611991    }
    19621992
    1963     QTime stopWatch;
     1993    QElapsedTimer stopWatch;
    19641994    stopWatch.start();
    19651995
  • trunk/src/network/socket/qabstractsocket.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qabstractsocket_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    159159
    160160    QAbstractSocket::SocketError socketError;
     161
     162    bool prePauseReadSocketNotifierState;
     163    bool prePauseWriteSocketNotifierState;
     164    bool prePauseExceptionSocketNotifierState;
     165    static void pauseSocketNotifiers(QAbstractSocket*);
     166    static void resumeSocketNotifiers(QAbstractSocket*);
     167    static QAbstractSocketEngine* getSocketEngine(QAbstractSocket*);
    161168};
    162169
  • trunk/src/network/socket/qabstractsocketengine.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qabstractsocketengine_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qhttpsocketengine.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4343#include "qtcpsocket.h"
    4444#include "qhostaddress.h"
    45 #include "qdatetime.h"
    4645#include "qurl.h"
    4746#include "qhttp.h"
     47#include "qelapsedtimer.h"
    4848
    4949#if !defined(QT_NO_NETWORKPROXY) && !defined(QT_NO_HTTP)
     
    320320        return false;
    321321
    322     QTime stopWatch;
     322    QElapsedTimer stopWatch;
    323323    stopWatch.start();
    324324
     
    367367    }
    368368
    369     QTime stopWatch;
     369    QElapsedTimer stopWatch;
    370370    stopWatch.start();
    371371
  • trunk/src/network/socket/qhttpsocketengine_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qlocalserver.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qlocalserver.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qlocalserver_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    100100        HANDLE handle;
    101101        OVERLAPPED overlapped;
     102        bool connected;
    102103    };
    103104
  • trunk/src/network/socket/qlocalserver_tcp.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qlocalserver_unix.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    120120    //
    121121    // This change can be removed once more generic fix to select thread
    122     // syncronization problem is implemented.
     122    // synchronization problem is implemented.
    123123    int flags = fcntl(listenSocket, F_GETFL, 0);
    124124    if (-1 == flags
  • trunk/src/network/socket/qlocalserver_win.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6666                 (const wchar_t *)fullServerName.utf16(), // pipe name
    6767                 PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,       // read/write access
    68                  PIPE_TYPE_MESSAGE |       // message type pipe
    69                  PIPE_READMODE_MESSAGE |   // message-read mode
     68                 PIPE_TYPE_BYTE |          // byte type pipe
     69                 PIPE_READMODE_BYTE |      // byte-read mode
    7070                 PIPE_WAIT,                // blocking mode
    7171                 PIPE_UNLIMITED_INSTANCES, // max. instances
     
    8686        switch (GetLastError()) {
    8787        case ERROR_IO_PENDING:
     88            listener.connected = false;
    8889            break;
    8990        case ERROR_PIPE_CONNECTED:
     91            listener.connected = true;
    9092            SetEvent(eventHandle);
    9193            break;
     
    156158    for (int i = 0; i < listeners.size(); ) {
    157159        HANDLE handle = listeners[i].handle;
    158         if (GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE)) {
     160        if (listeners[i].connected
     161            || GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE))
     162        {
    159163            listeners.removeAt(i);
    160164
  • trunk/src/network/socket/qlocalsocket.cpp

    r755 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qlocalsocket.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qlocalsocket_p.h

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    136136    void _q_pipeClosed();
    137137    void _q_emitReadyRead();
    138     DWORD bytesAvailable();
     138    DWORD checkPipeState();
    139139    void startAsyncRead();
    140140    bool completeAsyncRead();
  • trunk/src/network/socket/qlocalsocket_tcp.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qlocalsocket_unix.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5353#include <errno.h>
    5454
    55 #include <qdatetime.h>
    5655#include <qdir.h>
    5756#include <qdebug.h>
     57#include <qelapsedtimer.h>
    5858
    5959#ifdef Q_OS_VXWORKS
     
    535535    int result = -1;
    536536    // on Linux timeout will be updated by select, but _not_ on other systems.
    537     QTime timer;
     537    QElapsedTimer timer;
    538538    timer.start();
    539539    while (state() == ConnectingState
  • trunk/src/network/socket/qlocalsocket_win.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    193193    Q_D(QLocalSocket);
    194194
     195    if (d->pipeClosed && d->actualReadBufferSize == 0)
     196        return -1;  // signal EOF
     197
    195198    qint64 readSoFar;
    196199    // If startAsyncRead() read data, copy it to its destination.
     
    214217
    215218    if (d->pipeClosed) {
    216         if (readSoFar == 0) {
     219        if (d->actualReadBufferSize == 0)
    217220            QTimer::singleShot(0, this, SLOT(_q_pipeClosed()));
    218             return -1;  // signal EOF
    219         }
    220221    } else {
    221222        if (!d->readSequenceStarted)
     
    251252{
    252253    do {
    253         DWORD bytesToRead = bytesAvailable();
     254        DWORD bytesToRead = checkPipeState();
     255        if (pipeClosed)
     256            return;
     257
    254258        if (bytesToRead == 0) {
    255259            // There are no bytes in the pipe but we need to
     
    277281                    // This is not an error. We're getting notified, when data arrives.
    278282                    return;
     283                case ERROR_MORE_DATA:
     284                    // This is not an error. The synchronous read succeeded.
     285                    // We're connected to a message mode pipe and the message
     286                    // didn't fit into the pipe's system buffer.
     287                    completeAsyncRead();
     288                    break;
    279289                case ERROR_PIPE_NOT_CONNECTED:
    280290                    {
     
    297307    \internal
    298308    Sets the correct size of the read buffer after a read operation.
    299     Returns false, if an error occured or the connection dropped.
     309    Returns false, if an error occurred or the connection dropped.
    300310 */
    301311bool QLocalSocketPrivate::completeAsyncRead()
     
    306316    DWORD bytesRead;
    307317    if (!GetOverlappedResult(handle, &overlapped, &bytesRead, TRUE)) {
    308         if (GetLastError() != ERROR_PIPE_NOT_CONNECTED)
     318        switch (GetLastError()) {
     319        case ERROR_MORE_DATA:
     320            // This is not an error. We're connected to a message mode
     321            // pipe and the message didn't fit into the pipe's system
     322            // buffer. We will read the remaining data in the next call.
     323            break;
     324        case ERROR_PIPE_NOT_CONNECTED:
     325            return false;
     326        default:
    309327            setErrorString(QLatin1String("QLocalSocketPrivate::completeAsyncRead"));
    310         return false;
     328            return false;
     329        }
    311330    }
    312331
     
    334353
    335354/*!
    336     The number of bytes available from the pipe
    337   */
    338 DWORD QLocalSocketPrivate::bytesAvailable()
     355    \internal
     356    Returns the number of available bytes in the pipe.
     357    Sets QLocalSocketPrivate::pipeClosed to true if the connection is broken.
     358 */
     359DWORD QLocalSocketPrivate::checkPipeState()
    339360{
    340361    Q_Q(QLocalSocket);
     
    346367            pipeClosed = true;
    347368            emit q->readChannelFinished();
    348             QTimer::singleShot(0, q, SLOT(_q_pipeClosed()));
     369            if (actualReadBufferSize == 0)
     370                QTimer::singleShot(0, q, SLOT(_q_pipeClosed()));
    349371        }
    350372    }
     
    479501        pipeClosed = true;
    480502        emit q->readChannelFinished();
     503        if (actualReadBufferSize == 0)
     504            QTimer::singleShot(0, q, SLOT(_q_pipeClosed()));
    481505        return;
    482506    }
     
    530554    QIncrementalSleepTimer timer(msecs);
    531555    forever {
    532         d->bytesAvailable();    // to check if PeekNamedPipe fails
     556        d->checkPipeState();
    533557        if (d->pipeClosed)
    534558            close();
     
    562586        return false;
    563587
     588    // We already know that the pipe is gone, but did not enter the event loop yet.
     589    if (d->pipeClosed) {
     590        close();
     591        return false;
     592    }
     593
    564594    Q_ASSERT(d->readSequenceStarted);
    565595    DWORD result = WaitForSingleObject(d->overlapped.hEvent, msecs == -1 ? INFINITE : msecs);
     
    567597        case WAIT_OBJECT_0:
    568598            d->_q_notified();
     599            // We just noticed that the pipe is gone.
     600            if (d->pipeClosed) {
     601                close();
     602                return false;
     603            }
    569604            return true;
    570605        case WAIT_TIMEOUT:
  • trunk/src/network/socket/qnativesocketengine.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    186186        // one exception: SocketError(11) bypasses this as it's purely
    187187        // a temporary internal error condition.
     188        // Another exception is the way the waitFor*() functions set
     189        // an error when a timeout occurs. After the call to setError()
     190        // they reset the hasSetSocketError to false
    188191        return;
    189192    }
     
    860863        d->setError(QAbstractSocket::SocketTimeoutError,
    861864            QNativeSocketEnginePrivate::TimeOutErrorString);
     865        d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
    862866        return false;
    863867    } else if (state() == QAbstractSocket::ConnectingState) {
     
    928932        d->setError(QAbstractSocket::SocketTimeoutError,
    929933                    QNativeSocketEnginePrivate::TimeOutErrorString);
     934        d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
    930935        return false;
    931936    } else if (state() == QAbstractSocket::ConnectingState) {
     
    979984        d->setError(QAbstractSocket::SocketTimeoutError,
    980985                    QNativeSocketEnginePrivate::TimeOutErrorString);
     986        d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions
    981987        return false;
    982988    } else if (state() == QAbstractSocket::ConnectingState) {
  • trunk/src/network/socket/qnativesocketengine_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qnativesocketengine_unix.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4545#include "qiodevice.h"
    4646#include "qhostaddress.h"
     47#include "qelapsedtimer.h"
    4748#include "qvarlengtharray.h"
    48 #include "qdatetime.h"
    4949#include <time.h>
    5050#include <errno.h>
     
    203203    }
    204204
    205     // Ensure that the socket is closed on exec*().
    206     ::fcntl(socket, F_SETFD, FD_CLOEXEC);
    207 
    208205    socketDescriptor = socket;
    209206    return true;
     
    353350        sockAddrIPv6.sin6_family = AF_INET6;
    354351        sockAddrIPv6.sin6_port = htons(port);
     352
     353        QString scopeid = addr.scopeId();
     354        bool ok;
     355        sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
    355356#ifndef QT_NO_IPV6IFNAME
    356         sockAddrIPv6.sin6_scope_id = ::if_nametoindex(addr.scopeId().toLatin1().data());
    357 #else
    358         sockAddrIPv6.sin6_scope_id = addr.scopeId().toInt();
     357        if (!ok)
     358            sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
    359359#endif
    360360        Q_IPV6ADDR ip6 = addr.toIPv6Address();
     
    426426        case EFAULT:
    427427        case ENOTSOCK:
     428#ifdef Q_OS_SYMBIAN
     429        case EPIPE:
     430#endif
    428431            socketState = QAbstractSocket::UnconnectedState;
    429432        default:
     
    559562#else
    560563    int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0);
    561 #endif
    562     //check if we have vaild descriptor at all
    563     if(acceptedDescriptor > 0) {
    564         // Ensure that the socket is closed on exec*()
    565         ::fcntl(acceptedDescriptor, F_SETFD, FD_CLOEXEC);
    566     }
    567 #ifdef Q_OS_SYMBIAN
    568     else {
    569         qWarning("QNativeSocketEnginePrivate::nativeAccept() - acceptedDescriptor <= 0");
    570     }
    571564#endif
    572565
     
    10091002    ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv);
    10101003#else
    1011     QTime timer;
     1004    QElapsedTimer timer;
    10121005    timer.start();
    10131006
  • trunk/src/network/socket/qnativesocketengine_win.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    208208        memset(sockAddrIPv6, 0, sizeof(qt_sockaddr_in6));
    209209        sockAddrIPv6->sin6_family = AF_INET6;
     210        sockAddrIPv6->sin6_scope_id = address.scopeId().toInt();
    210211        WSAHtons(socketDescriptor, port, &(sockAddrIPv6->sin6_port));
    211212        Q_IPV6ADDR tmp = address.toIPv6Address();
     
    733734    int acceptedDescriptor = WSAAccept(socketDescriptor, 0,0,0,0);
    734735        if (acceptedDescriptor != -1 && QAbstractEventDispatcher::instance()) {
    735                 // Becuase of WSAAsyncSelect() WSAAccept returns a non blocking socket
     736                // Because of WSAAsyncSelect() WSAAccept returns a non blocking socket
    736737                // with the same attributes as the listening socket including the current
    737738                // WSAAsyncSelect(). To be able to change the socket to blocking mode the
  • trunk/src/network/socket/qnet_unix_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qsocks5socketengine.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5050#include "qhash.h"
    5151#include "qqueue.h"
    52 #include "qdatetime.h"
     52#include "qelapsedtimer.h"
    5353#include "qmutex.h"
    5454#include "qthread.h"
     
    309309    QHostAddress peerAddress;
    310310    quint16 peerPort;
    311     QDateTime timeStamp;
     311    QElapsedTimer timeStamp;
    312312};
    313313
     
    370370        // qDebug() << "delete it";
    371371    }
    372     bindData->timeStamp = QDateTime::currentDateTime();
     372    bindData->timeStamp.start();
    373373    store.insert(socketDescriptor, bindData);
    374374    // start sweep timer if not started
     
    413413        while (it.hasNext()) {
    414414            it.next();
    415             if (it.value()->timeStamp.secsTo(QDateTime::currentDateTime()) > 350) {
     415            if (it.value()->timeStamp.hasExpired(350000)) {
    416416                QSOCKS5_DEBUG << "QSocks5BindStore removing JJJJ";
    417417                it.remove();
     
    13561356
    13571357    int msecs = SOCKS5_BLOCKING_BIND_TIMEOUT;
    1358     QTime stopWatch;
     1358    QElapsedTimer stopWatch;
    13591359    stopWatch.start();
    13601360    d->data->controlSocket->connectToHost(d->proxyInfo.hostName(), d->proxyInfo.port());
     
    14561456        if (d->data->controlSocket->state() == QAbstractSocket::ConnectedState) {
    14571457            int msecs = 100;
    1458             QTime stopWatch;
     1458            QElapsedTimer stopWatch;
    14591459            stopWatch.start();
    14601460            while (!d->data->controlSocket->bytesToWrite()) {
     
    16751675        UdpAssociateSuccess;
    16761676
    1677     QTime stopWatch;
     1677    QElapsedTimer stopWatch;
    16781678    stopWatch.start();
    16791679
     
    17001700    d->readNotificationActivated = false;
    17011701
    1702     QTime stopWatch;
     1702    QElapsedTimer stopWatch;
    17031703    stopWatch.start();
    17041704
     
    17501750    QSOCKS5_DEBUG << "waitForWrite" << msecs;
    17511751
    1752     QTime stopWatch;
     1752    QElapsedTimer stopWatch;
    17531753    stopWatch.start();
    17541754
  • trunk/src/network/socket/qsocks5socketengine_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qtcpserver.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    563563    use its setSocketDescriptor() method.
    564564
    565     \sa newConnection(), nextPendingConnection()
     565    \sa newConnection(), nextPendingConnection(), addPendingConnection()
    566566*/
    567567void QTcpServer::incomingConnection(int socketDescriptor)
     
    573573    QTcpSocket *socket = new QTcpSocket(this);
    574574    socket->setSocketDescriptor(socketDescriptor);
     575    addPendingConnection(socket);
     576}
     577
     578/*!
     579    This function is called by QTcpServer::incomingConnection()
     580    to add the \a socket to the list of pending incoming connections.
     581
     582    \note Don't forget to call this member from reimplemented
     583    incomingConnection() if you do not want to break the
     584    Pending Connections mechanism.
     585
     586    \sa incomingConnection()
     587    \since 4.7
     588*/
     589void QTcpServer::addPendingConnection(QTcpSocket* socket)
     590{
    575591    d_func()->pendingConnections.append(socket);
    576592}
  • trunk/src/network/socket/qtcpserver.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9494protected:
    9595    virtual void incomingConnection(int handle);
     96    void addPendingConnection(QTcpSocket* socket);
    9697
    9798Q_SIGNALS:
  • trunk/src/network/socket/qtcpsocket.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qtcpsocket.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qtcpsocket_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qudpsocket.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/socket/qudpsocket.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qssl.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qssl.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslcertificate.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    260260/*!
    261261    Returns the certificate's serial number string in decimal format.
     262    In case the serial number cannot be converted to decimal format
     263    (i.e. if it is bigger than 4294967295, which means it does not fit into 4 bytes),
     264    its hexadecimal version is returned.
    262265*/
    263266QByteArray QSslCertificate::serialNumber() const
    264267{
    265     if (d->serialNumberString.isEmpty() && d->x509)
    266         d->serialNumberString =
    267             QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->serialNumber)));
    268 
     268    if (d->serialNumberString.isEmpty() && d->x509) {
     269        ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber;
     270        // if we cannot convert to a long, just output the hexadecimal number
     271        if (serialNumber->length > 4) {
     272            QByteArray hexString;
     273            hexString.reserve(serialNumber->length * 3);
     274            for (int a = 0; a < serialNumber->length; ++a) {
     275                hexString += QByteArray::number(serialNumber->data[a], 16).rightJustified(2, '0');
     276                hexString += ':';
     277            }
     278            hexString.chop(1);
     279            d->serialNumberString = hexString;
     280        } else {
     281            d->serialNumberString = QByteArray::number(qlonglong(q_ASN1_INTEGER_get(serialNumber)));
     282        }
     283    }
    269284    return d->serialNumberString;
    270285}
     
    534549    int startIndex = 0;
    535550    if (pathPrefix.trimmed().isEmpty()) {
    536         startIndex = 2;
    537         pathPrefix = QLatin1String(".");
     551        if(path.startsWith(QLatin1Char('/'))) {
     552            pathPrefix = path.left(path.indexOf(QRegExp(QLatin1String("[\\*\\?\\[]"))));
     553            pathPrefix = path.left(path.lastIndexOf(QLatin1Char('/')));
     554        } else {
     555            startIndex = 2;
     556            pathPrefix = QLatin1String(".");
     557        }
    538558    }
    539559
     
    697717static bool matchLineFeed(const QByteArray &pem, int *offset)
    698718{
    699     char ch;
     719    char ch = 0;
    700720
    701721    // ignore extra whitespace at the end of the line
  • trunk/src/network/ssl/qsslcertificate.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslcertificate_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslcipher.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslcipher.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslcipher_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslconfiguration.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    486486  Returns this connection's CA certificate database. The CA certificate
    487487  database is used by the socket during the handshake phase to
    488   validate the peer's certificate. It can be moodified prior to the
    489   handshake with addCaCertificate(), addCaCertificates(), and
    490   setCaCertificates().
     488  validate the peer's certificate. It can be modified prior to the
     489  handshake with setCaCertificates(), or with \l{QSslSocket}'s
     490  \l{QSslSocket::}{addCaCertificate()} and
     491  \l{QSslSocket::}{addCaCertificates()}.
    491492
    492493  \sa setCaCertificates()
  • trunk/src/network/ssl/qsslconfiguration.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslconfiguration_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslerror.cpp

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslerror.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslkey.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslkey.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslkey_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslsocket.cpp

    r769 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    211211    signal. This mode is the default for clients.
    212212
    213     \value AutoVerifyPeer QSslSocket will automaticaly use QueryPeer for
     213    \value AutoVerifyPeer QSslSocket will automatically use QueryPeer for
    214214    server sockets and VerifyPeer for client sockets.
    215215
     
    297297#include <QtCore/qdebug.h>
    298298#include <QtCore/qdir.h>
    299 #include <QtCore/qdatetime.h>
    300299#include <QtCore/qmutex.h>
     300#include <QtCore/qelapsedtimer.h>
    301301#include <QtNetwork/qhostaddress.h>
    302302#include <QtNetwork/qhostinfo.h>
     
    575575
    576576    The default mode is AutoVerifyPeer, which tells QSslSocket to use
    577     VerifyPeer for clients, QueryPeer for clients.
     577    VerifyPeer for clients and QueryPeer for servers.
    578578
    579579    \sa setPeerVerifyMode(), peerVerifyDepth(), mode()
     
    595595
    596596    The default mode is AutoVerifyPeer, which tells QSslSocket to use
    597     VerifyPeer for clients, QueryPeer for clients.
     597    VerifyPeer for clients and QueryPeer for servers.
    598598
    599599    Setting this mode after encryption has started has no effect on the
     
    13301330    Returns the current default CA certificate database. This database
    13311331    is originally set to your system's default CA certificate database.
    1332     If no system default database is found, Qt will provide its own
    1333     default database. You can override the default CA certificate database
     1332    If no system default database is found, an empty database will be
     1333    returned. You can override the default CA certificate database
    13341334    with your own CA certificate database using setDefaultCaCertificates().
    13351335
     
    13451345
    13461346/*!
    1347     This function provides a default CA certificate database
    1348     shipped together with Qt. The CA certificate database
     1347    This function provides the CA certificate database
     1348    provided by the operating system. The CA certificate database
    13491349    returned by this function is used to initialize the database
    13501350    returned by defaultCaCertificates(). You can replace that database
     
    13551355QList<QSslCertificate> QSslSocket::systemCaCertificates()
    13561356{
    1357     QSslSocketPrivate::ensureInitialized();
     1357    // we are calling ensureInitialized() in the method below
    13581358    return QSslSocketPrivate::systemCaCertificates();
    13591359}
     
    14041404        return false;
    14051405
    1406     QTime stopWatch;
     1406    QElapsedTimer stopWatch;
    14071407    stopWatch.start();
    14081408
     
    14441444    d->readyReadEmittedPointer = &readyReadEmitted;
    14451445
    1446     QTime stopWatch;
     1446    QElapsedTimer stopWatch;
    14471447    stopWatch.start();
    14481448
     
    14811481        return d->plainSocket->waitForBytesWritten(msecs);
    14821482
    1483     QTime stopWatch;
     1483    QElapsedTimer stopWatch;
    14841484    stopWatch.start();
    14851485
     
    15191519        return d->plainSocket->waitForDisconnected(msecs);
    15201520
    1521     QTime stopWatch;
     1521    QElapsedTimer stopWatch;
    15221522    stopWatch.start();
    15231523
     
    15571557bool QSslSocket::supportsSsl()
    15581558{
    1559     return QSslSocketPrivate::ensureInitialized();
     1559    return QSslSocketPrivate::supportsSsl();
    15601560}
    15611561
     
    19661966    QMutexLocker locker(&globalData()->mutex);
    19671967    const QSslConfigurationPrivate *global = globalData()->config.constData();
     1968
     1969    if (!global) {
     1970        ptr = 0;
     1971        return;
     1972    }
    19681973
    19691974    ptr->ref = 1;
     
    20312036}
    20322037
     2038void QSslSocketPrivate::pauseSocketNotifiers(QSslSocket *socket)
     2039{
     2040    if (!socket->d_func()->plainSocket)
     2041        return;
     2042    QAbstractSocketPrivate::pauseSocketNotifiers(socket->d_func()->plainSocket);
     2043}
     2044
     2045void QSslSocketPrivate::resumeSocketNotifiers(QSslSocket *socket)
     2046{
     2047    if (!socket->d_func()->plainSocket)
     2048        return;
     2049    QAbstractSocketPrivate::resumeSocketNotifiers(socket->d_func()->plainSocket);
     2050}
     2051
    20332052/*!
    20342053    \internal
  • trunk/src/network/ssl/qsslsocket.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
  • trunk/src/network/ssl/qsslsocket_openssl.cpp

    r788 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    5252#include <QtCore/qdir.h>
    5353#include <QtCore/qdiriterator.h>
     54#include <QtCore/qelapsedtimer.h>
    5455#include <QtCore/qfile.h>
    5556#include <QtCore/qfileinfo.h>
     
    5859#include <QtCore/qurl.h>
    5960#include <QtCore/qvarlengtharray.h>
    60 
    61 static void initNetworkResources()
    62 {
    63     // Initialize resources
    64     Q_INIT_RESOURCE(network);
    65 }
     61#include <QLibrary> // for loading the security lib for the CA store
    6662
    6763QT_BEGIN_NAMESPACE
    6864
    69 // Useful defines
    70 #define SSL_ERRORSTR() QString::fromLocal8Bit(q_ERR_error_string(q_ERR_get_error(), NULL))
     65#if defined(Q_OS_MAC)
     66#define kSecTrustSettingsDomainSystem 2 // so we do not need to include the header file
     67    PtrSecCertificateGetData QSslSocketPrivate::ptrSecCertificateGetData = 0;
     68    PtrSecTrustSettingsCopyCertificates QSslSocketPrivate::ptrSecTrustSettingsCopyCertificates = 0;
     69    PtrSecTrustCopyAnchorCertificates QSslSocketPrivate::ptrSecTrustCopyAnchorCertificates = 0;
     70#elif defined(Q_OS_WIN)
     71    PtrCertOpenSystemStoreW QSslSocketPrivate::ptrCertOpenSystemStoreW = 0;
     72    PtrCertFindCertificateInStore QSslSocketPrivate::ptrCertFindCertificateInStore = 0;
     73    PtrCertCloseStore QSslSocketPrivate::ptrCertCloseStore = 0;
     74#elif defined(Q_OS_SYMBIAN)
     75#include <e32base.h>
     76#include <e32std.h>
     77#include <e32debug.h>
     78#include <QtCore/private/qcore_symbian_p.h>
     79#endif
     80
     81bool QSslSocketPrivate::s_libraryLoaded = false;
     82bool QSslSocketPrivate::s_loadedCiphersAndCerts = false;
    7183
    7284/* \internal
     
    147159static unsigned long id_function()
    148160{
    149     return (unsigned long)QThread::currentThreadId();
     161    return (quintptr)QThread::currentThreadId();
    150162}
    151163} // extern "C"
     
    154166    : ssl(0),
    155167      ctx(0),
     168      pkey(0),
    156169      readBio(0),
    157170      writeBio(0),
     
    258271
    259272        // ### Bad error code
    260         q->setErrorString(QSslSocket::tr("Error creating SSL context (%1)").arg(SSL_ERRORSTR()));
     273        q->setErrorString(QSslSocket::tr("Error creating SSL context (%1)").arg(getErrorsFromOpenSsl()));
    261274        q->setSocketError(QAbstractSocket::UnknownSocketError);
    262275        emit q->error(QAbstractSocket::UnknownSocketError);
     
    283296    if (!q_SSL_CTX_set_cipher_list(ctx, cipherString.data())) {
    284297        // ### Bad error code
    285         q->setErrorString(QSslSocket::tr("Invalid or empty cipher list (%1)").arg(SSL_ERRORSTR()));
     298        q->setErrorString(QSslSocket::tr("Invalid or empty cipher list (%1)").arg(getErrorsFromOpenSsl()));
    286299        q->setSocketError(QAbstractSocket::UnknownSocketError);
    287300        emit q->error(QAbstractSocket::UnknownSocketError);
     
    290303
    291304    // Add all our CAs to this store.
    292     foreach (const QSslCertificate &caCertificate, q->caCertificates())
     305    QList<QSslCertificate> expiredCerts;
     306    foreach (const QSslCertificate &caCertificate, q->caCertificates()) {
     307        // add expired certs later, so that the
     308        // valid ones are used before the expired ones
     309        if (! caCertificate.isValid()) {
     310            expiredCerts.append(caCertificate);
     311        } else {
     312            q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle());
     313        }
     314    }
     315    // now add the expired certs
     316    foreach (const QSslCertificate &caCertificate, expiredCerts) {
    293317        q_X509_STORE_add_cert(ctx->cert_store, (X509 *)caCertificate.handle());
     318    }
    294319
    295320    // Register a custom callback to get all verification errors.
     
    299324        // Require a private key as well.
    300325        if (configuration.privateKey.isNull()) {
    301             q->setErrorString(QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(SSL_ERRORSTR()));
     326            q->setErrorString(QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(getErrorsFromOpenSsl()));
    302327            emit q->error(QAbstractSocket::UnknownSocketError);
    303328            return false;
     
    306331        // Load certificate
    307332        if (!q_SSL_CTX_use_certificate(ctx, (X509 *)configuration.localCertificate.handle())) {
    308             q->setErrorString(QSslSocket::tr("Error loading local certificate, %1").arg(SSL_ERRORSTR()));
     333            q->setErrorString(QSslSocket::tr("Error loading local certificate, %1").arg(getErrorsFromOpenSsl()));
    309334            emit q->error(QAbstractSocket::UnknownSocketError);
    310335            return false;
     
    312337
    313338        // Load private key
    314         EVP_PKEY *pkey = q_EVP_PKEY_new();
     339        pkey = q_EVP_PKEY_new();
     340        // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
     341        // this lead to a memory leak. Now we use the *_set1_* functions which do not
     342        // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
    315343        if (configuration.privateKey.algorithm() == QSsl::Rsa)
    316             q_EVP_PKEY_assign_RSA(pkey, (RSA *)configuration.privateKey.handle());
     344            q_EVP_PKEY_set1_RSA(pkey, (RSA *)configuration.privateKey.handle());
    317345        else
    318             q_EVP_PKEY_assign_DSA(pkey, (DSA *)configuration.privateKey.handle());
     346            q_EVP_PKEY_set1_DSA(pkey, (DSA *)configuration.privateKey.handle());
    319347        if (!q_SSL_CTX_use_PrivateKey(ctx, pkey)) {
    320             q->setErrorString(QSslSocket::tr("Error loading private key, %1").arg(SSL_ERRORSTR()));
     348            q->setErrorString(QSslSocket::tr("Error loading private key, %1").arg(getErrorsFromOpenSsl()));
    321349            emit q->error(QAbstractSocket::UnknownSocketError);
    322350            return false;
     
    325353        // Check if the certificate matches the private key.
    326354        if (!q_SSL_CTX_check_private_key(ctx)) {
    327             q->setErrorString(QSslSocket::tr("Private key does not certify public key, %1").arg(SSL_ERRORSTR()));
     355            q->setErrorString(QSslSocket::tr("Private key does not certify public key, %1").arg(getErrorsFromOpenSsl()));
    328356            emit q->error(QAbstractSocket::UnknownSocketError);
    329357            return false;
     
    345373    if (!(ssl = q_SSL_new(ctx))) {
    346374        // ### Bad error code
    347         q->setErrorString(QSslSocket::tr("Error creating SSL session, %1").arg(SSL_ERRORSTR()));
     375        q->setErrorString(QSslSocket::tr("Error creating SSL session, %1").arg(getErrorsFromOpenSsl()));
    348376        q->setSocketError(QAbstractSocket::UnknownSocketError);
    349377        emit q->error(QAbstractSocket::UnknownSocketError);
     
    360388    if (!readBio || !writeBio) {
    361389        // ### Bad error code
    362         q->setErrorString(QSslSocket::tr("Error creating SSL session: %1").arg(SSL_ERRORSTR()));
     390        q->setErrorString(QSslSocket::tr("Error creating SSL session: %1").arg(getErrorsFromOpenSsl()));
    363391        q->setSocketError(QAbstractSocket::UnknownSocketError);
    364392        emit q->error(QAbstractSocket::UnknownSocketError);
     
    389417    \internal
    390418
    391     Declared static in QSslSocketPrivate, makes sure the SSL libraries have
    392     been initialized.
     419    Does the minimum amount of initialization to determine whether SSL
     420    is supported or not.
    393421*/
    394 bool QSslSocketPrivate::ensureInitialized()
     422
     423bool QSslSocketPrivate::supportsSsl()
     424{
     425    return ensureLibraryLoaded();
     426}
     427
     428bool QSslSocketPrivate::ensureLibraryLoaded()
    395429{
    396430    if (!q_resolveOpenSslSymbols())
     
    399433    // Check if the library itself needs to be initialized.
    400434    QMutexLocker locker(openssl_locks()->initLock());
    401     static int q_initialized = false;
    402     if (!q_initialized) {
    403         q_initialized = true;
    404 
    405         // Initialize resources
    406         initNetworkResources();
     435    if (!s_libraryLoaded) {
     436        s_libraryLoaded = true;
    407437
    408438        // Initialize OpenSSL.
     
    441471                return false;
    442472        }
    443 
    444         resetDefaultCiphers();
    445         setDefaultCaCertificates(systemCaCertificates());
    446473    }
    447474    return true;
     475}
     476
     477void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
     478{
     479    QMutexLocker locker(openssl_locks()->initLock());
     480    if (s_loadedCiphersAndCerts)
     481        return;
     482    s_loadedCiphersAndCerts = true;
     483
     484    resetDefaultCiphers();
     485
     486    //load symbols needed to receive certificates from system store
     487#if defined(Q_OS_MAC)
     488    QLibrary securityLib("/System/Library/Frameworks/Security.framework/Versions/Current/Security");
     489    if (securityLib.load()) {
     490        ptrSecCertificateGetData = (PtrSecCertificateGetData) securityLib.resolve("SecCertificateGetData");
     491        if (!ptrSecCertificateGetData)
     492            qWarning("could not resolve symbols in security library"); // should never happen
     493
     494        ptrSecTrustSettingsCopyCertificates = (PtrSecTrustSettingsCopyCertificates) securityLib.resolve("SecTrustSettingsCopyCertificates");
     495        if (!ptrSecTrustSettingsCopyCertificates) { // method was introduced in Leopard, use legacy method if it's not there
     496            ptrSecTrustCopyAnchorCertificates = (PtrSecTrustCopyAnchorCertificates) securityLib.resolve("SecTrustCopyAnchorCertificates");
     497            if (!ptrSecTrustCopyAnchorCertificates)
     498                qWarning("could not resolve symbols in security library"); // should never happen
     499        }
     500    } else {
     501        qWarning("could not load security library");
     502    }
     503#elif defined(Q_OS_WIN)
     504    HINSTANCE hLib = LoadLibraryW(L"Crypt32");
     505    if (hLib) {
     506#if defined(Q_OS_WINCE)
     507        ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, L"CertOpenStore");
     508        ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, L"CertFindCertificateInStore");
     509        ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, L"CertCloseStore");
     510#else
     511        ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
     512        ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
     513        ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
     514#endif
     515        if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
     516            qWarning("could not resolve symbols in crypt32 library"); // should never happen
     517    } else {
     518        qWarning("could not load crypt32 library"); // should never happen
     519    }
     520#endif
     521    setDefaultCaCertificates(systemCaCertificates());
     522}
     523
     524/*!
     525    \internal
     526
     527    Declared static in QSslSocketPrivate, makes sure the SSL libraries have
     528    been initialized.
     529*/
     530
     531void QSslSocketPrivate::ensureInitialized()
     532{
     533    if (!supportsSsl())
     534        return;
     535
     536    ensureCiphersAndCertsLoaded();
    448537}
    449538
     
    481570}
    482571
     572#if defined(Q_OS_SYMBIAN)
     573
     574CSymbianCertificateRetriever::CSymbianCertificateRetriever() : CActive(CActive::EPriorityStandard),
     575    iCertificatePtr(0,0,0), iSequenceError(KErrNone)
     576{
     577}
     578
     579CSymbianCertificateRetriever::~CSymbianCertificateRetriever()
     580{
     581    iThread.Close();
     582}
     583
     584CSymbianCertificateRetriever* CSymbianCertificateRetriever::NewL()
     585{
     586    CSymbianCertificateRetriever* self = new (ELeave) CSymbianCertificateRetriever();
     587    CleanupStack::PushL(self);
     588    self->ConstructL();
     589    CleanupStack::Pop();
     590    return self;
     591}
     592
     593int CSymbianCertificateRetriever::GetCertificates(QList<QByteArray> &certificates)
     594{
     595    iCertificates = &certificates;
     596
     597    TRequestStatus status;
     598    iThread.Logon(status);
     599    iThread.Resume();
     600    User::WaitForRequest(status);
     601    if (iThread.ExitType() == EExitKill)
     602        return KErrDied;
     603    else
     604        return status.Int();    // Logon() completes with the thread's exit value
     605}
     606
     607void CSymbianCertificateRetriever::doThreadEntryL()
     608{
     609    CActiveScheduler* activeScheduler = new (ELeave) CActiveScheduler;
     610    CleanupStack::PushL(activeScheduler);
     611    CActiveScheduler::Install(activeScheduler);
     612
     613    CActiveScheduler::Add(this);
     614
     615    // These aren't deleted in the destructor so leaving the to CS is ok
     616    iCertStore = CUnifiedCertStore::NewLC(qt_s60GetRFs(), EFalse);
     617    iCertFilter = CCertAttributeFilter::NewLC();
     618
     619    // only interested in CA certs
     620    iCertFilter->SetOwnerType(ECACertificate);
     621    // only interested in X.509 format (we don't support WAP formats)
     622    iCertFilter->SetFormat(EX509Certificate);
     623
     624    // Kick off the sequence by initializing the cert store
     625    iState = Initializing;
     626    iCertStore->Initialize(iStatus);
     627    SetActive();
     628
     629    CActiveScheduler::Start();
     630
     631    // Sequence complete, clean up
     632
     633    // These MUST be cleaned up before the installed CActiveScheduler is destroyed and can't be left to the
     634    // destructor of CSymbianCertificateRetriever. Otherwise the destructor of CActiveScheduler will get
     635    // stuck.
     636    iCertInfos.Close();
     637    CleanupStack::PopAndDestroy(3);     // activeScheduler, iCertStore, iCertFilter
     638}
     639
     640
     641TInt CSymbianCertificateRetriever::ThreadEntryPoint(TAny* aParams)
     642{
     643    User::SetCritical(User::EProcessCritical);
     644    CTrapCleanup* cleanupStack = CTrapCleanup::New();
     645
     646    CSymbianCertificateRetriever* self = (CSymbianCertificateRetriever*) aParams;
     647    TRAPD(err, self->doThreadEntryL());
     648    delete cleanupStack;
     649
     650    // doThreadEntryL() can leave only before the retrieval sequence is started
     651    if (err)
     652        return err;
     653    else
     654        return self->iSequenceError;    // return any error that occurred during the retrieval
     655}
     656
     657void CSymbianCertificateRetriever::ConstructL()
     658{
     659    TInt err;
     660    int i=0;
     661    QString name(QLatin1String("CertWorkerThread-%1"));
     662    //recently closed thread names remain in use for a while until all handles have been closed
     663    //including users of RUndertaker
     664    do {
     665        err = iThread.Create(qt_QString2TPtrC(name.arg(i++)),
     666            CSymbianCertificateRetriever::ThreadEntryPoint, 16384, NULL, this);
     667    } while (err == KErrAlreadyExists);
     668    User::LeaveIfError(err);
     669}
     670
     671void CSymbianCertificateRetriever::DoCancel()
     672{
     673    switch(iState) {
     674    case Initializing:
     675        iCertStore->CancelInitialize();
     676        break;
     677    case Listing:
     678        iCertStore->CancelList();
     679        break;
     680    case RetrievingCertificates:
     681        iCertStore->CancelGetCert();
     682        break;
     683    }
     684}
     685
     686TInt CSymbianCertificateRetriever::RunError(TInt aError)
     687{
     688    // If something goes wrong in the sequence, abort the sequence
     689    iSequenceError = aError;    // this gets reported to the client in the TRequestStatus
     690    CActiveScheduler::Stop();
     691    return KErrNone;
     692}
     693
     694void CSymbianCertificateRetriever::GetCertificateL()
     695{
     696    if (iCurrentCertIndex < iCertInfos.Count()) {
     697        CCTCertInfo* certInfo = iCertInfos[iCurrentCertIndex++];
     698        iCertificateData = QByteArray();
     699        QT_TRYCATCH_LEAVING(iCertificateData.resize(certInfo->Size()));
     700        iCertificatePtr.Set((TUint8*)iCertificateData.data(), 0, iCertificateData.size());
     701#ifdef QSSLSOCKET_DEBUG
     702        qDebug() << "getting " << qt_TDesC2QString(certInfo->Label()) << " size=" << certInfo->Size();
     703        qDebug() << "format=" << certInfo->CertificateFormat();
     704        qDebug() << "ownertype=" << certInfo->CertificateOwnerType();
     705        qDebug() << "type=" << hex << certInfo->Type().iUid;
     706#endif
     707        iCertStore->Retrieve(*certInfo, iCertificatePtr, iStatus);
     708        iState = RetrievingCertificates;
     709        SetActive();
     710    } else {
     711        //reached end of list
     712        CActiveScheduler::Stop();
     713    }
     714}
     715
     716void CSymbianCertificateRetriever::RunL()
     717{
     718#ifdef QSSLSOCKET_DEBUG
     719    qDebug() << "CSymbianCertificateRetriever::RunL status " << iStatus.Int() << " count " << iCertInfos.Count() << " index " << iCurrentCertIndex;
     720#endif
     721    switch (iState) {
     722    case Initializing:
     723        User::LeaveIfError(iStatus.Int()); // initialise fail means pointless to continue
     724        iState = Listing;
     725        iCertStore->List(iCertInfos, *iCertFilter, iStatus);
     726        SetActive();
     727        break;
     728
     729    case Listing:
     730        User::LeaveIfError(iStatus.Int()); // listing fail means pointless to continue
     731        iCurrentCertIndex = 0;
     732        GetCertificateL();
     733        break;
     734
     735    case RetrievingCertificates:
     736        if (iStatus.Int() == KErrNone)
     737            iCertificates->append(iCertificateData);
     738        else
     739            qWarning() << "CSymbianCertificateRetriever: failed to retrieve a certificate, error " << iStatus.Int();
     740        GetCertificateL();
     741        break;
     742    }
     743}
     744#endif // defined(Q_OS_SYMBIAN)
     745
    483746QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
    484747{
    485     // Qt provides a default bundle of certificates
    486     QFile caBundle(QLatin1String(":/trolltech/network/ssl/qt-ca-bundle.crt"));
    487     if (caBundle.open(QIODevice::ReadOnly | QIODevice::Text))
    488         return QSslCertificate::fromDevice(&caBundle);
    489 
    490     // Unreachable; return no bundle.
    491     return QList<QSslCertificate>();
     748    ensureInitialized();
     749#ifdef QSSLSOCKET_DEBUG
     750    QElapsedTimer timer;
     751    timer.start();
     752#endif
     753    QList<QSslCertificate> systemCerts;
     754#if defined(Q_OS_MAC)
     755    CFArrayRef cfCerts;
     756    OSStatus status = 1;
     757
     758    OSStatus SecCertificateGetData (
     759       SecCertificateRef certificate,
     760       CSSM_DATA_PTR data
     761    );
     762
     763    if (ptrSecCertificateGetData) {
     764        if (ptrSecTrustSettingsCopyCertificates)
     765            status = ptrSecTrustSettingsCopyCertificates(kSecTrustSettingsDomainSystem, &cfCerts);
     766        else if (ptrSecTrustCopyAnchorCertificates)
     767            status = ptrSecTrustCopyAnchorCertificates(&cfCerts);
     768        if (!status) {
     769            CFIndex size = CFArrayGetCount(cfCerts);
     770            for (CFIndex i = 0; i < size; ++i) {
     771                SecCertificateRef cfCert = (SecCertificateRef)CFArrayGetValueAtIndex(cfCerts, i);
     772                CSSM_DATA data;
     773                CSSM_DATA_PTR dataPtr = &data;
     774                if (ptrSecCertificateGetData(cfCert, dataPtr)) {
     775                    qWarning("error retrieving a CA certificate from the system store");
     776                } else {
     777                    int len = data.Length;
     778                    char *rawData = reinterpret_cast<char *>(data.Data);
     779                    QByteArray rawCert(rawData, len);
     780                    systemCerts.append(QSslCertificate::fromData(rawCert, QSsl::Der));
     781                }
     782            }
     783        }
     784        else {
     785           // no detailed error handling here
     786           qWarning("could not retrieve system CA certificates");
     787        }
     788    }
     789#elif defined(Q_OS_WIN)
     790    if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
     791        HCERTSTORE hSystemStore;
     792#if defined(Q_OS_WINCE)
     793        hSystemStore = ptrCertOpenSystemStoreW(CERT_STORE_PROV_SYSTEM_W,
     794                                               0,
     795                                               0,
     796                                               CERT_STORE_NO_CRYPT_RELEASE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER,
     797                                               L"ROOT");
     798#else
     799        hSystemStore = ptrCertOpenSystemStoreW(0, L"ROOT");
     800#endif
     801        if(hSystemStore) {
     802            PCCERT_CONTEXT pc = NULL;
     803            while(1) {
     804                pc = ptrCertFindCertificateInStore( hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pc);
     805                if(!pc)
     806                    break;
     807                QByteArray der((const char *)(pc->pbCertEncoded), static_cast<int>(pc->cbCertEncoded));
     808                QSslCertificate cert(der, QSsl::Der);
     809                systemCerts.append(cert);
     810            }
     811            ptrCertCloseStore(hSystemStore, 0);
     812        }
     813    }
     814#elif defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
     815    QSet<QString> certFiles;
     816    QList<QByteArray> directories;
     817    directories << "/etc/ssl/certs/"; // (K)ubuntu, OpenSUSE, Mandriva, MeeGo ...
     818    directories << "/usr/lib/ssl/certs/"; // Gentoo, Mandrake
     819    directories << "/usr/share/ssl/"; // Centos, Redhat, SuSE
     820    directories << "/usr/local/ssl/"; // Normal OpenSSL Tarball
     821    directories << "/var/ssl/certs/"; // AIX
     822    directories << "/usr/local/ssl/certs/"; // Solaris
     823    directories << "/opt/openssl/certs/"; // HP-UX
     824
     825    QDir currentDir;
     826    QStringList nameFilters;
     827    nameFilters << QLatin1String("*.pem") << QLatin1String("*.crt");
     828    currentDir.setNameFilters(nameFilters);
     829    for (int a = 0; a < directories.count(); a++) {
     830        currentDir.setPath(QLatin1String(directories.at(a)));
     831        QDirIterator it(currentDir);
     832        while(it.hasNext()) {
     833            it.next();
     834            // use canonical path here to not load the same certificate twice if symlinked
     835            certFiles.insert(it.fileInfo().canonicalFilePath());
     836        }
     837    }
     838    QSetIterator<QString> it(certFiles);
     839    while(it.hasNext()) {
     840        systemCerts.append(QSslCertificate::fromPath(it.next()));
     841    }
     842    systemCerts.append(QSslCertificate::fromPath(QLatin1String("/etc/pki/tls/certs/ca-bundle.crt"), QSsl::Pem)); // Fedora, Mandriva
     843    systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/share/certs/ca-root-nss.crt"), QSsl::Pem)); // FreeBSD's ca_root_nss
     844
     845#elif defined(Q_OS_SYMBIAN)
     846    QList<QByteArray> certs;
     847    QScopedPointer<CSymbianCertificateRetriever> retriever(CSymbianCertificateRetriever::NewL());
     848
     849    retriever->GetCertificates(certs);
     850    foreach (const QByteArray &encodedCert, certs) {
     851        QSslCertificate cert(encodedCert, QSsl::Der);
     852        if (!cert.isNull()) {
     853#ifdef QSSLSOCKET_DEBUG
     854            qDebug() << "imported certificate: " << cert.issuerInfo(QSslCertificate::CommonName);
     855#endif
     856            systemCerts.append(cert);
     857        }
     858    }
     859#endif
     860#ifdef QSSLSOCKET_DEBUG
     861    qDebug() << "systemCaCertificates retrieval time " << timer.elapsed() << "ms";
     862    qDebug() << "imported " << systemCerts.count() << " certificates";
     863#endif
     864
     865    return systemCerts;
    492866}
    493867
     
    544918                if (writtenBytes <= 0) {
    545919                    // ### Better error handling.
    546                     q->setErrorString(QSslSocket::tr("Unable to write data: %1").arg(SSL_ERRORSTR()));
     920                    q->setErrorString(QSslSocket::tr("Unable to write data: %1").arg(getErrorsFromOpenSsl()));
    547921                    q->setSocketError(QAbstractSocket::UnknownSocketError);
    548922                    emit q->error(QAbstractSocket::UnknownSocketError);
     
    607981                } else {
    608982                    // ### Better error handling.
    609                     q->setErrorString(QSslSocket::tr("Unable to decrypt data: %1").arg(SSL_ERRORSTR()));
     983                    q->setErrorString(QSslSocket::tr("Unable to decrypt data: %1").arg(getErrorsFromOpenSsl()));
    610984                    q->setSocketError(QAbstractSocket::UnknownSocketError);
    611985                    emit q->error(QAbstractSocket::UnknownSocketError);
     
    6811055                plainSocket->disconnectFromHost();
    6821056                break;
     1057            case SSL_ERROR_SYSCALL: // some IO error
     1058            case SSL_ERROR_SSL: // error in the SSL library
     1059                // we do not know exactly what the error is, nor whether we can recover from it,
     1060                // so just return to prevent an endless loop in the outer "while" statement
     1061                q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
     1062                q->setSocketError(QAbstractSocket::UnknownSocketError);
     1063                emit q->error(QAbstractSocket::UnknownSocketError);
     1064                return;
    6831065            default:
    684                 // ### Handle errors better.
    685                 q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(SSL_ERRORSTR()));
     1066                // SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: can only happen with a
     1067                // BIO_s_connect() or BIO_s_accept(), which we do not call.
     1068                // SSL_ERROR_WANT_X509_LOOKUP: can only happen with a
     1069                // SSL_CTX_set_client_cert_cb(), which we do not call.
     1070                // So this default case should never be triggered.
     1071                q->setErrorString(QSslSocket::tr("Error while reading: %1").arg(getErrorsFromOpenSsl()));
    6861072                q->setSocketError(QAbstractSocket::UnknownSocketError);
    6871073                emit q->error(QAbstractSocket::UnknownSocketError);
     
    7781164            break;
    7791165        default:
    780             // ### Handle errors better
    781             q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(SSL_ERRORSTR()));
     1166            q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(getErrorsFromOpenSsl()));
    7821167            q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
    7831168#ifdef QSSLSOCKET_DEBUG
     
    8161201            QString commonName = configuration.peerCertificate.subjectInfo(QSslCertificate::CommonName);
    8171202
    818             QRegExp regexp(commonName, Qt::CaseInsensitive, QRegExp::Wildcard);
    819             if (!regexp.exactMatch(peerName)) {
     1203            if (!isMatchingHostname(commonName.toLower(), peerName.toLower())) {
    8201204                bool matched = false;
    8211205                foreach (const QString &altName, configuration.peerCertificate
    8221206                         .alternateSubjectNames().values(QSsl::DnsEntry)) {
    823                     regexp.setPattern(altName);
    824                     if (regexp.exactMatch(peerName)) {
     1207                    if (isMatchingHostname(altName.toLower(), peerName.toLower())) {
    8251208                        matched = true;
    8261209                        break;
    8271210                    }
    8281211                }
     1212
    8291213                if (!matched) {
    8301214                    // No matches in common names or alternate names.
     
    9231307        ctx = 0;
    9241308    }
     1309    if (pkey) {
     1310        q_EVP_PKEY_free(pkey);
     1311        pkey = 0;
     1312    }
     1313
    9251314}
    9261315
     
    9511340}
    9521341
     1342QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
     1343{
     1344    QString errorString;
     1345    unsigned long errNum;
     1346    while((errNum = q_ERR_get_error())) {
     1347        if (! errorString.isEmpty())
     1348            errorString.append(QLatin1String(", "));
     1349        const char *error = q_ERR_error_string(errNum, NULL);
     1350        errorString.append(QString::fromAscii(error)); // error is ascii according to man ERR_error_string
     1351    }
     1352    return errorString;
     1353}
     1354
     1355bool QSslSocketBackendPrivate::isMatchingHostname(const QString &cn, const QString &hostname)
     1356{
     1357    int wildcard = cn.indexOf(QLatin1Char('*'));
     1358
     1359    // Check this is a wildcard cert, if not then just compare the strings
     1360    if (wildcard < 0)
     1361        return cn == hostname;
     1362
     1363    int firstCnDot = cn.indexOf(QLatin1Char('.'));
     1364    int secondCnDot = cn.indexOf(QLatin1Char('.'), firstCnDot+1);
     1365
     1366    // Check at least 3 components
     1367    if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.length()))
     1368        return false;
     1369
     1370    // Check * is last character of 1st component (ie. there's a following .)
     1371    if (wildcard+1 != firstCnDot)
     1372        return false;
     1373
     1374    // Check only one star
     1375    if (cn.lastIndexOf(QLatin1Char('*')) != wildcard)
     1376        return false;
     1377
     1378    // Check characters preceding * (if any) match
     1379    if (wildcard && (hostname.leftRef(wildcard) != cn.leftRef(wildcard)))
     1380        return false;
     1381
     1382    // Check characters following first . match
     1383    if (hostname.midRef(hostname.indexOf(QLatin1Char('.'))) != cn.midRef(firstCnDot))
     1384        return false;
     1385
     1386    // Check if the hostname is an IP address, if so then wildcards are not allowed
     1387    QHostAddress addr(hostname);
     1388    if (!addr.isNull())
     1389        return false;
     1390
     1391    // Ok, I guess this was a wildcard CN and the hostname matches.
     1392    return true;
     1393}
     1394
    9531395QT_END_NAMESPACE
  • trunk/src/network/ssl/qsslsocket_openssl_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    9898    SSL *ssl;
    9999    SSL_CTX *ctx;
     100    EVP_PKEY *pkey;
    100101    BIO *readBio;
    101102    BIO *writeBio;
     
    116117    static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher);
    117118    static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
     119    Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QString &cn, const QString &hostname);
     120    static QString getErrorsFromOpenSsl();
    118121};
     122
     123#if defined(Q_OS_SYMBIAN)
     124
     125#include <QByteArray>
     126#include <e32base.h>
     127#include <f32file.h>
     128#include <unifiedcertstore.h>     // link against certstore.lib
     129#include <ccertattributefilter.h> // link against ctframework.lib
     130
     131// The purpose of this class is to wrap the asynchronous API of Symbian certificate store to one
     132// synchronizable call. The user of this class needs to provide a TRequestStatus object which can
     133// be used with User::WaitForRequest() unlike with the calls of the certificate store API.
     134// A thread is used instead of a CActiveSchedulerWait scheme, because that would make the call
     135// asynchronous (other events might be processed during the call even though the call would be seemingly
     136// synchronous).
     137
     138class CSymbianCertificateRetriever : public CActive
     139{
     140public:
     141    static CSymbianCertificateRetriever* NewL();
     142    ~CSymbianCertificateRetriever();
     143
     144    int GetCertificates(QList<QByteArray> &aCertificates);
     145
     146private:
     147    void ConstructL();
     148    CSymbianCertificateRetriever();
     149    static TInt ThreadEntryPoint(TAny* aParams);
     150    void doThreadEntryL();
     151    void GetCertificateL();
     152    void DoCancel();
     153    void RunL();
     154    TInt RunError(TInt aError);
     155
     156private:
     157    enum {
     158        Initializing,
     159        Listing,
     160        RetrievingCertificates
     161    } iState;
     162
     163    RThread iThread;
     164    CUnifiedCertStore* iCertStore;
     165    RMPointerArray<CCTCertInfo> iCertInfos;
     166    CCertAttributeFilter* iCertFilter;
     167    TInt iCurrentCertIndex;
     168    QByteArray iCertificateData;
     169    TPtr8 iCertificatePtr;
     170    QList<QByteArray>* iCertificates;
     171    TInt iSequenceError;
     172};
     173
     174
     175#endif
     176
    119177
    120178QT_END_NAMESPACE
  • trunk/src/network/ssl/qsslsocket_openssl_symbols.cpp

    r788 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    4343#include "qsslsocket_openssl_symbols_p.h"
    4444
    45 #include <QtCore/qlibrary.h>
     45#ifdef Q_OS_WIN
     46# include <private/qsystemlibrary_p.h>
     47#else
     48# include <QtCore/qlibrary.h>
     49#endif
    4650#include <QtCore/qmutex.h>
    4751#include <private/qmutexpool_p.h>
     
    120124DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return)
    121125DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return)
     126DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return)
     127DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return)
    122128DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG)
    123129DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return 0, return)
     
    333339            .split(QLatin1Char(':'), QString::SkipEmptyParts);
    334340#  endif
    335     paths << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");
     341    paths << QLatin1String("/lib") << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");
    336342
    337343    QStringList foundSsls;
     
    348354}
    349355# endif
     356
     357#ifdef Q_OS_WIN
     358static QPair<QSystemLibrary*, QSystemLibrary*> loadOpenSslWin32()
     359{
     360    QPair<QSystemLibrary*,QSystemLibrary*> pair;
     361    pair.first = 0;
     362    pair.second = 0;
     363
     364    QSystemLibrary *ssleay32 = new QSystemLibrary(QLatin1String("ssleay32"));
     365    if (!ssleay32->load(false)) {
     366        // Cannot find ssleay32.dll
     367        delete ssleay32;
     368        return pair;
     369    }
     370
     371    QSystemLibrary *libeay32 = new QSystemLibrary(QLatin1String("libeay32"));
     372    if (!libeay32->load(false)) {
     373        delete ssleay32;
     374        delete libeay32;
     375        return pair;
     376    }
     377
     378    pair.first = ssleay32;
     379    pair.second = libeay32;
     380    return pair;
     381}
     382#else
    350383
    351384static QPair<QLibrary*, QLibrary*> loadOpenSsl()
     
    355388    pair.second = 0;
    356389
    357 # ifdef Q_OS_WIN
    358     QLibrary *ssleay32 = new QLibrary(QLatin1String("ssleay32"));
    359     if (!ssleay32->load()) {
    360         // Cannot find ssleay32.dll
    361         delete ssleay32;
    362         return pair;
    363     }
    364 
    365     QLibrary *libeay32 = new QLibrary(QLatin1String("libeay32"));
    366     if (!libeay32->load()) {
    367         delete ssleay32;
    368         delete libeay32;
    369         return pair;
    370     }
    371 
    372     pair.first = ssleay32;
    373     pair.second = libeay32;
    374     return pair;
    375 # elif defined(Q_OS_SYMBIAN)
     390# if defined(Q_OS_SYMBIAN)
    376391     QLibrary *libssl = new QLibrary(QLatin1String("libssl"));
    377392    if (!libssl->load()) {
     
    506521# endif
    507522}
     523#endif
    508524
    509525bool q_resolveOpenSslSymbols()
     
    520536    triedToResolveSymbols = true;
    521537
     538#ifdef Q_OS_WIN
     539    QPair<QSystemLibrary *, QSystemLibrary *> libs = loadOpenSslWin32();
     540#else
    522541    QPair<QLibrary *, QLibrary *> libs = loadOpenSsl();
     542#endif
    523543    if (!libs.first || !libs.second)
    524544        // failed to load them
     
    549569    RESOLVEFUNC(EVP_des_ede3_cbc, 919, libs.second )
    550570    RESOLVEFUNC(EVP_PKEY_assign, 859, libs.second )
     571    RESOLVEFUNC(EVP_PKEY_set1_RSA, 880, libs.second )
     572    RESOLVEFUNC(EVP_PKEY_set1_DSA, 879, libs.second )
    551573    RESOLVEFUNC(EVP_PKEY_free, 867, libs.second )
    552574    RESOLVEFUNC(EVP_PKEY_get1_DSA, 869, libs.second )
     
    671693    RESOLVEFUNC(EVP_des_ede3_cbc)
    672694    RESOLVEFUNC(EVP_PKEY_assign)
     695    RESOLVEFUNC(EVP_PKEY_set1_RSA)
     696    RESOLVEFUNC(EVP_PKEY_set1_DSA)
    673697    RESOLVEFUNC(EVP_PKEY_free)
    674698    RESOLVEFUNC(EVP_PKEY_get1_DSA)
     
    794818QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime)
    795819{
    796     char lBuffer[24];
    797     char *pBuffer = lBuffer;
    798 
    799820    size_t lTimeLength = aTime->length;
    800821    char *pString = (char *) aTime->data;
    801822
    802823    if (aTime->type == V_ASN1_UTCTIME) {
     824
     825        char lBuffer[24];
     826        char *pBuffer = lBuffer;
     827
    803828        if ((lTimeLength < 11) || (lTimeLength > 17))
    804829            return QDateTime();
     
    807832        pBuffer += 10;
    808833        pString += 10;
     834
     835        if ((*pString == 'Z') || (*pString == '-') || (*pString == '+')) {
     836            *pBuffer++ = '0';
     837            *pBuffer++ = '0';
     838        } else {
     839            *pBuffer++ = *pString++;
     840            *pBuffer++ = *pString++;
     841            // Skip any fractional seconds...
     842            if (*pString == '.') {
     843                pString++;
     844                while ((*pString >= '0') && (*pString <= '9'))
     845                    pString++;
     846            }
     847        }
     848
     849        *pBuffer++ = 'Z';
     850        *pBuffer++ = '\0';
     851
     852        time_t lSecondsFromUCT;
     853        if (*pString == 'Z') {
     854            lSecondsFromUCT = 0;
     855        } else {
     856            if ((*pString != '+') && (*pString != '-'))
     857                return QDateTime();
     858
     859            lSecondsFromUCT = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60;
     860            lSecondsFromUCT += (pString[3] - '0') * 10 + (pString[4] - '0');
     861            lSecondsFromUCT *= 60;
     862            if (*pString == '-')
     863                lSecondsFromUCT = -lSecondsFromUCT;
     864        }
     865
     866        tm lTime;
     867        lTime.tm_sec = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
     868        lTime.tm_min = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
     869        lTime.tm_hour = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
     870        lTime.tm_mday = ((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0');
     871        lTime.tm_mon = (((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0')) - 1;
     872        lTime.tm_year = ((lBuffer[0] - '0') * 10) + (lBuffer[1] - '0');
     873        if (lTime.tm_year < 50)
     874            lTime.tm_year += 100; // RFC 2459
     875
     876        QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday);
     877        QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec);
     878
     879        QDateTime result(resDate, resTime, Qt::UTC);
     880        result = result.addSecs(lSecondsFromUCT);
     881        return result;
     882
     883    } else if (aTime->type == V_ASN1_GENERALIZEDTIME) {
     884
     885        if (lTimeLength < 15)
     886            return QDateTime(); // hopefully never triggered
     887
     888        // generalized time is always YYYYMMDDHHMMSSZ (RFC 2459, section 4.1.2.5.2)
     889        tm lTime;
     890        lTime.tm_sec = ((pString[12] - '0') * 10) + (pString[13] - '0');
     891        lTime.tm_min = ((pString[10] - '0') * 10) + (pString[11] - '0');
     892        lTime.tm_hour = ((pString[8] - '0') * 10) + (pString[9] - '0');
     893        lTime.tm_mday = ((pString[6] - '0') * 10) + (pString[7] - '0');
     894        lTime.tm_mon = (((pString[4] - '0') * 10) + (pString[5] - '0'));
     895        lTime.tm_year = ((pString[0] - '0') * 1000) + ((pString[1] - '0') * 100) +
     896                        ((pString[2] - '0') * 10) + (pString[3] - '0');
     897
     898        QDate resDate(lTime.tm_year, lTime.tm_mon, lTime.tm_mday);
     899        QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec);
     900
     901        QDateTime result(resDate, resTime, Qt::UTC);
     902        return result;
     903
    809904    } else {
    810         if (lTimeLength < 13)
    811             return QDateTime();
    812 
    813         memcpy(pBuffer, pString, 12);
    814         pBuffer += 12;
    815         pString += 12;
    816     }
    817 
    818     if ((*pString == 'Z') || (*pString == '-') || (*pString == '+')) {
    819         *pBuffer++ = '0';
    820         *pBuffer++ = '0';
    821     } else {
    822         *pBuffer++ = *pString++;
    823         *pBuffer++ = *pString++;
    824         // Skip any fractional seconds...
    825         if (*pString == '.') {
    826             pString++;
    827             while ((*pString >= '0') && (*pString <= '9'))
    828                 pString++;
    829         }
    830     }
    831 
    832     *pBuffer++ = 'Z';
    833     *pBuffer++ = '\0';
    834 
    835     time_t lSecondsFromUCT;
    836     if (*pString == 'Z') {
    837         lSecondsFromUCT = 0;
    838     } else {
    839         if ((*pString != '+') && (*pString != '-'))
    840             return QDateTime();
    841 
    842         lSecondsFromUCT = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60;
    843         lSecondsFromUCT += (pString[3] - '0') * 10 + (pString[4] - '0');
    844         lSecondsFromUCT *= 60;
    845         if (*pString == '-')
    846             lSecondsFromUCT = -lSecondsFromUCT;
    847     }
    848 
    849     tm lTime;
    850     lTime.tm_sec = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
    851     lTime.tm_min = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
    852     lTime.tm_hour = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
    853     lTime.tm_mday = ((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0');
    854     lTime.tm_mon = (((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0')) - 1;
    855     lTime.tm_year = ((lBuffer[0] - '0') * 10) + (lBuffer[1] - '0');
    856     if (lTime.tm_year < 50)
    857         lTime.tm_year += 100; // RFC 2459
    858 
    859     QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday);
    860     QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec);
    861     QDateTime result(resDate, resTime, Qt::UTC);
    862     result = result.addSecs(lSecondsFromUCT);
    863     return result;
     905        qWarning("unsupported date format detected");
     906        return QDateTime();
     907    }
     908
    864909}
    865910
  • trunk/src/network/ssl/qsslsocket_openssl_symbols_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    228228const EVP_CIPHER *q_EVP_des_ede3_cbc();
    229229int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c);
     230int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b);
     231int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);
    230232void q_EVP_PKEY_free(EVP_PKEY *a);
    231233RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a);
  • trunk/src/network/ssl/qsslsocket_p.h

    r651 r846  
    11/****************************************************************************
    22**
    3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
    44** All rights reserved.
    55** Contact: Nokia Corporation (qt-info@nokia.com)
     
    6767QT_BEGIN_NAMESPACE
    6868
     69#if defined(Q_OS_MAC)
     70#include <Security/SecCertificate.h>
     71#include <CoreFoundation/CFArray.h>
     72    typedef OSStatus (*PtrSecCertificateGetData)(SecCertificateRef, CSSM_DATA_PTR);
     73    typedef OSStatus (*PtrSecTrustSettingsCopyCertificates)(int, CFArrayRef*);
     74    typedef OSStatus (*PtrSecTrustCopyAnchorCertificates)(CFArrayRef*);
     75#elif defined(Q_OS_WIN)
     76#include <wincrypt.h>
     77#ifndef HCRYPTPROV_LEGACY
     78#define HCRYPTPROV_LEGACY HCRYPTPROV
     79#endif
     80#if defined(Q_OS_WINCE)
     81    typedef HCERTSTORE (WINAPI *PtrCertOpenSystemStoreW)(LPCSTR, DWORD, HCRYPTPROV_LEGACY, DWORD, const void*);
     82#else
     83    typedef HCERTSTORE (WINAPI *PtrCertOpenSystemStoreW)(HCRYPTPROV_LEGACY, LPCWSTR);
     84#endif
     85    typedef PCCERT_CONTEXT (WINAPI *PtrCertFindCertificateInStore)(HCERTSTORE, DWORD, DWORD, DWORD, const void*, PCCERT_CONTEXT);
     86    typedef BOOL (WINAPI *PtrCertCloseStore)(HCERTSTORE, DWORD);
     87#endif
     88
     89
     90
    6991class QSslSocketPrivate : public QTcpSocketPrivate
    7092{
     
    91113    QString verificationPeerName;
    92114
    93     static bool ensureInitialized();
     115    static bool supportsSsl();
     116    static void ensureInitialized();
    94117    static void deinitialize();
    95118    static QList<QSslCipher> defaultCiphers();
     
    107130    static void addDefaultCaCertificates(const QList<QSslCertificate> &certs);
    108131
     132#if defined(Q_OS_MAC)
     133    static PtrSecCertificateGetData ptrSecCertificateGetData;
     134    static PtrSecTrustSettingsCopyCertificates ptrSecTrustSettingsCopyCertificates;
     135    static PtrSecTrustCopyAnchorCertificates ptrSecTrustCopyAnchorCertificates;
     136#elif defined(Q_OS_WIN)
     137    static PtrCertOpenSystemStoreW ptrCertOpenSystemStoreW;
     138    static PtrCertFindCertificateInStore ptrCertFindCertificateInStore;
     139    static PtrCertCloseStore ptrCertCloseStore;
     140#endif
     141
    109142    // The socket itself, including private slots.
    110143    QTcpSocket *plainSocket;
    111144    void createPlainSocket(QIODevice::OpenMode openMode);
     145    static void pauseSocketNotifiers(QSslSocket*);
     146    static void resumeSocketNotifiers(QSslSocket*);
    112147    void _q_connectedSlot();
    113148    void _q_hostFoundSlot();
     
    127162    virtual void disconnected() = 0;
    128163    virtual QSslCipher sessionCipher() const = 0;
     164
     165private:
     166    static bool ensureLibraryLoaded();
     167    static void ensureCiphersAndCertsLoaded();
     168
     169    static bool s_libraryLoaded;
     170    static bool s_loadedCiphersAndCerts;
    129171};
    130172
  • trunk/src/network/ssl/ssl.pri

    r788 r846  
    3232               ssl/qsslsocket_openssl_symbols.cpp
    3333
    34     # Include Qt's default CA bundle
    35     RESOURCES += network.qrc
    36 
    3734    # Add optional SSL libs
    3835    LIBS_PRIVATE += $$OPENSSL_LIBS
Note: See TracChangeset for help on using the changeset viewer.