Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 {
63 QString domainName = QCoreApplication::instance()->applicationName();
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
124int qDBusParametersForMethod(const QMetaMethod &mm, QList<QMetaType> &metaTypes, QString &errorMsg)
125{
126 QList<QByteArray> parameterTypes;
127 parameterTypes.reserve(mm.parameterCount());
128
129 // Not using QMetaMethod::parameterTypes() since we call QMetaType::fromName below
130 // where we need any typedefs resolved already.
131 for (int i = 0; i < mm.parameterCount(); ++i) {
133 if (typeName.isEmpty())
135 parameterTypes.append(typeName);
136 }
137
138 return qDBusParametersForMethod(parameterTypes, metaTypes, errorMsg);
139}
140
141#endif // QT_BOOTSTRAPPED
142
143int qDBusParametersForMethod(const QList<QByteArray> &parameterTypes, QList<QMetaType> &metaTypes,
144 QString &errorMsg)
145{
147 metaTypes.clear();
148
149 metaTypes.append(QMetaType()); // return type
150 int inputCount = 0;
151 bool seenMessage = false;
152 for (QByteArray type : parameterTypes) {
153 if (type.endsWith('*')) {
154 errorMsg = "Pointers are not supported: "_L1 + QLatin1StringView(type);
155 return -1;
156 }
157
158 if (type.endsWith('&')) {
159 QByteArray basictype = type;
160 basictype.truncate(type.size() - 1);
161
162 QMetaType id = QMetaType::fromName(basictype);
163 if (!id.isValid()) {
164 errorMsg = "Unregistered output type in parameter list: "_L1 + QLatin1StringView(type);
165 return -1;
166 } else if (QDBusMetaType::typeToSignature(id) == nullptr)
167 return -1;
168
169 metaTypes.append(id);
170 seenMessage = true; // it cannot appear anymore anyways
171 continue;
172 }
173
174 if (seenMessage) { // && !type.endsWith('&')
175 errorMsg = "Invalid method, non-output parameters after message or after output parameters: "_L1 + QLatin1StringView(type);
176 return -1; // not allowed
177 }
178
179 if (type.startsWith("QVector<"))
180 type = "QList<" + type.mid(sizeof("QVector<") - 1);
181
183#ifdef QT_BOOTSTRAPPED
184 // in bootstrap mode QDBusMessage isn't included, thus we need to resolve it manually here
185 if (type == "QDBusMessage") {
187 }
188#endif
189
190 if (!id.isValid()) {
191 errorMsg = "Unregistered input type in parameter list: "_L1 + QLatin1StringView(type);
192 return -1;
193 }
194
195 if (id == QDBusMetaTypeId::message())
196 seenMessage = true;
197 else if (QDBusMetaType::typeToSignature(id) == nullptr) {
198 errorMsg = "Type not registered with QtDBus in parameter list: "_L1 + QLatin1StringView(type);
199 return -1;
200 }
201
202 metaTypes.append(id);
203 ++inputCount;
204 }
205
206 return inputCount;
207}
208
210
211#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.
static const char * typeToSignature(QMetaType type)
constexpr bool isEmpty() const noexcept
constexpr QLatin1StringView() noexcept
\inmodule QtCore
Definition qmetaobject.h:19
int parameterCount() const
QMetaType parameterMetaType(int index) const
QByteArray parameterTypeName(int index) const
\inmodule QtCore
Definition qmetatype.h:341
static QMetaType fromName(QByteArrayView name)
Returns a QMetaType matching typeName.
constexpr const char * name() const
Definition qmetatype.h:2680
\inmodule QtCore
Definition qobject.h:103
\inmodule QtCore
Definition qstringview.h:78
Q_CORE_EXPORT QList< QStringView > split(QStringView sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the view into substring views wherever sep occurs, and returns the list of those string views.
Definition qstring.cpp:8249
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
void reserve(qsizetype size)
Ensures the string has space for at least size characters.
Definition qstring.h:1325
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
QSet< QString >::iterator it
auto mo
[7]
Q_DBUS_EXPORT void init()
QMetaType message()
Combined button and popup list for selecting options.
@ SkipEmptyParts
Definition qnamespace.h:128
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]
const char * typeName
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:920
@ ToAceOnly
Definition qurl_p.h:31
const char className[16]
[1]
Definition qwizard.cpp:100
\inmodule QtCore