Recognize POSIX rules as valid timezone IDs for the TZ backend

The constructor, via findEntry(), does allow a POSIX rule as a valid
ID, so reflect that in the implementation of isTimeZoneIdAvailable(),
even though we can't sensibly enumerate all possible POSIX rules in
availableTimeZoneIds().

Change-Id: I7fd21d23ce8ce40c7f423b02e18d2e8df30fb952
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2023-03-15 17:19:14 +01:00
parent 0cefeb2593
commit 41c561ddde

View File

@ -521,7 +521,12 @@ PosixZone PosixZone::parse(const char *&pos, const char *end)
return {std::move(name), offset}; return {std::move(name), offset};
} }
static auto validatePosixRule(const QByteArray &posixRule) /* Parse and check a POSIX rule.
By default a simple zone abbreviation with no offset information is accepted.
Set \a requireOffset to \c true to require that there be offset data present.
*/
static auto validatePosixRule(const QByteArray &posixRule, bool requireOffset = false)
{ {
// Format is described here: // Format is described here:
// http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html // http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
@ -533,15 +538,19 @@ static auto validatePosixRule(const QByteArray &posixRule)
return fail; return fail;
const char *begin = zoneinfo.begin(); const char *begin = zoneinfo.begin();
{
// Updates begin to point after the name and offset it parses: // Updates begin to point after the name and offset it parses:
if (PosixZone::parse(begin, zoneinfo.end()).name.isEmpty()) const auto posix = PosixZone::parse(begin, zoneinfo.end());
return fail; if (posix.name.isEmpty())
return fail;
if (requireOffset && !posix.hasValidOffset())
return fail;
}
if (good.hasDst) { if (good.hasDst) {
if (begin >= zoneinfo.end()) if (begin >= zoneinfo.end())
return fail; return fail;
// Expect a second name and offset after the first: // Expect a second name (and optional offset) after the first:
if (PosixZone::parse(begin, zoneinfo.end()).name.isEmpty()) if (PosixZone::parse(begin, zoneinfo.end()).name.isEmpty())
return fail; return fail;
} }
@ -1189,7 +1198,11 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecs
bool QTzTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const bool QTzTimeZonePrivate::isTimeZoneIdAvailable(const QByteArray &ianaId) const
{ {
return tzZones->contains(ianaId); // Allow a POSIX rule as long as it has offset data. (This needs to reject a
// plain abbreviation, without offset, since claiming to support such zones
// would prevent the custom QTimeZone constructor from accepting such a
// name, as it doesn't want a custom zone to over-ride a "real" one.)
return tzZones->contains(ianaId) || validatePosixRule(ianaId, true).isValid;
} }
QList<QByteArray> QTzTimeZonePrivate::availableTimeZoneIds() const QList<QByteArray> QTzTimeZonePrivate::availableTimeZoneIds() const