From d76bd0d7358b1c061f3c685a9256243eb9f11d7a Mon Sep 17 00:00:00 2001 From: Shane Kearns Date: Fri, 8 Jun 2012 12:01:27 +0100 Subject: QNetworkCookie: Use RFC6265 rules for parsing Set-Cookie The ';' separator takes priority even inside a quoted string. Quotation marks have no special meaning, they are not parsed and regenerated anymore. This means it is not possible to include the ';' character inside a cookie value. Other characters are returned transparently, including [",\] Task-number: QTBUG-15794 Task-number: QTBUG-26002 Task-number: QTBUG-11641 Change-Id: I4eefef5c6ac7753d5a21c226169e264578521fe9 Reviewed-by: Richard J. Moore --- src/network/access/qnetworkcookie.cpp | 103 ++++++---------------------------- 1 file changed, 16 insertions(+), 87 deletions(-) (limited to 'src/network/access/qnetworkcookie.cpp') diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp index 89e6f8a5ae..306195addb 100644 --- a/src/network/access/qnetworkcookie.cpp +++ b/src/network/access/qnetworkcookie.cpp @@ -379,85 +379,27 @@ static QPair nextField(const QByteArray &text, int &posi // (1) token // (2) token = token // (3) token = quoted-string - int i; const int length = text.length(); position = nextNonWhitespace(text, position); - // parse the first part, before the equal sign - for (i = position; i < length; ++i) { - register char c = text.at(i); - if (c == ';' || c == '=') - break; - } - - QByteArray first = text.mid(position, i - position).trimmed(); - position = i; - - if (first.isEmpty()) - return qMakePair(QByteArray(), QByteArray()); - if (i == length || text.at(i) != '=') - // no equal sign, we found format (1) - return qMakePair(first, QByteArray()); - - QByteArray second; - second.reserve(32); // arbitrary but works for most cases - - i = nextNonWhitespace(text, position + 1); - if (i < length && text.at(i) == '"') { - // a quote, we found format (3), where: - // quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) - // qdtext = > - // quoted-pair = "\" CHAR + int semiColonPosition = text.indexOf(';', position); + if (semiColonPosition < 0) + semiColonPosition = length; //no ';' means take everything to end of string - // If it is NAME=VALUE, retain the value as is - // refer to http://bugreports.qt-project.org/browse/QTBUG-17746 + int equalsPosition = text.indexOf('=', position); + if (equalsPosition < 0 || equalsPosition > semiColonPosition) { if (isNameValue) - second += '"'; - ++i; - while (i < length) { - register char c = text.at(i); - if (c == '"') { - // end of quoted text - if (isNameValue) - second += '"'; - break; - } else if (c == '\\') { - if (isNameValue) - second += '\\'; - ++i; - if (i >= length) - // broken line - return qMakePair(QByteArray(), QByteArray()); - c = text.at(i); - } - - second += c; - ++i; - } - - for ( ; i < length; ++i) { - register char c = text.at(i); - if (c == ';') - break; - } - position = i; - } else { - // no quote, we found format (2) - position = i; - for ( ; i < length; ++i) { - register char c = text.at(i); - // for name value pairs, we want to parse until reaching the next ';' - // and not break when reaching a space char - if (c == ';' || ((isNameValue && (c == '\n' || c == '\r')) || (!isNameValue && isLWS(c)))) - break; - } - - second = text.mid(position, i - position).trimmed(); - position = i; + return qMakePair(QByteArray(), QByteArray()); //'=' is required for name-value-pair (RFC6265 section 5.2, rule 2) + equalsPosition = semiColonPosition; //no '=' means there is an attribute-name but no attribute-value } - if (second.isNull()) - second.resize(0); // turns into empty-but-not-null + QByteArray first = text.mid(position, equalsPosition - position).trimmed(); + QByteArray second; + int secondLength = semiColonPosition - equalsPosition - 1; + if (secondLength > 0) + second = text.mid(equalsPosition + 1, secondLength).trimmed(); + + position = semiColonPosition; return qMakePair(first, second); } @@ -500,20 +442,7 @@ QByteArray QNetworkCookie::toRawForm(RawForm form) const result = d->name; result += '='; - if ((d->value.contains(';') || - d->value.contains('"')) && - (!d->value.startsWith('"') && - !d->value.endsWith('"'))) { - result += '"'; - - QByteArray value = d->value; - value.replace('"', "\\\""); - result += value; - - result += '"'; - } else { - result += d->value; - } + result += d->value; if (form == Full) { // same as above, but encoding everything back @@ -972,7 +901,7 @@ QList QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt // The first part is always the "NAME=VALUE" part QPair field = nextField(cookieString, position, true); - if (field.first.isEmpty() || field.second.isNull()) + if (field.first.isEmpty()) // parsing error break; cookie.setName(field.first); -- cgit v1.2.3