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

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