From b3ce4470ae2ece0c03c66684ca3d9dd13955786b Mon Sep 17 00:00:00 2001 From: "Jonas M. Gastal" Date: Thu, 22 Dec 2011 17:42:49 -0200 Subject: Removing QHttp class, its tests and its usage in examples. Task-number: QTBUG-22750 Change-Id: I161fad772bfb26797e6ee9d69da925b6747c371f Reviewed-by: Lars Knoll --- src/network/access/access.pri | 4 +- src/network/access/qhttp.cpp | 3150 ------------------------- src/network/access/qhttp.h | 311 --- src/network/access/qhttpheader.cpp | 770 ++++++ src/network/access/qhttpheader_p.h | 147 ++ src/network/access/qhttpnetworkconnection.cpp | 1 - 6 files changed, 919 insertions(+), 3464 deletions(-) delete mode 100644 src/network/access/qhttp.cpp delete mode 100644 src/network/access/qhttp.h create mode 100644 src/network/access/qhttpheader.cpp create mode 100644 src/network/access/qhttpheader_p.h (limited to 'src/network/access') diff --git a/src/network/access/access.pri b/src/network/access/access.pri index 3d5558d334..944855e9d1 100644 --- a/src/network/access/access.pri +++ b/src/network/access/access.pri @@ -2,7 +2,7 @@ HEADERS += \ access/qftp.h \ - access/qhttp.h \ + access/qhttpheader_p.h \ access/qhttpnetworkheader_p.h \ access/qhttpnetworkrequest_p.h \ access/qhttpnetworkreply_p.h \ @@ -39,7 +39,7 @@ HEADERS += \ SOURCES += \ access/qftp.cpp \ - access/qhttp.cpp \ + access/qhttpheader.cpp \ access/qhttpnetworkheader.cpp \ access/qhttpnetworkrequest.cpp \ access/qhttpnetworkreply.cpp \ diff --git a/src/network/access/qhttp.cpp b/src/network/access/qhttp.cpp deleted file mode 100644 index 067b7f95d7..0000000000 --- a/src/network/access/qhttp.cpp +++ /dev/null @@ -1,3150 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -//#define QHTTP_DEBUG - -#include -#include "qhttp.h" - -#ifndef QT_NO_HTTP -# include "private/qobject_p.h" -# include "qtcpsocket.h" -# include "qsslsocket.h" -# include "qtextstream.h" -# include "qmap.h" -# include "qlist.h" -# include "qstring.h" -# include "qstringlist.h" -# include "qbuffer.h" -# include "private/qringbuffer_p.h" -# include "qcoreevent.h" -# include "qurl.h" -# include "qnetworkproxy.h" -# include "qauthenticator.h" -# include "qauthenticator_p.h" -# include "qdebug.h" -# include "qtimer.h" -#endif - -#ifndef QT_NO_HTTP - -QT_BEGIN_NAMESPACE - -class QHttpNormalRequest; -class QHttpRequest -{ -public: - QHttpRequest() : finished(false) - { id = idCounter.fetchAndAddRelaxed(1); } - virtual ~QHttpRequest() - { } - - virtual void start(QHttp *) = 0; - virtual bool hasRequestHeader(); - virtual QHttpRequestHeader requestHeader(); - - virtual QIODevice *sourceDevice() = 0; - virtual QIODevice *destinationDevice() = 0; - - int id; - bool finished; - -private: - static QBasicAtomicInt idCounter; -}; - -class QHttpPrivate : public QObjectPrivate -{ -public: - Q_DECLARE_PUBLIC(QHttp) - - inline QHttpPrivate() - : socket(0), reconnectAttempts(2), - deleteSocket(0), state(QHttp::Unconnected), - error(QHttp::NoError), port(0), mode(QHttp::ConnectionModeHttp), - toDevice(0), postDevice(0), bytesDone(0), chunkedSize(-1), - repost(false), pendingPost(false) - { - } - - inline ~QHttpPrivate() - { - while (!pending.isEmpty()) - delete pending.takeFirst(); - - if (deleteSocket) - delete socket; - } - - // private slots - void _q_startNextRequest(); - void _q_slotReadyRead(); - void _q_slotConnected(); - void _q_slotError(QAbstractSocket::SocketError); - void _q_slotClosed(); - void _q_slotBytesWritten(qint64 numBytes); -#ifndef QT_NO_OPENSSL - void _q_slotEncryptedBytesWritten(qint64 numBytes); -#endif - void _q_slotDoFinished(); - void _q_slotSendRequest(); - void _q_continuePost(); - - int addRequest(QHttpNormalRequest *); - int addRequest(QHttpRequest *); - void finishedWithSuccess(); - void finishedWithError(const QString &detail, int errorCode); - - void init(); - void setState(int); - void closeConn(); - void setSock(QTcpSocket *sock); - - void postMoreData(); - - QTcpSocket *socket; - int reconnectAttempts; - bool deleteSocket; - QList pending; - - QHttp::State state; - QHttp::Error error; - QString errorString; - - QString hostName; - quint16 port; - QHttp::ConnectionMode mode; - - QByteArray buffer; - QIODevice *toDevice; - QIODevice *postDevice; - - qint64 bytesDone; - qint64 bytesTotal; - qint64 chunkedSize; - - QHttpRequestHeader header; - - bool readHeader; - QString headerStr; - QHttpResponseHeader response; - - QRingBuffer rba; - -#ifndef QT_NO_NETWORKPROXY - QNetworkProxy proxy; - QAuthenticator proxyAuthenticator; -#endif - QAuthenticator authenticator; - bool repost; - bool hasFinishedWithError; - bool pendingPost; - QTimer post100ContinueTimer; -}; - -QBasicAtomicInt QHttpRequest::idCounter = Q_BASIC_ATOMIC_INITIALIZER(1); - -bool QHttpRequest::hasRequestHeader() -{ - return false; -} - -QHttpRequestHeader QHttpRequest::requestHeader() -{ - return QHttpRequestHeader(); -} - -/**************************************************** - * - * QHttpNormalRequest - * - ****************************************************/ - -class QHttpNormalRequest : public QHttpRequest -{ -public: - QHttpNormalRequest(const QHttpRequestHeader &h, QIODevice *d, QIODevice *t) : - header(h), to(t) - { - is_ba = false; - data.dev = d; - } - - QHttpNormalRequest(const QHttpRequestHeader &h, QByteArray *d, QIODevice *t) : - header(h), to(t) - { - is_ba = true; - data.ba = d; - } - - ~QHttpNormalRequest() - { - if (is_ba) - delete data.ba; - } - - void start(QHttp *); - bool hasRequestHeader(); - QHttpRequestHeader requestHeader(); - inline void setRequestHeader(const QHttpRequestHeader &h) { header = h; } - - QIODevice *sourceDevice(); - QIODevice *destinationDevice(); - -protected: - QHttpRequestHeader header; - -private: - union { - QByteArray *ba; - QIODevice *dev; - } data; - bool is_ba; - QIODevice *to; -}; - -void QHttpNormalRequest::start(QHttp *http) -{ - if (!http->d_func()->socket) - http->d_func()->setSock(0); - http->d_func()->header = header; - - if (is_ba) { - http->d_func()->buffer = *data.ba; - if (http->d_func()->buffer.size() >= 0) - http->d_func()->header.setContentLength(http->d_func()->buffer.size()); - - http->d_func()->postDevice = 0; - } else { - http->d_func()->buffer = QByteArray(); - - if (data.dev && (data.dev->isOpen() || data.dev->open(QIODevice::ReadOnly))) { - http->d_func()->postDevice = data.dev; - if (http->d_func()->postDevice->size() >= 0) - http->d_func()->header.setContentLength(http->d_func()->postDevice->size()); - } else { - http->d_func()->postDevice = 0; - } - } - - if (to && (to->isOpen() || to->open(QIODevice::WriteOnly))) - http->d_func()->toDevice = to; - else - http->d_func()->toDevice = 0; - - http->d_func()->reconnectAttempts = 2; - http->d_func()->_q_slotSendRequest(); -} - -bool QHttpNormalRequest::hasRequestHeader() -{ - return true; -} - -QHttpRequestHeader QHttpNormalRequest::requestHeader() -{ - return header; -} - -QIODevice *QHttpNormalRequest::sourceDevice() -{ - if (is_ba) - return 0; - return data.dev; -} - -QIODevice *QHttpNormalRequest::destinationDevice() -{ - return to; -} - -/**************************************************** - * - * QHttpPGHRequest - * (like a QHttpNormalRequest, but for the convenience - * functions put(), get() and head() -- i.e. set the - * host header field correctly before sending the - * request) - * - ****************************************************/ - -class QHttpPGHRequest : public QHttpNormalRequest -{ -public: - QHttpPGHRequest(const QHttpRequestHeader &h, QIODevice *d, QIODevice *t) : - QHttpNormalRequest(h, d, t) - { } - - QHttpPGHRequest(const QHttpRequestHeader &h, QByteArray *d, QIODevice *t) : - QHttpNormalRequest(h, d, t) - { } - - ~QHttpPGHRequest() - { } - - void start(QHttp *); -}; - -void QHttpPGHRequest::start(QHttp *http) -{ - if (http->d_func()->port && http->d_func()->port != 80) - header.setValue(QLatin1String("Host"), http->d_func()->hostName + QLatin1Char(':') + QString::number(http->d_func()->port)); - else - header.setValue(QLatin1String("Host"), http->d_func()->hostName); - QHttpNormalRequest::start(http); -} - -/**************************************************** - * - * QHttpSetHostRequest - * - ****************************************************/ - -class QHttpSetHostRequest : public QHttpRequest -{ -public: - QHttpSetHostRequest(const QString &h, quint16 p, QHttp::ConnectionMode m) - : hostName(h), port(p), mode(m) - { } - - void start(QHttp *); - - QIODevice *sourceDevice() - { return 0; } - QIODevice *destinationDevice() - { return 0; } - -private: - QString hostName; - quint16 port; - QHttp::ConnectionMode mode; -}; - -void QHttpSetHostRequest::start(QHttp *http) -{ - http->d_func()->hostName = hostName; - http->d_func()->port = port; - http->d_func()->mode = mode; - -#ifdef QT_NO_OPENSSL - if (mode == QHttp::ConnectionModeHttps) { - // SSL requested but no SSL support compiled in - http->d_func()->finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "HTTPS connection requested but SSL support not compiled in")), - QHttp::UnknownError); - return; - } -#endif - - http->d_func()->finishedWithSuccess(); -} - -/**************************************************** - * - * QHttpSetUserRequest - * - ****************************************************/ - -class QHttpSetUserRequest : public QHttpRequest -{ -public: - QHttpSetUserRequest(const QString &userName, const QString &password) : - user(userName), pass(password) - { } - - void start(QHttp *); - - QIODevice *sourceDevice() - { return 0; } - QIODevice *destinationDevice() - { return 0; } - -private: - QString user; - QString pass; -}; - -void QHttpSetUserRequest::start(QHttp *http) -{ - http->d_func()->authenticator.setUser(user); - http->d_func()->authenticator.setPassword(pass); - http->d_func()->finishedWithSuccess(); -} - -#ifndef QT_NO_NETWORKPROXY - -/**************************************************** - * - * QHttpSetProxyRequest - * - ****************************************************/ - -class QHttpSetProxyRequest : public QHttpRequest -{ -public: - inline QHttpSetProxyRequest(const QNetworkProxy &proxy) - { - this->proxy = proxy; - } - - inline void start(QHttp *http) - { - http->d_func()->proxy = proxy; - QString user = proxy.user(); - if (!user.isEmpty()) - http->d_func()->proxyAuthenticator.setUser(user); - QString password = proxy.password(); - if (!password.isEmpty()) - http->d_func()->proxyAuthenticator.setPassword(password); - http->d_func()->finishedWithSuccess(); - } - - inline QIODevice *sourceDevice() - { return 0; } - inline QIODevice *destinationDevice() - { return 0; } -private: - QNetworkProxy proxy; -}; - -#endif // QT_NO_NETWORKPROXY - -/**************************************************** - * - * QHttpSetSocketRequest - * - ****************************************************/ - -class QHttpSetSocketRequest : public QHttpRequest -{ -public: - QHttpSetSocketRequest(QTcpSocket *s) : socket(s) - { } - - void start(QHttp *); - - QIODevice *sourceDevice() - { return 0; } - QIODevice *destinationDevice() - { return 0; } - -private: - QTcpSocket *socket; -}; - -void QHttpSetSocketRequest::start(QHttp *http) -{ - http->d_func()->setSock(socket); - http->d_func()->finishedWithSuccess(); -} - -/**************************************************** - * - * QHttpCloseRequest - * - ****************************************************/ - -class QHttpCloseRequest : public QHttpRequest -{ -public: - QHttpCloseRequest() - { } - void start(QHttp *); - - QIODevice *sourceDevice() - { return 0; } - QIODevice *destinationDevice() - { return 0; } -}; - -void QHttpCloseRequest::start(QHttp *http) -{ - http->d_func()->closeConn(); -} - -class QHttpHeaderPrivate -{ - Q_DECLARE_PUBLIC(QHttpHeader) -public: - inline virtual ~QHttpHeaderPrivate() {} - - QList > values; - bool valid; - QHttpHeader *q_ptr; -}; - -/**************************************************** - * - * QHttpHeader - * - ****************************************************/ - -/*! - \class QHttpHeader - \obsolete - \brief The QHttpHeader class contains header information for HTTP. - - \ingroup network - \inmodule QtNetwork - - In most cases you should use the more specialized derivatives of - this class, QHttpResponseHeader and QHttpRequestHeader, rather - than directly using QHttpHeader. - - QHttpHeader provides the HTTP header fields. A HTTP header field - consists of a name followed by a colon, a single space, and the - field value. (See RFC 1945.) Field names are case-insensitive. A - typical header field looks like this: - \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 0 - - In the API the header field name is called the "key" and the - content is called the "value". You can get and set a header - field's value by using its key with value() and setValue(), e.g. - \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 1 - - Some fields are so common that getters and setters are provided - for them as a convenient alternative to using \l value() and - \l setValue(), e.g. contentLength() and contentType(), - setContentLength() and setContentType(). - - Each header key has a \e single value associated with it. If you - set the value for a key which already exists the previous value - will be discarded. - - \sa QHttpRequestHeader QHttpResponseHeader -*/ - -/*! - \fn int QHttpHeader::majorVersion() const - - Returns the major protocol-version of the HTTP header. -*/ - -/*! - \fn int QHttpHeader::minorVersion() const - - Returns the minor protocol-version of the HTTP header. -*/ - -/*! - Constructs an empty HTTP header. -*/ -QHttpHeader::QHttpHeader() - : d_ptr(new QHttpHeaderPrivate) -{ - Q_D(QHttpHeader); - d->q_ptr = this; - d->valid = true; -} - -/*! - Constructs a copy of \a header. -*/ -QHttpHeader::QHttpHeader(const QHttpHeader &header) - : d_ptr(new QHttpHeaderPrivate) -{ - Q_D(QHttpHeader); - d->q_ptr = this; - d->valid = header.d_func()->valid; - d->values = header.d_func()->values; -} - -/*! - Constructs a HTTP header for \a str. - - This constructor parses the string \a str for header fields and - adds this information. The \a str should consist of one or more - "\r\n" delimited lines; each of these lines should have the format - key, colon, space, value. -*/ -QHttpHeader::QHttpHeader(const QString &str) - : d_ptr(new QHttpHeaderPrivate) -{ - Q_D(QHttpHeader); - d->q_ptr = this; - d->valid = true; - parse(str); -} - -/*! \internal - */ -QHttpHeader::QHttpHeader(QHttpHeaderPrivate &dd, const QString &str) - : d_ptr(&dd) -{ - Q_D(QHttpHeader); - d->q_ptr = this; - d->valid = true; - if (!str.isEmpty()) - parse(str); -} - -/*! \internal - */ -QHttpHeader::QHttpHeader(QHttpHeaderPrivate &dd, const QHttpHeader &header) - : d_ptr(&dd) -{ - Q_D(QHttpHeader); - d->q_ptr = this; - d->valid = header.d_func()->valid; - d->values = header.d_func()->values; -} -/*! - Destructor. -*/ -QHttpHeader::~QHttpHeader() -{ -} - -/*! - Assigns \a h and returns a reference to this http header. -*/ -QHttpHeader &QHttpHeader::operator=(const QHttpHeader &h) -{ - Q_D(QHttpHeader); - d->values = h.d_func()->values; - d->valid = h.d_func()->valid; - return *this; -} - -/*! - Returns true if the HTTP header is valid; otherwise returns false. - - A QHttpHeader is invalid if it was created by parsing a malformed string. -*/ -bool QHttpHeader::isValid() const -{ - Q_D(const QHttpHeader); - return d->valid; -} - -/*! \internal - Parses the HTTP header string \a str for header fields and adds - the keys/values it finds. If the string is not parsed successfully - the QHttpHeader becomes \link isValid() invalid\endlink. - - Returns true if \a str was successfully parsed; otherwise returns false. - - \sa toString() -*/ -bool QHttpHeader::parse(const QString &str) -{ - Q_D(QHttpHeader); - QStringList lst; - int pos = str.indexOf(QLatin1Char('\n')); - if (pos > 0 && str.at(pos - 1) == QLatin1Char('\r')) - lst = str.trimmed().split(QLatin1String("\r\n")); - else - lst = str.trimmed().split(QLatin1String("\n")); - lst.removeAll(QString()); // No empties - - if (lst.isEmpty()) - return true; - - QStringList lines; - QStringList::Iterator it = lst.begin(); - for (; it != lst.end(); ++it) { - if (!(*it).isEmpty()) { - if ((*it)[0].isSpace()) { - if (!lines.isEmpty()) { - lines.last() += QLatin1Char(' '); - lines.last() += (*it).trimmed(); - } - } else { - lines.append((*it)); - } - } - } - - int number = 0; - it = lines.begin(); - for (; it != lines.end(); ++it) { - if (!parseLine(*it, number++)) { - d->valid = false; - return false; - } - } - return true; -} - -/*! \internal -*/ -void QHttpHeader::setValid(bool v) -{ - Q_D(QHttpHeader); - d->valid = v; -} - -/*! - Returns the first value for the entry with the given \a key. If no entry - has this \a key, an empty string is returned. - - \sa setValue() removeValue() hasKey() keys() -*/ -QString QHttpHeader::value(const QString &key) const -{ - Q_D(const QHttpHeader); - QString lowercaseKey = key.toLower(); - QList >::ConstIterator it = d->values.constBegin(); - while (it != d->values.constEnd()) { - if ((*it).first.toLower() == lowercaseKey) - return (*it).second; - ++it; - } - return QString(); -} - -/*! - Returns all the entries with the given \a key. If no entry - has this \a key, an empty string list is returned. -*/ -QStringList QHttpHeader::allValues(const QString &key) const -{ - Q_D(const QHttpHeader); - QString lowercaseKey = key.toLower(); - QStringList valueList; - QList >::ConstIterator it = d->values.constBegin(); - while (it != d->values.constEnd()) { - if ((*it).first.toLower() == lowercaseKey) - valueList.append((*it).second); - ++it; - } - return valueList; -} - -/*! - Returns a list of the keys in the HTTP header. - - \sa hasKey() -*/ -QStringList QHttpHeader::keys() const -{ - Q_D(const QHttpHeader); - QStringList keyList; - QSet seenKeys; - QList >::ConstIterator it = d->values.constBegin(); - while (it != d->values.constEnd()) { - const QString &key = (*it).first; - QString lowercaseKey = key.toLower(); - if (!seenKeys.contains(lowercaseKey)) { - keyList.append(key); - seenKeys.insert(lowercaseKey); - } - ++it; - } - return keyList; -} - -/*! - Returns true if the HTTP header has an entry with the given \a - key; otherwise returns false. - - \sa value() setValue() keys() -*/ -bool QHttpHeader::hasKey(const QString &key) const -{ - Q_D(const QHttpHeader); - QString lowercaseKey = key.toLower(); - QList >::ConstIterator it = d->values.constBegin(); - while (it != d->values.constEnd()) { - if ((*it).first.toLower() == lowercaseKey) - return true; - ++it; - } - return false; -} - -/*! - Sets the value of the entry with the \a key to \a value. - - If no entry with \a key exists, a new entry with the given \a key - and \a value is created. If an entry with the \a key already - exists, the first value is discarded and replaced with the given - \a value. - - \sa value() hasKey() removeValue() -*/ -void QHttpHeader::setValue(const QString &key, const QString &value) -{ - Q_D(QHttpHeader); - QString lowercaseKey = key.toLower(); - QList >::Iterator it = d->values.begin(); - while (it != d->values.end()) { - if ((*it).first.toLower() == lowercaseKey) { - (*it).second = value; - return; - } - ++it; - } - // not found so add - addValue(key, value); -} - -/*! - Sets the header entries to be the list of key value pairs in \a values. -*/ -void QHttpHeader::setValues(const QList > &values) -{ - Q_D(QHttpHeader); - d->values = values; -} - -/*! - Adds a new entry with the \a key and \a value. -*/ -void QHttpHeader::addValue(const QString &key, const QString &value) -{ - Q_D(QHttpHeader); - d->values.append(qMakePair(key, value)); -} - -/*! - Returns all the entries in the header. -*/ -QList > QHttpHeader::values() const -{ - Q_D(const QHttpHeader); - return d->values; -} - -/*! - Removes the entry with the key \a key from the HTTP header. - - \sa value() setValue() -*/ -void QHttpHeader::removeValue(const QString &key) -{ - Q_D(QHttpHeader); - QString lowercaseKey = key.toLower(); - QList >::Iterator it = d->values.begin(); - while (it != d->values.end()) { - if ((*it).first.toLower() == lowercaseKey) { - d->values.erase(it); - return; - } - ++it; - } -} - -/*! - Removes all the entries with the key \a key from the HTTP header. -*/ -void QHttpHeader::removeAllValues(const QString &key) -{ - Q_D(QHttpHeader); - QString lowercaseKey = key.toLower(); - QList >::Iterator it = d->values.begin(); - while (it != d->values.end()) { - if ((*it).first.toLower() == lowercaseKey) { - it = d->values.erase(it); - continue; - } - ++it; - } -} - -/*! \internal - Parses the single HTTP header line \a line which has the format - key, colon, space, value, and adds key/value to the headers. The - linenumber is \a number. Returns true if the line was successfully - parsed and the key/value added; otherwise returns false. - - \sa parse() -*/ -bool QHttpHeader::parseLine(const QString &line, int) -{ - int i = line.indexOf(QLatin1Char(':')); - if (i == -1) - return false; - - addValue(line.left(i).trimmed(), line.mid(i + 1).trimmed()); - - return true; -} - -/*! - Returns a string representation of the HTTP header. - - The string is suitable for use by the constructor that takes a - QString. It consists of lines with the format: key, colon, space, - value, "\r\n". -*/ -QString QHttpHeader::toString() const -{ - Q_D(const QHttpHeader); - if (!isValid()) - return QLatin1String(""); - - QString ret = QLatin1String(""); - - QList >::ConstIterator it = d->values.constBegin(); - while (it != d->values.constEnd()) { - ret += (*it).first + QLatin1String(": ") + (*it).second + QLatin1String("\r\n"); - ++it; - } - return ret; -} - -/*! - Returns true if the header has an entry for the special HTTP - header field \c content-length; otherwise returns false. - - \sa contentLength() setContentLength() -*/ -bool QHttpHeader::hasContentLength() const -{ - return hasKey(QLatin1String("content-length")); -} - -/*! - Returns the value of the special HTTP header field \c - content-length. - - \sa setContentLength() hasContentLength() -*/ -uint QHttpHeader::contentLength() const -{ - return value(QLatin1String("content-length")).toUInt(); -} - -/*! - Sets the value of the special HTTP header field \c content-length - to \a len. - - \sa contentLength() hasContentLength() -*/ -void QHttpHeader::setContentLength(int len) -{ - setValue(QLatin1String("content-length"), QString::number(len)); -} - -/*! - Returns true if the header has an entry for the special HTTP - header field \c content-type; otherwise returns false. - - \sa contentType() setContentType() -*/ -bool QHttpHeader::hasContentType() const -{ - return hasKey(QLatin1String("content-type")); -} - -/*! - Returns the value of the special HTTP header field \c content-type. - - \sa setContentType() hasContentType() -*/ -QString QHttpHeader::contentType() const -{ - QString type = value(QLatin1String("content-type")); - if (type.isEmpty()) - return QString(); - - int pos = type.indexOf(QLatin1Char(';')); - if (pos == -1) - return type; - - return type.left(pos).trimmed(); -} - -/*! - Sets the value of the special HTTP header field \c content-type to - \a type. - - \sa contentType() hasContentType() -*/ -void QHttpHeader::setContentType(const QString &type) -{ - setValue(QLatin1String("content-type"), type); -} - -class QHttpResponseHeaderPrivate : public QHttpHeaderPrivate -{ - Q_DECLARE_PUBLIC(QHttpResponseHeader) -public: - int statCode; - QString reasonPhr; - int majVer; - int minVer; -}; - -/**************************************************** - * - * QHttpResponseHeader - * - ****************************************************/ - -/*! - \class QHttpResponseHeader - \obsolete - \brief The QHttpResponseHeader class contains response header information for HTTP. - - \ingroup network - \inmodule QtNetwork - - This class is used by the QHttp class to report the header - information that the client received from the server. - - HTTP responses have a status code that indicates the status of the - response. This code is a 3-digit integer result code (for details - see to RFC 1945). In addition to the status code, you can also - specify a human-readable text that describes the reason for the - code ("reason phrase"). This class allows you to get the status - code and the reason phrase. - - \sa QHttpRequestHeader, QHttp, {HTTP Example} -*/ - -/*! - Constructs an empty HTTP response header. -*/ -QHttpResponseHeader::QHttpResponseHeader() - : QHttpHeader(*new QHttpResponseHeaderPrivate) -{ - setValid(false); -} - -/*! - Constructs a copy of \a header. -*/ -QHttpResponseHeader::QHttpResponseHeader(const QHttpResponseHeader &header) - : QHttpHeader(*new QHttpResponseHeaderPrivate, header) -{ - Q_D(QHttpResponseHeader); - d->statCode = header.d_func()->statCode; - d->reasonPhr = header.d_func()->reasonPhr; - d->majVer = header.d_func()->majVer; - d->minVer = header.d_func()->minVer; -} - -/*! - Copies the contents of \a header into this QHttpResponseHeader. -*/ -QHttpResponseHeader &QHttpResponseHeader::operator=(const QHttpResponseHeader &header) -{ - Q_D(QHttpResponseHeader); - QHttpHeader::operator=(header); - d->statCode = header.d_func()->statCode; - d->reasonPhr = header.d_func()->reasonPhr; - d->majVer = header.d_func()->majVer; - d->minVer = header.d_func()->minVer; - return *this; -} - -/*! - Constructs a HTTP response header from the string \a str. The - string is parsed and the information is set. The \a str should - consist of one or more "\r\n" delimited lines; the first line should be the - status-line (format: HTTP-version, space, status-code, space, - reason-phrase); each of remaining lines should have the format key, colon, - space, value. -*/ -QHttpResponseHeader::QHttpResponseHeader(const QString &str) - : QHttpHeader(*new QHttpResponseHeaderPrivate) -{ - parse(str); -} - -/*! - \since 4.1 - - Constructs a QHttpResponseHeader, setting the status code to \a code, the - reason phrase to \a text and the protocol-version to \a majorVer and \a - minorVer. - - \sa statusCode() reasonPhrase() majorVersion() minorVersion() -*/ -QHttpResponseHeader::QHttpResponseHeader(int code, const QString &text, int majorVer, int minorVer) - : QHttpHeader(*new QHttpResponseHeaderPrivate) -{ - setStatusLine(code, text, majorVer, minorVer); -} - -/*! - \since 4.1 - - Sets the status code to \a code, the reason phrase to \a text and - the protocol-version to \a majorVer and \a minorVer. - - \sa statusCode() reasonPhrase() majorVersion() minorVersion() -*/ -void QHttpResponseHeader::setStatusLine(int code, const QString &text, int majorVer, int minorVer) -{ - Q_D(QHttpResponseHeader); - setValid(true); - d->statCode = code; - d->reasonPhr = text; - d->majVer = majorVer; - d->minVer = minorVer; -} - -/*! - Returns the status code of the HTTP response header. - - \sa reasonPhrase() majorVersion() minorVersion() -*/ -int QHttpResponseHeader::statusCode() const -{ - Q_D(const QHttpResponseHeader); - return d->statCode; -} - -/*! - Returns the reason phrase of the HTTP response header. - - \sa statusCode() majorVersion() minorVersion() -*/ -QString QHttpResponseHeader::reasonPhrase() const -{ - Q_D(const QHttpResponseHeader); - return d->reasonPhr; -} - -/*! - Returns the major protocol-version of the HTTP response header. - - \sa minorVersion() statusCode() reasonPhrase() -*/ -int QHttpResponseHeader::majorVersion() const -{ - Q_D(const QHttpResponseHeader); - return d->majVer; -} - -/*! - Returns the minor protocol-version of the HTTP response header. - - \sa majorVersion() statusCode() reasonPhrase() -*/ -int QHttpResponseHeader::minorVersion() const -{ - Q_D(const QHttpResponseHeader); - return d->minVer; -} - -/*! \internal -*/ -bool QHttpResponseHeader::parseLine(const QString &line, int number) -{ - Q_D(QHttpResponseHeader); - if (number != 0) - return QHttpHeader::parseLine(line, number); - - QString l = line.simplified(); - if (l.length() < 10) - return false; - - if (l.left(5) == QLatin1String("HTTP/") && l[5].isDigit() && l[6] == QLatin1Char('.') && - l[7].isDigit() && l[8] == QLatin1Char(' ') && l[9].isDigit()) { - d->majVer = l[5].toLatin1() - '0'; - d->minVer = l[7].toLatin1() - '0'; - - int pos = l.indexOf(QLatin1Char(' '), 9); - if (pos != -1) { - d->reasonPhr = l.mid(pos + 1); - d->statCode = l.mid(9, pos - 9).toInt(); - } else { - d->statCode = l.mid(9).toInt(); - d->reasonPhr.clear(); - } - } else { - return false; - } - - return true; -} - -/*! \reimp -*/ -QString QHttpResponseHeader::toString() const -{ - Q_D(const QHttpResponseHeader); - QString ret(QLatin1String("HTTP/%1.%2 %3 %4\r\n%5\r\n")); - return ret.arg(d->majVer).arg(d->minVer).arg(d->statCode).arg(d->reasonPhr).arg(QHttpHeader::toString()); -} - -class QHttpRequestHeaderPrivate : public QHttpHeaderPrivate -{ - Q_DECLARE_PUBLIC(QHttpRequestHeader) -public: - QString m; - QString p; - int majVer; - int minVer; -}; - -/**************************************************** - * - * QHttpRequestHeader - * - ****************************************************/ - -/*! - \class QHttpRequestHeader - \obsolete - \brief The QHttpRequestHeader class contains request header information for HTTP. - - \ingroup network - \inmodule QtNetwork - - This class is used in the QHttp class to report the header - information if the client requests something from the server. - - HTTP requests have a method which describes the request's action. - The most common requests are "GET" and "POST". In addition to the - request method the header also includes a request-URI to specify - the location for the method to use. - - The method, request-URI and protocol-version can be set using a - constructor or later using setRequest(). The values can be - obtained using method(), path(), majorVersion() and - minorVersion(). - - Note that the request-URI must be in the format expected by the - HTTP server. That is, all reserved characters must be encoded in - %HH (where HH are two hexadecimal digits). See - QUrl::toPercentEncoding() for more information. - - Important inherited functions: setValue() and value(). - - \sa QHttpResponseHeader QHttp -*/ - -/*! - Constructs an empty HTTP request header. -*/ -QHttpRequestHeader::QHttpRequestHeader() - : QHttpHeader(*new QHttpRequestHeaderPrivate) -{ - setValid(false); -} - -/*! - Constructs a HTTP request header for the method \a method, the - request-URI \a path and the protocol-version \a majorVer and \a - minorVer. The \a path argument must be properly encoded for an - HTTP request. -*/ -QHttpRequestHeader::QHttpRequestHeader(const QString &method, const QString &path, int majorVer, int minorVer) - : QHttpHeader(*new QHttpRequestHeaderPrivate) -{ - Q_D(QHttpRequestHeader); - d->m = method; - d->p = path; - d->majVer = majorVer; - d->minVer = minorVer; -} - -/*! - Constructs a copy of \a header. -*/ -QHttpRequestHeader::QHttpRequestHeader(const QHttpRequestHeader &header) - : QHttpHeader(*new QHttpRequestHeaderPrivate, header) -{ - Q_D(QHttpRequestHeader); - d->m = header.d_func()->m; - d->p = header.d_func()->p; - d->majVer = header.d_func()->majVer; - d->minVer = header.d_func()->minVer; -} - -/*! - Copies the content of \a header into this QHttpRequestHeader -*/ -QHttpRequestHeader &QHttpRequestHeader::operator=(const QHttpRequestHeader &header) -{ - Q_D(QHttpRequestHeader); - QHttpHeader::operator=(header); - d->m = header.d_func()->m; - d->p = header.d_func()->p; - d->majVer = header.d_func()->majVer; - d->minVer = header.d_func()->minVer; - return *this; -} - -/*! - Constructs a HTTP request header from the string \a str. The \a - str should consist of one or more "\r\n" delimited lines; the first line - should be the request-line (format: method, space, request-URI, space - HTTP-version); each of the remaining lines should have the format key, - colon, space, value. -*/ -QHttpRequestHeader::QHttpRequestHeader(const QString &str) - : QHttpHeader(*new QHttpRequestHeaderPrivate) -{ - parse(str); -} - -/*! - This function sets the request method to \a method, the - request-URI to \a path and the protocol-version to \a majorVer and - \a minorVer. The \a path argument must be properly encoded for an - HTTP request. - - \sa method() path() majorVersion() minorVersion() -*/ -void QHttpRequestHeader::setRequest(const QString &method, const QString &path, int majorVer, int minorVer) -{ - Q_D(QHttpRequestHeader); - setValid(true); - d->m = method; - d->p = path; - d->majVer = majorVer; - d->minVer = minorVer; -} - -/*! - Returns the method of the HTTP request header. - - \sa path() majorVersion() minorVersion() setRequest() -*/ -QString QHttpRequestHeader::method() const -{ - Q_D(const QHttpRequestHeader); - return d->m; -} - -/*! - Returns the request-URI of the HTTP request header. - - \sa method() majorVersion() minorVersion() setRequest() -*/ -QString QHttpRequestHeader::path() const -{ - Q_D(const QHttpRequestHeader); - return d->p; -} - -/*! - Returns the major protocol-version of the HTTP request header. - - \sa minorVersion() method() path() setRequest() -*/ -int QHttpRequestHeader::majorVersion() const -{ - Q_D(const QHttpRequestHeader); - return d->majVer; -} - -/*! - Returns the minor protocol-version of the HTTP request header. - - \sa majorVersion() method() path() setRequest() -*/ -int QHttpRequestHeader::minorVersion() const -{ - Q_D(const QHttpRequestHeader); - return d->minVer; -} - -/*! \internal -*/ -bool QHttpRequestHeader::parseLine(const QString &line, int number) -{ - Q_D(QHttpRequestHeader); - if (number != 0) - return QHttpHeader::parseLine(line, number); - - QStringList lst = line.simplified().split(QLatin1String(" ")); - if (lst.count() > 0) { - d->m = lst[0]; - if (lst.count() > 1) { - d->p = lst[1]; - if (lst.count() > 2) { - QString v = lst[2]; - if (v.length() >= 8 && v.left(5) == QLatin1String("HTTP/") && - v[5].isDigit() && v[6] == QLatin1Char('.') && v[7].isDigit()) { - d->majVer = v[5].toLatin1() - '0'; - d->minVer = v[7].toLatin1() - '0'; - return true; - } - } - } - } - - return false; -} - -/*! \reimp -*/ -QString QHttpRequestHeader::toString() const -{ - Q_D(const QHttpRequestHeader); - QString first(QLatin1String("%1 %2")); - QString last(QLatin1String(" HTTP/%3.%4\r\n%5\r\n")); - return first.arg(d->m).arg(d->p) + - last.arg(d->majVer).arg(d->minVer).arg(QHttpHeader::toString()); -} - - -/**************************************************** - * - * QHttp - * - ****************************************************/ -/*! - \class QHttp - \obsolete - \reentrant - - \brief The QHttp class provides an implementation of the HTTP protocol. - - \ingroup network - \inmodule QtNetwork - - - This class provides a direct interface to HTTP that allows you to - download and upload data with the HTTP protocol. - However, for new applications, it is - recommended to use QNetworkAccessManager and QNetworkReply, as - those classes possess a simpler, yet more powerful API - and a more modern protocol implementation. - - The class works asynchronously, so there are no blocking - functions. If an operation cannot be executed immediately, the - function will still return straight away and the operation will be - scheduled for later execution. The results of scheduled operations - are reported via signals. This approach depends on the event loop - being in operation. - - The operations that can be scheduled (they are called "requests" - in the rest of the documentation) are the following: setHost(), - get(), post(), head() and request(). - - All of these requests return a unique identifier that allows you - to keep track of the request that is currently executed. When the - execution of a request starts, the requestStarted() signal with - the identifier is emitted and when the request is finished, the - requestFinished() signal is emitted with the identifier and a bool - that indicates if the request finished with an error. - - To make an HTTP request you must set up suitable HTTP headers. The - following example demonstrates how to request the main HTML page - from the Qt website (i.e., the URL \c http://qt.nokia.com/index.html): - - \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 2 - - For the common HTTP requests \c GET, \c POST and \c HEAD, QHttp - provides the convenience functions get(), post() and head(). They - already use a reasonable header and if you don't have to set - special header fields, they are easier to use. The above example - can also be written as: - - \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 3 - - For this example the following sequence of signals is emitted - (with small variations, depending on network traffic, etc.): - - \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 4 - - The dataSendProgress() and dataReadProgress() signals in the above - example are useful if you want to show a \link QProgressBar - progress bar\endlink to inform the user about the progress of the - download. The second argument is the total size of data. In - certain cases it is not possible to know the total amount in - advance, in which case the second argument is 0. (If you connect - to a QProgressBar a total of 0 results in a busy indicator.) - - When the response header is read, it is reported with the - responseHeaderReceived() signal. - - The readyRead() signal tells you that there is data ready to be - read. The amount of data can then be queried with the - bytesAvailable() function and it can be read with the read() - or readAll() functions. - - If an error occurs during the execution of one of the commands in - a sequence of commands, all the pending commands (i.e. scheduled, - but not yet executed commands) are cleared and no signals are - emitted for them. - - For example, if you have the following sequence of requests - - \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 5 - - and the get() request fails because the host lookup fails, then - the post() request is never executed and the signals would look - like this: - - \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 6 - - You can then get details about the error with the error() and - errorString() functions. Note that only unexpected behavior, like - network failure is considered as an error. If the server response - contains an error status, like a 404 response, this is reported as - a normal response case. So you should always check the \link - QHttpResponseHeader::statusCode() status code \endlink of the - response header. - - The functions currentId() and currentRequest() provide more - information about the currently executing request. - - The functions hasPendingRequests() and clearPendingRequests() - allow you to query and clear the list of pending requests. - - \sa QFtp, QNetworkAccessManager, QNetworkRequest, QNetworkReply, - {HTTP Example}, {Torrent Example} -*/ - -/*! - Constructs a QHttp object. The \a parent parameter is passed on - to the QObject constructor. -*/ -QHttp::QHttp(QObject *parent) - : QObject(*new QHttpPrivate, parent) -{ - Q_D(QHttp); - d->init(); -} - -/*! - Constructs a QHttp object. Subsequent requests are done by - connecting to the server \a hostName on port \a port. - - The \a parent parameter is passed on to the QObject constructor. - - \sa setHost() -*/ -QHttp::QHttp(const QString &hostName, quint16 port, QObject *parent) - : QObject(*new QHttpPrivate, parent) -{ - Q_D(QHttp); - d->init(); - - d->hostName = hostName; - d->port = port; -} - -/*! - Constructs a QHttp object. Subsequent requests are done by - connecting to the server \a hostName on port \a port using the - connection mode \a mode. - - If port is 0, it will use the default port for the \a mode used - (80 for Http and 443 for Https). - - The \a parent parameter is passed on to the QObject constructor. - - \sa setHost() -*/ -QHttp::QHttp(const QString &hostName, ConnectionMode mode, quint16 port, QObject *parent) - : QObject(*new QHttpPrivate, parent) -{ - Q_D(QHttp); - d->init(); - - d->hostName = hostName; - if (port == 0) - port = (mode == ConnectionModeHttp) ? 80 : 443; - d->port = port; - d->mode = mode; -} - -void QHttpPrivate::init() -{ - Q_Q(QHttp); - errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Unknown error")); - QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection); - post100ContinueTimer.setSingleShot(true); - QObject::connect(&post100ContinueTimer, SIGNAL(timeout()), q, SLOT(_q_continuePost())); -} - -/*! - Destroys the QHttp object. If there is an open connection, it is - closed. -*/ -QHttp::~QHttp() -{ - abort(); -} - -/*! - \enum QHttp::ConnectionMode - \since 4.3 - - This enum is used to specify the mode of connection to use: - - \value ConnectionModeHttp The connection is a regular HTTP connection to the server - \value ConnectionModeHttps The HTTPS protocol is used and the connection is encrypted using SSL. - - When using the HTTPS mode, care should be taken to connect to the sslErrors signal, and - handle possible SSL errors. - - \sa QSslSocket -*/ - -/*! - \enum QHttp::State - - This enum is used to specify the state the client is in: - - \value Unconnected There is no connection to the host. - \value HostLookup A host name lookup is in progress. - \value Connecting An attempt to connect to the host is in progress. - \value Sending The client is sending its request to the server. - \value Reading The client's request has been sent and the client - is reading the server's response. - \value Connected The connection to the host is open, but the client is - neither sending a request, nor waiting for a response. - \value Closing The connection is closing down, but is not yet - closed. (The state will be \c Unconnected when the connection is - closed.) - - \sa stateChanged() state() -*/ - -/*! \enum QHttp::Error - - This enum identifies the error that occurred. - - \value NoError No error occurred. - \value HostNotFound The host name lookup failed. - \value ConnectionRefused The server refused the connection. - \value UnexpectedClose The server closed the connection unexpectedly. - \value InvalidResponseHeader The server sent an invalid response header. - \value WrongContentLength The client could not read the content correctly - because an error with respect to the content length occurred. - \value Aborted The request was aborted with abort(). - \value ProxyAuthenticationRequiredError QHttp is using a proxy, and the - proxy server requires authentication to establish a connection. - \value AuthenticationRequiredError The web server requires authentication - to complete the request. - \value UnknownError An error other than those specified above - occurred. - - \sa error() -*/ - -/*! - \fn void QHttp::stateChanged(int state) - - This signal is emitted when the state of the QHttp object changes. - The argument \a state is the new state of the connection; it is - one of the \l State values. - - This usually happens when a request is started, but it can also - happen when the server closes the connection or when a call to - close() succeeded. - - \sa get() post() head() request() close() state() State -*/ - -/*! - \fn void QHttp::responseHeaderReceived(const QHttpResponseHeader &resp); - - This signal is emitted when the HTTP header of a server response - is available. The header is passed in \a resp. - - \sa get() post() head() request() readyRead() -*/ - -/*! - \fn void QHttp::readyRead(const QHttpResponseHeader &resp) - - This signal is emitted when there is new response data to read. - - If you specified a device in the request where the data should be - written to, then this signal is \e not emitted; instead the data - is written directly to the device. - - The response header is passed in \a resp. - - You can read the data with the readAll() or read() functions - - This signal is useful if you want to process the data in chunks as - soon as it becomes available. If you are only interested in the - complete data, just connect to the requestFinished() signal and - read the data then instead. - - \sa get() post() request() readAll() read() bytesAvailable() -*/ - -/*! - \fn void QHttp::dataSendProgress(int done, int total) - - This signal is emitted when this object sends data to a HTTP - server to inform it about the progress of the upload. - - \a done is the amount of data that has already arrived and \a - total is the total amount of data. It is possible that the total - amount of data that should be transferred cannot be determined, in - which case \a total is 0.(If you connect to a QProgressBar, the - progress bar shows a busy indicator if the total is 0). - - \warning \a done and \a total are not necessarily the size in - bytes, since for large files these values might need to be - "scaled" to avoid overflow. - - \sa dataReadProgress(), post(), request(), QProgressBar -*/ - -/*! - \fn void QHttp::dataReadProgress(int done, int total) - - This signal is emitted when this object reads data from a HTTP - server to indicate the current progress of the download. - - \a done is the amount of data that has already arrived and \a - total is the total amount of data. It is possible that the total - amount of data that should be transferred cannot be determined, in - which case \a total is 0.(If you connect to a QProgressBar, the - progress bar shows a busy indicator if the total is 0). - - \warning \a done and \a total are not necessarily the size in - bytes, since for large files these values might need to be - "scaled" to avoid overflow. - - \sa dataSendProgress() get() post() request() QProgressBar -*/ - -/*! - \fn void QHttp::requestStarted(int id) - - This signal is emitted when processing the request identified by - \a id starts. - - \sa requestFinished() done() -*/ - -/*! - \fn void QHttp::requestFinished(int id, bool error) - - This signal is emitted when processing the request identified by - \a id has finished. \a error is true if an error occurred during - the processing; otherwise \a error is false. - - \sa requestStarted() done() error() errorString() -*/ - -/*! - \fn void QHttp::done(bool error) - - This signal is emitted when the last pending request has finished; - (it is emitted after the last request's requestFinished() signal). - \a error is true if an error occurred during the processing; - otherwise \a error is false. - - \sa requestFinished() error() errorString() -*/ - -#ifndef QT_NO_NETWORKPROXY - -/*! - \fn void QHttp::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator) - \since 4.3 - - This signal can be emitted when a \a proxy that requires - authentication is used. The \a authenticator object can then be - filled in with the required details to allow authentication and - continue the connection. - - \note It is not possible to use a QueuedConnection to connect to - this signal, as the connection will fail if the authenticator has - not been filled in with new information when the signal returns. - - \sa QAuthenticator, QNetworkProxy -*/ - -#endif - -/*! - \fn void QHttp::authenticationRequired(const QString &hostname, quint16 port, QAuthenticator *authenticator) - \since 4.3 - - This signal can be emitted when a web server on a given \a hostname and \a - port requires authentication. The \a authenticator object can then be - filled in with the required details to allow authentication and continue - the connection. - - \note It is not possible to use a QueuedConnection to connect to - this signal, as the connection will fail if the authenticator has - not been filled in with new information when the signal returns. - - \sa QAuthenticator, QNetworkProxy -*/ - -/*! - \fn void QHttp::sslErrors(const QList &errors) - \since 4.3 - - Forwards the sslErrors signal from the QSslSocket used in QHttp. \a errors - is the list of errors that occurred during the SSL handshake. Unless you - call ignoreSslErrors() from within a slot connected to this signal when an - error occurs, QHttp will tear down the connection immediately after - emitting the signal. - - \sa QSslSocket QSslSocket::ignoreSslErrors() -*/ - -/*! - Aborts the current request and deletes all scheduled requests. - - For the current request, the requestFinished() signal with the \c - error argument \c true is emitted. For all other requests that are - affected by the abort(), no signals are emitted. - - Since this slot also deletes the scheduled requests, there are no - requests left and the done() signal is emitted (with the \c error - argument \c true). - - \sa clearPendingRequests() -*/ -void QHttp::abort() -{ - Q_D(QHttp); - if (d->pending.isEmpty()) - return; - - d->finishedWithError(tr("Request aborted"), Aborted); - clearPendingRequests(); - if (d->socket) - d->socket->abort(); - d->closeConn(); -} - -/*! - Returns the number of bytes that can be read from the response - content at the moment. - - \sa get() post() request() readyRead() read() readAll() -*/ -qint64 QHttp::bytesAvailable() const -{ - Q_D(const QHttp); -#if defined(QHTTP_DEBUG) - qDebug("QHttp::bytesAvailable(): %d bytes", (int)d->rba.size()); -#endif - return qint64(d->rba.size()); -} - -/*! - Reads \a maxlen bytes from the response content into \a data and - returns the number of bytes read. Returns -1 if an error occurred. - - \sa get() post() request() readyRead() bytesAvailable() readAll() -*/ -qint64 QHttp::read(char *data, qint64 maxlen) -{ - Q_D(QHttp); - if (data == 0 && maxlen != 0) { - qWarning("QHttp::read: Null pointer error"); - return -1; - } - if (maxlen >= d->rba.size()) - maxlen = d->rba.size(); - int readSoFar = 0; - while (!d->rba.isEmpty() && readSoFar < maxlen) { - int nextBlockSize = d->rba.nextDataBlockSize(); - int bytesToRead = qMin(maxlen - readSoFar, nextBlockSize); - memcpy(data + readSoFar, d->rba.readPointer(), bytesToRead); - d->rba.free(bytesToRead); - readSoFar += bytesToRead; - } - - d->bytesDone += maxlen; -#if defined(QHTTP_DEBUG) - qDebug("QHttp::read(): read %lld bytes (%lld bytes done)", maxlen, d->bytesDone); -#endif - return maxlen; -} - -/*! - Reads all the bytes from the response content and returns them. - - \sa get() post() request() readyRead() bytesAvailable() read() -*/ -QByteArray QHttp::readAll() -{ - qint64 avail = bytesAvailable(); - QByteArray tmp; - tmp.resize(int(avail)); - qint64 got = read(tmp.data(), int(avail)); - tmp.resize(got); - return tmp; -} - -/*! - Returns the identifier of the HTTP request being executed or 0 if - there is no request being executed (i.e. they've all finished). - - \sa currentRequest() -*/ -int QHttp::currentId() const -{ - Q_D(const QHttp); - if (d->pending.isEmpty()) - return 0; - return d->pending.first()->id; -} - -/*! - Returns the request header of the HTTP request being executed. If - the request is one issued by setHost() or close(), it - returns an invalid request header, i.e. - QHttpRequestHeader::isValid() returns false. - - \sa currentId() -*/ -QHttpRequestHeader QHttp::currentRequest() const -{ - Q_D(const QHttp); - if (!d->pending.isEmpty()) { - QHttpRequest *r = d->pending.first(); - if (r->hasRequestHeader()) - return r->requestHeader(); - } - return QHttpRequestHeader(); -} - -/*! - Returns the received response header of the most recently finished HTTP - request. If no response has yet been received - QHttpResponseHeader::isValid() will return false. - - \sa currentRequest() -*/ -QHttpResponseHeader QHttp::lastResponse() const -{ - Q_D(const QHttp); - return d->response; -} - -/*! - Returns the QIODevice pointer that is used as the data source of the HTTP - request being executed. If there is no current request or if the request - does not use an IO device as the data source, this function returns 0. - - This function can be used to delete the QIODevice in the slot connected to - the requestFinished() signal. - - \sa currentDestinationDevice() post() request() -*/ -QIODevice *QHttp::currentSourceDevice() const -{ - Q_D(const QHttp); - if (d->pending.isEmpty()) - return 0; - return d->pending.first()->sourceDevice(); -} - -/*! - Returns the QIODevice pointer that is used as to store the data of the HTTP - request being executed. If there is no current request or if the request - does not store the data to an IO device, this function returns 0. - - This function can be used to delete the QIODevice in the slot connected to - the requestFinished() signal. - - \sa currentSourceDevice() get() post() request() -*/ -QIODevice *QHttp::currentDestinationDevice() const -{ - Q_D(const QHttp); - if (d->pending.isEmpty()) - return 0; - return d->pending.first()->destinationDevice(); -} - -/*! - Returns true if there are any requests scheduled that have not yet - been executed; otherwise returns false. - - The request that is being executed is \e not considered as a - scheduled request. - - \sa clearPendingRequests() currentId() currentRequest() -*/ -bool QHttp::hasPendingRequests() const -{ - Q_D(const QHttp); - return d->pending.count() > 1; -} - -/*! - Deletes all pending requests from the list of scheduled requests. - This does not affect the request that is being executed. If - you want to stop this as well, use abort(). - - \sa hasPendingRequests() abort() -*/ -void QHttp::clearPendingRequests() -{ - Q_D(QHttp); - // delete all entires except the first one - while (d->pending.count() > 1) - delete d->pending.takeLast(); -} - -/*! - Sets the HTTP server that is used for requests to \a hostName on - port \a port. - - The function does not block; instead, it returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - \sa get() post() head() request() requestStarted() requestFinished() done() -*/ -int QHttp::setHost(const QString &hostName, quint16 port) -{ - Q_D(QHttp); - return d->addRequest(new QHttpSetHostRequest(hostName, port, ConnectionModeHttp)); -} - -/*! - Sets the HTTP server that is used for requests to \a hostName on - port \a port using the connection mode \a mode. - - If port is 0, it will use the default port for the \a mode used - (80 for HTTP and 443 for HTTPS). - - The function does not block; instead, it returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - \sa get() post() head() request() requestStarted() requestFinished() done() -*/ -int QHttp::setHost(const QString &hostName, ConnectionMode mode, quint16 port) -{ -#ifdef QT_NO_OPENSSL - if (mode == ConnectionModeHttps) - qWarning("QHttp::setHost: HTTPS connection requested but SSL support not compiled in"); -#endif - Q_D(QHttp); - if (port == 0) - port = (mode == ConnectionModeHttp) ? 80 : 443; - return d->addRequest(new QHttpSetHostRequest(hostName, port, mode)); -} - -/*! - Replaces the internal QTcpSocket that QHttp uses with \a - socket. This is useful if you want to use your own custom QTcpSocket - subclass instead of the plain QTcpSocket that QHttp uses by default. - QHttp does not take ownership of the socket, and will not delete \a - socket when destroyed. - - The function does not block; instead, it returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - Note: If QHttp is used in a non-GUI thread that runs its own event - loop, you must move \a socket to that thread before calling setSocket(). - - \sa QObject::moveToThread(), {Thread Support in Qt} -*/ -int QHttp::setSocket(QTcpSocket *socket) -{ - Q_D(QHttp); - return d->addRequest(new QHttpSetSocketRequest(socket)); -} - -/*! - This function sets the user name \a userName and password \a - password for web pages that require authentication. - - The function does not block; instead, it returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. -*/ -int QHttp::setUser(const QString &userName, const QString &password) -{ - Q_D(QHttp); - return d->addRequest(new QHttpSetUserRequest(userName, password)); -} - -#ifndef QT_NO_NETWORKPROXY - -/*! - Enables HTTP proxy support, using the proxy server \a host on port \a - port. \a username and \a password can be provided if the proxy server - requires authentication. - - Example: - - \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 7 - - QHttp supports non-transparent web proxy servers only, such as the Squid - Web proxy cache server (from \l http://www.squid.org/). For transparent - proxying, such as SOCKS5, use QNetworkProxy instead. - - \note setProxy() has to be called before setHost() for it to take effect. - If setProxy() is called after setHost(), then it will not apply until after - setHost() is called again. - - \sa QFtp::setProxy() -*/ -int QHttp::setProxy(const QString &host, int port, - const QString &username, const QString &password) -{ - Q_D(QHttp); - QNetworkProxy proxy(QNetworkProxy::HttpProxy, host, port, username, password); - return d->addRequest(new QHttpSetProxyRequest(proxy)); -} - -/*! - \overload - - Enables HTTP proxy support using the proxy settings from \a - proxy. If \a proxy is a transparent proxy, QHttp will call - QAbstractSocket::setProxy() on the underlying socket. If the type - is QNetworkProxy::HttpCachingProxy, QHttp will behave like the - previous function. - - \note for compatibility with Qt 4.3, if the proxy type is - QNetworkProxy::HttpProxy and the request type is unencrypted (that - is, ConnectionModeHttp), QHttp will treat the proxy as a caching - proxy. -*/ -int QHttp::setProxy(const QNetworkProxy &proxy) -{ - Q_D(QHttp); - return d->addRequest(new QHttpSetProxyRequest(proxy)); -} - -#endif - -/*! - Sends a get request for \a path to the server set by setHost() or - as specified in the constructor. - - \a path must be a absolute path like \c /index.html or an - absolute URI like \c http://example.com/index.html and - must be encoded with either QUrl::toPercentEncoding() or - QUrl::encodedPath(). - - If the IO device \a to is 0 the readyRead() signal is emitted - every time new content data is available to read. - - If the IO device \a to is not 0, the content data of the response - is written directly to the device. Make sure that the \a to - pointer is valid for the duration of the operation (it is safe to - delete it when the requestFinished() signal is emitted). - - \section1 Request Processing - - The function does not block; instead, it returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - \sa setHost(), post(), head(), request(), requestStarted(), - requestFinished(), done() -*/ -int QHttp::get(const QString &path, QIODevice *to) -{ - Q_D(QHttp); - QHttpRequestHeader header(QLatin1String("GET"), path); - header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive")); - return d->addRequest(new QHttpPGHRequest(header, (QIODevice *) 0, to)); -} - -/*! - Sends a post request for \a path to the server set by setHost() or - as specified in the constructor. - - \a path must be an absolute path like \c /index.html or an - absolute URI like \c http://example.com/index.html and - must be encoded with either QUrl::toPercentEncoding() or - QUrl::encodedPath(). - - The incoming data comes via the \a data IO device. - - If the IO device \a to is 0 the readyRead() signal is emitted - every time new content data is available to read. - - If the IO device \a to is not 0, the content data of the response - is written directly to the device. Make sure that the \a to - pointer is valid for the duration of the operation (it is safe to - delete it when the requestFinished() signal is emitted). - - The function does not block; instead, it returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - \sa setHost() get() head() request() requestStarted() requestFinished() done() -*/ -int QHttp::post(const QString &path, QIODevice *data, QIODevice *to ) -{ - Q_D(QHttp); - QHttpRequestHeader header(QLatin1String("POST"), path); - header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive")); - return d->addRequest(new QHttpPGHRequest(header, data, to)); -} - -/*! - \overload - - \a data is used as the content data of the HTTP request. -*/ -int QHttp::post(const QString &path, const QByteArray &data, QIODevice *to) -{ - Q_D(QHttp); - QHttpRequestHeader header(QLatin1String("POST"), path); - header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive")); - return d->addRequest(new QHttpPGHRequest(header, new QByteArray(data), to)); -} - -/*! - Sends a header request for \a path to the server set by setHost() - or as specified in the constructor. - - \a path must be an absolute path like \c /index.html or an - absolute URI like \c http://example.com/index.html. - - The function does not block; instead, it returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - \sa setHost() get() post() request() requestStarted() requestFinished() done() -*/ -int QHttp::head(const QString &path) -{ - Q_D(QHttp); - QHttpRequestHeader header(QLatin1String("HEAD"), path); - header.setValue(QLatin1String("Connection"), QLatin1String("Keep-Alive")); - return d->addRequest(new QHttpPGHRequest(header, (QIODevice*)0, 0)); -} - -/*! - Sends a request to the server set by setHost() or as specified in - the constructor. Uses the \a header as the HTTP request header. - You are responsible for setting up a header that is appropriate - for your request. - - The incoming data comes via the \a data IO device. - - If the IO device \a to is 0 the readyRead() signal is emitted - every time new content data is available to read. - - If the IO device \a to is not 0, the content data of the response - is written directly to the device. Make sure that the \a to - pointer is valid for the duration of the operation (it is safe to - delete it when the requestFinished() signal is emitted). - - The function does not block; instead, it returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - \sa setHost() get() post() head() requestStarted() requestFinished() done() -*/ -int QHttp::request(const QHttpRequestHeader &header, QIODevice *data, QIODevice *to) -{ - Q_D(QHttp); - return d->addRequest(new QHttpNormalRequest(header, data, to)); -} - -/*! - \overload - - \a data is used as the content data of the HTTP request. -*/ -int QHttp::request(const QHttpRequestHeader &header, const QByteArray &data, QIODevice *to ) -{ - Q_D(QHttp); - return d->addRequest(new QHttpNormalRequest(header, new QByteArray(data), to)); -} - -/*! - Closes the connection; this is useful if you have a keep-alive - connection and want to close it. - - For the requests issued with get(), post() and head(), QHttp sets - the connection to be keep-alive. You can also do this using the - header you pass to the request() function. QHttp only closes the - connection to the HTTP server if the response header requires it - to do so. - - The function does not block; instead, it returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - If you want to close the connection immediately, you have to use - abort() instead. - - \sa stateChanged() abort() requestStarted() requestFinished() done() -*/ -int QHttp::close() -{ - Q_D(QHttp); - return d->addRequest(new QHttpCloseRequest()); -} - -/*! - \obsolete - - Behaves the same as close(). -*/ -int QHttp::closeConnection() -{ - Q_D(QHttp); - return d->addRequest(new QHttpCloseRequest()); -} - -int QHttpPrivate::addRequest(QHttpNormalRequest *req) -{ - QHttpRequestHeader h = req->requestHeader(); - if (h.path().isEmpty()) { - // note: the following qWarning is autotested. If you change it, change the test too. - qWarning("QHttp: empty path requested is invalid -- using '/'"); - h.setRequest(h.method(), QLatin1String("/"), h.majorVersion(), h.minorVersion()); - req->setRequestHeader(h); - } - - // contine below - return addRequest(static_cast(req)); -} - -int QHttpPrivate::addRequest(QHttpRequest *req) -{ - Q_Q(QHttp); - pending.append(req); - - if (pending.count() == 1) { - // don't emit the requestStarted() signal before the id is returned - QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); - } - return req->id; -} - -void QHttpPrivate::_q_startNextRequest() -{ - Q_Q(QHttp); - if (pending.isEmpty()) - return; - QHttpRequest *r = pending.first(); - - error = QHttp::NoError; - errorString = QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Unknown error")); - - if (q->bytesAvailable() != 0) - q->readAll(); // clear the data - emit q->requestStarted(r->id); - r->start(q); -} - -void QHttpPrivate::_q_slotSendRequest() -{ - if (hostName.isNull()) { - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "No server set to connect to")), - QHttp::UnknownError); - return; - } - - QString connectionHost = hostName; - int connectionPort = port; - bool sslInUse = false; - -#ifndef QT_NO_OPENSSL - QSslSocket *sslSocket = qobject_cast(socket); - if (mode == QHttp::ConnectionModeHttps || (sslSocket && sslSocket->isEncrypted())) - sslInUse = true; -#endif - -#ifndef QT_NO_NETWORKPROXY - bool cachingProxyInUse = false; - bool transparentProxyInUse = false; - if (proxy.type() == QNetworkProxy::DefaultProxy) - proxy = QNetworkProxy::applicationProxy(); - - if (proxy.type() == QNetworkProxy::HttpCachingProxy) { - if (proxy.hostName().isEmpty()) - proxy.setType(QNetworkProxy::NoProxy); - else - cachingProxyInUse = true; - } else if (proxy.type() == QNetworkProxy::HttpProxy) { - // Compatibility behaviour: HttpProxy can be used to mean both - // transparent and caching proxy - if (proxy.hostName().isEmpty()) { - proxy.setType(QNetworkProxy::NoProxy); - } else if (sslInUse) { - // Disallow use of caching proxy with HTTPS; instead fall back to - // transparent HTTP CONNECT proxying. - transparentProxyInUse = true; - } else { - proxy.setType(QNetworkProxy::HttpCachingProxy); - cachingProxyInUse = true; - } - } - - // Proxy support. Insert the Proxy-Authorization item into the - // header before it's sent off to the proxy. - if (cachingProxyInUse) { - QUrl proxyUrl; - proxyUrl.setScheme(QLatin1String("http")); - proxyUrl.setHost(hostName); - if (port && port != 80) - proxyUrl.setPort(port); - QString request = QString::fromAscii(proxyUrl.resolved(QUrl::fromEncoded(header.path().toLatin1())).toEncoded()); - - header.setRequest(header.method(), request, header.majorVersion(), header.minorVersion()); - header.setValue(QLatin1String("Proxy-Connection"), QLatin1String("keep-alive")); - - QAuthenticatorPrivate *auth = QAuthenticatorPrivate::getPrivate(proxyAuthenticator); - if (auth && auth->method != QAuthenticatorPrivate::None) { - QByteArray response = auth->calculateResponse(header.method().toLatin1(), header.path().toLatin1()); - header.setValue(QLatin1String("Proxy-Authorization"), QString::fromLatin1(response)); - } - - connectionHost = proxy.hostName(); - connectionPort = proxy.port(); - } - - if (transparentProxyInUse || sslInUse) { - socket->setProxy(proxy); - } -#endif - - // Username support. Insert the user and password into the query - // string. - QAuthenticatorPrivate *auth = QAuthenticatorPrivate::getPrivate(authenticator); - if (auth && auth->method != QAuthenticatorPrivate::None) { - QByteArray response = auth->calculateResponse(header.method().toLatin1(), header.path().toLatin1()); - header.setValue(QLatin1String("Authorization"), QString::fromLatin1(response)); - } - - // Do we need to setup a new connection or can we reuse an - // existing one? - if (socket->peerName() != connectionHost || socket->peerPort() != connectionPort - || socket->state() != QTcpSocket::ConnectedState -#ifndef QT_NO_OPENSSL - || (sslSocket && sslSocket->isEncrypted() != (mode == QHttp::ConnectionModeHttps)) -#endif - ) { - socket->blockSignals(true); - socket->abort(); - socket->blockSignals(false); - - setState(QHttp::Connecting); -#ifndef QT_NO_OPENSSL - if (sslSocket && mode == QHttp::ConnectionModeHttps) { - sslSocket->connectToHostEncrypted(hostName, port); - } else -#endif - { - socket->connectToHost(connectionHost, connectionPort); - } - } else { - _q_slotConnected(); - } - -} - -void QHttpPrivate::finishedWithSuccess() -{ - Q_Q(QHttp); - if (pending.isEmpty()) - return; - QHttpRequest *r = pending.first(); - - // did we recurse? - if (r->finished) - return; - r->finished = true; - hasFinishedWithError = false; - - emit q->requestFinished(r->id, false); - if (hasFinishedWithError) { - // we recursed and changed into an error. The finishedWithError function - // below has emitted the done(bool) signal and cleared the queue by now. - return; - } - - pending.removeFirst(); - delete r; - - if (pending.isEmpty()) { - emit q->done(false); - } else { - _q_startNextRequest(); - } -} - -void QHttpPrivate::finishedWithError(const QString &detail, int errorCode) -{ - Q_Q(QHttp); - if (pending.isEmpty()) - return; - QHttpRequest *r = pending.first(); - hasFinishedWithError = true; - - error = QHttp::Error(errorCode); - errorString = detail; - - // did we recurse? - if (!r->finished) { - r->finished = true; - emit q->requestFinished(r->id, true); - } - - while (!pending.isEmpty()) - delete pending.takeFirst(); - emit q->done(hasFinishedWithError); -} - -void QHttpPrivate::_q_slotClosed() -{ - Q_Q(QHttp); - - if (state == QHttp::Reading) { - if (response.hasKey(QLatin1String("content-length"))) { - // We got Content-Length, so did we get all bytes? - if (bytesDone + q->bytesAvailable() != response.contentLength()) { - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Wrong content length")), QHttp::WrongContentLength); - } - } - } else if (state == QHttp::Connecting || state == QHttp::Sending) { - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Server closed connection unexpectedly")), QHttp::UnexpectedClose); - } - - postDevice = 0; - if (state != QHttp::Closing) - setState(QHttp::Closing); - QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection); -} - -void QHttpPrivate::_q_continuePost() -{ - if (pendingPost) { - pendingPost = false; - setState(QHttp::Sending); - _q_slotBytesWritten(0); - } -} - -void QHttpPrivate::_q_slotConnected() -{ - if (state != QHttp::Sending) { - bytesDone = 0; - setState(QHttp::Sending); - } - - QString str = header.toString(); - bytesTotal = str.length(); - socket->write(str.toLatin1(), bytesTotal); -#if defined(QHTTP_DEBUG) - qDebug("QHttp: write request header %p:\n---{\n%s}---", &header, str.toLatin1().constData()); -#endif - - if (postDevice) { - postDevice->seek(0); // reposition the device - bytesTotal += postDevice->size(); - //check for 100-continue - if (header.value(QLatin1String("expect")).contains(QLatin1String("100-continue"), Qt::CaseInsensitive)) { - //create a time out for 2 secs. - pendingPost = true; - post100ContinueTimer.start(2000); - } - } else { - bytesTotal += buffer.size(); - socket->write(buffer, buffer.size()); - } -} - -void QHttpPrivate::_q_slotError(QAbstractSocket::SocketError err) -{ - Q_Q(QHttp); - postDevice = 0; - - if (state == QHttp::Connecting || state == QHttp::Reading || state == QHttp::Sending) { - switch (err) { - case QTcpSocket::ConnectionRefusedError: - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Connection refused (or timed out)")), QHttp::ConnectionRefused); - break; - case QTcpSocket::HostNotFoundError: - finishedWithError(QString::fromLatin1(QT_TRANSLATE_NOOP("QHttp", "Host %1 not found")) - .arg(socket->peerName()), QHttp::HostNotFound); - break; - case QTcpSocket::RemoteHostClosedError: - if (state == QHttp::Sending && reconnectAttempts--) { - setState(QHttp::Closing); - setState(QHttp::Unconnected); - socket->blockSignals(true); - socket->abort(); - socket->blockSignals(false); - QMetaObject::invokeMethod(q, "_q_slotSendRequest", Qt::QueuedConnection); - return; - } - break; -#ifndef QT_NO_NETWORKPROXY - case QTcpSocket::ProxyAuthenticationRequiredError: - finishedWithError(socket->errorString(), QHttp::ProxyAuthenticationRequiredError); - break; -#endif - default: - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "HTTP request failed")), QHttp::UnknownError); - break; - } - } - - closeConn(); -} - -#ifndef QT_NO_OPENSSL -void QHttpPrivate::_q_slotEncryptedBytesWritten(qint64 written) -{ - Q_UNUSED(written); - postMoreData(); -} -#endif - -void QHttpPrivate::_q_slotBytesWritten(qint64 written) -{ - Q_Q(QHttp); - bytesDone += written; - emit q->dataSendProgress(bytesDone, bytesTotal); - postMoreData(); -} - -// Send the POST data -void QHttpPrivate::postMoreData() -{ - if (pendingPost) - return; - - if (!postDevice) - return; - - // the following is backported code from Qt 4.6 QNetworkAccessManager. - // We also have to check the encryptedBytesToWrite() if it is an SSL socket. -#ifndef QT_NO_OPENSSL - QSslSocket *sslSocket = qobject_cast(socket); - // if it is really an ssl socket, check more than just bytesToWrite() - if ((socket->bytesToWrite() + (sslSocket ? sslSocket->encryptedBytesToWrite() : 0)) == 0) { -#else - if (socket->bytesToWrite() == 0) { -#endif - int max = qMin(4096, postDevice->size() - postDevice->pos()); - QByteArray arr; - arr.resize(max); - - int n = postDevice->read(arr.data(), max); - if (n < 0) { - qWarning("Could not read enough bytes from the device"); - closeConn(); - return; - } - if (postDevice->atEnd()) { - postDevice = 0; - } - - socket->write(arr, n); - } -} - -void QHttpPrivate::_q_slotReadyRead() -{ - Q_Q(QHttp); - QHttp::State oldState = state; - if (state != QHttp::Reading) { - setState(QHttp::Reading); - readHeader = true; - headerStr = QLatin1String(""); - bytesDone = 0; - chunkedSize = -1; - repost = false; - } - - while (readHeader) { - bool end = false; - QString tmp; - while (!end && socket->canReadLine()) { - tmp = QString::fromAscii(socket->readLine()); - if (tmp == QLatin1String("\r\n") || tmp == QLatin1String("\n") || tmp.isEmpty()) - end = true; - else - headerStr += tmp; - } - - if (!end) - return; - - response = QHttpResponseHeader(headerStr); - headerStr = QLatin1String(""); -#if defined(QHTTP_DEBUG) - qDebug("QHttp: read response header:\n---{\n%s}---", response.toString().toLatin1().constData()); -#endif - // Check header - if (!response.isValid()) { - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Invalid HTTP response header")), - QHttp::InvalidResponseHeader); - closeConn(); - return; - } - - int statusCode = response.statusCode(); - if (statusCode == 401 || statusCode == 407) { // (Proxy) Authentication required - QAuthenticator *auth = -#ifndef QT_NO_NETWORKPROXY - statusCode == 407 - ? &proxyAuthenticator : -#endif - &authenticator; - if (auth->isNull()) - auth->detach(); - QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(*auth); - priv->parseHttpResponse(response, (statusCode == 407)); - if (priv->phase == QAuthenticatorPrivate::Done) { - socket->blockSignals(true); -#ifndef QT_NO_NETWORKPROXY - if (statusCode == 407) - emit q->proxyAuthenticationRequired(proxy, auth); - else -#endif - emit q->authenticationRequired(hostName, port, auth); - socket->blockSignals(false); - } else if (priv->phase == QAuthenticatorPrivate::Invalid) { - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Unknown authentication method")), - QHttp::AuthenticationRequiredError); - closeConn(); - return; - } - - // priv->phase will get reset to QAuthenticatorPrivate::Start if the authenticator got modified in the signal above. - if (priv->phase == QAuthenticatorPrivate::Done) { -#ifndef QT_NO_NETWORKPROXY - if (statusCode == 407) - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Proxy authentication required")), - QHttp::ProxyAuthenticationRequiredError); - else -#endif - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Authentication required")), - QHttp::AuthenticationRequiredError); - closeConn(); - return; - } else { - // close the connection if it isn't already and reconnect using the chosen authentication method - bool willClose = (response.value(QLatin1String("proxy-connection")).toLower() == QLatin1String("close")) - || (response.value(QLatin1String("connection")).toLower() == QLatin1String("close")); - if (willClose) { - if (socket) { - setState(QHttp::Closing); - socket->blockSignals(true); - socket->close(); - socket->blockSignals(false); - socket->readAll(); - } - _q_slotSendRequest(); - return; - } else { - repost = true; - } - } - } else { - buffer.clear(); - } - - if (response.statusCode() == 100 && pendingPost) { - // if we have pending POST, start sending data otherwise ignore - post100ContinueTimer.stop(); - QMetaObject::invokeMethod(q, "_q_continuePost", Qt::QueuedConnection); - return; - } - - // The 100-continue header is ignored (in case of no 'expect:100-continue' header), - // because when using the POST method, we send both the request header and data in - // one chunk. - if (response.statusCode() != 100) { - post100ContinueTimer.stop(); - pendingPost = false; - readHeader = false; - if (response.hasKey(QLatin1String("transfer-encoding")) && - response.value(QLatin1String("transfer-encoding")).toLower().contains(QLatin1String("chunked"))) - chunkedSize = 0; - - if (!repost) - emit q->responseHeaderReceived(response); - if (state == QHttp::Unconnected || state == QHttp::Closing) - return; - } else { - // Restore the state, the next incoming data will be treated as if - // we never say the 100 response. - state = oldState; - } - } - - bool everythingRead = false; - - if (q->currentRequest().method() == QLatin1String("HEAD") || - response.statusCode() == 304 || response.statusCode() == 204 || - response.statusCode() == 205) { - // HEAD requests have only headers as replies - // These status codes never have a body: - // 304 Not Modified - // 204 No Content - // 205 Reset Content - everythingRead = true; - } else { - qint64 n = socket->bytesAvailable(); - QByteArray *arr = 0; - if (chunkedSize != -1) { - // transfer-encoding is chunked - for (;;) { - // get chunk size - if (chunkedSize == 0) { - if (!socket->canReadLine()) - break; - QString sizeString = QString::fromAscii(socket->readLine()); - int tPos = sizeString.indexOf(QLatin1Char(';')); - if (tPos != -1) - sizeString.truncate(tPos); - bool ok; - chunkedSize = sizeString.toInt(&ok, 16); - if (!ok) { - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Invalid HTTP chunked body")), - QHttp::WrongContentLength); - closeConn(); - delete arr; - return; - } - if (chunkedSize == 0) // last-chunk - chunkedSize = -2; - } - - // read trailer - while (chunkedSize == -2 && socket->canReadLine()) { - QString read = QString::fromAscii(socket->readLine()); - if (read == QLatin1String("\r\n") || read == QLatin1String("\n")) - chunkedSize = -1; - } - if (chunkedSize == -1) { - everythingRead = true; - break; - } - - // make sure that you can read the terminating CRLF, - // otherwise wait until next time... - n = socket->bytesAvailable(); - if (n == 0) - break; - if (n == chunkedSize || n == chunkedSize+1) { - n = chunkedSize - 1; - if (n == 0) - break; - } - - // read data - qint64 toRead = chunkedSize < 0 ? n : qMin(n, chunkedSize); - if (!arr) - arr = new QByteArray; - uint oldArrSize = arr->size(); - arr->resize(oldArrSize + toRead); - qint64 read = socket->read(arr->data()+oldArrSize, toRead); - arr->resize(oldArrSize + read); - - chunkedSize -= read; - - if (chunkedSize == 0 && n - read >= 2) { - // read terminating CRLF - char tmp[2]; - socket->read(tmp, 2); - if (tmp[0] != '\r' || tmp[1] != '\n') { - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Invalid HTTP chunked body")), - QHttp::WrongContentLength); - closeConn(); - delete arr; - return; - } - } - } - } else if (response.hasContentLength()) { - if (repost && (n < response.contentLength())) { - // wait for the content to be available fully - // if repost is required, the content is ignored - return; - } - n = qMin(qint64(response.contentLength() - bytesDone), n); - if (n > 0) { - arr = new QByteArray; - arr->resize(n); - qint64 read = socket->read(arr->data(), n); - arr->resize(read); - } - if (bytesDone + q->bytesAvailable() + n == response.contentLength()) - everythingRead = true; - } else if (n > 0) { - // workaround for VC++ bug - QByteArray temp = socket->readAll(); - arr = new QByteArray(temp); - } - - if (arr && !repost) { - n = arr->size(); - if (toDevice) { - qint64 bytesWritten; - bytesWritten = toDevice->write(*arr, n); - delete arr; - arr = 0; - // if writing to the device does not succeed, quit with error - if (bytesWritten == -1 || bytesWritten < n) { - finishedWithError(QLatin1String(QT_TRANSLATE_NOOP("QHttp", "Error writing response to device")), QHttp::UnknownError); - } else { - bytesDone += bytesWritten; -#if defined(QHTTP_DEBUG) - qDebug("QHttp::_q_slotReadyRead(): read %lld bytes (%lld bytes done)", n, bytesDone); -#endif - } - if (response.hasContentLength()) - emit q->dataReadProgress(bytesDone, response.contentLength()); - else - emit q->dataReadProgress(bytesDone, 0); - } else { - char *ptr = rba.reserve(arr->size()); - memcpy(ptr, arr->data(), arr->size()); - delete arr; - arr = 0; -#if defined(QHTTP_DEBUG) - qDebug("QHttp::_q_slotReadyRead(): read %lld bytes (%lld bytes done)", n, bytesDone + q->bytesAvailable()); -#endif - if (response.hasContentLength()) - emit q->dataReadProgress(bytesDone + q->bytesAvailable(), response.contentLength()); - else - emit q->dataReadProgress(bytesDone + q->bytesAvailable(), 0); - emit q->readyRead(response); - } - } - - delete arr; - } - - if (everythingRead) { - if (repost) { - _q_slotSendRequest(); - return; - } - // Handle "Connection: close" - if (response.value(QLatin1String("connection")).toLower() == QLatin1String("close")) { - closeConn(); - } else { - setState(QHttp::Connected); - // Start a timer, so that we emit the keep alive signal - // "after" this method returned. - QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection); - } - } -} - -void QHttpPrivate::_q_slotDoFinished() -{ - if (state == QHttp::Connected) { - finishedWithSuccess(); - } else if (state != QHttp::Unconnected) { - setState(QHttp::Unconnected); - finishedWithSuccess(); - } -} - - -/*! - Returns the current state of the object. When the state changes, - the stateChanged() signal is emitted. - - \sa State stateChanged() -*/ -QHttp::State QHttp::state() const -{ - Q_D(const QHttp); - return d->state; -} - -/*! - Returns the last error that occurred. This is useful to find out - what happened when receiving a requestFinished() or a done() - signal with the \c error argument \c true. - - If you start a new request, the error status is reset to \c NoError. -*/ -QHttp::Error QHttp::error() const -{ - Q_D(const QHttp); - return d->error; -} - -/*! - Returns a human-readable description of the last error that - occurred. This is useful to present a error message to the user - when receiving a requestFinished() or a done() signal with the \c - error argument \c true. -*/ -QString QHttp::errorString() const -{ - Q_D(const QHttp); - return d->errorString; -} - -void QHttpPrivate::setState(int s) -{ - Q_Q(QHttp); -#if defined(QHTTP_DEBUG) - qDebug("QHttp state changed %d -> %d", state, s); -#endif - state = QHttp::State(s); - emit q->stateChanged(s); -} - -void QHttpPrivate::closeConn() -{ - Q_Q(QHttp); - // If no connection is open -> ignore - if (state == QHttp::Closing || state == QHttp::Unconnected) - return; - - postDevice = 0; - setState(QHttp::Closing); - - // Already closed ? - if (!socket || !socket->isOpen()) { - QMetaObject::invokeMethod(q, "_q_slotDoFinished", Qt::QueuedConnection); - } else { - // Close now. - socket->close(); - } -} - -void QHttpPrivate::setSock(QTcpSocket *sock) -{ - Q_Q(const QHttp); - - // disconnect all existing signals - if (socket) - socket->disconnect(); - if (deleteSocket) - delete socket; - - // use the new QTcpSocket socket, or create one if socket is 0. - deleteSocket = (sock == 0); - socket = sock; - if (!socket) { -#ifndef QT_NO_OPENSSL - if (QSslSocket::supportsSsl()) - socket = new QSslSocket(); - else -#endif - socket = new QTcpSocket(); - } - - // connect all signals - QObject::connect(socket, SIGNAL(connected()), q, SLOT(_q_slotConnected())); - QObject::connect(socket, SIGNAL(disconnected()), q, SLOT(_q_slotClosed())); - QObject::connect(socket, SIGNAL(readyRead()), q, SLOT(_q_slotReadyRead())); - QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), q, SLOT(_q_slotError(QAbstractSocket::SocketError))); - QObject::connect(socket, SIGNAL(bytesWritten(qint64)), - q, SLOT(_q_slotBytesWritten(qint64))); -#ifndef QT_NO_NETWORKPROXY - QObject::connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), - q, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); -#endif - -#ifndef QT_NO_OPENSSL - if (qobject_cast(socket)) { - QObject::connect(socket, SIGNAL(sslErrors(QList)), - q, SIGNAL(sslErrors(QList))); - QObject::connect(socket, SIGNAL(encryptedBytesWritten(qint64)), - q, SLOT(_q_slotEncryptedBytesWritten(qint64))); - } -#endif -} - -/*! - Tells the QSslSocket used for the Http connection to ignore the errors - reported in the sslErrors() signal. - - Note that this function must be called from within a slot connected to the - sslErrors() signal to have any effect. - - \sa QSslSocket QSslSocket::sslErrors() -*/ -#ifndef QT_NO_OPENSSL -void QHttp::ignoreSslErrors() -{ - Q_D(QHttp); - QSslSocket *sslSocket = qobject_cast(d->socket); - if (sslSocket) - sslSocket->ignoreSslErrors(); -} -#endif - -QT_END_NAMESPACE - -#include "moc_qhttp.cpp" - -#endif diff --git a/src/network/access/qhttp.h b/src/network/access/qhttp.h deleted file mode 100644 index 5dd3b5bc3d..0000000000 --- a/src/network/access/qhttp.h +++ /dev/null @@ -1,311 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QHTTP_H -#define QHTTP_H - -#include -#include -#include -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Network) - -#ifndef QT_NO_HTTP - -class QTcpSocket; -class QTimerEvent; -class QIODevice; -class QAuthenticator; -class QNetworkProxy; -class QSslError; - -class QHttpPrivate; - -class QHttpHeaderPrivate; -class Q_NETWORK_EXPORT QHttpHeader -{ -public: - QHttpHeader(); - QHttpHeader(const QHttpHeader &header); - QHttpHeader(const QString &str); - virtual ~QHttpHeader(); - - QHttpHeader &operator=(const QHttpHeader &h); - - void setValue(const QString &key, const QString &value); - void setValues(const QList > &values); - void addValue(const QString &key, const QString &value); - QList > values() const; - bool hasKey(const QString &key) const; - QStringList keys() const; - QString value(const QString &key) const; - QStringList allValues(const QString &key) const; - void removeValue(const QString &key); - void removeAllValues(const QString &key); - - // ### Qt 5: change to qint64 - bool hasContentLength() const; - uint contentLength() const; - void setContentLength(int len); - - bool hasContentType() const; - QString contentType() const; - void setContentType(const QString &type); - - virtual QString toString() const; - bool isValid() const; - - virtual int majorVersion() const = 0; - virtual int minorVersion() const = 0; - -protected: - virtual bool parseLine(const QString &line, int number); - bool parse(const QString &str); - void setValid(bool); - - QHttpHeader(QHttpHeaderPrivate &dd, const QString &str = QString()); - QHttpHeader(QHttpHeaderPrivate &dd, const QHttpHeader &header); - QScopedPointer d_ptr; - -private: - Q_DECLARE_PRIVATE(QHttpHeader) -}; - -class QHttpResponseHeaderPrivate; -class Q_NETWORK_EXPORT QHttpResponseHeader : public QHttpHeader -{ -public: - QHttpResponseHeader(); - QHttpResponseHeader(const QHttpResponseHeader &header); - QHttpResponseHeader(const QString &str); - QHttpResponseHeader(int code, const QString &text = QString(), int majorVer = 1, int minorVer = 1); - QHttpResponseHeader &operator=(const QHttpResponseHeader &header); - - void setStatusLine(int code, const QString &text = QString(), int majorVer = 1, int minorVer = 1); - - int statusCode() const; - QString reasonPhrase() const; - - int majorVersion() const; - int minorVersion() const; - - QString toString() const; - -protected: - bool parseLine(const QString &line, int number); - -private: - Q_DECLARE_PRIVATE(QHttpResponseHeader) - friend class QHttpPrivate; -}; - -class QHttpRequestHeaderPrivate; -class Q_NETWORK_EXPORT QHttpRequestHeader : public QHttpHeader -{ -public: - QHttpRequestHeader(); - QHttpRequestHeader(const QString &method, const QString &path, int majorVer = 1, int minorVer = 1); - QHttpRequestHeader(const QHttpRequestHeader &header); - QHttpRequestHeader(const QString &str); - QHttpRequestHeader &operator=(const QHttpRequestHeader &header); - - void setRequest(const QString &method, const QString &path, int majorVer = 1, int minorVer = 1); - - QString method() const; - QString path() const; - - int majorVersion() const; - int minorVersion() const; - - QString toString() const; - -protected: - bool parseLine(const QString &line, int number); - -private: - Q_DECLARE_PRIVATE(QHttpRequestHeader) -}; - -class Q_NETWORK_EXPORT QHttp : public QObject -{ - Q_OBJECT - -public: - enum ConnectionMode { - ConnectionModeHttp, - ConnectionModeHttps - }; - - explicit QHttp(QObject *parent = 0); - QHttp(const QString &hostname, quint16 port = 80, QObject *parent = 0); - QHttp(const QString &hostname, ConnectionMode mode, quint16 port = 0, QObject *parent = 0); - virtual ~QHttp(); - - enum State { - Unconnected, - HostLookup, - Connecting, - Sending, - Reading, - Connected, - Closing - }; - enum Error { - NoError, - UnknownError, - HostNotFound, - ConnectionRefused, - UnexpectedClose, - InvalidResponseHeader, - WrongContentLength, - Aborted, - AuthenticationRequiredError, - ProxyAuthenticationRequiredError - }; - - int setHost(const QString &hostname, quint16 port = 80); - int setHost(const QString &hostname, ConnectionMode mode, quint16 port = 0); - - int setSocket(QTcpSocket *socket); - int setUser(const QString &username, const QString &password = QString()); - -#ifndef QT_NO_NETWORKPROXY - int setProxy(const QString &host, int port, - const QString &username = QString(), - const QString &password = QString()); - int setProxy(const QNetworkProxy &proxy); -#endif - - int get(const QString &path, QIODevice *to=0); - int post(const QString &path, QIODevice *data, QIODevice *to=0 ); - int post(const QString &path, const QByteArray &data, QIODevice *to=0); - int head(const QString &path); - int request(const QHttpRequestHeader &header, QIODevice *device=0, QIODevice *to=0); - int request(const QHttpRequestHeader &header, const QByteArray &data, QIODevice *to=0); - - int closeConnection(); - int close(); - - qint64 bytesAvailable() const; - qint64 read(char *data, qint64 maxlen); - QByteArray readAll(); - - int currentId() const; - QIODevice *currentSourceDevice() const; - QIODevice *currentDestinationDevice() const; - QHttpRequestHeader currentRequest() const; - QHttpResponseHeader lastResponse() const; - bool hasPendingRequests() const; - void clearPendingRequests(); - - State state() const; - - Error error() const; - QString errorString() const; - -public Q_SLOTS: - void abort(); - -#ifndef QT_NO_OPENSSL - void ignoreSslErrors(); -#endif - -Q_SIGNALS: - void stateChanged(int); - void responseHeaderReceived(const QHttpResponseHeader &resp); - void readyRead(const QHttpResponseHeader &resp); - - // ### Qt 5: change to qint64 - void dataSendProgress(int, int); - void dataReadProgress(int, int); - - void requestStarted(int); - void requestFinished(int, bool); - void done(bool); - -#ifndef QT_NO_NETWORKPROXY - void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *); -#endif - void authenticationRequired(const QString &hostname, quint16 port, QAuthenticator *); - -#ifndef QT_NO_OPENSSL - void sslErrors(const QList &errors); -#endif - -private: - Q_DISABLE_COPY(QHttp) - Q_DECLARE_PRIVATE(QHttp) - - Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest()) - Q_PRIVATE_SLOT(d_func(), void _q_slotReadyRead()) - Q_PRIVATE_SLOT(d_func(), void _q_slotConnected()) - Q_PRIVATE_SLOT(d_func(), void _q_slotError(QAbstractSocket::SocketError)) - Q_PRIVATE_SLOT(d_func(), void _q_slotClosed()) - Q_PRIVATE_SLOT(d_func(), void _q_slotBytesWritten(qint64 numBytes)) -#ifndef QT_NO_OPENSSL - Q_PRIVATE_SLOT(d_func(), void _q_slotEncryptedBytesWritten(qint64 numBytes)) -#endif - Q_PRIVATE_SLOT(d_func(), void _q_slotDoFinished()) - Q_PRIVATE_SLOT(d_func(), void _q_slotSendRequest()) - Q_PRIVATE_SLOT(d_func(), void _q_continuePost()) - - friend class QHttpNormalRequest; - friend class QHttpSetHostRequest; - friend class QHttpSetSocketRequest; - friend class QHttpSetUserRequest; - friend class QHttpSetProxyRequest; - friend class QHttpCloseRequest; - friend class QHttpPGHRequest; -}; - -#endif // QT_NO_HTTP - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QHTTP_H diff --git a/src/network/access/qhttpheader.cpp b/src/network/access/qhttpheader.cpp new file mode 100644 index 0000000000..58c24cf3f5 --- /dev/null +++ b/src/network/access/qhttpheader.cpp @@ -0,0 +1,770 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//#define QHTTP_DEBUG + +#include +#include "qhttpheader_p.h" + +#ifndef QT_NO_HTTP +# include "private/qobject_p.h" +# include "qtcpsocket.h" +# include "qsslsocket.h" +# include "qtextstream.h" +# include "qmap.h" +# include "qlist.h" +# include "qstring.h" +# include "qstringlist.h" +# include "qbuffer.h" +# include "private/qringbuffer_p.h" +# include "qcoreevent.h" +# include "qurl.h" +# include "qnetworkproxy.h" +# include "qauthenticator.h" +# include "qauthenticator_p.h" +# include "qdebug.h" +# include "qtimer.h" +#endif + +#ifndef QT_NO_HTTP + +QT_BEGIN_NAMESPACE + +class QHttpHeaderPrivate +{ + Q_DECLARE_PUBLIC(QHttpHeader) +public: + inline virtual ~QHttpHeaderPrivate() {} + + QList > values; + bool valid; + QHttpHeader *q_ptr; +}; + +/**************************************************** + * + * QHttpHeader + * + ****************************************************/ + +/*! + \class QHttpHeader + \obsolete + \brief The QHttpHeader class contains header information for HTTP. + + \ingroup network + \inmodule QtNetwork + + In most cases you should use the more specialized derivatives of + this class, QHttpResponseHeader and QHttpRequestHeader, rather + than directly using QHttpHeader. + + QHttpHeader provides the HTTP header fields. A HTTP header field + consists of a name followed by a colon, a single space, and the + field value. (See RFC 1945.) Field names are case-insensitive. A + typical header field looks like this: + \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 0 + + In the API the header field name is called the "key" and the + content is called the "value". You can get and set a header + field's value by using its key with value() and setValue(), e.g. + \snippet doc/src/snippets/code/src_network_access_qhttp.cpp 1 + + Some fields are so common that getters and setters are provided + for them as a convenient alternative to using \l value() and + \l setValue(), e.g. contentLength() and contentType(), + setContentLength() and setContentType(). + + Each header key has a \e single value associated with it. If you + set the value for a key which already exists the previous value + will be discarded. + + \sa QHttpRequestHeader QHttpResponseHeader +*/ + +/*! + \fn int QHttpHeader::majorVersion() const + + Returns the major protocol-version of the HTTP header. +*/ + +/*! + \fn int QHttpHeader::minorVersion() const + + Returns the minor protocol-version of the HTTP header. +*/ + +/*! + Constructs an empty HTTP header. +*/ +QHttpHeader::QHttpHeader() + : d_ptr(new QHttpHeaderPrivate) +{ + Q_D(QHttpHeader); + d->q_ptr = this; + d->valid = true; +} + +/*! + Constructs a copy of \a header. +*/ +QHttpHeader::QHttpHeader(const QHttpHeader &header) + : d_ptr(new QHttpHeaderPrivate) +{ + Q_D(QHttpHeader); + d->q_ptr = this; + d->valid = header.d_func()->valid; + d->values = header.d_func()->values; +} + +/*! + Constructs a HTTP header for \a str. + + This constructor parses the string \a str for header fields and + adds this information. The \a str should consist of one or more + "\r\n" delimited lines; each of these lines should have the format + key, colon, space, value. +*/ +QHttpHeader::QHttpHeader(const QString &str) + : d_ptr(new QHttpHeaderPrivate) +{ + Q_D(QHttpHeader); + d->q_ptr = this; + d->valid = true; + parse(str); +} + +/*! \internal + */ +QHttpHeader::QHttpHeader(QHttpHeaderPrivate &dd, const QString &str) + : d_ptr(&dd) +{ + Q_D(QHttpHeader); + d->q_ptr = this; + d->valid = true; + if (!str.isEmpty()) + parse(str); +} + +/*! \internal + */ +QHttpHeader::QHttpHeader(QHttpHeaderPrivate &dd, const QHttpHeader &header) + : d_ptr(&dd) +{ + Q_D(QHttpHeader); + d->q_ptr = this; + d->valid = header.d_func()->valid; + d->values = header.d_func()->values; +} +/*! + Destructor. +*/ +QHttpHeader::~QHttpHeader() +{ +} + +/*! + Assigns \a h and returns a reference to this http header. +*/ +QHttpHeader &QHttpHeader::operator=(const QHttpHeader &h) +{ + Q_D(QHttpHeader); + d->values = h.d_func()->values; + d->valid = h.d_func()->valid; + return *this; +} + +/*! + Returns true if the HTTP header is valid; otherwise returns false. + + A QHttpHeader is invalid if it was created by parsing a malformed string. +*/ +bool QHttpHeader::isValid() const +{ + Q_D(const QHttpHeader); + return d->valid; +} + +/*! \internal + Parses the HTTP header string \a str for header fields and adds + the keys/values it finds. If the string is not parsed successfully + the QHttpHeader becomes \link isValid() invalid\endlink. + + Returns true if \a str was successfully parsed; otherwise returns false. + + \sa toString() +*/ +bool QHttpHeader::parse(const QString &str) +{ + Q_D(QHttpHeader); + QStringList lst; + int pos = str.indexOf(QLatin1Char('\n')); + if (pos > 0 && str.at(pos - 1) == QLatin1Char('\r')) + lst = str.trimmed().split(QLatin1String("\r\n")); + else + lst = str.trimmed().split(QLatin1String("\n")); + lst.removeAll(QString()); // No empties + + if (lst.isEmpty()) + return true; + + QStringList lines; + QStringList::Iterator it = lst.begin(); + for (; it != lst.end(); ++it) { + if (!(*it).isEmpty()) { + if ((*it)[0].isSpace()) { + if (!lines.isEmpty()) { + lines.last() += QLatin1Char(' '); + lines.last() += (*it).trimmed(); + } + } else { + lines.append((*it)); + } + } + } + + int number = 0; + it = lines.begin(); + for (; it != lines.end(); ++it) { + if (!parseLine(*it, number++)) { + d->valid = false; + return false; + } + } + return true; +} + +/*! \internal +*/ +void QHttpHeader::setValid(bool v) +{ + Q_D(QHttpHeader); + d->valid = v; +} + +/*! + Returns the first value for the entry with the given \a key. If no entry + has this \a key, an empty string is returned. + + \sa setValue() removeValue() hasKey() keys() +*/ +QString QHttpHeader::value(const QString &key) const +{ + Q_D(const QHttpHeader); + QString lowercaseKey = key.toLower(); + QList >::ConstIterator it = d->values.constBegin(); + while (it != d->values.constEnd()) { + if ((*it).first.toLower() == lowercaseKey) + return (*it).second; + ++it; + } + return QString(); +} + +/*! + Returns all the entries with the given \a key. If no entry + has this \a key, an empty string list is returned. +*/ +QStringList QHttpHeader::allValues(const QString &key) const +{ + Q_D(const QHttpHeader); + QString lowercaseKey = key.toLower(); + QStringList valueList; + QList >::ConstIterator it = d->values.constBegin(); + while (it != d->values.constEnd()) { + if ((*it).first.toLower() == lowercaseKey) + valueList.append((*it).second); + ++it; + } + return valueList; +} + +/*! + Returns a list of the keys in the HTTP header. + + \sa hasKey() +*/ +QStringList QHttpHeader::keys() const +{ + Q_D(const QHttpHeader); + QStringList keyList; + QSet seenKeys; + QList >::ConstIterator it = d->values.constBegin(); + while (it != d->values.constEnd()) { + const QString &key = (*it).first; + QString lowercaseKey = key.toLower(); + if (!seenKeys.contains(lowercaseKey)) { + keyList.append(key); + seenKeys.insert(lowercaseKey); + } + ++it; + } + return keyList; +} + +/*! + Returns true if the HTTP header has an entry with the given \a + key; otherwise returns false. + + \sa value() setValue() keys() +*/ +bool QHttpHeader::hasKey(const QString &key) const +{ + Q_D(const QHttpHeader); + QString lowercaseKey = key.toLower(); + QList >::ConstIterator it = d->values.constBegin(); + while (it != d->values.constEnd()) { + if ((*it).first.toLower() == lowercaseKey) + return true; + ++it; + } + return false; +} + +/*! + Sets the value of the entry with the \a key to \a value. + + If no entry with \a key exists, a new entry with the given \a key + and \a value is created. If an entry with the \a key already + exists, the first value is discarded and replaced with the given + \a value. + + \sa value() hasKey() removeValue() +*/ +void QHttpHeader::setValue(const QString &key, const QString &value) +{ + Q_D(QHttpHeader); + QString lowercaseKey = key.toLower(); + QList >::Iterator it = d->values.begin(); + while (it != d->values.end()) { + if ((*it).first.toLower() == lowercaseKey) { + (*it).second = value; + return; + } + ++it; + } + // not found so add + addValue(key, value); +} + +/*! + Sets the header entries to be the list of key value pairs in \a values. +*/ +void QHttpHeader::setValues(const QList > &values) +{ + Q_D(QHttpHeader); + d->values = values; +} + +/*! + Adds a new entry with the \a key and \a value. +*/ +void QHttpHeader::addValue(const QString &key, const QString &value) +{ + Q_D(QHttpHeader); + d->values.append(qMakePair(key, value)); +} + +/*! + Returns all the entries in the header. +*/ +QList > QHttpHeader::values() const +{ + Q_D(const QHttpHeader); + return d->values; +} + +/*! + Removes the entry with the key \a key from the HTTP header. + + \sa value() setValue() +*/ +void QHttpHeader::removeValue(const QString &key) +{ + Q_D(QHttpHeader); + QString lowercaseKey = key.toLower(); + QList >::Iterator it = d->values.begin(); + while (it != d->values.end()) { + if ((*it).first.toLower() == lowercaseKey) { + d->values.erase(it); + return; + } + ++it; + } +} + +/*! + Removes all the entries with the key \a key from the HTTP header. +*/ +void QHttpHeader::removeAllValues(const QString &key) +{ + Q_D(QHttpHeader); + QString lowercaseKey = key.toLower(); + QList >::Iterator it = d->values.begin(); + while (it != d->values.end()) { + if ((*it).first.toLower() == lowercaseKey) { + it = d->values.erase(it); + continue; + } + ++it; + } +} + +/*! \internal + Parses the single HTTP header line \a line which has the format + key, colon, space, value, and adds key/value to the headers. The + linenumber is \a number. Returns true if the line was successfully + parsed and the key/value added; otherwise returns false. + + \sa parse() +*/ +bool QHttpHeader::parseLine(const QString &line, int) +{ + int i = line.indexOf(QLatin1Char(':')); + if (i == -1) + return false; + + addValue(line.left(i).trimmed(), line.mid(i + 1).trimmed()); + + return true; +} + +/*! + Returns a string representation of the HTTP header. + + The string is suitable for use by the constructor that takes a + QString. It consists of lines with the format: key, colon, space, + value, "\r\n". +*/ +QString QHttpHeader::toString() const +{ + Q_D(const QHttpHeader); + if (!isValid()) + return QLatin1String(""); + + QString ret = QLatin1String(""); + + QList >::ConstIterator it = d->values.constBegin(); + while (it != d->values.constEnd()) { + ret += (*it).first + QLatin1String(": ") + (*it).second + QLatin1String("\r\n"); + ++it; + } + return ret; +} + +/*! + Returns true if the header has an entry for the special HTTP + header field \c content-length; otherwise returns false. + + \sa contentLength() setContentLength() +*/ +bool QHttpHeader::hasContentLength() const +{ + return hasKey(QLatin1String("content-length")); +} + +/*! + Returns the value of the special HTTP header field \c + content-length. + + \sa setContentLength() hasContentLength() +*/ +uint QHttpHeader::contentLength() const +{ + return value(QLatin1String("content-length")).toUInt(); +} + +/*! + Sets the value of the special HTTP header field \c content-length + to \a len. + + \sa contentLength() hasContentLength() +*/ +void QHttpHeader::setContentLength(int len) +{ + setValue(QLatin1String("content-length"), QString::number(len)); +} + +/*! + Returns true if the header has an entry for the special HTTP + header field \c content-type; otherwise returns false. + + \sa contentType() setContentType() +*/ +bool QHttpHeader::hasContentType() const +{ + return hasKey(QLatin1String("content-type")); +} + +/*! + Returns the value of the special HTTP header field \c content-type. + + \sa setContentType() hasContentType() +*/ +QString QHttpHeader::contentType() const +{ + QString type = value(QLatin1String("content-type")); + if (type.isEmpty()) + return QString(); + + int pos = type.indexOf(QLatin1Char(';')); + if (pos == -1) + return type; + + return type.left(pos).trimmed(); +} + +/*! + Sets the value of the special HTTP header field \c content-type to + \a type. + + \sa contentType() hasContentType() +*/ +void QHttpHeader::setContentType(const QString &type) +{ + setValue(QLatin1String("content-type"), type); +} + +class QHttpResponseHeaderPrivate : public QHttpHeaderPrivate +{ + Q_DECLARE_PUBLIC(QHttpResponseHeader) +public: + int statCode; + QString reasonPhr; + int majVer; + int minVer; +}; + +/**************************************************** + * + * QHttpResponseHeader + * + ****************************************************/ + +/*! + \class QHttpResponseHeader + \obsolete + \brief The QHttpResponseHeader class contains response header information for HTTP. + + \ingroup network + \inmodule QtNetwork + + HTTP responses have a status code that indicates the status of the + response. This code is a 3-digit integer result code (for details + see to RFC 1945). In addition to the status code, you can also + specify a human-readable text that describes the reason for the + code ("reason phrase"). This class allows you to get the status + code and the reason phrase. + + \sa QHttpRequestHeader, {HTTP Example} +*/ + +/*! + Constructs an empty HTTP response header. +*/ +QHttpResponseHeader::QHttpResponseHeader() + : QHttpHeader(*new QHttpResponseHeaderPrivate) +{ + setValid(false); +} + +/*! + Constructs a copy of \a header. +*/ +QHttpResponseHeader::QHttpResponseHeader(const QHttpResponseHeader &header) + : QHttpHeader(*new QHttpResponseHeaderPrivate, header) +{ + Q_D(QHttpResponseHeader); + d->statCode = header.d_func()->statCode; + d->reasonPhr = header.d_func()->reasonPhr; + d->majVer = header.d_func()->majVer; + d->minVer = header.d_func()->minVer; +} + +/*! + Copies the contents of \a header into this QHttpResponseHeader. +*/ +QHttpResponseHeader &QHttpResponseHeader::operator=(const QHttpResponseHeader &header) +{ + Q_D(QHttpResponseHeader); + QHttpHeader::operator=(header); + d->statCode = header.d_func()->statCode; + d->reasonPhr = header.d_func()->reasonPhr; + d->majVer = header.d_func()->majVer; + d->minVer = header.d_func()->minVer; + return *this; +} + +/*! + Constructs a HTTP response header from the string \a str. The + string is parsed and the information is set. The \a str should + consist of one or more "\r\n" delimited lines; the first line should be the + status-line (format: HTTP-version, space, status-code, space, + reason-phrase); each of remaining lines should have the format key, colon, + space, value. +*/ +QHttpResponseHeader::QHttpResponseHeader(const QString &str) + : QHttpHeader(*new QHttpResponseHeaderPrivate) +{ + parse(str); +} + +/*! + \since 4.1 + + Constructs a QHttpResponseHeader, setting the status code to \a code, the + reason phrase to \a text and the protocol-version to \a majorVer and \a + minorVer. + + \sa statusCode() reasonPhrase() majorVersion() minorVersion() +*/ +QHttpResponseHeader::QHttpResponseHeader(int code, const QString &text, int majorVer, int minorVer) + : QHttpHeader(*new QHttpResponseHeaderPrivate) +{ + setStatusLine(code, text, majorVer, minorVer); +} + +/*! + \since 4.1 + + Sets the status code to \a code, the reason phrase to \a text and + the protocol-version to \a majorVer and \a minorVer. + + \sa statusCode() reasonPhrase() majorVersion() minorVersion() +*/ +void QHttpResponseHeader::setStatusLine(int code, const QString &text, int majorVer, int minorVer) +{ + Q_D(QHttpResponseHeader); + setValid(true); + d->statCode = code; + d->reasonPhr = text; + d->majVer = majorVer; + d->minVer = minorVer; +} + +/*! + Returns the status code of the HTTP response header. + + \sa reasonPhrase() majorVersion() minorVersion() +*/ +int QHttpResponseHeader::statusCode() const +{ + Q_D(const QHttpResponseHeader); + return d->statCode; +} + +/*! + Returns the reason phrase of the HTTP response header. + + \sa statusCode() majorVersion() minorVersion() +*/ +QString QHttpResponseHeader::reasonPhrase() const +{ + Q_D(const QHttpResponseHeader); + return d->reasonPhr; +} + +/*! + Returns the major protocol-version of the HTTP response header. + + \sa minorVersion() statusCode() reasonPhrase() +*/ +int QHttpResponseHeader::majorVersion() const +{ + Q_D(const QHttpResponseHeader); + return d->majVer; +} + +/*! + Returns the minor protocol-version of the HTTP response header. + + \sa majorVersion() statusCode() reasonPhrase() +*/ +int QHttpResponseHeader::minorVersion() const +{ + Q_D(const QHttpResponseHeader); + return d->minVer; +} + +/*! \internal +*/ +bool QHttpResponseHeader::parseLine(const QString &line, int number) +{ + Q_D(QHttpResponseHeader); + if (number != 0) + return QHttpHeader::parseLine(line, number); + + QString l = line.simplified(); + if (l.length() < 10) + return false; + + if (l.left(5) == QLatin1String("HTTP/") && l[5].isDigit() && l[6] == QLatin1Char('.') && + l[7].isDigit() && l[8] == QLatin1Char(' ') && l[9].isDigit()) { + d->majVer = l[5].toLatin1() - '0'; + d->minVer = l[7].toLatin1() - '0'; + + int pos = l.indexOf(QLatin1Char(' '), 9); + if (pos != -1) { + d->reasonPhr = l.mid(pos + 1); + d->statCode = l.mid(9, pos - 9).toInt(); + } else { + d->statCode = l.mid(9).toInt(); + d->reasonPhr.clear(); + } + } else { + return false; + } + + return true; +} + +/*! \reimp +*/ +QString QHttpResponseHeader::toString() const +{ + Q_D(const QHttpResponseHeader); + QString ret(QLatin1String("HTTP/%1.%2 %3 %4\r\n%5\r\n")); + return ret.arg(d->majVer).arg(d->minVer).arg(d->statCode).arg(d->reasonPhr).arg(QHttpHeader::toString()); +} + +QT_END_NAMESPACE + +#endif diff --git a/src/network/access/qhttpheader_p.h b/src/network/access/qhttpheader_p.h new file mode 100644 index 0000000000..0d8b4fca13 --- /dev/null +++ b/src/network/access/qhttpheader_p.h @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QHTTP_H +#define QHTTP_H + +#include +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Network) + +#ifndef QT_NO_HTTP + +#if 0 +#pragma qt_class(QHttp) +#endif + +class QHttpHeaderPrivate; +class QHttpHeader +{ +public: + QHttpHeader(); + QHttpHeader(const QHttpHeader &header); + QHttpHeader(const QString &str); + virtual ~QHttpHeader(); + + QHttpHeader &operator=(const QHttpHeader &h); + + void setValue(const QString &key, const QString &value); + void setValues(const QList > &values); + void addValue(const QString &key, const QString &value); + QList > values() const; + bool hasKey(const QString &key) const; + QStringList keys() const; + QString value(const QString &key) const; + QStringList allValues(const QString &key) const; + void removeValue(const QString &key); + void removeAllValues(const QString &key); + + // ### Qt 5: change to qint64 + bool hasContentLength() const; + uint contentLength() const; + void setContentLength(int len); + + bool hasContentType() const; + QString contentType() const; + void setContentType(const QString &type); + + virtual QString toString() const; + bool isValid() const; + + virtual int majorVersion() const = 0; + virtual int minorVersion() const = 0; + +protected: + virtual bool parseLine(const QString &line, int number); + bool parse(const QString &str); + void setValid(bool); + + QHttpHeader(QHttpHeaderPrivate &dd, const QString &str = QString()); + QHttpHeader(QHttpHeaderPrivate &dd, const QHttpHeader &header); + QScopedPointer d_ptr; + +private: + Q_DECLARE_PRIVATE(QHttpHeader) +}; + +class QHttpResponseHeaderPrivate; +class QHttpResponseHeader : public QHttpHeader +{ +public: + QHttpResponseHeader(); + QHttpResponseHeader(const QHttpResponseHeader &header); + QHttpResponseHeader(const QString &str); + QHttpResponseHeader(int code, const QString &text = QString(), int majorVer = 1, int minorVer = 1); + QHttpResponseHeader &operator=(const QHttpResponseHeader &header); + + void setStatusLine(int code, const QString &text = QString(), int majorVer = 1, int minorVer = 1); + + int statusCode() const; + QString reasonPhrase() const; + + int majorVersion() const; + int minorVersion() const; + + QString toString() const; + +protected: + bool parseLine(const QString &line, int number); + +private: + Q_DECLARE_PRIVATE(QHttpResponseHeader) + friend class QHttpPrivate; +}; + +#endif // QT_NO_HTTP + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QHTTP_H diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index c9a41176d6..104a21f591 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -53,7 +53,6 @@ #include #include -#include #include #ifndef QT_NO_HTTP -- cgit v1.2.3