1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://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 https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://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 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qdbusargument_p.h" |
41 | #include "qdbusconnection.h" |
42 | #include "qdbusmetatype_p.h" |
43 | #include "qdbusutil_p.h" |
44 | |
45 | #ifndef QT_NO_DBUS |
46 | |
47 | QT_BEGIN_NAMESPACE |
48 | |
49 | static void qIterAppend(DBusMessageIter *it, QByteArray *ba, int type, const void *arg) |
50 | { |
51 | if (ba) |
52 | *ba += char(type); |
53 | else |
54 | q_dbus_message_iter_append_basic(it, type, arg); |
55 | } |
56 | |
57 | QDBusMarshaller::~QDBusMarshaller() |
58 | { |
59 | close(); |
60 | } |
61 | |
62 | inline QString QDBusMarshaller::currentSignature() |
63 | { |
64 | if (message) |
65 | return QString::fromUtf8(q_dbus_message_get_signature(message)); |
66 | return QString(); |
67 | } |
68 | |
69 | inline void QDBusMarshaller::append(uchar arg) |
70 | { |
71 | if (!skipSignature) |
72 | qIterAppend(&iterator, ba, DBUS_TYPE_BYTE, &arg); |
73 | } |
74 | |
75 | inline void QDBusMarshaller::append(bool arg) |
76 | { |
77 | dbus_bool_t cast = arg; |
78 | if (!skipSignature) |
79 | qIterAppend(&iterator, ba, DBUS_TYPE_BOOLEAN, &cast); |
80 | } |
81 | |
82 | inline void QDBusMarshaller::append(short arg) |
83 | { |
84 | if (!skipSignature) |
85 | qIterAppend(&iterator, ba, DBUS_TYPE_INT16, &arg); |
86 | } |
87 | |
88 | inline void QDBusMarshaller::append(ushort arg) |
89 | { |
90 | if (!skipSignature) |
91 | qIterAppend(&iterator, ba, DBUS_TYPE_UINT16, &arg); |
92 | } |
93 | |
94 | inline void QDBusMarshaller::append(int arg) |
95 | { |
96 | if (!skipSignature) |
97 | qIterAppend(&iterator, ba, DBUS_TYPE_INT32, &arg); |
98 | } |
99 | |
100 | inline void QDBusMarshaller::append(uint arg) |
101 | { |
102 | if (!skipSignature) |
103 | qIterAppend(&iterator, ba, DBUS_TYPE_UINT32, &arg); |
104 | } |
105 | |
106 | inline void QDBusMarshaller::append(qlonglong arg) |
107 | { |
108 | if (!skipSignature) |
109 | qIterAppend(&iterator, ba, DBUS_TYPE_INT64, &arg); |
110 | } |
111 | |
112 | inline void QDBusMarshaller::append(qulonglong arg) |
113 | { |
114 | if (!skipSignature) |
115 | qIterAppend(&iterator, ba, DBUS_TYPE_UINT64, &arg); |
116 | } |
117 | |
118 | inline void QDBusMarshaller::append(double arg) |
119 | { |
120 | if (!skipSignature) |
121 | qIterAppend(&iterator, ba, DBUS_TYPE_DOUBLE, &arg); |
122 | } |
123 | |
124 | void QDBusMarshaller::append(const QString &arg) |
125 | { |
126 | QByteArray data = arg.toUtf8(); |
127 | const char *cdata = data.constData(); |
128 | if (!skipSignature) |
129 | qIterAppend(&iterator, ba, DBUS_TYPE_STRING, &cdata); |
130 | } |
131 | |
132 | inline void QDBusMarshaller::append(const QDBusObjectPath &arg) |
133 | { |
134 | QByteArray data = arg.path().toUtf8(); |
135 | if (!ba && data.isEmpty()) { |
136 | error(QLatin1String("Invalid object path passed in arguments" )); |
137 | } else { |
138 | const char *cdata = data.constData(); |
139 | if (!skipSignature) |
140 | qIterAppend(&iterator, ba, DBUS_TYPE_OBJECT_PATH, &cdata); |
141 | } |
142 | } |
143 | |
144 | inline void QDBusMarshaller::append(const QDBusSignature &arg) |
145 | { |
146 | QByteArray data = arg.signature().toUtf8(); |
147 | if (!ba && data.isEmpty()) { |
148 | error(QLatin1String("Invalid signature passed in arguments" )); |
149 | } else { |
150 | const char *cdata = data.constData(); |
151 | if (!skipSignature) |
152 | qIterAppend(&iterator, ba, DBUS_TYPE_SIGNATURE, &cdata); |
153 | } |
154 | } |
155 | |
156 | inline void QDBusMarshaller::append(const QDBusUnixFileDescriptor &arg) |
157 | { |
158 | int fd = arg.fileDescriptor(); |
159 | if (!ba && fd == -1) { |
160 | error(QLatin1String("Invalid file descriptor passed in arguments" )); |
161 | } else { |
162 | if (!skipSignature) |
163 | qIterAppend(&iterator, ba, DBUS_TYPE_UNIX_FD, &fd); |
164 | } |
165 | } |
166 | |
167 | inline void QDBusMarshaller::append(const QByteArray &arg) |
168 | { |
169 | if (ba) { |
170 | if (!skipSignature) |
171 | *ba += DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING; |
172 | return; |
173 | } |
174 | |
175 | const char* cdata = arg.constData(); |
176 | DBusMessageIter subiterator; |
177 | q_dbus_message_iter_open_container(&iterator, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, |
178 | &subiterator); |
179 | q_dbus_message_iter_append_fixed_array(&subiterator, DBUS_TYPE_BYTE, &cdata, arg.length()); |
180 | q_dbus_message_iter_close_container(&iterator, &subiterator); |
181 | } |
182 | |
183 | inline bool QDBusMarshaller::append(const QDBusVariant &arg) |
184 | { |
185 | if (ba) { |
186 | if (!skipSignature) |
187 | *ba += DBUS_TYPE_VARIANT_AS_STRING; |
188 | return true; |
189 | } |
190 | |
191 | const QVariant &value = arg.variant(); |
192 | QMetaType id = value.metaType(); |
193 | if (!id.isValid()) { |
194 | qWarning("QDBusMarshaller: cannot add a null QDBusVariant" ); |
195 | error(QLatin1String("Invalid QVariant passed in arguments" )); |
196 | return false; |
197 | } |
198 | |
199 | QByteArray tmpSignature; |
200 | const char *signature = nullptr; |
201 | if (id == QDBusMetaTypeId::argument()) { |
202 | // take the signature from the QDBusArgument object we're marshalling |
203 | tmpSignature = |
204 | qvariant_cast<QDBusArgument>(value).currentSignature().toLatin1(); |
205 | signature = tmpSignature.constData(); |
206 | } else { |
207 | // take the signatuer from the metatype we're marshalling |
208 | signature = QDBusMetaType::typeToSignature(id); |
209 | } |
210 | if (!signature) { |
211 | qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. " |
212 | "Use qDBusRegisterMetaType to register it" , |
213 | id.name(), id.id()); |
214 | error(QLatin1String("Unregistered type %1 passed in arguments" ) |
215 | .arg(QLatin1String(id.name()))); |
216 | return false; |
217 | } |
218 | |
219 | QDBusMarshaller sub(capabilities); |
220 | open(sub, DBUS_TYPE_VARIANT, signature); |
221 | bool isOk = sub.appendVariantInternal(value); |
222 | // don't call sub.close(): it auto-closes |
223 | |
224 | return isOk; |
225 | } |
226 | |
227 | inline void QDBusMarshaller::append(const QStringList &arg) |
228 | { |
229 | if (ba) { |
230 | if (!skipSignature) |
231 | *ba += DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING; |
232 | return; |
233 | } |
234 | |
235 | QDBusMarshaller sub(capabilities); |
236 | open(sub, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING); |
237 | QStringList::ConstIterator it = arg.constBegin(); |
238 | QStringList::ConstIterator end = arg.constEnd(); |
239 | for ( ; it != end; ++it) |
240 | sub.append(*it); |
241 | // don't call sub.close(): it auto-closes |
242 | } |
243 | |
244 | inline QDBusMarshaller *QDBusMarshaller::beginStructure() |
245 | { |
246 | return beginCommon(DBUS_TYPE_STRUCT, nullptr); |
247 | } |
248 | |
249 | inline QDBusMarshaller *QDBusMarshaller::beginArray(QMetaType id) |
250 | { |
251 | const char *signature = QDBusMetaType::typeToSignature(id); |
252 | if (!signature) { |
253 | qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. " |
254 | "Use qDBusRegisterMetaType to register it" , |
255 | id.name(), id.id()); |
256 | error(QLatin1String("Unregistered type %1 passed in arguments" ) |
257 | .arg(QLatin1String(id.name()))); |
258 | return this; |
259 | } |
260 | |
261 | return beginCommon(DBUS_TYPE_ARRAY, signature); |
262 | } |
263 | |
264 | inline QDBusMarshaller *QDBusMarshaller::beginMap(QMetaType kid, QMetaType vid) |
265 | { |
266 | const char *ksignature = QDBusMetaType::typeToSignature(kid); |
267 | if (!ksignature) { |
268 | qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. " |
269 | "Use qDBusRegisterMetaType to register it" , |
270 | kid.name(), kid.id()); |
271 | error(QLatin1String("Unregistered type %1 passed in arguments" ) |
272 | .arg(QLatin1String(kid.name()))); |
273 | return this; |
274 | } |
275 | if (ksignature[1] != 0 || !QDBusUtil::isValidBasicType(*ksignature)) { |
276 | qWarning("QDBusMarshaller: type '%s' (%d) cannot be used as the key type in a D-BUS map." , |
277 | kid.name(), kid.id()); |
278 | error(QLatin1String("Type %1 passed in arguments cannot be used as a key in a map" ) |
279 | .arg(QLatin1String(kid.name()))); |
280 | return this; |
281 | } |
282 | |
283 | const char *vsignature = QDBusMetaType::typeToSignature(vid); |
284 | if (!vsignature) { |
285 | const char *typeName = vid.name(); |
286 | qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. " |
287 | "Use qDBusRegisterMetaType to register it" , |
288 | typeName, vid.id()); |
289 | error(QLatin1String("Unregistered type %1 passed in arguments" ) |
290 | .arg(QLatin1String(typeName))); |
291 | return this; |
292 | } |
293 | |
294 | QByteArray signature; |
295 | signature = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING; |
296 | signature += ksignature; |
297 | signature += vsignature; |
298 | signature += DBUS_DICT_ENTRY_END_CHAR_AS_STRING; |
299 | return beginCommon(DBUS_TYPE_ARRAY, signature); |
300 | } |
301 | |
302 | inline QDBusMarshaller *QDBusMarshaller::beginMapEntry() |
303 | { |
304 | return beginCommon(DBUS_TYPE_DICT_ENTRY, nullptr); |
305 | } |
306 | |
307 | void QDBusMarshaller::open(QDBusMarshaller &sub, int code, const char *signature) |
308 | { |
309 | sub.parent = this; |
310 | sub.ba = ba; |
311 | sub.ok = true; |
312 | sub.capabilities = capabilities; |
313 | sub.skipSignature = skipSignature; |
314 | |
315 | if (ba) { |
316 | if (!skipSignature) { |
317 | switch (code) { |
318 | case DBUS_TYPE_ARRAY: |
319 | *ba += char(code); |
320 | *ba += signature; |
321 | Q_FALLTHROUGH(); |
322 | |
323 | case DBUS_TYPE_DICT_ENTRY: |
324 | sub.closeCode = 0; |
325 | sub.skipSignature = true; |
326 | break; |
327 | |
328 | case DBUS_TYPE_STRUCT: |
329 | *ba += DBUS_STRUCT_BEGIN_CHAR; |
330 | sub.closeCode = DBUS_STRUCT_END_CHAR; |
331 | break; |
332 | } |
333 | } |
334 | } else { |
335 | q_dbus_message_iter_open_container(&iterator, code, signature, &sub.iterator); |
336 | } |
337 | } |
338 | |
339 | QDBusMarshaller *QDBusMarshaller::beginCommon(int code, const char *signature) |
340 | { |
341 | QDBusMarshaller *d = new QDBusMarshaller(capabilities); |
342 | open(*d, code, signature); |
343 | return d; |
344 | } |
345 | |
346 | inline QDBusMarshaller *QDBusMarshaller::endStructure() |
347 | { return endCommon(); } |
348 | |
349 | inline QDBusMarshaller *QDBusMarshaller::endArray() |
350 | { return endCommon(); } |
351 | |
352 | inline QDBusMarshaller *QDBusMarshaller::endMap() |
353 | { return endCommon(); } |
354 | |
355 | inline QDBusMarshaller *QDBusMarshaller::endMapEntry() |
356 | { return endCommon(); } |
357 | |
358 | QDBusMarshaller *QDBusMarshaller::endCommon() |
359 | { |
360 | QDBusMarshaller *retval = parent; |
361 | delete this; |
362 | return retval; |
363 | } |
364 | |
365 | void QDBusMarshaller::close() |
366 | { |
367 | if (ba) { |
368 | if (!skipSignature && closeCode) |
369 | *ba += closeCode; |
370 | } else if (parent) { |
371 | q_dbus_message_iter_close_container(&parent->iterator, &iterator); |
372 | } |
373 | } |
374 | |
375 | void QDBusMarshaller::error(const QString &msg) |
376 | { |
377 | ok = false; |
378 | if (parent) |
379 | parent->error(msg); |
380 | else |
381 | errorString = msg; |
382 | } |
383 | |
384 | bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) |
385 | { |
386 | QMetaType id = arg.metaType(); |
387 | if (!id.isValid()) { |
388 | qWarning("QDBusMarshaller: cannot add an invalid QVariant" ); |
389 | error(QLatin1String("Invalid QVariant passed in arguments" )); |
390 | return false; |
391 | } |
392 | |
393 | // intercept QDBusArgument parameters here |
394 | if (id == QDBusMetaTypeId::argument()) { |
395 | QDBusArgument dbusargument = qvariant_cast<QDBusArgument>(arg); |
396 | QDBusArgumentPrivate *d = QDBusArgumentPrivate::d(dbusargument); |
397 | if (!d->message) |
398 | return false; // can't append this one... |
399 | |
400 | QDBusDemarshaller demarshaller(capabilities); |
401 | demarshaller.message = q_dbus_message_ref(d->message); |
402 | |
403 | if (d->direction == Demarshalling) { |
404 | // it's demarshalling; just copy |
405 | demarshaller.iterator = static_cast<QDBusDemarshaller *>(d)->iterator; |
406 | } else { |
407 | // it's marshalling; start over |
408 | if (!q_dbus_message_iter_init(demarshaller.message, &demarshaller.iterator)) |
409 | return false; // error! |
410 | } |
411 | |
412 | return appendCrossMarshalling(&demarshaller); |
413 | } |
414 | |
415 | const char *signature = QDBusMetaType::typeToSignature(id); |
416 | if (!signature) { |
417 | qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. " |
418 | "Use qDBusRegisterMetaType to register it" , |
419 | id.name(), id.id()); |
420 | error(QLatin1String("Unregistered type %1 passed in arguments" ) |
421 | .arg(QLatin1String(id.name()))); |
422 | return false; |
423 | } |
424 | |
425 | switch (*signature) { |
426 | #ifdef __OPTIMIZE__ |
427 | case DBUS_TYPE_BYTE: |
428 | case DBUS_TYPE_INT16: |
429 | case DBUS_TYPE_UINT16: |
430 | case DBUS_TYPE_INT32: |
431 | case DBUS_TYPE_UINT32: |
432 | case DBUS_TYPE_INT64: |
433 | case DBUS_TYPE_UINT64: |
434 | case DBUS_TYPE_DOUBLE: |
435 | qIterAppend(&iterator, ba, *signature, arg.constData()); |
436 | return true; |
437 | case DBUS_TYPE_BOOLEAN: |
438 | append( arg.toBool() ); |
439 | return true; |
440 | #else |
441 | case DBUS_TYPE_BYTE: |
442 | append( qvariant_cast<uchar>(arg) ); |
443 | return true; |
444 | case DBUS_TYPE_BOOLEAN: |
445 | append( arg.toBool() ); |
446 | return true; |
447 | case DBUS_TYPE_INT16: |
448 | append( qvariant_cast<short>(arg) ); |
449 | return true; |
450 | case DBUS_TYPE_UINT16: |
451 | append( qvariant_cast<ushort>(arg) ); |
452 | return true; |
453 | case DBUS_TYPE_INT32: |
454 | append( static_cast<dbus_int32_t>(arg.toInt()) ); |
455 | return true; |
456 | case DBUS_TYPE_UINT32: |
457 | append( static_cast<dbus_uint32_t>(arg.toUInt()) ); |
458 | return true; |
459 | case DBUS_TYPE_INT64: |
460 | append( arg.toLongLong() ); |
461 | return true; |
462 | case DBUS_TYPE_UINT64: |
463 | append( arg.toULongLong() ); |
464 | return true; |
465 | case DBUS_TYPE_DOUBLE: |
466 | append( arg.toDouble() ); |
467 | return true; |
468 | #endif |
469 | |
470 | case DBUS_TYPE_STRING: |
471 | append( arg.toString() ); |
472 | return true; |
473 | case DBUS_TYPE_OBJECT_PATH: |
474 | append( qvariant_cast<QDBusObjectPath>(arg) ); |
475 | return true; |
476 | case DBUS_TYPE_SIGNATURE: |
477 | append( qvariant_cast<QDBusSignature>(arg) ); |
478 | return true; |
479 | |
480 | // compound types: |
481 | case DBUS_TYPE_VARIANT: |
482 | // nested QVariant |
483 | return append( qvariant_cast<QDBusVariant>(arg) ); |
484 | |
485 | case DBUS_TYPE_ARRAY: |
486 | // could be many things |
487 | // find out what kind of array it is |
488 | switch (arg.metaType().id()) { |
489 | case QMetaType::QStringList: |
490 | append( arg.toStringList() ); |
491 | return true; |
492 | |
493 | case QMetaType::QByteArray: |
494 | append( arg.toByteArray() ); |
495 | return true; |
496 | |
497 | default: |
498 | ; |
499 | } |
500 | Q_FALLTHROUGH(); |
501 | |
502 | case DBUS_TYPE_STRUCT: |
503 | case DBUS_STRUCT_BEGIN_CHAR: |
504 | return appendRegisteredType( arg ); |
505 | |
506 | case DBUS_TYPE_DICT_ENTRY: |
507 | case DBUS_DICT_ENTRY_BEGIN_CHAR: |
508 | qFatal("QDBusMarshaller::appendVariantInternal got a DICT_ENTRY!" ); |
509 | return false; |
510 | |
511 | case DBUS_TYPE_UNIX_FD: |
512 | if (capabilities & QDBusConnection::UnixFileDescriptorPassing || ba) { |
513 | append(qvariant_cast<QDBusUnixFileDescriptor>(arg)); |
514 | return true; |
515 | } |
516 | Q_FALLTHROUGH(); |
517 | |
518 | default: |
519 | qWarning("QDBusMarshaller::appendVariantInternal: Found unknown D-BUS type '%s'" , |
520 | signature); |
521 | return false; |
522 | } |
523 | |
524 | return true; |
525 | } |
526 | |
527 | bool QDBusMarshaller::appendRegisteredType(const QVariant &arg) |
528 | { |
529 | ref.ref(); // reference up |
530 | QDBusArgument self(QDBusArgumentPrivate::create(this)); |
531 | return QDBusMetaType::marshall(self, arg.metaType(), arg.constData()); |
532 | } |
533 | |
534 | bool QDBusMarshaller::appendCrossMarshalling(QDBusDemarshaller *demarshaller) |
535 | { |
536 | int code = q_dbus_message_iter_get_arg_type(&demarshaller->iterator); |
537 | if (QDBusUtil::isValidBasicType(code)) { |
538 | // easy: just append |
539 | // do exactly like the D-BUS docs suggest |
540 | // (see apidocs for q_dbus_message_iter_get_basic) |
541 | |
542 | qlonglong value; |
543 | q_dbus_message_iter_get_basic(&demarshaller->iterator, &value); |
544 | q_dbus_message_iter_next(&demarshaller->iterator); |
545 | q_dbus_message_iter_append_basic(&iterator, code, &value); |
546 | return true; |
547 | } |
548 | |
549 | if (code == DBUS_TYPE_ARRAY) { |
550 | int element = q_dbus_message_iter_get_element_type(&demarshaller->iterator); |
551 | if (QDBusUtil::isValidFixedType(element) && element != DBUS_TYPE_UNIX_FD) { |
552 | // another optimization: fixed size arrays |
553 | // code is exactly like QDBusDemarshaller::toByteArray |
554 | DBusMessageIter sub; |
555 | q_dbus_message_iter_recurse(&demarshaller->iterator, &sub); |
556 | q_dbus_message_iter_next(&demarshaller->iterator); |
557 | int len; |
558 | void* data; |
559 | q_dbus_message_iter_get_fixed_array(&sub,&data,&len); |
560 | |
561 | char signature[2] = { char(element), 0 }; |
562 | q_dbus_message_iter_open_container(&iterator, DBUS_TYPE_ARRAY, signature, &sub); |
563 | q_dbus_message_iter_append_fixed_array(&sub, element, &data, len); |
564 | q_dbus_message_iter_close_container(&iterator, &sub); |
565 | |
566 | return true; |
567 | } |
568 | } |
569 | |
570 | // We have to recurse |
571 | QDBusDemarshaller *drecursed = demarshaller->beginCommon(); |
572 | |
573 | QDBusMarshaller mrecursed(capabilities); // create on the stack makes it autoclose |
574 | QByteArray subSignature; |
575 | const char *sig = nullptr; |
576 | if (code == DBUS_TYPE_VARIANT || code == DBUS_TYPE_ARRAY) { |
577 | subSignature = drecursed->currentSignature().toLatin1(); |
578 | if (!subSignature.isEmpty()) |
579 | sig = subSignature.constData(); |
580 | } |
581 | open(mrecursed, code, sig); |
582 | |
583 | while (!drecursed->atEnd()) { |
584 | if (!mrecursed.appendCrossMarshalling(drecursed)) { |
585 | delete drecursed; |
586 | return false; |
587 | } |
588 | } |
589 | |
590 | delete drecursed; |
591 | return true; |
592 | } |
593 | |
594 | QT_END_NAMESPACE |
595 | |
596 | #endif // QT_NO_DBUS |
597 | |