Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qdbusmisc.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <string.h>
5
6#ifndef QT_BOOTSTRAPPED
7#include <QtCore/qcoreapplication.h>
8#include <QtCore/qlist.h>
9#include <QtCore/qmetaobject.h>
10#include <QtCore/qvariant.h>
11#include <private/qurl_p.h>
12
13#include "qdbusutil_p.h"
14#include "qdbusconnection_p.h"
15#include "qdbusabstractadaptor_p.h" // for QCLASSINFO_DBUS_*
16#endif
17#include "qdbusmetatype_p.h"
18
19#ifndef QT_NO_DBUS
20
22
23using namespace Qt::StringLiterals;
24
25bool qDBusCheckAsyncTag(const char *tag)
26{
27 static const char noReplyTag[] = "Q_NOREPLY";
28 if (!tag || !*tag)
29 return false;
30
31 const char *p = strstr(tag, noReplyTag);
32 if (p != nullptr &&
33 (p == tag || *(p-1) == ' ') &&
34 (p[sizeof noReplyTag - 1] == '\0' || p[sizeof noReplyTag - 1] == ' '))
35 return true;
36
37 return false;
38}
39
40#ifndef QT_BOOTSTRAPPED
41
43{
45
46 int idx = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE);
47 if (idx >= mo->classInfoOffset()) {
48 interface = QLatin1StringView(mo->classInfo(idx).value());
49 } else {
50 interface = QLatin1StringView(mo->className());
51 interface.replace("::"_L1, "."_L1);
52
53 if (interface.startsWith("QDBus"_L1)) {
54 interface.prepend("org.qtproject.QtDBus."_L1);
55 } else if (interface.startsWith(u'Q') &&
56 interface.size() >= 2 && interface.at(1).isUpper()) {
57 // assume it's Qt
58 interface.prepend("org.qtproject.Qt."_L1);
59 } else if (!QCoreApplication::instance()||
60 QCoreApplication::instance()->applicationName().isEmpty()) {
61 interface.prepend("local."_L1);
62 } else {
64 const QString organizationDomain = QCoreApplication::instance()->organizationDomain();
65 if (organizationDomain.isEmpty())
66 domainName.append(".local"_L1);
67 else
68 domainName.append(u'.').append(organizationDomain);
69
70 // Domain names used to produce interface names should be IDN-encoded.
71 QString encodedDomainName = qt_ACE_do(domainName, ToAceOnly, ForbidLeadingDot);
72 if (encodedDomainName.isEmpty()) {
73 interface.prepend("local."_L1);
74 return interface;
75 }
76
77 // Hyphens are not allowed in interface names and should be replaced
78 // by underscores.
79 encodedDomainName.replace(u'-', u'_');
80
81 auto nameParts = QStringView{ encodedDomainName }.split(u'.', Qt::SkipEmptyParts);
82
83 QString composedDomain;
84 // + 1 for additional dot, e.g. domainName equals "App.example.com",
85 // then composedDomain will be equal "com.example.App."
86 composedDomain.reserve(encodedDomainName.size() + nameParts.size() + 1);
87 for (auto it = nameParts.rbegin(), end = nameParts.rend(); it != end; ++it) {
88 // An interface name cannot start with a digit, and cannot
89 // contain digits immediately following a period. Prefix such
90 // digits with underscores.
91 if (it->first().isDigit())
92 composedDomain += u'_';
93 composedDomain += *it + u'.';
94 }
95
96 interface.prepend(composedDomain);
97 }
98 }
99
100 return interface;
101}
102
103bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name)
104{
105 const QMetaObject *mo = obj->metaObject();
106 for ( ; mo != &QObject::staticMetaObject; mo = mo->superClass())
107 if (interface_name == qDBusInterfaceFromMetaObject(mo))
108 return true;
109 return false;
110}
111
112// calculates the metatypes for the method
113// the slot must have the parameters in the following form:
114// - zero or more value or const-ref parameters of any kind
115// - zero or one const ref of QDBusMessage
116// - zero or more non-const ref parameters
117// No parameter may be a template.
118// this function returns -1 if the parameters don't match the above form
119// this function returns the number of *input* parameters, including the QDBusMessage one if any
120// this function does not check the return type, so metaTypes[0] is always 0 and always present
121// metaTypes.count() >= retval + 1 in all cases
122//
123// sig must be the normalised signature for the method
125{
126 return qDBusParametersForMethod(mm.parameterTypes(), metaTypes, errorMsg);
127}
128
129#endif // QT_BOOTSTRAPPED
130
131int qDBusParametersForMethod(const QList<QByteArray> &parameterTypes, QList<QMetaType> &metaTypes,
132 QString &errorMsg)
133{
135 metaTypes.clear();
136
137 metaTypes.append(QMetaType()); // return type
138 int inputCount = 0;
139 bool seenMessage = false;
140 for (QByteArray type : parameterTypes) {
141 if (type.endsWith('*')) {
142 errorMsg = "Pointers are not supported: "_L1 + QLatin1StringView(type);
143 return -1;
144 }
145
146 if (type.endsWith('&')) {
147 QByteArray basictype = type;
148 basictype.truncate(type.size() - 1);
149
150 QMetaType id = QMetaType::fromName(basictype);
151 if (!id.isValid()) {
152 errorMsg = "Unregistered output type in parameter list: "_L1 + QLatin1StringView(type);
153 return -1;
154 } else if (QDBusMetaType::typeToSignature(id) == nullptr)
155 return -1;
156
157 metaTypes.append(id);
158 seenMessage = true; // it cannot appear anymore anyways
159 continue;
160 }
161
162 if (seenMessage) { // && !type.endsWith('&')
163 errorMsg = "Invalid method, non-output parameters after message or after output parameters: "_L1 + QLatin1StringView(type);
164 return -1; // not allowed
165 }
166
167 if (type.startsWith("QVector<"))
168 type = "QList<" + type.mid(sizeof("QVector<") - 1);
169
171#ifdef QT_BOOTSTRAPPED
172 // in bootstrap mode QDBusMessage isn't included, thus we need to resolve it manually here
173 if (type == "QDBusMessage") {
175 }
176#endif
177
178 if (!id.isValid()) {
179 errorMsg = "Unregistered input type in parameter list: "_L1 + QLatin1StringView(type);
180 return -1;
181 }
182
183 if (id == QDBusMetaTypeId::message())
184 seenMessage = true;
185 else if (QDBusMetaType::typeToSignature(id) == nullptr) {
186 errorMsg = "Type not registered with QtDBus in parameter list: "_L1 + QLatin1StringView(type);
187 return -1;
188 }
189
190 metaTypes.append(id);
191 ++inputCount;
192 }
193
194 return inputCount;
195}
196
198
199#endif // QT_NO_DBUS
\inmodule QtCore
Definition qbytearray.h:57
void truncate(qsizetype pos)
Truncates the byte array at index position pos.
static QCoreApplication * instance() noexcept
Returns a pointer to the application's QCoreApplication (or QGuiApplication/QApplication) instance.
QString applicationName
the name of this application
QString organizationDomain
the Internet domain of the organization that wrote this application
static const char * typeToSignature(QMetaType type)
constexpr bool isEmpty() const noexcept
constexpr QLatin1StringView() noexcept
Definition qlist.h:74
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
\inmodule QtCore
Definition qmetaobject.h:18
QList< QByteArray > parameterTypes() const
Returns a list of parameter types.
\inmodule QtCore
Definition qmetatype.h:320
static QMetaType fromName(QByteArrayView name)
Returns a QMetaType matching typeName.
\inmodule QtCore
Definition qobject.h:90
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
QString & replace(qsizetype i, qsizetype len, QChar after)
Definition qstring.cpp:3794
void reserve(qsizetype size)
Ensures the string has space for at least size characters.
Definition qstring.h:1173
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:7956
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QString & append(QChar c)
Definition qstring.cpp:3227
QSet< QString >::iterator it
auto mo
[7]
QMetaType message()
Combined button and popup list for selecting options.
@ SkipEmptyParts
Definition qnamespace.h:127
AudioChannelLayoutTag tag
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char * interface
#define QCLASSINFO_DBUS_INTERFACE
bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name)
QString qDBusInterfaceFromMetaObject(const QMetaObject *mo)
Definition qdbusmisc.cpp:42
bool qDBusCheckAsyncTag(const char *tag)
Definition qdbusmisc.cpp:25
int qDBusParametersForMethod(const QMetaMethod &mm, QList< QMetaType > &metaTypes, QString &errorMsg)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLuint GLuint end
GLenum type
GLhandleARB obj
[2]
GLfloat GLfloat p
[1]
@ ForbidLeadingDot
Definition qurl_p.h:30
QString Q_CORE_EXPORT qt_ACE_do(const QString &domain, AceOperation op, AceLeadingDot dot, QUrl::AceProcessingOptions options={})
Definition qurlidna.cpp:889
@ ToAceOnly
Definition qurl_p.h:31
const char className[16]
[1]
Definition qwizard.cpp:100
\inmodule QtCore