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