src/network/access/qhttp.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 //#define QHTTP_DEBUG
       
    43 
       
    44 #include <qplatformdefs.h>
       
    45 #include "qhttp.h"
       
    46 
       
    47 #ifndef QT_NO_HTTP
       
    48 # include "private/qobject_p.h"
       
    49 # include "qtcpsocket.h"
       
    50 # include "qsslsocket.h"
       
    51 # include "qtextstream.h"
       
    52 # include "qmap.h"
       
    53 # include "qlist.h"
       
    54 # include "qstring.h"
       
    55 # include "qstringlist.h"
       
    56 # include "qbuffer.h"
       
    57 # include "private/qringbuffer_p.h"
       
    58 # include "qcoreevent.h"
       
    59 # include "qurl.h"
       
    60 # include "qnetworkproxy.h"
       
    61 # include "qauthenticator.h"
       
    62 # include "qauthenticator_p.h"
       
    63 # include "qdebug.h"
       
    64 # include "qtimer.h"
       
    65 #endif
       
    66 
       
    67 #ifndef QT_NO_HTTP
       
    68 
       
    69 QT_BEGIN_NAMESPACE
       
    70 
       
    71 class QHttpNormalRequest;
       
    72 class QHttpRequest
       
    73 {
       
    74 public:
       
    75     QHttpRequest() : finished(false)
       
    76     { id = idCounter.fetchAndAddRelaxed(1); }
       
    77     virtual ~QHttpRequest()
       
    78     { }
       
    79 
       
    80     virtual void start(QHttp *) = 0;
       
    81     virtual bool hasRequestHeader();
       
    82     virtual QHttpRequestHeader requestHeader();
       
    83 
       
    84     virtual QIODevice *sourceDevice() = 0;
       
    85     virtual QIODevice *destinationDevice() = 0;
       
    86 
       
    87     int id;
       
    88     bool finished;
       
    89 
       
    90 private:
       
    91     static QBasicAtomicInt idCounter;
       
    92 };
       
    93 
       
    94 class QHttpPrivate : public QObjectPrivate
       
    95 {
       
    96 public:
       
    97     Q_DECLARE_PUBLIC(QHttp)
       
    98 
       
    99     inline QHttpPrivate()
       
   100         : socket(0), reconnectAttempts(2),
       
   101           deleteSocket(0), state(QHttp::Unconnected),
       
   102           error(QHttp::NoError), port(0), mode(QHttp::ConnectionModeHttp),
       
   103           toDevice(0), postDevice(0), bytesDone(0), chunkedSize(-1),
       
   104           repost(false), pendingPost(false)
       
   105     {
       
   106     }
       
   107 
       
   108     inline ~QHttpPrivate()
       
   109     {
       
   110         while (!pending.isEmpty())
       
   111             delete pending.takeFirst();
       
   112 
       
   113         if (deleteSocket)
       
   114             delete socket;
       
   115     }
       
   116 
       
   117     // private slots
       
   118     void _q_startNextRequest();
       
   119     void _q_slotReadyRead();
       
   120     void _q_slotConnected();
       
   121     void _q_slotError(QAbstractSocket::SocketError);
       
   122     void _q_slotClosed();
       
   123     void _q_slotBytesWritten(qint64 numBytes);
       
   124 #ifndef QT_NO_OPENSSL
       
   125     void _q_slotEncryptedBytesWritten(qint64 numBytes);
       
   126 #endif
       
   127     void _q_slotDoFinished();
       
   128     void _q_slotSendRequest();
       
   129     void _q_continuePost();
       
   130 
       
   131     int addRequest(QHttpNormalRequest *);
       
   132     int addRequest(QHttpRequest *);
       
   133     void finishedWithSuccess();
       
   134     void finishedWithError(const QString &detail, int errorCode);
       
   135 
       
   136     void init();
       
   137     void setState(int);
       
   138     void closeConn();
       
   139     void setSock(QTcpSocket *sock);
       
   140 
       
   141     void postMoreData();
       
   142 
       
   143     QTcpSocket *socket;
       
   144     int reconnectAttempts;
       
   145     bool deleteSocket;
       
   146     QList<QHttpRequest *> pending;
       
   147 
       
   148     QHttp::State state;
       
   149     QHttp::Error error;
       
   150     QString errorString;
       
   151 
       
   152     QString hostName;
       
   153     quint16 port;
       
   154     QHttp::ConnectionMode mode;
       
   155 
       
   156     QByteArray buffer;
       
   157     QIODevice *toDevice;
       
   158     QIODevice *postDevice;
       
   159 
       
   160     qint64 bytesDone;
       
   161     qint64 bytesTotal;
       
   162     qint64 chunkedSize;
       
   163 
       
   164     QHttpRequestHeader header;
       
   165 
       
   166     bool readHeader;
       
   167     QString headerStr;
       
   168     QHttpResponseHeader response;
       
   169 
       
   170     QRingBuffer rba;
       
   171 
       
   172 #ifndef QT_NO_NETWORKPROXY
       
   173     QNetworkProxy proxy;
       
   174     QAuthenticator proxyAuthenticator;
       
   175 #endif
       
   176     QAuthenticator authenticator;
       
   177     bool repost;
       
   178     bool hasFinishedWithError;
       
   179     bool pendingPost;
       
   180     QTimer post100ContinueTimer;
       
   181 };
       
   182 
       
   183 QBasicAtomicInt QHttpRequest::idCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
       
   184 
       
   185 bool QHttpRequest::hasRequestHeader()
       
   186 {
       
   187     return false;
       
   188 }
       
   189 
       
   190 QHttpRequestHeader QHttpRequest::requestHeader()
       
   191 {
       
   192     return QHttpRequestHeader();
       
   193 }
       
   194 
       
   195 /****************************************************
       
   196  *
       
   197  * QHttpNormalRequest
       
   198  *
       
   199  ****************************************************/
       
   200 
       
   201 class QHttpNormalRequest : public QHttpRequest
       
   202 {
       
   203 public:
       
   204     QHttpNormalRequest(const QHttpRequestHeader &h, QIODevice *d, QIODevice *t) :
       
   205         header(h), to(t)
       
   206     {
       
   207         is_ba = false;
       
   208         data.dev = d;
       
   209     }
       
   210 
       
   211     QHttpNormalRequest(const QHttpRequestHeader &h, QByteArray *d, QIODevice *t) :
       
   212         header(h), to(t)
       
   213     {
       
   214         is_ba = true;
       
   215         data.ba = d;
       
   216     }
       
   217 
       
   218     ~QHttpNormalRequest()
       
   219     {
       
   220         if (is_ba)
       
   221             delete data.ba;
       
   222     }
       
   223 
       
   224     void start(QHttp *);
       
   225     bool hasRequestHeader();
       
   226     QHttpRequestHeader requestHeader();
       
   227     inline void setRequestHeader(const QHttpRequestHeader &h) { header = h; }
       
   228 
       
   229     QIODevice *sourceDevice();
       
   230     QIODevice *destinationDevice();
       
   231 
       
   232 protected:
       
   233     QHttpRequestHeader header;
       
   234 
       
   235 private:
       
   236     union {
       
   237         QByteArray *ba;
       
   238         QIODevice *dev;
       
   239     } data;
       
   240     bool is_ba;
       
   241     QIODevice *to;
       
   242 };
       
   243 
       
   244 void QHttpNormalRequest::start(QHttp *http)
       
   245 {
       
   246     if (!http->d_func()->socket)
       
   247         http->d_func()->setSock(0);
       
   248     http->d_func()->header = header;
       
   249 
       
   250     if (is_ba) {
       
   251         http->d_func()->buffer = *data.ba;
       
   252         if (http->d_func()->buffer.size() >= 0)
       
   253             http->d_func()->header.setContentLength(http->d_func()->buffer.size());
       
   254 
       
   255         http->d_func()->postDevice = 0;
       
   256     } else {
       
   257         http->d_func()->buffer = QByteArray();
       
   258 
       
   259         if (data.dev && (data.dev->isOpen() || data.dev->open(QIODevice::ReadOnly))) {
       
   260             http->d_func()->postDevice = data.dev;
       
   261             if (http->d_func()->postDevice->size() >= 0)
       
   262                 http->d_func()->header.setContentLength(http->d_func()->postDevice->size());
       
   263         } else {
       
   264             http->d_func()->postDevice = 0;
       
   265         }
       
   266     }
       
   267 
       
   268     if (to && (to->isOpen() || to->open(QIODevice::WriteOnly)))
       
   269         http->d_func()->toDevice = to;
       
   270     else
       
   271         http->d_func()->toDevice = 0;
       
   272 
       
   273     http->d_func()->reconnectAttempts = 2;
       
   274     http->d_func()->_q_slotSendRequest();
       
   275 }
       
   276 
       
   277 bool QHttpNormalRequest::hasRequestHeader()
       
   278 {
       
   279     return true;
       
   280 }
       
   281 
       
   282 QHttpRequestHeader QHttpNormalRequest::requestHeader()
       
   283 {
       
   284     return header;
       
   285 }
       
   286 
       
   287 QIODevice *QHttpNormalRequest::sourceDevice()
       
   288 {
       
   289     if (is_ba)
       
   290         return 0;
       
   291     return data.dev;
       
   292 }
       
   293 
       
   294 QIODevice *QHttpNormalRequest::destinationDevice()
       
   295 {
       
   296     return to;
       
   297 }
       
   298 
       
   299 /****************************************************
       
   300  *
       
   301  * QHttpPGHRequest
       
   302  * (like a QHttpNormalRequest, but for the convenience
       
   303  * functions put(), get() and head() -- i.e. set the
       
   304  * host header field correctly before sending the
       
   305  * request)
       
   306  *
       
   307  ****************************************************/
       
   308 
       
   309 class QHttpPGHRequest : public QHttpNormalRequest
       
   310 {
       
   311 public:
       
   312     QHttpPGHRequest(const QHttpRequestHeader &h, QIODevice *d, QIODevice *t) :
       
   313         QHttpNormalRequest(h, d, t)
       
   314     { }
       
   315 
       
   316     QHttpPGHRequest(const QHttpRequestHeader &h, QByteArray *d, QIODevice *t) :
       
   317         QHttpNormalRequest(h, d, t)
       
   318     { }
       
   319 
       
   320     ~QHttpPGHRequest()
       
   321     { }
       
   322 
       
   323     void start(QHttp *);
       
   324 };
       
   325 
       
   326 void QHttpPGHRequest::start(QHttp *http)
       
   327 {
       
   328     if (http->d_func()->port && http->d_func()->port != 80)
       
   329 	header.setValue(QLatin1String("Host"), http->d_func()->hostName + QLatin1Char(':') + QString::number(http->d_func()->port));
       
   330     else
       
   331 	header.setValue(QLatin1String("Host"), http->d_func()->hostName);
       
   332     QHttpNormalRequest::start(http);
       
   333 }
       
   334 
       
   335 /****************************************************
       
   336  *
       
   337  * QHttpSetHostRequest
       
   338  *
       
   339  ****************************************************/
       
   340 
       
   341 class QHttpSetHostRequest : public QHttpRequest
       
   342 {
       
   343 public:
       
   344     QHttpSetHostRequest(const QString &h, quint16 p, QHttp::ConnectionMode m)
       
   345         : hostName(h), port(p), mode(m)
       
   346     { }
       
   347 
       
   348     void start(QHttp *);
       
   349 
       
   350     QIODevice *sourceDevice()
       
   351     { return 0; }
       
   352     QIODevice *destinationDevice()
       
   353     { return 0; }
       
   354 
       
   355 private:
       
   356     QString hostName;
       
   357     quint16 port;
       
   358     QHttp::ConnectionMode mode;
       
   359 };
       
   360 
       
   361 void QHttpSetHostRequest::start(QHttp *http)
       
   362 {
       
   363     http->d_func()->hostName = hostName;
       
   364     http->d_func()->port = port;
       
   365     http->d_func()->mode = mode;
       
   366 
       
   367 #ifdef QT_NO_OPENSSL
       
   368     if (mode == QHttp::ConnectionModeHttps) {
       
   369         // SSL requested but no SSL support compiled in
       
   370         http->d_func()->finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "HTTPS connection requested but SSL support not compiled in")),
       
   371                           QHttp::UnknownError);
       
   372         return;
       
   373     }
       
   374 #endif
       
   375 
       
   376     http->d_func()->finishedWithSuccess();
       
   377 }
       
   378 
       
   379 /****************************************************
       
   380  *
       
   381  * QHttpSetUserRequest
       
   382  *
       
   383  ****************************************************/
       
   384 
       
   385 class QHttpSetUserRequest : public QHttpRequest
       
   386 {
       
   387 public:
       
   388     QHttpSetUserRequest(const QString &userName, const QString &password) :
       
   389         user(userName), pass(password)
       
   390     { }
       
   391 
       
   392     void start(QHttp *);
       
   393 
       
   394     QIODevice *sourceDevice()
       
   395     { return 0; }
       
   396     QIODevice *destinationDevice()
       
   397     { return 0; }
       
   398 
       
   399 private:
       
   400     QString user;
       
   401     QString pass;
       
   402 };
       
   403 
       
   404 void QHttpSetUserRequest::start(QHttp *http)
       
   405 {
       
   406     http->d_func()->authenticator.setUser(user);
       
   407     http->d_func()->authenticator.setPassword(pass);
       
   408     http->d_func()->finishedWithSuccess();
       
   409 }
       
   410 
       
   411 #ifndef QT_NO_NETWORKPROXY
       
   412 
       
   413 /****************************************************
       
   414  *
       
   415  * QHttpSetProxyRequest
       
   416  *
       
   417  ****************************************************/
       
   418 
       
   419 class QHttpSetProxyRequest : public QHttpRequest
       
   420 {
       
   421 public:
       
   422     inline QHttpSetProxyRequest(const QNetworkProxy &proxy)
       
   423     {
       
   424         this->proxy = proxy;
       
   425     }
       
   426 
       
   427     inline void start(QHttp *http)
       
   428     {
       
   429         http->d_func()->proxy = proxy;
       
   430         QString user = proxy.user();
       
   431         if (!user.isEmpty())
       
   432             http->d_func()->proxyAuthenticator.setUser(user);
       
   433         QString password = proxy.password();
       
   434         if (!password.isEmpty())
       
   435             http->d_func()->proxyAuthenticator.setPassword(password);
       
   436         http->d_func()->finishedWithSuccess();
       
   437     }
       
   438 
       
   439     inline QIODevice *sourceDevice()
       
   440     { return 0; }
       
   441     inline QIODevice *destinationDevice()
       
   442     { return 0; }
       
   443 private:
       
   444     QNetworkProxy proxy;
       
   445 };
       
   446 
       
   447 #endif // QT_NO_NETWORKPROXY
       
   448 
       
   449 /****************************************************
       
   450  *
       
   451  * QHttpSetSocketRequest
       
   452  *
       
   453  ****************************************************/
       
   454 
       
   455 class QHttpSetSocketRequest : public QHttpRequest
       
   456 {
       
   457 public:
       
   458     QHttpSetSocketRequest(QTcpSocket *s) : socket(s)
       
   459     { }
       
   460 
       
   461     void start(QHttp *);
       
   462 
       
   463     QIODevice *sourceDevice()
       
   464     { return 0; }
       
   465     QIODevice *destinationDevice()
       
   466     { return 0; }
       
   467 
       
   468 private:
       
   469     QTcpSocket *socket;
       
   470 };
       
   471 
       
   472 void QHttpSetSocketRequest::start(QHttp *http)
       
   473 {
       
   474     http->d_func()->setSock(socket);
       
   475     http->d_func()->finishedWithSuccess();
       
   476 }
       
   477 
       
   478 /****************************************************
       
   479  *
       
   480  * QHttpCloseRequest
       
   481  *
       
   482  ****************************************************/
       
   483 
       
   484 class QHttpCloseRequest : public QHttpRequest
       
   485 {
       
   486 public:
       
   487     QHttpCloseRequest()
       
   488     { }
       
   489     void start(QHttp *);
       
   490 
       
   491     QIODevice *sourceDevice()
       
   492     { return 0; }
       
   493     QIODevice *destinationDevice()
       
   494     { return 0; }
       
   495 };
       
   496 
       
   497 void QHttpCloseRequest::start(QHttp *http)
       
   498 {
       
   499     http->d_func()->closeConn();
       
   500 }
       
   501 
       
   502 class QHttpHeaderPrivate
       
   503 {
       
   504     Q_DECLARE_PUBLIC(QHttpHeader)
       
   505 public:
       
   506     inline virtual ~QHttpHeaderPrivate() {}
       
   507 
       
   508     QList<QPair<QString, QString> > values;
       
   509     bool valid;
       
   510     QHttpHeader *q_ptr;
       
   511 };
       
   512 
       
   513 /****************************************************
       
   514  *
       
   515  * QHttpHeader
       
   516  *
       
   517  ****************************************************/
       
   518 
       
   519 /*!
       
   520     \class QHttpHeader
       
   521     \obsolete
       
   522     \brief The QHttpHeader class contains header information for HTTP.
       
   523 
       
   524     \ingroup network
       
   525     \inmodule QtNetwork
       
   526 
       
   527     In most cases you should use the more specialized derivatives of
       
   528     this class, QHttpResponseHeader and QHttpRequestHeader, rather
       
   529     than directly using QHttpHeader.
       
   530 
       
   531     QHttpHeader provides the HTTP header fields. A HTTP header field
       
   532     consists of a name followed by a colon, a single space, and the
       
   533     field value. (See RFC 1945.) Field names are case-insensitive. A
       
   534     typical header field looks like this:
       
   535     \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 0
       
   536 
       
   537     In the API the header field name is called the "key" and the
       
   538     content is called the "value". You can get and set a header
       
   539     field's value by using its key with value() and setValue(), e.g.
       
   540     \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 1
       
   541 
       
   542     Some fields are so common that getters and setters are provided
       
   543     for them as a convenient alternative to using \l value() and
       
   544     \l setValue(), e.g. contentLength() and contentType(),
       
   545     setContentLength() and setContentType().
       
   546 
       
   547     Each header key has a \e single value associated with it. If you
       
   548     set the value for a key which already exists the previous value
       
   549     will be discarded.
       
   550 
       
   551     \sa QHttpRequestHeader QHttpResponseHeader
       
   552 */
       
   553 
       
   554 /*!
       
   555     \fn int QHttpHeader::majorVersion() const
       
   556 
       
   557     Returns the major protocol-version of the HTTP header.
       
   558 */
       
   559 
       
   560 /*!
       
   561     \fn int QHttpHeader::minorVersion() const
       
   562 
       
   563     Returns the minor protocol-version of the HTTP header.
       
   564 */
       
   565 
       
   566 /*!
       
   567         Constructs an empty HTTP header.
       
   568 */
       
   569 QHttpHeader::QHttpHeader()
       
   570     : d_ptr(new QHttpHeaderPrivate)
       
   571 {
       
   572     Q_D(QHttpHeader);
       
   573     d->q_ptr = this;
       
   574     d->valid = true;
       
   575 }
       
   576 
       
   577 /*!
       
   578         Constructs a copy of \a header.
       
   579 */
       
   580 QHttpHeader::QHttpHeader(const QHttpHeader &header)
       
   581     : d_ptr(new QHttpHeaderPrivate)
       
   582 {
       
   583     Q_D(QHttpHeader);
       
   584     d->q_ptr = this;
       
   585     d->valid = header.d_func()->valid;
       
   586     d->values = header.d_func()->values;
       
   587 }
       
   588 
       
   589 /*!
       
   590     Constructs a HTTP header for \a str.
       
   591 
       
   592     This constructor parses the string \a str for header fields and
       
   593     adds this information. The \a str should consist of one or more
       
   594     "\r\n" delimited lines; each of these lines should have the format
       
   595     key, colon, space, value.
       
   596 */
       
   597 QHttpHeader::QHttpHeader(const QString &str)
       
   598     : d_ptr(new QHttpHeaderPrivate)
       
   599 {
       
   600     Q_D(QHttpHeader);
       
   601     d->q_ptr = this;
       
   602     d->valid = true;
       
   603     parse(str);
       
   604 }
       
   605 
       
   606 /*! \internal
       
   607  */
       
   608 QHttpHeader::QHttpHeader(QHttpHeaderPrivate &dd, const QString &str)
       
   609     : d_ptr(&dd)
       
   610 {
       
   611     Q_D(QHttpHeader);
       
   612     d->q_ptr = this;
       
   613     d->valid = true;
       
   614     if (!str.isEmpty())
       
   615         parse(str);
       
   616 }
       
   617 
       
   618 /*! \internal
       
   619  */
       
   620 QHttpHeader::QHttpHeader(QHttpHeaderPrivate &dd, const QHttpHeader &header)
       
   621     : d_ptr(&dd)
       
   622 {
       
   623     Q_D(QHttpHeader);
       
   624     d->q_ptr = this;
       
   625     d->valid = header.d_func()->valid;
       
   626     d->values = header.d_func()->values;
       
   627 }
       
   628 /*!
       
   629     Destructor.
       
   630 */
       
   631 QHttpHeader::~QHttpHeader()
       
   632 {
       
   633 }
       
   634 
       
   635 /*!
       
   636     Assigns \a h and returns a reference to this http header.
       
   637 */
       
   638 QHttpHeader &QHttpHeader::operator=(const QHttpHeader &h)
       
   639 {
       
   640     Q_D(QHttpHeader);
       
   641     d->values = h.d_func()->values;
       
   642     d->valid = h.d_func()->valid;
       
   643     return *this;
       
   644 }
       
   645 
       
   646 /*!
       
   647     Returns true if the HTTP header is valid; otherwise returns false.
       
   648 
       
   649     A QHttpHeader is invalid if it was created by parsing a malformed string.
       
   650 */
       
   651 bool QHttpHeader::isValid() const
       
   652 {
       
   653     Q_D(const QHttpHeader);
       
   654     return d->valid;
       
   655 }
       
   656 
       
   657 /*! \internal
       
   658     Parses the HTTP header string \a str for header fields and adds
       
   659     the keys/values it finds. If the string is not parsed successfully
       
   660     the QHttpHeader becomes \link isValid() invalid\endlink.
       
   661 
       
   662     Returns true if \a str was successfully parsed; otherwise returns false.
       
   663 
       
   664     \sa toString()
       
   665 */
       
   666 bool QHttpHeader::parse(const QString &str)
       
   667 {
       
   668     Q_D(QHttpHeader);
       
   669     QStringList lst;
       
   670     int pos = str.indexOf(QLatin1Char('\n'));
       
   671     if (pos > 0 && str.at(pos - 1) == QLatin1Char('\r'))
       
   672         lst = str.trimmed().split(QLatin1String("\r\n"));
       
   673     else
       
   674         lst = str.trimmed().split(QLatin1String("\n"));
       
   675     lst.removeAll(QString()); // No empties
       
   676 
       
   677     if (lst.isEmpty())
       
   678         return true;
       
   679 
       
   680     QStringList lines;
       
   681     QStringList::Iterator it = lst.begin();
       
   682     for (; it != lst.end(); ++it) {
       
   683         if (!(*it).isEmpty()) {
       
   684             if ((*it)[0].isSpace()) {
       
   685                 if (!lines.isEmpty()) {
       
   686                     lines.last() += QLatin1Char(' ');
       
   687                     lines.last() += (*it).trimmed();
       
   688                 }
       
   689             } else {
       
   690                 lines.append((*it));
       
   691             }
       
   692         }
       
   693     }
       
   694 
       
   695     int number = 0;
       
   696     it = lines.begin();
       
   697     for (; it != lines.end(); ++it) {
       
   698         if (!parseLine(*it, number++)) {
       
   699             d->valid = false;
       
   700             return false;
       
   701         }
       
   702     }
       
   703     return true;
       
   704 }
       
   705 
       
   706 /*! \internal
       
   707 */
       
   708 void QHttpHeader::setValid(bool v)
       
   709 {
       
   710     Q_D(QHttpHeader);
       
   711     d->valid = v;
       
   712 }
       
   713 
       
   714 /*!
       
   715     Returns the first value for the entry with the given \a key. If no entry
       
   716     has this \a key, an empty string is returned.
       
   717 
       
   718     \sa setValue() removeValue() hasKey() keys()
       
   719 */
       
   720 QString QHttpHeader::value(const QString &key) const
       
   721 {
       
   722     Q_D(const QHttpHeader);
       
   723     QString lowercaseKey = key.toLower();
       
   724     QList<QPair<QString, QString> >::ConstIterator it = d->values.constBegin();
       
   725     while (it != d->values.constEnd()) {
       
   726         if ((*it).first.toLower() == lowercaseKey)
       
   727             return (*it).second;
       
   728         ++it;
       
   729     }
       
   730     return QString();
       
   731 }
       
   732 
       
   733 /*!
       
   734     Returns all the entries with the given \a key. If no entry
       
   735     has this \a key, an empty string list is returned.
       
   736 */
       
   737 QStringList QHttpHeader::allValues(const QString &key) const
       
   738 {
       
   739     Q_D(const QHttpHeader);
       
   740     QString lowercaseKey = key.toLower();
       
   741     QStringList valueList;
       
   742     QList<QPair<QString, QString> >::ConstIterator it = d->values.constBegin();
       
   743     while (it != d->values.constEnd()) {
       
   744         if ((*it).first.toLower() == lowercaseKey)
       
   745             valueList.append((*it).second);
       
   746         ++it;
       
   747     }
       
   748     return valueList;
       
   749 }
       
   750 
       
   751 /*!
       
   752     Returns a list of the keys in the HTTP header.
       
   753 
       
   754     \sa hasKey()
       
   755 */
       
   756 QStringList QHttpHeader::keys() const
       
   757 {
       
   758     Q_D(const QHttpHeader);
       
   759     QStringList keyList;
       
   760     QSet<QString> seenKeys;
       
   761     QList<QPair<QString, QString> >::ConstIterator it = d->values.constBegin();
       
   762     while (it != d->values.constEnd()) {
       
   763         const QString &key = (*it).first;
       
   764         QString lowercaseKey = key.toLower();
       
   765         if (!seenKeys.contains(lowercaseKey)) {
       
   766             keyList.append(key);
       
   767             seenKeys.insert(lowercaseKey);
       
   768         }
       
   769         ++it;
       
   770     }
       
   771     return keyList;
       
   772 }
       
   773 
       
   774 /*!
       
   775     Returns true if the HTTP header has an entry with the given \a
       
   776     key; otherwise returns false.
       
   777 
       
   778     \sa value() setValue() keys()
       
   779 */
       
   780 bool QHttpHeader::hasKey(const QString &key) const
       
   781 {
       
   782     Q_D(const QHttpHeader);
       
   783     QString lowercaseKey = key.toLower();
       
   784     QList<QPair<QString, QString> >::ConstIterator it = d->values.constBegin();
       
   785     while (it != d->values.constEnd()) {
       
   786         if ((*it).first.toLower() == lowercaseKey)
       
   787             return true;
       
   788         ++it;
       
   789     }
       
   790     return false;
       
   791 }
       
   792 
       
   793 /*!
       
   794     Sets the value of the entry with the \a key to \a value.
       
   795 
       
   796     If no entry with \a key exists, a new entry with the given \a key
       
   797     and \a value is created. If an entry with the \a key already
       
   798     exists, the first value is discarded and replaced with the given
       
   799     \a value.
       
   800 
       
   801     \sa value() hasKey() removeValue()
       
   802 */
       
   803 void QHttpHeader::setValue(const QString &key, const QString &value)
       
   804 {
       
   805     Q_D(QHttpHeader);
       
   806     QString lowercaseKey = key.toLower();
       
   807     QList<QPair<QString, QString> >::Iterator it = d->values.begin();
       
   808     while (it != d->values.end()) {
       
   809         if ((*it).first.toLower() == lowercaseKey) {
       
   810             (*it).second = value;
       
   811             return;
       
   812         }
       
   813         ++it;
       
   814     }
       
   815     // not found so add
       
   816     addValue(key, value);
       
   817 }
       
   818 
       
   819 /*!
       
   820     Sets the header entries to be the list of key value pairs in \a values.
       
   821 */
       
   822 void QHttpHeader::setValues(const QList<QPair<QString, QString> > &values)
       
   823 {
       
   824     Q_D(QHttpHeader);
       
   825     d->values = values;
       
   826 }
       
   827 
       
   828 /*!
       
   829     Adds a new entry with the \a key and \a value.
       
   830 */
       
   831 void QHttpHeader::addValue(const QString &key, const QString &value)
       
   832 {
       
   833     Q_D(QHttpHeader);
       
   834     d->values.append(qMakePair(key, value));
       
   835 }
       
   836 
       
   837 /*!
       
   838     Returns all the entries in the header.
       
   839 */
       
   840 QList<QPair<QString, QString> > QHttpHeader::values() const
       
   841 {
       
   842     Q_D(const QHttpHeader);
       
   843     return d->values;
       
   844 }
       
   845 
       
   846 /*!
       
   847     Removes the entry with the key \a key from the HTTP header.
       
   848 
       
   849     \sa value() setValue()
       
   850 */
       
   851 void QHttpHeader::removeValue(const QString &key)
       
   852 {
       
   853     Q_D(QHttpHeader);
       
   854     QString lowercaseKey = key.toLower();
       
   855     QList<QPair<QString, QString> >::Iterator it = d->values.begin();
       
   856     while (it != d->values.end()) {
       
   857         if ((*it).first.toLower() == lowercaseKey) {
       
   858             d->values.erase(it);
       
   859             return;
       
   860         }
       
   861         ++it;
       
   862     }
       
   863 }
       
   864 
       
   865 /*!
       
   866     Removes all the entries with the key \a key from the HTTP header.
       
   867 */
       
   868 void QHttpHeader::removeAllValues(const QString &key)
       
   869 {
       
   870     Q_D(QHttpHeader);
       
   871     QString lowercaseKey = key.toLower();
       
   872     QList<QPair<QString, QString> >::Iterator it = d->values.begin();
       
   873     while (it != d->values.end()) {
       
   874         if ((*it).first.toLower() == lowercaseKey) {
       
   875             it = d->values.erase(it);
       
   876             continue;
       
   877         }
       
   878         ++it;
       
   879     }
       
   880 }
       
   881 
       
   882 /*! \internal
       
   883     Parses the single HTTP header line \a line which has the format
       
   884     key, colon, space, value, and adds key/value to the headers. The
       
   885     linenumber is \a number. Returns true if the line was successfully
       
   886     parsed and the key/value added; otherwise returns false.
       
   887 
       
   888     \sa parse()
       
   889 */
       
   890 bool QHttpHeader::parseLine(const QString &line, int)
       
   891 {
       
   892     int i = line.indexOf(QLatin1Char(':'));
       
   893     if (i == -1)
       
   894         return false;
       
   895 
       
   896     addValue(line.left(i).trimmed(), line.mid(i + 1).trimmed());
       
   897 
       
   898     return true;
       
   899 }
       
   900 
       
   901 /*!
       
   902     Returns a string representation of the HTTP header.
       
   903 
       
   904     The string is suitable for use by the constructor that takes a
       
   905     QString. It consists of lines with the format: key, colon, space,
       
   906     value, "\r\n".
       
   907 */
       
   908 QString QHttpHeader::toString() const
       
   909 {
       
   910     Q_D(const QHttpHeader);
       
   911     if (!isValid())
       
   912         return QLatin1String("");
       
   913 
       
   914     QString ret = QLatin1String("");
       
   915 
       
   916     QList<QPair<QString, QString> >::ConstIterator it = d->values.constBegin();
       
   917     while (it != d->values.constEnd()) {
       
   918         ret += (*it).first + QLatin1String(": ") + (*it).second + QLatin1String("\r\n");
       
   919         ++it;
       
   920     }
       
   921     return ret;
       
   922 }
       
   923 
       
   924 /*!
       
   925     Returns true if the header has an entry for the special HTTP
       
   926     header field \c content-length; otherwise returns false.
       
   927 
       
   928     \sa contentLength() setContentLength()
       
   929 */
       
   930 bool QHttpHeader::hasContentLength() const
       
   931 {
       
   932     return hasKey(QLatin1String("content-length"));
       
   933 }
       
   934 
       
   935 /*!
       
   936     Returns the value of the special HTTP header field \c
       
   937     content-length.
       
   938 
       
   939     \sa setContentLength() hasContentLength()
       
   940 */
       
   941 uint QHttpHeader::contentLength() const
       
   942 {
       
   943     return value(QLatin1String("content-length")).toUInt();
       
   944 }
       
   945 
       
   946 /*!
       
   947     Sets the value of the special HTTP header field \c content-length
       
   948     to \a len.
       
   949 
       
   950     \sa contentLength() hasContentLength()
       
   951 */
       
   952 void QHttpHeader::setContentLength(int len)
       
   953 {
       
   954     setValue(QLatin1String("content-length"), QString::number(len));
       
   955 }
       
   956 
       
   957 /*!
       
   958     Returns true if the header has an entry for the special HTTP
       
   959     header field \c content-type; otherwise returns false.
       
   960 
       
   961     \sa contentType() setContentType()
       
   962 */
       
   963 bool QHttpHeader::hasContentType() const
       
   964 {
       
   965     return hasKey(QLatin1String("content-type"));
       
   966 }
       
   967 
       
   968 /*!
       
   969     Returns the value of the special HTTP header field \c content-type.
       
   970 
       
   971     \sa setContentType() hasContentType()
       
   972 */
       
   973 QString QHttpHeader::contentType() const
       
   974 {
       
   975     QString type = value(QLatin1String("content-type"));
       
   976     if (type.isEmpty())
       
   977         return QString();
       
   978 
       
   979     int pos = type.indexOf(QLatin1Char(';'));
       
   980     if (pos == -1)
       
   981         return type;
       
   982 
       
   983     return type.left(pos).trimmed();
       
   984 }
       
   985 
       
   986 /*!
       
   987     Sets the value of the special HTTP header field \c content-type to
       
   988     \a type.
       
   989 
       
   990     \sa contentType() hasContentType()
       
   991 */
       
   992 void QHttpHeader::setContentType(const QString &type)
       
   993 {
       
   994     setValue(QLatin1String("content-type"), type);
       
   995 }
       
   996 
       
   997 class QHttpResponseHeaderPrivate : public QHttpHeaderPrivate
       
   998 {
       
   999     Q_DECLARE_PUBLIC(QHttpResponseHeader)
       
  1000 public:
       
  1001     int statCode;
       
  1002     QString reasonPhr;
       
  1003     int majVer;
       
  1004     int minVer;
       
  1005 };
       
  1006 
       
  1007 /****************************************************
       
  1008  *
       
  1009  * QHttpResponseHeader
       
  1010  *
       
  1011  ****************************************************/
       
  1012 
       
  1013 /*!
       
  1014     \class QHttpResponseHeader
       
  1015     \obsolete
       
  1016     \brief The QHttpResponseHeader class contains response header information for HTTP.
       
  1017 
       
  1018     \ingroup network
       
  1019     \inmodule QtNetwork
       
  1020 
       
  1021     This class is used by the QHttp class to report the header
       
  1022     information that the client received from the server.
       
  1023 
       
  1024     HTTP responses have a status code that indicates the status of the
       
  1025     response. This code is a 3-digit integer result code (for details
       
  1026     see to RFC 1945). In addition to the status code, you can also
       
  1027     specify a human-readable text that describes the reason for the
       
  1028     code ("reason phrase"). This class allows you to get the status
       
  1029     code and the reason phrase.
       
  1030 
       
  1031     \sa QHttpRequestHeader, QHttp, {HTTP Example}
       
  1032 */
       
  1033 
       
  1034 /*!
       
  1035     Constructs an empty HTTP response header.
       
  1036 */
       
  1037 QHttpResponseHeader::QHttpResponseHeader()
       
  1038     : QHttpHeader(*new QHttpResponseHeaderPrivate)
       
  1039 {
       
  1040     setValid(false);
       
  1041 }
       
  1042 
       
  1043 /*!
       
  1044     Constructs a copy of \a header.
       
  1045 */
       
  1046 QHttpResponseHeader::QHttpResponseHeader(const QHttpResponseHeader &header)
       
  1047     : QHttpHeader(*new QHttpResponseHeaderPrivate, header)
       
  1048 {
       
  1049     Q_D(QHttpResponseHeader);
       
  1050     d->statCode = header.d_func()->statCode;
       
  1051     d->reasonPhr = header.d_func()->reasonPhr;
       
  1052     d->majVer = header.d_func()->majVer;
       
  1053     d->minVer = header.d_func()->minVer;
       
  1054 }
       
  1055 
       
  1056 /*!
       
  1057     Copies the contents of \a header into this QHttpResponseHeader.
       
  1058 */
       
  1059 QHttpResponseHeader &QHttpResponseHeader::operator=(const QHttpResponseHeader &header)
       
  1060 {
       
  1061     Q_D(QHttpResponseHeader);
       
  1062     QHttpHeader::operator=(header);
       
  1063     d->statCode = header.d_func()->statCode;
       
  1064     d->reasonPhr = header.d_func()->reasonPhr;
       
  1065     d->majVer = header.d_func()->majVer;
       
  1066     d->minVer = header.d_func()->minVer;
       
  1067     return *this;
       
  1068 }
       
  1069 
       
  1070 /*!
       
  1071     Constructs a HTTP response header from the string \a str. The
       
  1072     string is parsed and the information is set. The \a str should
       
  1073     consist of one or more "\r\n" delimited lines; the first line should be the
       
  1074     status-line (format: HTTP-version, space, status-code, space,
       
  1075     reason-phrase); each of remaining lines should have the format key, colon,
       
  1076     space, value.
       
  1077 */
       
  1078 QHttpResponseHeader::QHttpResponseHeader(const QString &str)
       
  1079     : QHttpHeader(*new QHttpResponseHeaderPrivate)
       
  1080 {
       
  1081     parse(str);
       
  1082 }
       
  1083 
       
  1084 /*!
       
  1085     \since 4.1
       
  1086 
       
  1087     Constructs a QHttpResponseHeader, setting the status code to \a code, the
       
  1088     reason phrase to \a text and the protocol-version to \a majorVer and \a
       
  1089     minorVer.
       
  1090 
       
  1091     \sa statusCode() reasonPhrase() majorVersion() minorVersion()
       
  1092 */
       
  1093 QHttpResponseHeader::QHttpResponseHeader(int code, const QString &text, int majorVer, int minorVer)
       
  1094     : QHttpHeader(*new QHttpResponseHeaderPrivate)
       
  1095 {
       
  1096     setStatusLine(code, text, majorVer, minorVer);
       
  1097 }
       
  1098 
       
  1099 /*!
       
  1100     \since 4.1
       
  1101 
       
  1102     Sets the status code to \a code, the reason phrase to \a text and
       
  1103     the protocol-version to \a majorVer and \a minorVer.
       
  1104 
       
  1105     \sa statusCode() reasonPhrase() majorVersion() minorVersion()
       
  1106 */
       
  1107 void QHttpResponseHeader::setStatusLine(int code, const QString &text, int majorVer, int minorVer)
       
  1108 {
       
  1109     Q_D(QHttpResponseHeader);
       
  1110     setValid(true);
       
  1111     d->statCode = code;
       
  1112     d->reasonPhr = text;
       
  1113     d->majVer = majorVer;
       
  1114     d->minVer = minorVer;
       
  1115 }
       
  1116 
       
  1117 /*!
       
  1118     Returns the status code of the HTTP response header.
       
  1119 
       
  1120     \sa reasonPhrase() majorVersion() minorVersion()
       
  1121 */
       
  1122 int QHttpResponseHeader::statusCode() const
       
  1123 {
       
  1124     Q_D(const QHttpResponseHeader);
       
  1125     return d->statCode;
       
  1126 }
       
  1127 
       
  1128 /*!
       
  1129     Returns the reason phrase of the HTTP response header.
       
  1130 
       
  1131     \sa statusCode() majorVersion() minorVersion()
       
  1132 */
       
  1133 QString QHttpResponseHeader::reasonPhrase() const
       
  1134 {
       
  1135     Q_D(const QHttpResponseHeader);
       
  1136     return d->reasonPhr;
       
  1137 }
       
  1138 
       
  1139 /*!
       
  1140     Returns the major protocol-version of the HTTP response header.
       
  1141 
       
  1142     \sa minorVersion() statusCode() reasonPhrase()
       
  1143 */
       
  1144 int QHttpResponseHeader::majorVersion() const
       
  1145 {
       
  1146     Q_D(const QHttpResponseHeader);
       
  1147     return d->majVer;
       
  1148 }
       
  1149 
       
  1150 /*!
       
  1151     Returns the minor protocol-version of the HTTP response header.
       
  1152 
       
  1153     \sa majorVersion() statusCode() reasonPhrase()
       
  1154 */
       
  1155 int QHttpResponseHeader::minorVersion() const
       
  1156 {
       
  1157     Q_D(const QHttpResponseHeader);
       
  1158     return d->minVer;
       
  1159 }
       
  1160 
       
  1161 /*! \internal
       
  1162 */
       
  1163 bool QHttpResponseHeader::parseLine(const QString &line, int number)
       
  1164 {
       
  1165     Q_D(QHttpResponseHeader);
       
  1166     if (number != 0)
       
  1167         return QHttpHeader::parseLine(line, number);
       
  1168 
       
  1169     QString l = line.simplified();
       
  1170     if (l.length() < 10)
       
  1171         return false;
       
  1172 
       
  1173     if (l.left(5) == QLatin1String("HTTP/") && l[5].isDigit() && l[6] == QLatin1Char('.') &&
       
  1174         l[7].isDigit() && l[8] == QLatin1Char(' ') && l[9].isDigit()) {
       
  1175         d->majVer = l[5].toLatin1() - '0';
       
  1176         d->minVer = l[7].toLatin1() - '0';
       
  1177 
       
  1178         int pos = l.indexOf(QLatin1Char(' '), 9);
       
  1179         if (pos != -1) {
       
  1180             d->reasonPhr = l.mid(pos + 1);
       
  1181             d->statCode = l.mid(9, pos - 9).toInt();
       
  1182         } else {
       
  1183             d->statCode = l.mid(9).toInt();
       
  1184             d->reasonPhr.clear();
       
  1185         }
       
  1186     } else {
       
  1187         return false;
       
  1188     }
       
  1189 
       
  1190     return true;
       
  1191 }
       
  1192 
       
  1193 /*! \reimp
       
  1194 */
       
  1195 QString QHttpResponseHeader::toString() const
       
  1196 {
       
  1197     Q_D(const QHttpResponseHeader);
       
  1198     QString ret(QLatin1String("HTTP/%1.%2 %3 %4\r\n%5\r\n"));
       
  1199     return ret.arg(d->majVer).arg(d->minVer).arg(d->statCode).arg(d->reasonPhr).arg(QHttpHeader::toString());
       
  1200 }
       
  1201 
       
  1202 class QHttpRequestHeaderPrivate : public QHttpHeaderPrivate
       
  1203 {
       
  1204     Q_DECLARE_PUBLIC(QHttpRequestHeader)
       
  1205 public:
       
  1206     QString m;
       
  1207     QString p;
       
  1208     int majVer;
       
  1209     int minVer;
       
  1210 };
       
  1211 
       
  1212 /****************************************************
       
  1213  *
       
  1214  * QHttpRequestHeader
       
  1215  *
       
  1216  ****************************************************/
       
  1217 
       
  1218 /*!
       
  1219     \class QHttpRequestHeader
       
  1220     \obsolete
       
  1221     \brief The QHttpRequestHeader class contains request header information for HTTP.
       
  1222 
       
  1223     \ingroup network
       
  1224     \inmodule QtNetwork
       
  1225 
       
  1226     This class is used in the QHttp class to report the header
       
  1227     information if the client requests something from the server.
       
  1228 
       
  1229     HTTP requests have a method which describes the request's action.
       
  1230     The most common requests are "GET" and "POST". In addition to the
       
  1231     request method the header also includes a request-URI to specify
       
  1232     the location for the method to use.
       
  1233 
       
  1234     The method, request-URI and protocol-version can be set using a
       
  1235     constructor or later using setRequest(). The values can be
       
  1236     obtained using method(), path(), majorVersion() and
       
  1237     minorVersion().
       
  1238 
       
  1239     Note that the request-URI must be in the format expected by the
       
  1240     HTTP server. That is, all reserved characters must be encoded in
       
  1241     %HH (where HH are two hexadecimal digits). See
       
  1242     QUrl::toPercentEncoding() for more information.
       
  1243 
       
  1244     Important inherited functions: setValue() and value().
       
  1245 
       
  1246     \sa QHttpResponseHeader QHttp
       
  1247 */
       
  1248 
       
  1249 /*!
       
  1250     Constructs an empty HTTP request header.
       
  1251 */
       
  1252 QHttpRequestHeader::QHttpRequestHeader()
       
  1253     : QHttpHeader(*new QHttpRequestHeaderPrivate)
       
  1254 {
       
  1255     setValid(false);
       
  1256 }
       
  1257 
       
  1258 /*!
       
  1259     Constructs a HTTP request header for the method \a method, the
       
  1260     request-URI \a path and the protocol-version \a majorVer and \a
       
  1261     minorVer. The \a path argument must be properly encoded for an
       
  1262     HTTP request.
       
  1263 */
       
  1264 QHttpRequestHeader::QHttpRequestHeader(const QString &method, const QString &path, int majorVer, int minorVer)
       
  1265     : QHttpHeader(*new QHttpRequestHeaderPrivate)
       
  1266 {
       
  1267     Q_D(QHttpRequestHeader);
       
  1268     d->m = method;
       
  1269     d->p = path;
       
  1270     d->majVer = majorVer;
       
  1271     d->minVer = minorVer;
       
  1272 }
       
  1273 
       
  1274 /*!
       
  1275     Constructs a copy of \a header.
       
  1276 */
       
  1277 QHttpRequestHeader::QHttpRequestHeader(const QHttpRequestHeader &header)
       
  1278     : QHttpHeader(*new QHttpRequestHeaderPrivate, header)
       
  1279 {
       
  1280     Q_D(QHttpRequestHeader);
       
  1281     d->m = header.d_func()->m;
       
  1282     d->p = header.d_func()->p;
       
  1283     d->majVer = header.d_func()->majVer;
       
  1284     d->minVer = header.d_func()->minVer;
       
  1285 }
       
  1286 
       
  1287 /*!
       
  1288     Copies the content of \a header into this QHttpRequestHeader
       
  1289 */
       
  1290 QHttpRequestHeader &QHttpRequestHeader::operator=(const QHttpRequestHeader &header)
       
  1291 {
       
  1292     Q_D(QHttpRequestHeader);
       
  1293     QHttpHeader::operator=(header);
       
  1294     d->m = header.d_func()->m;
       
  1295     d->p = header.d_func()->p;
       
  1296     d->majVer = header.d_func()->majVer;
       
  1297     d->minVer = header.d_func()->minVer;
       
  1298     return *this;
       
  1299 }
       
  1300 
       
  1301 /*!
       
  1302     Constructs a HTTP request header from the string \a str. The \a
       
  1303     str should consist of one or more "\r\n" delimited lines; the first line
       
  1304     should be the request-line (format: method, space, request-URI, space
       
  1305     HTTP-version); each of the remaining lines should have the format key,
       
  1306     colon, space, value.
       
  1307 */
       
  1308 QHttpRequestHeader::QHttpRequestHeader(const QString &str)
       
  1309     : QHttpHeader(*new QHttpRequestHeaderPrivate)
       
  1310 {
       
  1311     parse(str);
       
  1312 }
       
  1313 
       
  1314 /*!
       
  1315     This function sets the request method to \a method, the
       
  1316     request-URI to \a path and the protocol-version to \a majorVer and
       
  1317     \a minorVer. The \a path argument must be properly encoded for an
       
  1318     HTTP request.
       
  1319 
       
  1320     \sa method() path() majorVersion() minorVersion()
       
  1321 */
       
  1322 void QHttpRequestHeader::setRequest(const QString &method, const QString &path, int majorVer, int minorVer)
       
  1323 {
       
  1324     Q_D(QHttpRequestHeader);
       
  1325     setValid(true);
       
  1326     d->m = method;
       
  1327     d->p = path;
       
  1328     d->majVer = majorVer;
       
  1329     d->minVer = minorVer;
       
  1330 }
       
  1331 
       
  1332 /*!
       
  1333     Returns the method of the HTTP request header.
       
  1334 
       
  1335     \sa path() majorVersion() minorVersion() setRequest()
       
  1336 */
       
  1337 QString QHttpRequestHeader::method() const
       
  1338 {
       
  1339     Q_D(const QHttpRequestHeader);
       
  1340     return d->m;
       
  1341 }
       
  1342 
       
  1343 /*!
       
  1344     Returns the request-URI of the HTTP request header.
       
  1345 
       
  1346     \sa method() majorVersion() minorVersion() setRequest()
       
  1347 */
       
  1348 QString QHttpRequestHeader::path() const
       
  1349 {
       
  1350     Q_D(const QHttpRequestHeader);
       
  1351     return d->p;
       
  1352 }
       
  1353 
       
  1354 /*!
       
  1355     Returns the major protocol-version of the HTTP request header.
       
  1356 
       
  1357     \sa minorVersion() method() path() setRequest()
       
  1358 */
       
  1359 int QHttpRequestHeader::majorVersion() const
       
  1360 {
       
  1361     Q_D(const QHttpRequestHeader);
       
  1362     return d->majVer;
       
  1363 }
       
  1364 
       
  1365 /*!
       
  1366     Returns the minor protocol-version of the HTTP request header.
       
  1367 
       
  1368     \sa majorVersion() method() path() setRequest()
       
  1369 */
       
  1370 int QHttpRequestHeader::minorVersion() const
       
  1371 {
       
  1372     Q_D(const QHttpRequestHeader);
       
  1373     return d->minVer;
       
  1374 }
       
  1375 
       
  1376 /*! \internal
       
  1377 */
       
  1378 bool QHttpRequestHeader::parseLine(const QString &line, int number)
       
  1379 {
       
  1380     Q_D(QHttpRequestHeader);
       
  1381     if (number != 0)
       
  1382         return QHttpHeader::parseLine(line, number);
       
  1383 
       
  1384     QStringList lst = line.simplified().split(QLatin1String(" "));
       
  1385     if (lst.count() > 0) {
       
  1386         d->m = lst[0];
       
  1387         if (lst.count() > 1) {
       
  1388             d->p = lst[1];
       
  1389             if (lst.count() > 2) {
       
  1390                 QString v = lst[2];
       
  1391                 if (v.length() >= 8 && v.left(5) == QLatin1String("HTTP/") &&
       
  1392                     v[5].isDigit() && v[6] == QLatin1Char('.') && v[7].isDigit()) {
       
  1393                     d->majVer = v[5].toLatin1() - '0';
       
  1394                     d->minVer = v[7].toLatin1() - '0';
       
  1395                     return true;
       
  1396                 }
       
  1397             }
       
  1398         }
       
  1399     }
       
  1400 
       
  1401     return false;
       
  1402 }
       
  1403 
       
  1404 /*! \reimp
       
  1405 */
       
  1406 QString QHttpRequestHeader::toString() const
       
  1407 {
       
  1408     Q_D(const QHttpRequestHeader);
       
  1409     QString first(QLatin1String("%1 %2"));
       
  1410     QString last(QLatin1String(" HTTP/%3.%4\r\n%5\r\n"));
       
  1411     return first.arg(d->m).arg(d->p) +
       
  1412         last.arg(d->majVer).arg(d->minVer).arg(QHttpHeader::toString());
       
  1413 }
       
  1414 
       
  1415 
       
  1416 /****************************************************
       
  1417  *
       
  1418  * QHttp
       
  1419  *
       
  1420  ****************************************************/
       
  1421 /*!
       
  1422     \class QHttp
       
  1423     \obsolete
       
  1424     \reentrant
       
  1425 
       
  1426     \brief The QHttp class provides an implementation of the HTTP protocol.
       
  1427 
       
  1428     \ingroup network
       
  1429     \inmodule QtNetwork
       
  1430 
       
  1431 
       
  1432     This class provides a direct interface to HTTP that allows you to
       
  1433     download and upload data with the HTTP protocol.
       
  1434     However, for new applications, it is
       
  1435     recommended to use QNetworkAccessManager and QNetworkReply, as
       
  1436     those classes possess a simpler, yet more powerful API
       
  1437     and a more modern protocol implementation.
       
  1438 
       
  1439     The class works asynchronously, so there are no blocking
       
  1440     functions. If an operation cannot be executed immediately, the
       
  1441     function will still return straight away and the operation will be
       
  1442     scheduled for later execution. The results of scheduled operations
       
  1443     are reported via signals. This approach depends on the event loop
       
  1444     being in operation.
       
  1445 
       
  1446     The operations that can be scheduled (they are called "requests"
       
  1447     in the rest of the documentation) are the following: setHost(),
       
  1448     get(), post(), head() and request().
       
  1449 
       
  1450     All of these requests return a unique identifier that allows you
       
  1451     to keep track of the request that is currently executed. When the
       
  1452     execution of a request starts, the requestStarted() signal with
       
  1453     the identifier is emitted and when the request is finished, the
       
  1454     requestFinished() signal is emitted with the identifier and a bool
       
  1455     that indicates if the request finished with an error.
       
  1456 
       
  1457     To make an HTTP request you must set up suitable HTTP headers. The
       
  1458     following example demonstrates how to request the main HTML page
       
  1459     from the Qt website (i.e., the URL \c http://qt.nokia.com/index.html):
       
  1460 
       
  1461     \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 2
       
  1462 
       
  1463     For the common HTTP requests \c GET, \c POST and \c HEAD, QHttp
       
  1464     provides the convenience functions get(), post() and head(). They
       
  1465     already use a reasonable header and if you don't have to set
       
  1466     special header fields, they are easier to use. The above example
       
  1467     can also be written as:
       
  1468 
       
  1469     \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 3
       
  1470 
       
  1471     For this example the following sequence of signals is emitted
       
  1472     (with small variations, depending on network traffic, etc.):
       
  1473 
       
  1474     \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 4
       
  1475 
       
  1476     The dataSendProgress() and dataReadProgress() signals in the above
       
  1477     example are useful if you want to show a \link QProgressBar
       
  1478     progress bar\endlink to inform the user about the progress of the
       
  1479     download. The second argument is the total size of data. In
       
  1480     certain cases it is not possible to know the total amount in
       
  1481     advance, in which case the second argument is 0. (If you connect
       
  1482     to a QProgressBar a total of 0 results in a busy indicator.)
       
  1483 
       
  1484     When the response header is read, it is reported with the
       
  1485     responseHeaderReceived() signal.
       
  1486 
       
  1487     The readyRead() signal tells you that there is data ready to be
       
  1488     read. The amount of data can then be queried with the
       
  1489     bytesAvailable() function and it can be read with the read()
       
  1490     or readAll() functions.
       
  1491 
       
  1492     If an error occurs during the execution of one of the commands in
       
  1493     a sequence of commands, all the pending commands (i.e. scheduled,
       
  1494     but not yet executed commands) are cleared and no signals are
       
  1495     emitted for them.
       
  1496 
       
  1497     For example, if you have the following sequence of requests
       
  1498 
       
  1499     \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 5
       
  1500 
       
  1501     and the get() request fails because the host lookup fails, then
       
  1502     the post() request is never executed and the signals would look
       
  1503     like this:
       
  1504 
       
  1505     \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 6
       
  1506 
       
  1507     You can then get details about the error with the error() and
       
  1508     errorString() functions. Note that only unexpected behavior, like
       
  1509     network failure is considered as an error. If the server response
       
  1510     contains an error status, like a 404 response, this is reported as
       
  1511     a normal response case. So you should always check the \link
       
  1512     QHttpResponseHeader::statusCode() status code \endlink of the
       
  1513     response header.
       
  1514 
       
  1515     The functions currentId() and currentRequest() provide more
       
  1516     information about the currently executing request.
       
  1517 
       
  1518     The functions hasPendingRequests() and clearPendingRequests()
       
  1519     allow you to query and clear the list of pending requests.
       
  1520 
       
  1521     \sa QFtp, QNetworkAccessManager, QNetworkRequest, QNetworkReply,
       
  1522         {HTTP Example}, {Torrent Example}
       
  1523 */
       
  1524 
       
  1525 /*!
       
  1526     Constructs a QHttp object. The \a parent parameter is passed on
       
  1527     to the QObject constructor.
       
  1528 */
       
  1529 QHttp::QHttp(QObject *parent)
       
  1530     : QObject(*new QHttpPrivate, parent)
       
  1531 {
       
  1532     Q_D(QHttp);
       
  1533     d->init();
       
  1534 }
       
  1535 
       
  1536 /*!
       
  1537     Constructs a QHttp object. Subsequent requests are done by
       
  1538     connecting to the server \a hostName on port \a port.
       
  1539 
       
  1540     The \a parent parameter is passed on to the QObject constructor.
       
  1541 
       
  1542     \sa setHost()
       
  1543 */
       
  1544 QHttp::QHttp(const QString &hostName, quint16 port, QObject *parent)
       
  1545     : QObject(*new QHttpPrivate, parent)
       
  1546 {
       
  1547     Q_D(QHttp);
       
  1548     d->init();
       
  1549 
       
  1550     d->hostName = hostName;
       
  1551     d->port = port;
       
  1552 }
       
  1553 
       
  1554 /*!
       
  1555     Constructs a QHttp object. Subsequent requests are done by
       
  1556     connecting to the server \a hostName on port \a port using the
       
  1557     connection mode \a mode.
       
  1558 
       
  1559     If port is 0, it will use the default port for the \a mode used
       
  1560     (80 for Http and 443 for Https).
       
  1561 
       
  1562     The \a parent parameter is passed on to the QObject constructor.
       
  1563 
       
  1564     \sa setHost()
       
  1565 */
       
  1566 QHttp::QHttp(const QString &hostName, ConnectionMode mode, quint16 port, QObject *parent)
       
  1567     : QObject(*new QHttpPrivate, parent)
       
  1568 {
       
  1569     Q_D(QHttp);
       
  1570     d->init();
       
  1571 
       
  1572     d->hostName = hostName;
       
  1573     if (port == 0)
       
  1574         port = (mode == ConnectionModeHttp) ? 80 : 443;
       
  1575     d->port = port;
       
  1576     d->mode = mode;
       
  1577 }
       
  1578 
       
  1579 void QHttpPrivate::init()
       
  1580 {
       
  1581     Q_Q(QHttp);
       
  1582     errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Unknown error"));
       
  1583     QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection);
       
  1584     post100ContinueTimer.setSingleShot(true);
       
  1585     QObject::connect(&post100ContinueTimer, SIGNAL(timeout()), q, SLOT(_q_continuePost()));
       
  1586 }
       
  1587 
       
  1588 /*!
       
  1589     Destroys the QHttp object. If there is an open connection, it is
       
  1590     closed.
       
  1591 */
       
  1592 QHttp::~QHttp()
       
  1593 {
       
  1594     abort();
       
  1595 }
       
  1596 
       
  1597 /*!
       
  1598     \enum QHttp::ConnectionMode
       
  1599     \since 4.3
       
  1600 
       
  1601     This enum is used to specify the mode of connection to use:
       
  1602 
       
  1603     \value ConnectionModeHttp The connection is a regular HTTP connection to the server
       
  1604     \value ConnectionModeHttps The HTTPS protocol is used and the connection is encrypted using SSL.
       
  1605 
       
  1606     When using the HTTPS mode, care should be taken to connect to the sslErrors signal, and
       
  1607     handle possible SSL errors.
       
  1608 
       
  1609     \sa QSslSocket
       
  1610 */
       
  1611 
       
  1612 /*!
       
  1613     \enum QHttp::State
       
  1614 
       
  1615     This enum is used to specify the state the client is in:
       
  1616 
       
  1617     \value Unconnected There is no connection to the host.
       
  1618     \value HostLookup A host name lookup is in progress.
       
  1619     \value Connecting An attempt to connect to the host is in progress.
       
  1620     \value Sending The client is sending its request to the server.
       
  1621     \value Reading The client's request has been sent and the client
       
  1622     is reading the server's response.
       
  1623     \value Connected The connection to the host is open, but the client is
       
  1624     neither sending a request, nor waiting for a response.
       
  1625     \value Closing The connection is closing down, but is not yet
       
  1626     closed. (The state will be \c Unconnected when the connection is
       
  1627     closed.)
       
  1628 
       
  1629     \sa stateChanged() state()
       
  1630 */
       
  1631 
       
  1632 /*!  \enum QHttp::Error
       
  1633 
       
  1634     This enum identifies the error that occurred.
       
  1635 
       
  1636     \value NoError No error occurred.
       
  1637     \value HostNotFound The host name lookup failed.
       
  1638     \value ConnectionRefused The server refused the connection.
       
  1639     \value UnexpectedClose The server closed the connection unexpectedly.
       
  1640     \value InvalidResponseHeader The server sent an invalid response header.
       
  1641     \value WrongContentLength The client could not read the content correctly
       
  1642     because an error with respect to the content length occurred.
       
  1643     \value Aborted The request was aborted with abort().
       
  1644     \value ProxyAuthenticationRequiredError QHttp is using a proxy, and the
       
  1645     proxy server requires authentication to establish a connection.
       
  1646     \value AuthenticationRequiredError The web server requires authentication
       
  1647     to complete the request.
       
  1648     \value UnknownError An error other than those specified above
       
  1649     occurred.
       
  1650 
       
  1651     \sa error()
       
  1652 */
       
  1653 
       
  1654 /*!
       
  1655     \fn void QHttp::stateChanged(int state)
       
  1656 
       
  1657     This signal is emitted when the state of the QHttp object changes.
       
  1658     The argument \a state is the new state of the connection; it is
       
  1659     one of the \l State values.
       
  1660 
       
  1661     This usually happens when a request is started, but it can also
       
  1662     happen when the server closes the connection or when a call to
       
  1663     close() succeeded.
       
  1664 
       
  1665     \sa get() post() head() request() close() state() State
       
  1666 */
       
  1667 
       
  1668 /*!
       
  1669     \fn void QHttp::responseHeaderReceived(const QHttpResponseHeader &resp);
       
  1670 
       
  1671     This signal is emitted when the HTTP header of a server response
       
  1672     is available. The header is passed in \a resp.
       
  1673 
       
  1674     \sa get() post() head() request() readyRead()
       
  1675 */
       
  1676 
       
  1677 /*!
       
  1678     \fn void QHttp::readyRead(const QHttpResponseHeader &resp)
       
  1679 
       
  1680     This signal is emitted when there is new response data to read.
       
  1681 
       
  1682     If you specified a device in the request where the data should be
       
  1683     written to, then this signal is \e not emitted; instead the data
       
  1684     is written directly to the device.
       
  1685 
       
  1686     The response header is passed in \a resp.
       
  1687 
       
  1688     You can read the data with the readAll() or read() functions
       
  1689 
       
  1690     This signal is useful if you want to process the data in chunks as
       
  1691     soon as it becomes available. If you are only interested in the
       
  1692     complete data, just connect to the requestFinished() signal and
       
  1693     read the data then instead.
       
  1694 
       
  1695     \sa get() post() request() readAll() read() bytesAvailable()
       
  1696 */
       
  1697 
       
  1698 /*!
       
  1699     \fn void QHttp::dataSendProgress(int done, int total)
       
  1700 
       
  1701     This signal is emitted when this object sends data to a HTTP
       
  1702     server to inform it about the progress of the upload.
       
  1703 
       
  1704     \a done is the amount of data that has already arrived and \a
       
  1705     total is the total amount of data. It is possible that the total
       
  1706     amount of data that should be transferred cannot be determined, in
       
  1707     which case \a total is 0.(If you connect to a QProgressBar, the
       
  1708     progress bar shows a busy indicator if the total is 0).
       
  1709 
       
  1710     \warning \a done and \a total are not necessarily the size in
       
  1711     bytes, since for large files these values might need to be
       
  1712     "scaled" to avoid overflow.
       
  1713 
       
  1714     \sa dataReadProgress(), post(), request(), QProgressBar
       
  1715 */
       
  1716 
       
  1717 /*!
       
  1718     \fn void QHttp::dataReadProgress(int done, int total)
       
  1719 
       
  1720     This signal is emitted when this object reads data from a HTTP
       
  1721     server to indicate the current progress of the download.
       
  1722 
       
  1723     \a done is the amount of data that has already arrived and \a
       
  1724     total is the total amount of data. It is possible that the total
       
  1725     amount of data that should be transferred cannot be determined, in
       
  1726     which case \a total is 0.(If you connect to a QProgressBar, the
       
  1727     progress bar shows a busy indicator if the total is 0).
       
  1728 
       
  1729     \warning \a done and \a total are not necessarily the size in
       
  1730     bytes, since for large files these values might need to be
       
  1731     "scaled" to avoid overflow.
       
  1732 
       
  1733     \sa dataSendProgress() get() post() request() QProgressBar
       
  1734 */
       
  1735 
       
  1736 /*!
       
  1737     \fn void QHttp::requestStarted(int id)
       
  1738 
       
  1739     This signal is emitted when processing the request identified by
       
  1740     \a id starts.
       
  1741 
       
  1742     \sa requestFinished() done()
       
  1743 */
       
  1744 
       
  1745 /*!
       
  1746     \fn void QHttp::requestFinished(int id, bool error)
       
  1747 
       
  1748     This signal is emitted when processing the request identified by
       
  1749     \a id has finished. \a error is true if an error occurred during
       
  1750     the processing; otherwise \a error is false.
       
  1751 
       
  1752     \sa requestStarted() done() error() errorString()
       
  1753 */
       
  1754 
       
  1755 /*!
       
  1756     \fn void QHttp::done(bool error)
       
  1757 
       
  1758     This signal is emitted when the last pending request has finished;
       
  1759     (it is emitted after the last request's requestFinished() signal).
       
  1760     \a error is true if an error occurred during the processing;
       
  1761     otherwise \a error is false.
       
  1762 
       
  1763     \sa requestFinished() error() errorString()
       
  1764 */
       
  1765 
       
  1766 #ifndef QT_NO_NETWORKPROXY
       
  1767 
       
  1768 /*!
       
  1769     \fn void QHttp::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
       
  1770     \since 4.3
       
  1771 
       
  1772     This signal can be emitted when a \a proxy that requires
       
  1773     authentication is used. The \a authenticator object can then be
       
  1774     filled in with the required details to allow authentication and
       
  1775     continue the connection.
       
  1776 
       
  1777     \note It is not possible to use a QueuedConnection to connect to
       
  1778     this signal, as the connection will fail if the authenticator has
       
  1779     not been filled in with new information when the signal returns.
       
  1780 
       
  1781     \sa QAuthenticator, QNetworkProxy
       
  1782 */
       
  1783 
       
  1784 #endif
       
  1785 
       
  1786 /*!
       
  1787     \fn void QHttp::authenticationRequired(const QString &hostname, quint16 port, QAuthenticator *authenticator)
       
  1788     \since 4.3
       
  1789 
       
  1790     This signal can be emitted when a web server on a given \a hostname and \a
       
  1791     port requires authentication. The \a authenticator object can then be
       
  1792     filled in with the required details to allow authentication and continue
       
  1793     the connection.
       
  1794 
       
  1795     \note It is not possible to use a QueuedConnection to connect to
       
  1796     this signal, as the connection will fail if the authenticator has
       
  1797     not been filled in with new information when the signal returns.
       
  1798 
       
  1799     \sa QAuthenticator, QNetworkProxy
       
  1800 */
       
  1801 
       
  1802 /*!
       
  1803     \fn void QHttp::sslErrors(const QList<QSslError> &errors)
       
  1804     \since 4.3
       
  1805 
       
  1806     Forwards the sslErrors signal from the QSslSocket used in QHttp. \a errors
       
  1807     is the list of errors that occurred during the SSL handshake. Unless you
       
  1808     call ignoreSslErrors() from within a slot connected to this signal when an
       
  1809     error occurs, QHttp will tear down the connection immediately after
       
  1810     emitting the signal.
       
  1811 
       
  1812     \sa QSslSocket QSslSocket::ignoreSslErrors()
       
  1813 */
       
  1814 
       
  1815 /*!
       
  1816     Aborts the current request and deletes all scheduled requests.
       
  1817 
       
  1818     For the current request, the requestFinished() signal with the \c
       
  1819     error argument \c true is emitted. For all other requests that are
       
  1820     affected by the abort(), no signals are emitted.
       
  1821 
       
  1822     Since this slot also deletes the scheduled requests, there are no
       
  1823     requests left and the done() signal is emitted (with the \c error
       
  1824     argument \c true).
       
  1825 
       
  1826     \sa clearPendingRequests()
       
  1827 */
       
  1828 void QHttp::abort()
       
  1829 {
       
  1830     Q_D(QHttp);
       
  1831     if (d->pending.isEmpty())
       
  1832         return;
       
  1833 
       
  1834     d->finishedWithError(tr("Request aborted"), Aborted);
       
  1835     clearPendingRequests();
       
  1836     if (d->socket)
       
  1837         d->socket->abort();
       
  1838     d->closeConn();
       
  1839 }
       
  1840 
       
  1841 /*!
       
  1842     Returns the number of bytes that can be read from the response
       
  1843     content at the moment.
       
  1844 
       
  1845     \sa get() post() request() readyRead() read() readAll()
       
  1846 */
       
  1847 qint64 QHttp::bytesAvailable() const
       
  1848 {
       
  1849     Q_D(const QHttp);
       
  1850 #if defined(QHTTP_DEBUG)
       
  1851     qDebug("QHttp::bytesAvailable(): %d bytes", (int)d->rba.size());
       
  1852 #endif
       
  1853     return qint64(d->rba.size());
       
  1854 }
       
  1855 
       
  1856 /*! \fn qint64 QHttp::readBlock(char *data, quint64 maxlen)
       
  1857 
       
  1858     Use read() instead.
       
  1859 */
       
  1860 
       
  1861 /*!
       
  1862     Reads \a maxlen bytes from the response content into \a data and
       
  1863     returns the number of bytes read. Returns -1 if an error occurred.
       
  1864 
       
  1865     \sa get() post() request() readyRead() bytesAvailable() readAll()
       
  1866 */
       
  1867 qint64 QHttp::read(char *data, qint64 maxlen)
       
  1868 {
       
  1869     Q_D(QHttp);
       
  1870     if (data == 0 && maxlen != 0) {
       
  1871         qWarning("QHttp::read: Null pointer error");
       
  1872         return -1;
       
  1873     }
       
  1874     if (maxlen >= d->rba.size())
       
  1875         maxlen = d->rba.size();
       
  1876     int readSoFar = 0;
       
  1877     while (!d->rba.isEmpty() && readSoFar < maxlen) {
       
  1878         int nextBlockSize = d->rba.nextDataBlockSize();
       
  1879         int bytesToRead = qMin<qint64>(maxlen - readSoFar, nextBlockSize);
       
  1880         memcpy(data + readSoFar, d->rba.readPointer(), bytesToRead);
       
  1881         d->rba.free(bytesToRead);
       
  1882         readSoFar += bytesToRead;
       
  1883     }
       
  1884 
       
  1885     d->bytesDone += maxlen;
       
  1886 #if defined(QHTTP_DEBUG)
       
  1887     qDebug("QHttp::read(): read %lld bytes (%lld bytes done)", maxlen, d->bytesDone);
       
  1888 #endif
       
  1889     return maxlen;
       
  1890 }
       
  1891 
       
  1892 /*!
       
  1893     Reads all the bytes from the response content and returns them.
       
  1894 
       
  1895     \sa get() post() request() readyRead() bytesAvailable() read()
       
  1896 */
       
  1897 QByteArray QHttp::readAll()
       
  1898 {
       
  1899     qint64 avail = bytesAvailable();
       
  1900     QByteArray tmp;
       
  1901     tmp.resize(int(avail));
       
  1902     qint64 got = read(tmp.data(), int(avail));
       
  1903     tmp.resize(got);
       
  1904     return tmp;
       
  1905 }
       
  1906 
       
  1907 /*!
       
  1908     Returns the identifier of the HTTP request being executed or 0 if
       
  1909     there is no request being executed (i.e. they've all finished).
       
  1910 
       
  1911     \sa currentRequest()
       
  1912 */
       
  1913 int QHttp::currentId() const
       
  1914 {
       
  1915     Q_D(const QHttp);
       
  1916     if (d->pending.isEmpty())
       
  1917         return 0;
       
  1918     return d->pending.first()->id;
       
  1919 }
       
  1920 
       
  1921 /*!
       
  1922     Returns the request header of the HTTP request being executed. If
       
  1923     the request is one issued by setHost() or close(), it
       
  1924     returns an invalid request header, i.e.
       
  1925     QHttpRequestHeader::isValid() returns false.
       
  1926 
       
  1927     \sa currentId()
       
  1928 */
       
  1929 QHttpRequestHeader QHttp::currentRequest() const
       
  1930 {
       
  1931     Q_D(const QHttp);
       
  1932     if (!d->pending.isEmpty()) {
       
  1933         QHttpRequest *r = d->pending.first();
       
  1934         if (r->hasRequestHeader())
       
  1935             return r->requestHeader();
       
  1936     }
       
  1937     return QHttpRequestHeader();
       
  1938 }
       
  1939 
       
  1940 /*!
       
  1941     Returns the received response header of the most recently finished HTTP
       
  1942     request. If no response has yet been received
       
  1943     QHttpResponseHeader::isValid() will return false.
       
  1944 
       
  1945     \sa currentRequest()
       
  1946 */
       
  1947 QHttpResponseHeader QHttp::lastResponse() const
       
  1948 {
       
  1949     Q_D(const QHttp);
       
  1950     return d->response;
       
  1951 }
       
  1952 
       
  1953 /*!
       
  1954     Returns the QIODevice pointer that is used as the data source of the HTTP
       
  1955     request being executed. If there is no current request or if the request
       
  1956     does not use an IO device as the data source, this function returns 0.
       
  1957 
       
  1958     This function can be used to delete the QIODevice in the slot connected to
       
  1959     the requestFinished() signal.
       
  1960 
       
  1961     \sa currentDestinationDevice() post() request()
       
  1962 */
       
  1963 QIODevice *QHttp::currentSourceDevice() const
       
  1964 {
       
  1965     Q_D(const QHttp);
       
  1966     if (d->pending.isEmpty())
       
  1967         return 0;
       
  1968     return d->pending.first()->sourceDevice();
       
  1969 }
       
  1970 
       
  1971 /*!
       
  1972     Returns the QIODevice pointer that is used as to store the data of the HTTP
       
  1973     request being executed. If there is no current request or if the request
       
  1974     does not store the data to an IO device, this function returns 0.
       
  1975 
       
  1976     This function can be used to delete the QIODevice in the slot connected to
       
  1977     the requestFinished() signal.
       
  1978 
       
  1979     \sa currentSourceDevice() get() post() request()
       
  1980 */
       
  1981 QIODevice *QHttp::currentDestinationDevice() const
       
  1982 {
       
  1983     Q_D(const QHttp);
       
  1984     if (d->pending.isEmpty())
       
  1985         return 0;
       
  1986     return d->pending.first()->destinationDevice();
       
  1987 }
       
  1988 
       
  1989 /*!
       
  1990     Returns true if there are any requests scheduled that have not yet
       
  1991     been executed; otherwise returns false.
       
  1992 
       
  1993     The request that is being executed is \e not considered as a
       
  1994     scheduled request.
       
  1995 
       
  1996     \sa clearPendingRequests() currentId() currentRequest()
       
  1997 */
       
  1998 bool QHttp::hasPendingRequests() const
       
  1999 {
       
  2000     Q_D(const QHttp);
       
  2001     return d->pending.count() > 1;
       
  2002 }
       
  2003 
       
  2004 /*!
       
  2005     Deletes all pending requests from the list of scheduled requests.
       
  2006     This does not affect the request that is being executed. If
       
  2007     you want to stop this as well, use abort().
       
  2008 
       
  2009     \sa hasPendingRequests() abort()
       
  2010 */
       
  2011 void QHttp::clearPendingRequests()
       
  2012 {
       
  2013     Q_D(QHttp);
       
  2014     // delete all entires except the first one
       
  2015     while (d->pending.count() > 1)
       
  2016         delete d->pending.takeLast();
       
  2017 }
       
  2018 
       
  2019 /*!
       
  2020     Sets the HTTP server that is used for requests to \a hostName on
       
  2021     port \a port.
       
  2022 
       
  2023     The function does not block; instead, it returns immediately. The request
       
  2024     is scheduled, and its execution is performed asynchronously. The
       
  2025     function returns a unique identifier which is passed by
       
  2026     requestStarted() and requestFinished().
       
  2027 
       
  2028     When the request is started the requestStarted() signal is
       
  2029     emitted. When it is finished the requestFinished() signal is
       
  2030     emitted.
       
  2031 
       
  2032     \sa get() post() head() request() requestStarted() requestFinished() done()
       
  2033 */
       
  2034 int QHttp::setHost(const QString &hostName, quint16 port)
       
  2035 {
       
  2036     Q_D(QHttp);
       
  2037     return d->addRequest(new QHttpSetHostRequest(hostName, port, ConnectionModeHttp));
       
  2038 }
       
  2039 
       
  2040 /*!
       
  2041     Sets the HTTP server that is used for requests to \a hostName on
       
  2042     port \a port using the connection mode \a mode.
       
  2043 
       
  2044     If port is 0, it will use the default port for the \a mode used
       
  2045     (80 for HTTP and 443 for HTTPS).
       
  2046 
       
  2047     The function does not block; instead, it returns immediately. The request
       
  2048     is scheduled, and its execution is performed asynchronously. The
       
  2049     function returns a unique identifier which is passed by
       
  2050     requestStarted() and requestFinished().
       
  2051 
       
  2052     When the request is started the requestStarted() signal is
       
  2053     emitted. When it is finished the requestFinished() signal is
       
  2054     emitted.
       
  2055 
       
  2056     \sa get() post() head() request() requestStarted() requestFinished() done()
       
  2057 */
       
  2058 int QHttp::setHost(const QString &hostName, ConnectionMode mode, quint16 port)
       
  2059 {
       
  2060 #ifdef QT_NO_OPENSSL
       
  2061     if (mode == ConnectionModeHttps)
       
  2062         qWarning("QHttp::setHost: HTTPS connection requested but SSL support not compiled in");
       
  2063 #endif
       
  2064     Q_D(QHttp);
       
  2065     if (port == 0)
       
  2066         port = (mode == ConnectionModeHttp) ? 80 : 443;
       
  2067     return d->addRequest(new QHttpSetHostRequest(hostName, port, mode));
       
  2068 }
       
  2069 
       
  2070 /*!
       
  2071     Replaces the internal QTcpSocket that QHttp uses with \a
       
  2072     socket. This is useful if you want to use your own custom QTcpSocket
       
  2073     subclass instead of the plain QTcpSocket that QHttp uses by default.
       
  2074     QHttp does not take ownership of the socket, and will not delete \a
       
  2075     socket when destroyed.
       
  2076 
       
  2077     The function does not block; instead, it returns immediately. The request
       
  2078     is scheduled, and its execution is performed asynchronously. The
       
  2079     function returns a unique identifier which is passed by
       
  2080     requestStarted() and requestFinished().
       
  2081 
       
  2082     When the request is started the requestStarted() signal is
       
  2083     emitted. When it is finished the requestFinished() signal is
       
  2084     emitted.
       
  2085 
       
  2086     Note: If QHttp is used in a non-GUI thread that runs its own event
       
  2087     loop, you must move \a socket to that thread before calling setSocket().
       
  2088 
       
  2089     \sa QObject::moveToThread(), {Thread Support in Qt}
       
  2090 */
       
  2091 int QHttp::setSocket(QTcpSocket *socket)
       
  2092 {
       
  2093     Q_D(QHttp);
       
  2094     return d->addRequest(new QHttpSetSocketRequest(socket));
       
  2095 }
       
  2096 
       
  2097 /*!
       
  2098     This function sets the user name \a userName and password \a
       
  2099     password for web pages that require authentication.
       
  2100 
       
  2101     The function does not block; instead, it returns immediately. The request
       
  2102     is scheduled, and its execution is performed asynchronously. The
       
  2103     function returns a unique identifier which is passed by
       
  2104     requestStarted() and requestFinished().
       
  2105 
       
  2106     When the request is started the requestStarted() signal is
       
  2107     emitted. When it is finished the requestFinished() signal is
       
  2108     emitted.
       
  2109 */
       
  2110 int QHttp::setUser(const QString &userName, const QString &password)
       
  2111 {
       
  2112     Q_D(QHttp);
       
  2113     return d->addRequest(new QHttpSetUserRequest(userName, password));
       
  2114 }
       
  2115 
       
  2116 #ifndef QT_NO_NETWORKPROXY
       
  2117 
       
  2118 /*!
       
  2119     Enables HTTP proxy support, using the proxy server \a host on port \a
       
  2120     port. \a username and \a password can be provided if the proxy server
       
  2121     requires authentication.
       
  2122 
       
  2123     Example:
       
  2124 
       
  2125     \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 7
       
  2126 
       
  2127     QHttp supports non-transparent web proxy servers only, such as the Squid
       
  2128     Web proxy cache server (from \l http://www.squid.org/). For transparent
       
  2129     proxying, such as SOCKS5, use QNetworkProxy instead.
       
  2130 
       
  2131     \note setProxy() has to be called before setHost() for it to take effect.
       
  2132     If setProxy() is called after setHost(), then it will not apply until after 
       
  2133     setHost() is called again.
       
  2134 
       
  2135     \sa QFtp::setProxy()
       
  2136 */
       
  2137 int QHttp::setProxy(const QString &host, int port,
       
  2138                     const QString &username, const QString &password)
       
  2139 {
       
  2140     Q_D(QHttp);
       
  2141     QNetworkProxy proxy(QNetworkProxy::HttpProxy, host, port, username, password);
       
  2142     return d->addRequest(new QHttpSetProxyRequest(proxy));
       
  2143 }
       
  2144 
       
  2145 /*!
       
  2146     \overload
       
  2147 
       
  2148     Enables HTTP proxy support using the proxy settings from \a
       
  2149     proxy. If \a proxy is a transparent proxy, QHttp will call
       
  2150     QAbstractSocket::setProxy() on the underlying socket. If the type
       
  2151     is QNetworkProxy::HttpCachingProxy, QHttp will behave like the
       
  2152     previous function.
       
  2153 
       
  2154     \note for compatibility with Qt 4.3, if the proxy type is
       
  2155     QNetworkProxy::HttpProxy and the request type is unencrypted (that
       
  2156     is, ConnectionModeHttp), QHttp will treat the proxy as a caching
       
  2157     proxy.
       
  2158 */
       
  2159 int QHttp::setProxy(const QNetworkProxy &proxy)
       
  2160 {
       
  2161     Q_D(QHttp);
       
  2162     return d->addRequest(new QHttpSetProxyRequest(proxy));
       
  2163 }
       
  2164 
       
  2165 #endif
       
  2166 
       
  2167 /*!
       
  2168     Sends a get request for \a path to the server set by setHost() or
       
  2169     as specified in the constructor.
       
  2170 
       
  2171     \a path must be a absolute path like \c /index.html or an
       
  2172     absolute URI like \c http://example.com/index.html and
       
  2173     must be encoded with either QUrl::toPercentEncoding() or
       
  2174     QUrl::encodedPath().
       
  2175 
       
  2176     If the IO device \a to is 0 the readyRead() signal is emitted
       
  2177     every time new content data is available to read.
       
  2178 
       
  2179     If the IO device \a to is not 0, the content data of the response
       
  2180     is written directly to the device. Make sure that the \a to
       
  2181     pointer is valid for the duration of the operation (it is safe to
       
  2182     delete it when the requestFinished() signal is emitted).
       
  2183 
       
  2184     \section1 Request Processing
       
  2185 
       
  2186     The function does not block; instead, it returns immediately. The request
       
  2187     is scheduled, and its execution is performed asynchronously. The
       
  2188     function returns a unique identifier which is passed by
       
  2189     requestStarted() and requestFinished().
       
  2190 
       
  2191     When the request is started the requestStarted() signal is
       
  2192     emitted. When it is finished the requestFinished() signal is
       
  2193     emitted.
       
  2194 
       
  2195     \sa setHost(), post(), head(), request(), requestStarted(),
       
  2196     requestFinished(), done()
       
  2197 */
       
  2198 int QHttp::get(const QString &path, QIODevice *to)
       
  2199 {
       
  2200     Q_D(QHttp);
       
  2201     QHttpRequestHeader header(QLatin1String("GET"), path);
       
  2202     header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive"));
       
  2203     return d->addRequest(new QHttpPGHRequest(header, (QIODevice *) 0, to));
       
  2204 }
       
  2205 
       
  2206 /*!
       
  2207     Sends a post request for \a path to the server set by setHost() or
       
  2208     as specified in the constructor.
       
  2209 
       
  2210     \a path must be an absolute path like \c /index.html or an
       
  2211     absolute URI like \c http://example.com/index.html and
       
  2212     must be encoded with either QUrl::toPercentEncoding() or
       
  2213     QUrl::encodedPath().
       
  2214 
       
  2215     The incoming data comes via the \a data IO device.
       
  2216 
       
  2217     If the IO device \a to is 0 the readyRead() signal is emitted
       
  2218     every time new content data is available to read.
       
  2219 
       
  2220     If the IO device \a to is not 0, the content data of the response
       
  2221     is written directly to the device. Make sure that the \a to
       
  2222     pointer is valid for the duration of the operation (it is safe to
       
  2223     delete it when the requestFinished() signal is emitted).
       
  2224 
       
  2225     The function does not block; instead, it returns immediately. The request
       
  2226     is scheduled, and its execution is performed asynchronously. The
       
  2227     function returns a unique identifier which is passed by
       
  2228     requestStarted() and requestFinished().
       
  2229 
       
  2230     When the request is started the requestStarted() signal is
       
  2231     emitted. When it is finished the requestFinished() signal is
       
  2232     emitted.
       
  2233 
       
  2234     \sa setHost() get() head() request() requestStarted() requestFinished() done()
       
  2235 */
       
  2236 int QHttp::post(const QString &path, QIODevice *data, QIODevice *to )
       
  2237 {
       
  2238     Q_D(QHttp);
       
  2239     QHttpRequestHeader header(QLatin1String("POST"), path);
       
  2240     header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive"));
       
  2241     return d->addRequest(new QHttpPGHRequest(header, data, to));
       
  2242 }
       
  2243 
       
  2244 /*!
       
  2245     \overload
       
  2246 
       
  2247     \a data is used as the content data of the HTTP request.
       
  2248 */
       
  2249 int QHttp::post(const QString &path, const QByteArray &data, QIODevice *to)
       
  2250 {
       
  2251     Q_D(QHttp);
       
  2252     QHttpRequestHeader header(QLatin1String("POST"), path);
       
  2253     header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive"));
       
  2254     return d->addRequest(new QHttpPGHRequest(header, new QByteArray(data), to));
       
  2255 }
       
  2256 
       
  2257 /*!
       
  2258     Sends a header request for \a path to the server set by setHost()
       
  2259     or as specified in the constructor.
       
  2260 
       
  2261     \a path must be an absolute path like \c /index.html or an
       
  2262     absolute URI like \c http://example.com/index.html.
       
  2263 
       
  2264     The function does not block; instead, it returns immediately. The request
       
  2265     is scheduled, and its execution is performed asynchronously. The
       
  2266     function returns a unique identifier which is passed by
       
  2267     requestStarted() and requestFinished().
       
  2268 
       
  2269     When the request is started the requestStarted() signal is
       
  2270     emitted. When it is finished the requestFinished() signal is
       
  2271     emitted.
       
  2272 
       
  2273     \sa setHost() get() post() request() requestStarted() requestFinished() done()
       
  2274 */
       
  2275 int QHttp::head(const QString &path)
       
  2276 {
       
  2277     Q_D(QHttp);
       
  2278     QHttpRequestHeader header(QLatin1String("HEAD"), path);
       
  2279     header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive"));
       
  2280     return d->addRequest(new QHttpPGHRequest(header, (QIODevice*)0, 0));
       
  2281 }
       
  2282 
       
  2283 /*!
       
  2284     Sends a request to the server set by setHost() or as specified in
       
  2285     the constructor. Uses the \a header as the HTTP request header.
       
  2286     You are responsible for setting up a header that is appropriate
       
  2287     for your request.
       
  2288 
       
  2289     The incoming data comes via the \a data IO device.
       
  2290 
       
  2291     If the IO device \a to is 0 the readyRead() signal is emitted
       
  2292     every time new content data is available to read.
       
  2293 
       
  2294     If the IO device \a to is not 0, the content data of the response
       
  2295     is written directly to the device. Make sure that the \a to
       
  2296     pointer is valid for the duration of the operation (it is safe to
       
  2297     delete it when the requestFinished() signal is emitted).
       
  2298 
       
  2299     The function does not block; instead, it returns immediately. The request
       
  2300     is scheduled, and its execution is performed asynchronously. The
       
  2301     function returns a unique identifier which is passed by
       
  2302     requestStarted() and requestFinished().
       
  2303 
       
  2304     When the request is started the requestStarted() signal is
       
  2305     emitted. When it is finished the requestFinished() signal is
       
  2306     emitted.
       
  2307 
       
  2308     \sa setHost() get() post() head() requestStarted() requestFinished() done()
       
  2309 */
       
  2310 int QHttp::request(const QHttpRequestHeader &header, QIODevice *data, QIODevice *to)
       
  2311 {
       
  2312     Q_D(QHttp);
       
  2313     return d->addRequest(new QHttpNormalRequest(header, data, to));
       
  2314 }
       
  2315 
       
  2316 /*!
       
  2317     \overload
       
  2318 
       
  2319     \a data is used as the content data of the HTTP request.
       
  2320 */
       
  2321 int QHttp::request(const QHttpRequestHeader &header, const QByteArray &data, QIODevice *to )
       
  2322 {
       
  2323     Q_D(QHttp);
       
  2324     return d->addRequest(new QHttpNormalRequest(header, new QByteArray(data), to));
       
  2325 }
       
  2326 
       
  2327 /*!
       
  2328     Closes the connection; this is useful if you have a keep-alive
       
  2329     connection and want to close it.
       
  2330 
       
  2331     For the requests issued with get(), post() and head(), QHttp sets
       
  2332     the connection to be keep-alive. You can also do this using the
       
  2333     header you pass to the request() function. QHttp only closes the
       
  2334     connection to the HTTP server if the response header requires it
       
  2335     to do so.
       
  2336 
       
  2337     The function does not block; instead, it returns immediately. The request
       
  2338     is scheduled, and its execution is performed asynchronously. The
       
  2339     function returns a unique identifier which is passed by
       
  2340     requestStarted() and requestFinished().
       
  2341 
       
  2342     When the request is started the requestStarted() signal is
       
  2343     emitted. When it is finished the requestFinished() signal is
       
  2344     emitted.
       
  2345 
       
  2346     If you want to close the connection immediately, you have to use
       
  2347     abort() instead.
       
  2348 
       
  2349     \sa stateChanged() abort() requestStarted() requestFinished() done()
       
  2350 */
       
  2351 int QHttp::close()
       
  2352 {
       
  2353     Q_D(QHttp);
       
  2354     return d->addRequest(new QHttpCloseRequest());
       
  2355 }
       
  2356 
       
  2357 /*!
       
  2358     \obsolete
       
  2359 
       
  2360     Behaves the same as close().
       
  2361 */
       
  2362 int QHttp::closeConnection()
       
  2363 {
       
  2364     Q_D(QHttp);
       
  2365     return d->addRequest(new QHttpCloseRequest());
       
  2366 }
       
  2367 
       
  2368 int QHttpPrivate::addRequest(QHttpNormalRequest *req)
       
  2369 {
       
  2370     QHttpRequestHeader h = req->requestHeader();
       
  2371     if (h.path().isEmpty()) {
       
  2372         // note: the following qWarning is autotested. If you change it, change the test too.
       
  2373         qWarning("QHttp: empty path requested is invalid -- using '/'");
       
  2374         h.setRequest(h.method(), QLatin1String("/"), h.majorVersion(), h.minorVersion());
       
  2375         req->setRequestHeader(h);
       
  2376     }
       
  2377 
       
  2378     // contine below
       
  2379     return addRequest(static_cast<QHttpRequest *>(req));
       
  2380 }
       
  2381 
       
  2382 int QHttpPrivate::addRequest(QHttpRequest *req)
       
  2383 {
       
  2384     Q_Q(QHttp);
       
  2385     pending.append(req);
       
  2386 
       
  2387     if (pending.count() == 1) {
       
  2388         // don't emit the requestStarted() signal before the id is returned
       
  2389         QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
       
  2390     }
       
  2391     return req->id;
       
  2392 }
       
  2393 
       
  2394 void QHttpPrivate::_q_startNextRequest()
       
  2395 {
       
  2396     Q_Q(QHttp);
       
  2397     if (pending.isEmpty())
       
  2398         return;
       
  2399     QHttpRequest *r = pending.first();
       
  2400 
       
  2401     error = QHttp::NoError;
       
  2402     errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Unknown error"));
       
  2403 
       
  2404     if (q->bytesAvailable() != 0)
       
  2405         q->readAll(); // clear the data
       
  2406     emit q->requestStarted(r->id);
       
  2407     r->start(q);
       
  2408 }
       
  2409 
       
  2410 void QHttpPrivate::_q_slotSendRequest()
       
  2411 {
       
  2412     if (hostName.isNull()) {
       
  2413         finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "No server set to connect to")),
       
  2414                           QHttp::UnknownError);
       
  2415         return;
       
  2416     }
       
  2417 
       
  2418     QString connectionHost = hostName;
       
  2419     int connectionPort = port;
       
  2420     bool sslInUse = false;
       
  2421 
       
  2422 #ifndef QT_NO_OPENSSL
       
  2423     QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);
       
  2424     if (mode == QHttp::ConnectionModeHttps || (sslSocket && sslSocket->isEncrypted()))
       
  2425         sslInUse = true;
       
  2426 #endif
       
  2427 
       
  2428 #ifndef QT_NO_NETWORKPROXY
       
  2429     bool cachingProxyInUse = false;
       
  2430     bool transparentProxyInUse = false;
       
  2431     if (proxy.type() == QNetworkProxy::DefaultProxy)
       
  2432         proxy = QNetworkProxy::applicationProxy();
       
  2433 
       
  2434     if (proxy.type() == QNetworkProxy::HttpCachingProxy) {
       
  2435         if (proxy.hostName().isEmpty())
       
  2436             proxy.setType(QNetworkProxy::NoProxy);
       
  2437         else
       
  2438             cachingProxyInUse = true;
       
  2439     } else if (proxy.type() == QNetworkProxy::HttpProxy) {
       
  2440         // Compatibility behaviour: HttpProxy can be used to mean both
       
  2441         // transparent and caching proxy
       
  2442         if (proxy.hostName().isEmpty()) {
       
  2443             proxy.setType(QNetworkProxy::NoProxy);
       
  2444         } else if (sslInUse) {
       
  2445             // Disallow use of cacheing proxy with HTTPS; instead fall back to
       
  2446             // transparent HTTP CONNECT proxying.
       
  2447             transparentProxyInUse = true;
       
  2448         } else {
       
  2449             proxy.setType(QNetworkProxy::HttpCachingProxy);
       
  2450             cachingProxyInUse = true;
       
  2451         }
       
  2452     }
       
  2453 
       
  2454     // Proxy support. Insert the Proxy-Authorization item into the
       
  2455     // header before it's sent off to the proxy.
       
  2456     if (cachingProxyInUse) {
       
  2457         QUrl proxyUrl;
       
  2458         proxyUrl.setScheme(QLatin1String("http"));
       
  2459         proxyUrl.setHost(hostName);
       
  2460         if (port && port != 80)
       
  2461             proxyUrl.setPort(port);
       
  2462         QString request = QString::fromAscii(proxyUrl.resolved(QUrl::fromEncoded(header.path().toLatin1())).toEncoded());
       
  2463 
       
  2464         header.setRequest(header.method(), request, header.majorVersion(), header.minorVersion());
       
  2465         header.setValue(QLatin1String("Proxy-Connection"), QLatin1String("keep-alive"));
       
  2466 
       
  2467         QAuthenticatorPrivate *auth = QAuthenticatorPrivate::getPrivate(proxyAuthenticator);
       
  2468         if (auth && auth->method != QAuthenticatorPrivate::None) {
       
  2469             QByteArray response = auth->calculateResponse(header.method().toLatin1(), header.path().toLatin1());
       
  2470             header.setValue(QLatin1String("Proxy-Authorization"), QString::fromLatin1(response));
       
  2471         }
       
  2472 
       
  2473         connectionHost = proxy.hostName();
       
  2474         connectionPort = proxy.port();
       
  2475     }
       
  2476 
       
  2477     if (transparentProxyInUse || sslInUse) {
       
  2478         socket->setProxy(proxy);
       
  2479     }
       
  2480 #endif
       
  2481 
       
  2482     // Username support. Insert the user and password into the query
       
  2483     // string.
       
  2484     QAuthenticatorPrivate *auth = QAuthenticatorPrivate::getPrivate(authenticator);
       
  2485     if (auth && auth->method != QAuthenticatorPrivate::None) {
       
  2486         QByteArray response = auth->calculateResponse(header.method().toLatin1(), header.path().toLatin1());
       
  2487         header.setValue(QLatin1String("Authorization"), QString::fromLatin1(response));
       
  2488     }
       
  2489 
       
  2490     // Do we need to setup a new connection or can we reuse an
       
  2491     // existing one?
       
  2492     if (socket->peerName() != connectionHost || socket->peerPort() != connectionPort
       
  2493         || socket->state() != QTcpSocket::ConnectedState
       
  2494 #ifndef QT_NO_OPENSSL
       
  2495         || (sslSocket && sslSocket->isEncrypted() != (mode == QHttp::ConnectionModeHttps))
       
  2496 #endif
       
  2497         ) {
       
  2498         socket->blockSignals(true);
       
  2499         socket->abort();
       
  2500         socket->blockSignals(false);
       
  2501 
       
  2502         setState(QHttp::Connecting);
       
  2503 #ifndef QT_NO_OPENSSL
       
  2504         if (sslSocket && mode == QHttp::ConnectionModeHttps) {
       
  2505             sslSocket->connectToHostEncrypted(hostName, port);
       
  2506         } else
       
  2507 #endif
       
  2508         {
       
  2509             socket->connectToHost(connectionHost, connectionPort);
       
  2510         }
       
  2511     } else {
       
  2512         _q_slotConnected();
       
  2513     }
       
  2514 
       
  2515 }
       
  2516 
       
  2517 void QHttpPrivate::finishedWithSuccess()
       
  2518 {
       
  2519     Q_Q(QHttp);
       
  2520     if (pending.isEmpty())
       
  2521         return;
       
  2522     QHttpRequest *r = pending.first();
       
  2523 
       
  2524     // did we recurse?
       
  2525     if (r->finished)
       
  2526         return;
       
  2527     r->finished = true;
       
  2528     hasFinishedWithError = false;
       
  2529 
       
  2530     emit q->requestFinished(r->id, false);
       
  2531     if (hasFinishedWithError) {
       
  2532         // we recursed and changed into an error. The finishedWithError function
       
  2533         // below has emitted the done(bool) signal and cleared the queue by now.
       
  2534         return;
       
  2535     }
       
  2536 
       
  2537     pending.removeFirst();
       
  2538     delete r;
       
  2539 
       
  2540     if (pending.isEmpty()) {
       
  2541         emit q->done(false);
       
  2542     } else {
       
  2543         _q_startNextRequest();
       
  2544     }
       
  2545 }
       
  2546 
       
  2547 void QHttpPrivate::finishedWithError(const QString &detail, int errorCode)
       
  2548 {
       
  2549     Q_Q(QHttp);
       
  2550     if (pending.isEmpty())
       
  2551         return;
       
  2552     QHttpRequest *r = pending.first();
       
  2553     hasFinishedWithError = true;
       
  2554 
       
  2555     error = QHttp::Error(errorCode);
       
  2556     errorString = detail;
       
  2557 
       
  2558     // did we recurse?
       
  2559     if (!r->finished) {
       
  2560         r->finished = true;
       
  2561         emit q->requestFinished(r->id, true);
       
  2562     }
       
  2563 
       
  2564     while (!pending.isEmpty())
       
  2565         delete pending.takeFirst();
       
  2566     emit q->done(hasFinishedWithError);
       
  2567 }
       
  2568 
       
  2569 void QHttpPrivate::_q_slotClosed()
       
  2570 {
       
  2571     Q_Q(QHttp);
       
  2572 
       
  2573     if (state == QHttp::Reading) {
       
  2574         if (response.hasKey(QLatin1String("content-length"))) {
       
  2575             // We got Content-Length, so did we get all bytes?
       
  2576             if (bytesDone + q->bytesAvailable() != response.contentLength()) {
       
  2577                 finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Wrong content length")), QHttp::WrongContentLength);
       
  2578             }
       
  2579         }
       
  2580     } else if (state == QHttp::Connecting || state == QHttp::Sending) {
       
  2581         finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Server closed connection unexpectedly")), QHttp::UnexpectedClose);
       
  2582     }
       
  2583 
       
  2584     postDevice = 0;
       
  2585     if (state != QHttp::Closing)
       
  2586         setState(QHttp::Closing);
       
  2587     QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection);
       
  2588 }
       
  2589 
       
  2590 void QHttpPrivate::_q_continuePost()
       
  2591 {
       
  2592     if (pendingPost) {
       
  2593         pendingPost = false;
       
  2594         setState(QHttp::Sending);
       
  2595         _q_slotBytesWritten(0);
       
  2596     }
       
  2597 }
       
  2598 
       
  2599 void QHttpPrivate::_q_slotConnected()
       
  2600 {
       
  2601     if (state != QHttp::Sending) {
       
  2602         bytesDone = 0;
       
  2603         setState(QHttp::Sending);
       
  2604     }
       
  2605 
       
  2606     QString str = header.toString();
       
  2607     bytesTotal = str.length();
       
  2608     socket->write(str.toLatin1(), bytesTotal);
       
  2609 #if defined(QHTTP_DEBUG)
       
  2610     qDebug("QHttp: write request header %p:\n---{\n%s}---", &header, str.toLatin1().constData());
       
  2611 #endif
       
  2612 
       
  2613     if (postDevice) {
       
  2614         postDevice->seek(0);    // reposition the device
       
  2615         bytesTotal += postDevice->size();
       
  2616         //check for 100-continue
       
  2617         if (header.value(QLatin1String("expect")).contains(QLatin1String("100-continue"), Qt::CaseInsensitive)) {
       
  2618             //create a time out for 2 secs.
       
  2619             pendingPost = true;
       
  2620             post100ContinueTimer.start(2000);
       
  2621         }
       
  2622     } else {
       
  2623         bytesTotal += buffer.size();
       
  2624         socket->write(buffer, buffer.size());
       
  2625     }
       
  2626 }
       
  2627 
       
  2628 void QHttpPrivate::_q_slotError(QAbstractSocket::SocketError err)
       
  2629 {
       
  2630     Q_Q(QHttp);
       
  2631     postDevice = 0;
       
  2632 
       
  2633     if (state == QHttp::Connecting || state == QHttp::Reading || state == QHttp::Sending) {
       
  2634         switch (err) {
       
  2635         case QTcpSocket::ConnectionRefusedError:
       
  2636             finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Connection refused (or timed out)")), QHttp::ConnectionRefused);
       
  2637             break;
       
  2638         case QTcpSocket::HostNotFoundError:
       
  2639             finishedWithError(QString::fromLatin1(QT_TRANSLATE_NOOP("QHttp", "Host %1 not found"))
       
  2640                               .arg(socket->peerName()), QHttp::HostNotFound);
       
  2641             break;
       
  2642         case QTcpSocket::RemoteHostClosedError:
       
  2643             if (state == QHttp::Sending && reconnectAttempts--) {
       
  2644                 setState(QHttp::Closing);
       
  2645                 setState(QHttp::Unconnected);
       
  2646                 socket->blockSignals(true);
       
  2647                 socket->abort();
       
  2648                 socket->blockSignals(false);
       
  2649                 QMetaObject::invokeMethod(q, "_q_slotSendRequest", Qt::QueuedConnection);
       
  2650                 return;
       
  2651             }
       
  2652             break;
       
  2653 #ifndef QT_NO_NETWORKPROXY
       
  2654         case QTcpSocket::ProxyAuthenticationRequiredError:
       
  2655             finishedWithError(socket->errorString(), QHttp::ProxyAuthenticationRequiredError);
       
  2656             break;
       
  2657 #endif
       
  2658         default:
       
  2659             finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "HTTP request failed")), QHttp::UnknownError);
       
  2660             break;
       
  2661         }
       
  2662     }
       
  2663 
       
  2664     closeConn();
       
  2665 }
       
  2666 
       
  2667 #ifndef QT_NO_OPENSSL
       
  2668 void QHttpPrivate::_q_slotEncryptedBytesWritten(qint64 written)
       
  2669 {
       
  2670     Q_UNUSED(written);
       
  2671     postMoreData();
       
  2672 }
       
  2673 #endif
       
  2674 
       
  2675 void QHttpPrivate::_q_slotBytesWritten(qint64 written)
       
  2676 {
       
  2677     Q_Q(QHttp);
       
  2678     bytesDone += written;
       
  2679     emit q->dataSendProgress(bytesDone, bytesTotal);
       
  2680     postMoreData();
       
  2681 }
       
  2682 
       
  2683 // Send the POST data
       
  2684 void QHttpPrivate::postMoreData()
       
  2685 {
       
  2686     if (pendingPost)
       
  2687         return;
       
  2688 
       
  2689     if (!postDevice)
       
  2690         return;
       
  2691 
       
  2692     // the following is backported code from Qt 4.6 QNetworkAccessManager.
       
  2693     // We also have to check the encryptedBytesToWrite() if it is an SSL socket.
       
  2694 #ifndef QT_NO_OPENSSL
       
  2695     QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
       
  2696     // if it is really an ssl socket, check more than just bytesToWrite()
       
  2697     if ((socket->bytesToWrite() + (sslSocket ? sslSocket->encryptedBytesToWrite() : 0)) == 0) {
       
  2698 #else
       
  2699     if (socket->bytesToWrite() == 0) {
       
  2700 #endif
       
  2701         int max = qMin<qint64>(4096, postDevice->size() - postDevice->pos());
       
  2702         QByteArray arr;
       
  2703         arr.resize(max);
       
  2704 
       
  2705         int n = postDevice->read(arr.data(), max);
       
  2706         if (n < 0) {
       
  2707             qWarning("Could not read enough bytes from the device");
       
  2708             closeConn();
       
  2709             return;
       
  2710         }
       
  2711         if (postDevice->atEnd()) {
       
  2712             postDevice = 0;
       
  2713         }
       
  2714 
       
  2715         socket->write(arr, n);
       
  2716     }
       
  2717 }
       
  2718 
       
  2719 void QHttpPrivate::_q_slotReadyRead()
       
  2720 {
       
  2721     Q_Q(QHttp);
       
  2722     QHttp::State oldState = state;
       
  2723     if (state != QHttp::Reading) {
       
  2724         setState(QHttp::Reading);
       
  2725         readHeader = true;
       
  2726         headerStr = QLatin1String("");
       
  2727         bytesDone = 0;
       
  2728         chunkedSize = -1;
       
  2729         repost = false;
       
  2730     }
       
  2731 
       
  2732     while (readHeader) {
       
  2733         bool end = false;
       
  2734         QString tmp;
       
  2735         while (!end && socket->canReadLine()) {
       
  2736             tmp = QString::fromAscii(socket->readLine());
       
  2737             if (tmp == QLatin1String("\r\n") || tmp == QLatin1String("\n") || tmp.isEmpty())
       
  2738                 end = true;
       
  2739             else
       
  2740                 headerStr += tmp;
       
  2741         }
       
  2742 
       
  2743         if (!end)
       
  2744             return;
       
  2745 
       
  2746         response = QHttpResponseHeader(headerStr);
       
  2747         headerStr = QLatin1String("");
       
  2748 #if defined(QHTTP_DEBUG)
       
  2749         qDebug("QHttp: read response header:\n---{\n%s}---", response.toString().toLatin1().constData());
       
  2750 #endif
       
  2751         // Check header
       
  2752         if (!response.isValid()) {
       
  2753             finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Invalid HTTP response header")),
       
  2754                               QHttp::InvalidResponseHeader);
       
  2755             closeConn();
       
  2756             return;
       
  2757         }
       
  2758 
       
  2759         int statusCode = response.statusCode();
       
  2760         if (statusCode == 401 || statusCode == 407) { // (Proxy) Authentication required
       
  2761             QAuthenticator *auth =
       
  2762 #ifndef QT_NO_NETWORKPROXY
       
  2763                 statusCode == 407
       
  2764                 ? &proxyAuthenticator :
       
  2765 #endif
       
  2766                 &authenticator;
       
  2767             if (auth->isNull())
       
  2768                 auth->detach();
       
  2769             QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(*auth);
       
  2770             priv->parseHttpResponse(response, (statusCode == 407));
       
  2771             if (priv->phase == QAuthenticatorPrivate::Done) {
       
  2772                 socket->blockSignals(true);
       
  2773 #ifndef QT_NO_NETWORKPROXY
       
  2774                 if (statusCode == 407)
       
  2775                     emit q->proxyAuthenticationRequired(proxy, auth);
       
  2776                 else
       
  2777 #endif
       
  2778                     emit q->authenticationRequired(hostName, port, auth);
       
  2779                 socket->blockSignals(false);
       
  2780             } else if (priv->phase == QAuthenticatorPrivate::Invalid) {
       
  2781                 finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Unknown authentication method")),
       
  2782                         QHttp::AuthenticationRequiredError);
       
  2783                 closeConn();
       
  2784                 return;
       
  2785             }
       
  2786 
       
  2787             // priv->phase will get reset to QAuthenticatorPrivate::Start if the authenticator got modified in the signal above.
       
  2788             if (priv->phase == QAuthenticatorPrivate::Done) {
       
  2789 #ifndef QT_NO_NETWORKPROXY
       
  2790                 if (statusCode == 407)
       
  2791                     finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Proxy authentication required")),
       
  2792                                       QHttp::ProxyAuthenticationRequiredError);
       
  2793                 else
       
  2794 #endif
       
  2795                     finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Authentication required")),
       
  2796                                       QHttp::AuthenticationRequiredError);
       
  2797                 closeConn();
       
  2798                 return;
       
  2799             } else {
       
  2800                 // close the connection if it isn't already and reconnect using the chosen authentication method
       
  2801                 bool willClose = (response.value(QLatin1String("proxy-connection")).toLower() == QLatin1String("close"))
       
  2802                                  || (response.value(QLatin1String("connection")).toLower() == QLatin1String("close"));
       
  2803                 if (willClose) {
       
  2804                     if (socket) {
       
  2805                         setState(QHttp::Closing);
       
  2806                         socket->blockSignals(true);
       
  2807                         socket->close();
       
  2808                         socket->blockSignals(false);
       
  2809                         socket->readAll();
       
  2810                     }
       
  2811                     _q_slotSendRequest();
       
  2812                     return;
       
  2813                 } else {
       
  2814                     repost = true;
       
  2815                 }
       
  2816             }
       
  2817         } else {
       
  2818             buffer.clear();
       
  2819         }
       
  2820 
       
  2821         if (response.statusCode() == 100 && pendingPost) {
       
  2822             // if we have pending POST, start sending data otherwise ignore
       
  2823             post100ContinueTimer.stop();
       
  2824             QMetaObject::invokeMethod(q, "_q_continuePost", Qt::QueuedConnection); 
       
  2825             return;
       
  2826         }
       
  2827 
       
  2828         // The 100-continue header is ignored (in case of no 'expect:100-continue' header),
       
  2829         // because when using the POST method, we send both the request header and data in
       
  2830         // one chunk.
       
  2831         if (response.statusCode() != 100) {
       
  2832             post100ContinueTimer.stop();
       
  2833             pendingPost = false;
       
  2834             readHeader = false;
       
  2835             if (response.hasKey(QLatin1String("transfer-encoding")) &&
       
  2836                 response.value(QLatin1String("transfer-encoding")).toLower().contains(QLatin1String("chunked")))
       
  2837                 chunkedSize = 0;
       
  2838 
       
  2839             if (!repost)
       
  2840                 emit q->responseHeaderReceived(response);
       
  2841             if (state == QHttp::Unconnected || state == QHttp::Closing)
       
  2842                 return;
       
  2843         } else {
       
  2844             // Restore the state, the next incoming data will be treated as if
       
  2845             // we never say the 100 response.
       
  2846             state = oldState;
       
  2847         }
       
  2848     }
       
  2849 
       
  2850     bool everythingRead = false;
       
  2851 
       
  2852     if (q->currentRequest().method() == QLatin1String("HEAD") ||
       
  2853         response.statusCode() == 304 || response.statusCode() == 204 ||
       
  2854         response.statusCode() == 205) {
       
  2855         // HEAD requests have only headers as replies
       
  2856         // These status codes never have a body:
       
  2857         //  304 Not Modified
       
  2858         //  204 No Content
       
  2859         //  205 Reset Content
       
  2860         everythingRead = true;
       
  2861     } else {
       
  2862         qint64 n = socket->bytesAvailable();
       
  2863         QByteArray *arr = 0;
       
  2864         if (chunkedSize != -1) {
       
  2865             // transfer-encoding is chunked
       
  2866             for (;;) {
       
  2867                 // get chunk size
       
  2868                 if (chunkedSize == 0) {
       
  2869                     if (!socket->canReadLine())
       
  2870                         break;
       
  2871                     QString sizeString = QString::fromAscii(socket->readLine());
       
  2872                     int tPos = sizeString.indexOf(QLatin1Char(';'));
       
  2873                     if (tPos != -1)
       
  2874                         sizeString.truncate(tPos);
       
  2875                     bool ok;
       
  2876                     chunkedSize = sizeString.toInt(&ok, 16);
       
  2877                     if (!ok) {
       
  2878                         finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Invalid HTTP chunked body")),
       
  2879                                           QHttp::WrongContentLength);
       
  2880                         closeConn();
       
  2881                         delete arr;
       
  2882                         return;
       
  2883                     }
       
  2884                     if (chunkedSize == 0) // last-chunk
       
  2885                         chunkedSize = -2;
       
  2886                 }
       
  2887 
       
  2888                 // read trailer
       
  2889                 while (chunkedSize == -2 && socket->canReadLine()) {
       
  2890                     QString read = QString::fromAscii(socket->readLine());
       
  2891                     if (read == QLatin1String("\r\n") || read == QLatin1String("\n"))
       
  2892                         chunkedSize = -1;
       
  2893                 }
       
  2894                 if (chunkedSize == -1) {
       
  2895                     everythingRead = true;
       
  2896                     break;
       
  2897                 }
       
  2898 
       
  2899                 // make sure that you can read the terminating CRLF,
       
  2900                 // otherwise wait until next time...
       
  2901                 n = socket->bytesAvailable();
       
  2902                 if (n == 0)
       
  2903                     break;
       
  2904                 if (n == chunkedSize || n == chunkedSize+1) {
       
  2905                     n = chunkedSize - 1;
       
  2906                     if (n == 0)
       
  2907                         break;
       
  2908                 }
       
  2909 
       
  2910                 // read data
       
  2911                 qint64 toRead = chunkedSize < 0 ? n : qMin(n, chunkedSize);
       
  2912                 if (!arr)
       
  2913                     arr = new QByteArray;
       
  2914                 uint oldArrSize = arr->size();
       
  2915                 arr->resize(oldArrSize + toRead);
       
  2916                 qint64 read = socket->read(arr->data()+oldArrSize, toRead);
       
  2917                 arr->resize(oldArrSize + read);
       
  2918 
       
  2919                 chunkedSize -= read;
       
  2920 
       
  2921                 if (chunkedSize == 0 && n - read >= 2) {
       
  2922                     // read terminating CRLF
       
  2923                     char tmp[2];
       
  2924                     socket->read(tmp, 2);
       
  2925                     if (tmp[0] != '\r' || tmp[1] != '\n') {
       
  2926                         finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Invalid HTTP chunked body")),
       
  2927                                           QHttp::WrongContentLength);
       
  2928                         closeConn();
       
  2929                         delete arr;
       
  2930                         return;
       
  2931                     }
       
  2932                 }
       
  2933             }
       
  2934         } else if (response.hasContentLength()) {
       
  2935             if (repost && (n < response.contentLength())) {
       
  2936                 // wait for the content to be available fully
       
  2937                 // if repost is required, the content is ignored
       
  2938                 return;
       
  2939             }
       
  2940             n = qMin(qint64(response.contentLength() - bytesDone), n);
       
  2941             if (n > 0) {
       
  2942                 arr = new QByteArray;
       
  2943                 arr->resize(n);
       
  2944                 qint64 read = socket->read(arr->data(), n);
       
  2945                 arr->resize(read);
       
  2946             }
       
  2947             if (bytesDone + q->bytesAvailable() + n == response.contentLength())
       
  2948                 everythingRead = true;
       
  2949         } else if (n > 0) {
       
  2950             // workaround for VC++ bug
       
  2951             QByteArray temp = socket->readAll();
       
  2952             arr = new QByteArray(temp);
       
  2953         }
       
  2954 
       
  2955         if (arr && !repost) {
       
  2956             n = arr->size();
       
  2957             if (toDevice) {
       
  2958                 qint64 bytesWritten;
       
  2959                 bytesWritten = toDevice->write(*arr, n);
       
  2960                 delete arr;
       
  2961                 arr = 0;
       
  2962                 // if writing to the device does not succeed, quit with error
       
  2963                 if (bytesWritten == -1 || bytesWritten < n) {
       
  2964                     finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Error writing response to device")), QHttp::UnknownError);
       
  2965                 } else {
       
  2966                     bytesDone += bytesWritten;
       
  2967 #if defined(QHTTP_DEBUG)
       
  2968                 qDebug("QHttp::_q_slotReadyRead(): read %lld bytes (%lld bytes done)", n, bytesDone);
       
  2969 #endif
       
  2970                 }
       
  2971                 if (response.hasContentLength())
       
  2972                     emit q->dataReadProgress(bytesDone, response.contentLength());
       
  2973                 else
       
  2974                     emit q->dataReadProgress(bytesDone, 0);
       
  2975             } else {
       
  2976                 char *ptr = rba.reserve(arr->size());
       
  2977                 memcpy(ptr, arr->data(), arr->size());
       
  2978                 delete arr;
       
  2979                 arr = 0;
       
  2980 #if defined(QHTTP_DEBUG)
       
  2981                 qDebug("QHttp::_q_slotReadyRead(): read %lld bytes (%lld bytes done)", n, bytesDone + q->bytesAvailable());
       
  2982 #endif
       
  2983                 if (response.hasContentLength())
       
  2984                     emit q->dataReadProgress(bytesDone + q->bytesAvailable(), response.contentLength());
       
  2985                 else
       
  2986                     emit q->dataReadProgress(bytesDone + q->bytesAvailable(), 0);
       
  2987                 emit q->readyRead(response);
       
  2988             }
       
  2989         }
       
  2990 
       
  2991         delete arr;
       
  2992     }
       
  2993 
       
  2994     if (everythingRead) {
       
  2995         if (repost) {
       
  2996             _q_slotSendRequest();
       
  2997             return;
       
  2998         }
       
  2999         // Handle "Connection: close"
       
  3000         if (response.value(QLatin1String("connection")).toLower() == QLatin1String("close")) {
       
  3001             closeConn();
       
  3002         } else {
       
  3003             setState(QHttp::Connected);
       
  3004             // Start a timer, so that we emit the keep alive signal
       
  3005             // "after" this method returned.
       
  3006             QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection);
       
  3007         }
       
  3008     }
       
  3009 }
       
  3010 
       
  3011 void QHttpPrivate::_q_slotDoFinished()
       
  3012 {
       
  3013     if (state == QHttp::Connected) {
       
  3014         finishedWithSuccess();
       
  3015     } else if (state != QHttp::Unconnected) {
       
  3016         setState(QHttp::Unconnected);
       
  3017         finishedWithSuccess();
       
  3018     }
       
  3019 }
       
  3020 
       
  3021 
       
  3022 /*!
       
  3023     Returns the current state of the object. When the state changes,
       
  3024     the stateChanged() signal is emitted.
       
  3025 
       
  3026     \sa State stateChanged()
       
  3027 */
       
  3028 QHttp::State QHttp::state() const
       
  3029 {
       
  3030     Q_D(const QHttp);
       
  3031     return d->state;
       
  3032 }
       
  3033 
       
  3034 /*!
       
  3035     Returns the last error that occurred. This is useful to find out
       
  3036     what happened when receiving a requestFinished() or a done()
       
  3037     signal with the \c error argument \c true.
       
  3038 
       
  3039     If you start a new request, the error status is reset to \c NoError.
       
  3040 */
       
  3041 QHttp::Error QHttp::error() const
       
  3042 {
       
  3043     Q_D(const QHttp);
       
  3044     return d->error;
       
  3045 }
       
  3046 
       
  3047 /*!
       
  3048     Returns a human-readable description of the last error that
       
  3049     occurred. This is useful to present a error message to the user
       
  3050     when receiving a requestFinished() or a done() signal with the \c
       
  3051     error argument \c true.
       
  3052 */
       
  3053 QString QHttp::errorString() const
       
  3054 {
       
  3055     Q_D(const QHttp);
       
  3056     return d->errorString;
       
  3057 }
       
  3058 
       
  3059 void QHttpPrivate::setState(int s)
       
  3060 {
       
  3061     Q_Q(QHttp);
       
  3062 #if defined(QHTTP_DEBUG)
       
  3063     qDebug("QHttp state changed %d -> %d", state, s);
       
  3064 #endif
       
  3065     state = QHttp::State(s);
       
  3066     emit q->stateChanged(s);
       
  3067 }
       
  3068 
       
  3069 void QHttpPrivate::closeConn()
       
  3070 {
       
  3071     Q_Q(QHttp);
       
  3072     // If no connection is open -> ignore
       
  3073     if (state == QHttp::Closing || state == QHttp::Unconnected)
       
  3074         return;
       
  3075 
       
  3076     postDevice = 0;
       
  3077     setState(QHttp::Closing);
       
  3078 
       
  3079     // Already closed ?
       
  3080     if (!socket || !socket->isOpen()) {
       
  3081         QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection);
       
  3082     } else {
       
  3083         // Close now.
       
  3084         socket->close();
       
  3085     }
       
  3086 }
       
  3087 
       
  3088 void QHttpPrivate::setSock(QTcpSocket *sock)
       
  3089 {
       
  3090     Q_Q(const QHttp);
       
  3091 
       
  3092     // disconnect all existing signals
       
  3093     if (socket)
       
  3094         socket->disconnect();
       
  3095     if (deleteSocket)
       
  3096         delete socket;
       
  3097 
       
  3098     // use the new QTcpSocket socket, or create one if socket is 0.
       
  3099     deleteSocket = (sock == 0);
       
  3100     socket = sock;
       
  3101     if (!socket) {
       
  3102 #ifndef QT_NO_OPENSSL
       
  3103         if (QSslSocket::supportsSsl())
       
  3104             socket = new QSslSocket();
       
  3105         else
       
  3106 #endif
       
  3107             socket = new QTcpSocket();
       
  3108     }
       
  3109 
       
  3110     // connect all signals
       
  3111     QObject::connect(socket, SIGNAL(connected()), q, SLOT(_q_slotConnected()));
       
  3112     QObject::connect(socket, SIGNAL(disconnected()), q, SLOT(_q_slotClosed()));
       
  3113     QObject::connect(socket, SIGNAL(readyRead()), q, SLOT(_q_slotReadyRead()));
       
  3114     QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), q, SLOT(_q_slotError(QAbstractSocket::SocketError)));
       
  3115     QObject::connect(socket, SIGNAL(bytesWritten(qint64)),
       
  3116                      q, SLOT(_q_slotBytesWritten(qint64)));
       
  3117 #ifndef QT_NO_NETWORKPROXY
       
  3118     QObject::connect(socket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)),
       
  3119                      q, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)));
       
  3120 #endif
       
  3121 
       
  3122 #ifndef QT_NO_OPENSSL
       
  3123     if (qobject_cast<QSslSocket *>(socket)) {
       
  3124         QObject::connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)),
       
  3125                          q, SIGNAL(sslErrors(const QList<QSslError> &)));
       
  3126         QObject::connect(socket, SIGNAL(encryptedBytesWritten(qint64)),
       
  3127                          q, SLOT(_q_slotEncryptedBytesWritten(qint64)));
       
  3128     }
       
  3129 #endif
       
  3130 }
       
  3131 
       
  3132 /*!
       
  3133     Tells the QSslSocket used for the Http connection to ignore the errors
       
  3134     reported in the sslErrors() signal.
       
  3135 
       
  3136     Note that this function must be called from within a slot connected to the
       
  3137     sslErrors() signal to have any effect.
       
  3138 
       
  3139     \sa QSslSocket QSslSocket::sslErrors()
       
  3140 */
       
  3141 #ifndef QT_NO_OPENSSL
       
  3142 void QHttp::ignoreSslErrors()
       
  3143 {
       
  3144     Q_D(QHttp);
       
  3145     QSslSocket *sslSocket = qobject_cast<QSslSocket *>(d->socket);
       
  3146     if (sslSocket)
       
  3147         sslSocket->ignoreSslErrors();
       
  3148 }
       
  3149 #endif
       
  3150 
       
  3151 QT_END_NAMESPACE
       
  3152 
       
  3153 #include "moc_qhttp.cpp"
       
  3154 
       
  3155 #endif