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 
57 QT_BEGIN_NAMESPACE
58 
59 Q_STATIC_ASSERT(QDBusMessage::InvalidMessage == DBUS_MESSAGE_TYPE_INVALID);
60 Q_STATIC_ASSERT(QDBusMessage::MethodCallMessage == DBUS_MESSAGE_TYPE_METHOD_CALL);
61 Q_STATIC_ASSERT(QDBusMessage::ReplyMessage == DBUS_MESSAGE_TYPE_METHOD_RETURN);
62 Q_STATIC_ASSERT(QDBusMessage::ErrorMessage == DBUS_MESSAGE_TYPE_ERROR);
63 Q_STATIC_ASSERT(QDBusMessage::SignalMessage == DBUS_MESSAGE_TYPE_SIGNAL);
64 
data(const QByteArray & arr)65 static inline const char *data(const QByteArray &arr)
66 {
67     return arr.isEmpty() ? nullptr : arr.constData();
68 }
69 
QDBusMessagePrivate()70 QDBusMessagePrivate::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 
~QDBusMessagePrivate()78 QDBusMessagePrivate::~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 */
errorMessage() const91 QString 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 */
toDBusMessage(const QDBusMessage & message,QDBusConnection::ConnectionCapabilities capabilities,QDBusError * error)111 DBusMessage *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 /*
210 struct DBusMessage
211 {
212     DBusAtomic refcount;
213     DBusHeader header;
214     DBusString body;
215     char byte_order;
216     unsigned int locked : 1;
217 DBUS_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 */
fromDBusMessage(DBusMessage * dmsg,QDBusConnection::ConnectionCapabilities capabilities)234 QDBusMessage 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 
isLocal(const QDBusMessage & message)259 bool QDBusMessagePrivate::isLocal(const QDBusMessage &message)
260 {
261     return message.d_ptr->localMessage;
262 }
263 
makeLocal(const QDBusConnectionPrivate & conn,const QDBusMessage & asSent)264 QDBusMessage 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 != QMetaType::QStringList && id != QMetaType::QByteArray &&
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.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 
makeLocalReply(const QDBusConnectionPrivate & conn,const QDBusMessage & callMsg)321 QDBusMessage 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 */
createSignal(const QString & path,const QString & interface,const QString & name)376 QDBusMessage 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 */
createTargetedSignal(const QString & service,const QString & path,const QString & interface,const QString & name)400 QDBusMessage 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 */
createMethodCall(const QString & service,const QString & path,const QString & interface,const QString & method)432 QDBusMessage 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 */
createError(const QString & name,const QString & msg)449 QDBusMessage 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 */
createReply(const QVariantList & arguments) const478 QDBusMessage 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)
createErrorReply(const QString & name,const QString & msg) const500 QDBusMessage QDBusMessage::createErrorReply(const QString &name, const QString &msg) const
501 #else
502 QDBusMessage 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 */
createErrorReply(QDBusError::ErrorType atype,const QString & amsg) const538 QDBusMessage 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 */
QDBusMessage()551 QDBusMessage::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 */
QDBusMessage(const QDBusMessage & other)563 QDBusMessage::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 */
~QDBusMessage()572 QDBusMessage::~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 */
operator =(const QDBusMessage & other)585 QDBusMessage &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 */
service() const594 QString 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 */
path() const603 QString 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 */
interface() const612 QString 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 */
member() const620 QString 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 */
errorName() const630 QString 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 */
signature() const641 QString 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 */
isReplyRequired() const652 bool 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 */
setDelayedReply(bool enable) const677 void 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 */
isDelayedReply() const687 bool 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 */
setAutoStartService(bool enable)712 void 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 */
autoStartService() const726 bool 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 */
setInteractiveAuthorizationAllowed(bool enable)749 void 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 */
isInteractiveAuthorizationAllowed() const764 bool 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 */
setArguments(const QList<QVariant> & arguments)775 void 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 */
arguments() const785 QList<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 
operator <<(const QVariant & arg)795 QDBusMessage &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 */
type() const805 QDBusMessage::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
operator <<(QDebug dbg,QDBusMessage::MessageType t)823 static 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 
debugVariantList(QDebug dbg,const QVariantList & list)840 static 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 
operator <<(QDebug dbg,const QDBusMessage & msg)853 QDebug 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 
880 QT_END_NAMESPACE
881 
882 #endif // QT_NO_DBUS
883