Removing QHttpHeader and QHttpResponseHeader.
QAuthenticator used it for the convinience of QHttpSocketEngine only. QHttpSocketEngine has now been ported to use QHttpNetworkReply to parse HTTP responses. Change-Id: Idf6e70aa76613aad6e3d789d81ca1b4fd73575c2 Reviewed-by: Peter Hartmann <peter.hartmann@nokia.com>bb10
parent
658a239eb9
commit
8bbf1a46a5
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
HEADERS += \
|
||||
access/qftp_p.h \
|
||||
access/qhttpheader_p.h \
|
||||
access/qhttpnetworkheader_p.h \
|
||||
access/qhttpnetworkrequest_p.h \
|
||||
access/qhttpnetworkreply_p.h \
|
||||
|
|
@ -39,7 +38,6 @@ HEADERS += \
|
|||
|
||||
SOURCES += \
|
||||
access/qftp.cpp \
|
||||
access/qhttpheader.cpp \
|
||||
access/qhttpnetworkheader.cpp \
|
||||
access/qhttpnetworkrequest.cpp \
|
||||
access/qhttpnetworkreply.cpp \
|
||||
|
|
|
|||
|
|
@ -1,770 +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 <qplatformdefs.h>
|
||||
#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<QPair<QString, QString> > 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<QPair<QString, QString> >::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<QPair<QString, QString> >::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<QString> seenKeys;
|
||||
QList<QPair<QString, QString> >::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<QPair<QString, QString> >::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<QPair<QString, QString> >::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<QPair<QString, QString> > &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<QPair<QString, QString> > 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<QPair<QString, QString> >::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<QPair<QString, QString> >::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<QPair<QString, QString> >::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
|
||||
|
|
@ -1,147 +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 <QtCore/qobject.h>
|
||||
#include <QtCore/qstringlist.h>
|
||||
#include <QtCore/qmap.h>
|
||||
#include <QtCore/qpair.h>
|
||||
#include <QtCore/qscopedpointer.h>
|
||||
|
||||
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<QPair<QString, QString> > &values);
|
||||
void addValue(const QString &key, const QString &value);
|
||||
QList<QPair<QString, QString> > 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<QHttpHeaderPrivate> 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
|
||||
|
|
@ -156,6 +156,7 @@ Q_SIGNALS:
|
|||
void authenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *authenticator);
|
||||
private:
|
||||
Q_DECLARE_PRIVATE(QHttpNetworkReply)
|
||||
friend class QHttpSocketEngine;
|
||||
friend class QHttpNetworkConnection;
|
||||
friend class QHttpNetworkConnectionPrivate;
|
||||
friend class QHttpNetworkConnectionChannel;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@
|
|||
#include <qhash.h>
|
||||
#include <qbytearray.h>
|
||||
#include <qcryptographichash.h>
|
||||
#include <private/qhttpheader_p.h>
|
||||
#include <qiodevice.h>
|
||||
#include <qdatastream.h>
|
||||
#include <qendian.h>
|
||||
|
|
@ -339,21 +338,6 @@ QAuthenticatorPrivate::QAuthenticatorPrivate()
|
|||
nonceCount = 0;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_HTTP
|
||||
void QAuthenticatorPrivate::parseHttpResponse(const QHttpResponseHeader &header, bool isProxy)
|
||||
{
|
||||
const QList<QPair<QString, QString> > values = header.values();
|
||||
QList<QPair<QByteArray, QByteArray> > rawValues;
|
||||
|
||||
QList<QPair<QString, QString> >::const_iterator it, end;
|
||||
for (it = values.constBegin(), end = values.constEnd(); it != end; ++it)
|
||||
rawValues.append(qMakePair(it->first.toLatin1(), it->second.toUtf8()));
|
||||
|
||||
// continue in byte array form
|
||||
parseHttpResponse(rawValues, isProxy);
|
||||
}
|
||||
#endif
|
||||
|
||||
void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByteArray> > &values, bool isProxy)
|
||||
{
|
||||
const char *search = isProxy ? "proxy-authenticate" : "www-authenticate";
|
||||
|
|
|
|||
|
|
@ -103,9 +103,6 @@ public:
|
|||
QByteArray digestMd5Response(const QByteArray &challenge, const QByteArray &method, const QByteArray &path);
|
||||
static QHash<QByteArray, QByteArray> parseDigestAuthenticationChallenge(const QByteArray &challenge);
|
||||
|
||||
#ifndef QT_NO_HTTP
|
||||
void parseHttpResponse(const QHttpResponseHeader &, bool isProxy);
|
||||
#endif
|
||||
void parseHttpResponse(const QList<QPair<QByteArray, QByteArray> >&, bool isProxy);
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
#include "qtcpsocket.h"
|
||||
#include "qhostaddress.h"
|
||||
#include "qurl.h"
|
||||
#include "private/qhttpheader_p.h"
|
||||
#include "private/qhttpnetworkreply_p.h"
|
||||
#include "qelapsedtimer.h"
|
||||
#include "qnetworkinterface.h"
|
||||
|
||||
|
|
@ -72,6 +72,7 @@ bool QHttpSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstractSo
|
|||
setProtocol(protocol);
|
||||
setSocketType(type);
|
||||
d->socket = new QTcpSocket(this);
|
||||
d->reply = new QHttpNetworkReply(QUrl(), this);
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
d->socket->setProperty("_q_networkSession", property("_q_networkSession"));
|
||||
#endif
|
||||
|
|
@ -214,7 +215,7 @@ void QHttpSocketEngine::close()
|
|||
qint64 QHttpSocketEngine::bytesAvailable() const
|
||||
{
|
||||
Q_D(const QHttpSocketEngine);
|
||||
return d->readBuffer.size() + (d->socket ? d->socket->bytesAvailable() : 0);
|
||||
return d->socket ? d->socket->bytesAvailable() : 0;
|
||||
}
|
||||
|
||||
qint64 QHttpSocketEngine::read(char *data, qint64 maxlen)
|
||||
|
|
@ -567,20 +568,21 @@ void QHttpSocketEngine::slotSocketReadNotification()
|
|||
return;
|
||||
}
|
||||
|
||||
// Still in handshake mode. Wait until we've got a full response.
|
||||
bool done = false;
|
||||
do {
|
||||
d->readBuffer += d->socket->readLine();
|
||||
} while (!(done = d->readBuffer.endsWith("\r\n\r\n")) && d->socket->canReadLine());
|
||||
|
||||
if (!done) {
|
||||
// Wait for more.
|
||||
return;
|
||||
bool ok = true;
|
||||
if (d->reply->d_func()->state == QHttpNetworkReplyPrivate::NothingDoneState)
|
||||
d->reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState;
|
||||
if (d->reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingStatusState) {
|
||||
ok = d->reply->d_func()->readStatus(d->socket) != -1;
|
||||
if (ok && d->reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingStatusState)
|
||||
return; //Not done parsing headers yet, wait for more data
|
||||
}
|
||||
|
||||
if (!d->readBuffer.startsWith("HTTP/1.")) {
|
||||
if (ok && d->reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingHeaderState) {
|
||||
ok = d->reply->d_func()->readHeader(d->socket) != -1;
|
||||
if (ok && d->reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingHeaderState)
|
||||
return; //Not done parsing headers yet, wait for more data
|
||||
}
|
||||
if (!ok) {
|
||||
// protocol error, this isn't HTTP
|
||||
d->readBuffer.clear();
|
||||
d->socket->close();
|
||||
setState(QAbstractSocket::UnconnectedState);
|
||||
setError(QAbstractSocket::ProxyProtocolError, tr("Did not receive HTTP response from proxy"));
|
||||
|
|
@ -588,10 +590,7 @@ void QHttpSocketEngine::slotSocketReadNotification()
|
|||
return;
|
||||
}
|
||||
|
||||
QHttpResponseHeader responseHeader(QString::fromLatin1(d->readBuffer));
|
||||
d->readBuffer.clear(); // we parsed the proxy protocol response. from now on direct socket reading will be done
|
||||
|
||||
int statusCode = responseHeader.statusCode();
|
||||
int statusCode = d->reply->statusCode();
|
||||
QAuthenticatorPrivate *priv = 0;
|
||||
if (statusCode == 200) {
|
||||
d->state = Connected;
|
||||
|
|
@ -613,7 +612,7 @@ void QHttpSocketEngine::slotSocketReadNotification()
|
|||
d->authenticator.detach();
|
||||
priv = QAuthenticatorPrivate::getPrivate(d->authenticator);
|
||||
|
||||
priv->parseHttpResponse(responseHeader, true);
|
||||
priv->parseHttpResponse(d->reply->header(), true);
|
||||
|
||||
if (priv->phase == QAuthenticatorPrivate::Invalid) {
|
||||
// problem parsing the reply
|
||||
|
|
@ -625,21 +624,21 @@ void QHttpSocketEngine::slotSocketReadNotification()
|
|||
}
|
||||
|
||||
bool willClose;
|
||||
QString proxyConnectionHeader = responseHeader.value(QLatin1String("Proxy-Connection"));
|
||||
QByteArray proxyConnectionHeader = d->reply->headerField("Proxy-Connection");
|
||||
// Although most proxies use the unofficial Proxy-Connection header, the Connection header
|
||||
// from http spec is also allowed.
|
||||
if (proxyConnectionHeader.isEmpty())
|
||||
proxyConnectionHeader = responseHeader.value(QLatin1String("Connection"));
|
||||
proxyConnectionHeader = d->reply->headerField("Connection");
|
||||
proxyConnectionHeader = proxyConnectionHeader.toLower();
|
||||
if (proxyConnectionHeader == QLatin1String("close")) {
|
||||
if (proxyConnectionHeader == "close") {
|
||||
willClose = true;
|
||||
} else if (proxyConnectionHeader == QLatin1String("keep-alive")) {
|
||||
} else if (proxyConnectionHeader == "keep-alive") {
|
||||
willClose = false;
|
||||
} else {
|
||||
// no Proxy-Connection header, so use the default
|
||||
// HTTP 1.1's default behaviour is to keep persistent connections
|
||||
// HTTP 1.0 or earlier, so we expect the server to close
|
||||
willClose = (responseHeader.majorVersion() * 0x100 + responseHeader.minorVersion()) <= 0x0100;
|
||||
willClose = (d->reply->majorVersion() * 0x100 + d->reply->minorVersion()) <= 0x0100;
|
||||
}
|
||||
|
||||
if (willClose) {
|
||||
|
|
@ -647,6 +646,9 @@ void QHttpSocketEngine::slotSocketReadNotification()
|
|||
// especially since the signal below may trigger a new event loop
|
||||
d->socket->disconnectFromHost();
|
||||
d->socket->readAll();
|
||||
//We're done with the reply and need to reset it for the next connection
|
||||
delete d->reply;
|
||||
d->reply = new QHttpNetworkReply;
|
||||
}
|
||||
|
||||
if (priv->phase == QAuthenticatorPrivate::Done)
|
||||
|
|
@ -662,7 +664,7 @@ void QHttpSocketEngine::slotSocketReadNotification()
|
|||
d->socket->connectToHost(d->proxy.hostName(), d->proxy.port());
|
||||
} else {
|
||||
bool ok;
|
||||
int contentLength = responseHeader.value(QLatin1String("Content-Length")).toInt(&ok);
|
||||
int contentLength = d->reply->headerField("Content-Length").toInt(&ok);
|
||||
if (ok && contentLength > 0) {
|
||||
d->state = ReadResponseContent;
|
||||
d->pendingResponseData = contentLength;
|
||||
|
|
@ -708,7 +710,6 @@ void QHttpSocketEngine::slotSocketBytesWritten()
|
|||
void QHttpSocketEngine::slotSocketError(QAbstractSocket::SocketError error)
|
||||
{
|
||||
Q_D(QHttpSocketEngine);
|
||||
d->readBuffer.clear();
|
||||
|
||||
if (d->state != Connected) {
|
||||
// we are in proxy handshaking stages
|
||||
|
|
@ -811,6 +812,7 @@ QHttpSocketEnginePrivate::QHttpSocketEnginePrivate()
|
|||
, pendingResponseData(0)
|
||||
{
|
||||
socket = 0;
|
||||
reply = 0;
|
||||
state = QHttpSocketEngine::None;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ QT_BEGIN_NAMESPACE
|
|||
#if !defined(QT_NO_NETWORKPROXY) && !defined(QT_NO_HTTP)
|
||||
|
||||
class QTcpSocket;
|
||||
class QHttpNetworkReply;
|
||||
class QHttpSocketEnginePrivate;
|
||||
|
||||
class Q_AUTOTEST_EXPORT QHttpSocketEngine : public QAbstractSocketEngine
|
||||
|
|
@ -171,7 +172,7 @@ public:
|
|||
QNetworkProxy proxy;
|
||||
QString peerName;
|
||||
QTcpSocket *socket;
|
||||
QByteArray readBuffer; // only used for parsing the proxy response
|
||||
QHttpNetworkReply *reply; // only used for parsing the proxy response
|
||||
QHttpSocketEngine::HttpState state;
|
||||
QAuthenticator authenticator;
|
||||
bool readNotificationEnabled;
|
||||
|
|
|
|||
|
|
@ -397,8 +397,6 @@ QT_CLASS_LIB(QXmlStreamStringRef, QtXml, qxmlstream.h)
|
|||
QT_CLASS_LIB(QXmlStreamWriter, QtXml, qxmlstream.h)
|
||||
QT_CLASS_LIB(QNetworkCacheMetaData, QtNetwork, qabstractnetworkcache.h)
|
||||
QT_CLASS_LIB(QAbstractNetworkCache, QtNetwork, qabstractnetworkcache.h)
|
||||
QT_CLASS_LIB(QHttpHeader, QtNetwork, qhttpheader_p.h)
|
||||
QT_CLASS_LIB(QHttpResponseHeader, QtNetwork, qhttpheader_p.h)
|
||||
QT_CLASS_LIB(QNetworkAccessManager, QtNetwork, qnetworkaccessmanager.h)
|
||||
QT_CLASS_LIB(QNetworkCookie, QtNetwork, qnetworkcookie.h)
|
||||
QT_CLASS_LIB(QNetworkCookieJar, QtNetwork, qnetworkcookiejar.h)
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ void tst_QHttpSocketEngine::errorTest_data()
|
|||
|
||||
QTest::newRow("garbage2") << QString() << 0 << QString()
|
||||
<< "This is not HTTP"
|
||||
<< int(QAbstractSocket::ProxyConnectionClosedError);
|
||||
<< int(QAbstractSocket::ProxyProtocolError);
|
||||
|
||||
QTest::newRow("garbage3") << QString() << 0 << QString()
|
||||
<< ""
|
||||
|
|
|
|||
Loading…
Reference in New Issue