diff options
Diffstat (limited to 'src/dbus/qdbusmisc.cpp')
-rw-r--r-- | src/dbus/qdbusmisc.cpp | 161 |
1 files changed, 78 insertions, 83 deletions
diff --git a/src/dbus/qdbusmisc.cpp b/src/dbus/qdbusmisc.cpp index 1925331eae..635258c86d 100644 --- a/src/dbus/qdbusmisc.cpp +++ b/src/dbus/qdbusmisc.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 <string.h> @@ -44,6 +8,7 @@ #include <QtCore/qlist.h> #include <QtCore/qmetaobject.h> #include <QtCore/qvariant.h> +#include <private/qurl_p.h> #include "qdbusutil_p.h" #include "qdbusconnection_p.h" @@ -55,6 +20,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + bool qDBusCheckAsyncTag(const char *tag) { static const char noReplyTag[] = "Q_NOREPLY"; @@ -78,37 +45,56 @@ QString qDBusInterfaceFromMetaObject(const QMetaObject *mo) int idx = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE); if (idx >= mo->classInfoOffset()) { - interface = QLatin1String(mo->classInfo(idx).value()); + interface = QLatin1StringView(mo->classInfo(idx).value()); } else { - interface = QLatin1String(mo->className()); - interface.replace(QLatin1String("::"), QLatin1String(".")); + interface = QLatin1StringView(mo->className()); + interface.replace("::"_L1, "."_L1); - if (interface.startsWith(QLatin1String("QDBus"))) { - interface.prepend(QLatin1String("org.qtproject.QtDBus.")); - } else if (interface.startsWith(QLatin1Char('Q')) && - interface.length() >= 2 && interface.at(1).isUpper()) { + if (interface.startsWith("QDBus"_L1)) { + interface.prepend("org.qtproject.QtDBus."_L1); + } else if (interface.startsWith(u'Q') && + interface.size() >= 2 && interface.at(1).isUpper()) { // assume it's Qt - interface.prepend(QLatin1String("org.qtproject.Qt.")); + interface.prepend("org.qtproject.Qt."_L1); } else if (!QCoreApplication::instance()|| QCoreApplication::instance()->applicationName().isEmpty()) { - interface.prepend(QLatin1String("local.")); - } else { - interface.prepend(QLatin1Char('.')).prepend(QCoreApplication::instance()->applicationName()); + interface.prepend("local."_L1); + } else { + QString domainName = QCoreApplication::instance()->applicationName(); const QString organizationDomain = QCoreApplication::instance()->organizationDomain(); - const auto domainName = QStringView{organizationDomain}.split(QLatin1Char('.'), Qt::SkipEmptyParts); - if (domainName.isEmpty()) { - interface.prepend(QLatin1String("local.")); - } else { - QString composedDomain; - // + 1 for additional dot, e.g. organizationDomain equals "example.com", - // then composedDomain will be equal "com.example." - composedDomain.reserve(organizationDomain.size() + 1); - for (auto it = domainName.rbegin(), end = domainName.rend(); it != end; ++it) - composedDomain += *it + QLatin1Char('.'); - - interface.prepend(composedDomain); + if (organizationDomain.isEmpty()) + domainName.append(".local"_L1); + else + domainName.append(u'.').append(organizationDomain); + + // Domain names used to produce interface names should be IDN-encoded. + QString encodedDomainName = qt_ACE_do(domainName, ToAceOnly, ForbidLeadingDot); + if (encodedDomainName.isEmpty()) { + interface.prepend("local."_L1); + return interface; + } + + // Hyphens are not allowed in interface names and should be replaced + // by underscores. + encodedDomainName.replace(u'-', u'_'); + + auto nameParts = QStringView{ encodedDomainName }.split(u'.', Qt::SkipEmptyParts); + + QString composedDomain; + // + 1 for additional dot, e.g. domainName equals "App.example.com", + // then composedDomain will be equal "com.example.App." + composedDomain.reserve(encodedDomainName.size() + nameParts.size() + 1); + for (auto it = nameParts.rbegin(), end = nameParts.rend(); it != end; ++it) { + // An interface name cannot start with a digit, and cannot + // contain digits immediately following a period. Prefix such + // digits with underscores. + if (it->first().isDigit()) + composedDomain += u'_'; + composedDomain += *it + u'.'; } - } + + interface.prepend(composedDomain); + } } return interface; @@ -135,56 +121,65 @@ bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name) // metaTypes.count() >= retval + 1 in all cases // // sig must be the normalised signature for the method -int qDBusParametersForMethod(const QMetaMethod &mm, QList<int> &metaTypes, QString &errorMsg) +int qDBusParametersForMethod(const QMetaMethod &mm, QList<QMetaType> &metaTypes, QString &errorMsg) { - return qDBusParametersForMethod(mm.parameterTypes(), metaTypes, errorMsg); + QList<QByteArray> parameterTypes; + parameterTypes.reserve(mm.parameterCount()); + + // Not using QMetaMethod::parameterTypes() since we call QMetaType::fromName below + // where we need any typedefs resolved already. + for (int i = 0; i < mm.parameterCount(); ++i) { + QByteArray typeName = mm.parameterMetaType(i).name(); + if (typeName.isEmpty()) + typeName = mm.parameterTypeName(i); + parameterTypes.append(typeName); + } + + return qDBusParametersForMethod(parameterTypes, metaTypes, errorMsg); } #endif // QT_BOOTSTRAPPED -int qDBusParametersForMethod(const QList<QByteArray> ¶meterTypes, QList<int> &metaTypes, +int qDBusParametersForMethod(const QList<QByteArray> ¶meterTypes, QList<QMetaType> &metaTypes, QString &errorMsg) { QDBusMetaTypeId::init(); metaTypes.clear(); - metaTypes.append(0); // return type + metaTypes.append(QMetaType()); // return type int inputCount = 0; bool seenMessage = false; - QList<QByteArray>::ConstIterator it = parameterTypes.constBegin(); - QList<QByteArray>::ConstIterator end = parameterTypes.constEnd(); - for ( ; it != end; ++it) { - QByteArray type = *it; + for (QByteArray type : parameterTypes) { if (type.endsWith('*')) { - errorMsg = QLatin1String("Pointers are not supported: ") + QLatin1String(type); + errorMsg = "Pointers are not supported: "_L1 + QLatin1StringView(type); return -1; } if (type.endsWith('&')) { QByteArray basictype = type; - basictype.truncate(type.length() - 1); + basictype.truncate(type.size() - 1); - int id = QMetaType::type(basictype); - if (id == 0) { - errorMsg = QLatin1String("Unregistered output type in parameter list: ") + QLatin1String(type); + QMetaType id = QMetaType::fromName(basictype); + if (!id.isValid()) { + errorMsg = "Unregistered output type in parameter list: "_L1 + QLatin1StringView(type); return -1; } else if (QDBusMetaType::typeToSignature(id) == nullptr) return -1; - metaTypes.append( id ); + metaTypes.append(id); seenMessage = true; // it cannot appear anymore anyways continue; } if (seenMessage) { // && !type.endsWith('&') - errorMsg = QLatin1String("Invalid method, non-output parameters after message or after output parameters: ") + QLatin1String(type); + errorMsg = "Invalid method, non-output parameters after message or after output parameters: "_L1 + QLatin1StringView(type); return -1; // not allowed } - if (type.startsWith("QList<")) - type = "QVector<" + type.mid(sizeof("QList<") - 1); + if (type.startsWith("QVector<")) + type = "QList<" + type.mid(sizeof("QVector<") - 1); - int id = QMetaType::type(type); + QMetaType id = QMetaType::fromName(type); #ifdef QT_BOOTSTRAPPED // in bootstrap mode QDBusMessage isn't included, thus we need to resolve it manually here if (type == "QDBusMessage") { @@ -192,15 +187,15 @@ int qDBusParametersForMethod(const QList<QByteArray> ¶meterTypes, QList<int> } #endif - if (id == QMetaType::UnknownType) { - errorMsg = QLatin1String("Unregistered input type in parameter list: ") + QLatin1String(type); + if (!id.isValid()) { + errorMsg = "Unregistered input type in parameter list: "_L1 + QLatin1StringView(type); return -1; } if (id == QDBusMetaTypeId::message()) seenMessage = true; else if (QDBusMetaType::typeToSignature(id) == nullptr) { - errorMsg = QLatin1String("Type not registered with QtDBus in parameter list: ") + QLatin1String(type); + errorMsg = "Type not registered with QtDBus in parameter list: "_L1 + QLatin1StringView(type); return -1; } |