diff options
Diffstat (limited to 'src/dbus/qdbusutil.cpp')
-rw-r--r-- | src/dbus/qdbusutil.cpp | 214 |
1 files changed, 84 insertions, 130 deletions
diff --git a/src/dbus/qdbusutil.cpp b/src/dbus/qdbusutil.cpp index 8322ff02c4..78338aa054 100644 --- a/src/dbus/qdbusutil.cpp +++ b/src/dbus/qdbusutil.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtDBus module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qdbusutil_p.h" @@ -43,6 +7,7 @@ #include <QtCore/qlist.h> #include <QtCore/qstringlist.h> +#include <private/qtools_p.h> #include "qdbusargument.h" #include "qdbusunixfiledescriptor.h" @@ -51,28 +16,25 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; +using namespace QtMiscUtils; + static inline bool isValidCharacterNoDash(QChar c) { ushort u = c.unicode(); - return (u >= 'a' && u <= 'z') - || (u >= 'A' && u <= 'Z') - || (u >= '0' && u <= '9') - || (u == '_'); + return isAsciiLetterOrNumber(u) || (u == '_'); } static inline bool isValidCharacter(QChar c) { ushort u = c.unicode(); - return (u >= 'a' && u <= 'z') - || (u >= 'A' && u <= 'Z') - || (u >= '0' && u <= '9') + return isAsciiLetterOrNumber(u) || (u == '_') || (u == '-'); } static inline bool isValidNumber(QChar c) { - ushort u = c.unicode(); - return (u >= '0' && u <= '9'); + return (isAsciiDigit(c.toLatin1())); } #ifndef QT_BOOTSTRAPPED @@ -83,34 +45,34 @@ static bool variantToString(const QVariant &arg, QString &out) int argType = arg.metaType().id(); if (argType == QMetaType::QStringList) { - out += QLatin1Char('{'); + out += u'{'; const QStringList list = arg.toStringList(); for (const QString &item : list) - out += QLatin1Char('\"') + item + QLatin1String("\", "); + out += u'\"' + item + "\", "_L1; if (!list.isEmpty()) out.chop(2); - out += QLatin1Char('}'); + out += u'}'; } else if (argType == QMetaType::QByteArray) { - out += QLatin1Char('{'); + out += u'{'; QByteArray list = arg.toByteArray(); - for (int i = 0; i < list.count(); ++i) { + for (int i = 0; i < list.size(); ++i) { out += QString::number(list.at(i)); - out += QLatin1String(", "); + out += ", "_L1; } if (!list.isEmpty()) out.chop(2); - out += QLatin1Char('}'); + out += u'}'; } else if (argType == QMetaType::QVariantList) { - out += QLatin1Char('{'); + out += u'{'; const QList<QVariant> list = arg.toList(); for (const QVariant &item : list) { if (!variantToString(item, out)) return false; - out += QLatin1String(", "); + out += ", "_L1; } if (!list.isEmpty()) out.chop(2); - out += QLatin1Char('}'); + out += u'}'; } else if (argType == QMetaType::Char || argType == QMetaType::Short || argType == QMetaType::Int || argType == QMetaType::Long || argType == QMetaType::LongLong) { out += QString::number(arg.toLongLong()); @@ -120,40 +82,40 @@ static bool variantToString(const QVariant &arg, QString &out) } else if (argType == QMetaType::Double) { out += QString::number(arg.toDouble()); } else if (argType == QMetaType::Bool) { - out += QLatin1String(arg.toBool() ? "true" : "false"); + out += arg.toBool() ? "true"_L1 : "false"_L1; } else if (argType == qMetaTypeId<QDBusArgument>()) { argToString(qvariant_cast<QDBusArgument>(arg), out); } else if (argType == qMetaTypeId<QDBusObjectPath>()) { const QString path = qvariant_cast<QDBusObjectPath>(arg).path(); - out += QLatin1String("[ObjectPath: "); + out += "[ObjectPath: "_L1; out += path; - out += QLatin1Char(']'); + out += u']'; } else if (argType == qMetaTypeId<QDBusSignature>()) { - out += QLatin1String("[Signature: ") + qvariant_cast<QDBusSignature>(arg).signature(); - out += QLatin1Char(']'); + out += "[Signature: "_L1 + qvariant_cast<QDBusSignature>(arg).signature(); + out += u']'; } else if (argType == qMetaTypeId<QDBusUnixFileDescriptor>()) { - out += QLatin1String("[Unix FD: "); - out += QLatin1String(qvariant_cast<QDBusUnixFileDescriptor>(arg).isValid() ? "valid" : "not valid"); - out += QLatin1Char(']'); + out += "[Unix FD: "_L1; + out += qvariant_cast<QDBusUnixFileDescriptor>(arg).isValid() ? "valid"_L1 : "not valid"_L1; + out += u']'; } else if (argType == qMetaTypeId<QDBusVariant>()) { const QVariant v = qvariant_cast<QDBusVariant>(arg).variant(); - out += QLatin1String("[Variant"); + out += "[Variant"_L1; QMetaType vUserType = v.metaType(); if (vUserType != QMetaType::fromType<QDBusVariant>() && vUserType != QMetaType::fromType<QDBusSignature>() && vUserType != QMetaType::fromType<QDBusObjectPath>() && vUserType != QMetaType::fromType<QDBusArgument>()) - out += QLatin1Char('(') + QLatin1String(v.typeName()) + QLatin1Char(')'); - out += QLatin1String(": "); + out += u'(' + QLatin1StringView(v.typeName()) + u')'; + out += ": "_L1; if (!variantToString(v, out)) return false; - out += QLatin1Char(']'); + out += u']'; } else if (arg.canConvert<QString>()) { - out += QLatin1Char('\"') + arg.toString() + QLatin1Char('\"'); + out += u'\"' + arg.toString() + u'\"'; } else { - out += QLatin1Char('['); - out += QLatin1String(arg.typeName()); - out += QLatin1Char(']'); + out += u'['; + out += QLatin1StringView(arg.typeName()); + out += u']'; } return true; @@ -167,7 +129,7 @@ bool argToString(const QDBusArgument &busArg, QString &out) if (elementType != QDBusArgument::BasicType && elementType != QDBusArgument::VariantType && elementType != QDBusArgument::MapEntryType) - out += QLatin1String("[Argument: ") + busSig + QLatin1Char(' '); + out += "[Argument: "_L1 + busSig + u' '; switch (elementType) { case QDBusArgument::BasicType: @@ -181,33 +143,33 @@ bool argToString(const QDBusArgument &busArg, QString &out) break; case QDBusArgument::ArrayType: busArg.beginArray(); - out += QLatin1Char('{'); + out += u'{'; doIterate = true; break; case QDBusArgument::MapType: busArg.beginMap(); - out += QLatin1Char('{'); + out += u'{'; doIterate = true; break; case QDBusArgument::MapEntryType: busArg.beginMapEntry(); if (!variantToString(busArg.asVariant(), out)) return false; - out += QLatin1String(" = "); + out += " = "_L1; if (!argToString(busArg, out)) return false; busArg.endMapEntry(); break; case QDBusArgument::UnknownType: default: - out += QLatin1String("<ERROR - Unknown Type>"); + out += "<ERROR - Unknown Type>"_L1; return false; } if (doIterate && !busArg.atEnd()) { while (!busArg.atEnd()) { if (!argToString(busArg, out)) return false; - out += QLatin1String(", "); + out += ", "_L1; } out.chop(2); } @@ -222,18 +184,18 @@ bool argToString(const QDBusArgument &busArg, QString &out) busArg.endStructure(); break; case QDBusArgument::ArrayType: - out += QLatin1Char('}'); + out += u'}'; busArg.endArray(); break; case QDBusArgument::MapType: - out += QLatin1Char('}'); + out += u'}'; busArg.endMap(); break; } if (elementType != QDBusArgument::BasicType && elementType != QDBusArgument::VariantType && elementType != QDBusArgument::MapEntryType) - out += QLatin1Char(']'); + out += u']'; return true; } @@ -244,6 +206,21 @@ static const char oneLetterTypes[] = "vsogybnqiuxtdh"; static const char basicTypes[] = "sogybnqiuxtdh"; static const char fixedTypes[] = "ybnqiuxtdh"; +/* + D-Bus signature grammar (in ABNF), as of 0.42 (2023-08-21): + https://dbus.freedesktop.org/doc/dbus-specification.html#type-system + + <signature> = *<single-complete-type> + <single-complete-type> = <basic-type> / <variant> / <struct> / <array> + <fixed-type> = "y" / "b" / "n" / "q" / "i" / "u" / "x" / "t" / "d" / "h" + <variable-length-type> = "s" / "o" / "g" + <basic-type> = <variable-length-type> / <fixed-type> + <variant> = "v" + <struct> = "(" 1*<single-complete-type> ")" + <array> = "a" ( <single-complete-type> / <dict-entry> ) + <dict-entry> = "{" <basic-type> <single-complete-type> "}" +*/ + static bool isBasicType(int c) { return c != DBUS_TYPE_INVALID && strchr(basicTypes, c) != nullptr; @@ -340,7 +317,7 @@ namespace QDBusUtil return false; // can't be valid if it's empty const QChar *c = part.data(); - for (int i = 0; i < part.length(); ++i) + for (int i = 0; i < part.size(); ++i) if (!isValidCharacterNoDash(c[i])) return false; @@ -348,13 +325,6 @@ namespace QDBusUtil } /*! - \internal - \fn bool isValidPartOfObjectPath(const QString &part) - - \overload - */ - - /*! \fn bool isValidInterfaceName(const QString &ifaceName) Returns \c true if this is \a ifaceName is a valid interface name. @@ -369,11 +339,11 @@ namespace QDBusUtil */ bool isValidInterfaceName(const QString& ifaceName) { - if (ifaceName.isEmpty() || ifaceName.length() > DBUS_MAXIMUM_NAME_LENGTH) + if (ifaceName.isEmpty() || ifaceName.size() > DBUS_MAXIMUM_NAME_LENGTH) return false; - const auto parts = QStringView{ifaceName}.split(QLatin1Char('.')); - if (parts.count() < 2) + const auto parts = QStringView{ifaceName}.split(u'.'); + if (parts.size() < 2) return false; // at least two parts for (auto part : parts) @@ -392,12 +362,12 @@ namespace QDBusUtil */ bool isValidUniqueConnectionName(QStringView connName) { - if (connName.isEmpty() || connName.length() > DBUS_MAXIMUM_NAME_LENGTH || - !connName.startsWith(QLatin1Char(':'))) + if (connName.isEmpty() || connName.size() > DBUS_MAXIMUM_NAME_LENGTH || + !connName.startsWith(u':')) return false; - const auto parts = connName.mid(1).split(QLatin1Char('.')); - if (parts.count() < 1) + const auto parts = connName.mid(1).split(u'.'); + if (parts.size() < 1) return false; for (QStringView part : parts) { @@ -405,7 +375,7 @@ namespace QDBusUtil return false; const QChar* c = part.data(); - for (int j = 0; j < part.length(); ++j) + for (int j = 0; j < part.size(); ++j) if (!isValidCharacter(c[j])) return false; } @@ -414,12 +384,6 @@ namespace QDBusUtil } /*! - \fn bool isValidUniqueConnectionName(const QString &connName) - - \overload - */ - - /*! \fn bool isValidBusName(const QString &busName) Returns \c true if \a busName is a valid bus name. @@ -436,16 +400,13 @@ namespace QDBusUtil */ bool isValidBusName(const QString &busName) { - if (busName.isEmpty() || busName.length() > DBUS_MAXIMUM_NAME_LENGTH) + if (busName.isEmpty() || busName.size() > DBUS_MAXIMUM_NAME_LENGTH) return false; - if (busName.startsWith(QLatin1Char(':'))) + if (busName.startsWith(u':')) return isValidUniqueConnectionName(busName); - const auto parts = QStringView{busName}.split(QLatin1Char('.')); - if (parts.count() < 1) - return false; - + const auto parts = QStringView{busName}.split(u'.'); for (QStringView part : parts) { if (part.isEmpty()) return false; @@ -453,7 +414,7 @@ namespace QDBusUtil const QChar *c = part.data(); if (isValidNumber(c[0])) return false; - for (int j = 0; j < part.length(); ++j) + for (int j = 0; j < part.size(); ++j) if (!isValidCharacter(c[j])) return false; } @@ -469,25 +430,19 @@ namespace QDBusUtil */ bool isValidMemberName(QStringView memberName) { - if (memberName.isEmpty() || memberName.length() > DBUS_MAXIMUM_NAME_LENGTH) + if (memberName.isEmpty() || memberName.size() > DBUS_MAXIMUM_NAME_LENGTH) return false; const QChar* c = memberName.data(); if (isValidNumber(c[0])) return false; - for (int j = 0; j < memberName.length(); ++j) + for (int j = 0; j < memberName.size(); ++j) if (!isValidCharacterNoDash(c[j])) return false; return true; } /*! - \fn bool isValidMemberName(const QString &memberName) - - \overload - */ - - /*! \fn bool isValidErrorName(const QString &errorName) Returns \c true if \a errorName is a valid error name. Valid error names are valid interface names and vice-versa, so this function is actually an alias for isValidInterfaceName. @@ -505,22 +460,21 @@ namespace QDBusUtil \list \li start with the slash character ("/") \li do not end in a slash, unless the path is just the initial slash - \li do not contain any two slashes in sequence - \li contain slash-separated parts, each of which is composed of ASCII letters, digits and - underscores ("_") + \li contain slash-separated parts, each of which is not empty, and composed + only of ASCII letters, digits and underscores ("_"). \endlist */ bool isValidObjectPath(const QString &path) { - if (path == QLatin1String("/")) + if (path == "/"_L1) return true; - if (!path.startsWith(QLatin1Char('/')) || path.indexOf(QLatin1String("//")) != -1 || - path.endsWith(QLatin1Char('/'))) + if (!path.startsWith(u'/') || path.indexOf("//"_L1) != -1 || + path.endsWith(u'/')) return false; // it starts with /, so we skip the empty first part - const auto parts = QStringView{path}.mid(1).split(QLatin1Char('/')); + const auto parts = QStringView{path}.mid(1).split(u'/'); for (QStringView part : parts) if (!isValidPartOfObjectPath(part)) return false; @@ -558,14 +512,14 @@ namespace QDBusUtil bool isValidSignature(const QString &signature) { QByteArray ba = signature.toLatin1(); - const char *data = ba.constData(); - while (true) { + const char *data = ba.constBegin(); + const char *end = ba.constEnd(); + while (data != end) { data = validateSingleType(data); if (!data) return false; - if (*data == '\0') - return true; } + return true; } /*! |