docs: Add GIOModuleScope and GIOModuleScopeFlags
[glib.git] / gio / gdbusutils.c
blob1773a5c0c17d79b80724799aef0b3510504bb673
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>
23 #include "config.h"
25 #include <stdlib.h>
26 #include <string.h>
28 #include "gdbusutils.h"
30 #include "glibintl.h"
32 /**
33 * SECTION:gdbusutils
34 * @title: D-Bus Utilities
35 * @short_description: Various utilities related to D-Bus.
36 * @include: gio/gio.h
38 * Various utility routines related to D-Bus.
41 static gboolean
42 is_valid_bus_name_character (gint c,
43 gboolean allow_hyphen)
45 return
46 (c >= '0' && c <= '9') ||
47 (c >= 'A' && c <= 'Z') ||
48 (c >= 'a' && c <= 'z') ||
49 (c == '_') ||
50 (allow_hyphen && c == '-');
53 static gboolean
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);
60 else
61 return
62 (c >= 'A' && c <= 'Z') ||
63 (c >= 'a' && c <= 'z') ||
64 (c == '_') ||
65 (allow_hyphen && c == '-');
68 static gboolean
69 is_valid_name (const gchar *start,
70 guint len,
71 gboolean allow_initial_digit,
72 gboolean allow_hyphen)
74 gboolean ret;
75 const gchar *s;
76 const gchar *end;
77 gboolean has_dot;
79 ret = FALSE;
81 if (len == 0)
82 goto out;
84 s = start;
85 end = s + len;
86 has_dot = FALSE;
87 while (s != end)
89 if (*s == '.')
91 s += 1;
92 if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, allow_initial_digit, allow_hyphen)))
93 goto out;
94 has_dot = TRUE;
96 else if (G_UNLIKELY (!is_valid_bus_name_character (*s, allow_hyphen)))
98 goto out;
100 s += 1;
103 if (G_UNLIKELY (!has_dot))
104 goto out;
106 ret = TRUE;
108 out:
109 return ret;
113 * g_dbus_is_name:
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.
120 * Since: 2.26
122 gboolean
123 g_dbus_is_name (const gchar *string)
125 guint len;
126 gboolean ret;
127 const gchar *s;
129 g_return_val_if_fail (string != NULL, FALSE);
131 ret = FALSE;
133 len = strlen (string);
134 if (G_UNLIKELY (len == 0 || len > 255))
135 goto out;
137 s = string;
138 if (*s == ':')
140 /* handle unique name */
141 if (!is_valid_name (s + 1, len - 1, TRUE, TRUE))
142 goto out;
143 ret = TRUE;
144 goto out;
146 else if (G_UNLIKELY (*s == '.'))
148 /* can't start with a . */
149 goto out;
151 else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, TRUE)))
152 goto out;
154 ret = is_valid_name (s + 1, len - 1, FALSE, TRUE);
156 out:
157 return ret;
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.
168 * Since: 2.26
170 gboolean
171 g_dbus_is_unique_name (const gchar *string)
173 gboolean ret;
174 guint len;
176 g_return_val_if_fail (string != NULL, FALSE);
178 ret = FALSE;
180 len = strlen (string);
181 if (G_UNLIKELY (len == 0 || len > 255))
182 goto out;
184 if (G_UNLIKELY (*string != ':'))
185 goto out;
187 if (G_UNLIKELY (!is_valid_name (string + 1, len - 1, TRUE, TRUE)))
188 goto out;
190 ret = TRUE;
192 out:
193 return ret;
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.
204 * Since: 2.26
206 gboolean
207 g_dbus_is_member_name (const gchar *string)
209 gboolean ret;
210 guint n;
212 ret = FALSE;
213 if (G_UNLIKELY (string == NULL))
214 goto out;
216 if (G_UNLIKELY (!is_valid_initial_bus_name_character (string[0], FALSE, FALSE)))
217 goto out;
219 for (n = 1; string[n] != '\0'; n++)
221 if (G_UNLIKELY (!is_valid_bus_name_character (string[n], FALSE)))
223 goto out;
227 ret = TRUE;
229 out:
230 return ret;
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.
241 * Since: 2.26
243 gboolean
244 g_dbus_is_interface_name (const gchar *string)
246 guint len;
247 gboolean ret;
248 const gchar *s;
250 g_return_val_if_fail (string != NULL, FALSE);
252 ret = FALSE;
254 len = strlen (string);
255 if (G_UNLIKELY (len == 0 || len > 255))
256 goto out;
258 s = string;
259 if (G_UNLIKELY (*s == '.'))
261 /* can't start with a . */
262 goto out;
264 else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, FALSE)))
265 goto out;
267 ret = is_valid_name (s + 1, len - 1, FALSE, FALSE);
269 out:
270 return ret;
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().
290 * Since: 2.26
292 gchar *
293 g_dbus_generate_guid (void)
295 GString *s;
296 GTimeVal now;
297 guint32 r1;
298 guint32 r2;
299 guint32 r3;
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);
317 * g_dbus_is_guid:
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.
327 * Since: 2.26
329 gboolean
330 g_dbus_is_guid (const gchar *string)
332 gboolean ret;
333 guint n;
335 g_return_val_if_fail (string != NULL, FALSE);
337 ret = FALSE;
339 for (n = 0; n < 32; n++)
341 if (!g_ascii_isxdigit (string[n]))
342 goto out;
344 if (string[32] != '\0')
345 goto out;
347 ret = TRUE;
349 out:
350 return ret;
353 /* ---------------------------------------------------------------------------------------------------- */
356 * g_dbus_gvariant_to_gvalue:
357 * @value: A #GVariant.
358 * @out_gvalue: Return location pointing to a zero-filled (uninitialized) #GValue.
360 * Converts a #GVariant to a #GValue. If @value is floating, it is consumed.
362 * The rules specified in the g_dbus_gvalue_to_gvariant() function are
363 * used - this function is essentially its reverse form.
365 * The conversion never fails - a valid #GValue is always returned in
366 * @out_gvalue.
368 * Since: 2.30
370 void
371 g_dbus_gvariant_to_gvalue (GVariant *value,
372 GValue *out_gvalue)
374 const GVariantType *type;
375 gchar **array;
377 g_return_if_fail (value != NULL);
378 g_return_if_fail (out_gvalue != NULL);
380 memset (out_gvalue, '\0', sizeof (GValue));
382 switch (g_variant_classify (value))
384 case G_VARIANT_CLASS_BOOLEAN:
385 g_value_init (out_gvalue, G_TYPE_BOOLEAN);
386 g_value_set_boolean (out_gvalue, g_variant_get_boolean (value));
387 break;
389 case G_VARIANT_CLASS_BYTE:
390 g_value_init (out_gvalue, G_TYPE_UCHAR);
391 g_value_set_uchar (out_gvalue, g_variant_get_byte (value));
392 break;
394 case G_VARIANT_CLASS_INT16:
395 g_value_init (out_gvalue, G_TYPE_INT);
396 g_value_set_int (out_gvalue, g_variant_get_int16 (value));
397 break;
399 case G_VARIANT_CLASS_UINT16:
400 g_value_init (out_gvalue, G_TYPE_UINT);
401 g_value_set_uint (out_gvalue, g_variant_get_uint16 (value));
402 break;
404 case G_VARIANT_CLASS_INT32:
405 g_value_init (out_gvalue, G_TYPE_INT);
406 g_value_set_int (out_gvalue, g_variant_get_int32 (value));
407 break;
409 case G_VARIANT_CLASS_UINT32:
410 g_value_init (out_gvalue, G_TYPE_UINT);
411 g_value_set_uint (out_gvalue, g_variant_get_uint32 (value));
412 break;
414 case G_VARIANT_CLASS_INT64:
415 g_value_init (out_gvalue, G_TYPE_INT64);
416 g_value_set_int64 (out_gvalue, g_variant_get_int64 (value));
417 break;
419 case G_VARIANT_CLASS_UINT64:
420 g_value_init (out_gvalue, G_TYPE_UINT64);
421 g_value_set_uint64 (out_gvalue, g_variant_get_uint64 (value));
422 break;
424 case G_VARIANT_CLASS_DOUBLE:
425 g_value_init (out_gvalue, G_TYPE_DOUBLE);
426 g_value_set_double (out_gvalue, g_variant_get_double (value));
427 break;
429 case G_VARIANT_CLASS_STRING:
430 g_value_init (out_gvalue, G_TYPE_STRING);
431 g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
432 break;
434 case G_VARIANT_CLASS_OBJECT_PATH:
435 g_value_init (out_gvalue, G_TYPE_STRING);
436 g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
437 break;
439 case G_VARIANT_CLASS_SIGNATURE:
440 g_value_init (out_gvalue, G_TYPE_STRING);
441 g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
442 break;
444 case G_VARIANT_CLASS_ARRAY:
445 type = g_variant_get_type (value);
446 switch (g_variant_type_peek_string (type)[1])
448 case G_VARIANT_CLASS_BYTE:
449 g_value_init (out_gvalue, G_TYPE_STRING);
450 g_value_set_string (out_gvalue, g_variant_get_bytestring (value));
451 break;
453 case G_VARIANT_CLASS_STRING:
454 g_value_init (out_gvalue, G_TYPE_STRV);
455 array = g_variant_dup_strv (value, NULL);
456 g_value_take_boxed (out_gvalue, array);
457 break;
459 case G_VARIANT_CLASS_OBJECT_PATH:
460 g_value_init (out_gvalue, G_TYPE_STRV);
461 array = g_variant_dup_objv (value, NULL);
462 g_value_take_boxed (out_gvalue, array);
463 break;
465 case G_VARIANT_CLASS_ARRAY:
466 switch (g_variant_type_peek_string (type)[2])
468 case G_VARIANT_CLASS_BYTE:
469 g_value_init (out_gvalue, G_TYPE_STRV);
470 array = g_variant_dup_bytestring_array (value, NULL);
471 g_value_take_boxed (out_gvalue, array);
472 break;
474 default:
475 g_value_init (out_gvalue, G_TYPE_VARIANT);
476 g_value_set_variant (out_gvalue, value);
477 break;
479 break;
481 default:
482 g_value_init (out_gvalue, G_TYPE_VARIANT);
483 g_value_set_variant (out_gvalue, value);
484 break;
486 break;
488 case G_VARIANT_CLASS_HANDLE:
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);
495 break;
501 * g_dbus_gvalue_to_gvariant:
502 * @gvalue: A #GValue to convert to a #GVariant.
503 * @type: A #GVariantType.
505 * Converts a #GValue to a #GVariant of the type indicated by the @type parameter.
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'>
511 * <thead>
512 * <row>
513 * <entry>If the #GType for @gvalue is...</entry>
514 * <entry>... then @type must be</entry>
515 * </row>
516 * </thead>
517 * <tbody>
518 * <row>
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> or <link linkend="G-VARIANT-TYPE-BYTESTRING:CAPS">'ay'</link></entry>
521 * </row>
522 * <row>
523 * <entry>#G_TYPE_STRV</entry>
524 * <entry><link linkend="G-VARIANT-TYPE-STRING-ARRAY:CAPS">'as'</link>, <link linkend="G-VARIANT-TYPE-OBJECT-PATH-ARRAY:CAPS">'ao'</link> or <link linkend="G-VARIANT-TYPE-BYTESTRING-ARRAY:CAPS">'aay'</link></entry>
525 * </row>
526 * <row>
527 * <entry>#G_TYPE_BOOLEAN</entry>
528 * <entry><link linkend="G-VARIANT-TYPE-BOOLEAN:CAPS">'b'</link></entry>
529 * </row>
530 * <row>
531 * <entry>#G_TYPE_UCHAR</entry>
532 * <entry><link linkend="G-VARIANT-TYPE-BYTE:CAPS">'y'</link></entry>
533 * </row>
534 * <row>
535 * <entry>#G_TYPE_INT</entry>
536 * <entry><link linkend="G-VARIANT-TYPE-INT32:CAPS">'i'</link> or <link linkend="G-VARIANT-TYPE-INT16:CAPS">'n'</link></entry>
537 * </row>
538 * <row>
539 * <entry>#G_TYPE_UINT</entry>
540 * <entry><link linkend="G-VARIANT-TYPE-UINT32:CAPS">'u'</link> or <link linkend="G-VARIANT-TYPE-UINT16:CAPS">'q'</link></entry>
541 * </row>
542 * <row>
543 * <entry>#G_TYPE_INT64</entry>
544 * <entry><link linkend="G-VARIANT-TYPE-INT64:CAPS">'x'</link></entry>
545 * </row>
546 * <row>
547 * <entry>#G_TYPE_UINT64</entry>
548 * <entry><link linkend="G-VARIANT-TYPE-UINT64:CAPS">'t'</link></entry>
549 * </row>
550 * <row>
551 * <entry>#G_TYPE_DOUBLE</entry>
552 * <entry><link linkend="G-VARIANT-TYPE-DOUBLE:CAPS">'d'</link></entry>
553 * </row>
554 * <row>
555 * <entry>#G_TYPE_VARIANT</entry>
556 * <entry>Any #GVariantType</entry>
557 * </row>
558 * </tbody>
559 * </tgroup>
560 * </table>
561 * This can fail if e.g. @gvalue is of type #G_TYPE_STRING and @type
562 * is <link linkend="G-VARIANT-TYPE-INT32:CAPS">'i'</link>. It will
563 * also fail for any #GType (including e.g. #G_TYPE_OBJECT and
564 * #G_TYPE_BOXED derived-types) not in the table above.
566 * Note that if @gvalue is of type #G_TYPE_VARIANT and its value is
567 * %NULL, the <emphasis>empty</emphasis> #GVariant instance (never
568 * %NULL) for @type is returned (e.g. 0 for scalar types, the empty
569 * string for string types, <literal>'/'</literal> for object path
570 * types, the empty array for any array type and so on).
572 * See the g_dbus_gvariant_to_gvalue() function for how to convert a
573 * #GVariant to a #GValue.
575 * Returns: A #GVariant (never floating) of #GVariantType
576 * @type holding the data from @gvalue or %NULL in case of
577 * failure. Free with g_variant_unref().
579 * Since: 2.30
581 GVariant *
582 g_dbus_gvalue_to_gvariant (const GValue *gvalue,
583 const GVariantType *type)
585 GVariant *ret;
586 const gchar *s;
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 (type != NULL, NULL);
593 ret = NULL;
595 /* @type can easily be e.g. "s" with the GValue holding a GVariant - for example this
596 * can happen when using the org.gtk.GDBus.C.ForceGVariant annotation with the
597 * gdbus-codegen(1) tool.
599 if (G_VALUE_TYPE (gvalue) == G_TYPE_VARIANT)
601 ret = g_value_dup_variant (gvalue);
603 else
605 switch (g_variant_type_peek_string (type)[0])
607 case G_VARIANT_CLASS_BOOLEAN:
608 ret = g_variant_ref_sink (g_variant_new_boolean (g_value_get_boolean (gvalue)));
609 break;
611 case G_VARIANT_CLASS_BYTE:
612 ret = g_variant_ref_sink (g_variant_new_byte (g_value_get_uchar (gvalue)));
613 break;
615 case G_VARIANT_CLASS_INT16:
616 ret = g_variant_ref_sink (g_variant_new_int16 (g_value_get_int (gvalue)));
617 break;
619 case G_VARIANT_CLASS_UINT16:
620 ret = g_variant_ref_sink (g_variant_new_uint16 (g_value_get_uint (gvalue)));
621 break;
623 case G_VARIANT_CLASS_INT32:
624 ret = g_variant_ref_sink (g_variant_new_int32 (g_value_get_int (gvalue)));
625 break;
627 case G_VARIANT_CLASS_UINT32:
628 ret = g_variant_ref_sink (g_variant_new_uint32 (g_value_get_uint (gvalue)));
629 break;
631 case G_VARIANT_CLASS_INT64:
632 ret = g_variant_ref_sink (g_variant_new_int64 (g_value_get_int64 (gvalue)));
633 break;
635 case G_VARIANT_CLASS_UINT64:
636 ret = g_variant_ref_sink (g_variant_new_uint64 (g_value_get_uint64 (gvalue)));
637 break;
639 case G_VARIANT_CLASS_DOUBLE:
640 ret = g_variant_ref_sink (g_variant_new_double (g_value_get_double (gvalue)));
641 break;
643 case G_VARIANT_CLASS_STRING:
644 s = g_value_get_string (gvalue);
645 if (s == NULL)
646 s = "";
647 ret = g_variant_ref_sink (g_variant_new_string (s));
648 break;
650 case G_VARIANT_CLASS_OBJECT_PATH:
651 s = g_value_get_string (gvalue);
652 if (s == NULL)
653 s = "/";
654 ret = g_variant_ref_sink (g_variant_new_object_path (s));
655 break;
657 case G_VARIANT_CLASS_SIGNATURE:
658 s = g_value_get_string (gvalue);
659 if (s == NULL)
660 s = "";
661 ret = g_variant_ref_sink (g_variant_new_signature (s));
662 break;
664 case G_VARIANT_CLASS_ARRAY:
665 switch (g_variant_type_peek_string (type)[1])
667 case G_VARIANT_CLASS_BYTE:
668 s = g_value_get_string (gvalue);
669 if (s == NULL)
670 s = "";
671 ret = g_variant_ref_sink (g_variant_new_bytestring (s));
672 break;
674 case G_VARIANT_CLASS_STRING:
675 as = g_value_get_boxed (gvalue);
676 if (as == NULL)
677 as = empty_strv;
678 ret = g_variant_ref_sink (g_variant_new_strv (as, -1));
679 break;
681 case G_VARIANT_CLASS_OBJECT_PATH:
682 as = g_value_get_boxed (gvalue);
683 if (as == NULL)
684 as = empty_strv;
685 ret = g_variant_ref_sink (g_variant_new_objv (as, -1));
686 break;
688 case G_VARIANT_CLASS_ARRAY:
689 switch (g_variant_type_peek_string (type)[2])
691 case G_VARIANT_CLASS_BYTE:
692 as = g_value_get_boxed (gvalue);
693 if (as == NULL)
694 as = empty_strv;
695 ret = g_variant_ref_sink (g_variant_new_bytestring_array (as, -1));
696 break;
698 default:
699 ret = g_value_dup_variant (gvalue);
700 break;
702 break;
704 default:
705 ret = g_value_dup_variant (gvalue);
706 break;
708 break;
710 case G_VARIANT_CLASS_HANDLE:
711 case G_VARIANT_CLASS_VARIANT:
712 case G_VARIANT_CLASS_MAYBE:
713 case G_VARIANT_CLASS_TUPLE:
714 case G_VARIANT_CLASS_DICT_ENTRY:
715 ret = g_value_dup_variant (gvalue);
716 break;
720 /* Could be that the GValue is holding a NULL GVariant - in that case,
721 * we return an "empty" GVariant instead of a NULL GVariant
723 if (ret == NULL)
725 GVariant *untrusted_empty;
726 untrusted_empty = g_variant_new_from_data (type, NULL, 0, FALSE, NULL, NULL);
727 ret = g_variant_ref_sink (g_variant_get_normal_form (untrusted_empty));
728 g_variant_unref (untrusted_empty);
731 g_assert (!g_variant_is_floating (ret));
733 return ret;