src/network/access/qnetworkaccessmanager.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtNetwork module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qnetworkaccessmanager.h"
       
    43 #include "qnetworkaccessmanager_p.h"
       
    44 #include "qnetworkrequest.h"
       
    45 #include "qnetworkreply.h"
       
    46 #include "qnetworkreply_p.h"
       
    47 #include "qnetworkcookie.h"
       
    48 #include "qabstractnetworkcache.h"
       
    49 
       
    50 #include "qnetworkaccesshttpbackend_p.h"
       
    51 #include "qnetworkaccessftpbackend_p.h"
       
    52 #include "qnetworkaccessfilebackend_p.h"
       
    53 #include "qnetworkaccessdatabackend_p.h"
       
    54 #include "qnetworkaccessdebugpipebackend_p.h"
       
    55 
       
    56 #include "QtCore/qbuffer.h"
       
    57 #include "QtCore/qurl.h"
       
    58 #include "QtCore/qvector.h"
       
    59 #include "QtNetwork/qauthenticator.h"
       
    60 #include "QtNetwork/qsslconfiguration.h"
       
    61 
       
    62 QT_BEGIN_NAMESPACE
       
    63 
       
    64 #ifndef QT_NO_HTTP
       
    65 Q_GLOBAL_STATIC(QNetworkAccessHttpBackendFactory, httpBackend)
       
    66 #endif // QT_NO_HTTP
       
    67 Q_GLOBAL_STATIC(QNetworkAccessFileBackendFactory, fileBackend)
       
    68 Q_GLOBAL_STATIC(QNetworkAccessDataBackendFactory, dataBackend)
       
    69 #ifndef QT_NO_FTP
       
    70 Q_GLOBAL_STATIC(QNetworkAccessFtpBackendFactory, ftpBackend)
       
    71 #endif // QT_NO_FTP
       
    72 
       
    73 #ifdef QT_BUILD_INTERNAL
       
    74 Q_GLOBAL_STATIC(QNetworkAccessDebugPipeBackendFactory, debugpipeBackend)
       
    75 #endif
       
    76 
       
    77 static void ensureInitialized()
       
    78 {
       
    79 #ifndef QT_NO_HTTP
       
    80     (void) httpBackend();
       
    81 #endif // QT_NO_HTTP
       
    82     (void) dataBackend();
       
    83 #ifndef QT_NO_FTP
       
    84     (void) ftpBackend();
       
    85 #endif
       
    86 
       
    87 #ifdef QT_BUILD_INTERNAL
       
    88     (void) debugpipeBackend();
       
    89 #endif
       
    90 
       
    91     // leave this one last since it will query the special QAbstractFileEngines
       
    92     (void) fileBackend();
       
    93 }
       
    94 
       
    95 /*!
       
    96     \class QNetworkAccessManager
       
    97     \brief The QNetworkAccessManager class allows the application to
       
    98     send network requests and receive replies
       
    99     \since 4.4
       
   100 
       
   101     \ingroup network
       
   102     \inmodule QtNetwork
       
   103     \reentrant
       
   104 
       
   105     The Network Access API is constructed around one QNetworkAccessManager
       
   106     object, which holds the common configuration and settings for the requests
       
   107     it sends. It contains the proxy and cache configuration, as well as the
       
   108     signals related to such issues, and reply signals that can be used to
       
   109     monitor the progress of a network operation.
       
   110 
       
   111     Once a QNetworkAccessManager object has been created, the application can
       
   112     use it to send requests over the network. A group of standard functions
       
   113     are supplied that take a request and optional data, and each return a
       
   114     QNetworkReply object. The returned object is used to obtain any data
       
   115     returned in response to the corresponding request.
       
   116 
       
   117     A simple download off the network could be accomplished with:
       
   118     \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 0
       
   119 
       
   120     When the \tt replyFinished slot above is called, the parameter it
       
   121     takes is the QNetworkReply object containing the downloaded data
       
   122     as well as meta-data (headers, etc.).
       
   123 
       
   124     \note After the request has finished, it is the responsibility of the user
       
   125     to delete the QNetworkReply object at an appropriate time. Do not directly
       
   126     delete it inside the slot connected to finished(). You can use the
       
   127     deleteLater() function.
       
   128 
       
   129     A more involved example, assuming the manager is already existent,
       
   130     can be:
       
   131     \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 1
       
   132 
       
   133     \sa QNetworkRequest, QNetworkReply, QNetworkProxy
       
   134 */
       
   135 
       
   136 /*!
       
   137     \enum QNetworkAccessManager::Operation
       
   138 
       
   139     Indicates the operation this reply is processing.
       
   140 
       
   141     \value HeadOperation        retrieve headers operation (created
       
   142     with head())
       
   143 
       
   144     \value GetOperation         retrieve headers and download contents
       
   145     (created with get())
       
   146 
       
   147     \value PutOperation         upload contents operation (created
       
   148     with put())
       
   149 
       
   150     \value PostOperation        send the contents of an HTML form for
       
   151     processing via HTTP POST (created with post())
       
   152 
       
   153     \value DeleteOperation      delete contents operation (created with
       
   154     deleteResource())
       
   155 
       
   156     \omitvalue UnknownOperation
       
   157 
       
   158     \sa QNetworkReply::operation()
       
   159 */
       
   160 
       
   161 /*!
       
   162     \fn void QNetworkAccessManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
       
   163 
       
   164     This signal is emitted whenever a proxy requests authentication
       
   165     and QNetworkAccessManager cannot find a valid, cached
       
   166     credential. The slot connected to this signal should fill in the
       
   167     credentials for the proxy \a proxy in the \a authenticator object.
       
   168 
       
   169     QNetworkAccessManager will cache the credentials internally. The
       
   170     next time the proxy requests authentication, QNetworkAccessManager
       
   171     will automatically send the same credential without emitting the
       
   172     proxyAuthenticationRequired signal again.
       
   173 
       
   174     If the proxy rejects the credentials, QNetworkAccessManager will
       
   175     emit the signal again.
       
   176 
       
   177     \sa proxy(), setProxy(), authenticationRequired()
       
   178 */
       
   179 
       
   180 /*!
       
   181     \fn void QNetworkAccessManager::authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
       
   182 
       
   183     This signal is emitted whenever a final server requests
       
   184     authentication before it delivers the requested contents. The slot
       
   185     connected to this signal should fill the credentials for the
       
   186     contents (which can be determined by inspecting the \a reply
       
   187     object) in the \a authenticator object.
       
   188 
       
   189     QNetworkAccessManager will cache the credentials internally and
       
   190     will send the same values if the server requires authentication
       
   191     again, without emitting the authenticationRequired() signal. If it
       
   192     rejects the credentials, this signal will be emitted again.
       
   193 
       
   194     \sa proxyAuthenticationRequired()
       
   195 */
       
   196 
       
   197 /*!
       
   198     \fn void QNetworkAccessManager::finished(QNetworkReply *reply)
       
   199 
       
   200     This signal is emitted whenever a pending network reply is
       
   201     finished. The \a reply parameter will contain a pointer to the
       
   202     reply that has just finished. This signal is emitted in tandem
       
   203     with the QNetworkReply::finished() signal.
       
   204 
       
   205     See QNetworkReply::finished() for information on the status that
       
   206     the object will be in.
       
   207 
       
   208     \note Do not delete the \a reply object in the slot connected to this
       
   209     signal. Use deleteLater().
       
   210 
       
   211     \sa QNetworkReply::finished(), QNetworkReply::error()
       
   212 */
       
   213 
       
   214 /*!
       
   215     \fn void QNetworkAccessManager::sslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
       
   216 
       
   217     This signal is emitted if the SSL/TLS session encountered errors
       
   218     during the set up, including certificate verification errors. The
       
   219     \a errors parameter contains the list of errors and \a reply is
       
   220     the QNetworkReply that is encountering these errors.
       
   221 
       
   222     To indicate that the errors are not fatal and that the connection
       
   223     should proceed, the QNetworkReply::ignoreSslErrors() function should be called
       
   224     from the slot connected to this signal. If it is not called, the
       
   225     SSL session will be torn down before any data is exchanged
       
   226     (including the URL).
       
   227 
       
   228     This signal can be used to display an error message to the user
       
   229     indicating that security may be compromised and display the
       
   230     SSL settings (see sslConfiguration() to obtain it). If the user
       
   231     decides to proceed after analyzing the remote certificate, the
       
   232     slot should call ignoreSslErrors().
       
   233 
       
   234     \sa QSslSocket::sslErrors(), QNetworkReply::sslErrors(),
       
   235     QNetworkReply::sslConfiguration(), QNetworkReply::ignoreSslErrors()
       
   236 */
       
   237 
       
   238 class QNetworkAuthenticationCredential
       
   239 {
       
   240 public:
       
   241     QString domain;
       
   242     QString user;
       
   243     QString password;
       
   244 };
       
   245 Q_DECLARE_TYPEINFO(QNetworkAuthenticationCredential, Q_MOVABLE_TYPE);
       
   246 inline bool operator<(const QNetworkAuthenticationCredential &t1, const QString &t2)
       
   247 { return t1.domain < t2; }
       
   248 
       
   249 class QNetworkAuthenticationCache: private QVector<QNetworkAuthenticationCredential>,
       
   250                                    public QNetworkAccessCache::CacheableObject
       
   251 {
       
   252 public:
       
   253     QNetworkAuthenticationCache()
       
   254     {
       
   255         setExpires(false);
       
   256         setShareable(true);
       
   257         reserve(1);
       
   258     }
       
   259 
       
   260     QNetworkAuthenticationCredential *findClosestMatch(const QString &domain)
       
   261     {
       
   262         iterator it = qLowerBound(begin(), end(), domain);
       
   263         if (it == end() && !isEmpty())
       
   264             --it;
       
   265         if (it == end() || !domain.startsWith(it->domain))
       
   266             return 0;
       
   267         return &*it;
       
   268     }
       
   269 
       
   270     void insert(const QString &domain, const QString &user, const QString &password)
       
   271     {
       
   272         QNetworkAuthenticationCredential *closestMatch = findClosestMatch(domain);
       
   273         if (closestMatch && closestMatch->domain == domain) {
       
   274             // we're overriding the current credentials
       
   275             closestMatch->user = user;
       
   276             closestMatch->password = password;
       
   277         } else {
       
   278             QNetworkAuthenticationCredential newCredential;
       
   279             newCredential.domain = domain;
       
   280             newCredential.user = user;
       
   281             newCredential.password = password;
       
   282 
       
   283             if (closestMatch)
       
   284                 QVector<QNetworkAuthenticationCredential>::insert(++closestMatch, newCredential);
       
   285             else
       
   286                 QVector<QNetworkAuthenticationCredential>::insert(end(), newCredential);
       
   287         }
       
   288     }
       
   289 
       
   290     virtual void dispose() { delete this; }
       
   291 };
       
   292 
       
   293 #ifndef QT_NO_NETWORKPROXY
       
   294 static QByteArray proxyAuthenticationKey(const QNetworkProxy &proxy, const QString &realm)
       
   295 {
       
   296     QUrl key;
       
   297 
       
   298     switch (proxy.type()) {
       
   299     case QNetworkProxy::Socks5Proxy:
       
   300         key.setScheme(QLatin1String("proxy-socks5"));
       
   301         break;
       
   302 
       
   303     case QNetworkProxy::HttpProxy:
       
   304     case QNetworkProxy::HttpCachingProxy:
       
   305         key.setScheme(QLatin1String("proxy-http"));
       
   306         break;
       
   307 
       
   308     case QNetworkProxy::FtpCachingProxy:
       
   309         key.setScheme(QLatin1String("proxy-ftp"));
       
   310         break;
       
   311 
       
   312     case QNetworkProxy::DefaultProxy:
       
   313     case QNetworkProxy::NoProxy:
       
   314         // shouldn't happen
       
   315         return QByteArray();
       
   316 
       
   317         // no default:
       
   318         // let there be errors if a new proxy type is added in the future
       
   319     }
       
   320 
       
   321     if (key.scheme().isEmpty())
       
   322         // proxy type not handled
       
   323         return QByteArray();
       
   324 
       
   325     key.setUserName(proxy.user());
       
   326     key.setHost(proxy.hostName());
       
   327     key.setPort(proxy.port());
       
   328     key.setFragment(realm);
       
   329     return "auth:" + key.toEncoded();
       
   330 }
       
   331 #endif
       
   332 
       
   333 static inline QByteArray authenticationKey(const QUrl &url, const QString &realm)
       
   334 {
       
   335     QUrl copy = url;
       
   336     copy.setFragment(realm);
       
   337     return "auth:" + copy.toEncoded(QUrl::RemovePassword | QUrl::RemovePath | QUrl::RemoveQuery);
       
   338 }
       
   339 
       
   340 /*!
       
   341     Constructs a QNetworkAccessManager object that is the center of
       
   342     the Network Access API and sets \a parent as the parent object.
       
   343 */
       
   344 QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
       
   345     : QObject(*new QNetworkAccessManagerPrivate, parent)
       
   346 {
       
   347     ensureInitialized();
       
   348 }
       
   349 
       
   350 /*!
       
   351     Destroys the QNetworkAccessManager object and frees up any
       
   352     resources. Note that QNetworkReply objects that are returned from
       
   353     this class have this object set as their parents, which means that
       
   354     they will be deleted along with it if you don't call
       
   355     QObject::setParent() on them.
       
   356 */
       
   357 QNetworkAccessManager::~QNetworkAccessManager()
       
   358 {
       
   359 #ifndef QT_NO_NETWORKPROXY
       
   360     delete d_func()->proxyFactory;
       
   361 #endif
       
   362 }
       
   363 
       
   364 #ifndef QT_NO_NETWORKPROXY
       
   365 /*!
       
   366     Returns the QNetworkProxy that the requests sent using this
       
   367     QNetworkAccessManager object will use. The default value for the
       
   368     proxy is QNetworkProxy::DefaultProxy.
       
   369 
       
   370     \sa setProxy(), setProxyFactory(), proxyAuthenticationRequired()
       
   371 */
       
   372 QNetworkProxy QNetworkAccessManager::proxy() const
       
   373 {
       
   374     return d_func()->proxy;
       
   375 }
       
   376 
       
   377 /*!
       
   378     Sets the proxy to be used in future requests to be \a proxy. This
       
   379     does not affect requests that have already been sent. The
       
   380     proxyAuthenticationRequired() signal will be emitted if the proxy
       
   381     requests authentication.
       
   382 
       
   383     A proxy set with this function will be used for all requests
       
   384     issued by QNetworkAccessManager. In some cases, it might be
       
   385     necessary to select different proxies depending on the type of
       
   386     request being sent or the destination host. If that's the case,
       
   387     you should consider using setProxyFactory().
       
   388 
       
   389     \sa proxy(), proxyAuthenticationRequired()
       
   390 */
       
   391 void QNetworkAccessManager::setProxy(const QNetworkProxy &proxy)
       
   392 {
       
   393     Q_D(QNetworkAccessManager);
       
   394     delete d->proxyFactory;
       
   395     d->proxy = proxy;
       
   396     d->proxyFactory = 0;
       
   397 }
       
   398 
       
   399 /*!
       
   400     \fn QNetworkProxyFactory *QNetworkAccessManager::proxyFactory() const
       
   401     \since 4.5
       
   402 
       
   403     Returns the proxy factory that this QNetworkAccessManager object
       
   404     is using to determine the proxies to be used for requests.
       
   405 
       
   406     Note that the pointer returned by this function is managed by
       
   407     QNetworkAccessManager and could be deleted at any time.
       
   408 
       
   409     \sa setProxyFactory(), proxy()
       
   410 */
       
   411 QNetworkProxyFactory *QNetworkAccessManager::proxyFactory() const
       
   412 {
       
   413     return d_func()->proxyFactory;
       
   414 }
       
   415 
       
   416 /*!
       
   417     \since 4.5
       
   418 
       
   419     Sets the proxy factory for this class to be \a factory. A proxy
       
   420     factory is used to determine a more specific list of proxies to be
       
   421     used for a given request, instead of trying to use the same proxy
       
   422     value for all requests.
       
   423 
       
   424     All queries sent by QNetworkAccessManager will have type
       
   425     QNetworkProxyQuery::UrlRequest.
       
   426 
       
   427     For example, a proxy factory could apply the following rules:
       
   428     \list
       
   429       \o if the target address is in the local network (for example,
       
   430          if the hostname contains no dots or if it's an IP address in
       
   431          the organization's range), return QNetworkProxy::NoProxy
       
   432       \o if the request is FTP, return an FTP proxy
       
   433       \o if the request is HTTP or HTTPS, then return an HTTP proxy
       
   434       \o otherwise, return a SOCKSv5 proxy server
       
   435     \endlist
       
   436 
       
   437     The lifetime of the object \a factory will be managed by
       
   438     QNetworkAccessManager. It will delete the object when necessary.
       
   439 
       
   440     \note If a specific proxy is set with setProxy(), the factory will not
       
   441     be used.
       
   442 
       
   443     \sa proxyFactory(), setProxy(), QNetworkProxyQuery
       
   444 */
       
   445 void QNetworkAccessManager::setProxyFactory(QNetworkProxyFactory *factory)
       
   446 {
       
   447     Q_D(QNetworkAccessManager);
       
   448     delete d->proxyFactory;
       
   449     d->proxyFactory = factory;
       
   450     d->proxy = QNetworkProxy();
       
   451 }
       
   452 #endif
       
   453 
       
   454 /*!
       
   455     \since 4.5
       
   456 
       
   457     Returns the cache that is used to store data obtained from the network.
       
   458 
       
   459     \sa setCache()
       
   460 */
       
   461 QAbstractNetworkCache *QNetworkAccessManager::cache() const
       
   462 {
       
   463     Q_D(const QNetworkAccessManager);
       
   464     return d->networkCache;
       
   465 }
       
   466 
       
   467 /*!
       
   468     \since 4.5
       
   469 
       
   470     Sets the manager's network cache to be the \a cache specified. The cache
       
   471     is used for all requests dispatched by the manager.
       
   472 
       
   473     Use this function to set the network cache object to a class that implements
       
   474     additional features, like saving the cookies to permanent storage.
       
   475 
       
   476     \note QNetworkAccessManager takes ownership of the \a cache object.
       
   477 
       
   478     QNetworkAccessManager by default does not have a set cache.
       
   479     Qt provides a simple disk cache, QNetworkDiskCache, which can be used.
       
   480 
       
   481     \sa cache(), QNetworkRequest::CacheLoadControl
       
   482 */
       
   483 void QNetworkAccessManager::setCache(QAbstractNetworkCache *cache)
       
   484 {
       
   485     Q_D(QNetworkAccessManager);
       
   486     if (d->networkCache != cache) {
       
   487         delete d->networkCache;
       
   488         d->networkCache = cache;
       
   489         if (d->networkCache)
       
   490             d->networkCache->setParent(this);
       
   491     }
       
   492 }
       
   493 
       
   494 /*!
       
   495     Returns the QNetworkCookieJar that is used to store cookies
       
   496     obtained from the network as well as cookies that are about to be
       
   497     sent.
       
   498 
       
   499     \sa setCookieJar()
       
   500 */
       
   501 QNetworkCookieJar *QNetworkAccessManager::cookieJar() const
       
   502 {
       
   503     Q_D(const QNetworkAccessManager);
       
   504     if (!d->cookieJar)
       
   505         d->createCookieJar();
       
   506     return d->cookieJar;
       
   507 }
       
   508 
       
   509 /*!
       
   510     Sets the manager's cookie jar to be the \a cookieJar specified.
       
   511     The cookie jar is used by all requests dispatched by the manager.
       
   512 
       
   513     Use this function to set the cookie jar object to a class that
       
   514     implements additional features, like saving the cookies to permanent
       
   515     storage.
       
   516 
       
   517     \note QNetworkAccessManager takes ownership of the \a cookieJar object.
       
   518 
       
   519     QNetworkAccessManager will set the parent of the \a cookieJar
       
   520     passed to itself, so that the cookie jar is deleted when this
       
   521     object is deleted as well. If you want to share cookie jars
       
   522     between different QNetworkAccessManager objects, you may want to
       
   523     set the cookie jar's parent to 0 after calling this function.
       
   524 
       
   525     QNetworkAccessManager by default does not implement any cookie
       
   526     policy of its own: it accepts all cookies sent by the server, as
       
   527     long as they are well formed and meet the minimum security
       
   528     requirements (cookie domain matches the request's and cookie path
       
   529     matches the request's). In order to implement your own security
       
   530     policy, override the QNetworkCookieJar::cookiesForUrl() and
       
   531     QNetworkCookieJar::setCookiesFromUrl() virtual functions. Those
       
   532     functions are called by QNetworkAccessManager when it detects a
       
   533     new cookie.
       
   534 
       
   535     \sa cookieJar(), QNetworkCookieJar::cookiesForUrl(), QNetworkCookieJar::setCookiesFromUrl()
       
   536 */
       
   537 void QNetworkAccessManager::setCookieJar(QNetworkCookieJar *cookieJar)
       
   538 {
       
   539     Q_D(QNetworkAccessManager);
       
   540     d->cookieJarCreated = true;
       
   541     if (d->cookieJar != cookieJar) {
       
   542         if (d->cookieJar && d->cookieJar->parent() == this)
       
   543             delete d->cookieJar;
       
   544         d->cookieJar = cookieJar;
       
   545         d->cookieJar->setParent(this);
       
   546     }
       
   547 }
       
   548 
       
   549 /*!
       
   550     Posts a request to obtain the network headers for \a request
       
   551     and returns a new QNetworkReply object which will contain such headers
       
   552 
       
   553     The function is named after the HTTP request associated (HEAD).
       
   554 */
       
   555 QNetworkReply *QNetworkAccessManager::head(const QNetworkRequest &request)
       
   556 {
       
   557     return d_func()->postProcess(createRequest(QNetworkAccessManager::HeadOperation, request));
       
   558 }
       
   559 
       
   560 /*!
       
   561     Posts a request to obtain the contents of the target \a request
       
   562     and returns a new QNetworkReply object opened for reading which emits the 
       
   563     \l{QIODevice::readyRead()}{readyRead()} signal whenever new data 
       
   564     arrives.
       
   565 
       
   566     The contents as well as associated headers will be downloaded.
       
   567 
       
   568     \sa post(), put(), deleteResource()
       
   569 */
       
   570 QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
       
   571 {
       
   572     return d_func()->postProcess(createRequest(QNetworkAccessManager::GetOperation, request));
       
   573 }
       
   574 
       
   575 /*!
       
   576     Sends an HTTP POST request to the destination specified by \a request
       
   577     and returns a new QNetworkReply object opened for reading that will 
       
   578     contain the reply sent by the server. The contents of  the \a data 
       
   579     device will be uploaded to the server.
       
   580 
       
   581     \a data must be open for reading and must remain valid until the 
       
   582     finished() signal is emitted for this reply.
       
   583 
       
   584     \note Sending a POST request on protocols other than HTTP and
       
   585     HTTPS is undefined and will probably fail.
       
   586 
       
   587     \sa get(), put(), deleteResource()
       
   588 */
       
   589 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data)
       
   590 {
       
   591     return d_func()->postProcess(createRequest(QNetworkAccessManager::PostOperation, request, data));
       
   592 }
       
   593 
       
   594 /*!
       
   595     \overload
       
   596 
       
   597     Sends the contents of the \a data byte array to the destination 
       
   598     specified by \a request.
       
   599 */
       
   600 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data)
       
   601 {
       
   602     QBuffer *buffer = new QBuffer;
       
   603     buffer->setData(data);
       
   604     buffer->open(QIODevice::ReadOnly);
       
   605 
       
   606     QNetworkReply *reply = post(request, buffer);
       
   607     buffer->setParent(reply);
       
   608     return reply;
       
   609 }
       
   610 
       
   611 /*!
       
   612     Uploads the contents of \a data to the destination \a request and
       
   613     returnes a new QNetworkReply object that will be open for reply.
       
   614 
       
   615     \a data must be opened for reading when this function is called
       
   616     and must remain valid until the finished() signal is emitted for
       
   617     this reply.
       
   618 
       
   619     Whether anything will be available for reading from the returned
       
   620     object is protocol dependent. For HTTP, the server may send a 
       
   621     small HTML page indicating the upload was successful (or not). 
       
   622     Other protocols will probably have content in their replies.
       
   623 
       
   624     \note For HTTP, this request will send a PUT request, which most servers
       
   625     do not allow. Form upload mechanisms, including that of uploading
       
   626     files through HTML forms, use the POST mechanism.
       
   627 
       
   628     \sa get(), post()
       
   629 */
       
   630 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QIODevice *data)
       
   631 {
       
   632     return d_func()->postProcess(createRequest(QNetworkAccessManager::PutOperation, request, data));
       
   633 }
       
   634 
       
   635 /*!
       
   636     \overload
       
   637     Sends the contents of the \a data byte array to the destination 
       
   638     specified by \a request.
       
   639 */
       
   640 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data)
       
   641 {
       
   642     QBuffer *buffer = new QBuffer;
       
   643     buffer->setData(data);
       
   644     buffer->open(QIODevice::ReadOnly);
       
   645 
       
   646     QNetworkReply *reply = put(request, buffer);
       
   647     buffer->setParent(reply);
       
   648     return reply;
       
   649 }
       
   650 
       
   651 /*!
       
   652     \since 4.6
       
   653 
       
   654     Sends a request to delete the resource identified by the URL of \a request.
       
   655 
       
   656     \note This feature is currently available for HTTP only, performing an 
       
   657     HTTP DELETE request.
       
   658 
       
   659     \sa get(), post(), put()
       
   660 */
       
   661 QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &request)
       
   662 {
       
   663     return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
       
   664 }
       
   665 
       
   666 /*!
       
   667     Returns a new QNetworkReply object to handle the operation \a op
       
   668     and request \a req. The device \a outgoingData is always 0 for Get and
       
   669     Head requests, but is the value passed to post() and put() in
       
   670     those operations (the QByteArray variants will pass a QBuffer
       
   671     object).
       
   672 
       
   673     The default implementation calls QNetworkCookieJar::cookiesForUrl()
       
   674     on the cookie jar set with setCookieJar() to obtain the cookies to
       
   675     be sent to the remote server.
       
   676 
       
   677     The returned object must be in an open state.
       
   678 */
       
   679 QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op,
       
   680                                                     const QNetworkRequest &req,
       
   681                                                     QIODevice *outgoingData)
       
   682 {
       
   683     Q_D(QNetworkAccessManager);
       
   684     QNetworkRequest request = req;
       
   685     if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() &&
       
   686         outgoingData && !outgoingData->isSequential()) {
       
   687         // request has no Content-Length
       
   688         // but the data that is outgoing is random-access
       
   689         request.setHeader(QNetworkRequest::ContentLengthHeader, outgoingData->size());
       
   690     }
       
   691     if (d->cookieJar) {
       
   692         QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url());
       
   693         if (!cookies.isEmpty())
       
   694             request.setHeader(QNetworkRequest::CookieHeader, qVariantFromValue(cookies));
       
   695     }
       
   696 
       
   697     // first step: create the reply
       
   698     QUrl url = request.url();
       
   699     QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
       
   700     QNetworkReplyImplPrivate *priv = reply->d_func();
       
   701     priv->manager = this;
       
   702 
       
   703     // second step: fetch cached credentials
       
   704     QNetworkAuthenticationCredential *cred = d->fetchCachedCredentials(url);
       
   705     if (cred) {
       
   706         url.setUserName(cred->user);
       
   707         url.setPassword(cred->password);
       
   708         priv->urlForLastAuthentication = url;
       
   709     }
       
   710 
       
   711     // third step: find a backend
       
   712     priv->backend = d->findBackend(op, request);
       
   713 
       
   714     // fourth step: setup the reply
       
   715     priv->setup(op, request, outgoingData);
       
   716 #ifndef QT_NO_NETWORKPROXY
       
   717     QList<QNetworkProxy> proxyList = d->queryProxy(QNetworkProxyQuery(request.url()));
       
   718     priv->proxyList = proxyList;
       
   719 #endif
       
   720     if (priv->backend) {
       
   721         priv->backend->setParent(reply);
       
   722         priv->backend->reply = priv;
       
   723     }
       
   724 
       
   725 #ifndef QT_NO_OPENSSL
       
   726     reply->setSslConfiguration(request.sslConfiguration());
       
   727 #endif
       
   728     return reply;
       
   729 }
       
   730 
       
   731 void QNetworkAccessManagerPrivate::_q_replyFinished()
       
   732 {
       
   733     Q_Q(QNetworkAccessManager);
       
   734     QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
       
   735     if (reply)
       
   736         emit q->finished(reply);
       
   737 }
       
   738 
       
   739 void QNetworkAccessManagerPrivate::_q_replySslErrors(const QList<QSslError> &errors)
       
   740 {
       
   741 #ifndef QT_NO_OPENSSL
       
   742     Q_Q(QNetworkAccessManager);
       
   743     QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
       
   744     if (reply)
       
   745         emit q->sslErrors(reply, errors);
       
   746 #else
       
   747     Q_UNUSED(errors);
       
   748 #endif
       
   749 }
       
   750 
       
   751 QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply)
       
   752 {
       
   753     Q_Q(QNetworkAccessManager);
       
   754     QNetworkReplyPrivate::setManager(reply, q);
       
   755     q->connect(reply, SIGNAL(finished()), SLOT(_q_replyFinished()));
       
   756 #ifndef QT_NO_OPENSSL
       
   757     /* In case we're compiled without SSL support, we don't have this signal and we need to
       
   758      * avoid getting a connection error. */
       
   759     q->connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(_q_replySslErrors(QList<QSslError>)));
       
   760 #endif
       
   761 
       
   762     return reply;
       
   763 }
       
   764 
       
   765 void QNetworkAccessManagerPrivate::createCookieJar() const
       
   766 {
       
   767     if (!cookieJarCreated) {
       
   768         // keep the ugly hack in here
       
   769         QNetworkAccessManagerPrivate *that = const_cast<QNetworkAccessManagerPrivate *>(this);
       
   770         that->cookieJar = new QNetworkCookieJar(that->q_func());
       
   771         that->cookieJarCreated = true;
       
   772     }
       
   773 }
       
   774 
       
   775 void QNetworkAccessManagerPrivate::authenticationRequired(QNetworkAccessBackend *backend,
       
   776                                                           QAuthenticator *authenticator)
       
   777 {
       
   778     Q_Q(QNetworkAccessManager);
       
   779 
       
   780     // FIXME: Add support for domains (i.e., the leading path)
       
   781     QUrl url = backend->reply->url;
       
   782 
       
   783     // don't try the cache for the same URL twice in a row
       
   784     // being called twice for the same URL means the authentication failed
       
   785     if (url != backend->reply->urlForLastAuthentication) {
       
   786         QNetworkAuthenticationCredential *cred = fetchCachedCredentials(url, authenticator);
       
   787         if (cred) {
       
   788             authenticator->setUser(cred->user);
       
   789             authenticator->setPassword(cred->password);
       
   790             backend->reply->urlForLastAuthentication = url;
       
   791             return;
       
   792         }
       
   793     }
       
   794 
       
   795     backend->reply->urlForLastAuthentication = url;
       
   796     emit q->authenticationRequired(backend->reply->q_func(), authenticator);
       
   797     addCredentials(url, authenticator);
       
   798 }
       
   799 
       
   800 #ifndef QT_NO_NETWORKPROXY
       
   801 void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(QNetworkAccessBackend *backend,
       
   802                                                                const QNetworkProxy &proxy,
       
   803                                                                QAuthenticator *authenticator)
       
   804 {
       
   805     Q_Q(QNetworkAccessManager);
       
   806     // ### FIXME Tracking of successful authentications
       
   807     // This code is a bit broken right now for SOCKS authentication
       
   808     // first request: proxyAuthenticationRequired gets emitted, credentials gets saved
       
   809     // second request: (proxy != backend->reply->lastProxyAuthentication) does not evaluate to true,
       
   810     //      proxyAuthenticationRequired gets emitted again
       
   811     // possible solution: some tracking inside the authenticator
       
   812     //      or a new function proxyAuthenticationSucceeded(true|false)
       
   813     if (proxy != backend->reply->lastProxyAuthentication) {
       
   814         QNetworkAuthenticationCredential *cred = fetchCachedCredentials(proxy);
       
   815         if (cred) {
       
   816             authenticator->setUser(cred->user);
       
   817             authenticator->setPassword(cred->password);
       
   818             return;
       
   819         }
       
   820     }
       
   821 
       
   822     backend->reply->lastProxyAuthentication = proxy;
       
   823     emit q->proxyAuthenticationRequired(proxy, authenticator);
       
   824     addCredentials(proxy, authenticator);
       
   825 }
       
   826 
       
   827 void QNetworkAccessManagerPrivate::addCredentials(const QNetworkProxy &p,
       
   828                                                   const QAuthenticator *authenticator)
       
   829 {
       
   830     Q_ASSERT(authenticator);
       
   831     Q_ASSERT(p.type() != QNetworkProxy::DefaultProxy);
       
   832     Q_ASSERT(p.type() != QNetworkProxy::NoProxy);
       
   833 
       
   834     QString realm = authenticator->realm();
       
   835     QNetworkProxy proxy = p;
       
   836     proxy.setUser(authenticator->user());
       
   837     // Set two credentials: one with the username and one without
       
   838     do {
       
   839         // Set two credentials actually: one with and one without the realm
       
   840         do {
       
   841             QByteArray cacheKey = proxyAuthenticationKey(proxy, realm);
       
   842             if (cacheKey.isEmpty())
       
   843                 return;             // should not happen
       
   844 
       
   845             QNetworkAuthenticationCache *auth = new QNetworkAuthenticationCache;
       
   846             auth->insert(QString(), authenticator->user(), authenticator->password());
       
   847             objectCache.addEntry(cacheKey, auth); // replace the existing one, if there's any
       
   848 
       
   849             if (realm.isEmpty()) {
       
   850                 break;
       
   851             } else {
       
   852                 realm.clear();
       
   853             }
       
   854         } while (true);
       
   855 
       
   856         if (proxy.user().isEmpty())
       
   857             break;
       
   858         else
       
   859             proxy.setUser(QString());
       
   860     } while (true);
       
   861 }
       
   862 
       
   863 QNetworkAuthenticationCredential *
       
   864 QNetworkAccessManagerPrivate::fetchCachedCredentials(const QNetworkProxy &p,
       
   865                                                      const QAuthenticator *authenticator)
       
   866 {
       
   867     QNetworkProxy proxy = p;
       
   868     if (proxy.type() == QNetworkProxy::DefaultProxy) {
       
   869         proxy = QNetworkProxy::applicationProxy();
       
   870     }
       
   871     if (!proxy.password().isEmpty())
       
   872         return 0;               // no need to set credentials if it already has them
       
   873 
       
   874     QString realm;
       
   875     if (authenticator)
       
   876         realm = authenticator->realm();
       
   877 
       
   878     QByteArray cacheKey = proxyAuthenticationKey(proxy, realm);
       
   879     if (cacheKey.isEmpty())
       
   880         return 0;
       
   881     if (!objectCache.hasEntry(cacheKey))
       
   882         return 0;
       
   883 
       
   884     QNetworkAuthenticationCache *auth =
       
   885         static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey));
       
   886     QNetworkAuthenticationCredential *cred = auth->findClosestMatch(QString());
       
   887     objectCache.releaseEntry(cacheKey);
       
   888 
       
   889     // proxy cache credentials always have exactly one item
       
   890     Q_ASSERT_X(cred, "QNetworkAccessManager",
       
   891                "Internal inconsistency: found a cache key for a proxy, but it's empty");
       
   892     return cred;
       
   893 }
       
   894 
       
   895 QList<QNetworkProxy> QNetworkAccessManagerPrivate::queryProxy(const QNetworkProxyQuery &query)
       
   896 {
       
   897     QList<QNetworkProxy> proxies;
       
   898     if (proxyFactory) {
       
   899         proxies = proxyFactory->queryProxy(query);
       
   900         if (proxies.isEmpty()) {
       
   901             qWarning("QNetworkAccessManager: factory %p has returned an empty result set",
       
   902                      proxyFactory);
       
   903             proxies << QNetworkProxy::NoProxy;
       
   904         }
       
   905     } else if (proxy.type() == QNetworkProxy::DefaultProxy) {
       
   906         // no proxy set, query the application
       
   907         return QNetworkProxyFactory::proxyForQuery(query);
       
   908     } else {
       
   909         proxies << proxy;
       
   910     }
       
   911 
       
   912     return proxies;
       
   913 }
       
   914 #endif
       
   915 
       
   916 void QNetworkAccessManagerPrivate::addCredentials(const QUrl &url,
       
   917                                                   const QAuthenticator *authenticator)
       
   918 {
       
   919     Q_ASSERT(authenticator);
       
   920     QString domain = QString::fromLatin1("/"); // FIXME: make QAuthenticator return the domain
       
   921     QString realm = authenticator->realm();
       
   922 
       
   923     // Set two credentials actually: one with and one without the username in the URL
       
   924     QUrl copy = url;
       
   925     copy.setUserName(authenticator->user());
       
   926     do {
       
   927         QByteArray cacheKey = authenticationKey(copy, realm);
       
   928         if (objectCache.hasEntry(cacheKey)) {
       
   929             QNetworkAuthenticationCache *auth =
       
   930                 static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey));
       
   931             auth->insert(domain, authenticator->user(), authenticator->password());
       
   932             objectCache.releaseEntry(cacheKey);
       
   933         } else {
       
   934             QNetworkAuthenticationCache *auth = new QNetworkAuthenticationCache;
       
   935             auth->insert(domain, authenticator->user(), authenticator->password());
       
   936             objectCache.addEntry(cacheKey, auth);
       
   937         }
       
   938 
       
   939         if (copy.userName().isEmpty()) {
       
   940             break;
       
   941         } else {
       
   942             copy.setUserName(QString());
       
   943         }
       
   944     } while (true);
       
   945 }
       
   946 
       
   947 /*!
       
   948     Fetch the credential data from the credential cache.
       
   949 
       
   950     If auth is 0 (as it is when called from createRequest()), this will try to
       
   951     look up with an empty realm. That fails in most cases for HTTP (because the
       
   952     realm is seldom empty for HTTP challenges). In any case, QHttpNetworkConnection
       
   953     never sends the credentials on the first attempt: it needs to find out what
       
   954     authentication methods the server supports.
       
   955 
       
   956     For FTP, realm is always empty.
       
   957 */
       
   958 QNetworkAuthenticationCredential *
       
   959 QNetworkAccessManagerPrivate::fetchCachedCredentials(const QUrl &url,
       
   960                                                      const QAuthenticator *authentication)
       
   961 {
       
   962     if (!url.password().isEmpty())
       
   963         return 0;               // no need to set credentials if it already has them
       
   964 
       
   965     QString realm;
       
   966     if (authentication)
       
   967         realm = authentication->realm();
       
   968 
       
   969     QByteArray cacheKey = authenticationKey(url, realm);
       
   970     if (!objectCache.hasEntry(cacheKey))
       
   971         return 0;
       
   972 
       
   973     QNetworkAuthenticationCache *auth =
       
   974         static_cast<QNetworkAuthenticationCache *>(objectCache.requestEntryNow(cacheKey));
       
   975     QNetworkAuthenticationCredential *cred = auth->findClosestMatch(url.path());
       
   976     objectCache.releaseEntry(cacheKey);
       
   977     return cred;
       
   978 }
       
   979 
       
   980 void QNetworkAccessManagerPrivate::clearCache(QNetworkAccessManager *manager)
       
   981 {
       
   982     manager->d_func()->objectCache.clear();
       
   983 }
       
   984 
       
   985 QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate()
       
   986 {
       
   987 }
       
   988 
       
   989 QT_END_NAMESPACE
       
   990 
       
   991 #include "moc_qnetworkaccessmanager.cpp"