Skip to content

Commit

Permalink
Sanitize QAndroidTimeZonePrivate::init()
Browse files Browse the repository at this point in the history
It was setting the system zone ID if it somehow managed to find a
match for an empty zone name; that makes no sense.

A case-insensitive comparison seems reasonable for the "this isn't
just a default zone object, used because the name I asked for isn't
recognized" check.

It set m_id after it had checked everything, where it could just as
well have used m_id as the variable in which to record whether its
check has succeeded already.

It was using the name it was asked for, rather than the one this ended
up being mapped to, which is probably a better name to use for
it. (This should only differ in case.)

Split a long line.

Change-Id: I41a3b01ba99522ee68f3d7941c532019b9ebf946
Reviewed-by: Edward Welbourne <[email protected]>
  • Loading branch information
ediosyncratic committed Nov 27, 2019
1 parent 52affd3 commit c20c7ef
Showing 1 changed file with 19 additions and 17 deletions.
36 changes: 19 additions & 17 deletions src/corelib/time/qtimezoneprivate_android.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2014 Drew Parsons <[email protected]>
** Contact: https://www.qt.io/licensing/
**
Expand Down Expand Up @@ -76,32 +77,33 @@ QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate()
{
}


void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
{
QJNIObjectPrivate jo_ianaId = QJNIObjectPrivate::fromString( QString::fromUtf8(ianaId) );
androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( "java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;", static_cast<jstring>(jo_ianaId.object()) );
const QString iana = QString::fromUtf8(ianaId);
androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod(
"java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;",
static_cast<jstring>(QJNIObjectPrivate::fromString(iana).object()));

// The ID or display name of the zone we've got, if it looks like what we asked for:
const auto match = [iana](const QJNIObjectPrivate &jname) -> QByteArray {
const QString name = jname.toString();
if (iana.compare(name, Qt::CaseInsensitive))
return name.toUtf8();

return QByteArray();
};

// Painfully, JNI gives us back a default zone object if it doesn't
// recognize the name; so check for whether ianaId is a recognized name of
// the zone object we got and ignore the zone if not.
// Try checking ianaId against getID(), getDisplayName():
QJNIObjectPrivate jname = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;");
bool found = (jname.toString().toUtf8() == ianaId);
for (int style = 1; !found && style-- > 0;) {
for (int dst = 1; !found && dst-- > 0;) {
jname = androidTimeZone.callObjectMethod("getDisplayName", "(ZI;)Ljava/lang/String;",
bool(dst), style);
found = (jname.toString().toUtf8() == ianaId);
m_id = match(androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;"));
for (int style = 1; m_id.isEmpty() && style-- > 0;) {
for (int dst = 1; m_id.isEmpty() && dst-- > 0;) {
m_id = match(androidTimeZone.callObjectMethod(
"getDisplayName", "(ZI;)Ljava/lang/String;", bool(dst), style));
}
}

if (!found)
m_id.clear();
else if (ianaId.isEmpty())
m_id = systemTimeZoneId();
else
m_id = ianaId;
}

QAndroidTimeZonePrivate *QAndroidTimeZonePrivate::clone() const
Expand Down

0 comments on commit c20c7ef

Please sign in to comment.