From aa8fd6bc39f929a2bfad6bba4bf26e69624cd88a Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 13 Jan 2022 16:37:01 +0100 Subject: [PATCH] Convert date-time to UTC before claiming it's in GMT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QNetworkHeadersPrivate::toHttpDate() used a custom format to output a date-time; the format supplied GMT as suffix, but neglected to convert the date-time to UTC, so local-time was formatted as if it were UTC, regardless of its actual offset from it. Fixing this (by the obvious toUTC() call) broke formatting when the supplied header value was a QDate, since it's packaged as a QVariant and QVariant's conversion of QDate to QDateTime uses local time's (not UTC's) start of day. So fix headerValue() to separate QDate and QDateTime cases and use startOfDay(Qt::UTC) to get the right start of the day. Added tests for non-UTC date-times appearing correctly in HTTP headers. Fixes: QTBUG-80666 Pick-to: 6.3 6.2 6.2.3 5.15 Change-Id: I2792bce14a07be025cf551b0594630260c112269 Reviewed-by: MÃ¥rten Nordheim --- src/network/access/qnetworkrequest.cpp | 8 ++--- .../qnetworkrequest/tst_qnetworkrequest.cpp | 34 ++++++++++++++----- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 64d35aa2782..de40b2c088e 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtNetwork module of the Qt Toolkit. @@ -1071,9 +1071,10 @@ static QByteArray headerValue(QNetworkRequest::KnownHeaders header, const QVaria case QNetworkRequest::LastModifiedHeader: case QNetworkRequest::IfModifiedSinceHeader: switch (value.userType()) { + // Generate RFC 1123/822 dates: case QMetaType::QDate: + return QNetworkHeadersPrivate::toHttpDate(value.toDate().startOfDay(Qt::UTC)); case QMetaType::QDateTime: - // generate RFC 1123/822 dates: return QNetworkHeadersPrivate::toHttpDate(value.toDateTime()); default: @@ -1515,8 +1516,7 @@ QDateTime QNetworkHeadersPrivate::fromHttpDate(const QByteArray &value) QByteArray QNetworkHeadersPrivate::toHttpDate(const QDateTime &dt) { - return QLocale::c().toString(dt, u"ddd, dd MMM yyyy hh:mm:ss 'GMT'") - .toLatin1(); + return QLocale::c().toString(dt.toUTC(), u"ddd, dd MMM yyyy hh:mm:ss 'GMT'").toLatin1(); } QT_END_NAMESPACE diff --git a/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp b/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp index d90289ea08e..8cd37a21c72 100644 --- a/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp +++ b/tests/auto/network/access/qnetworkrequest/tst_qnetworkrequest.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -26,9 +26,11 @@ ** ****************************************************************************/ - #include #include +#if QT_CONFIG(timezone) +# include +#endif #include #include @@ -236,12 +238,28 @@ void tst_QNetworkRequest::setHeader_data() << QVariant(QDate(2007, 11, 01)) << true << "Last-Modified" << "Thu, 01 Nov 2007 00:00:00 GMT"; - QTest::newRow("Last-Modified-DateTime") << QNetworkRequest::LastModifiedHeader - << QVariant(QDateTime(QDate(2007, 11, 01), - QTime(18, 8, 30), - Qt::UTC)) - << true << "Last-Modified" - << "Thu, 01 Nov 2007 18:08:30 GMT"; + QTest::newRow("Last-Modified-DateTime-UTC") + << QNetworkRequest::LastModifiedHeader + << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30), Qt::UTC)) + << true << "Last-Modified" << "Thu, 01 Nov 2007 18:08:30 GMT"; + // QTBUG-80666: format dates correctly (as GMT) even if the date passed in isn't in UTC: + QTest::newRow("Last-Modified-DateTime-Local") + << QNetworkRequest::LastModifiedHeader + << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30), Qt::UTC).toLocalTime()) + << true << "Last-Modified" << "Thu, 01 Nov 2007 18:08:30 GMT"; + QTest::newRow("Last-Modified-DateTime-Offset") + << QNetworkRequest::LastModifiedHeader + << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30), Qt::UTC).toOffsetFromUtc(3600)) + << true << "Last-Modified" << "Thu, 01 Nov 2007 18:08:30 GMT"; +#if QT_CONFIG(timezone) + QTimeZone cet("Europe/Oslo"); + if (cet.isValid()) { + QTest::newRow("Last-Modified-DateTime-CET") + << QNetworkRequest::LastModifiedHeader + << QVariant(QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30), Qt::UTC).toTimeZone(cet)) + << true << "Last-Modified" << "Thu, 01 Nov 2007 18:08:30 GMT"; + } +#endif QTest::newRow("If-Modified-Since-Date") << QNetworkRequest::IfModifiedSinceHeader << QVariant(QDate(2017, 7, 01))