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