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 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, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: David Zeuthen <davidz@redhat.com>
28 #include "gdbusutils.h"
34 * @title: D-Bus Utilities
35 * @short_description: Various utilities related to D-Bus.
38 * Various utility routines related to D-Bus.
42 is_valid_bus_name_character (gint c,
43 gboolean allow_hyphen)
46 (c >= '0' && c <= '9') ||
47 (c >= 'A' && c <= 'Z') ||
48 (c >= 'a' && c <= 'z') ||
50 (allow_hyphen && c == '-');
54 is_valid_initial_bus_name_character (gint c,
55 gboolean allow_initial_digit,
56 gboolean allow_hyphen)
58 if (allow_initial_digit)
59 return is_valid_bus_name_character (c, allow_hyphen);
62 (c >= 'A' && c <= 'Z') ||
63 (c >= 'a' && c <= 'z') ||
65 (allow_hyphen && c == '-');
69 is_valid_name (const gchar *start,
71 gboolean allow_initial_digit,
72 gboolean allow_hyphen)
92 if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, allow_initial_digit, allow_hyphen)))
96 else if (G_UNLIKELY (!is_valid_bus_name_character (*s, allow_hyphen)))
103 if (G_UNLIKELY (!has_dot))
114 * @string: The string to check.
116 * Checks if @string is a valid D-Bus bus name (either unique or well-known).
118 * Returns: %TRUE if valid, %FALSE otherwise.
123 g_dbus_is_name (const gchar *string)
129 g_return_val_if_fail (string != NULL, FALSE);
133 len = strlen (string);
134 if (G_UNLIKELY (len == 0 || len > 255))
140 /* handle unique name */
141 if (!is_valid_name (s + 1, len - 1, TRUE, TRUE))
146 else if (G_UNLIKELY (*s == '.'))
148 /* can't start with a . */
151 else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, TRUE)))
154 ret = is_valid_name (s + 1, len - 1, FALSE, TRUE);
161 * g_dbus_is_unique_name:
162 * @string: The string to check.
164 * Checks if @string is a valid D-Bus unique bus name.
166 * Returns: %TRUE if valid, %FALSE otherwise.
171 g_dbus_is_unique_name (const gchar *string)
176 g_return_val_if_fail (string != NULL, FALSE);
180 len = strlen (string);
181 if (G_UNLIKELY (len == 0 || len > 255))
184 if (G_UNLIKELY (*string != ':'))
187 if (G_UNLIKELY (!is_valid_name (string + 1, len - 1, TRUE, TRUE)))
197 * g_dbus_is_member_name:
198 * @string: The string to check.
200 * Checks if @string is a valid D-Bus member (e.g. signal or method) name.
202 * Returns: %TRUE if valid, %FALSE otherwise.
207 g_dbus_is_member_name (const gchar *string)
213 if (G_UNLIKELY (string == NULL))
216 if (G_UNLIKELY (!is_valid_initial_bus_name_character (string[0], FALSE, FALSE)))
219 for (n = 1; string[n] != '\0'; n++)
221 if (G_UNLIKELY (!is_valid_bus_name_character (string[n], FALSE)))
234 * g_dbus_is_interface_name:
235 * @string: The string to check.
237 * Checks if @string is a valid D-Bus interface name.
239 * Returns: %TRUE if valid, %FALSE otherwise.
244 g_dbus_is_interface_name (const gchar *string)
250 g_return_val_if_fail (string != NULL, FALSE);
254 len = strlen (string);
255 if (G_UNLIKELY (len == 0 || len > 255))
259 if (G_UNLIKELY (*s == '.'))
261 /* can't start with a . */
264 else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, FALSE)))
267 ret = is_valid_name (s + 1, len - 1, FALSE, FALSE);
273 /* ---------------------------------------------------------------------------------------------------- */
275 /* TODO: maybe move to glib? if so, it should conform to http://en.wikipedia.org/wiki/Guid and/or
276 * http://tools.ietf.org/html/rfc4122 - specifically it should have hyphens then.
280 * g_dbus_generate_guid:
282 * Generate a D-Bus GUID that can be used with
283 * e.g. g_dbus_connection_new().
285 * See the D-Bus specification regarding what strings are valid D-Bus
286 * GUID (for example, D-Bus GUIDs are not RFC-4122 compliant).
288 * Returns: A valid D-Bus GUID. Free with g_free().
293 g_dbus_generate_guid (void)
301 s = g_string_new (NULL);
303 r1 = g_random_int ();
304 r2 = g_random_int ();
305 r3 = g_random_int ();
306 g_get_current_time (&now);
308 g_string_append_printf (s, "%08x", r1);
309 g_string_append_printf (s, "%08x", r2);
310 g_string_append_printf (s, "%08x", r3);
311 g_string_append_printf (s, "%08x", (guint32) now.tv_sec);
313 return g_string_free (s, FALSE);
318 * @string: The string to check.
320 * Checks if @string is a D-Bus GUID.
322 * See the D-Bus specification regarding what strings are valid D-Bus
323 * GUID (for example, D-Bus GUIDs are not RFC-4122 compliant).
325 * Returns: %TRUE if @string is a guid, %FALSE otherwise.
330 g_dbus_is_guid (const gchar *string)
335 g_return_val_if_fail (string != NULL, FALSE);
339 for (n = 0; n < 32; n++)
341 if (!g_ascii_isxdigit (string[n]))
344 if (string[32] != '\0')
353 /* ---------------------------------------------------------------------------------------------------- */
356 * g_dbus_gvariant_to_gvalue:
357 * @value: A #GVariant.
358 * @out_gvalue: Return location for the #GValue.
360 * Convert a #GVariant to a #GValue. If @value is floating, it is consumed.
362 * The rules specified in g_dbus_gvalue_to_gvariant() are used.
364 * Note that the passed @out_gvalue does not have to have a #GType
365 * set, as it will be initialized to the #GType corresponding to
368 * This conversion can never fail.
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_HANDLE:
427 g_value_init (out_gvalue, G_TYPE_INT);
428 g_value_set_int (out_gvalue, g_variant_get_int32 (value));
431 case G_VARIANT_CLASS_DOUBLE:
432 g_value_init (out_gvalue, G_TYPE_DOUBLE);
433 g_value_set_double (out_gvalue, g_variant_get_double (value));
436 case G_VARIANT_CLASS_STRING:
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_OBJECT_PATH:
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_SIGNATURE:
447 g_value_init (out_gvalue, G_TYPE_STRING);
448 g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
451 case G_VARIANT_CLASS_ARRAY:
452 type = g_variant_get_type (value);
453 switch (g_variant_type_peek_string (type)[1])
455 case G_VARIANT_CLASS_BYTE:
456 g_value_init (out_gvalue, G_TYPE_STRING);
457 g_value_set_string (out_gvalue, g_variant_get_bytestring (value));
460 case G_VARIANT_CLASS_STRING:
461 g_value_init (out_gvalue, G_TYPE_STRV);
462 array = g_variant_dup_strv (value, NULL);
463 g_value_take_boxed (out_gvalue, array);
466 case G_VARIANT_CLASS_ARRAY:
467 switch (g_variant_type_peek_string (type)[2])
469 case G_VARIANT_CLASS_BYTE:
470 g_value_init (out_gvalue, G_TYPE_STRV);
471 array = g_variant_dup_bytestring_array (value, NULL);
472 g_value_take_boxed (out_gvalue, array);
476 g_value_init (out_gvalue, G_TYPE_VARIANT);
477 g_value_set_variant (out_gvalue, value);
483 g_value_init (out_gvalue, G_TYPE_VARIANT);
484 g_value_set_variant (out_gvalue, value);
489 case G_VARIANT_CLASS_VARIANT:
490 case G_VARIANT_CLASS_MAYBE:
491 case G_VARIANT_CLASS_TUPLE:
492 case G_VARIANT_CLASS_DICT_ENTRY:
493 g_value_init (out_gvalue, G_TYPE_VARIANT);
494 g_value_set_variant (out_gvalue, value);
501 * g_dbus_gvalue_to_gvariant:
502 * @gvalue: A #GValue to convert to a #GVariant.
503 * @expected_type: The #GVariantType to create.
505 * Convert a #GValue to #GVariant.
507 * The conversion is using the following rules:
508 * <table frame='all'>
509 * <title>#GValue / #GVariant conversion rules</title>
510 * <tgroup cols='2' align='left' colsep='1' rowsep='1'>
513 * <entry>If the #GType for @gvalue is...</entry>
514 * <entry>... then @expected_type must be</entry>
519 * <entry>#G_TYPE_STRING</entry>
520 * <entry><link linkend="G-VARIANT-TYPE-STRING:CAPS">s</link>, <link linkend="G-VARIANT-TYPE-OBJECT-PATH:CAPS">o</link>, <link linkend="G-VARIANT-TYPE-SIGNATURE:CAPS">g</link>, <link linkend="G-VARIANT-TYPE-BYTESTRING:CAPS">ay</link></entry>
523 * <entry>#G_TYPE_STRV</entry>
524 * <entry><link linkend="G-VARIANT-TYPE-STRING-ARRAY:CAPS">as</link>, <link linkend="G-VARIANT-TYPE-BYTESTRING-ARRAY:CAPS">aay</link></entry>
527 * <entry>#G_TYPE_BOOLEAN</entry>
528 * <entry><link linkend="G-VARIANT-TYPE-BOOLEAN:CAPS">b</link></entry>
531 * <entry>#G_TYPE_UCHAR</entry>
532 * <entry><link linkend="G-VARIANT-TYPE-BYTE:CAPS">y</link></entry>
535 * <entry>#G_TYPE_INT</entry>
536 * <entry><link linkend="G-VARIANT-TYPE-INT32:CAPS">i</link>, <link linkend="G-VARIANT-TYPE-INT16:CAPS">n</link></entry>
539 * <entry>#G_TYPE_UINT</entry>
540 * <entry><link linkend="G-VARIANT-TYPE-UINT32:CAPS">u</link>, <link linkend="G-VARIANT-TYPE-UINT16:CAPS">q</link></entry>
543 * <entry>#G_TYPE_INT64</entry>
544 * <entry><link linkend="G-VARIANT-TYPE-INT64:CAPS">x</link></entry>
547 * <entry>#G_TYPE_UINT64</entry>
548 * <entry><link linkend="G-VARIANT-TYPE-UINT64:CAPS">t</link></entry>
551 * <entry>#G_TYPE_INT</entry>
552 * <entry><link linkend="G-VARIANT-TYPE-HANDLE:CAPS">h</link></entry>
555 * <entry>#G_TYPE_DOUBLE</entry>
556 * <entry><link linkend="G-VARIANT-TYPE-DOUBLE:CAPS">d</link></entry>
559 * <entry>#G_TYPE_VARIANT</entry>
560 * <entry>Any #GVariantType</entry>
565 * This can fail if e.g. @gvalue is of type #G_TYPE_STRING and
566 * @expected_type is <literal>'i'</literal>. It will also fail for any
567 * #GType (including e.g. #G_TYPE_OBJECT and #G_TYPE_BOXED
568 * derived-types) not in the table above.
570 * Note that if @gvalue is of type #G_TYPE_VARIANT and its value is
571 * %NULL, the <emphasis>empty</emphasis> #GVariant instance (never
572 * %NULL) for @expected_type is returned (e.g. 0 for scalar types, the
573 * empty string for string types and so on).
575 * Returns: A #GVariant (never floating) of #GVariantType
576 * @expected_type holding the data from @gvalue or %NULL in case of
577 * failure. Free with g_variant_unref().
582 g_dbus_gvalue_to_gvariant (const GValue *gvalue,
583 const GVariantType *expected_type)
587 const gchar * const *as;
588 const gchar *empty_strv[1] = {NULL};
590 g_return_val_if_fail (gvalue != NULL, NULL);
591 g_return_val_if_fail (expected_type != NULL, NULL);
595 /* The expected type could easily be e.g. "s" with the GValue holding a string.
596 * because of the UseGVariant annotation
598 if (G_VALUE_TYPE (gvalue) == G_TYPE_VARIANT)
600 ret = g_value_dup_variant (gvalue);
604 switch (g_variant_type_peek_string (expected_type)[0])
606 case G_VARIANT_CLASS_BOOLEAN:
607 ret = g_variant_ref_sink (g_variant_new_boolean (g_value_get_boolean (gvalue)));
610 case G_VARIANT_CLASS_BYTE:
611 ret = g_variant_ref_sink (g_variant_new_byte (g_value_get_uchar (gvalue)));
614 case G_VARIANT_CLASS_INT16:
615 ret = g_variant_ref_sink (g_variant_new_int16 (g_value_get_int (gvalue)));
618 case G_VARIANT_CLASS_UINT16:
619 ret = g_variant_ref_sink (g_variant_new_uint16 (g_value_get_uint (gvalue)));
622 case G_VARIANT_CLASS_INT32:
623 ret = g_variant_ref_sink (g_variant_new_int32 (g_value_get_int (gvalue)));
626 case G_VARIANT_CLASS_UINT32:
627 ret = g_variant_ref_sink (g_variant_new_uint32 (g_value_get_uint (gvalue)));
630 case G_VARIANT_CLASS_INT64:
631 ret = g_variant_ref_sink (g_variant_new_int64 (g_value_get_int64 (gvalue)));
634 case G_VARIANT_CLASS_UINT64:
635 ret = g_variant_ref_sink (g_variant_new_uint64 (g_value_get_uint64 (gvalue)));
638 case G_VARIANT_CLASS_HANDLE:
639 ret = g_variant_ref_sink (g_variant_new_handle (g_value_get_int (gvalue)));
642 case G_VARIANT_CLASS_DOUBLE:
643 ret = g_variant_ref_sink (g_variant_new_double (g_value_get_double (gvalue)));
646 case G_VARIANT_CLASS_STRING:
647 s = g_value_get_string (gvalue);
650 ret = g_variant_ref_sink (g_variant_new_string (s));
653 case G_VARIANT_CLASS_OBJECT_PATH:
654 s = g_value_get_string (gvalue);
657 ret = g_variant_ref_sink (g_variant_new_object_path (s));
660 case G_VARIANT_CLASS_SIGNATURE:
661 s = g_value_get_string (gvalue);
664 ret = g_variant_ref_sink (g_variant_new_signature (s));
667 case G_VARIANT_CLASS_ARRAY:
668 switch (g_variant_type_peek_string (expected_type)[1])
670 case G_VARIANT_CLASS_BYTE:
671 s = g_value_get_string (gvalue);
674 ret = g_variant_ref_sink (g_variant_new_bytestring (s));
677 case G_VARIANT_CLASS_STRING:
678 as = g_value_get_boxed (gvalue);
681 ret = g_variant_ref_sink (g_variant_new_strv (as, -1));
684 case G_VARIANT_CLASS_ARRAY:
685 switch (g_variant_type_peek_string (expected_type)[2])
687 case G_VARIANT_CLASS_BYTE:
688 as = g_value_get_boxed (gvalue);
691 ret = g_variant_ref_sink (g_variant_new_bytestring_array (as, -1));
695 ret = g_value_dup_variant (gvalue);
701 ret = g_value_dup_variant (gvalue);
707 case G_VARIANT_CLASS_VARIANT:
708 case G_VARIANT_CLASS_MAYBE:
709 case G_VARIANT_CLASS_TUPLE:
710 case G_VARIANT_CLASS_DICT_ENTRY:
711 ret = g_value_dup_variant (gvalue);
716 /* Could be that the GValue is holding a NULL GVariant - in that case,
717 * we return an "empty" GVariant instead of a NULL GVariant
721 GVariant *untrusted_empty;
722 untrusted_empty = g_variant_new_from_data (expected_type, NULL, 0, FALSE, NULL, NULL);
723 ret = g_variant_ref_sink (g_variant_get_normal_form (untrusted_empty));
724 g_variant_unref (untrusted_empty);
727 g_assert (!g_variant_is_floating (ret));