1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
26 #include "gdbusutils.h"
32 * @title: D-Bus Utilities
33 * @short_description: Various utilities related to D-Bus
36 * Various utility routines related to D-Bus.
40 is_valid_bus_name_character (gint c
,
41 gboolean allow_hyphen
)
44 (c
>= '0' && c
<= '9') ||
45 (c
>= 'A' && c
<= 'Z') ||
46 (c
>= 'a' && c
<= 'z') ||
48 (allow_hyphen
&& c
== '-');
52 is_valid_initial_bus_name_character (gint c
,
53 gboolean allow_initial_digit
,
54 gboolean allow_hyphen
)
56 if (allow_initial_digit
)
57 return is_valid_bus_name_character (c
, allow_hyphen
);
60 (c
>= 'A' && c
<= 'Z') ||
61 (c
>= 'a' && c
<= 'z') ||
63 (allow_hyphen
&& c
== '-');
67 is_valid_name (const gchar
*start
,
69 gboolean allow_initial_digit
,
70 gboolean allow_hyphen
)
90 if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s
, allow_initial_digit
, allow_hyphen
)))
94 else if (G_UNLIKELY (!is_valid_bus_name_character (*s
, allow_hyphen
)))
101 if (G_UNLIKELY (!has_dot
))
112 * @string: The string to check.
114 * Checks if @string is a valid D-Bus bus name (either unique or well-known).
116 * Returns: %TRUE if valid, %FALSE otherwise.
121 g_dbus_is_name (const gchar
*string
)
127 g_return_val_if_fail (string
!= NULL
, FALSE
);
131 len
= strlen (string
);
132 if (G_UNLIKELY (len
== 0 || len
> 255))
138 /* handle unique name */
139 if (!is_valid_name (s
+ 1, len
- 1, TRUE
, TRUE
))
144 else if (G_UNLIKELY (*s
== '.'))
146 /* can't start with a . */
149 else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s
, FALSE
, TRUE
)))
152 ret
= is_valid_name (s
+ 1, len
- 1, FALSE
, TRUE
);
159 * g_dbus_is_unique_name:
160 * @string: The string to check.
162 * Checks if @string is a valid D-Bus unique bus name.
164 * Returns: %TRUE if valid, %FALSE otherwise.
169 g_dbus_is_unique_name (const gchar
*string
)
174 g_return_val_if_fail (string
!= NULL
, FALSE
);
178 len
= strlen (string
);
179 if (G_UNLIKELY (len
== 0 || len
> 255))
182 if (G_UNLIKELY (*string
!= ':'))
185 if (G_UNLIKELY (!is_valid_name (string
+ 1, len
- 1, TRUE
, TRUE
)))
195 * g_dbus_is_member_name:
196 * @string: The string to check.
198 * Checks if @string is a valid D-Bus member (e.g. signal or method) name.
200 * Returns: %TRUE if valid, %FALSE otherwise.
205 g_dbus_is_member_name (const gchar
*string
)
211 if (G_UNLIKELY (string
== NULL
))
214 if (G_UNLIKELY (!is_valid_initial_bus_name_character (string
[0], FALSE
, FALSE
)))
217 for (n
= 1; string
[n
] != '\0'; n
++)
219 if (G_UNLIKELY (!is_valid_bus_name_character (string
[n
], FALSE
)))
232 * g_dbus_is_interface_name:
233 * @string: The string to check.
235 * Checks if @string is a valid D-Bus interface name.
237 * Returns: %TRUE if valid, %FALSE otherwise.
242 g_dbus_is_interface_name (const gchar
*string
)
248 g_return_val_if_fail (string
!= NULL
, FALSE
);
252 len
= strlen (string
);
253 if (G_UNLIKELY (len
== 0 || len
> 255))
257 if (G_UNLIKELY (*s
== '.'))
259 /* can't start with a . */
262 else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s
, FALSE
, FALSE
)))
265 ret
= is_valid_name (s
+ 1, len
- 1, FALSE
, FALSE
);
271 /* ---------------------------------------------------------------------------------------------------- */
273 /* TODO: maybe move to glib? if so, it should conform to http://en.wikipedia.org/wiki/Guid and/or
274 * http://tools.ietf.org/html/rfc4122 - specifically it should have hyphens then.
278 * g_dbus_generate_guid:
280 * Generate a D-Bus GUID that can be used with
281 * e.g. g_dbus_connection_new().
283 * See the D-Bus specification regarding what strings are valid D-Bus
284 * GUID (for example, D-Bus GUIDs are not RFC-4122 compliant).
286 * Returns: A valid D-Bus GUID. Free with g_free().
291 g_dbus_generate_guid (void)
299 s
= g_string_new (NULL
);
301 r1
= g_random_int ();
302 r2
= g_random_int ();
303 r3
= g_random_int ();
304 g_get_current_time (&now
);
306 g_string_append_printf (s
, "%08x", r1
);
307 g_string_append_printf (s
, "%08x", r2
);
308 g_string_append_printf (s
, "%08x", r3
);
309 g_string_append_printf (s
, "%08x", (guint32
) now
.tv_sec
);
311 return g_string_free (s
, FALSE
);
316 * @string: The string to check.
318 * Checks if @string is a D-Bus GUID.
320 * See the D-Bus specification regarding what strings are valid D-Bus
321 * GUID (for example, D-Bus GUIDs are not RFC-4122 compliant).
323 * Returns: %TRUE if @string is a guid, %FALSE otherwise.
328 g_dbus_is_guid (const gchar
*string
)
333 g_return_val_if_fail (string
!= NULL
, FALSE
);
337 for (n
= 0; n
< 32; n
++)
339 if (!g_ascii_isxdigit (string
[n
]))
342 if (string
[32] != '\0')
351 /* ---------------------------------------------------------------------------------------------------- */
354 * g_dbus_gvariant_to_gvalue:
355 * @value: A #GVariant.
356 * @out_gvalue: (out): Return location pointing to a zero-filled (uninitialized) #GValue.
358 * Converts a #GVariant to a #GValue. If @value is floating, it is consumed.
360 * The rules specified in the g_dbus_gvalue_to_gvariant() function are
361 * used - this function is essentially its reverse form. So, a #GVariant
362 * containing any basic or string array type will be converted to a #GValue
363 * containing a basic value or string array. Any other #GVariant (handle,
364 * variant, tuple, dict entry) will be converted to a #GValue containing that
367 * The conversion never fails - a valid #GValue is always returned in
373 g_dbus_gvariant_to_gvalue (GVariant
*value
,
376 const GVariantType
*type
;
379 g_return_if_fail (value
!= NULL
);
380 g_return_if_fail (out_gvalue
!= NULL
);
382 memset (out_gvalue
, '\0', sizeof (GValue
));
384 switch (g_variant_classify (value
))
386 case G_VARIANT_CLASS_BOOLEAN
:
387 g_value_init (out_gvalue
, G_TYPE_BOOLEAN
);
388 g_value_set_boolean (out_gvalue
, g_variant_get_boolean (value
));
391 case G_VARIANT_CLASS_BYTE
:
392 g_value_init (out_gvalue
, G_TYPE_UCHAR
);
393 g_value_set_uchar (out_gvalue
, g_variant_get_byte (value
));
396 case G_VARIANT_CLASS_INT16
:
397 g_value_init (out_gvalue
, G_TYPE_INT
);
398 g_value_set_int (out_gvalue
, g_variant_get_int16 (value
));
401 case G_VARIANT_CLASS_UINT16
:
402 g_value_init (out_gvalue
, G_TYPE_UINT
);
403 g_value_set_uint (out_gvalue
, g_variant_get_uint16 (value
));
406 case G_VARIANT_CLASS_INT32
:
407 g_value_init (out_gvalue
, G_TYPE_INT
);
408 g_value_set_int (out_gvalue
, g_variant_get_int32 (value
));
411 case G_VARIANT_CLASS_UINT32
:
412 g_value_init (out_gvalue
, G_TYPE_UINT
);
413 g_value_set_uint (out_gvalue
, g_variant_get_uint32 (value
));
416 case G_VARIANT_CLASS_INT64
:
417 g_value_init (out_gvalue
, G_TYPE_INT64
);
418 g_value_set_int64 (out_gvalue
, g_variant_get_int64 (value
));
421 case G_VARIANT_CLASS_UINT64
:
422 g_value_init (out_gvalue
, G_TYPE_UINT64
);
423 g_value_set_uint64 (out_gvalue
, g_variant_get_uint64 (value
));
426 case G_VARIANT_CLASS_DOUBLE
:
427 g_value_init (out_gvalue
, G_TYPE_DOUBLE
);
428 g_value_set_double (out_gvalue
, g_variant_get_double (value
));
431 case G_VARIANT_CLASS_STRING
:
432 g_value_init (out_gvalue
, G_TYPE_STRING
);
433 g_value_set_string (out_gvalue
, g_variant_get_string (value
, NULL
));
436 case G_VARIANT_CLASS_OBJECT_PATH
:
437 g_value_init (out_gvalue
, G_TYPE_STRING
);
438 g_value_set_string (out_gvalue
, g_variant_get_string (value
, NULL
));
441 case G_VARIANT_CLASS_SIGNATURE
:
442 g_value_init (out_gvalue
, G_TYPE_STRING
);
443 g_value_set_string (out_gvalue
, g_variant_get_string (value
, NULL
));
446 case G_VARIANT_CLASS_ARRAY
:
447 type
= g_variant_get_type (value
);
448 switch (g_variant_type_peek_string (type
)[1])
450 case G_VARIANT_CLASS_BYTE
:
451 g_value_init (out_gvalue
, G_TYPE_STRING
);
452 g_value_set_string (out_gvalue
, g_variant_get_bytestring (value
));
455 case G_VARIANT_CLASS_STRING
:
456 g_value_init (out_gvalue
, G_TYPE_STRV
);
457 array
= g_variant_dup_strv (value
, NULL
);
458 g_value_take_boxed (out_gvalue
, array
);
461 case G_VARIANT_CLASS_OBJECT_PATH
:
462 g_value_init (out_gvalue
, G_TYPE_STRV
);
463 array
= g_variant_dup_objv (value
, NULL
);
464 g_value_take_boxed (out_gvalue
, array
);
467 case G_VARIANT_CLASS_ARRAY
:
468 switch (g_variant_type_peek_string (type
)[2])
470 case G_VARIANT_CLASS_BYTE
:
471 g_value_init (out_gvalue
, G_TYPE_STRV
);
472 array
= g_variant_dup_bytestring_array (value
, NULL
);
473 g_value_take_boxed (out_gvalue
, array
);
477 g_value_init (out_gvalue
, G_TYPE_VARIANT
);
478 g_value_set_variant (out_gvalue
, value
);
484 g_value_init (out_gvalue
, G_TYPE_VARIANT
);
485 g_value_set_variant (out_gvalue
, value
);
490 case G_VARIANT_CLASS_HANDLE
:
491 case G_VARIANT_CLASS_VARIANT
:
492 case G_VARIANT_CLASS_MAYBE
:
493 case G_VARIANT_CLASS_TUPLE
:
494 case G_VARIANT_CLASS_DICT_ENTRY
:
495 g_value_init (out_gvalue
, G_TYPE_VARIANT
);
496 g_value_set_variant (out_gvalue
, value
);
503 * g_dbus_gvalue_to_gvariant:
504 * @gvalue: A #GValue to convert to a #GVariant
505 * @type: A #GVariantType
507 * Converts a #GValue to a #GVariant of the type indicated by the @type
510 * The conversion is using the following rules:
512 * - #G_TYPE_STRING: 's', 'o', 'g' or 'ay'
513 * - #G_TYPE_STRV: 'as', 'ao' or 'aay'
514 * - #G_TYPE_BOOLEAN: 'b'
515 * - #G_TYPE_UCHAR: 'y'
516 * - #G_TYPE_INT: 'i', 'n'
517 * - #G_TYPE_UINT: 'u', 'q'
518 * - #G_TYPE_INT64 'x'
519 * - #G_TYPE_UINT64: 't'
520 * - #G_TYPE_DOUBLE: 'd'
521 * - #G_TYPE_VARIANT: Any #GVariantType
523 * This can fail if e.g. @gvalue is of type #G_TYPE_STRING and @type
524 * is ['i'][G-VARIANT-TYPE-INT32:CAPS]. It will also fail for any #GType
525 * (including e.g. #G_TYPE_OBJECT and #G_TYPE_BOXED derived-types) not
526 * in the table above.
528 * Note that if @gvalue is of type #G_TYPE_VARIANT and its value is
529 * %NULL, the empty #GVariant instance (never %NULL) for @type is
530 * returned (e.g. 0 for scalar types, the empty string for string types,
531 * '/' for object path types, the empty array for any array type and so on).
533 * See the g_dbus_gvariant_to_gvalue() function for how to convert a
534 * #GVariant to a #GValue.
536 * Returns: A #GVariant (never floating) of #GVariantType @type holding
537 * the data from @gvalue or %NULL in case of failure. Free with
543 g_dbus_gvalue_to_gvariant (const GValue
*gvalue
,
544 const GVariantType
*type
)
548 const gchar
* const *as
;
549 const gchar
*empty_strv
[1] = {NULL
};
551 g_return_val_if_fail (gvalue
!= NULL
, NULL
);
552 g_return_val_if_fail (type
!= NULL
, NULL
);
556 /* @type can easily be e.g. "s" with the GValue holding a GVariant - for example this
557 * can happen when using the org.gtk.GDBus.C.ForceGVariant annotation with the
558 * gdbus-codegen(1) tool.
560 if (G_VALUE_TYPE (gvalue
) == G_TYPE_VARIANT
)
562 ret
= g_value_dup_variant (gvalue
);
566 switch (g_variant_type_peek_string (type
)[0])
568 case G_VARIANT_CLASS_BOOLEAN
:
569 ret
= g_variant_ref_sink (g_variant_new_boolean (g_value_get_boolean (gvalue
)));
572 case G_VARIANT_CLASS_BYTE
:
573 ret
= g_variant_ref_sink (g_variant_new_byte (g_value_get_uchar (gvalue
)));
576 case G_VARIANT_CLASS_INT16
:
577 ret
= g_variant_ref_sink (g_variant_new_int16 (g_value_get_int (gvalue
)));
580 case G_VARIANT_CLASS_UINT16
:
581 ret
= g_variant_ref_sink (g_variant_new_uint16 (g_value_get_uint (gvalue
)));
584 case G_VARIANT_CLASS_INT32
:
585 ret
= g_variant_ref_sink (g_variant_new_int32 (g_value_get_int (gvalue
)));
588 case G_VARIANT_CLASS_UINT32
:
589 ret
= g_variant_ref_sink (g_variant_new_uint32 (g_value_get_uint (gvalue
)));
592 case G_VARIANT_CLASS_INT64
:
593 ret
= g_variant_ref_sink (g_variant_new_int64 (g_value_get_int64 (gvalue
)));
596 case G_VARIANT_CLASS_UINT64
:
597 ret
= g_variant_ref_sink (g_variant_new_uint64 (g_value_get_uint64 (gvalue
)));
600 case G_VARIANT_CLASS_DOUBLE
:
601 ret
= g_variant_ref_sink (g_variant_new_double (g_value_get_double (gvalue
)));
604 case G_VARIANT_CLASS_STRING
:
605 s
= g_value_get_string (gvalue
);
608 ret
= g_variant_ref_sink (g_variant_new_string (s
));
611 case G_VARIANT_CLASS_OBJECT_PATH
:
612 s
= g_value_get_string (gvalue
);
615 ret
= g_variant_ref_sink (g_variant_new_object_path (s
));
618 case G_VARIANT_CLASS_SIGNATURE
:
619 s
= g_value_get_string (gvalue
);
622 ret
= g_variant_ref_sink (g_variant_new_signature (s
));
625 case G_VARIANT_CLASS_ARRAY
:
626 switch (g_variant_type_peek_string (type
)[1])
628 case G_VARIANT_CLASS_BYTE
:
629 s
= g_value_get_string (gvalue
);
632 ret
= g_variant_ref_sink (g_variant_new_bytestring (s
));
635 case G_VARIANT_CLASS_STRING
:
636 as
= g_value_get_boxed (gvalue
);
639 ret
= g_variant_ref_sink (g_variant_new_strv (as
, -1));
642 case G_VARIANT_CLASS_OBJECT_PATH
:
643 as
= g_value_get_boxed (gvalue
);
646 ret
= g_variant_ref_sink (g_variant_new_objv (as
, -1));
649 case G_VARIANT_CLASS_ARRAY
:
650 switch (g_variant_type_peek_string (type
)[2])
652 case G_VARIANT_CLASS_BYTE
:
653 as
= g_value_get_boxed (gvalue
);
656 ret
= g_variant_ref_sink (g_variant_new_bytestring_array (as
, -1));
660 ret
= g_value_dup_variant (gvalue
);
666 ret
= g_value_dup_variant (gvalue
);
671 case G_VARIANT_CLASS_HANDLE
:
672 case G_VARIANT_CLASS_VARIANT
:
673 case G_VARIANT_CLASS_MAYBE
:
674 case G_VARIANT_CLASS_TUPLE
:
675 case G_VARIANT_CLASS_DICT_ENTRY
:
676 ret
= g_value_dup_variant (gvalue
);
681 /* Could be that the GValue is holding a NULL GVariant - in that case,
682 * we return an "empty" GVariant instead of a NULL GVariant
686 GVariant
*untrusted_empty
;
687 untrusted_empty
= g_variant_new_from_data (type
, NULL
, 0, FALSE
, NULL
, NULL
);
688 ret
= g_variant_take_ref (g_variant_get_normal_form (untrusted_empty
));
689 g_variant_unref (untrusted_empty
);
692 g_assert (!g_variant_is_floating (ret
));