1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
6#include "qdbusmessage.h"
7#include "qdbusmessage_p.h"
8
9#include <qdebug.h>
10#include <qstringlist.h>
11
12#include "qdbus_symbols_p.h"
13
14#include "qdbusargument_p.h"
15#include "qdbuserror.h"
16#include "qdbusmetatype.h"
17#include "qdbusconnection_p.h"
18#include "qdbusutil_p.h"
19
20#ifndef QT_NO_DBUS
21
22QT_BEGIN_NAMESPACE
23
24using namespace Qt::StringLiterals;
25
26QT_IMPL_METATYPE_EXTERN(QDBusMessage)
27
28static_assert(QDBusMessage::InvalidMessage == DBUS_MESSAGE_TYPE_INVALID);
29static_assert(QDBusMessage::MethodCallMessage == DBUS_MESSAGE_TYPE_METHOD_CALL);
30static_assert(QDBusMessage::ReplyMessage == DBUS_MESSAGE_TYPE_METHOD_RETURN);
31static_assert(QDBusMessage::ErrorMessage == DBUS_MESSAGE_TYPE_ERROR);
32static_assert(QDBusMessage::SignalMessage == DBUS_MESSAGE_TYPE_SIGNAL);
33
34static inline const char *data(const QByteArray &arr)
35{
36 return arr.isEmpty() ? nullptr : arr.constData();
37}
38
39QDBusMessagePrivate::QDBusMessagePrivate()
40 : localReply(nullptr), ref(1), type(QDBusMessage::InvalidMessage),
41 delayedReply(false), parametersValidated(false),
42 localMessage(false), autoStartService(true),
43 interactiveAuthorizationAllowed(false), isReplyRequired(false)
44{
45}
46
47QDBusMessagePrivate::~QDBusMessagePrivate()
48{
49 delete localReply;
50}
51
52void QDBusMessagePrivate::createResponseLink(const QDBusMessagePrivate *call)
53{
54 if (Q_UNLIKELY(call->type != QDBusMessage::MethodCallMessage)) {
55 qWarning(msg: "QDBusMessage: replying to a message that isn't a method call");
56 return;
57 }
58
59 if (call->localMessage) {
60 localMessage = true;
61 call->localReply = new QDBusMessage(*this); // keep an internal copy
62 } else {
63 serial = call->serial;
64 service = call->service;
65 }
66
67 // the reply must have a serial or be a local-loop optimization
68 Q_ASSERT(serial || localMessage);
69}
70
71/*!
72 \since 4.3
73 Returns the human-readable message associated with the error that was received.
74*/
75QString QDBusMessage::errorMessage() const
76{
77 if (d_ptr->type == ErrorMessage) {
78 if (!d_ptr->message.isEmpty())
79 return d_ptr->message;
80 if (!d_ptr->arguments.isEmpty())
81 return d_ptr->arguments.at(i: 0).toString();
82 }
83 return QString();
84}
85
86/*!
87 \internal
88 Constructs a DBusMessage object from \a message. The returned value must be de-referenced
89 with q_dbus_message_unref. The \a capabilities flags indicates which capabilities to use.
90
91 The \a error object is set to indicate the error if anything went wrong with the
92 marshalling. Usually, this error message will be placed in the reply, as if the call failed.
93 The \a error pointer must not be null.
94*/
95DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDBusConnection::ConnectionCapabilities capabilities,
96 QDBusError *error)
97{
98 if (!qdbus_loadLibDBus()) {
99 *error = QDBusError(QDBusError::Failed, "Could not open lidbus-1 library"_L1);
100 return nullptr;
101 }
102
103 DBusMessage *msg = nullptr;
104 const QDBusMessagePrivate *d_ptr = message.d_ptr;
105
106 switch (d_ptr->type) {
107 case QDBusMessage::InvalidMessage:
108 //qDebug() << "QDBusMessagePrivate::toDBusMessage" << "message is invalid";
109 break;
110 case QDBusMessage::MethodCallMessage:
111 // only service and interface can be empty -> path and name must not be empty
112 if (!d_ptr->parametersValidated) {
113 using namespace QDBusUtil;
114 AllowEmptyFlag serviceCheckMode = capabilities & QDBusConnectionPrivate::ConnectionIsBus
115 ? EmptyNotAllowed : EmptyAllowed;
116 if (!checkBusName(name: d_ptr->service, empty: serviceCheckMode, error))
117 return nullptr;
118 if (!QDBusUtil::checkObjectPath(path: d_ptr->path, empty: QDBusUtil::EmptyNotAllowed, error))
119 return nullptr;
120 if (!QDBusUtil::checkInterfaceName(name: d_ptr->interface, empty: QDBusUtil::EmptyAllowed, error))
121 return nullptr;
122 if (!QDBusUtil::checkMemberName(name: d_ptr->name, empty: QDBusUtil::EmptyNotAllowed, error, nameType: "method"))
123 return nullptr;
124 }
125
126 msg = q_dbus_message_new_method_call(bus_name: data(arr: d_ptr->service.toUtf8()), path: d_ptr->path.toUtf8(),
127 interface: data(arr: d_ptr->interface.toUtf8()), method: d_ptr->name.toUtf8());
128 q_dbus_message_set_auto_start( message: msg, auto_start: d_ptr->autoStartService );
129 q_dbus_message_set_allow_interactive_authorization(message: msg, allow: d_ptr->interactiveAuthorizationAllowed);
130
131 break;
132 case QDBusMessage::ReplyMessage:
133 msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN);
134 if (!d_ptr->localMessage) {
135 q_dbus_message_set_destination(message: msg, destination: data(arr: d_ptr->service.toUtf8()));
136 q_dbus_message_set_reply_serial(message: msg, reply_serial: d_ptr->serial);
137 }
138 break;
139 case QDBusMessage::ErrorMessage:
140 // error name can't be empty
141 if (!d_ptr->parametersValidated
142 && !QDBusUtil::checkErrorName(name: d_ptr->name, empty: QDBusUtil::EmptyNotAllowed, error))
143 return nullptr;
144
145 msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_ERROR);
146 q_dbus_message_set_error_name(message: msg, name: d_ptr->name.toUtf8());
147 if (!d_ptr->localMessage) {
148 q_dbus_message_set_destination(message: msg, destination: data(arr: d_ptr->service.toUtf8()));
149 q_dbus_message_set_reply_serial(message: msg, reply_serial: d_ptr->serial);
150 }
151 break;
152 case QDBusMessage::SignalMessage:
153 // only the service name can be empty here (even for bus connections)
154 if (!d_ptr->parametersValidated) {
155 if (!QDBusUtil::checkBusName(name: d_ptr->service, empty: QDBusUtil::EmptyAllowed, error))
156 return nullptr;
157 if (!QDBusUtil::checkObjectPath(path: d_ptr->path, empty: QDBusUtil::EmptyNotAllowed, error))
158 return nullptr;
159 if (!QDBusUtil::checkInterfaceName(name: d_ptr->interface, empty: QDBusUtil::EmptyAllowed, error))
160 return nullptr;
161 if (!QDBusUtil::checkMemberName(name: d_ptr->name, empty: QDBusUtil::EmptyNotAllowed, error, nameType: "method"))
162 return nullptr;
163 }
164
165 msg = q_dbus_message_new_signal(path: d_ptr->path.toUtf8(), interface: d_ptr->interface.toUtf8(),
166 name: d_ptr->name.toUtf8());
167 q_dbus_message_set_destination(message: msg, destination: data(arr: d_ptr->service.toUtf8()));
168 break;
169 }
170
171 // if we got here, the parameters validated
172 // and since the message parameters cannot be changed once the message is created
173 // we can record this fact
174 d_ptr->parametersValidated = true;
175
176 QDBusMarshaller marshaller(capabilities);
177 q_dbus_message_iter_init_append(message: msg, iter: &marshaller.iterator);
178 if (!d_ptr->message.isEmpty())
179 // prepend the error message
180 marshaller.append(arg: d_ptr->message);
181 for (const QVariant &argument : std::as_const(t: d_ptr->arguments))
182 marshaller.appendVariantInternal(arg: argument);
183
184 // check if everything is ok
185 if (marshaller.ok)
186 return msg;
187
188 // not ok;
189 q_dbus_message_unref(message: msg);
190 *error = QDBusError(QDBusError::Failed, "Marshalling failed: "_L1 + marshaller.errorString);
191 return nullptr;
192}
193
194/*
195struct DBusMessage
196{
197 DBusAtomic refcount;
198 DBusHeader header;
199 DBusString body;
200 char byte_order;
201 unsigned int locked : 1;
202DBUS_DISABLE_CHECKS
203 unsigned int in_cache : 1;
204#endif
205 DBusList *size_counters;
206 long size_counter_delta;
207 dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS;
208 DBusDataSlotList slot_list;
209#ifndef DBUS_DISABLE_CHECKS
210 int generation;
211#endif
212};
213*/
214
215/*!
216 \internal
217 Constructs a QDBusMessage by parsing the given DBusMessage object.
218*/
219QDBusMessage QDBusMessagePrivate::fromDBusMessage(DBusMessage *dmsg, QDBusConnection::ConnectionCapabilities capabilities)
220{
221 QDBusMessage message;
222 if (!dmsg)
223 return message;
224
225 message.d_ptr->type = QDBusMessage::MessageType(q_dbus_message_get_type(message: dmsg));
226 message.d_ptr->serial = q_dbus_message_get_serial(message: dmsg);
227 message.d_ptr->path = QString::fromUtf8(utf8: q_dbus_message_get_path(message: dmsg));
228 message.d_ptr->interface = QString::fromUtf8(utf8: q_dbus_message_get_interface(message: dmsg));
229 message.d_ptr->name = message.d_ptr->type == DBUS_MESSAGE_TYPE_ERROR ?
230 QString::fromUtf8(utf8: q_dbus_message_get_error_name(message: dmsg)) :
231 QString::fromUtf8(utf8: q_dbus_message_get_member(message: dmsg));
232 message.d_ptr->service = QString::fromUtf8(utf8: q_dbus_message_get_sender(message: dmsg));
233 message.d_ptr->signature = QString::fromUtf8(utf8: q_dbus_message_get_signature(message: dmsg));
234 message.d_ptr->interactiveAuthorizationAllowed = q_dbus_message_get_allow_interactive_authorization(message: dmsg);
235 message.d_ptr->isReplyRequired = !q_dbus_message_get_no_reply(message: dmsg);
236
237 QDBusDemarshaller demarshaller(capabilities);
238 demarshaller.message = q_dbus_message_ref(message: dmsg);
239 if (q_dbus_message_iter_init(message: demarshaller.message, iter: &demarshaller.iterator))
240 while (!demarshaller.atEnd())
241 message << demarshaller.toVariantInternal();
242 return message;
243}
244
245bool QDBusMessagePrivate::isLocal(const QDBusMessage &message)
246{
247 return message.d_ptr->localMessage;
248}
249
250QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn,
251 const QDBusMessage &asSent)
252{
253 // simulate the message being sent to the bus and then received back
254 // the only field that the bus sets when delivering the message
255 // (as opposed to the message as we send it), is the sender
256 // so we simply set the sender to our unique name
257
258 // determine if we are carrying any complex types
259 QString computedSignature;
260 for (const QVariant &argument : std::as_const(t&: asSent.d_ptr->arguments)) {
261 QMetaType id = argument.metaType();
262 const char *signature = QDBusMetaType::typeToSignature(type: id);
263 if ((id.id() != QMetaType::QStringList && id.id() != QMetaType::QByteArray &&
264 qstrlen(str: signature) != 1) || id == QMetaType::fromType<QDBusVariant>()) {
265 // yes, we are
266 // we must marshall and demarshall again so as to create QDBusArgument
267 // entries for the complex types
268 QDBusError error;
269 DBusMessage *message = toDBusMessage(message: asSent, capabilities: conn.connectionCapabilities(), error: &error);
270 if (!message) {
271 // failed to marshall, so it's a call error
272 return QDBusMessage::createError(err: error);
273 }
274
275 q_dbus_message_set_sender(message, sender: conn.baseService.toUtf8());
276
277 QDBusMessage retval = fromDBusMessage(dmsg: message, capabilities: conn.connectionCapabilities());
278 retval.d_ptr->localMessage = true;
279 q_dbus_message_unref(message);
280 if (retval.d_ptr->service.isEmpty())
281 retval.d_ptr->service = conn.baseService;
282 return retval;
283 } else {
284 computedSignature += QLatin1StringView(signature);
285 }
286 }
287
288 // no complex types seen
289 // optimize by using the variant list itself
290 QDBusMessage retval;
291 QDBusMessagePrivate *d = retval.d_ptr;
292 d->arguments = asSent.d_ptr->arguments;
293 d->path = asSent.d_ptr->path;
294 d->interface = asSent.d_ptr->interface;
295 d->name = asSent.d_ptr->name;
296 d->message = asSent.d_ptr->message;
297 d->type = asSent.d_ptr->type;
298
299 d->service = conn.baseService;
300 d->signature = computedSignature;
301 d->localMessage = true;
302 return retval;
303}
304
305QDBusMessage QDBusMessagePrivate::makeLocalReply(const QDBusConnectionPrivate &conn,
306 const QDBusMessage &callMsg)
307{
308 // simulate the reply (return or error) message being sent to the bus and
309 // then received back.
310 if (callMsg.d_ptr->localReply)
311 return makeLocal(conn, asSent: *callMsg.d_ptr->localReply);
312 return QDBusMessage(); // failed
313}
314
315/*!
316 \class QDBusMessage
317 \inmodule QtDBus
318 \since 4.2
319
320 \brief The QDBusMessage class represents one message sent or
321 received over the D-Bus bus.
322
323 This object can represent any of the four different types of
324 messages (MessageType) that can occur on the bus:
325
326 \list
327 \li Method calls
328 \li Method return values
329 \li Signal emissions
330 \li Error codes
331 \endlist
332
333 Objects of this type are created with the static createError(),
334 createMethodCall() and createSignal() functions. Use the
335 QDBusConnection::send() function to send the messages.
336*/
337
338/*!
339 \enum QDBusMessage::MessageType
340 The possible message types:
341
342 \value MethodCallMessage a message representing an outgoing or incoming method call
343 \value SignalMessage a message representing an outgoing or incoming signal emission
344 \value ReplyMessage a message representing the return values of a method call
345 \value ErrorMessage a message representing an error condition in response to a method call
346 \value InvalidMessage an invalid message: this is never set on messages received from D-Bus
347*/
348
349/*!
350 Constructs a new DBus message with the given \a path, \a interface
351 and \a name, representing a signal emission.
352
353 A DBus signal is emitted from one application and is received by
354 all applications that are listening for that signal from that
355 interface.
356
357 The QDBusMessage object that is returned can be sent using the
358 QDBusConnection::send() function.
359*/
360QDBusMessage QDBusMessage::createSignal(const QString &path, const QString &interface,
361 const QString &name)
362{
363 QDBusMessage message;
364 message.d_ptr->type = SignalMessage;
365 message.d_ptr->path = path;
366 message.d_ptr->interface = interface;
367 message.d_ptr->name = name;
368
369 return message;
370}
371
372/*!
373 \since 5.6
374
375 Constructs a new DBus message with the given \a path, \a interface
376 and \a name, representing a signal emission to a specific destination.
377
378 A DBus signal is emitted from one application and is received only by
379 the application owning the destination \a service name.
380
381 The QDBusMessage object that is returned can be sent using the
382 QDBusConnection::send() function.
383*/
384QDBusMessage QDBusMessage::createTargetedSignal(const QString &service, const QString &path,
385 const QString &interface, const QString &name)
386{
387 QDBusMessage message;
388 message.d_ptr->type = SignalMessage;
389 message.d_ptr->service = service;
390 message.d_ptr->path = path;
391 message.d_ptr->interface = interface;
392 message.d_ptr->name = name;
393
394 return message;
395}
396
397/*!
398 Constructs a new DBus message representing a method call.
399 A method call always informs its destination address
400 (\a service, \a path, \a interface and \a method).
401
402 The DBus bus allows calling a method on a given remote object without specifying the
403 destination interface, if the method name is unique. However, if two interfaces on the
404 remote object export the same method name, the result is undefined (one of the two may be
405 called or an error may be returned).
406
407 When using DBus in a peer-to-peer context (i.e., not on a bus), the \a service parameter is
408 optional.
409
410 The QDBusInterface class provides a simpler abstraction to synchronous
411 method calling.
412
413 This function returns a QDBusMessage object that can be sent with
414 QDBusConnection::call().
415*/
416QDBusMessage QDBusMessage::createMethodCall(const QString &service, const QString &path,
417 const QString &interface, const QString &method)
418{
419 QDBusMessage message;
420 message.d_ptr->type = MethodCallMessage;
421 message.d_ptr->service = service;
422 message.d_ptr->path = path;
423 message.d_ptr->interface = interface;
424 message.d_ptr->name = method;
425 message.d_ptr->isReplyRequired = true;
426
427 return message;
428}
429
430/*!
431 Constructs a new DBus message representing an error,
432 with the given \a name and \a msg.
433*/
434QDBusMessage QDBusMessage::createError(const QString &name, const QString &msg)
435{
436 QDBusMessage error;
437 error.d_ptr->type = ErrorMessage;
438 error.d_ptr->name = name;
439 error.d_ptr->message = msg;
440
441 return error;
442}
443
444/*!
445 \fn QDBusMessage QDBusMessage::createError(const QDBusError &error)
446
447 Constructs a new DBus message representing the given \a error.
448*/
449
450/*!
451 \fn QDBusMessage QDBusMessage::createError(QDBusError::ErrorType type, const QString &msg)
452
453 Constructs a new DBus message for the error type \a type using
454 the message \a msg. Returns the DBus message.
455*/
456
457/*!
458 \fn QDBusMessage QDBusMessage::createReply(const QList<QVariant> &arguments) const
459
460 Constructs a new DBus message representing a reply, with the given
461 \a arguments.
462*/
463QDBusMessage QDBusMessage::createReply(const QVariantList &arguments) const
464{
465 QDBusMessage reply;
466 reply.setArguments(arguments);
467 reply.d_ptr->type = ReplyMessage;
468 reply.d_ptr->createResponseLink(call: d_ptr);
469 return reply;
470}
471
472/*!
473 Constructs a new DBus message representing an error reply message,
474 with the given \a name and \a msg.
475*/
476QDBusMessage QDBusMessage::createErrorReply(const QString &name, const QString &msg) const
477{
478 QDBusMessage reply = QDBusMessage::createError(name, msg);
479 reply.d_ptr->createResponseLink(call: d_ptr);
480 return reply;
481}
482
483/*!
484 Constructs a new DBus message representing a reply, with the
485 given \a argument.
486*/
487QDBusMessage QDBusMessage::createReply(const QVariant &argument) const
488{
489 return createReply(arguments: QList{argument});
490}
491
492/*!
493 \fn QDBusMessage QDBusMessage::createErrorReply(const QDBusError &error) const
494
495 Constructs a new DBus message representing an error reply message,
496 from the given \a error object.
497*/
498
499/*!
500 \fn QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType type, const QString &msg) const
501
502 Constructs a new DBus reply message for the error type \a type using
503 the message \a msg. Returns the DBus message.
504*/
505QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType atype, const QString &amsg) const
506{
507 QDBusMessage msg = createErrorReply(name: QDBusError::errorString(error: atype), msg: amsg);
508 msg.d_ptr->parametersValidated = true;
509 return msg;
510}
511
512
513/*!
514 Constructs an empty, invalid QDBusMessage object.
515
516 \sa createError(), createMethodCall(), createSignal()
517*/
518QDBusMessage::QDBusMessage()
519{
520 d_ptr = new QDBusMessagePrivate;
521}
522
523/*!
524 Constructs a copy of the object given by \a other.
525
526 Note: QDBusMessage objects are shared. Modifications made to the
527 copy will affect the original one as well. See setDelayedReply()
528 for more information.
529*/
530QDBusMessage::QDBusMessage(const QDBusMessage &other)
531{
532 d_ptr = other.d_ptr;
533 d_ptr->ref.ref();
534}
535
536/*!
537 Disposes of the object and frees any resources that were being held.
538*/
539QDBusMessage::~QDBusMessage()
540{
541 if (!d_ptr->ref.deref())
542 delete d_ptr;
543}
544
545/*!
546 \fn QDBusMessage &QDBusMessage::operator=(QDBusMessage &&other)
547
548 Move-assigns \a other into this object.
549
550//! [partially-formed]
551 \note The moved-from object \a other is placed in a partially-formed state,
552 in which the only valid operations are destruction and assignment of a new
553 value.
554//! [partially-formed]
555*/
556
557/*!
558 Copies the contents of the object given by \a other.
559
560 Note: QDBusMessage objects are shared. Modifications made to the
561 copy will affect the original one as well. See setDelayedReply()
562 for more information.
563*/
564QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
565{
566 qAtomicAssign(d&: d_ptr, x: other.d_ptr);
567 return *this;
568}
569
570/*!
571 Returns the name of the service or the bus address of the remote method call.
572*/
573QString QDBusMessage::service() const
574{
575 if (d_ptr->type == ErrorMessage || d_ptr->type == ReplyMessage)
576 return QString(); // d_ptr->service holds the destination
577 return d_ptr->service;
578}
579
580/*!
581 Returns the path of the object that this message is being sent to (in the case of a
582 method call) or being received from (for a signal).
583*/
584QString QDBusMessage::path() const
585{
586 return d_ptr->path;
587}
588
589/*!
590 Returns the interface of the method being called (in the case of a method call) or of
591 the signal being received from.
592*/
593QString QDBusMessage::interface() const
594{
595 return d_ptr->interface;
596}
597
598/*!
599 Returns the name of the signal that was emitted or the name of the method that was called.
600*/
601QString QDBusMessage::member() const
602{
603 if (d_ptr->type != ErrorMessage)
604 return d_ptr->name;
605 return QString();
606}
607
608/*!
609 Returns the name of the error that was received.
610*/
611QString QDBusMessage::errorName() const
612{
613 if (d_ptr->type == ErrorMessage)
614 return d_ptr->name;
615 return QString();
616}
617
618/*!
619 Returns the signature of the signal that was received or for the output arguments
620 of a method call.
621*/
622QString QDBusMessage::signature() const
623{
624 return d_ptr->signature;
625}
626
627/*!
628 Returns the flag that indicates if this message should see a reply
629 or not. This is only meaningful for \l {MethodCallMessage}{method
630 call messages}: any other kind of message cannot have replies and
631 this function will always return false for them.
632*/
633bool QDBusMessage::isReplyRequired() const
634{
635 // Only method calls can have replies
636 if (d_ptr->type != QDBusMessage::MethodCallMessage)
637 return false;
638
639 if (d_ptr->localMessage) // if it's a local message, reply is required
640 return true;
641 return d_ptr->isReplyRequired;
642}
643
644/*!
645 Sets whether the message will be replied later (if \a enable is
646 true) or if an automatic reply should be generated by Qt D-Bus
647 (if \a enable is false).
648
649 In D-Bus, all method calls must generate a reply to the caller, unless the
650 caller explicitly indicates otherwise (see isReplyRequired()). QtDBus
651 automatically generates such replies for any slots being called, but it
652 also allows slots to indicate whether they will take responsibility
653 of sending the reply at a later time, after the function has finished
654 processing.
655
656 \sa {Delayed Replies}
657*/
658void QDBusMessage::setDelayedReply(bool enable) const
659{
660 d_ptr->delayedReply = enable;
661}
662
663/*!
664 Returns the delayed reply flag, as set by setDelayedReply(). By default, this
665 flag is false, which means Qt D-Bus will generate automatic replies
666 when necessary.
667*/
668bool QDBusMessage::isDelayedReply() const
669{
670 return d_ptr->delayedReply;
671}
672
673/*!
674 Sets the auto start flag to \a enable. This flag only makes sense
675 for method call messages, where it tells the D-Bus server to
676 either auto start the service responsible for the service name, or
677 not to auto start it.
678
679 By default this flag is true, i.e. a service is autostarted.
680 This means:
681
682 When the service that this method call is sent to is already
683 running, the method call is sent to it. If the service is not
684 running yet, the D-Bus daemon is requested to autostart the
685 service that is assigned to this service name. This is
686 handled by .service files that are placed in a directory known
687 to the D-Bus server. These files then each contain a service
688 name and the path to a program that should be executed when
689 this service name is requested.
690
691 \since 4.7
692*/
693void QDBusMessage::setAutoStartService(bool enable)
694{
695 d_ptr->autoStartService = enable;
696}
697
698/*!
699 Returns the auto start flag, as set by setAutoStartService(). By default, this
700 flag is true, which means Qt D-Bus will auto start a service, if it is
701 not running already.
702
703 \sa setAutoStartService()
704
705 \since 4.7
706*/
707bool QDBusMessage::autoStartService() const
708{
709 return d_ptr->autoStartService;
710}
711
712/*!
713 Enables or disables the \c ALLOW_INTERACTIVE_AUTHORIZATION flag
714 in a message.
715
716 This flag only makes sense for method call messages
717 (\l QDBusMessage::MethodCallMessage). If \a enable
718 is set to \c true, the flag indicates to the callee that the
719 caller of the method is prepared to wait for interactive authorization
720 to take place (for instance via Polkit) before the actual method
721 is processed.
722
723 If \a enable is set to \c false, the flag is not
724 set, meaning that the other end is expected to make any authorization
725 decisions non-interactively and promptly. This is the default.
726
727 The \c org.freedesktop.DBus.Error.InteractiveAuthorizationRequired
728 error indicates that authorization failed, but could have succeeded
729 if this flag had been set.
730
731 \sa isInteractiveAuthorizationAllowed(),
732 QDBusAbstractInterface::setInteractiveAuthorizationAllowed()
733
734 \since 5.12
735*/
736void QDBusMessage::setInteractiveAuthorizationAllowed(bool enable)
737{
738 d_ptr->interactiveAuthorizationAllowed = enable;
739}
740
741/*!
742 Returns whether the message has the
743 \c ALLOW_INTERACTIVE_AUTHORIZATION flag set.
744
745 \sa setInteractiveAuthorizationAllowed(),
746 QDBusAbstractInterface::isInteractiveAuthorizationAllowed()
747
748 \since 5.12
749*/
750bool QDBusMessage::isInteractiveAuthorizationAllowed() const
751{
752 return d_ptr->interactiveAuthorizationAllowed;
753}
754
755/*!
756 Sets the arguments that are going to be sent over D-Bus to \a arguments. Those
757 will be the arguments to a method call or the parameters in the signal.
758
759 Note that QVariantMap with invalid QVariant as value is not allowed
760 in \a arguments.
761
762 \sa arguments()
763*/
764void QDBusMessage::setArguments(const QList<QVariant> &arguments)
765{
766 d_ptr->arguments = arguments;
767}
768
769/*!
770 Returns the list of arguments that are going to be sent or were received from
771 D-Bus.
772*/
773QList<QVariant> QDBusMessage::arguments() const
774{
775 return d_ptr->arguments;
776}
777
778/*!
779 Appends the argument \a arg to the list of arguments to be sent over D-Bus in
780 a method call or signal emission.
781*/
782
783QDBusMessage &QDBusMessage::operator<<(const QVariant &arg)
784{
785 d_ptr->arguments.append(t: arg);
786 return *this;
787}
788
789QDBusMessage::QDBusMessage(QDBusMessagePrivate &dd)
790 : d_ptr(&dd)
791{
792 d_ptr->ref.ref();
793}
794
795/*!
796 Returns the message type.
797*/
798QDBusMessage::MessageType QDBusMessage::type() const
799{
800 switch (d_ptr->type) {
801 case DBUS_MESSAGE_TYPE_METHOD_CALL:
802 return MethodCallMessage;
803 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
804 return ReplyMessage;
805 case DBUS_MESSAGE_TYPE_ERROR:
806 return ErrorMessage;
807 case DBUS_MESSAGE_TYPE_SIGNAL:
808 return SignalMessage;
809 default:
810 break;
811 }
812 return InvalidMessage;
813}
814
815#ifndef QT_NO_DEBUG_STREAM
816static QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
817{
818 switch (t)
819 {
820 case QDBusMessage::MethodCallMessage:
821 return dbg << "MethodCall";
822 case QDBusMessage::ReplyMessage:
823 return dbg << "MethodReturn";
824 case QDBusMessage::SignalMessage:
825 return dbg << "Signal";
826 case QDBusMessage::ErrorMessage:
827 return dbg << "Error";
828 default:
829 return dbg << "Invalid";
830 }
831}
832
833static void debugVariantList(QDebug dbg, const QVariantList &list)
834{
835 bool first = true;
836 for (const QVariant &elem : list) {
837 if (!first)
838 dbg.nospace() << ", ";
839 dbg.nospace() << qPrintable(QDBusUtil::argumentToString(elem));
840 first = false;
841 }
842}
843
844QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
845{
846 QDebugStateSaver saver(dbg);
847 dbg.nospace() << "QDBusMessage(type=" << msg.type()
848 << ", service=" << msg.service();
849 if (msg.type() == QDBusMessage::MethodCallMessage ||
850 msg.type() == QDBusMessage::SignalMessage)
851 dbg.nospace() << ", path=" << msg.path()
852 << ", interface=" << msg.interface()
853 << ", member=" << msg.member();
854 if (msg.type() == QDBusMessage::ErrorMessage)
855 dbg.nospace() << ", error name=" << msg.errorName()
856 << ", error message=" << msg.errorMessage();
857 dbg.nospace() << ", signature=" << msg.signature()
858 << ", contents=(";
859 debugVariantList(dbg, list: msg.arguments());
860 dbg.nospace() << ") )";
861 return dbg;
862}
863#endif
864
865/*!
866 \fn void QDBusMessage::swap(QDBusMessage &other)
867 \memberswap{message}
868*/
869
870QT_END_NAMESPACE
871
872#endif // QT_NO_DBUS
873

source code of qtbase/src/dbus/qdbusmessage.cpp