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
59Q_STATIC_ASSERT(QDBusMessage::InvalidMessage == DBUS_MESSAGE_TYPE_INVALID);
60Q_STATIC_ASSERT(QDBusMessage::MethodCallMessage == DBUS_MESSAGE_TYPE_METHOD_CALL);
61Q_STATIC_ASSERT(QDBusMessage::ReplyMessage == DBUS_MESSAGE_TYPE_METHOD_RETURN);
62Q_STATIC_ASSERT(QDBusMessage::ErrorMessage == DBUS_MESSAGE_TYPE_ERROR);
63Q_STATIC_ASSERT(QDBusMessage::SignalMessage == DBUS_MESSAGE_TYPE_SIGNAL);
64
65static inline const char *data(const QByteArray &arr)
66{
67 return arr.isEmpty() ? 0 : arr.constData();
68}
69
70QDBusMessagePrivate::QDBusMessagePrivate()
71 : msg(0), reply(0), localReply(0), 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 0;
117 }
118
119 DBusMessage *msg = 0;
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 0;
131 if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
132 return 0;
133 if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error))
134 return 0;
135 if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method"))
136 return 0;
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 0;
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 0;
170 if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error))
171 return 0;
172 if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error))
173 return 0;
174 if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method"))
175 return 0;
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 0;
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 int id = it->userType();
278 const char *signature = QDBusMetaType::typeToSignature(id);
279 if ((id != QVariant::StringList && id != QVariant::ByteArray &&
280 qstrlen(signature) != 1) || id == qMetaTypeId<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.capabilities, &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.capabilities);
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*/
499#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
500QDBusMessage QDBusMessage::createErrorReply(const QString &name, const QString &msg) const
501#else
502QDBusMessage QDBusMessage::createErrorReply(const QString name, const QString &msg) const
503#endif
504{
505 QDBusMessage reply = QDBusMessage::createError(name, msg);
506 if (d_ptr->msg)
507 reply.d_ptr->reply = q_dbus_message_ref(d_ptr->msg);
508 if (d_ptr->localMessage) {
509 reply.d_ptr->localMessage = true;
510 d_ptr->localReply = new QDBusMessage(reply); // keep an internal copy
511 }
512
513 // the reply must have a msg or be a local-loop optimization
514 Q_ASSERT(reply.d_ptr->reply || reply.d_ptr->localMessage);
515 return reply;
516}
517
518/*!
519 \fn QDBusMessage QDBusMessage::createReply(const QVariant &argument) const
520
521 Constructs a new DBus message representing a reply, with the
522 given \a argument.
523*/
524
525/*!
526 \fn QDBusMessage QDBusMessage::createErrorReply(const QDBusError &error) const
527
528 Constructs a new DBus message representing an error reply message,
529 from the given \a error object.
530*/
531
532/*!
533 \fn QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType type, const QString &msg) const
534
535 Constructs a new DBus reply message for the error type \a type using
536 the message \a msg. Returns the DBus message.
537*/
538QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType atype, const QString &amsg) const
539{
540 QDBusMessage msg = createErrorReply(QDBusError::errorString(atype), amsg);
541 msg.d_ptr->parametersValidated = true;
542 return msg;
543}
544
545
546/*!
547 Constructs an empty, invalid QDBusMessage object.
548
549 \sa createError(), createMethodCall(), createSignal()
550*/
551QDBusMessage::QDBusMessage()
552{
553 d_ptr = new QDBusMessagePrivate;
554}
555
556/*!
557 Constructs a copy of the object given by \a other.
558
559 Note: QDBusMessage objects are shared. Modifications made to the
560 copy will affect the original one as well. See setDelayedReply()
561 for more information.
562*/
563QDBusMessage::QDBusMessage(const QDBusMessage &other)
564{
565 d_ptr = other.d_ptr;
566 d_ptr->ref.ref();
567}
568
569/*!
570 Disposes of the object and frees any resources that were being held.
571*/
572QDBusMessage::~QDBusMessage()
573{
574 if (!d_ptr->ref.deref())
575 delete d_ptr;
576}
577
578/*!
579 Copies the contents of the object given by \a other.
580
581 Note: QDBusMessage objects are shared. Modifications made to the
582 copy will affect the original one as well. See setDelayedReply()
583 for more information.
584*/
585QDBusMessage &QDBusMessage::operator=(const QDBusMessage &other)
586{
587 qAtomicAssign(d_ptr, other.d_ptr);
588 return *this;
589}
590
591/*!
592 Returns the name of the service or the bus address of the remote method call.
593*/
594QString QDBusMessage::service() const
595{
596 return d_ptr->service;
597}
598
599/*!
600 Returns the path of the object that this message is being sent to (in the case of a
601 method call) or being received from (for a signal).
602*/
603QString QDBusMessage::path() const
604{
605 return d_ptr->path;
606}
607
608/*!
609 Returns the interface of the method being called (in the case of a method call) or of
610 the signal being received from.
611*/
612QString QDBusMessage::interface() const
613{
614 return d_ptr->interface;
615}
616
617/*!
618 Returns the name of the signal that was emitted or the name of the method that was called.
619*/
620QString QDBusMessage::member() const
621{
622 if (d_ptr->type != ErrorMessage)
623 return d_ptr->name;
624 return QString();
625}
626
627/*!
628 Returns the name of the error that was received.
629*/
630QString QDBusMessage::errorName() const
631{
632 if (d_ptr->type == ErrorMessage)
633 return d_ptr->name;
634 return QString();
635}
636
637/*!
638 Returns the signature of the signal that was received or for the output arguments
639 of a method call.
640*/
641QString QDBusMessage::signature() const
642{
643 return d_ptr->signature;
644}
645
646/*!
647 Returns the flag that indicates if this message should see a reply
648 or not. This is only meaningful for \l {MethodCallMessage}{method
649 call messages}: any other kind of message cannot have replies and
650 this function will always return false for them.
651*/
652bool QDBusMessage::isReplyRequired() const
653{
654 // Only method calls can have replies
655 if (d_ptr->type != QDBusMessage::MethodCallMessage)
656 return false;
657
658 if (!d_ptr->msg)
659 return d_ptr->localMessage; // if it's a local message, reply is required
660 return !q_dbus_message_get_no_reply(d_ptr->msg);
661}
662
663/*!
664 Sets whether the message will be replied later (if \a enable is
665 true) or if an automatic reply should be generated by Qt D-Bus
666 (if \a enable is false).
667
668 In D-Bus, all method calls must generate a reply to the caller, unless the
669 caller explicitly indicates otherwise (see isReplyRequired()). QtDBus
670 automatically generates such replies for any slots being called, but it
671 also allows slots to indicate whether they will take responsibility
672 of sending the reply at a later time, after the function has finished
673 processing.
674
675 \sa {Delayed Replies}
676*/
677void QDBusMessage::setDelayedReply(bool enable) const
678{
679 d_ptr->delayedReply = enable;
680}
681
682/*!
683 Returns the delayed reply flag, as set by setDelayedReply(). By default, this
684 flag is false, which means Qt D-Bus will generate automatic replies
685 when necessary.
686*/
687bool QDBusMessage::isDelayedReply() const
688{
689 return d_ptr->delayedReply;
690}
691
692/*!
693 Sets the auto start flag to \a enable. This flag only makes sense
694 for method call messages, where it tells the D-Bus server to
695 either auto start the service responsible for the service name, or
696 not to auto start it.
697
698 By default this flag is true, i.e. a service is autostarted.
699 This means:
700
701 When the service that this method call is sent to is already
702 running, the method call is sent to it. If the service is not
703 running yet, the D-Bus daemon is requested to autostart the
704 service that is assigned to this service name. This is
705 handled by .service files that are placed in a directory known
706 to the D-Bus server. These files then each contain a service
707 name and the path to a program that should be executed when
708 this service name is requested.
709
710 \since 4.7
711*/
712void QDBusMessage::setAutoStartService(bool enable)
713{
714 d_ptr->autoStartService = enable;
715}
716
717/*!
718 Returns the auto start flag, as set by setAutoStartService(). By default, this
719 flag is true, which means Qt D-Bus will auto start a service, if it is
720 not running already.
721
722 \sa setAutoStartService()
723
724 \since 4.7
725*/
726bool QDBusMessage::autoStartService() const
727{
728 return d_ptr->autoStartService;
729}
730
731/*!
732 Sets the interactive authorization flag to \a enable.
733 This flag only makes sense for method call messages, where it
734 tells the D-Bus server that the caller of the method is prepared
735 to wait for interactive authorization to take place (for instance
736 via Polkit) before the actual method is processed.
737
738 By default this flag is false and the other end is expected to
739 make any authorization decisions non-interactively and promptly.
740
741 The \c org.freedesktop.DBus.Error.InteractiveAuthorizationRequired
742 error indicates that authorization failed, but could have succeeded
743 if this flag had been set.
744
745 \sa isInteractiveAuthorizationAllowed()
746
747 \since 5.12
748*/
749void QDBusMessage::setInteractiveAuthorizationAllowed(bool enable)
750{
751 d_ptr->interactiveAuthorizationAllowed = enable;
752}
753
754/*!
755 Returns the interactive authorization allowed flag, as set by
756 setInteractiveAuthorizationAllowed(). By default this flag
757 is false and the other end is expected to make any authorization
758 decisions non-interactively and promptly.
759
760 \sa setInteractiveAuthorizationAllowed()
761
762 \since 5.12
763*/
764bool QDBusMessage::isInteractiveAuthorizationAllowed() const
765{
766 return d_ptr->interactiveAuthorizationAllowed;
767}
768
769/*!
770 Sets the arguments that are going to be sent over D-Bus to \a arguments. Those
771 will be the arguments to a method call or the parameters in the signal.
772
773 \sa arguments()
774*/
775void QDBusMessage::setArguments(const QList<QVariant> &arguments)
776{
777 // FIXME: should we detach?
778 d_ptr->arguments = arguments;
779}
780
781/*!
782 Returns the list of arguments that are going to be sent or were received from
783 D-Bus.
784*/
785QList<QVariant> QDBusMessage::arguments() const
786{
787 return d_ptr->arguments;
788}
789
790/*!
791 Appends the argument \a arg to the list of arguments to be sent over D-Bus in
792 a method call or signal emission.
793*/
794
795QDBusMessage &QDBusMessage::operator<<(const QVariant &arg)
796{
797 // FIXME: should we detach?
798 d_ptr->arguments.append(arg);
799 return *this;
800}
801
802/*!
803 Returns the message type.
804*/
805QDBusMessage::MessageType QDBusMessage::type() const
806{
807 switch (d_ptr->type) {
808 case DBUS_MESSAGE_TYPE_METHOD_CALL:
809 return MethodCallMessage;
810 case DBUS_MESSAGE_TYPE_METHOD_RETURN:
811 return ReplyMessage;
812 case DBUS_MESSAGE_TYPE_ERROR:
813 return ErrorMessage;
814 case DBUS_MESSAGE_TYPE_SIGNAL:
815 return SignalMessage;
816 default:
817 break;
818 }
819 return InvalidMessage;
820}
821
822#ifndef QT_NO_DEBUG_STREAM
823static QDebug operator<<(QDebug dbg, QDBusMessage::MessageType t)
824{
825 switch (t)
826 {
827 case QDBusMessage::MethodCallMessage:
828 return dbg << "MethodCall";
829 case QDBusMessage::ReplyMessage:
830 return dbg << "MethodReturn";
831 case QDBusMessage::SignalMessage:
832 return dbg << "Signal";
833 case QDBusMessage::ErrorMessage:
834 return dbg << "Error";
835 default:
836 return dbg << "Invalid";
837 }
838}
839
840static void debugVariantList(QDebug dbg, const QVariantList &list)
841{
842 bool first = true;
843 QVariantList::ConstIterator it = list.constBegin();
844 QVariantList::ConstIterator end = list.constEnd();
845 for ( ; it != end; ++it) {
846 if (!first)
847 dbg.nospace() << ", ";
848 dbg.nospace() << qPrintable(QDBusUtil::argumentToString(*it));
849 first = false;
850 }
851}
852
853QDebug operator<<(QDebug dbg, const QDBusMessage &msg)
854{
855 QDebugStateSaver saver(dbg);
856 dbg.nospace() << "QDBusMessage(type=" << msg.type()
857 << ", service=" << msg.service();
858 if (msg.type() == QDBusMessage::MethodCallMessage ||
859 msg.type() == QDBusMessage::SignalMessage)
860 dbg.nospace() << ", path=" << msg.path()
861 << ", interface=" << msg.interface()
862 << ", member=" << msg.member();
863 if (msg.type() == QDBusMessage::ErrorMessage)
864 dbg.nospace() << ", error name=" << msg.errorName()
865 << ", error message=" << msg.errorMessage();
866 dbg.nospace() << ", signature=" << msg.signature()
867 << ", contents=(";
868 debugVariantList(dbg, msg.arguments());
869 dbg.nospace() << ") )";
870 return dbg;
871}
872#endif
873
874/*!
875 \fn void QDBusMessage::swap(QDBusMessage &other)
876
877 Swaps this QDBusMessage instance with \a other.
878*/
879
880QT_END_NAMESPACE
881
882#endif // QT_NO_DBUS
883