Coverage Report

Created: 2026-04-29 07:00

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