1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-message.c  DBusMessage object
3  *
4  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
5  * Copyright (C) 2002, 2003  CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24 
25 #include <config.h>
26 #include "dbus-internals.h"
27 #include "dbus-marshal-recursive.h"
28 #include "dbus-marshal-validate.h"
29 #include "dbus-marshal-byteswap.h"
30 #include "dbus-marshal-header.h"
31 #include "dbus-signature.h"
32 #include "dbus-message-private.h"
33 #include "dbus-object-tree.h"
34 #include "dbus-memory.h"
35 #include "dbus-list.h"
36 #include "dbus-threads-internal.h"
37 #ifdef HAVE_UNIX_FD_PASSING
38 #include "dbus-sysdeps.h"
39 #include "dbus-sysdeps-unix.h"
40 #endif
41 
42 #include <string.h>
43 
44 #define _DBUS_TYPE_IS_STRINGLIKE(type) \
45   (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \
46    type == DBUS_TYPE_OBJECT_PATH)
47 
48 static void dbus_message_finalize (DBusMessage *message);
49 
50 /**
51  * @defgroup DBusMessageInternals DBusMessage implementation details
52  * @ingroup DBusInternals
53  * @brief DBusMessage private implementation details.
54  *
55  * The guts of DBusMessage and its methods.
56  *
57  * @{
58  */
59 
60 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
61 static dbus_bool_t
_dbus_enable_message_cache(void)62 _dbus_enable_message_cache (void)
63 {
64   static int enabled = -1;
65 
66   if (enabled < 0)
67     {
68       const char *s = _dbus_getenv ("DBUS_MESSAGE_CACHE");
69 
70       enabled = TRUE;
71 
72       if (s && *s)
73         {
74           if (*s == '0')
75             enabled = FALSE;
76           else if (*s == '1')
77             enabled = TRUE;
78           else
79             _dbus_warn ("DBUS_MESSAGE_CACHE should be 0 or 1 if set, not '%s'",
80                 s);
81         }
82     }
83 
84   return enabled;
85 }
86 #else
87     /* constant expression, should be optimized away */
88 #   define _dbus_enable_message_cache() (TRUE)
89 #endif
90 
91 #ifndef _dbus_message_trace_ref
92 void
_dbus_message_trace_ref(DBusMessage * message,int old_refcount,int new_refcount,const char * why)93 _dbus_message_trace_ref (DBusMessage *message,
94                          int          old_refcount,
95                          int          new_refcount,
96                          const char  *why)
97 {
98   static int enabled = -1;
99 
100   _dbus_trace_ref ("DBusMessage", message, old_refcount, new_refcount, why,
101       "DBUS_MESSAGE_TRACE", &enabled);
102 }
103 #endif
104 
105 /* Not thread locked, but strictly const/read-only so should be OK
106  */
107 /** An static string representing an empty signature */
108 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,  "");
109 
110 /* these have wacky values to help trap uninitialized iterators;
111  * but has to fit in 3 bits
112  */
113 enum {
114   DBUS_MESSAGE_ITER_TYPE_READER = 3,
115   DBUS_MESSAGE_ITER_TYPE_WRITER = 7
116 };
117 
118 /** typedef for internals of message iterator */
119 typedef struct DBusMessageRealIter DBusMessageRealIter;
120 
121 /**
122  * @brief Internals of DBusMessageIter
123  *
124  * Object representing a position in a message. All fields are internal.
125  */
126 struct DBusMessageRealIter
127 {
128   DBusMessage *message; /**< Message used */
129   dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; /**< stamp to detect invalid iters */
130   dbus_uint32_t iter_type : 3;      /**< whether this is a reader or writer iter */
131   dbus_uint32_t sig_refcount : 8;   /**< depth of open_signature() */
132   union
133   {
134     DBusTypeWriter writer; /**< writer */
135     DBusTypeReader reader; /**< reader */
136   } u; /**< the type writer or reader that does all the work */
137 };
138 
139 /**
140  * Layout of a DBusMessageIter on the stack in dbus 1.10.0. This is no
141  * longer used, but for ABI compatibility we need to assert that the
142  * new layout is the same size.
143  */
144 typedef struct
145 {
146   void *dummy1;
147   void *dummy2;
148   dbus_uint32_t dummy3;
149   int dummy4;
150   int dummy5;
151   int dummy6;
152   int dummy7;
153   int dummy8;
154   int dummy9;
155   int dummy10;
156   int dummy11;
157   int pad1;
158   int pad2;
159   void *pad3;
160 } DBusMessageIter_1_10_0;
161 
162 static void
get_const_signature(DBusHeader * header,const DBusString ** type_str_p,int * type_pos_p)163 get_const_signature (DBusHeader        *header,
164                      const DBusString **type_str_p,
165                      int               *type_pos_p)
166 {
167   if (_dbus_header_get_field_raw (header,
168                                   DBUS_HEADER_FIELD_SIGNATURE,
169                                   type_str_p,
170                                   type_pos_p))
171     {
172       *type_pos_p += 1; /* skip the signature length which is 1 byte */
173     }
174   else
175     {
176       *type_str_p = &_dbus_empty_signature_str;
177       *type_pos_p = 0;
178     }
179 }
180 
181 /**
182  * Swaps the message to compiler byte order if required
183  *
184  * @param message the message
185  */
186 static void
_dbus_message_byteswap(DBusMessage * message)187 _dbus_message_byteswap (DBusMessage *message)
188 {
189   const DBusString *type_str;
190   int type_pos;
191   char byte_order;
192 
193   byte_order = _dbus_header_get_byte_order (&message->header);
194 
195   if (byte_order == DBUS_COMPILER_BYTE_ORDER)
196     return;
197 
198   _dbus_verbose ("Swapping message into compiler byte order\n");
199 
200   get_const_signature (&message->header, &type_str, &type_pos);
201 
202   _dbus_marshal_byteswap (type_str, type_pos,
203                           byte_order,
204                           DBUS_COMPILER_BYTE_ORDER,
205                           &message->body, 0);
206 
207   _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
208   _dbus_assert (_dbus_header_get_byte_order (&message->header) ==
209                 DBUS_COMPILER_BYTE_ORDER);
210 }
211 
212 /** byte-swap the message if it doesn't match our byte order.
213  *  Called only when we need the message in our own byte order,
214  *  normally when reading arrays of integers or doubles.
215  *  Otherwise should not be called since it would do needless
216  *  work.
217  */
218 #define ensure_byte_order(message) _dbus_message_byteswap (message)
219 
220 /**
221  * Gets the data to be sent over the network for this message.
222  * The header and then the body should be written out.
223  * This function is guaranteed to always return the same
224  * data once a message is locked (with dbus_message_lock()).
225  *
226  * @param message the message.
227  * @param header return location for message header data.
228  * @param body return location for message body data.
229  */
230 void
_dbus_message_get_network_data(DBusMessage * message,const DBusString ** header,const DBusString ** body)231 _dbus_message_get_network_data (DBusMessage          *message,
232                                 const DBusString    **header,
233                                 const DBusString    **body)
234 {
235   _dbus_assert (message->locked);
236 
237   *header = &message->header.data;
238   *body = &message->body;
239 }
240 
241 /**
242  * Gets the unix fds to be sent over the network for this message.
243  * This function is guaranteed to always return the same data once a
244  * message is locked (with dbus_message_lock()).
245  *
246  * @param message the message.
247  * @param fds return location of unix fd array
248  * @param n_fds return number of entries in array
249  */
_dbus_message_get_unix_fds(DBusMessage * message,const int ** fds,unsigned * n_fds)250 void _dbus_message_get_unix_fds(DBusMessage *message,
251                                 const int  **fds,
252                                 unsigned    *n_fds)
253 {
254   _dbus_assert (message->locked);
255 
256 #ifdef HAVE_UNIX_FD_PASSING
257   *fds = message->unix_fds;
258   *n_fds = message->n_unix_fds;
259 #else
260   *fds = NULL;
261   *n_fds = 0;
262 #endif
263 }
264 
265 /**
266  * Sets the serial number of a message.
267  * This can only be done once on a message.
268  *
269  * DBusConnection will automatically set the serial to an appropriate value
270  * when the message is sent; this function is only needed when encapsulating
271  * messages in another protocol, or otherwise bypassing DBusConnection.
272  *
273  * @param message the message
274  * @param serial the serial
275  */
276 void
dbus_message_set_serial(DBusMessage * message,dbus_uint32_t serial)277 dbus_message_set_serial (DBusMessage   *message,
278                          dbus_uint32_t  serial)
279 {
280   _dbus_return_if_fail (message != NULL);
281   _dbus_return_if_fail (!message->locked);
282 
283   _dbus_header_set_serial (&message->header, serial);
284 }
285 
286 /**
287  * Adds a counter to be incremented immediately with the size/unix fds
288  * of this message, and decremented by the size/unix fds of this
289  * message when this message if finalized.  The link contains a
290  * counter with its refcount already incremented, but the counter
291  * itself not incremented.  Ownership of link and counter refcount is
292  * passed to the message.
293  *
294  * This function may be called with locks held. As a result, the counter's
295  * notify function is not called; the caller is expected to either call
296  * _dbus_counter_notify() on the counter when they are no longer holding
297  * locks, or take the same action that would be taken by the notify function.
298  *
299  * @param message the message
300  * @param link link with counter as data
301  */
302 void
_dbus_message_add_counter_link(DBusMessage * message,DBusList * link)303 _dbus_message_add_counter_link (DBusMessage  *message,
304                                 DBusList     *link)
305 {
306   /* right now we don't recompute the delta when message
307    * size changes, and that's OK for current purposes
308    * I think, but could be important to change later.
309    * Do recompute it whenever there are no outstanding counters,
310    * since it's basically free.
311    */
312   if (message->counters == NULL)
313     {
314       message->size_counter_delta =
315         _dbus_string_get_length (&message->header.data) +
316         _dbus_string_get_length (&message->body);
317 
318 #ifdef HAVE_UNIX_FD_PASSING
319       message->unix_fd_counter_delta = message->n_unix_fds;
320 #endif
321 
322 #if 0
323       _dbus_verbose ("message has size %ld\n",
324                      message->size_counter_delta);
325 #endif
326     }
327 
328   _dbus_list_append_link (&message->counters, link);
329 
330   _dbus_counter_adjust_size (link->data, message->size_counter_delta);
331 
332 #ifdef HAVE_UNIX_FD_PASSING
333   _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
334 #endif
335 }
336 
337 /**
338  * Adds a counter to be incremented immediately with the size/unix fds
339  * of this message, and decremented by the size/unix fds of this
340  * message when this message if finalized.
341  *
342  * This function may be called with locks held. As a result, the counter's
343  * notify function is not called; the caller is expected to either call
344  * _dbus_counter_notify() on the counter when they are no longer holding
345  * locks, or take the same action that would be taken by the notify function.
346  *
347  * @param message the message
348  * @param counter the counter
349  * @returns #FALSE if no memory
350  */
351 dbus_bool_t
_dbus_message_add_counter(DBusMessage * message,DBusCounter * counter)352 _dbus_message_add_counter (DBusMessage *message,
353                            DBusCounter *counter)
354 {
355   DBusList *link;
356 
357   link = _dbus_list_alloc_link (counter);
358   if (link == NULL)
359     return FALSE;
360 
361   _dbus_counter_ref (counter);
362   _dbus_message_add_counter_link (message, link);
363 
364   return TRUE;
365 }
366 
367 /**
368  * Removes a counter tracking the size/unix fds of this message, and
369  * decrements the counter by the size/unix fds of this message.
370  *
371  * @param message the message
372  * @param counter the counter
373  */
374 void
_dbus_message_remove_counter(DBusMessage * message,DBusCounter * counter)375 _dbus_message_remove_counter (DBusMessage  *message,
376                               DBusCounter  *counter)
377 {
378   DBusList *link;
379 
380   link = _dbus_list_find_last (&message->counters,
381                                counter);
382   _dbus_assert (link != NULL);
383 
384   _dbus_list_remove_link (&message->counters, link);
385 
386   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
387 
388 #ifdef HAVE_UNIX_FD_PASSING
389   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
390 #endif
391 
392   _dbus_counter_notify (counter);
393   _dbus_counter_unref (counter);
394 }
395 
396 /**
397  * Locks a message. Allows checking that applications don't keep a
398  * reference to a message in the outgoing queue and change it
399  * underneath us. Messages are locked when they enter the outgoing
400  * queue (dbus_connection_send_message()), and the library complains
401  * if the message is modified while locked. This function may also
402  * called externally, for applications wrapping D-Bus in another protocol.
403  *
404  * @param message the message to lock.
405  */
406 void
dbus_message_lock(DBusMessage * message)407 dbus_message_lock (DBusMessage  *message)
408 {
409   if (!message->locked)
410     {
411       _dbus_header_update_lengths (&message->header,
412                                    _dbus_string_get_length (&message->body));
413 
414       /* must have a signature if you have a body */
415       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
416                     dbus_message_get_signature (message) != NULL);
417 
418       message->locked = TRUE;
419     }
420 }
421 
422 static dbus_bool_t
set_or_delete_string_field(DBusMessage * message,int field,int typecode,const char * value)423 set_or_delete_string_field (DBusMessage *message,
424                             int          field,
425                             int          typecode,
426                             const char  *value)
427 {
428   if (value == NULL)
429     return _dbus_header_delete_field (&message->header, field);
430   else
431     return _dbus_header_set_field_basic (&message->header,
432                                          field,
433                                          typecode,
434                                          &value);
435 }
436 
437 /* Message Cache
438  *
439  * We cache some DBusMessage to reduce the overhead of allocating
440  * them.  In my profiling this consistently made about an 8%
441  * difference.  It avoids the malloc for the message, the malloc for
442  * the slot list, the malloc for the header string and body string,
443  * and the associated free() calls. It does introduce another global
444  * lock which could be a performance issue in certain cases.
445  *
446  * For the echo client/server the round trip time goes from around
447  * .000077 to .000069 with the message cache on my laptop. The sysprof
448  * change is as follows (numbers are cumulative percentage):
449  *
450  *  with message cache implemented as array as it is now (0.000069 per):
451  *    new_empty_header           1.46
452  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
453  *      mutex_unlock             0.25
454  *      self                     0.41
455  *    unref                      2.24
456  *      self                     0.68
457  *      list_clear               0.43
458  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
459  *      mutex_unlock             0.25
460  *
461  *  with message cache implemented as list (0.000070 per roundtrip):
462  *    new_empty_header           2.72
463  *      list_pop_first           1.88
464  *    unref                      3.3
465  *      list_prepend             1.63
466  *
467  * without cache (0.000077 per roundtrip):
468  *    new_empty_header           6.7
469  *      string_init_preallocated 3.43
470  *        dbus_malloc            2.43
471  *      dbus_malloc0             2.59
472  *
473  *    unref                      4.02
474  *      string_free              1.82
475  *        dbus_free              1.63
476  *      dbus_free                0.71
477  *
478  * If you implement the message_cache with a list, the primary reason
479  * it's slower is that you add another thread lock (on the DBusList
480  * mempool).
481  */
482 
483 /** Avoid caching huge messages */
484 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
485 
486 /** Avoid caching too many messages */
487 #define MAX_MESSAGE_CACHE_SIZE    5
488 
489 /* Protected by _DBUS_LOCK (message_cache) */
490 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
491 static int message_cache_count = 0;
492 static dbus_bool_t message_cache_shutdown_registered = FALSE;
493 
494 static void
dbus_message_cache_shutdown(void * data)495 dbus_message_cache_shutdown (void *data)
496 {
497   int i;
498 
499   if (!_DBUS_LOCK (message_cache))
500     _dbus_assert_not_reached ("we would have initialized global locks "
501         "before registering a shutdown function");
502 
503   i = 0;
504   while (i < MAX_MESSAGE_CACHE_SIZE)
505     {
506       if (message_cache[i])
507         dbus_message_finalize (message_cache[i]);
508 
509       ++i;
510     }
511 
512   message_cache_count = 0;
513   message_cache_shutdown_registered = FALSE;
514 
515   _DBUS_UNLOCK (message_cache);
516 }
517 
518 /**
519  * Tries to get a message from the message cache.  The retrieved
520  * message will have junk in it, so it still needs to be cleared out
521  * in dbus_message_new_empty_header()
522  *
523  * @returns the message, or #NULL if none cached
524  */
525 static DBusMessage*
dbus_message_get_cached(void)526 dbus_message_get_cached (void)
527 {
528   DBusMessage *message;
529   int i;
530 
531   message = NULL;
532 
533   if (!_DBUS_LOCK (message_cache))
534     {
535       /* we'd have initialized global locks before caching anything,
536        * so there can't be anything in the cache */
537       return NULL;
538     }
539 
540   _dbus_assert (message_cache_count >= 0);
541 
542   if (message_cache_count == 0)
543     {
544       _DBUS_UNLOCK (message_cache);
545       return NULL;
546     }
547 
548   /* This is not necessarily true unless count > 0, and
549    * message_cache is uninitialized until the shutdown is
550    * registered
551    */
552   _dbus_assert (message_cache_shutdown_registered);
553 
554   i = 0;
555   while (i < MAX_MESSAGE_CACHE_SIZE)
556     {
557       if (message_cache[i])
558         {
559           message = message_cache[i];
560           message_cache[i] = NULL;
561           message_cache_count -= 1;
562           break;
563         }
564       ++i;
565     }
566   _dbus_assert (message_cache_count >= 0);
567   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
568   _dbus_assert (message != NULL);
569 
570   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
571 
572   _dbus_assert (message->counters == NULL);
573 
574   _DBUS_UNLOCK (message_cache);
575 
576   return message;
577 }
578 
579 #ifdef HAVE_UNIX_FD_PASSING
580 static void
close_unix_fds(int * fds,unsigned * n_fds)581 close_unix_fds(int *fds, unsigned *n_fds)
582 {
583   DBusError e;
584   unsigned int i;
585 
586   if (*n_fds <= 0)
587     return;
588 
589   dbus_error_init(&e);
590 
591   for (i = 0; i < *n_fds; i++)
592     {
593       if (!_dbus_close(fds[i], &e))
594         {
595           _dbus_warn("Failed to close file descriptor: %s", e.message);
596           dbus_error_free(&e);
597         }
598     }
599 
600   *n_fds = 0;
601 
602   /* We don't free the array here, in case we can recycle it later */
603 }
604 #endif
605 
606 static void
free_counter(void * element,void * data)607 free_counter (void *element,
608               void *data)
609 {
610   DBusCounter *counter = element;
611   DBusMessage *message = data;
612 
613   _dbus_counter_adjust_size (counter, - message->size_counter_delta);
614 #ifdef HAVE_UNIX_FD_PASSING
615   _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
616 #endif
617 
618   _dbus_counter_notify (counter);
619   _dbus_counter_unref (counter);
620 }
621 
622 /**
623  * Tries to cache a message, otherwise finalize it.
624  *
625  * @param message the message
626  */
627 static void
dbus_message_cache_or_finalize(DBusMessage * message)628 dbus_message_cache_or_finalize (DBusMessage *message)
629 {
630   dbus_bool_t was_cached;
631   int i;
632 
633   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
634 
635   /* This calls application code and has to be done first thing
636    * without holding the lock
637    */
638   _dbus_data_slot_list_clear (&message->slot_list);
639 
640   _dbus_list_foreach (&message->counters,
641                       free_counter, message);
642   _dbus_list_clear (&message->counters);
643 
644 #ifdef HAVE_UNIX_FD_PASSING
645   close_unix_fds(message->unix_fds, &message->n_unix_fds);
646 #endif
647 
648   was_cached = FALSE;
649 
650   if (!_DBUS_LOCK (message_cache))
651     {
652       /* The only way to get a non-null message goes through
653        * dbus_message_get_cached() which takes the lock. */
654       _dbus_assert_not_reached ("we would have initialized global locks "
655           "the first time we constructed a message");
656     }
657 
658   if (!message_cache_shutdown_registered)
659     {
660       _dbus_assert (message_cache_count == 0);
661 
662       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
663         goto out;
664 
665       i = 0;
666       while (i < MAX_MESSAGE_CACHE_SIZE)
667         {
668           message_cache[i] = NULL;
669           ++i;
670         }
671 
672       message_cache_shutdown_registered = TRUE;
673     }
674 
675   _dbus_assert (message_cache_count >= 0);
676 
677   if (!_dbus_enable_message_cache ())
678     goto out;
679 
680   if ((_dbus_string_get_length (&message->header.data) +
681        _dbus_string_get_length (&message->body)) >
682       MAX_MESSAGE_SIZE_TO_CACHE)
683     goto out;
684 
685   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
686     goto out;
687 
688   /* Find empty slot */
689   i = 0;
690   while (message_cache[i] != NULL)
691     ++i;
692 
693   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
694 
695   _dbus_assert (message_cache[i] == NULL);
696   message_cache[i] = message;
697   message_cache_count += 1;
698   was_cached = TRUE;
699 #ifndef DBUS_DISABLE_CHECKS
700   message->in_cache = TRUE;
701 #endif
702 
703  out:
704   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
705 
706   _DBUS_UNLOCK (message_cache);
707 
708   if (!was_cached)
709     dbus_message_finalize (message);
710 }
711 
712 /*
713  * Arrange for iter to be something that _dbus_message_iter_check() would
714  * reject as not a valid iterator.
715  */
716 static void
_dbus_message_real_iter_zero(DBusMessageRealIter * iter)717 _dbus_message_real_iter_zero (DBusMessageRealIter *iter)
718 {
719   _dbus_assert (iter != NULL);
720   _DBUS_ZERO (*iter);
721   /* NULL is not, strictly speaking, guaranteed to be all-bits-zero */
722   iter->message = NULL;
723 }
724 
725 /**
726  * Initialize iter as if with #DBUS_MESSAGE_ITER_INIT_CLOSED. The only valid
727  * operation for such an iterator is
728  * dbus_message_iter_abandon_container_if_open(), which does nothing.
729  */
730 void
dbus_message_iter_init_closed(DBusMessageIter * iter)731 dbus_message_iter_init_closed (DBusMessageIter *iter)
732 {
733   _dbus_return_if_fail (iter != NULL);
734   _dbus_message_real_iter_zero ((DBusMessageRealIter *) iter);
735 }
736 
737 static dbus_bool_t
_dbus_message_real_iter_is_zeroed(DBusMessageRealIter * iter)738 _dbus_message_real_iter_is_zeroed (DBusMessageRealIter *iter)
739 {
740   return (iter != NULL && iter->message == NULL && iter->changed_stamp == 0 &&
741           iter->iter_type == 0 && iter->sig_refcount == 0);
742 }
743 
744 #if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
745 static dbus_bool_t
_dbus_message_iter_check(DBusMessageRealIter * iter)746 _dbus_message_iter_check (DBusMessageRealIter *iter)
747 {
748   char byte_order;
749 
750   if (iter == NULL)
751     {
752       _dbus_warn_check_failed ("dbus message iterator is NULL");
753       return FALSE;
754     }
755 
756   if (iter->message == NULL || iter->iter_type == 0)
757     {
758       _dbus_warn_check_failed ("dbus message iterator has already been "
759                                "closed, or is uninitialized or corrupt");
760       return FALSE;
761     }
762 
763   byte_order = _dbus_header_get_byte_order (&iter->message->header);
764 
765   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
766     {
767       if (iter->u.reader.byte_order != byte_order)
768         {
769           _dbus_warn_check_failed ("dbus message changed byte order since iterator was created");
770           return FALSE;
771         }
772       /* because we swap the message into compiler order when you init an iter */
773       _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
774     }
775   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
776     {
777       if (iter->u.writer.byte_order != byte_order)
778         {
779           _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created");
780           return FALSE;
781         }
782       /* because we swap the message into compiler order when you init an iter */
783       _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
784     }
785   else
786     {
787       _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted");
788       return FALSE;
789     }
790 
791   if (iter->changed_stamp != iter->message->changed_stamp)
792     {
793       _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)");
794       return FALSE;
795     }
796 
797   return TRUE;
798 }
799 #endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */
800 
801 /**
802  * Implementation of the varargs arg-getting functions.
803  * dbus_message_get_args() is the place to go for complete
804  * documentation.
805  *
806  * @see dbus_message_get_args
807  * @param iter the message iter
808  * @param error error to be filled in
809  * @param first_arg_type type of the first argument
810  * @param var_args return location for first argument, followed by list of type/location pairs
811  * @returns #FALSE if error was set
812  */
813 dbus_bool_t
_dbus_message_iter_get_args_valist(DBusMessageIter * iter,DBusError * error,int first_arg_type,va_list var_args)814 _dbus_message_iter_get_args_valist (DBusMessageIter *iter,
815                                     DBusError       *error,
816                                     int              first_arg_type,
817                                     va_list          var_args)
818 {
819   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
820   int spec_type, msg_type, i, j;
821   dbus_bool_t retval;
822   va_list copy_args;
823 
824   _dbus_assert (_dbus_message_iter_check (real));
825 
826   retval = FALSE;
827 
828   spec_type = first_arg_type;
829   i = 0;
830 
831   /* copy var_args first, then we can do another iteration over it to
832    * free memory and close unix fds if parse failed at some point.
833    */
834   DBUS_VA_COPY (copy_args, var_args);
835 
836   while (spec_type != DBUS_TYPE_INVALID)
837     {
838       msg_type = dbus_message_iter_get_arg_type (iter);
839 
840       if (msg_type != spec_type)
841         {
842           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
843                           "Argument %d is specified to be of type \"%s\", but "
844                           "is actually of type \"%s\"\n", i,
845                           _dbus_type_to_string (spec_type),
846                           _dbus_type_to_string (msg_type));
847 
848           goto out;
849         }
850 
851       if (spec_type == DBUS_TYPE_UNIX_FD)
852         {
853 #ifdef HAVE_UNIX_FD_PASSING
854           DBusBasicValue idx;
855           int *pfd, nfd;
856 
857           pfd = va_arg (var_args, int*);
858           _dbus_assert(pfd);
859 
860           _dbus_type_reader_read_basic(&real->u.reader, &idx);
861 
862           if (idx.u32 >= real->message->n_unix_fds)
863             {
864               dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
865                               "Message refers to file descriptor at index %i,"
866                               "but has only %i descriptors attached.\n",
867                               idx.u32,
868                               real->message->n_unix_fds);
869               goto out;
870             }
871 
872           if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
873             goto out;
874 
875           *pfd = nfd;
876 #else
877           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
878                           "Platform does not support file desciptor passing.\n");
879           goto out;
880 #endif
881         }
882       else if (dbus_type_is_basic (spec_type))
883         {
884           DBusBasicValue *ptr;
885 
886           ptr = va_arg (var_args, DBusBasicValue*);
887 
888           _dbus_assert (ptr != NULL);
889 
890           _dbus_type_reader_read_basic (&real->u.reader,
891                                         ptr);
892         }
893       else if (spec_type == DBUS_TYPE_ARRAY)
894         {
895           int element_type;
896           int spec_element_type;
897           const DBusBasicValue **ptr;
898           int *n_elements_p;
899           DBusTypeReader array;
900 
901           spec_element_type = va_arg (var_args, int);
902           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
903 
904           if (spec_element_type != element_type)
905             {
906               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
907                               "Argument %d is specified to be an array of \"%s\", but "
908                               "is actually an array of \"%s\"\n",
909                               i,
910                               _dbus_type_to_string (spec_element_type),
911                               _dbus_type_to_string (element_type));
912 
913               goto out;
914             }
915 
916           if (dbus_type_is_fixed (spec_element_type) &&
917               element_type != DBUS_TYPE_UNIX_FD)
918             {
919               ptr = va_arg (var_args, const DBusBasicValue**);
920               n_elements_p = va_arg (var_args, int*);
921 
922               _dbus_assert (ptr != NULL);
923               _dbus_assert (n_elements_p != NULL);
924 
925               _dbus_type_reader_recurse (&real->u.reader, &array);
926 
927               _dbus_type_reader_read_fixed_multi (&array,
928                                                   (void *) ptr, n_elements_p);
929             }
930           else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
931             {
932               char ***str_array_p;
933               int n_elements;
934               char **str_array;
935 
936               str_array_p = va_arg (var_args, char***);
937               n_elements_p = va_arg (var_args, int*);
938 
939               _dbus_assert (str_array_p != NULL);
940               _dbus_assert (n_elements_p != NULL);
941 
942               /* Count elements in the array */
943               _dbus_type_reader_recurse (&real->u.reader, &array);
944 
945               n_elements = 0;
946               while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
947                 {
948                   ++n_elements;
949                   _dbus_type_reader_next (&array);
950                 }
951 
952               str_array = dbus_new0 (char*, n_elements + 1);
953               if (str_array == NULL)
954                 {
955                   _DBUS_SET_OOM (error);
956                   goto out;
957                 }
958 
959               /* Now go through and dup each string */
960               _dbus_type_reader_recurse (&real->u.reader, &array);
961 
962               j = 0;
963               while (j < n_elements)
964                 {
965                   const char *s;
966                   _dbus_type_reader_read_basic (&array,
967                                                 (void *) &s);
968 
969                   str_array[j] = _dbus_strdup (s);
970                   if (str_array[j] == NULL)
971                     {
972                       dbus_free_string_array (str_array);
973                       _DBUS_SET_OOM (error);
974                       goto out;
975                     }
976 
977                   ++j;
978 
979                   if (!_dbus_type_reader_next (&array))
980                     _dbus_assert (j == n_elements);
981                 }
982 
983               _dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
984               _dbus_assert (j == n_elements);
985               _dbus_assert (str_array[j] == NULL);
986 
987               *str_array_p = str_array;
988               *n_elements_p = n_elements;
989             }
990 #ifndef DBUS_DISABLE_CHECKS
991           else
992             {
993               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now",
994                           _DBUS_FUNCTION_NAME);
995               goto out;
996             }
997 #endif
998         }
999 #ifndef DBUS_DISABLE_CHECKS
1000       else
1001         {
1002           _dbus_warn ("you can only read arrays and basic types with %s for now",
1003                       _DBUS_FUNCTION_NAME);
1004           goto out;
1005         }
1006 #endif
1007 
1008       /* how many arguments already handled */
1009       i++;
1010 
1011       spec_type = va_arg (var_args, int);
1012       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
1013         {
1014           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1015                           "Message has only %d arguments, but more were expected", i);
1016           goto out;
1017         }
1018     }
1019 
1020   retval = TRUE;
1021 
1022  out:
1023   /* there may memory or unix fd leak in the above iteration if parse failed.
1024    * so we have another iteration over copy_args to free memory and close
1025    * unix fds.
1026    */
1027   if (!retval)
1028     {
1029       spec_type = first_arg_type;
1030       j = 0;
1031 
1032       while (j < i)
1033         {
1034           if (spec_type == DBUS_TYPE_UNIX_FD)
1035             {
1036 #ifdef HAVE_UNIX_FD_PASSING
1037               int *pfd;
1038 
1039               pfd = va_arg (copy_args, int *);
1040               _dbus_assert(pfd);
1041               if (*pfd >= 0)
1042                 {
1043                   _dbus_close (*pfd, NULL);
1044                   *pfd = -1;
1045                 }
1046 #endif
1047             }
1048           else if (dbus_type_is_basic (spec_type))
1049             {
1050               /* move the index forward */
1051               va_arg (copy_args, DBusBasicValue *);
1052             }
1053           else if (spec_type == DBUS_TYPE_ARRAY)
1054             {
1055               int spec_element_type;
1056 
1057               spec_element_type = va_arg (copy_args, int);
1058               if (dbus_type_is_fixed (spec_element_type))
1059                 {
1060                   /* move the index forward */
1061                   va_arg (copy_args, const DBusBasicValue **);
1062                   va_arg (copy_args, int *);
1063                 }
1064               else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
1065                 {
1066                   char ***str_array_p;
1067 
1068                   str_array_p = va_arg (copy_args, char ***);
1069                   /* move the index forward */
1070                   va_arg (copy_args, int *);
1071                   _dbus_assert (str_array_p != NULL);
1072                   dbus_free_string_array (*str_array_p);
1073                   *str_array_p = NULL;
1074                 }
1075             }
1076 
1077           spec_type = va_arg (copy_args, int);
1078           j++;
1079         }
1080     }
1081 
1082   va_end (copy_args);
1083   return retval;
1084 }
1085 
1086 /** @} */
1087 
1088 /**
1089  * @defgroup DBusMessage DBusMessage
1090  * @ingroup  DBus
1091  * @brief Message to be sent or received over a #DBusConnection.
1092  *
1093  * A DBusMessage is the most basic unit of communication over a
1094  * DBusConnection. A DBusConnection represents a stream of messages
1095  * received from a remote application, and a stream of messages
1096  * sent to a remote application.
1097  *
1098  * A message has a message type, returned from
1099  * dbus_message_get_type().  This indicates whether the message is a
1100  * method call, a reply to a method call, a signal, or an error reply.
1101  *
1102  * A message has header fields such as the sender, destination, method
1103  * or signal name, and so forth. DBusMessage has accessor functions for
1104  * these, such as dbus_message_get_member().
1105  *
1106  * Convenience functions dbus_message_is_method_call(), dbus_message_is_signal(),
1107  * and dbus_message_is_error() check several header fields at once and are
1108  * slightly more efficient than checking the header fields with individual
1109  * accessor functions.
1110  *
1111  * Finally, a message has arguments. The number and types of arguments
1112  * are in the message's signature header field (accessed with
1113  * dbus_message_get_signature()).  Simple argument values are usually
1114  * retrieved with dbus_message_get_args() but more complex values such
1115  * as structs may require the use of #DBusMessageIter.
1116  *
1117  * The D-Bus specification goes into some more detail about header fields and
1118  * message types.
1119  *
1120  * @{
1121  */
1122 
1123 /**
1124  * @typedef DBusMessage
1125  *
1126  * Opaque data type representing a message received from or to be
1127  * sent to another application.
1128  */
1129 
1130 /**
1131  * Returns the serial of a message or 0 if none has been specified.
1132  * The message's serial number is provided by the application sending
1133  * the message and is used to identify replies to this message.
1134  *
1135  * All messages received on a connection will have a serial provided
1136  * by the remote application.
1137  *
1138  * For messages you're sending, dbus_connection_send() will assign a
1139  * serial and return it to you.
1140  *
1141  * @param message the message
1142  * @returns the serial
1143  */
1144 dbus_uint32_t
dbus_message_get_serial(DBusMessage * message)1145 dbus_message_get_serial (DBusMessage *message)
1146 {
1147   _dbus_return_val_if_fail (message != NULL, 0);
1148 
1149   return _dbus_header_get_serial (&message->header);
1150 }
1151 
1152 /**
1153  * Sets the reply serial of a message (the serial of the message this
1154  * is a reply to).
1155  *
1156  * @param message the message
1157  * @param reply_serial the serial we're replying to
1158  * @returns #FALSE if not enough memory
1159  */
1160 dbus_bool_t
dbus_message_set_reply_serial(DBusMessage * message,dbus_uint32_t reply_serial)1161 dbus_message_set_reply_serial (DBusMessage   *message,
1162                                dbus_uint32_t  reply_serial)
1163 {
1164   DBusBasicValue value;
1165 
1166   _dbus_return_val_if_fail (message != NULL, FALSE);
1167   _dbus_return_val_if_fail (!message->locked, FALSE);
1168   _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
1169 
1170   value.u32 = reply_serial;
1171 
1172   return _dbus_header_set_field_basic (&message->header,
1173                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
1174                                        DBUS_TYPE_UINT32,
1175                                        &value);
1176 }
1177 
1178 /**
1179  * Returns the serial that the message is a reply to or 0 if none.
1180  *
1181  * @param message the message
1182  * @returns the reply serial
1183  */
1184 dbus_uint32_t
dbus_message_get_reply_serial(DBusMessage * message)1185 dbus_message_get_reply_serial  (DBusMessage *message)
1186 {
1187   dbus_uint32_t v_UINT32;
1188 
1189   _dbus_return_val_if_fail (message != NULL, 0);
1190 
1191   if (_dbus_header_get_field_basic (&message->header,
1192                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
1193                                     DBUS_TYPE_UINT32,
1194                                     &v_UINT32))
1195     return v_UINT32;
1196   else
1197     return 0;
1198 }
1199 
1200 static void
dbus_message_finalize(DBusMessage * message)1201 dbus_message_finalize (DBusMessage *message)
1202 {
1203   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1204 
1205   /* This calls application callbacks! */
1206   _dbus_data_slot_list_free (&message->slot_list);
1207 
1208   _dbus_list_foreach (&message->counters,
1209                       free_counter, message);
1210   _dbus_list_clear (&message->counters);
1211 
1212   _dbus_header_free (&message->header);
1213   _dbus_string_free (&message->body);
1214 
1215 #ifdef HAVE_UNIX_FD_PASSING
1216   close_unix_fds(message->unix_fds, &message->n_unix_fds);
1217   dbus_free(message->unix_fds);
1218 #endif
1219 
1220   _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1221 
1222   dbus_free (message);
1223 }
1224 
1225 static DBusMessage*
dbus_message_new_empty_header(void)1226 dbus_message_new_empty_header (void)
1227 {
1228   DBusMessage *message;
1229   dbus_bool_t from_cache;
1230 
1231   message = dbus_message_get_cached ();
1232 
1233   if (message != NULL)
1234     {
1235       from_cache = TRUE;
1236     }
1237   else
1238     {
1239       from_cache = FALSE;
1240       message = dbus_new0 (DBusMessage, 1);
1241       if (message == NULL)
1242         return NULL;
1243 #ifndef DBUS_DISABLE_CHECKS
1244       message->generation = _dbus_current_generation;
1245 #endif
1246 
1247 #ifdef HAVE_UNIX_FD_PASSING
1248       message->unix_fds = NULL;
1249       message->n_unix_fds_allocated = 0;
1250 #endif
1251     }
1252 
1253   _dbus_atomic_inc (&message->refcount);
1254 
1255   _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
1256 
1257   message->locked = FALSE;
1258 #ifndef DBUS_DISABLE_CHECKS
1259   message->in_cache = FALSE;
1260 #endif
1261   message->counters = NULL;
1262   message->size_counter_delta = 0;
1263   message->changed_stamp = 0;
1264 
1265 #ifdef HAVE_UNIX_FD_PASSING
1266   message->n_unix_fds = 0;
1267   message->n_unix_fds_allocated = 0;
1268   message->unix_fd_counter_delta = 0;
1269 #endif
1270 
1271   if (!from_cache)
1272     _dbus_data_slot_list_init (&message->slot_list);
1273 
1274   if (from_cache)
1275     {
1276       _dbus_header_reinit (&message->header);
1277       _dbus_string_set_length (&message->body, 0);
1278     }
1279   else
1280     {
1281       if (!_dbus_header_init (&message->header))
1282         {
1283           dbus_free (message);
1284           return NULL;
1285         }
1286 
1287       if (!_dbus_string_init_preallocated (&message->body, 32))
1288         {
1289           _dbus_header_free (&message->header);
1290           dbus_free (message);
1291           return NULL;
1292         }
1293     }
1294 
1295   return message;
1296 }
1297 
1298 /**
1299  * Constructs a new message of the given message type.
1300  * Types include #DBUS_MESSAGE_TYPE_METHOD_CALL,
1301  * #DBUS_MESSAGE_TYPE_SIGNAL, and so forth.
1302  *
1303  * Usually you want to use dbus_message_new_method_call(),
1304  * dbus_message_new_method_return(), dbus_message_new_signal(),
1305  * or dbus_message_new_error() instead.
1306  *
1307  * @param message_type type of message
1308  * @returns new message or #NULL if no memory
1309  */
1310 DBusMessage*
dbus_message_new(int message_type)1311 dbus_message_new (int message_type)
1312 {
1313   DBusMessage *message;
1314 
1315   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
1316 
1317   message = dbus_message_new_empty_header ();
1318   if (message == NULL)
1319     return NULL;
1320 
1321   if (!_dbus_header_create (&message->header,
1322                             DBUS_COMPILER_BYTE_ORDER,
1323                             message_type,
1324                             NULL, NULL, NULL, NULL, NULL))
1325     {
1326       dbus_message_unref (message);
1327       return NULL;
1328     }
1329 
1330   return message;
1331 }
1332 
1333 /**
1334  * Constructs a new message to invoke a method on a remote
1335  * object. Returns #NULL if memory can't be allocated for the
1336  * message. The destination may be #NULL in which case no destination
1337  * is set; this is appropriate when using D-Bus in a peer-to-peer
1338  * context (no message bus). The interface may be #NULL, which means
1339  * that if multiple methods with the given name exist it is undefined
1340  * which one will be invoked.
1341  *
1342  * The path and method names may not be #NULL.
1343  *
1344  * Destination, path, interface, and method name can't contain
1345  * any invalid characters (see the D-Bus specification).
1346  *
1347  * @param destination name that the message should be sent to or #NULL
1348  * @param path object path the message should be sent to
1349  * @param iface interface to invoke method on, or #NULL
1350  * @param method method to invoke
1351  *
1352  * @returns a new DBusMessage, free with dbus_message_unref()
1353  */
1354 DBusMessage*
dbus_message_new_method_call(const char * destination,const char * path,const char * iface,const char * method)1355 dbus_message_new_method_call (const char *destination,
1356                               const char *path,
1357                               const char *iface,
1358                               const char *method)
1359 {
1360   DBusMessage *message;
1361 
1362   _dbus_return_val_if_fail (path != NULL, NULL);
1363   _dbus_return_val_if_fail (method != NULL, NULL);
1364   _dbus_return_val_if_fail (destination == NULL ||
1365                             _dbus_check_is_valid_bus_name (destination), NULL);
1366   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1367   _dbus_return_val_if_fail (iface == NULL ||
1368                             _dbus_check_is_valid_interface (iface), NULL);
1369   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
1370 
1371   message = dbus_message_new_empty_header ();
1372   if (message == NULL)
1373     return NULL;
1374 
1375   if (!_dbus_header_create (&message->header,
1376                             DBUS_COMPILER_BYTE_ORDER,
1377                             DBUS_MESSAGE_TYPE_METHOD_CALL,
1378                             destination, path, iface, method, NULL))
1379     {
1380       dbus_message_unref (message);
1381       return NULL;
1382     }
1383 
1384   return message;
1385 }
1386 
1387 /**
1388  * Constructs a message that is a reply to a method call. Returns
1389  * #NULL if memory can't be allocated for the message.
1390  *
1391  * @param method_call the message being replied to
1392  * @returns a new DBusMessage, free with dbus_message_unref()
1393  */
1394 DBusMessage*
dbus_message_new_method_return(DBusMessage * method_call)1395 dbus_message_new_method_return (DBusMessage *method_call)
1396 {
1397   DBusMessage *message;
1398   const char *sender;
1399 
1400   _dbus_return_val_if_fail (method_call != NULL, NULL);
1401 
1402   sender = dbus_message_get_sender (method_call);
1403 
1404   /* sender is allowed to be null here in peer-to-peer case */
1405 
1406   message = dbus_message_new_empty_header ();
1407   if (message == NULL)
1408     return NULL;
1409 
1410   if (!_dbus_header_create (&message->header,
1411                             DBUS_COMPILER_BYTE_ORDER,
1412                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
1413                             sender, NULL, NULL, NULL, NULL))
1414     {
1415       dbus_message_unref (message);
1416       return NULL;
1417     }
1418 
1419   dbus_message_set_no_reply (message, TRUE);
1420 
1421   if (!dbus_message_set_reply_serial (message,
1422                                       dbus_message_get_serial (method_call)))
1423     {
1424       dbus_message_unref (message);
1425       return NULL;
1426     }
1427 
1428   return message;
1429 }
1430 
1431 /**
1432  * Constructs a new message representing a signal emission. Returns
1433  * #NULL if memory can't be allocated for the message.  A signal is
1434  * identified by its originating object path, interface, and the name
1435  * of the signal.
1436  *
1437  * Path, interface, and signal name must all be valid (the D-Bus
1438  * specification defines the syntax of these fields).
1439  *
1440  * @param path the path to the object emitting the signal
1441  * @param iface the interface the signal is emitted from
1442  * @param name name of the signal
1443  * @returns a new DBusMessage, free with dbus_message_unref()
1444  */
1445 DBusMessage*
dbus_message_new_signal(const char * path,const char * iface,const char * name)1446 dbus_message_new_signal (const char *path,
1447                          const char *iface,
1448                          const char *name)
1449 {
1450   DBusMessage *message;
1451 
1452   _dbus_return_val_if_fail (path != NULL, NULL);
1453   _dbus_return_val_if_fail (iface != NULL, NULL);
1454   _dbus_return_val_if_fail (name != NULL, NULL);
1455   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1456   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
1457   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
1458 
1459   message = dbus_message_new_empty_header ();
1460   if (message == NULL)
1461     return NULL;
1462 
1463   if (!_dbus_header_create (&message->header,
1464                             DBUS_COMPILER_BYTE_ORDER,
1465                             DBUS_MESSAGE_TYPE_SIGNAL,
1466                             NULL, path, iface, name, NULL))
1467     {
1468       dbus_message_unref (message);
1469       return NULL;
1470     }
1471 
1472   dbus_message_set_no_reply (message, TRUE);
1473 
1474   return message;
1475 }
1476 
1477 /**
1478  * Creates a new message that is an error reply to another message.
1479  * Error replies are most common in response to method calls, but
1480  * can be returned in reply to any message.
1481  *
1482  * The error name must be a valid error name according to the syntax
1483  * given in the D-Bus specification. If you don't want to make
1484  * up an error name just use #DBUS_ERROR_FAILED.
1485  *
1486  * @param reply_to the message we're replying to
1487  * @param error_name the error name
1488  * @param error_message the error message string (or #NULL for none, but please give a message)
1489  * @returns a new error message object, free with dbus_message_unref()
1490  */
1491 DBusMessage*
dbus_message_new_error(DBusMessage * reply_to,const char * error_name,const char * error_message)1492 dbus_message_new_error (DBusMessage *reply_to,
1493                         const char  *error_name,
1494                         const char  *error_message)
1495 {
1496   DBusMessage *message;
1497   const char *sender;
1498   DBusMessageIter iter;
1499 
1500   _dbus_return_val_if_fail (reply_to != NULL, NULL);
1501   _dbus_return_val_if_fail (error_name != NULL, NULL);
1502   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1503 
1504   sender = dbus_message_get_sender (reply_to);
1505 
1506   /* sender may be NULL for non-message-bus case or
1507    * when the message bus is dealing with an unregistered
1508    * connection.
1509    */
1510   message = dbus_message_new_empty_header ();
1511   if (message == NULL)
1512     return NULL;
1513 
1514   if (!_dbus_header_create (&message->header,
1515                             DBUS_COMPILER_BYTE_ORDER,
1516                             DBUS_MESSAGE_TYPE_ERROR,
1517                             sender, NULL, NULL, NULL, error_name))
1518     {
1519       dbus_message_unref (message);
1520       return NULL;
1521     }
1522 
1523   dbus_message_set_no_reply (message, TRUE);
1524 
1525   if (!dbus_message_set_reply_serial (message,
1526                                       dbus_message_get_serial (reply_to)))
1527     {
1528       dbus_message_unref (message);
1529       return NULL;
1530     }
1531 
1532   if (error_message != NULL)
1533     {
1534       dbus_message_iter_init_append (message, &iter);
1535       if (!dbus_message_iter_append_basic (&iter,
1536                                            DBUS_TYPE_STRING,
1537                                            &error_message))
1538         {
1539           dbus_message_unref (message);
1540           return NULL;
1541         }
1542     }
1543 
1544   return message;
1545 }
1546 
1547 /**
1548  * Creates a new message that is an error reply to another message, allowing
1549  * you to use printf formatting.
1550  *
1551  * See dbus_message_new_error() for details - this function is the same
1552  * aside from the printf formatting.
1553  *
1554  * @todo add _DBUS_GNUC_PRINTF to this (requires moving _DBUS_GNUC_PRINTF to
1555  * public header, see DBUS_DEPRECATED for an example)
1556  *
1557  * @param reply_to the original message
1558  * @param error_name the error name
1559  * @param error_format the error message format as with printf
1560  * @param ... format string arguments
1561  * @returns a new error message
1562  */
1563 DBusMessage*
dbus_message_new_error_printf(DBusMessage * reply_to,const char * error_name,const char * error_format,...)1564 dbus_message_new_error_printf (DBusMessage *reply_to,
1565 			       const char  *error_name,
1566 			       const char  *error_format,
1567 			       ...)
1568 {
1569   va_list args;
1570   DBusString str;
1571   DBusMessage *message;
1572 
1573   _dbus_return_val_if_fail (reply_to != NULL, NULL);
1574   _dbus_return_val_if_fail (error_name != NULL, NULL);
1575   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1576 
1577   if (!_dbus_string_init (&str))
1578     return NULL;
1579 
1580   va_start (args, error_format);
1581 
1582   if (_dbus_string_append_printf_valist (&str, error_format, args))
1583     message = dbus_message_new_error (reply_to, error_name,
1584 				      _dbus_string_get_const_data (&str));
1585   else
1586     message = NULL;
1587 
1588   _dbus_string_free (&str);
1589 
1590   va_end (args);
1591 
1592   return message;
1593 }
1594 
1595 
1596 /**
1597  * Creates a new message that is an exact replica of the message
1598  * specified, except that its refcount is set to 1, its message serial
1599  * is reset to 0, and if the original message was "locked" (in the
1600  * outgoing message queue and thus not modifiable) the new message
1601  * will not be locked.
1602  *
1603  * @todo This function can't be used in programs that try to recover from OOM errors.
1604  *
1605  * @param message the message
1606  * @returns the new message.or #NULL if not enough memory or Unix file descriptors (in case the message to copy includes Unix file descriptors) can be allocated.
1607  */
1608 DBusMessage *
dbus_message_copy(const DBusMessage * message)1609 dbus_message_copy (const DBusMessage *message)
1610 {
1611   DBusMessage *retval;
1612 
1613   _dbus_return_val_if_fail (message != NULL, NULL);
1614 
1615   retval = dbus_new0 (DBusMessage, 1);
1616   if (retval == NULL)
1617     return NULL;
1618 
1619   _dbus_atomic_inc (&retval->refcount);
1620 
1621   retval->locked = FALSE;
1622 #ifndef DBUS_DISABLE_CHECKS
1623   retval->generation = message->generation;
1624 #endif
1625 
1626   if (!_dbus_header_copy (&message->header, &retval->header))
1627     {
1628       dbus_free (retval);
1629       return NULL;
1630     }
1631 
1632   if (!_dbus_string_init_preallocated (&retval->body,
1633                                        _dbus_string_get_length (&message->body)))
1634     {
1635       _dbus_header_free (&retval->header);
1636       dbus_free (retval);
1637       return NULL;
1638     }
1639 
1640   if (!_dbus_string_copy (&message->body, 0,
1641 			  &retval->body, 0))
1642     goto failed_copy;
1643 
1644 #ifdef HAVE_UNIX_FD_PASSING
1645   retval->unix_fds = dbus_new(int, message->n_unix_fds);
1646   if (retval->unix_fds == NULL && message->n_unix_fds > 0)
1647     goto failed_copy;
1648 
1649   retval->n_unix_fds_allocated = message->n_unix_fds;
1650 
1651   for (retval->n_unix_fds = 0;
1652        retval->n_unix_fds < message->n_unix_fds;
1653        retval->n_unix_fds++)
1654     {
1655       retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
1656 
1657       if (retval->unix_fds[retval->n_unix_fds] < 0)
1658         goto failed_copy;
1659     }
1660 
1661 #endif
1662 
1663   _dbus_message_trace_ref (retval, 0, 1, "copy");
1664   return retval;
1665 
1666  failed_copy:
1667   _dbus_header_free (&retval->header);
1668   _dbus_string_free (&retval->body);
1669 
1670 #ifdef HAVE_UNIX_FD_PASSING
1671   close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
1672   dbus_free(retval->unix_fds);
1673 #endif
1674 
1675   dbus_free (retval);
1676 
1677   return NULL;
1678 }
1679 
1680 
1681 /**
1682  * Increments the reference count of a DBusMessage.
1683  *
1684  * @param message the message
1685  * @returns the message
1686  * @see dbus_message_unref
1687  */
1688 DBusMessage *
dbus_message_ref(DBusMessage * message)1689 dbus_message_ref (DBusMessage *message)
1690 {
1691   dbus_int32_t old_refcount;
1692 
1693   _dbus_return_val_if_fail (message != NULL, NULL);
1694   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
1695   _dbus_return_val_if_fail (!message->in_cache, NULL);
1696 
1697   old_refcount = _dbus_atomic_inc (&message->refcount);
1698   _dbus_assert (old_refcount >= 1);
1699   _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
1700 
1701   return message;
1702 }
1703 
1704 /**
1705  * Decrements the reference count of a DBusMessage, freeing the
1706  * message if the count reaches 0.
1707  *
1708  * @param message the message
1709  * @see dbus_message_ref
1710  */
1711 void
dbus_message_unref(DBusMessage * message)1712 dbus_message_unref (DBusMessage *message)
1713 {
1714  dbus_int32_t old_refcount;
1715 
1716   _dbus_return_if_fail (message != NULL);
1717   _dbus_return_if_fail (message->generation == _dbus_current_generation);
1718   _dbus_return_if_fail (!message->in_cache);
1719 
1720   old_refcount = _dbus_atomic_dec (&message->refcount);
1721 
1722   _dbus_assert (old_refcount >= 1);
1723 
1724   _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
1725 
1726   if (old_refcount == 1)
1727     {
1728       /* Calls application callbacks! */
1729       dbus_message_cache_or_finalize (message);
1730     }
1731 }
1732 
1733 /**
1734  * Gets the type of a message. Types include
1735  * #DBUS_MESSAGE_TYPE_METHOD_CALL, #DBUS_MESSAGE_TYPE_METHOD_RETURN,
1736  * #DBUS_MESSAGE_TYPE_ERROR, #DBUS_MESSAGE_TYPE_SIGNAL, but other
1737  * types are allowed and all code must silently ignore messages of
1738  * unknown type. #DBUS_MESSAGE_TYPE_INVALID will never be returned.
1739  *
1740  * @param message the message
1741  * @returns the type of the message
1742  */
1743 int
dbus_message_get_type(DBusMessage * message)1744 dbus_message_get_type (DBusMessage *message)
1745 {
1746   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
1747 
1748   return _dbus_header_get_message_type (&message->header);
1749 }
1750 
1751 /**
1752  * Appends fields to a message given a variable argument list. The
1753  * variable argument list should contain the type of each argument
1754  * followed by the value to append. Appendable types are basic types,
1755  * and arrays of fixed-length basic types (except arrays of Unix file
1756  * descriptors). To append variable-length basic types, or any more
1757  * complex value, you have to use an iterator rather than this
1758  * function.
1759  *
1760  * To append a basic type, specify its type code followed by the
1761  * address of the value. For example:
1762  *
1763  * @code
1764  *
1765  * dbus_int32_t v_INT32 = 42;
1766  * const char *v_STRING = "Hello World";
1767  * dbus_message_append_args (message,
1768  *                           DBUS_TYPE_INT32, &v_INT32,
1769  *                           DBUS_TYPE_STRING, &v_STRING,
1770  *                           DBUS_TYPE_INVALID);
1771  * @endcode
1772  *
1773  * To append an array of fixed-length basic types (except Unix file
1774  * descriptors), pass in the DBUS_TYPE_ARRAY typecode, the element
1775  * typecode, the address of the array pointer, and a 32-bit integer
1776  * giving the number of elements in the array. So for example:
1777  *
1778  * @code
1779  *
1780  * const dbus_int32_t array[] = { 1, 2, 3 };
1781  * const dbus_int32_t *v_ARRAY = array;
1782  * dbus_message_append_args (message,
1783  *                           DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY, 3,
1784  *                           DBUS_TYPE_INVALID);
1785  *
1786  * @endcode
1787  *
1788  * This function does not support arrays of Unix file descriptors. If
1789  * you need those you need to manually recurse into the array.
1790  *
1791  * For Unix file descriptors this function will internally duplicate
1792  * the descriptor you passed in. Hence you may close the descriptor
1793  * immediately after this call.
1794  *
1795  * @warning in C, given "int array[]", "&array == array" (the
1796  * comp.lang.c FAQ says otherwise, but gcc and the FAQ don't agree).
1797  * So if you're using an array instead of a pointer you have to create
1798  * a pointer variable, assign the array to it, then take the address
1799  * of the pointer variable. For strings it works to write
1800  * const char *array = "Hello" and then use &array though.
1801  *
1802  * The last argument to this function must be #DBUS_TYPE_INVALID,
1803  * marking the end of the argument list. If you don't do this
1804  * then libdbus won't know to stop and will read invalid memory.
1805  *
1806  * String/signature/path arrays should be passed in as "const char***
1807  * address_of_array" and "int n_elements"
1808  *
1809  * @todo support DBUS_TYPE_STRUCT and DBUS_TYPE_VARIANT and complex arrays
1810  *
1811  * @todo If this fails due to lack of memory, the message is hosed and
1812  * you have to start over building the whole message.
1813  *
1814  * @param message the message
1815  * @param first_arg_type type of the first argument
1816  * @param ... value of first argument, list of additional type-value pairs
1817  * @returns #TRUE on success
1818  */
1819 dbus_bool_t
dbus_message_append_args(DBusMessage * message,int first_arg_type,...)1820 dbus_message_append_args (DBusMessage *message,
1821 			  int          first_arg_type,
1822 			  ...)
1823 {
1824   dbus_bool_t retval;
1825   va_list var_args;
1826 
1827   _dbus_return_val_if_fail (message != NULL, FALSE);
1828 
1829   va_start (var_args, first_arg_type);
1830   retval = dbus_message_append_args_valist (message,
1831 					    first_arg_type,
1832 					    var_args);
1833   va_end (var_args);
1834 
1835   return retval;
1836 }
1837 
1838 /**
1839  * Like dbus_message_append_args() but takes a va_list for use by language bindings.
1840  *
1841  * @todo for now, if this function fails due to OOM it will leave
1842  * the message half-written and you have to discard the message
1843  * and start over.
1844  *
1845  * @see dbus_message_append_args.
1846  * @param message the message
1847  * @param first_arg_type type of first argument
1848  * @param var_args value of first argument, then list of type/value pairs
1849  * @returns #TRUE on success
1850  */
1851 dbus_bool_t
dbus_message_append_args_valist(DBusMessage * message,int first_arg_type,va_list var_args)1852 dbus_message_append_args_valist (DBusMessage *message,
1853 				 int          first_arg_type,
1854 				 va_list      var_args)
1855 {
1856   int type;
1857   DBusMessageIter iter;
1858 
1859   _dbus_return_val_if_fail (message != NULL, FALSE);
1860 
1861   type = first_arg_type;
1862 
1863   dbus_message_iter_init_append (message, &iter);
1864 
1865   while (type != DBUS_TYPE_INVALID)
1866     {
1867       if (dbus_type_is_basic (type))
1868         {
1869           const DBusBasicValue *value;
1870           value = va_arg (var_args, const DBusBasicValue*);
1871 
1872           if (!dbus_message_iter_append_basic (&iter,
1873                                                type,
1874                                                value))
1875             goto failed;
1876         }
1877       else if (type == DBUS_TYPE_ARRAY)
1878         {
1879           int element_type;
1880           DBusMessageIter array;
1881           char buf[2];
1882 
1883           element_type = va_arg (var_args, int);
1884 
1885           buf[0] = element_type;
1886           buf[1] = '\0';
1887           if (!dbus_message_iter_open_container (&iter,
1888                                                  DBUS_TYPE_ARRAY,
1889                                                  buf,
1890                                                  &array))
1891             goto failed;
1892 
1893           if (dbus_type_is_fixed (element_type) &&
1894               element_type != DBUS_TYPE_UNIX_FD)
1895             {
1896               const DBusBasicValue **value;
1897               int n_elements;
1898 
1899               value = va_arg (var_args, const DBusBasicValue**);
1900               n_elements = va_arg (var_args, int);
1901 
1902               if (!dbus_message_iter_append_fixed_array (&array,
1903                                                          element_type,
1904                                                          value,
1905                                                          n_elements)) {
1906                 dbus_message_iter_abandon_container (&iter, &array);
1907                 goto failed;
1908               }
1909             }
1910           else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
1911             {
1912               const char ***value_p;
1913               const char **value;
1914               int n_elements;
1915               int i;
1916 
1917               value_p = va_arg (var_args, const char***);
1918               n_elements = va_arg (var_args, int);
1919 
1920               value = *value_p;
1921 
1922               i = 0;
1923               while (i < n_elements)
1924                 {
1925                   if (!dbus_message_iter_append_basic (&array,
1926                                                        element_type,
1927                                                        &value[i])) {
1928                     dbus_message_iter_abandon_container (&iter, &array);
1929                     goto failed;
1930                   }
1931                   ++i;
1932                 }
1933             }
1934           else
1935             {
1936               _dbus_warn ("arrays of %s can't be appended with %s for now",
1937                           _dbus_type_to_string (element_type),
1938                           _DBUS_FUNCTION_NAME);
1939               dbus_message_iter_abandon_container (&iter, &array);
1940               goto failed;
1941             }
1942 
1943           if (!dbus_message_iter_close_container (&iter, &array))
1944             goto failed;
1945         }
1946 #ifndef DBUS_DISABLE_CHECKS
1947       else
1948         {
1949           _dbus_warn ("type %s isn't supported yet in %s",
1950                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
1951           goto failed;
1952         }
1953 #endif
1954 
1955       type = va_arg (var_args, int);
1956     }
1957 
1958   return TRUE;
1959 
1960  failed:
1961   return FALSE;
1962 }
1963 
1964 /**
1965  * Gets arguments from a message given a variable argument list.  The
1966  * supported types include those supported by
1967  * dbus_message_append_args(); that is, basic types and arrays of
1968  * fixed-length basic types.  The arguments are the same as they would
1969  * be for dbus_message_iter_get_basic() or
1970  * dbus_message_iter_get_fixed_array().
1971  *
1972  * In addition to those types, arrays of string, object path, and
1973  * signature are supported; but these are returned as allocated memory
1974  * and must be freed with dbus_free_string_array(), while the other
1975  * types are returned as const references. To get a string array
1976  * pass in "char ***array_location" and "int *n_elements".
1977  *
1978  * Similar to dbus_message_get_fixed_array() this function does not
1979  * support arrays of type DBUS_TYPE_UNIX_FD. If you need to parse
1980  * messages with arrays of Unix file descriptors you need to recurse
1981  * into the array manually.
1982  *
1983  * Unix file descriptors that are read with this function will have
1984  * the FD_CLOEXEC flag set. If you need them without this flag set,
1985  * make sure to unset it with fcntl().
1986  *
1987  * The variable argument list should contain the type of the argument
1988  * followed by a pointer to where the value should be stored. The list
1989  * is terminated with #DBUS_TYPE_INVALID.
1990  *
1991  * Except for string arrays, the returned values are constant; do not
1992  * free them. They point into the #DBusMessage.
1993  *
1994  * If the requested arguments are not present, or do not have the
1995  * requested types, then an error will be set.
1996  *
1997  * If more arguments than requested are present, the requested
1998  * arguments are returned and the extra arguments are ignored.
1999  *
2000  * @todo support DBUS_TYPE_STRUCT and DBUS_TYPE_VARIANT and complex arrays
2001  *
2002  * @param message the message
2003  * @param error error to be filled in on failure
2004  * @param first_arg_type the first argument type
2005  * @param ... location for first argument value, then list of type-location pairs
2006  * @returns #FALSE if the error was set
2007  */
2008 dbus_bool_t
dbus_message_get_args(DBusMessage * message,DBusError * error,int first_arg_type,...)2009 dbus_message_get_args (DBusMessage     *message,
2010                        DBusError       *error,
2011 		       int              first_arg_type,
2012 		       ...)
2013 {
2014   dbus_bool_t retval;
2015   va_list var_args;
2016 
2017   _dbus_return_val_if_fail (message != NULL, FALSE);
2018   _dbus_return_val_if_error_is_set (error, FALSE);
2019 
2020   va_start (var_args, first_arg_type);
2021   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
2022   va_end (var_args);
2023 
2024   return retval;
2025 }
2026 
2027 /**
2028  * Like dbus_message_get_args but takes a va_list for use by language bindings.
2029  *
2030  * @see dbus_message_get_args
2031  * @param message the message
2032  * @param error error to be filled in
2033  * @param first_arg_type type of the first argument
2034  * @param var_args return location for first argument, followed by list of type/location pairs
2035  * @returns #FALSE if error was set
2036  */
2037 dbus_bool_t
dbus_message_get_args_valist(DBusMessage * message,DBusError * error,int first_arg_type,va_list var_args)2038 dbus_message_get_args_valist (DBusMessage     *message,
2039                               DBusError       *error,
2040 			      int              first_arg_type,
2041 			      va_list          var_args)
2042 {
2043   DBusMessageIter iter;
2044 
2045   _dbus_return_val_if_fail (message != NULL, FALSE);
2046   _dbus_return_val_if_error_is_set (error, FALSE);
2047 
2048   dbus_message_iter_init (message, &iter);
2049   return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
2050 }
2051 
2052 static void
_dbus_message_iter_init_common(DBusMessage * message,DBusMessageRealIter * real,int iter_type)2053 _dbus_message_iter_init_common (DBusMessage         *message,
2054                                 DBusMessageRealIter *real,
2055                                 int                  iter_type)
2056 {
2057   /* If these static assertions fail on your platform, report it as a bug. */
2058   _DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
2059   _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <=
2060       _DBUS_ALIGNOF (DBusMessageIter));
2061   /* A failure of these two assertions would indicate that we've broken
2062    * ABI on this platform since 1.10.0. */
2063   _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) ==
2064       sizeof (DBusMessageIter));
2065   _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) ==
2066       _DBUS_ALIGNOF (DBusMessageIter));
2067   /* If this static assertion fails, it means the DBusMessageIter struct
2068    * is not "packed", which might result in "iter = other_iter" not copying
2069    * every byte. */
2070   _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) ==
2071       4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int));
2072 
2073   /* Since the iterator will read or write who-knows-what from the
2074    * message, we need to get in the right byte order
2075    */
2076   ensure_byte_order (message);
2077 
2078   real->message = message;
2079   real->changed_stamp = message->changed_stamp;
2080   real->iter_type = iter_type;
2081   real->sig_refcount = 0;
2082 }
2083 
2084 /**
2085  * Initializes a #DBusMessageIter for reading the arguments of the
2086  * message passed in.
2087  *
2088  * When possible, dbus_message_get_args() is much more convenient.
2089  * Some types of argument can only be read with #DBusMessageIter
2090  * however.
2091  *
2092  * The easiest way to iterate is like this:
2093  * @code
2094  * dbus_message_iter_init (message, &iter);
2095  * while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
2096  *   dbus_message_iter_next (&iter);
2097  * @endcode
2098  *
2099  * #DBusMessageIter contains no allocated memory; it need not be
2100  * freed, and can be copied by assignment or memcpy().
2101  *
2102  * @param message the message
2103  * @param iter pointer to an iterator to initialize
2104  * @returns #FALSE if the message has no arguments
2105  */
2106 dbus_bool_t
dbus_message_iter_init(DBusMessage * message,DBusMessageIter * iter)2107 dbus_message_iter_init (DBusMessage     *message,
2108 			DBusMessageIter *iter)
2109 {
2110   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2111   const DBusString *type_str;
2112   int type_pos;
2113 
2114   _dbus_return_val_if_fail (message != NULL, FALSE);
2115   _dbus_return_val_if_fail (iter != NULL, FALSE);
2116 
2117   get_const_signature (&message->header, &type_str, &type_pos);
2118 
2119   _dbus_message_iter_init_common (message, real,
2120                                   DBUS_MESSAGE_ITER_TYPE_READER);
2121 
2122   _dbus_type_reader_init (&real->u.reader,
2123                           _dbus_header_get_byte_order (&message->header),
2124                           type_str, type_pos,
2125                           &message->body,
2126                           0);
2127 
2128   return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
2129 }
2130 
2131 /**
2132  * Checks if an iterator has any more fields.
2133  *
2134  * @param iter the message iter
2135  * @returns #TRUE if there are more fields following
2136  */
2137 dbus_bool_t
dbus_message_iter_has_next(DBusMessageIter * iter)2138 dbus_message_iter_has_next (DBusMessageIter *iter)
2139 {
2140   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2141 
2142   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2143   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2144 
2145   return _dbus_type_reader_has_next (&real->u.reader);
2146 }
2147 
2148 /**
2149  * Moves the iterator to the next field, if any. If there's no next
2150  * field, returns #FALSE. If the iterator moves forward, returns
2151  * #TRUE.
2152  *
2153  * @param iter the message iter
2154  * @returns #TRUE if the iterator was moved to the next field
2155  */
2156 dbus_bool_t
dbus_message_iter_next(DBusMessageIter * iter)2157 dbus_message_iter_next (DBusMessageIter *iter)
2158 {
2159   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2160 
2161   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2162   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2163 
2164   return _dbus_type_reader_next (&real->u.reader);
2165 }
2166 
2167 /**
2168  * Returns the argument type of the argument that the message iterator
2169  * points to. If the iterator is at the end of the message, returns
2170  * #DBUS_TYPE_INVALID. You can thus write a loop as follows:
2171  *
2172  * @code
2173  * dbus_message_iter_init (message, &iter);
2174  * while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
2175  *   dbus_message_iter_next (&iter);
2176  * @endcode
2177  *
2178  * @param iter the message iter
2179  * @returns the argument type
2180  */
2181 int
dbus_message_iter_get_arg_type(DBusMessageIter * iter)2182 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
2183 {
2184   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2185 
2186   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2187   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2188 
2189   return _dbus_type_reader_get_current_type (&real->u.reader);
2190 }
2191 
2192 /**
2193  * Returns the element type of the array that the message iterator
2194  * points to. Note that you need to check that the iterator points to
2195  * an array prior to using this function.
2196  *
2197  * @param iter the message iter
2198  * @returns the array element type
2199  */
2200 int
dbus_message_iter_get_element_type(DBusMessageIter * iter)2201 dbus_message_iter_get_element_type (DBusMessageIter *iter)
2202 {
2203   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2204 
2205   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2206   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
2207   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
2208 
2209   return _dbus_type_reader_get_element_type (&real->u.reader);
2210 }
2211 
2212 /**
2213  * Recurses into a container value when reading values from a message,
2214  * initializing a sub-iterator to use for traversing the child values
2215  * of the container.
2216  *
2217  * Note that this recurses into a value, not a type, so you can only
2218  * recurse if the value exists. The main implication of this is that
2219  * if you have for example an empty array of array of int32, you can
2220  * recurse into the outermost array, but it will have no values, so
2221  * you won't be able to recurse further. There's no array of int32 to
2222  * recurse into.
2223  *
2224  * If a container is an array of fixed-length types (except Unix file
2225  * descriptors), it is much more efficient to use
2226  * dbus_message_iter_get_fixed_array() to get the whole array in one
2227  * shot, rather than individually walking over the array elements.
2228  *
2229  * Be sure you have somehow checked that
2230  * dbus_message_iter_get_arg_type() matches the type you are expecting
2231  * to recurse into. Results of this function are undefined if there is
2232  * no container to recurse into at the current iterator position.
2233  *
2234  * @param iter the message iterator
2235  * @param sub the sub-iterator to initialize
2236  */
2237 void
dbus_message_iter_recurse(DBusMessageIter * iter,DBusMessageIter * sub)2238 dbus_message_iter_recurse (DBusMessageIter  *iter,
2239                            DBusMessageIter  *sub)
2240 {
2241   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2242   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2243 
2244   _dbus_return_if_fail (_dbus_message_iter_check (real));
2245   _dbus_return_if_fail (sub != NULL);
2246 
2247   *real_sub = *real;
2248   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
2249 }
2250 
2251 /**
2252  * Returns the current signature of a message iterator.  This
2253  * is useful primarily for dealing with variants; one can
2254  * recurse into a variant and determine the signature of
2255  * the variant's value.
2256  *
2257  * The returned string must be freed with dbus_free().
2258  *
2259  * @param iter the message iterator
2260  * @returns the contained signature, or NULL if out of memory
2261  */
2262 char *
dbus_message_iter_get_signature(DBusMessageIter * iter)2263 dbus_message_iter_get_signature (DBusMessageIter *iter)
2264 {
2265   const DBusString *sig;
2266   DBusString retstr;
2267   char *ret;
2268   int start, len;
2269   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2270 
2271   _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
2272 
2273   if (!_dbus_string_init (&retstr))
2274     return NULL;
2275 
2276   _dbus_type_reader_get_signature (&real->u.reader, &sig,
2277 				   &start, &len);
2278   if (!_dbus_string_append_len (&retstr,
2279 				_dbus_string_get_const_data (sig) + start,
2280 				len))
2281     return NULL;
2282   if (!_dbus_string_steal_data (&retstr, &ret))
2283     return NULL;
2284   _dbus_string_free (&retstr);
2285   return ret;
2286 }
2287 
2288 /**
2289  * Reads a basic-typed value from the message iterator.
2290  * Basic types are the non-containers such as integer and string.
2291  *
2292  * The value argument should be the address of a location to store
2293  * the returned value. So for int32 it should be a "dbus_int32_t*"
2294  * and for string a "const char**". The returned value is
2295  * by reference and should not be freed.
2296  *
2297  * This call duplicates Unix file descriptors when reading them. It is
2298  * your job to close them when you don't need them anymore.
2299  *
2300  * Unix file descriptors that are read with this function will have
2301  * the FD_CLOEXEC flag set. If you need them without this flag set,
2302  * make sure to unset it with fcntl().
2303  *
2304  * Be sure you have somehow checked that
2305  * dbus_message_iter_get_arg_type() matches the type you are
2306  * expecting, or you'll crash when you try to use an integer as a
2307  * string or something.
2308  *
2309  * To read any container type (array, struct, dict) you will need to
2310  * recurse into the container with dbus_message_iter_recurse().  If
2311  * the container is an array of fixed-length values (except Unix file
2312  * descriptors), you can get all the array elements at once with
2313  * dbus_message_iter_get_fixed_array(). Otherwise, you have to iterate
2314  * over the container's contents one value at a time.
2315  *
2316  * All basic-typed values are guaranteed to fit in a #DBusBasicValue,
2317  * so in versions of libdbus that have that type, you can write code like this:
2318  *
2319  * @code
2320  * DBusBasicValue value;
2321  * int type;
2322  * dbus_message_iter_get_basic (&read_iter, &value);
2323  * type = dbus_message_iter_get_arg_type (&read_iter);
2324  * dbus_message_iter_append_basic (&write_iter, type, &value);
2325  * @endcode
2326  *
2327  * (All D-Bus basic types are either numeric and 8 bytes or smaller, or
2328  * behave like a string; so in older versions of libdbus, DBusBasicValue
2329  * can be replaced with union { char *string; unsigned char bytes[8]; },
2330  * for instance.)
2331  *
2332  * @param iter the iterator
2333  * @param value location to store the value
2334  */
2335 void
dbus_message_iter_get_basic(DBusMessageIter * iter,void * value)2336 dbus_message_iter_get_basic (DBusMessageIter  *iter,
2337                              void             *value)
2338 {
2339   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2340 
2341   _dbus_return_if_fail (_dbus_message_iter_check (real));
2342   _dbus_return_if_fail (value != NULL);
2343 
2344   if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
2345     {
2346 #ifdef HAVE_UNIX_FD_PASSING
2347       DBusBasicValue idx;
2348 
2349       _dbus_type_reader_read_basic(&real->u.reader, &idx);
2350 
2351       if (idx.u32 >= real->message->n_unix_fds) {
2352         /* Hmm, we cannot really signal an error here, so let's make
2353            sure to return an invalid fd. */
2354         *((int*) value) = -1;
2355         return;
2356       }
2357 
2358       *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
2359 #else
2360       *((int*) value) = -1;
2361 #endif
2362     }
2363   else
2364     {
2365       _dbus_type_reader_read_basic (&real->u.reader,
2366                                     value);
2367     }
2368 }
2369 
2370 /**
2371  * Returns the number of elements in the array-typed value pointed
2372  * to by the iterator.
2373  * Note that this function is O(1) for arrays of fixed-size types
2374  * but O(n) for arrays of variable-length types such as strings,
2375  * so it may be a bad idea to use it.
2376  *
2377  * @param iter the iterator
2378  * @returns the number of elements in the array
2379  */
2380 int
dbus_message_iter_get_element_count(DBusMessageIter * iter)2381 dbus_message_iter_get_element_count (DBusMessageIter *iter)
2382 {
2383   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2384   DBusTypeReader array;
2385   int element_type;
2386   int n_elements = 0;
2387 
2388   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2389   _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
2390                             == DBUS_TYPE_ARRAY, 0);
2391 
2392   element_type = _dbus_type_reader_get_element_type (&real->u.reader);
2393   _dbus_type_reader_recurse (&real->u.reader, &array);
2394   if (dbus_type_is_fixed (element_type))
2395     {
2396       int alignment = _dbus_type_get_alignment (element_type);
2397       int total_len = _dbus_type_reader_get_array_length (&array);
2398       n_elements = total_len / alignment;
2399     }
2400   else
2401     {
2402       while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
2403         {
2404           ++n_elements;
2405           _dbus_type_reader_next (&array);
2406         }
2407     }
2408 
2409    return n_elements;
2410 }
2411 
2412 /**
2413  * Returns the number of bytes in the array as marshaled in the wire
2414  * protocol. The iterator must currently be inside an array-typed
2415  * value.
2416  *
2417  * This function is deprecated on the grounds that it is stupid.  Why
2418  * would you want to know how many bytes are in the array as marshaled
2419  * in the wire protocol?  Use dbus_message_iter_get_element_count() instead.
2420  *
2421  * @param iter the iterator
2422  * @returns the number of bytes in the array
2423  */
2424 int
dbus_message_iter_get_array_len(DBusMessageIter * iter)2425 dbus_message_iter_get_array_len (DBusMessageIter *iter)
2426 {
2427   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2428 
2429   _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2430 
2431   return _dbus_type_reader_get_array_length (&real->u.reader);
2432 }
2433 
2434 /**
2435  * Reads a block of fixed-length values from the message iterator.
2436  * Fixed-length values are those basic types that are not string-like,
2437  * such as integers, bool, double. The returned block will be from the
2438  * current position in the array until the end of the array.
2439  *
2440  * There is one exception here: although DBUS_TYPE_UNIX_FD is
2441  * considered a 'fixed' type arrays of this type may not be read with
2442  * this function.
2443  *
2444  * The message iter should be "in" the array (that is, you recurse into the
2445  * array, and then you call dbus_message_iter_get_fixed_array() on the
2446  * "sub-iterator" created by dbus_message_iter_recurse()).
2447  *
2448  * The value argument should be the address of a location to store the
2449  * returned array. So for int32 it should be a "const dbus_int32_t**"
2450  * The returned value is by reference and should not be freed.
2451  *
2452  * This function should only be used if dbus_type_is_fixed() returns
2453  * #TRUE for the element type.
2454  *
2455  * If an array's elements are not fixed in size, you have to recurse
2456  * into the array with dbus_message_iter_recurse() and read the
2457  * elements one by one.
2458  *
2459  * Because the array is not copied, this function runs in constant
2460  * time and is fast; it's much preferred over walking the entire array
2461  * with an iterator. (However, you can always use
2462  * dbus_message_iter_recurse(), even for fixed-length types;
2463  * dbus_message_iter_get_fixed_array() is just an optimization.)
2464  *
2465  * @param iter the iterator
2466  * @param value location to store the block
2467  * @param n_elements number of elements in the block
2468  */
2469 void
dbus_message_iter_get_fixed_array(DBusMessageIter * iter,void * value,int * n_elements)2470 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
2471                                    void             *value,
2472                                    int              *n_elements)
2473 {
2474   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2475 #ifndef DBUS_DISABLE_CHECKS
2476   int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
2477 
2478   _dbus_return_if_fail (_dbus_message_iter_check (real));
2479   _dbus_return_if_fail (value != NULL);
2480   _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
2481                         (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
2482 #endif
2483 
2484   _dbus_type_reader_read_fixed_multi (&real->u.reader,
2485                                       value, n_elements);
2486 }
2487 
2488 /**
2489  * Initializes a #DBusMessageIter for appending arguments to the end
2490  * of a message.
2491  *
2492  * @todo If appending any of the arguments fails due to lack of
2493  * memory, the message is hosed and you have to start over building
2494  * the whole message.
2495  *
2496  * @param message the message
2497  * @param iter pointer to an iterator to initialize
2498  */
2499 void
dbus_message_iter_init_append(DBusMessage * message,DBusMessageIter * iter)2500 dbus_message_iter_init_append (DBusMessage     *message,
2501 			       DBusMessageIter *iter)
2502 {
2503   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2504 
2505   _dbus_return_if_fail (message != NULL);
2506   _dbus_return_if_fail (iter != NULL);
2507 
2508   _dbus_message_iter_init_common (message, real,
2509                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
2510 
2511   /* We create the signature string and point iterators at it "on demand"
2512    * when a value is actually appended. That means that init() never fails
2513    * due to OOM.
2514    */
2515   _dbus_type_writer_init_types_delayed (&real->u.writer,
2516                                         _dbus_header_get_byte_order (&message->header),
2517                                         &message->body,
2518                                         _dbus_string_get_length (&message->body));
2519 }
2520 
2521 /**
2522  * Creates a temporary signature string containing the current
2523  * signature, stores it in the iterator, and points the iterator to
2524  * the end of it. Used any time we write to the message.
2525  *
2526  * @param real an iterator without a type_str
2527  * @returns #FALSE if no memory
2528  */
2529 static dbus_bool_t
_dbus_message_iter_open_signature(DBusMessageRealIter * real)2530 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
2531 {
2532   DBusString *str;
2533   const DBusString *current_sig;
2534   int current_sig_pos;
2535 
2536   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2537 
2538   if (real->u.writer.type_str != NULL)
2539     {
2540       _dbus_assert (real->sig_refcount > 0);
2541       real->sig_refcount += 1;
2542       return TRUE;
2543     }
2544 
2545   str = dbus_new (DBusString, 1);
2546   if (str == NULL)
2547     return FALSE;
2548 
2549   if (!_dbus_header_get_field_raw (&real->message->header,
2550                                    DBUS_HEADER_FIELD_SIGNATURE,
2551                                    &current_sig, &current_sig_pos))
2552     current_sig = NULL;
2553 
2554   if (current_sig)
2555     {
2556       int current_len;
2557 
2558       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
2559       current_sig_pos += 1; /* move on to sig data */
2560 
2561       if (!_dbus_string_init_preallocated (str, current_len + 4))
2562         {
2563           dbus_free (str);
2564           return FALSE;
2565         }
2566 
2567       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
2568                                   str, 0))
2569         {
2570           _dbus_string_free (str);
2571           dbus_free (str);
2572           return FALSE;
2573         }
2574     }
2575   else
2576     {
2577       if (!_dbus_string_init_preallocated (str, 4))
2578         {
2579           dbus_free (str);
2580           return FALSE;
2581         }
2582     }
2583 
2584   real->sig_refcount = 1;
2585 
2586   /* If this assertion failed, then str would be neither stored in u.writer
2587    * nor freed by this function, resulting in a memory leak. */
2588   _dbus_assert (real->u.writer.type_str == NULL);
2589   _dbus_type_writer_add_types (&real->u.writer,
2590                                str, _dbus_string_get_length (str));
2591   return TRUE;
2592 }
2593 
2594 /**
2595  * Sets the new signature as the message signature, frees the
2596  * signature string, and marks the iterator as not having a type_str
2597  * anymore. Frees the signature even if it fails, so you can't
2598  * really recover from failure. Kinda busted.
2599  *
2600  * @param real an iterator without a type_str
2601  * @returns #FALSE if no memory
2602  */
2603 static dbus_bool_t
_dbus_message_iter_close_signature(DBusMessageRealIter * real)2604 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
2605 {
2606   DBusString *str;
2607   const char *v_STRING;
2608   dbus_bool_t retval;
2609 
2610   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2611   _dbus_assert (real->u.writer.type_str != NULL);
2612   _dbus_assert (real->sig_refcount > 0);
2613 
2614   real->sig_refcount -= 1;
2615 
2616   if (real->sig_refcount > 0)
2617     return TRUE;
2618   _dbus_assert (real->sig_refcount == 0);
2619 
2620   retval = TRUE;
2621 
2622   str = real->u.writer.type_str;
2623 
2624   v_STRING = _dbus_string_get_const_data (str);
2625   if (!_dbus_header_set_field_basic (&real->message->header,
2626                                      DBUS_HEADER_FIELD_SIGNATURE,
2627                                      DBUS_TYPE_SIGNATURE,
2628                                      &v_STRING))
2629     retval = FALSE;
2630 
2631   _dbus_type_writer_remove_types (&real->u.writer);
2632   _dbus_string_free (str);
2633   dbus_free (str);
2634 
2635   return retval;
2636 }
2637 
2638 /**
2639  * Frees the signature string and marks the iterator as not having a
2640  * type_str anymore.  Since the new signature is not set, the message
2641  * will generally be hosed after this is called.
2642  *
2643  * @param real an iterator without a type_str
2644  */
2645 static void
_dbus_message_iter_abandon_signature(DBusMessageRealIter * real)2646 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
2647 {
2648   DBusString *str;
2649 
2650   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2651   _dbus_assert (real->u.writer.type_str != NULL);
2652   _dbus_assert (real->sig_refcount > 0);
2653 
2654   real->sig_refcount -= 1;
2655 
2656   if (real->sig_refcount > 0)
2657     return;
2658   _dbus_assert (real->sig_refcount == 0);
2659 
2660   str = real->u.writer.type_str;
2661 
2662   _dbus_type_writer_remove_types (&real->u.writer);
2663   _dbus_string_free (str);
2664   dbus_free (str);
2665 }
2666 
2667 #ifndef DBUS_DISABLE_CHECKS
2668 static dbus_bool_t
_dbus_message_iter_append_check(DBusMessageRealIter * iter)2669 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
2670 {
2671   if (!_dbus_message_iter_check (iter))
2672     return FALSE;
2673 
2674   if (iter->message->locked)
2675     {
2676       _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)");
2677       return FALSE;
2678     }
2679 
2680   return TRUE;
2681 }
2682 #endif /* DBUS_DISABLE_CHECKS */
2683 
2684 #ifdef HAVE_UNIX_FD_PASSING
2685 static int *
expand_fd_array(DBusMessage * m,unsigned n)2686 expand_fd_array(DBusMessage *m,
2687                 unsigned     n)
2688 {
2689   _dbus_assert(m);
2690 
2691   /* This makes space for adding n new fds to the array and returns a
2692      pointer to the place were the first fd should be put. */
2693 
2694   if (m->n_unix_fds + n > m->n_unix_fds_allocated)
2695     {
2696       unsigned k;
2697       int *p;
2698 
2699       /* Make twice as much space as necessary */
2700       k = (m->n_unix_fds + n) * 2;
2701 
2702       /* Allocate at least four */
2703       if (k < 4)
2704         k = 4;
2705 
2706       p = dbus_realloc(m->unix_fds, k * sizeof(int));
2707       if (p == NULL)
2708         return NULL;
2709 
2710       m->unix_fds = p;
2711       m->n_unix_fds_allocated = k;
2712     }
2713 
2714   return m->unix_fds + m->n_unix_fds;
2715 }
2716 #endif
2717 
2718 /**
2719  * Appends a basic-typed value to the message. The basic types are the
2720  * non-container types such as integer and string.
2721  *
2722  * The "value" argument should be the address of a basic-typed value.
2723  * So for string, const char**. For integer, dbus_int32_t*.
2724  *
2725  * For Unix file descriptors this function will internally duplicate
2726  * the descriptor you passed in. Hence you may close the descriptor
2727  * immediately after this call.
2728  *
2729  * @todo If this fails due to lack of memory, the message is hosed and
2730  * you have to start over building the whole message.
2731  *
2732  * @param iter the append iterator
2733  * @param type the type of the value
2734  * @param value the address of the value
2735  * @returns #FALSE if not enough memory
2736  */
2737 dbus_bool_t
dbus_message_iter_append_basic(DBusMessageIter * iter,int type,const void * value)2738 dbus_message_iter_append_basic (DBusMessageIter *iter,
2739                                 int              type,
2740                                 const void      *value)
2741 {
2742   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2743   dbus_bool_t ret;
2744 
2745   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2746   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2747   _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
2748   _dbus_return_val_if_fail (value != NULL, FALSE);
2749 
2750 #ifndef DBUS_DISABLE_CHECKS
2751   switch (type)
2752     {
2753       DBusString str;
2754       DBusValidity signature_validity;
2755       const char * const *string_p;
2756       const dbus_bool_t *bool_p;
2757 
2758       case DBUS_TYPE_STRING:
2759         string_p = value;
2760         _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
2761         break;
2762 
2763       case DBUS_TYPE_OBJECT_PATH:
2764         string_p = value;
2765         _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
2766         break;
2767 
2768       case DBUS_TYPE_SIGNATURE:
2769         string_p = value;
2770         _dbus_string_init_const (&str, *string_p);
2771         signature_validity = _dbus_validate_signature_with_reason (&str,
2772                                                                    0,
2773                                                                    _dbus_string_get_length (&str));
2774 
2775         if (signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
2776           return FALSE;
2777 
2778         _dbus_return_val_if_fail (signature_validity == DBUS_VALID, FALSE);
2779         break;
2780 
2781       case DBUS_TYPE_BOOLEAN:
2782         bool_p = value;
2783         _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
2784         break;
2785 
2786       default:
2787           {
2788             /* nothing to check, all possible values are allowed */
2789           }
2790     }
2791 #endif
2792 
2793   if (!_dbus_message_iter_open_signature (real))
2794     return FALSE;
2795 
2796   if (type == DBUS_TYPE_UNIX_FD)
2797     {
2798 #ifdef HAVE_UNIX_FD_PASSING
2799       int *fds;
2800       dbus_uint32_t u;
2801 
2802       ret = FALSE;
2803 
2804       /* First step, include the fd in the fd list of this message */
2805       if (!(fds = expand_fd_array(real->message, 1)))
2806         goto out;
2807 
2808       *fds = _dbus_dup(*(int*) value, NULL);
2809       if (*fds < 0)
2810         goto out;
2811 
2812       u = real->message->n_unix_fds;
2813 
2814       /* Second step, write the index to the fd */
2815       if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
2816         _dbus_close(*fds, NULL);
2817         goto out;
2818       }
2819 
2820       real->message->n_unix_fds += 1;
2821       u += 1;
2822 
2823       /* Final step, update the header accordingly */
2824       ret = _dbus_header_set_field_basic (&real->message->header,
2825                                           DBUS_HEADER_FIELD_UNIX_FDS,
2826                                           DBUS_TYPE_UINT32,
2827                                           &u);
2828 
2829       /* If any of these operations fail the message is
2830          hosed. However, no memory or fds should be leaked since what
2831          has been added to message has been added to the message, and
2832          can hence be accounted for when the message is being
2833          freed. */
2834 #else
2835       ret = FALSE;
2836       /* This is redundant (we could just fall through), but it avoids
2837        * -Wunused-label in builds that don't HAVE_UNIX_FD_PASSING */
2838       goto out;
2839 #endif
2840     }
2841   else
2842     {
2843       ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
2844     }
2845 
2846 out:
2847   if (!_dbus_message_iter_close_signature (real))
2848     ret = FALSE;
2849 
2850   return ret;
2851 }
2852 
2853 /**
2854  * Appends a block of fixed-length values to an array. The
2855  * fixed-length types are all basic types that are not string-like. So
2856  * int32, double, bool, etc. (Unix file descriptors however are not
2857  * supported.) You must call dbus_message_iter_open_container() to
2858  * open an array of values before calling this function. You may call
2859  * this function multiple times (and intermixed with calls to
2860  * dbus_message_iter_append_basic()) for the same array.
2861  *
2862  * The "value" argument should be the address of the array.  So for
2863  * integer, "dbus_int32_t**" is expected for example.
2864  *
2865  * @warning in C, given "int array[]", "&array == array" (the
2866  * comp.lang.c FAQ says otherwise, but gcc and the FAQ don't agree).
2867  * So if you're using an array instead of a pointer you have to create
2868  * a pointer variable, assign the array to it, then take the address
2869  * of the pointer variable.
2870  * @code
2871  * const dbus_int32_t array[] = { 1, 2, 3 };
2872  * const dbus_int32_t *v_ARRAY = array;
2873  * if (!dbus_message_iter_append_fixed_array (&iter, DBUS_TYPE_INT32, &v_ARRAY, 3))
2874  *   fprintf (stderr, "No memory!\n");
2875  * @endcode
2876  * For strings it works to write const char *array = "Hello" and then
2877  * use &array though.
2878  *
2879  * @todo If this fails due to lack of memory, the message is hosed and
2880  * you have to start over building the whole message.
2881  *
2882  * @param iter the append iterator
2883  * @param element_type the type of the array elements
2884  * @param value the address of the array
2885  * @param n_elements the number of elements to append
2886  * @returns #FALSE if not enough memory
2887  */
2888 dbus_bool_t
dbus_message_iter_append_fixed_array(DBusMessageIter * iter,int element_type,const void * value,int n_elements)2889 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
2890                                       int              element_type,
2891                                       const void      *value,
2892                                       int              n_elements)
2893 {
2894   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2895   dbus_bool_t ret;
2896 
2897   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2898   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2899   _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
2900   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
2901   _dbus_return_val_if_fail (value != NULL, FALSE);
2902   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
2903   _dbus_return_val_if_fail (n_elements <=
2904                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
2905                             FALSE);
2906 
2907 #ifndef DBUS_DISABLE_CHECKS
2908   if (element_type == DBUS_TYPE_BOOLEAN)
2909     {
2910       const dbus_bool_t * const *bools = value;
2911       int i;
2912 
2913       for (i = 0; i < n_elements; i++)
2914         {
2915           _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
2916         }
2917     }
2918 #endif
2919 
2920   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
2921 
2922   return ret;
2923 }
2924 
2925 /**
2926  * Appends a container-typed value to the message. On success, you are
2927  * required to append the contents of the container using the returned
2928  * sub-iterator, and then call
2929  * dbus_message_iter_close_container(). Container types are for
2930  * example struct, variant, and array. For variants, the
2931  * contained_signature should be the type of the single value inside
2932  * the variant. For structs and dict entries, contained_signature
2933  * should be #NULL; it will be set to whatever types you write into
2934  * the struct.  For arrays, contained_signature should be the type of
2935  * the array elements.
2936  *
2937  * @todo If this fails due to lack of memory, the message is hosed and
2938  * you have to start over building the whole message.
2939  *
2940  * If this function fails, the sub-iterator remains invalid, and must
2941  * not be closed with dbus_message_iter_close_container() or abandoned
2942  * with dbus_message_iter_abandon_container(). However, after this
2943  * function has either succeeded or failed, it is valid to call
2944  * dbus_message_iter_abandon_container_if_open().
2945  *
2946  * @param iter the append iterator
2947  * @param type the type of the value
2948  * @param contained_signature the type of container contents
2949  * @param sub sub-iterator to initialize
2950  * @returns #FALSE if not enough memory
2951  */
2952 dbus_bool_t
dbus_message_iter_open_container(DBusMessageIter * iter,int type,const char * contained_signature,DBusMessageIter * sub)2953 dbus_message_iter_open_container (DBusMessageIter *iter,
2954                                   int              type,
2955                                   const char      *contained_signature,
2956                                   DBusMessageIter *sub)
2957 {
2958   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2959   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2960   DBusString contained_str;
2961   DBusValidity contained_signature_validity;
2962   dbus_bool_t ret;
2963 
2964   _dbus_return_val_if_fail (sub != NULL, FALSE);
2965   /* Do our best to make sure the sub-iterator doesn't contain something
2966    * valid-looking on failure */
2967   _dbus_message_real_iter_zero (real_sub);
2968 
2969   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2970   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2971   _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
2972   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
2973                              contained_signature == NULL) ||
2974                             (type == DBUS_TYPE_DICT_ENTRY &&
2975                              contained_signature == NULL) ||
2976                             (type == DBUS_TYPE_VARIANT &&
2977                              contained_signature != NULL) ||
2978                             (type == DBUS_TYPE_ARRAY &&
2979                              contained_signature != NULL), FALSE);
2980 
2981   /* this would fail if the contained_signature is a dict entry, since
2982    * dict entries are invalid signatures standalone (they must be in
2983    * an array)
2984    */
2985   if (contained_signature != NULL)
2986     {
2987       _dbus_string_init_const (&contained_str, contained_signature);
2988       contained_signature_validity = _dbus_validate_signature_with_reason (&contained_str,
2989           0,
2990           _dbus_string_get_length (&contained_str));
2991 
2992       if (contained_signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
2993         return FALSE;
2994     }
2995   else
2996     {
2997       /* just some placeholder value */
2998       contained_signature_validity = DBUS_VALID_BUT_INCOMPLETE;
2999     }
3000 
3001   _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
3002                             contained_signature == NULL ||
3003                             contained_signature_validity == DBUS_VALID,
3004                             FALSE);
3005 
3006   if (!_dbus_message_iter_open_signature (real))
3007     return FALSE;
3008 
3009   ret = FALSE;
3010   *real_sub = *real;
3011 
3012   if (contained_signature != NULL)
3013     {
3014       _dbus_string_init_const (&contained_str, contained_signature);
3015 
3016       ret = _dbus_type_writer_recurse (&real->u.writer,
3017                                        type,
3018                                        &contained_str, 0,
3019                                        &real_sub->u.writer);
3020     }
3021   else
3022     {
3023       ret = _dbus_type_writer_recurse (&real->u.writer,
3024                                        type,
3025                                        NULL, 0,
3026                                        &real_sub->u.writer);
3027     }
3028 
3029   if (!ret)
3030     _dbus_message_iter_abandon_signature (real);
3031 
3032   return ret;
3033 }
3034 
3035 
3036 /**
3037  * Closes a container-typed value appended to the message; may write
3038  * out more information to the message known only after the entire
3039  * container is written, and may free resources created by
3040  * dbus_message_iter_open_container().
3041  *
3042  * Even if this function fails due to lack of memory, the sub-iterator sub
3043  * has been closed and invalidated. It must not be closed again with this
3044  * function, or abandoned with dbus_message_iter_abandon_container().
3045  * However, it remains valid to call
3046  * dbus_message_iter_abandon_container_if_open().
3047  *
3048  * @todo If this fails due to lack of memory, the message is hosed and
3049  * you have to start over building the whole message.
3050  *
3051  * @param iter the append iterator
3052  * @param sub sub-iterator to close
3053  * @returns #FALSE if not enough memory
3054  */
3055 dbus_bool_t
dbus_message_iter_close_container(DBusMessageIter * iter,DBusMessageIter * sub)3056 dbus_message_iter_close_container (DBusMessageIter *iter,
3057                                    DBusMessageIter *sub)
3058 {
3059   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3060   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3061   dbus_bool_t ret;
3062 
3063   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
3064   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3065   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
3066   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3067 
3068   ret = _dbus_type_writer_unrecurse (&real->u.writer,
3069                                      &real_sub->u.writer);
3070   _dbus_message_real_iter_zero (real_sub);
3071 
3072   if (!_dbus_message_iter_close_signature (real))
3073     ret = FALSE;
3074 
3075   return ret;
3076 }
3077 
3078 /**
3079  * Abandons creation of a contained-typed value and frees resources created
3080  * by dbus_message_iter_open_container().  Once this returns, the message
3081  * is hosed and you have to start over building the whole message.
3082  *
3083  * This should only be used to abandon creation of a message when you have
3084  * open containers.
3085  *
3086  * @param iter the append iterator
3087  * @param sub sub-iterator to close
3088  */
3089 void
dbus_message_iter_abandon_container(DBusMessageIter * iter,DBusMessageIter * sub)3090 dbus_message_iter_abandon_container (DBusMessageIter *iter,
3091                                      DBusMessageIter *sub)
3092 {
3093   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3094   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3095 
3096 #ifndef DBUS_DISABLE_CHECKS
3097   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3098   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3099   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3100   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3101 #endif
3102 
3103   _dbus_message_iter_abandon_signature (real);
3104   _dbus_message_real_iter_zero (real_sub);
3105 }
3106 
3107 /**
3108  * Abandons creation of a contained-typed value and frees resources created
3109  * by dbus_message_iter_open_container().  Once this returns, the message
3110  * is hosed and you have to start over building the whole message.
3111  *
3112  * Unlike dbus_message_iter_abandon_container(), it is valid to call this
3113  * function on an iterator that was initialized with
3114  * #DBUS_MESSAGE_ITER_INIT_CLOSED, or an iterator that was already closed
3115  * or abandoned. However, it is not valid to call this function on
3116  * uninitialized memory. This is intended to be used in error cleanup
3117  * code paths, similar to this pattern:
3118  *
3119  *       DBusMessageIter outer = DBUS_MESSAGE_ITER_INIT_CLOSED;
3120  *       DBusMessageIter inner = DBUS_MESSAGE_ITER_INIT_CLOSED;
3121  *       dbus_bool_t result = FALSE;
3122  *
3123  *       if (!dbus_message_iter_open_container (iter, ..., &outer))
3124  *         goto out;
3125  *
3126  *       if (!dbus_message_iter_open_container (&outer, ..., &inner))
3127  *         goto out;
3128  *
3129  *       if (!dbus_message_iter_append_basic (&inner, ...))
3130  *         goto out;
3131  *
3132  *       if (!dbus_message_iter_close_container (&outer, ..., &inner))
3133  *         goto out;
3134  *
3135  *       if (!dbus_message_iter_close_container (iter, ..., &outer))
3136  *         goto out;
3137  *
3138  *       result = TRUE;
3139  *
3140  *     out:
3141  *       dbus_message_iter_abandon_container_if_open (&outer, &inner);
3142  *       dbus_message_iter_abandon_container_if_open (iter, &outer);
3143  *       return result;
3144  *
3145  * @param iter the append iterator
3146  * @param sub sub-iterator to close
3147  */
3148 void
dbus_message_iter_abandon_container_if_open(DBusMessageIter * iter,DBusMessageIter * sub)3149 dbus_message_iter_abandon_container_if_open (DBusMessageIter *iter,
3150                                              DBusMessageIter *sub)
3151 {
3152   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3153   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3154 
3155   /* If both the parent and the child are zeroed out, then either we didn't
3156    * even get as far as successfully recursing into the parent, or we already
3157    * closed both the child and the parent. For example, in the code sample
3158    * in the doc-comment above, this happens for
3159    * abandon_container_if_open (&outer, &inner) if the first open_container
3160    * call failed, or if we reached result = TRUE and fell through. */
3161   if (_dbus_message_real_iter_is_zeroed (real) &&
3162       _dbus_message_real_iter_is_zeroed (real_sub))
3163     return;
3164 
3165 #ifndef DBUS_DISABLE_CHECKS
3166   /* If the child is not zeroed out, but the parent is, then something has
3167    * gone horribly wrong (in practice that would probably mean both are
3168    * uninitialized or corrupt, and the parent happens to have ended up
3169    * all-bytes-zero). */
3170   _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3171   _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3172 #endif
3173 
3174   /* If the parent is not zeroed out, but the child is, then either we did
3175    * not successfully open the child, or we already closed the child. This
3176    * means we do not own a reference to the parent's signature, so it would
3177    * be wrong to release it; so we must not call abandon_signature() here.
3178    * In the code sample in the doc-comment above, this happens for
3179    * abandon_container_if_open (&outer, &inner) if the second open_container
3180    * call failed, or if the second close_container call failed. */
3181   if (_dbus_message_real_iter_is_zeroed (real_sub))
3182     return;
3183 
3184 #ifndef DBUS_DISABLE_CHECKS
3185   _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3186   _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3187 #endif
3188 
3189   /* If neither the parent nor the child is zeroed out, then we genuinely
3190    * have an open container; close it. In the code sample in the doc-comment,
3191    * this happens for abandon_container_if_open (&outer, &inner) if the
3192    * append_basic call failed. */
3193   _dbus_message_iter_abandon_signature (real);
3194   _dbus_message_real_iter_zero (real_sub);
3195 }
3196 
3197 /**
3198  * Sets a flag indicating that the message does not want a reply; if
3199  * this flag is set, the other end of the connection may (but is not
3200  * required to) optimize by not sending method return or error
3201  * replies. If this flag is set, there is no way to know whether the
3202  * message successfully arrived at the remote end. Normally you know a
3203  * message was received when you receive the reply to it.
3204  *
3205  * The flag is #FALSE by default, that is by default the other end is
3206  * required to reply.
3207  *
3208  * On the protocol level this toggles #DBUS_HEADER_FLAG_NO_REPLY_EXPECTED
3209  *
3210  * @param message the message
3211  * @param no_reply #TRUE if no reply is desired
3212  */
3213 void
dbus_message_set_no_reply(DBusMessage * message,dbus_bool_t no_reply)3214 dbus_message_set_no_reply (DBusMessage *message,
3215                            dbus_bool_t  no_reply)
3216 {
3217   _dbus_return_if_fail (message != NULL);
3218   _dbus_return_if_fail (!message->locked);
3219 
3220   _dbus_header_toggle_flag (&message->header,
3221                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
3222                             no_reply);
3223 }
3224 
3225 /**
3226  * Returns #TRUE if the message does not expect
3227  * a reply.
3228  *
3229  * @param message the message
3230  * @returns #TRUE if the message sender isn't waiting for a reply
3231  */
3232 dbus_bool_t
dbus_message_get_no_reply(DBusMessage * message)3233 dbus_message_get_no_reply (DBusMessage *message)
3234 {
3235   _dbus_return_val_if_fail (message != NULL, FALSE);
3236 
3237   return _dbus_header_get_flag (&message->header,
3238                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
3239 }
3240 
3241 /**
3242  * Sets a flag indicating that an owner for the destination name will
3243  * be automatically started before the message is delivered. When this
3244  * flag is set, the message is held until a name owner finishes
3245  * starting up, or fails to start up. In case of failure, the reply
3246  * will be an error.
3247  *
3248  * The flag is set to #TRUE by default, i.e. auto starting is the default.
3249  *
3250  * On the protocol level this toggles #DBUS_HEADER_FLAG_NO_AUTO_START
3251  *
3252  * @param message the message
3253  * @param auto_start #TRUE if auto-starting is desired
3254  */
3255 void
dbus_message_set_auto_start(DBusMessage * message,dbus_bool_t auto_start)3256 dbus_message_set_auto_start (DBusMessage *message,
3257                              dbus_bool_t  auto_start)
3258 {
3259   _dbus_return_if_fail (message != NULL);
3260   _dbus_return_if_fail (!message->locked);
3261 
3262   _dbus_header_toggle_flag (&message->header,
3263                             DBUS_HEADER_FLAG_NO_AUTO_START,
3264                             !auto_start);
3265 }
3266 
3267 /**
3268  * Returns #TRUE if the message will cause an owner for
3269  * destination name to be auto-started.
3270  *
3271  * @param message the message
3272  * @returns #TRUE if the message will use auto-start
3273  */
3274 dbus_bool_t
dbus_message_get_auto_start(DBusMessage * message)3275 dbus_message_get_auto_start (DBusMessage *message)
3276 {
3277   _dbus_return_val_if_fail (message != NULL, FALSE);
3278 
3279   return !_dbus_header_get_flag (&message->header,
3280                                  DBUS_HEADER_FLAG_NO_AUTO_START);
3281 }
3282 
3283 
3284 /**
3285  * Sets the object path this message is being sent to (for
3286  * DBUS_MESSAGE_TYPE_METHOD_CALL) or the one a signal is being
3287  * emitted from (for DBUS_MESSAGE_TYPE_SIGNAL).
3288  *
3289  * The path must contain only valid characters as defined
3290  * in the D-Bus specification.
3291  *
3292  * @param message the message
3293  * @param object_path the path or #NULL to unset
3294  * @returns #FALSE if not enough memory
3295  */
3296 dbus_bool_t
dbus_message_set_path(DBusMessage * message,const char * object_path)3297 dbus_message_set_path (DBusMessage   *message,
3298                        const char    *object_path)
3299 {
3300   _dbus_return_val_if_fail (message != NULL, FALSE);
3301   _dbus_return_val_if_fail (!message->locked, FALSE);
3302   _dbus_return_val_if_fail (object_path == NULL ||
3303                             _dbus_check_is_valid_path (object_path),
3304                             FALSE);
3305 
3306   return set_or_delete_string_field (message,
3307                                      DBUS_HEADER_FIELD_PATH,
3308                                      DBUS_TYPE_OBJECT_PATH,
3309                                      object_path);
3310 }
3311 
3312 /**
3313  * Gets the object path this message is being sent to (for
3314  * DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted from (for
3315  * DBUS_MESSAGE_TYPE_SIGNAL). Returns #NULL if none.
3316  *
3317  * See also dbus_message_get_path_decomposed().
3318  *
3319  * The returned string becomes invalid if the message is
3320  * modified, since it points into the wire-marshaled message data.
3321  *
3322  * @param message the message
3323  * @returns the path (should not be freed) or #NULL
3324  */
3325 const char*
dbus_message_get_path(DBusMessage * message)3326 dbus_message_get_path (DBusMessage   *message)
3327 {
3328   const char *v;
3329 
3330   _dbus_return_val_if_fail (message != NULL, NULL);
3331 
3332   v = NULL; /* in case field doesn't exist */
3333   _dbus_header_get_field_basic (&message->header,
3334                                 DBUS_HEADER_FIELD_PATH,
3335                                 DBUS_TYPE_OBJECT_PATH,
3336                                 (void *) &v);
3337   return v;
3338 }
3339 
3340 /**
3341  * Checks if the message has a particular object path.  The object
3342  * path is the destination object for a method call or the emitting
3343  * object for a signal.
3344  *
3345  * @param message the message
3346  * @param path the path name
3347  * @returns #TRUE if there is a path field in the header
3348  */
3349 dbus_bool_t
dbus_message_has_path(DBusMessage * message,const char * path)3350 dbus_message_has_path (DBusMessage   *message,
3351                        const char    *path)
3352 {
3353   const char *msg_path;
3354   msg_path = dbus_message_get_path (message);
3355 
3356   if (msg_path == NULL)
3357     {
3358       if (path == NULL)
3359         return TRUE;
3360       else
3361         return FALSE;
3362     }
3363 
3364   if (path == NULL)
3365     return FALSE;
3366 
3367   if (strcmp (msg_path, path) == 0)
3368     return TRUE;
3369 
3370   return FALSE;
3371 }
3372 
3373 /**
3374  * Gets the object path this message is being sent to
3375  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted
3376  * from (for DBUS_MESSAGE_TYPE_SIGNAL) in a decomposed
3377  * format (one array element per path component).
3378  * Free the returned array with dbus_free_string_array().
3379  *
3380  * An empty but non-NULL path array means the path "/".
3381  * So the path "/foo/bar" becomes { "foo", "bar", NULL }
3382  * and the path "/" becomes { NULL }.
3383  *
3384  * See also dbus_message_get_path().
3385  *
3386  * @todo this could be optimized by using the len from the message
3387  * instead of calling strlen() again
3388  *
3389  * @param message the message
3390  * @param path place to store allocated array of path components; #NULL set here if no path field exists
3391  * @returns #FALSE if no memory to allocate the array
3392  */
3393 dbus_bool_t
dbus_message_get_path_decomposed(DBusMessage * message,char *** path)3394 dbus_message_get_path_decomposed (DBusMessage   *message,
3395                                   char        ***path)
3396 {
3397   const char *v;
3398 
3399   _dbus_return_val_if_fail (message != NULL, FALSE);
3400   _dbus_return_val_if_fail (path != NULL, FALSE);
3401 
3402   *path = NULL;
3403 
3404   v = dbus_message_get_path (message);
3405   if (v != NULL)
3406     {
3407       if (!_dbus_decompose_path (v, strlen (v),
3408                                  path, NULL))
3409         return FALSE;
3410     }
3411   return TRUE;
3412 }
3413 
3414 /**
3415  * Sets the interface this message is being sent to
3416  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or
3417  * the interface a signal is being emitted from
3418  * (for DBUS_MESSAGE_TYPE_SIGNAL).
3419  *
3420  * The interface name must contain only valid characters as defined
3421  * in the D-Bus specification.
3422  *
3423  * @param message the message
3424  * @param iface the interface or #NULL to unset
3425  * @returns #FALSE if not enough memory
3426  */
3427 dbus_bool_t
dbus_message_set_interface(DBusMessage * message,const char * iface)3428 dbus_message_set_interface (DBusMessage  *message,
3429                             const char   *iface)
3430 {
3431   _dbus_return_val_if_fail (message != NULL, FALSE);
3432   _dbus_return_val_if_fail (!message->locked, FALSE);
3433   _dbus_return_val_if_fail (iface == NULL ||
3434                             _dbus_check_is_valid_interface (iface),
3435                             FALSE);
3436 
3437   return set_or_delete_string_field (message,
3438                                      DBUS_HEADER_FIELD_INTERFACE,
3439                                      DBUS_TYPE_STRING,
3440                                      iface);
3441 }
3442 
3443 /**
3444  * Gets the interface this message is being sent to
3445  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted
3446  * from (for DBUS_MESSAGE_TYPE_SIGNAL).
3447  * The interface name is fully-qualified (namespaced).
3448  * Returns #NULL if none.
3449  *
3450  * The returned string becomes invalid if the message is
3451  * modified, since it points into the wire-marshaled message data.
3452  *
3453  * @param message the message
3454  * @returns the message interface (should not be freed) or #NULL
3455  */
3456 const char*
dbus_message_get_interface(DBusMessage * message)3457 dbus_message_get_interface (DBusMessage *message)
3458 {
3459   const char *v;
3460 
3461   _dbus_return_val_if_fail (message != NULL, NULL);
3462 
3463   v = NULL; /* in case field doesn't exist */
3464   _dbus_header_get_field_basic (&message->header,
3465                                 DBUS_HEADER_FIELD_INTERFACE,
3466                                 DBUS_TYPE_STRING,
3467                                 (void *) &v);
3468   return v;
3469 }
3470 
3471 /**
3472  * Checks if the message has an interface
3473  *
3474  * @param message the message
3475  * @param iface the interface name
3476  * @returns #TRUE if the interface field in the header matches
3477  */
3478 dbus_bool_t
dbus_message_has_interface(DBusMessage * message,const char * iface)3479 dbus_message_has_interface (DBusMessage   *message,
3480                             const char    *iface)
3481 {
3482   const char *msg_interface;
3483   msg_interface = dbus_message_get_interface (message);
3484 
3485   if (msg_interface == NULL)
3486     {
3487       if (iface == NULL)
3488         return TRUE;
3489       else
3490         return FALSE;
3491     }
3492 
3493   if (iface == NULL)
3494     return FALSE;
3495 
3496   if (strcmp (msg_interface, iface) == 0)
3497     return TRUE;
3498 
3499   return FALSE;
3500 
3501 }
3502 
3503 /**
3504  * Sets the interface member being invoked
3505  * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
3506  * (DBUS_MESSAGE_TYPE_SIGNAL).
3507  *
3508  * The member name must contain only valid characters as defined
3509  * in the D-Bus specification.
3510  *
3511  * @param message the message
3512  * @param member the member or #NULL to unset
3513  * @returns #FALSE if not enough memory
3514  */
3515 dbus_bool_t
dbus_message_set_member(DBusMessage * message,const char * member)3516 dbus_message_set_member (DBusMessage  *message,
3517                          const char   *member)
3518 {
3519   _dbus_return_val_if_fail (message != NULL, FALSE);
3520   _dbus_return_val_if_fail (!message->locked, FALSE);
3521   _dbus_return_val_if_fail (member == NULL ||
3522                             _dbus_check_is_valid_member (member),
3523                             FALSE);
3524 
3525   return set_or_delete_string_field (message,
3526                                      DBUS_HEADER_FIELD_MEMBER,
3527                                      DBUS_TYPE_STRING,
3528                                      member);
3529 }
3530 
3531 /**
3532  * Gets the interface member being invoked
3533  * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
3534  * (DBUS_MESSAGE_TYPE_SIGNAL). Returns #NULL if none.
3535  *
3536  * The returned string becomes invalid if the message is
3537  * modified, since it points into the wire-marshaled message data.
3538  *
3539  * @param message the message
3540  * @returns the member name (should not be freed) or #NULL
3541  */
3542 const char*
dbus_message_get_member(DBusMessage * message)3543 dbus_message_get_member (DBusMessage *message)
3544 {
3545   const char *v;
3546 
3547   _dbus_return_val_if_fail (message != NULL, NULL);
3548 
3549   v = NULL; /* in case field doesn't exist */
3550   _dbus_header_get_field_basic (&message->header,
3551                                 DBUS_HEADER_FIELD_MEMBER,
3552                                 DBUS_TYPE_STRING,
3553                                 (void *) &v);
3554   return v;
3555 }
3556 
3557 /**
3558  * Checks if the message has an interface member
3559  *
3560  * @param message the message
3561  * @param member the member name
3562  * @returns #TRUE if there is a member field in the header
3563  */
3564 dbus_bool_t
dbus_message_has_member(DBusMessage * message,const char * member)3565 dbus_message_has_member (DBusMessage   *message,
3566                          const char    *member)
3567 {
3568   const char *msg_member;
3569   msg_member = dbus_message_get_member (message);
3570 
3571   if (msg_member == NULL)
3572     {
3573       if (member == NULL)
3574         return TRUE;
3575       else
3576         return FALSE;
3577     }
3578 
3579   if (member == NULL)
3580     return FALSE;
3581 
3582   if (strcmp (msg_member, member) == 0)
3583     return TRUE;
3584 
3585   return FALSE;
3586 
3587 }
3588 
3589 /**
3590  * Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
3591  * The name is fully-qualified (namespaced).
3592  *
3593  * The error name must contain only valid characters as defined
3594  * in the D-Bus specification.
3595  *
3596  * @param message the message
3597  * @param error_name the name or #NULL to unset
3598  * @returns #FALSE if not enough memory
3599  */
3600 dbus_bool_t
dbus_message_set_error_name(DBusMessage * message,const char * error_name)3601 dbus_message_set_error_name (DBusMessage  *message,
3602                              const char   *error_name)
3603 {
3604   _dbus_return_val_if_fail (message != NULL, FALSE);
3605   _dbus_return_val_if_fail (!message->locked, FALSE);
3606   _dbus_return_val_if_fail (error_name == NULL ||
3607                             _dbus_check_is_valid_error_name (error_name),
3608                             FALSE);
3609 
3610   return set_or_delete_string_field (message,
3611                                      DBUS_HEADER_FIELD_ERROR_NAME,
3612                                      DBUS_TYPE_STRING,
3613                                      error_name);
3614 }
3615 
3616 /**
3617  * Gets the error name (DBUS_MESSAGE_TYPE_ERROR only)
3618  * or #NULL if none.
3619  *
3620  * The returned string becomes invalid if the message is
3621  * modified, since it points into the wire-marshaled message data.
3622  *
3623  * @param message the message
3624  * @returns the error name (should not be freed) or #NULL
3625  */
3626 const char*
dbus_message_get_error_name(DBusMessage * message)3627 dbus_message_get_error_name (DBusMessage *message)
3628 {
3629   const char *v;
3630 
3631   _dbus_return_val_if_fail (message != NULL, NULL);
3632 
3633   v = NULL; /* in case field doesn't exist */
3634   _dbus_header_get_field_basic (&message->header,
3635                                 DBUS_HEADER_FIELD_ERROR_NAME,
3636                                 DBUS_TYPE_STRING,
3637                                 (void *) &v);
3638   return v;
3639 }
3640 
3641 /**
3642  * Sets the message's destination. The destination is the name of
3643  * another connection on the bus and may be either the unique name
3644  * assigned by the bus to each connection, or a well-known name
3645  * specified in advance.
3646  *
3647  * The destination name must contain only valid characters as defined
3648  * in the D-Bus specification.
3649  *
3650  * @param message the message
3651  * @param destination the destination name or #NULL to unset
3652  * @returns #FALSE if not enough memory
3653  */
3654 dbus_bool_t
dbus_message_set_destination(DBusMessage * message,const char * destination)3655 dbus_message_set_destination (DBusMessage  *message,
3656                               const char   *destination)
3657 {
3658   _dbus_return_val_if_fail (message != NULL, FALSE);
3659   _dbus_return_val_if_fail (!message->locked, FALSE);
3660   _dbus_return_val_if_fail (destination == NULL ||
3661                             _dbus_check_is_valid_bus_name (destination),
3662                             FALSE);
3663 
3664   return set_or_delete_string_field (message,
3665                                      DBUS_HEADER_FIELD_DESTINATION,
3666                                      DBUS_TYPE_STRING,
3667                                      destination);
3668 }
3669 
3670 /**
3671  * Gets the destination of a message or #NULL if there is none set.
3672  *
3673  * The returned string becomes invalid if the message is
3674  * modified, since it points into the wire-marshaled message data.
3675  *
3676  * @param message the message
3677  * @returns the message destination (should not be freed) or #NULL
3678  */
3679 const char*
dbus_message_get_destination(DBusMessage * message)3680 dbus_message_get_destination (DBusMessage *message)
3681 {
3682   const char *v;
3683 
3684   _dbus_return_val_if_fail (message != NULL, NULL);
3685 
3686   v = NULL; /* in case field doesn't exist */
3687   _dbus_header_get_field_basic (&message->header,
3688                                 DBUS_HEADER_FIELD_DESTINATION,
3689                                 DBUS_TYPE_STRING,
3690                                 (void *) &v);
3691   return v;
3692 }
3693 
3694 /**
3695  * Sets the message sender.
3696  *
3697  * The sender must be a valid bus name as defined in the D-Bus
3698  * specification.
3699  *
3700  * Usually you don't want to call this. The message bus daemon will
3701  * call it to set the origin of each message. If you aren't implementing
3702  * a message bus daemon you shouldn't need to set the sender.
3703  *
3704  * @param message the message
3705  * @param sender the sender or #NULL to unset
3706  * @returns #FALSE if not enough memory
3707  */
3708 dbus_bool_t
dbus_message_set_sender(DBusMessage * message,const char * sender)3709 dbus_message_set_sender (DBusMessage  *message,
3710                          const char   *sender)
3711 {
3712   _dbus_return_val_if_fail (message != NULL, FALSE);
3713   _dbus_return_val_if_fail (!message->locked, FALSE);
3714   _dbus_return_val_if_fail (sender == NULL ||
3715                             _dbus_check_is_valid_bus_name (sender),
3716                             FALSE);
3717 
3718   return set_or_delete_string_field (message,
3719                                      DBUS_HEADER_FIELD_SENDER,
3720                                      DBUS_TYPE_STRING,
3721                                      sender);
3722 }
3723 
3724 /**
3725  * Gets the unique name of the connection which originated this
3726  * message, or #NULL if unknown or inapplicable. The sender is filled
3727  * in by the message bus.
3728  *
3729  * Note, the returned sender is always the unique bus name.
3730  * Connections may own multiple other bus names, but those
3731  * are not found in the sender field.
3732  *
3733  * The returned string becomes invalid if the message is
3734  * modified, since it points into the wire-marshaled message data.
3735  *
3736  * @param message the message
3737  * @returns the unique name of the sender or #NULL
3738  */
3739 const char*
dbus_message_get_sender(DBusMessage * message)3740 dbus_message_get_sender (DBusMessage *message)
3741 {
3742   const char *v;
3743 
3744   _dbus_return_val_if_fail (message != NULL, NULL);
3745 
3746   v = NULL; /* in case field doesn't exist */
3747   _dbus_header_get_field_basic (&message->header,
3748                                 DBUS_HEADER_FIELD_SENDER,
3749                                 DBUS_TYPE_STRING,
3750                                 (void *) &v);
3751   return v;
3752 }
3753 
3754 /**
3755  * Gets the type signature of the message, i.e. the arguments in the
3756  * message payload. The signature includes only "in" arguments for
3757  * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
3758  * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
3759  * what you might expect (that is, it does not include the signature of the
3760  * entire C++-style method).
3761  *
3762  * The signature is a string made up of type codes such as
3763  * #DBUS_TYPE_INT32. The string is terminated with nul (nul is also
3764  * the value of #DBUS_TYPE_INVALID).
3765  *
3766  * The returned string becomes invalid if the message is
3767  * modified, since it points into the wire-marshaled message data.
3768  *
3769  * @param message the message
3770  * @returns the type signature
3771  */
3772 const char*
dbus_message_get_signature(DBusMessage * message)3773 dbus_message_get_signature (DBusMessage *message)
3774 {
3775   const DBusString *type_str;
3776   int type_pos;
3777 
3778   _dbus_return_val_if_fail (message != NULL, NULL);
3779 
3780   get_const_signature (&message->header, &type_str, &type_pos);
3781 
3782   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
3783 }
3784 
3785 static dbus_bool_t
_dbus_message_has_type_interface_member(DBusMessage * message,int type,const char * iface,const char * member)3786 _dbus_message_has_type_interface_member (DBusMessage *message,
3787                                          int          type,
3788                                          const char  *iface,
3789                                          const char  *member)
3790 {
3791   const char *n;
3792 
3793   _dbus_assert (message != NULL);
3794   _dbus_assert (iface != NULL);
3795   _dbus_assert (member != NULL);
3796 
3797   if (dbus_message_get_type (message) != type)
3798     return FALSE;
3799 
3800   /* Optimize by checking the short member name first
3801    * instead of the longer interface name
3802    */
3803 
3804   n = dbus_message_get_member (message);
3805 
3806   if (n && strcmp (n, member) == 0)
3807     {
3808       n = dbus_message_get_interface (message);
3809 
3810       if (n == NULL || strcmp (n, iface) == 0)
3811         return TRUE;
3812     }
3813 
3814   return FALSE;
3815 }
3816 
3817 /**
3818  * Checks whether the message is a method call with the given
3819  * interface and member fields.  If the message is not
3820  * #DBUS_MESSAGE_TYPE_METHOD_CALL, or has a different interface or
3821  * member field, returns #FALSE. If the interface field is missing,
3822  * then it will be assumed equal to the provided interface.  The D-Bus
3823  * protocol allows method callers to leave out the interface name.
3824  *
3825  * @param message the message
3826  * @param iface the name to check (must not be #NULL)
3827  * @param method the name to check (must not be #NULL)
3828  *
3829  * @returns #TRUE if the message is the specified method call
3830  */
3831 dbus_bool_t
dbus_message_is_method_call(DBusMessage * message,const char * iface,const char * method)3832 dbus_message_is_method_call (DBusMessage *message,
3833                              const char  *iface,
3834                              const char  *method)
3835 {
3836   _dbus_return_val_if_fail (message != NULL, FALSE);
3837   _dbus_return_val_if_fail (iface != NULL, FALSE);
3838   _dbus_return_val_if_fail (method != NULL, FALSE);
3839   /* don't check that interface/method are valid since it would be
3840    * expensive, and not catch many common errors
3841    */
3842 
3843   return _dbus_message_has_type_interface_member (message,
3844                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
3845                                                   iface, method);
3846 }
3847 
3848 /**
3849  * Checks whether the message is a signal with the given interface and
3850  * member fields.  If the message is not #DBUS_MESSAGE_TYPE_SIGNAL, or
3851  * has a different interface or member field, returns #FALSE.
3852  *
3853  * @param message the message
3854  * @param iface the name to check (must not be #NULL)
3855  * @param signal_name the name to check (must not be #NULL)
3856  *
3857  * @returns #TRUE if the message is the specified signal
3858  */
3859 dbus_bool_t
dbus_message_is_signal(DBusMessage * message,const char * iface,const char * signal_name)3860 dbus_message_is_signal (DBusMessage *message,
3861                         const char  *iface,
3862                         const char  *signal_name)
3863 {
3864   _dbus_return_val_if_fail (message != NULL, FALSE);
3865   _dbus_return_val_if_fail (iface != NULL, FALSE);
3866   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
3867   /* don't check that interface/name are valid since it would be
3868    * expensive, and not catch many common errors
3869    */
3870 
3871   return _dbus_message_has_type_interface_member (message,
3872                                                   DBUS_MESSAGE_TYPE_SIGNAL,
3873                                                   iface, signal_name);
3874 }
3875 
3876 /**
3877  * Checks whether the message is an error reply with the given error
3878  * name.  If the message is not #DBUS_MESSAGE_TYPE_ERROR, or has a
3879  * different name, returns #FALSE.
3880  *
3881  * @param message the message
3882  * @param error_name the name to check (must not be #NULL)
3883  *
3884  * @returns #TRUE if the message is the specified error
3885  */
3886 dbus_bool_t
dbus_message_is_error(DBusMessage * message,const char * error_name)3887 dbus_message_is_error (DBusMessage *message,
3888                        const char  *error_name)
3889 {
3890   const char *n;
3891 
3892   _dbus_return_val_if_fail (message != NULL, FALSE);
3893   _dbus_return_val_if_fail (error_name != NULL, FALSE);
3894   /* don't check that error_name is valid since it would be expensive,
3895    * and not catch many common errors
3896    */
3897 
3898   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
3899     return FALSE;
3900 
3901   n = dbus_message_get_error_name (message);
3902 
3903   if (n && strcmp (n, error_name) == 0)
3904     return TRUE;
3905   else
3906     return FALSE;
3907 }
3908 
3909 /**
3910  * Checks whether the message was sent to the given name.  If the
3911  * message has no destination specified or has a different
3912  * destination, returns #FALSE.
3913  *
3914  * @param message the message
3915  * @param name the name to check (must not be #NULL)
3916  *
3917  * @returns #TRUE if the message has the given destination name
3918  */
3919 dbus_bool_t
dbus_message_has_destination(DBusMessage * message,const char * name)3920 dbus_message_has_destination (DBusMessage  *message,
3921                               const char   *name)
3922 {
3923   const char *s;
3924 
3925   _dbus_return_val_if_fail (message != NULL, FALSE);
3926   _dbus_return_val_if_fail (name != NULL, FALSE);
3927   /* don't check that name is valid since it would be expensive, and
3928    * not catch many common errors
3929    */
3930 
3931   s = dbus_message_get_destination (message);
3932 
3933   if (s && strcmp (s, name) == 0)
3934     return TRUE;
3935   else
3936     return FALSE;
3937 }
3938 
3939 /**
3940  * Checks whether the message has the given unique name as its sender.
3941  * If the message has no sender specified or has a different sender,
3942  * returns #FALSE. Note that a peer application will always have the
3943  * unique name of the connection as the sender. So you can't use this
3944  * function to see whether a sender owned a well-known name.
3945  *
3946  * Messages from the bus itself will have #DBUS_SERVICE_DBUS
3947  * as the sender.
3948  *
3949  * @param message the message
3950  * @param name the name to check (must not be #NULL)
3951  *
3952  * @returns #TRUE if the message has the given sender
3953  */
3954 dbus_bool_t
dbus_message_has_sender(DBusMessage * message,const char * name)3955 dbus_message_has_sender (DBusMessage  *message,
3956                          const char   *name)
3957 {
3958   const char *s;
3959 
3960   _dbus_return_val_if_fail (message != NULL, FALSE);
3961   _dbus_return_val_if_fail (name != NULL, FALSE);
3962   /* don't check that name is valid since it would be expensive, and
3963    * not catch many common errors
3964    */
3965 
3966   s = dbus_message_get_sender (message);
3967 
3968   if (s && strcmp (s, name) == 0)
3969     return TRUE;
3970   else
3971     return FALSE;
3972 }
3973 
3974 /**
3975  * Checks whether the message has the given signature; see
3976  * dbus_message_get_signature() for more details on what the signature
3977  * looks like.
3978  *
3979  * @param message the message
3980  * @param signature typecode array
3981  * @returns #TRUE if message has the given signature
3982 */
3983 dbus_bool_t
dbus_message_has_signature(DBusMessage * message,const char * signature)3984 dbus_message_has_signature (DBusMessage   *message,
3985                             const char    *signature)
3986 {
3987   const char *s;
3988 
3989   _dbus_return_val_if_fail (message != NULL, FALSE);
3990   _dbus_return_val_if_fail (signature != NULL, FALSE);
3991   /* don't check that signature is valid since it would be expensive,
3992    * and not catch many common errors
3993    */
3994 
3995   s = dbus_message_get_signature (message);
3996 
3997   if (s && strcmp (s, signature) == 0)
3998     return TRUE;
3999   else
4000     return FALSE;
4001 }
4002 
4003 /**
4004  * Sets a #DBusError based on the contents of the given
4005  * message. The error is only set if the message
4006  * is an error message, as in #DBUS_MESSAGE_TYPE_ERROR.
4007  * The name of the error is set to the name of the message,
4008  * and the error message is set to the first argument
4009  * if the argument exists and is a string.
4010  *
4011  * The return value indicates whether the error was set (the error is
4012  * set if and only if the message is an error message).  So you can
4013  * check for an error reply and convert it to DBusError in one go:
4014  * @code
4015  *  if (dbus_set_error_from_message (error, reply))
4016  *    return error;
4017  *  else
4018  *    process reply;
4019  * @endcode
4020  *
4021  * @param error the error to set
4022  * @param message the message to set it from
4023  * @returns #TRUE if the message had type #DBUS_MESSAGE_TYPE_ERROR
4024  */
4025 dbus_bool_t
dbus_set_error_from_message(DBusError * error,DBusMessage * message)4026 dbus_set_error_from_message (DBusError   *error,
4027                              DBusMessage *message)
4028 {
4029   const char *str;
4030 
4031   _dbus_return_val_if_fail (message != NULL, FALSE);
4032   _dbus_return_val_if_error_is_set (error, FALSE);
4033 
4034   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
4035     return FALSE;
4036 
4037   str = NULL;
4038   dbus_message_get_args (message, NULL,
4039                          DBUS_TYPE_STRING, &str,
4040                          DBUS_TYPE_INVALID);
4041 
4042   dbus_set_error (error, dbus_message_get_error_name (message),
4043                   str ? "%s" : NULL, str);
4044 
4045   return TRUE;
4046 }
4047 
4048 /**
4049  * Checks whether a message contains unix fds
4050  *
4051  * @param message the message
4052  * @returns #TRUE if the message contains unix fds
4053  */
4054 dbus_bool_t
dbus_message_contains_unix_fds(DBusMessage * message)4055 dbus_message_contains_unix_fds(DBusMessage *message)
4056 {
4057 #ifdef HAVE_UNIX_FD_PASSING
4058   _dbus_assert(message);
4059 
4060   return message->n_unix_fds > 0;
4061 #else
4062   return FALSE;
4063 #endif
4064 }
4065 
4066 /** @} */
4067 
4068 /**
4069  * @addtogroup DBusMessageInternals
4070  *
4071  * @{
4072  */
4073 
4074 /**
4075  * The initial buffer size of the message loader.
4076  *
4077  * @todo this should be based on min header size plus some average
4078  * body size, or something. Or rather, the min header size only, if we
4079  * want to try to read only the header, store that in a DBusMessage,
4080  * then read only the body and store that, etc., depends on
4081  * how we optimize _dbus_message_loader_get_buffer() and what
4082  * the exact message format is.
4083  */
4084 #define INITIAL_LOADER_DATA_LEN 32
4085 
4086 /**
4087  * Creates a new message loader. Returns #NULL if memory can't
4088  * be allocated.
4089  *
4090  * @returns new loader, or #NULL.
4091  */
4092 DBusMessageLoader*
_dbus_message_loader_new(void)4093 _dbus_message_loader_new (void)
4094 {
4095   DBusMessageLoader *loader;
4096 
4097   loader = dbus_new0 (DBusMessageLoader, 1);
4098   if (loader == NULL)
4099     return NULL;
4100 
4101   loader->refcount = 1;
4102 
4103   loader->corrupted = FALSE;
4104   loader->corruption_reason = DBUS_VALID;
4105 
4106   /* this can be configured by the app, but defaults to the protocol max */
4107   loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
4108 
4109   /* We set a very relatively conservative default here since due to how
4110   SCM_RIGHTS works we need to preallocate an fd array of the maximum
4111   number of unix fds we want to receive in advance. A
4112   try-and-reallocate loop is not possible. */
4113   loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
4114 
4115   if (!_dbus_string_init (&loader->data))
4116     {
4117       dbus_free (loader);
4118       return NULL;
4119     }
4120 
4121   /* preallocate the buffer for speed, ignore failure */
4122   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
4123   _dbus_string_set_length (&loader->data, 0);
4124 
4125 #ifdef HAVE_UNIX_FD_PASSING
4126   loader->unix_fds = NULL;
4127   loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
4128   loader->unix_fds_outstanding = FALSE;
4129 #endif
4130 
4131   return loader;
4132 }
4133 
4134 /**
4135  * Increments the reference count of the loader.
4136  *
4137  * @param loader the loader.
4138  * @returns the loader
4139  */
4140 DBusMessageLoader *
_dbus_message_loader_ref(DBusMessageLoader * loader)4141 _dbus_message_loader_ref (DBusMessageLoader *loader)
4142 {
4143   loader->refcount += 1;
4144 
4145   return loader;
4146 }
4147 
4148 /**
4149  * Decrements the reference count of the loader and finalizes the
4150  * loader when the count reaches zero.
4151  *
4152  * @param loader the loader.
4153  */
4154 void
_dbus_message_loader_unref(DBusMessageLoader * loader)4155 _dbus_message_loader_unref (DBusMessageLoader *loader)
4156 {
4157   loader->refcount -= 1;
4158   if (loader->refcount == 0)
4159     {
4160 #ifdef HAVE_UNIX_FD_PASSING
4161       close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
4162       dbus_free(loader->unix_fds);
4163 #endif
4164       _dbus_list_foreach (&loader->messages,
4165                           (DBusForeachFunction) dbus_message_unref,
4166                           NULL);
4167       _dbus_list_clear (&loader->messages);
4168       _dbus_string_free (&loader->data);
4169       dbus_free (loader);
4170     }
4171 }
4172 
4173 /**
4174  * Gets the buffer to use for reading data from the network.  Network
4175  * data is read directly into an allocated buffer, which is then used
4176  * in the DBusMessage, to avoid as many extra memcpy's as possible.
4177  * The buffer must always be returned immediately using
4178  * _dbus_message_loader_return_buffer(), even if no bytes are
4179  * successfully read.
4180  *
4181  * @todo this function can be a lot more clever. For example
4182  * it can probably always return a buffer size to read exactly
4183  * the body of the next message, thus avoiding any memory wastage
4184  * or reallocs.
4185  *
4186  * @todo we need to enforce a max length on strings in header fields.
4187  *
4188  * @param loader the message loader.
4189  * @param buffer the buffer
4190  */
4191 void
_dbus_message_loader_get_buffer(DBusMessageLoader * loader,DBusString ** buffer,int * max_to_read,dbus_bool_t * may_read_fds)4192 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
4193                                  DBusString        **buffer,
4194                                  int                *max_to_read,
4195                                  dbus_bool_t        *may_read_fds)
4196 {
4197   _dbus_assert (!loader->buffer_outstanding);
4198 
4199   *buffer = &loader->data;
4200 
4201   loader->buffer_outstanding = TRUE;
4202 
4203   if (max_to_read != NULL)
4204     {
4205 #ifdef HAVE_UNIX_FD_PASSING
4206       int offset = 0;
4207       int remain;
4208       int byte_order;
4209       int fields_array_len;
4210       int header_len;
4211       int body_len;
4212 #endif
4213 
4214       *max_to_read = DBUS_MAXIMUM_MESSAGE_LENGTH;
4215       *may_read_fds = TRUE;
4216 
4217 #ifdef HAVE_UNIX_FD_PASSING
4218       /* If we aren't holding onto any fds, we can read as much as we want
4219        * (fast path). */
4220       if (loader->n_unix_fds == 0)
4221         return;
4222 
4223       /* Slow path: we have a message with some fds in it. We don't want
4224        * to start on the next message until this one is out of the way;
4225        * otherwise a legitimate sender can keep us processing messages
4226        * containing fds, until we disconnect it for having had fds pending
4227        * for too long, a limit that is in place to stop malicious senders
4228        * from setting up recursive fd-passing that takes up our quota and
4229        * will never go away. */
4230 
4231       remain = _dbus_string_get_length (&loader->data);
4232 
4233       while (remain > 0)
4234         {
4235           DBusValidity validity = DBUS_VALIDITY_UNKNOWN;
4236           int needed;
4237 
4238           /* If 0 < remain < DBUS_MINIMUM_HEADER_SIZE, then we've had at
4239            * least the first byte of a message, but we don't know how
4240            * much more to read. Only read the rest of the
4241            * DBUS_MINIMUM_HEADER_SIZE for now; then we'll know. */
4242           if (remain < DBUS_MINIMUM_HEADER_SIZE)
4243             {
4244               *max_to_read = DBUS_MINIMUM_HEADER_SIZE - remain;
4245               *may_read_fds = FALSE;
4246               return;
4247             }
4248 
4249           if (!_dbus_header_have_message_untrusted (loader->max_message_size,
4250                                                     &validity,
4251                                                     &byte_order,
4252                                                     &fields_array_len,
4253                                                     &header_len,
4254                                                     &body_len,
4255                                                     &loader->data,
4256                                                     offset,
4257                                                     remain))
4258             {
4259               /* If a message in the buffer is invalid, we're going to
4260                * disconnect the sender anyway, so reading an arbitrary amount
4261                * is fine. */
4262               if (validity != DBUS_VALID)
4263                 return;
4264 
4265               /* We have a partial message, with the
4266                * DBUS_MINIMUM_HEADER_SIZE-byte fixed part of the header (which
4267                * lets us work out how much more we need), but no more. Read
4268                * the rest of the message. */
4269               needed = header_len + body_len;
4270               _dbus_assert (needed > remain);
4271               *max_to_read = needed - remain;
4272               *may_read_fds = FALSE;
4273               return;
4274             }
4275 
4276           /* Skip over entire messages until we have less than a message
4277            * remaining. */
4278           needed = header_len + body_len;
4279           _dbus_assert (needed > DBUS_MINIMUM_HEADER_SIZE);
4280           _dbus_assert (remain >= needed);
4281           remain -= needed;
4282           offset += needed;
4283         }
4284 #endif
4285     }
4286 }
4287 
4288 /**
4289  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
4290  * indicating to the loader how many bytes of the buffer were filled
4291  * in. This function must always be called, even if no bytes were
4292  * successfully read.
4293  *
4294  * @param loader the loader.
4295  * @param buffer the buffer.
4296  */
4297 void
_dbus_message_loader_return_buffer(DBusMessageLoader * loader,DBusString * buffer)4298 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
4299                                     DBusString         *buffer)
4300 {
4301   _dbus_assert (loader->buffer_outstanding);
4302   _dbus_assert (buffer == &loader->data);
4303 
4304   loader->buffer_outstanding = FALSE;
4305 }
4306 
4307 #ifdef HAVE_UNIX_FD_PASSING
4308 /**
4309  * Gets the buffer to use for reading unix fds from the network.
4310  *
4311  * This works similar to _dbus_message_loader_get_buffer()
4312  *
4313  * @param loader the message loader.
4314  * @param fds the array to read fds into
4315  * @param max_n_fds how many fds to read at most
4316  * @return TRUE on success, FALSE on OOM
4317  */
4318 dbus_bool_t
_dbus_message_loader_get_unix_fds(DBusMessageLoader * loader,int ** fds,unsigned * max_n_fds)4319 _dbus_message_loader_get_unix_fds(DBusMessageLoader  *loader,
4320                                   int               **fds,
4321                                   unsigned           *max_n_fds)
4322 {
4323   _dbus_assert (!loader->unix_fds_outstanding);
4324 
4325   /* Allocate space where we can put the fds we read. We allocate
4326      space for max_message_unix_fds since this is an
4327      upper limit how many fds can be received within a single
4328      message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
4329      we are allocating the maximum possible array size right from the
4330      beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
4331      there is no better way. */
4332 
4333   if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
4334     {
4335       int *a = dbus_realloc(loader->unix_fds,
4336                             loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
4337 
4338       if (!a)
4339         return FALSE;
4340 
4341       loader->unix_fds = a;
4342       loader->n_unix_fds_allocated = loader->max_message_unix_fds;
4343     }
4344 
4345   *fds = loader->unix_fds + loader->n_unix_fds;
4346   *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
4347 
4348   loader->unix_fds_outstanding = TRUE;
4349   return TRUE;
4350 }
4351 
4352 /**
4353  * Returns a buffer obtained from _dbus_message_loader_get_unix_fds().
4354  *
4355  * This works similar to _dbus_message_loader_return_buffer()
4356  *
4357  * @param loader the message loader.
4358  * @param fds the array fds were read into
4359  * @param n_fds how many fds were read
4360  */
4361 
4362 void
_dbus_message_loader_return_unix_fds(DBusMessageLoader * loader,int * fds,unsigned n_fds)4363 _dbus_message_loader_return_unix_fds(DBusMessageLoader  *loader,
4364                                      int                *fds,
4365                                      unsigned            n_fds)
4366 {
4367   _dbus_assert(loader->unix_fds_outstanding);
4368   _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
4369   _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
4370 
4371   loader->n_unix_fds += n_fds;
4372   loader->unix_fds_outstanding = FALSE;
4373 
4374   if (n_fds && loader->unix_fds_change)
4375     loader->unix_fds_change (loader->unix_fds_change_data);
4376 }
4377 #endif
4378 
4379 /*
4380  * FIXME when we move the header out of the buffer, that memmoves all
4381  * buffered messages. Kind of crappy.
4382  *
4383  * Also we copy the header and body, which is kind of crappy.  To
4384  * avoid this, we have to allow header and body to be in a single
4385  * memory block, which is good for messages we read and bad for
4386  * messages we are creating. But we could move_len() the buffer into
4387  * this single memory block, and move_len() will just swap the buffers
4388  * if you're moving the entire buffer replacing the dest string.
4389  *
4390  * We could also have the message loader tell the transport how many
4391  * bytes to read; so it would first ask for some arbitrary number like
4392  * 256, then if the message was incomplete it would use the
4393  * header/body len to ask for exactly the size of the message (or
4394  * blocks the size of a typical kernel buffer for the socket). That
4395  * way we don't get trailing bytes in the buffer that have to be
4396  * memmoved. Though I suppose we also don't have a chance of reading a
4397  * bunch of small messages at once, so the optimization may be stupid.
4398  *
4399  * Another approach would be to keep a "start" index into
4400  * loader->data and only delete it occasionally, instead of after
4401  * each message is loaded.
4402  *
4403  * load_message() returns FALSE if not enough memory OR the loader was corrupted
4404  */
4405 static dbus_bool_t
load_message(DBusMessageLoader * loader,DBusMessage * message,int byte_order,int fields_array_len,int header_len,int body_len)4406 load_message (DBusMessageLoader *loader,
4407               DBusMessage       *message,
4408               int                byte_order,
4409               int                fields_array_len,
4410               int                header_len,
4411               int                body_len)
4412 {
4413   dbus_bool_t oom;
4414   DBusValidity validity;
4415   const DBusString *type_str;
4416   int type_pos;
4417   DBusValidationMode mode;
4418   dbus_uint32_t n_unix_fds = 0;
4419 
4420   mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
4421 
4422   oom = FALSE;
4423 
4424 #if 0
4425   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
4426 #endif
4427 
4428   /* 1. VALIDATE AND COPY OVER HEADER */
4429   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
4430   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
4431 
4432   if (!_dbus_header_load (&message->header,
4433                           mode,
4434                           &validity,
4435                           byte_order,
4436                           fields_array_len,
4437                           header_len,
4438                           body_len,
4439                           &loader->data, 0,
4440                           _dbus_string_get_length (&loader->data)))
4441     {
4442       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
4443 
4444       /* assert here so we can catch any code that still uses DBUS_VALID to indicate
4445          oom errors.  They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
4446       _dbus_assert (validity != DBUS_VALID);
4447 
4448       if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
4449         oom = TRUE;
4450       else
4451         {
4452           loader->corrupted = TRUE;
4453           loader->corruption_reason = validity;
4454         }
4455       goto failed;
4456     }
4457 
4458   _dbus_assert (validity == DBUS_VALID);
4459 
4460   /* 2. VALIDATE BODY */
4461   if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
4462     {
4463       get_const_signature (&message->header, &type_str, &type_pos);
4464 
4465       /* Because the bytes_remaining arg is NULL, this validates that the
4466        * body is the right length
4467        */
4468       validity = _dbus_validate_body_with_reason (type_str,
4469                                                   type_pos,
4470                                                   byte_order,
4471                                                   NULL,
4472                                                   &loader->data,
4473                                                   header_len,
4474                                                   body_len);
4475       if (validity != DBUS_VALID)
4476         {
4477           _dbus_verbose ("Failed to validate message body code %d\n", validity);
4478 
4479           loader->corrupted = TRUE;
4480           loader->corruption_reason = validity;
4481 
4482           goto failed;
4483         }
4484     }
4485 
4486   /* 3. COPY OVER UNIX FDS */
4487   _dbus_header_get_field_basic(&message->header,
4488                                DBUS_HEADER_FIELD_UNIX_FDS,
4489                                DBUS_TYPE_UINT32,
4490                                &n_unix_fds);
4491 
4492 #ifdef HAVE_UNIX_FD_PASSING
4493 
4494   if (n_unix_fds > loader->n_unix_fds)
4495     {
4496       _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
4497                     n_unix_fds, loader->n_unix_fds);
4498 
4499       loader->corrupted = TRUE;
4500       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4501       goto failed;
4502     }
4503 
4504   /* If this was a recycled message there might still be
4505      some memory allocated for the fds */
4506   dbus_free(message->unix_fds);
4507 
4508   if (n_unix_fds > 0)
4509     {
4510       message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
4511       if (message->unix_fds == NULL)
4512         {
4513           _dbus_verbose ("Failed to allocate file descriptor array\n");
4514           oom = TRUE;
4515           goto failed;
4516         }
4517 
4518       message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
4519       loader->n_unix_fds -= n_unix_fds;
4520       memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
4521 
4522       if (loader->unix_fds_change)
4523         loader->unix_fds_change (loader->unix_fds_change_data);
4524     }
4525   else
4526     message->unix_fds = NULL;
4527 
4528 #else
4529 
4530   if (n_unix_fds > 0)
4531     {
4532       _dbus_verbose ("Hmm, message claims to come with file descriptors "
4533                      "but that's not supported on our platform, disconnecting.\n");
4534 
4535       loader->corrupted = TRUE;
4536       loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4537       goto failed;
4538     }
4539 
4540 #endif
4541 
4542   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
4543 
4544   if (!_dbus_list_append (&loader->messages, message))
4545     {
4546       _dbus_verbose ("Failed to append new message to loader queue\n");
4547       oom = TRUE;
4548       goto failed;
4549     }
4550 
4551   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4552   _dbus_assert (_dbus_string_get_length (&loader->data) >=
4553                 (header_len + body_len));
4554 
4555   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
4556     {
4557       _dbus_verbose ("Failed to move body into new message\n");
4558       oom = TRUE;
4559       goto failed;
4560     }
4561 
4562   _dbus_string_delete (&loader->data, 0, header_len + body_len);
4563 
4564   /* don't waste more than 2k of memory */
4565   _dbus_string_compact (&loader->data, 2048);
4566 
4567   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
4568   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4569 
4570   _dbus_verbose ("Loaded message %p\n", message);
4571 
4572   _dbus_assert (!oom);
4573   _dbus_assert (!loader->corrupted);
4574   _dbus_assert (loader->messages != NULL);
4575   _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4576 
4577   return TRUE;
4578 
4579  failed:
4580 
4581   /* Clean up */
4582 
4583   /* does nothing if the message isn't in the list */
4584   _dbus_list_remove_last (&loader->messages, message);
4585 
4586   if (oom)
4587     _dbus_assert (!loader->corrupted);
4588   else
4589     _dbus_assert (loader->corrupted);
4590 
4591   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
4592 
4593   return FALSE;
4594 }
4595 
4596 /**
4597  * Converts buffered data into messages, if we have enough data.  If
4598  * we don't have enough data, does nothing.
4599  *
4600  * @todo we need to check that the proper named header fields exist
4601  * for each message type.
4602  *
4603  * @todo If a message has unknown type, we should probably eat it
4604  * right here rather than passing it out to applications.  However
4605  * it's not an error to see messages of unknown type.
4606  *
4607  * @param loader the loader.
4608  * @returns #TRUE if we had enough memory to finish.
4609  */
4610 dbus_bool_t
_dbus_message_loader_queue_messages(DBusMessageLoader * loader)4611 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
4612 {
4613   while (!loader->corrupted &&
4614          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
4615     {
4616       DBusValidity validity;
4617       int byte_order, fields_array_len, header_len, body_len;
4618 
4619       if (_dbus_header_have_message_untrusted (loader->max_message_size,
4620                                                &validity,
4621                                                &byte_order,
4622                                                &fields_array_len,
4623                                                &header_len,
4624                                                &body_len,
4625                                                &loader->data, 0,
4626                                                _dbus_string_get_length (&loader->data)))
4627         {
4628           DBusMessage *message;
4629 
4630           _dbus_assert (validity == DBUS_VALID);
4631 
4632           message = dbus_message_new_empty_header ();
4633           if (message == NULL)
4634             return FALSE;
4635 
4636           if (!load_message (loader, message,
4637                              byte_order, fields_array_len,
4638                              header_len, body_len))
4639             {
4640               dbus_message_unref (message);
4641               /* load_message() returns false if corrupted or OOM; if
4642                * corrupted then return TRUE for not OOM
4643                */
4644               return loader->corrupted;
4645             }
4646 
4647           _dbus_assert (loader->messages != NULL);
4648           _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4649 	}
4650       else
4651         {
4652           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
4653                          validity);
4654           if (validity != DBUS_VALID)
4655             {
4656               loader->corrupted = TRUE;
4657               loader->corruption_reason = validity;
4658             }
4659           return TRUE;
4660         }
4661     }
4662 
4663   return TRUE;
4664 }
4665 
4666 /**
4667  * Peeks at first loaded message, returns #NULL if no messages have
4668  * been queued.
4669  *
4670  * @param loader the loader.
4671  * @returns the next message, or #NULL if none.
4672  */
4673 DBusMessage*
_dbus_message_loader_peek_message(DBusMessageLoader * loader)4674 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
4675 {
4676   if (loader->messages)
4677     return loader->messages->data;
4678   else
4679     return NULL;
4680 }
4681 
4682 /**
4683  * Pops a loaded message (passing ownership of the message
4684  * to the caller). Returns #NULL if no messages have been
4685  * queued.
4686  *
4687  * @param loader the loader.
4688  * @returns the next message, or #NULL if none.
4689  */
4690 DBusMessage*
_dbus_message_loader_pop_message(DBusMessageLoader * loader)4691 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
4692 {
4693   return _dbus_list_pop_first (&loader->messages);
4694 }
4695 
4696 /**
4697  * Pops a loaded message inside a list link (passing ownership of the
4698  * message and link to the caller). Returns #NULL if no messages have
4699  * been loaded.
4700  *
4701  * @param loader the loader.
4702  * @returns the next message link, or #NULL if none.
4703  */
4704 DBusList*
_dbus_message_loader_pop_message_link(DBusMessageLoader * loader)4705 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
4706 {
4707   return _dbus_list_pop_first_link (&loader->messages);
4708 }
4709 
4710 /**
4711  * Returns a popped message link, used to undo a pop.
4712  *
4713  * @param loader the loader
4714  * @param link the link with a message in it
4715  */
4716 void
_dbus_message_loader_putback_message_link(DBusMessageLoader * loader,DBusList * link)4717 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
4718                                            DBusList           *link)
4719 {
4720   _dbus_list_prepend_link (&loader->messages, link);
4721 }
4722 
4723 /**
4724  * Checks whether the loader is confused due to bad data.
4725  * If messages are received that are invalid, the
4726  * loader gets confused and gives up permanently.
4727  * This state is called "corrupted."
4728  *
4729  * @param loader the loader
4730  * @returns #TRUE if the loader is hosed.
4731  */
4732 dbus_bool_t
_dbus_message_loader_get_is_corrupted(DBusMessageLoader * loader)4733 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
4734 {
4735   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4736                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4737   return loader->corrupted;
4738 }
4739 
4740 /**
4741  * Checks what kind of bad data confused the loader.
4742  *
4743  * @param loader the loader
4744  * @returns why the loader is hosed, or DBUS_VALID if it isn't.
4745  */
4746 DBusValidity
_dbus_message_loader_get_corruption_reason(DBusMessageLoader * loader)4747 _dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
4748 {
4749   _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4750                 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4751 
4752   return loader->corruption_reason;
4753 }
4754 
4755 /**
4756  * Sets the maximum size message we allow.
4757  *
4758  * @param loader the loader
4759  * @param size the max message size in bytes
4760  */
4761 void
_dbus_message_loader_set_max_message_size(DBusMessageLoader * loader,long size)4762 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
4763                                            long                size)
4764 {
4765   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
4766     {
4767       _dbus_verbose ("clamping requested max message size %ld to %d\n",
4768                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
4769       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
4770     }
4771   loader->max_message_size = size;
4772 }
4773 
4774 /**
4775  * Gets the maximum allowed message size in bytes.
4776  *
4777  * @param loader the loader
4778  * @returns max size in bytes
4779  */
4780 long
_dbus_message_loader_get_max_message_size(DBusMessageLoader * loader)4781 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
4782 {
4783   return loader->max_message_size;
4784 }
4785 
4786 /**
4787  * Sets the maximum unix fds per message we allow.
4788  *
4789  * @param loader the loader
4790  * @param n the max number of unix fds in a message
4791  */
4792 void
_dbus_message_loader_set_max_message_unix_fds(DBusMessageLoader * loader,long n)4793 _dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader  *loader,
4794                                                long                n)
4795 {
4796   if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
4797     {
4798       _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
4799                      n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
4800       n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
4801     }
4802   loader->max_message_unix_fds = n;
4803 }
4804 
4805 /**
4806  * Gets the maximum allowed number of unix fds per message
4807  *
4808  * @param loader the loader
4809  * @returns max unix fds
4810  */
4811 long
_dbus_message_loader_get_max_message_unix_fds(DBusMessageLoader * loader)4812 _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader  *loader)
4813 {
4814   return loader->max_message_unix_fds;
4815 }
4816 
4817 /**
4818  * Return how many file descriptors are pending in the loader
4819  *
4820  * @param loader the loader
4821  */
4822 int
_dbus_message_loader_get_pending_fds_count(DBusMessageLoader * loader)4823 _dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader)
4824 {
4825 #ifdef HAVE_UNIX_FD_PASSING
4826   return loader->n_unix_fds;
4827 #else
4828   return 0;
4829 #endif
4830 }
4831 
4832 /**
4833  * Register a function to be called whenever the number of pending file
4834  * descriptors in the loader change.
4835  *
4836  * @param loader the loader
4837  * @param callback the callback
4838  * @param data the data for the callback
4839  */
4840 void
_dbus_message_loader_set_pending_fds_function(DBusMessageLoader * loader,void (* callback)(void *),void * data)4841 _dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader,
4842                                                void (* callback) (void *),
4843                                                void *data)
4844 {
4845 #ifdef HAVE_UNIX_FD_PASSING
4846   loader->unix_fds_change = callback;
4847   loader->unix_fds_change_data = data;
4848 #endif
4849 }
4850 
4851 static DBusDataSlotAllocator slot_allocator =
4852   _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
4853 
4854 /**
4855  * Allocates an integer ID to be used for storing application-specific
4856  * data on any DBusMessage. The allocated ID may then be used
4857  * with dbus_message_set_data() and dbus_message_get_data().
4858  * The passed-in slot must be initialized to -1, and is filled in
4859  * with the slot ID. If the passed-in slot is not -1, it's assumed
4860  * to be already allocated, and its refcount is incremented.
4861  *
4862  * The allocated slot is global, i.e. all DBusMessage objects will
4863  * have a slot with the given integer ID reserved.
4864  *
4865  * @param slot_p address of a global variable storing the slot
4866  * @returns #FALSE on failure (no memory)
4867  */
4868 dbus_bool_t
dbus_message_allocate_data_slot(dbus_int32_t * slot_p)4869 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
4870 {
4871   return _dbus_data_slot_allocator_alloc (&slot_allocator,
4872                                           slot_p);
4873 }
4874 
4875 /**
4876  * Deallocates a global ID for message data slots.
4877  * dbus_message_get_data() and dbus_message_set_data() may no
4878  * longer be used with this slot.  Existing data stored on existing
4879  * DBusMessage objects will be freed when the message is
4880  * finalized, but may not be retrieved (and may only be replaced if
4881  * someone else reallocates the slot).  When the refcount on the
4882  * passed-in slot reaches 0, it is set to -1.
4883  *
4884  * @param slot_p address storing the slot to deallocate
4885  */
4886 void
dbus_message_free_data_slot(dbus_int32_t * slot_p)4887 dbus_message_free_data_slot (dbus_int32_t *slot_p)
4888 {
4889   _dbus_return_if_fail (*slot_p >= 0);
4890 
4891   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
4892 }
4893 
4894 /**
4895  * Stores a pointer on a DBusMessage, along
4896  * with an optional function to be used for freeing
4897  * the data when the data is set again, or when
4898  * the message is finalized. The slot number
4899  * must have been allocated with dbus_message_allocate_data_slot().
4900  *
4901  * @param message the message
4902  * @param slot the slot number
4903  * @param data the data to store
4904  * @param free_data_func finalizer function for the data
4905  * @returns #TRUE if there was enough memory to store the data
4906  */
4907 dbus_bool_t
dbus_message_set_data(DBusMessage * message,dbus_int32_t slot,void * data,DBusFreeFunction free_data_func)4908 dbus_message_set_data (DBusMessage     *message,
4909                        dbus_int32_t     slot,
4910                        void            *data,
4911                        DBusFreeFunction free_data_func)
4912 {
4913   DBusFreeFunction old_free_func;
4914   void *old_data;
4915   dbus_bool_t retval;
4916 
4917   _dbus_return_val_if_fail (message != NULL, FALSE);
4918   _dbus_return_val_if_fail (slot >= 0, FALSE);
4919 
4920   retval = _dbus_data_slot_list_set (&slot_allocator,
4921                                      &message->slot_list,
4922                                      slot, data, free_data_func,
4923                                      &old_free_func, &old_data);
4924 
4925   if (retval)
4926     {
4927       /* Do the actual free outside the message lock */
4928       if (old_free_func)
4929         (* old_free_func) (old_data);
4930     }
4931 
4932   return retval;
4933 }
4934 
4935 /**
4936  * Retrieves data previously set with dbus_message_set_data().
4937  * The slot must still be allocated (must not have been freed).
4938  *
4939  * @param message the message
4940  * @param slot the slot to get data from
4941  * @returns the data, or #NULL if not found
4942  */
4943 void*
dbus_message_get_data(DBusMessage * message,dbus_int32_t slot)4944 dbus_message_get_data (DBusMessage   *message,
4945                        dbus_int32_t   slot)
4946 {
4947   void *res;
4948 
4949   _dbus_return_val_if_fail (message != NULL, NULL);
4950 
4951   res = _dbus_data_slot_list_get (&slot_allocator,
4952                                   &message->slot_list,
4953                                   slot);
4954 
4955   return res;
4956 }
4957 
4958 /**
4959  * Utility function to convert a machine-readable (not translated)
4960  * string into a D-Bus message type.
4961  *
4962  * @code
4963  *   "method_call"    -> DBUS_MESSAGE_TYPE_METHOD_CALL
4964  *   "method_return"  -> DBUS_MESSAGE_TYPE_METHOD_RETURN
4965  *   "signal"         -> DBUS_MESSAGE_TYPE_SIGNAL
4966  *   "error"          -> DBUS_MESSAGE_TYPE_ERROR
4967  *   anything else    -> DBUS_MESSAGE_TYPE_INVALID
4968  * @endcode
4969  *
4970  */
4971 int
dbus_message_type_from_string(const char * type_str)4972 dbus_message_type_from_string (const char *type_str)
4973 {
4974   if (strcmp (type_str, "method_call") == 0)
4975     return DBUS_MESSAGE_TYPE_METHOD_CALL;
4976   if (strcmp (type_str, "method_return") == 0)
4977     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
4978   else if (strcmp (type_str, "signal") == 0)
4979     return DBUS_MESSAGE_TYPE_SIGNAL;
4980   else if (strcmp (type_str, "error") == 0)
4981     return DBUS_MESSAGE_TYPE_ERROR;
4982   else
4983     return DBUS_MESSAGE_TYPE_INVALID;
4984 }
4985 
4986 /**
4987  * Utility function to convert a D-Bus message type into a
4988  * machine-readable string (not translated).
4989  *
4990  * @code
4991  *   DBUS_MESSAGE_TYPE_METHOD_CALL    -> "method_call"
4992  *   DBUS_MESSAGE_TYPE_METHOD_RETURN  -> "method_return"
4993  *   DBUS_MESSAGE_TYPE_SIGNAL         -> "signal"
4994  *   DBUS_MESSAGE_TYPE_ERROR          -> "error"
4995  *   DBUS_MESSAGE_TYPE_INVALID        -> "invalid"
4996  * @endcode
4997  *
4998  */
4999 const char *
dbus_message_type_to_string(int type)5000 dbus_message_type_to_string (int type)
5001 {
5002   switch (type)
5003     {
5004     case DBUS_MESSAGE_TYPE_METHOD_CALL:
5005       return "method_call";
5006     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
5007       return "method_return";
5008     case DBUS_MESSAGE_TYPE_SIGNAL:
5009       return "signal";
5010     case DBUS_MESSAGE_TYPE_ERROR:
5011       return "error";
5012     default:
5013       return "invalid";
5014     }
5015 }
5016 
5017 /**
5018  * Turn a DBusMessage into the marshalled form as described in the D-Bus
5019  * specification.
5020  *
5021  * Generally, this function is only useful for encapsulating D-Bus messages in
5022  * a different protocol.
5023  *
5024  * @param msg the DBusMessage
5025  * @param marshalled_data_p the location to save the marshalled form to
5026  * @param len_p the location to save the length of the marshalled form to
5027  * @returns #FALSE if there was not enough memory
5028  */
5029 dbus_bool_t
dbus_message_marshal(DBusMessage * msg,char ** marshalled_data_p,int * len_p)5030 dbus_message_marshal (DBusMessage  *msg,
5031                       char        **marshalled_data_p,
5032                       int          *len_p)
5033 {
5034   DBusString tmp;
5035   dbus_bool_t was_locked;
5036 
5037   _dbus_return_val_if_fail (msg != NULL, FALSE);
5038   _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
5039   _dbus_return_val_if_fail (len_p != NULL, FALSE);
5040 
5041   if (!_dbus_string_init (&tmp))
5042     return FALSE;
5043 
5044   /* Ensure the message is locked, to ensure the length header is filled in. */
5045   was_locked = msg->locked;
5046 
5047   if (!was_locked)
5048     dbus_message_lock (msg);
5049 
5050   if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
5051     goto fail;
5052 
5053   *len_p = _dbus_string_get_length (&tmp);
5054 
5055   if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
5056     goto fail;
5057 
5058   *len_p = _dbus_string_get_length (&tmp);
5059 
5060   if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
5061     goto fail;
5062 
5063   _dbus_string_free (&tmp);
5064 
5065   if (!was_locked)
5066     msg->locked = FALSE;
5067 
5068   return TRUE;
5069 
5070  fail:
5071   _dbus_string_free (&tmp);
5072 
5073   if (!was_locked)
5074     msg->locked = FALSE;
5075 
5076   return FALSE;
5077 }
5078 
5079 /**
5080  * Demarshal a D-Bus message from the format described in the D-Bus
5081  * specification.
5082  *
5083  * Generally, this function is only useful for encapsulating D-Bus messages in
5084  * a different protocol.
5085  *
5086  * @param str the marshalled DBusMessage
5087  * @param len the length of str
5088  * @param error the location to save errors to
5089  * @returns #NULL if there was an error
5090  */
5091 DBusMessage *
dbus_message_demarshal(const char * str,int len,DBusError * error)5092 dbus_message_demarshal (const char *str,
5093                         int         len,
5094                         DBusError  *error)
5095 {
5096   DBusMessageLoader *loader;
5097   DBusString *buffer;
5098   DBusMessage *msg;
5099 
5100   _dbus_return_val_if_fail (str != NULL, NULL);
5101 
5102   loader = _dbus_message_loader_new ();
5103 
5104   if (loader == NULL)
5105     return NULL;
5106 
5107   _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
5108 
5109   if (!_dbus_string_append_len (buffer, str, len))
5110     goto fail_oom;
5111 
5112   _dbus_message_loader_return_buffer (loader, buffer);
5113 
5114   if (!_dbus_message_loader_queue_messages (loader))
5115     goto fail_oom;
5116 
5117   if (_dbus_message_loader_get_is_corrupted (loader))
5118     goto fail_corrupt;
5119 
5120   msg = _dbus_message_loader_pop_message (loader);
5121 
5122   if (!msg)
5123     goto fail_oom;
5124 
5125   _dbus_message_loader_unref (loader);
5126   return msg;
5127 
5128  fail_corrupt:
5129   dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
5130                   _dbus_validity_to_error_message (loader->corruption_reason));
5131   _dbus_message_loader_unref (loader);
5132   return NULL;
5133 
5134  fail_oom:
5135   _DBUS_SET_OOM (error);
5136   _dbus_message_loader_unref (loader);
5137   return NULL;
5138 }
5139 
5140 /**
5141  * Returns the number of bytes required to be in the buffer to demarshal a
5142  * D-Bus message.
5143  *
5144  * Generally, this function is only useful for encapsulating D-Bus messages in
5145  * a different protocol.
5146  *
5147  * @param buf data to be marshalled
5148  * @param len the length of @p buf
5149  * @returns -1 if there was no valid data to be demarshalled, 0 if there wasn't enough data to determine how much should be demarshalled. Otherwise returns the number of bytes to be demarshalled
5150  *
5151  */
5152 int
dbus_message_demarshal_bytes_needed(const char * buf,int len)5153 dbus_message_demarshal_bytes_needed(const char *buf,
5154                                     int         len)
5155 {
5156   DBusString str;
5157   int byte_order, fields_array_len, header_len, body_len;
5158   DBusValidity validity = DBUS_VALID;
5159   int have_message;
5160 
5161   if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
5162     return 0;
5163 
5164   if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
5165     len = DBUS_MAXIMUM_MESSAGE_LENGTH;
5166   _dbus_string_init_const_len (&str, buf, len);
5167 
5168   validity = DBUS_VALID;
5169   have_message
5170     = _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
5171                                           &validity, &byte_order,
5172                                           &fields_array_len,
5173                                           &header_len,
5174                                           &body_len,
5175                                           &str, 0,
5176                                           len);
5177   _dbus_string_free (&str);
5178 
5179   if (validity == DBUS_VALID)
5180     {
5181       _dbus_assert (have_message || (header_len + body_len) > len);
5182       (void) have_message; /* unused unless asserting */
5183       return header_len + body_len;
5184     }
5185   else
5186     {
5187       return -1; /* broken! */
5188     }
5189 }
5190 
5191 /**
5192  * Sets a flag indicating that the caller of the method is prepared
5193  * to wait for interactive authorization to take place (for instance
5194  * via Polkit) before the actual method is processed.
5195  *
5196  * The flag is #FALSE by default; that is, by default the other end is
5197  * expected to make any authorization decisions non-interactively
5198  * and promptly. It may use the error
5199  * #DBUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED to signal that
5200  * authorization failed, but could have succeeded if this flag had
5201  * been used.
5202  *
5203  * For messages whose type is not #DBUS_MESSAGE_TYPE_METHOD_CALL,
5204  * this flag is meaningless and should not be set.
5205  *
5206  * On the protocol level this toggles
5207  * #DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION.
5208  *
5209  * @param message the message
5210  * @param allow #TRUE if interactive authorization is acceptable
5211  */
5212 void
dbus_message_set_allow_interactive_authorization(DBusMessage * message,dbus_bool_t allow)5213 dbus_message_set_allow_interactive_authorization (DBusMessage *message,
5214                                                   dbus_bool_t  allow)
5215 {
5216   _dbus_return_if_fail (message != NULL);
5217   _dbus_return_if_fail (!message->locked);
5218 
5219   _dbus_header_toggle_flag (&message->header,
5220                             DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION,
5221                             allow);
5222 }
5223 
5224 /**
5225  * Returns whether the flag controlled by
5226  * dbus_message_set_allow_interactive_authorization() has been set.
5227  *
5228  * @param message the message
5229  */
5230 dbus_bool_t
dbus_message_get_allow_interactive_authorization(DBusMessage * message)5231 dbus_message_get_allow_interactive_authorization (DBusMessage *message)
5232 {
5233   _dbus_return_val_if_fail (message != NULL, FALSE);
5234 
5235   return _dbus_header_get_flag (&message->header,
5236                                 DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION);
5237 }
5238 
5239 /**
5240  * An opaque data structure containing the serialized form of any single
5241  * D-Bus message item, whose signature is a single complete type.
5242  *
5243  * (Implementation detail: It's serialized as a single variant.)
5244  */
5245 struct DBusVariant
5246 {
5247   DBusString data;
5248 };
5249 
5250 /**
5251  * Copy a single D-Bus message item from reader into a
5252  * newly-allocated #DBusVariant.
5253  *
5254  * For example, if a message contains three string arguments, and reader points
5255  * to the second string, the resulting DBusVariant will have signature
5256  * #DBUS_TYPE_STRING_AS_STRING and contain only that second string.
5257  *
5258  * @param reader An iterator over message items, pointing to one item to copy
5259  * @returns The variant, or #NULL if out of memory
5260  */
5261 DBusVariant *
_dbus_variant_read(DBusMessageIter * reader)5262 _dbus_variant_read (DBusMessageIter *reader)
5263 {
5264   DBusVariant *self = NULL;
5265   /* Points to the single item we will read from the reader */
5266   DBusMessageRealIter *real_reader = (DBusMessageRealIter *) reader;
5267   /* The position in self at which we will write a single variant
5268    * (it is position 0) */
5269   DBusTypeWriter items_writer;
5270   /* The position in self at which we will write a copy of reader
5271    * (it is inside the variant) */
5272   DBusTypeWriter variant_writer;
5273   /* 'v' */
5274   DBusString variant_signature;
5275   /* Whatever is the signature of the item we will copy from the reader */
5276   DBusString contained_signature;
5277   /* TRUE if self->data needs to be freed */
5278   dbus_bool_t data_inited = FALSE;
5279   /* The type of the item we will read from the reader */
5280   int type;
5281   /* The string, start position within that string, and length of the signature
5282    * of the single complete type of the item reader points to */
5283   const DBusString *sig;
5284   int start, len;
5285 
5286   _dbus_assert (_dbus_message_iter_check (real_reader));
5287   _dbus_assert (real_reader->iter_type == DBUS_MESSAGE_ITER_TYPE_READER);
5288   _dbus_string_init_const (&variant_signature, DBUS_TYPE_VARIANT_AS_STRING);
5289   type = dbus_message_iter_get_arg_type (reader);
5290   _dbus_type_reader_get_signature (&real_reader->u.reader, &sig, &start, &len);
5291 
5292   if (!_dbus_string_init (&contained_signature))
5293     return NULL;
5294 
5295   if (!_dbus_string_copy_len (sig, start, len, &contained_signature, 0))
5296     goto oom;
5297 
5298   self = dbus_new0 (DBusVariant, 1);
5299 
5300   if (self == NULL)
5301     goto oom;
5302 
5303   if (!_dbus_string_init (&self->data))
5304     goto oom;
5305 
5306   data_inited = TRUE;
5307 
5308   _dbus_type_writer_init_values_only (&items_writer, DBUS_COMPILER_BYTE_ORDER,
5309                                       &variant_signature, 0, &self->data, 0);
5310 
5311   if (!_dbus_type_writer_recurse (&items_writer, DBUS_TYPE_VARIANT,
5312                                   &contained_signature, 0, &variant_writer))
5313     goto oom;
5314 
5315   if (type == DBUS_TYPE_ARRAY)
5316     {
5317       /* Points to each item in turn inside the array we are copying */
5318       DBusMessageIter array_reader;
5319       /* Same as array_reader */
5320       DBusMessageRealIter *real_array_reader = (DBusMessageRealIter *) &array_reader;
5321       /* The position inside the copied array at which we will write
5322        * the copy of array_reader */
5323       DBusTypeWriter array_writer;
5324 
5325       dbus_message_iter_recurse (reader, &array_reader);
5326 
5327       if (!_dbus_type_writer_recurse (&variant_writer, type,
5328                                       &contained_signature, 1, &array_writer))
5329         goto oom;
5330 
5331       if (!_dbus_type_writer_write_reader (&array_writer,
5332                                            &real_array_reader->u.reader))
5333         goto oom;
5334 
5335       if (!_dbus_type_writer_unrecurse (&variant_writer, &array_writer))
5336         goto oom;
5337     }
5338   else if (type == DBUS_TYPE_DICT_ENTRY || type == DBUS_TYPE_VARIANT ||
5339            type == DBUS_TYPE_STRUCT)
5340     {
5341       /* Points to each item in turn inside the container we are copying */
5342       DBusMessageIter inner_reader;
5343       /* Same as inner_reader */
5344       DBusMessageRealIter *real_inner_reader = (DBusMessageRealIter *) &inner_reader;
5345       /* The position inside the copied container at which we will write the
5346        * copy of inner_reader */
5347       DBusTypeWriter inner_writer;
5348 
5349       dbus_message_iter_recurse (reader, &inner_reader);
5350 
5351       if (!_dbus_type_writer_recurse (&variant_writer, type, NULL, 0,
5352                                       &inner_writer))
5353         goto oom;
5354 
5355       if (!_dbus_type_writer_write_reader (&inner_writer,
5356                                            &real_inner_reader->u.reader))
5357         goto oom;
5358 
5359       if (!_dbus_type_writer_unrecurse (&variant_writer, &inner_writer))
5360         goto oom;
5361     }
5362   else
5363     {
5364       DBusBasicValue value;
5365 
5366       /* We eliminated all the container types above */
5367       _dbus_assert (dbus_type_is_basic (type));
5368 
5369       dbus_message_iter_get_basic (reader, &value);
5370 
5371       if (!_dbus_type_writer_write_basic (&variant_writer, type, &value))
5372         goto oom;
5373     }
5374 
5375   _dbus_string_free (&contained_signature);
5376   return self;
5377 
5378 oom:
5379   if (self != NULL)
5380     {
5381       if (data_inited)
5382         _dbus_string_free (&self->data);
5383 
5384       dbus_free (self);
5385     }
5386 
5387   _dbus_string_free (&contained_signature);
5388   return NULL;
5389 }
5390 
5391 /**
5392  * Return the signature of the item stored in self. It is a single complete
5393  * type.
5394  *
5395  * @param self the variant
5396  */
5397 const char *
_dbus_variant_get_signature(DBusVariant * self)5398 _dbus_variant_get_signature (DBusVariant *self)
5399 {
5400   unsigned char len;
5401   const char *ret;
5402 
5403   _dbus_assert (self != NULL);
5404 
5405   /* Here we make use of the fact that the serialization of a variant starts
5406    * with the 1-byte length, then that many bytes of signature, then \0. */
5407   len = _dbus_string_get_byte (&self->data, 0);
5408   ret = _dbus_string_get_const_data_len (&self->data, 1, len);
5409   _dbus_assert (strlen (ret) == len);
5410   return ret;
5411 }
5412 
5413 /**
5414  * Copy the single D-Bus message item from self into writer.
5415  *
5416  * For example, if writer points into the body of an empty message and self has
5417  * signature #DBUS_TYPE_STRING_AS_STRING, then the message will
5418  * have signature #DBUS_TYPE_STRING_AS_STRING after this function returns
5419  *
5420  * @param self the variant
5421  * @param writer the place to write the contents of the variant
5422  * @returns #TRUE on success, #FALSE if out of memory
5423  */
5424 dbus_bool_t
_dbus_variant_write(DBusVariant * self,DBusMessageIter * writer)5425 _dbus_variant_write (DBusVariant *self,
5426                      DBusMessageIter *writer)
5427 {
5428   /* 'v' */
5429   DBusString variant_signature;
5430   /* Points to the single item in self */
5431   DBusTypeReader variant_reader;
5432   /* Points to the single item (of whatever type) inside the variant */
5433   DBusTypeReader reader;
5434   /* The position at which we will copy reader */
5435   DBusMessageRealIter *real_writer = (DBusMessageRealIter *) writer;
5436   dbus_bool_t ret;
5437 
5438   _dbus_assert (self != NULL);
5439   _dbus_assert (_dbus_message_iter_append_check (real_writer));
5440   _dbus_assert (real_writer->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
5441 
5442   _dbus_string_init_const (&variant_signature, DBUS_TYPE_VARIANT_AS_STRING);
5443   _dbus_type_reader_init (&reader, DBUS_COMPILER_BYTE_ORDER,
5444                           &variant_signature, 0, &self->data, 0);
5445   _dbus_type_reader_recurse (&reader, &variant_reader);
5446 
5447   if (!_dbus_message_iter_open_signature (real_writer))
5448     return FALSE;
5449 
5450   ret = _dbus_type_writer_write_reader (&real_writer->u.writer,
5451                                         &variant_reader);
5452 
5453   if (!_dbus_message_iter_close_signature (real_writer))
5454     return FALSE;
5455 
5456   return ret;
5457 }
5458 
5459 int
_dbus_variant_get_length(DBusVariant * self)5460 _dbus_variant_get_length (DBusVariant *self)
5461 {
5462   _dbus_assert (self != NULL);
5463   return _dbus_string_get_length (&self->data);
5464 }
5465 
5466 const DBusString *
_dbus_variant_peek(DBusVariant * self)5467 _dbus_variant_peek (DBusVariant *self)
5468 {
5469   _dbus_assert (self != NULL);
5470   return &self->data;
5471 }
5472 
5473 void
_dbus_variant_free(DBusVariant * self)5474 _dbus_variant_free (DBusVariant *self)
5475 {
5476   _dbus_assert (self != NULL);
5477   _dbus_string_free (&self->data);
5478   dbus_free (self);
5479 }
5480 
5481 /** @} */
5482 
5483 /* tests in dbus-message-util.c */
5484