nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /* GDBus - GLib D-Bus Library
2 *
3 * Copyright (C) 2008-2010 Red Hat, Inc.
4 *
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.
9 *
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.
14 *
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/>.
17 *
18 * Author: David Zeuthen <davidz@redhat.com>
19 */
20  
21 #include "config.h"
22  
23 #include <stdlib.h>
24 #include <string.h>
25  
26 #include "gdbusutils.h"
27  
28 #include "glibintl.h"
29  
30 /**
31 * SECTION:gdbusutils
32 * @title: D-Bus Utilities
33 * @short_description: Various utilities related to D-Bus
34 * @include: gio/gio.h
35 *
36 * Various utility routines related to D-Bus.
37 */
38  
39 static gboolean
40 is_valid_bus_name_character (gint c,
41 gboolean allow_hyphen)
42 {
43 return
44 (c >= '0' && c <= '9') ||
45 (c >= 'A' && c <= 'Z') ||
46 (c >= 'a' && c <= 'z') ||
47 (c == '_') ||
48 (allow_hyphen && c == '-');
49 }
50  
51 static gboolean
52 is_valid_initial_bus_name_character (gint c,
53 gboolean allow_initial_digit,
54 gboolean allow_hyphen)
55 {
56 if (allow_initial_digit)
57 return is_valid_bus_name_character (c, allow_hyphen);
58 else
59 return
60 (c >= 'A' && c <= 'Z') ||
61 (c >= 'a' && c <= 'z') ||
62 (c == '_') ||
63 (allow_hyphen && c == '-');
64 }
65  
66 static gboolean
67 is_valid_name (const gchar *start,
68 guint len,
69 gboolean allow_initial_digit,
70 gboolean allow_hyphen)
71 {
72 gboolean ret;
73 const gchar *s;
74 const gchar *end;
75 gboolean has_dot;
76  
77 ret = FALSE;
78  
79 if (len == 0)
80 goto out;
81  
82 s = start;
83 end = s + len;
84 has_dot = FALSE;
85 while (s != end)
86 {
87 if (*s == '.')
88 {
89 s += 1;
90 if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, allow_initial_digit, allow_hyphen)))
91 goto out;
92 has_dot = TRUE;
93 }
94 else if (G_UNLIKELY (!is_valid_bus_name_character (*s, allow_hyphen)))
95 {
96 goto out;
97 }
98 s += 1;
99 }
100  
101 if (G_UNLIKELY (!has_dot))
102 goto out;
103  
104 ret = TRUE;
105  
106 out:
107 return ret;
108 }
109  
110 /**
111 * g_dbus_is_name:
112 * @string: The string to check.
113 *
114 * Checks if @string is a valid D-Bus bus name (either unique or well-known).
115 *
116 * Returns: %TRUE if valid, %FALSE otherwise.
117 *
118 * Since: 2.26
119 */
120 gboolean
121 g_dbus_is_name (const gchar *string)
122 {
123 guint len;
124 gboolean ret;
125 const gchar *s;
126  
127 g_return_val_if_fail (string != NULL, FALSE);
128  
129 ret = FALSE;
130  
131 len = strlen (string);
132 if (G_UNLIKELY (len == 0 || len > 255))
133 goto out;
134  
135 s = string;
136 if (*s == ':')
137 {
138 /* handle unique name */
139 if (!is_valid_name (s + 1, len - 1, TRUE, TRUE))
140 goto out;
141 ret = TRUE;
142 goto out;
143 }
144 else if (G_UNLIKELY (*s == '.'))
145 {
146 /* can't start with a . */
147 goto out;
148 }
149 else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, TRUE)))
150 goto out;
151  
152 ret = is_valid_name (s + 1, len - 1, FALSE, TRUE);
153  
154 out:
155 return ret;
156 }
157  
158 /**
159 * g_dbus_is_unique_name:
160 * @string: The string to check.
161 *
162 * Checks if @string is a valid D-Bus unique bus name.
163 *
164 * Returns: %TRUE if valid, %FALSE otherwise.
165 *
166 * Since: 2.26
167 */
168 gboolean
169 g_dbus_is_unique_name (const gchar *string)
170 {
171 gboolean ret;
172 guint len;
173  
174 g_return_val_if_fail (string != NULL, FALSE);
175  
176 ret = FALSE;
177  
178 len = strlen (string);
179 if (G_UNLIKELY (len == 0 || len > 255))
180 goto out;
181  
182 if (G_UNLIKELY (*string != ':'))
183 goto out;
184  
185 if (G_UNLIKELY (!is_valid_name (string + 1, len - 1, TRUE, TRUE)))
186 goto out;
187  
188 ret = TRUE;
189  
190 out:
191 return ret;
192 }
193  
194 /**
195 * g_dbus_is_member_name:
196 * @string: The string to check.
197 *
198 * Checks if @string is a valid D-Bus member (e.g. signal or method) name.
199 *
200 * Returns: %TRUE if valid, %FALSE otherwise.
201 *
202 * Since: 2.26
203 */
204 gboolean
205 g_dbus_is_member_name (const gchar *string)
206 {
207 gboolean ret;
208 guint n;
209  
210 ret = FALSE;
211 if (G_UNLIKELY (string == NULL))
212 goto out;
213  
214 if (G_UNLIKELY (!is_valid_initial_bus_name_character (string[0], FALSE, FALSE)))
215 goto out;
216  
217 for (n = 1; string[n] != '\0'; n++)
218 {
219 if (G_UNLIKELY (!is_valid_bus_name_character (string[n], FALSE)))
220 {
221 goto out;
222 }
223 }
224  
225 ret = TRUE;
226  
227 out:
228 return ret;
229 }
230  
231 /**
232 * g_dbus_is_interface_name:
233 * @string: The string to check.
234 *
235 * Checks if @string is a valid D-Bus interface name.
236 *
237 * Returns: %TRUE if valid, %FALSE otherwise.
238 *
239 * Since: 2.26
240 */
241 gboolean
242 g_dbus_is_interface_name (const gchar *string)
243 {
244 guint len;
245 gboolean ret;
246 const gchar *s;
247  
248 g_return_val_if_fail (string != NULL, FALSE);
249  
250 ret = FALSE;
251  
252 len = strlen (string);
253 if (G_UNLIKELY (len == 0 || len > 255))
254 goto out;
255  
256 s = string;
257 if (G_UNLIKELY (*s == '.'))
258 {
259 /* can't start with a . */
260 goto out;
261 }
262 else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, FALSE)))
263 goto out;
264  
265 ret = is_valid_name (s + 1, len - 1, FALSE, FALSE);
266  
267 out:
268 return ret;
269 }
270  
271 /* ---------------------------------------------------------------------------------------------------- */
272  
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.
275 */
276  
277 /**
278 * g_dbus_generate_guid:
279 *
280 * Generate a D-Bus GUID that can be used with
281 * e.g. g_dbus_connection_new().
282 *
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).
285 *
286 * Returns: A valid D-Bus GUID. Free with g_free().
287 *
288 * Since: 2.26
289 */
290 gchar *
291 g_dbus_generate_guid (void)
292 {
293 GString *s;
294 GTimeVal now;
295 guint32 r1;
296 guint32 r2;
297 guint32 r3;
298  
299 s = g_string_new (NULL);
300  
301 r1 = g_random_int ();
302 r2 = g_random_int ();
303 r3 = g_random_int ();
304 g_get_current_time (&now);
305  
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);
310  
311 return g_string_free (s, FALSE);
312 }
313  
314 /**
315 * g_dbus_is_guid:
316 * @string: The string to check.
317 *
318 * Checks if @string is a D-Bus GUID.
319 *
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).
322 *
323 * Returns: %TRUE if @string is a guid, %FALSE otherwise.
324 *
325 * Since: 2.26
326 */
327 gboolean
328 g_dbus_is_guid (const gchar *string)
329 {
330 gboolean ret;
331 guint n;
332  
333 g_return_val_if_fail (string != NULL, FALSE);
334  
335 ret = FALSE;
336  
337 for (n = 0; n < 32; n++)
338 {
339 if (!g_ascii_isxdigit (string[n]))
340 goto out;
341 }
342 if (string[32] != '\0')
343 goto out;
344  
345 ret = TRUE;
346  
347 out:
348 return ret;
349 }
350  
351 /* ---------------------------------------------------------------------------------------------------- */
352  
353 /**
354 * g_dbus_gvariant_to_gvalue:
355 * @value: A #GVariant.
356 * @out_gvalue: (out): Return location pointing to a zero-filled (uninitialized) #GValue.
357 *
358 * Converts a #GVariant to a #GValue. If @value is floating, it is consumed.
359 *
360 * The rules specified in the g_dbus_gvalue_to_gvariant() function are
361 * used - this function is essentially its reverse form.
362 *
363 * The conversion never fails - a valid #GValue is always returned in
364 * @out_gvalue.
365 *
366 * Since: 2.30
367 */
368 void
369 g_dbus_gvariant_to_gvalue (GVariant *value,
370 GValue *out_gvalue)
371 {
372 const GVariantType *type;
373 gchar **array;
374  
375 g_return_if_fail (value != NULL);
376 g_return_if_fail (out_gvalue != NULL);
377  
378 memset (out_gvalue, '\0', sizeof (GValue));
379  
380 switch (g_variant_classify (value))
381 {
382 case G_VARIANT_CLASS_BOOLEAN:
383 g_value_init (out_gvalue, G_TYPE_BOOLEAN);
384 g_value_set_boolean (out_gvalue, g_variant_get_boolean (value));
385 break;
386  
387 case G_VARIANT_CLASS_BYTE:
388 g_value_init (out_gvalue, G_TYPE_UCHAR);
389 g_value_set_uchar (out_gvalue, g_variant_get_byte (value));
390 break;
391  
392 case G_VARIANT_CLASS_INT16:
393 g_value_init (out_gvalue, G_TYPE_INT);
394 g_value_set_int (out_gvalue, g_variant_get_int16 (value));
395 break;
396  
397 case G_VARIANT_CLASS_UINT16:
398 g_value_init (out_gvalue, G_TYPE_UINT);
399 g_value_set_uint (out_gvalue, g_variant_get_uint16 (value));
400 break;
401  
402 case G_VARIANT_CLASS_INT32:
403 g_value_init (out_gvalue, G_TYPE_INT);
404 g_value_set_int (out_gvalue, g_variant_get_int32 (value));
405 break;
406  
407 case G_VARIANT_CLASS_UINT32:
408 g_value_init (out_gvalue, G_TYPE_UINT);
409 g_value_set_uint (out_gvalue, g_variant_get_uint32 (value));
410 break;
411  
412 case G_VARIANT_CLASS_INT64:
413 g_value_init (out_gvalue, G_TYPE_INT64);
414 g_value_set_int64 (out_gvalue, g_variant_get_int64 (value));
415 break;
416  
417 case G_VARIANT_CLASS_UINT64:
418 g_value_init (out_gvalue, G_TYPE_UINT64);
419 g_value_set_uint64 (out_gvalue, g_variant_get_uint64 (value));
420 break;
421  
422 case G_VARIANT_CLASS_DOUBLE:
423 g_value_init (out_gvalue, G_TYPE_DOUBLE);
424 g_value_set_double (out_gvalue, g_variant_get_double (value));
425 break;
426  
427 case G_VARIANT_CLASS_STRING:
428 g_value_init (out_gvalue, G_TYPE_STRING);
429 g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
430 break;
431  
432 case G_VARIANT_CLASS_OBJECT_PATH:
433 g_value_init (out_gvalue, G_TYPE_STRING);
434 g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
435 break;
436  
437 case G_VARIANT_CLASS_SIGNATURE:
438 g_value_init (out_gvalue, G_TYPE_STRING);
439 g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
440 break;
441  
442 case G_VARIANT_CLASS_ARRAY:
443 type = g_variant_get_type (value);
444 switch (g_variant_type_peek_string (type)[1])
445 {
446 case G_VARIANT_CLASS_BYTE:
447 g_value_init (out_gvalue, G_TYPE_STRING);
448 g_value_set_string (out_gvalue, g_variant_get_bytestring (value));
449 break;
450  
451 case G_VARIANT_CLASS_STRING:
452 g_value_init (out_gvalue, G_TYPE_STRV);
453 array = g_variant_dup_strv (value, NULL);
454 g_value_take_boxed (out_gvalue, array);
455 break;
456  
457 case G_VARIANT_CLASS_OBJECT_PATH:
458 g_value_init (out_gvalue, G_TYPE_STRV);
459 array = g_variant_dup_objv (value, NULL);
460 g_value_take_boxed (out_gvalue, array);
461 break;
462  
463 case G_VARIANT_CLASS_ARRAY:
464 switch (g_variant_type_peek_string (type)[2])
465 {
466 case G_VARIANT_CLASS_BYTE:
467 g_value_init (out_gvalue, G_TYPE_STRV);
468 array = g_variant_dup_bytestring_array (value, NULL);
469 g_value_take_boxed (out_gvalue, array);
470 break;
471  
472 default:
473 g_value_init (out_gvalue, G_TYPE_VARIANT);
474 g_value_set_variant (out_gvalue, value);
475 break;
476 }
477 break;
478  
479 default:
480 g_value_init (out_gvalue, G_TYPE_VARIANT);
481 g_value_set_variant (out_gvalue, value);
482 break;
483 }
484 break;
485  
486 case G_VARIANT_CLASS_HANDLE:
487 case G_VARIANT_CLASS_VARIANT:
488 case G_VARIANT_CLASS_MAYBE:
489 case G_VARIANT_CLASS_TUPLE:
490 case G_VARIANT_CLASS_DICT_ENTRY:
491 g_value_init (out_gvalue, G_TYPE_VARIANT);
492 g_value_set_variant (out_gvalue, value);
493 break;
494 }
495 }
496  
497  
498 /**
499 * g_dbus_gvalue_to_gvariant:
500 * @gvalue: A #GValue to convert to a #GVariant
501 * @type: A #GVariantType
502 *
503 * Converts a #GValue to a #GVariant of the type indicated by the @type
504 * parameter.
505 *
506 * The conversion is using the following rules:
507 *
508 * - #G_TYPE_STRING: 's', 'o', 'g' or 'ay'
509 * - #G_TYPE_STRV: 'as', 'ao' or 'aay'
510 * - #G_TYPE_BOOLEAN: 'b'
511 * - #G_TYPE_UCHAR: 'y'
512 * - #G_TYPE_INT: 'i', 'n'
513 * - #G_TYPE_UINT: 'u', 'q'
514 * - #G_TYPE_INT64 'x'
515 * - #G_TYPE_UINT64: 't'
516 * - #G_TYPE_DOUBLE: 'd'
517 * - #G_TYPE_VARIANT: Any #GVariantType
518 *
519 * This can fail if e.g. @gvalue is of type #G_TYPE_STRING and @type
520 * is ['i'][G-VARIANT-TYPE-INT32:CAPS]. It will also fail for any #GType
521 * (including e.g. #G_TYPE_OBJECT and #G_TYPE_BOXED derived-types) not
522 * in the table above.
523 *
524 * Note that if @gvalue is of type #G_TYPE_VARIANT and its value is
525 * %NULL, the empty #GVariant instance (never %NULL) for @type is
526 * returned (e.g. 0 for scalar types, the empty string for string types,
527 * '/' for object path types, the empty array for any array type and so on).
528 *
529 * See the g_dbus_gvariant_to_gvalue() function for how to convert a
530 * #GVariant to a #GValue.
531 *
532 * Returns: A #GVariant (never floating) of #GVariantType @type holding
533 * the data from @gvalue or %NULL in case of failure. Free with
534 * g_variant_unref().
535 *
536 * Since: 2.30
537 */
538 GVariant *
539 g_dbus_gvalue_to_gvariant (const GValue *gvalue,
540 const GVariantType *type)
541 {
542 GVariant *ret;
543 const gchar *s;
544 const gchar * const *as;
545 const gchar *empty_strv[1] = {NULL};
546  
547 g_return_val_if_fail (gvalue != NULL, NULL);
548 g_return_val_if_fail (type != NULL, NULL);
549  
550 ret = NULL;
551  
552 /* @type can easily be e.g. "s" with the GValue holding a GVariant - for example this
553 * can happen when using the org.gtk.GDBus.C.ForceGVariant annotation with the
554 * gdbus-codegen(1) tool.
555 */
556 if (G_VALUE_TYPE (gvalue) == G_TYPE_VARIANT)
557 {
558 ret = g_value_dup_variant (gvalue);
559 }
560 else
561 {
562 switch (g_variant_type_peek_string (type)[0])
563 {
564 case G_VARIANT_CLASS_BOOLEAN:
565 ret = g_variant_ref_sink (g_variant_new_boolean (g_value_get_boolean (gvalue)));
566 break;
567  
568 case G_VARIANT_CLASS_BYTE:
569 ret = g_variant_ref_sink (g_variant_new_byte (g_value_get_uchar (gvalue)));
570 break;
571  
572 case G_VARIANT_CLASS_INT16:
573 ret = g_variant_ref_sink (g_variant_new_int16 (g_value_get_int (gvalue)));
574 break;
575  
576 case G_VARIANT_CLASS_UINT16:
577 ret = g_variant_ref_sink (g_variant_new_uint16 (g_value_get_uint (gvalue)));
578 break;
579  
580 case G_VARIANT_CLASS_INT32:
581 ret = g_variant_ref_sink (g_variant_new_int32 (g_value_get_int (gvalue)));
582 break;
583  
584 case G_VARIANT_CLASS_UINT32:
585 ret = g_variant_ref_sink (g_variant_new_uint32 (g_value_get_uint (gvalue)));
586 break;
587  
588 case G_VARIANT_CLASS_INT64:
589 ret = g_variant_ref_sink (g_variant_new_int64 (g_value_get_int64 (gvalue)));
590 break;
591  
592 case G_VARIANT_CLASS_UINT64:
593 ret = g_variant_ref_sink (g_variant_new_uint64 (g_value_get_uint64 (gvalue)));
594 break;
595  
596 case G_VARIANT_CLASS_DOUBLE:
597 ret = g_variant_ref_sink (g_variant_new_double (g_value_get_double (gvalue)));
598 break;
599  
600 case G_VARIANT_CLASS_STRING:
601 s = g_value_get_string (gvalue);
602 if (s == NULL)
603 s = "";
604 ret = g_variant_ref_sink (g_variant_new_string (s));
605 break;
606  
607 case G_VARIANT_CLASS_OBJECT_PATH:
608 s = g_value_get_string (gvalue);
609 if (s == NULL)
610 s = "/";
611 ret = g_variant_ref_sink (g_variant_new_object_path (s));
612 break;
613  
614 case G_VARIANT_CLASS_SIGNATURE:
615 s = g_value_get_string (gvalue);
616 if (s == NULL)
617 s = "";
618 ret = g_variant_ref_sink (g_variant_new_signature (s));
619 break;
620  
621 case G_VARIANT_CLASS_ARRAY:
622 switch (g_variant_type_peek_string (type)[1])
623 {
624 case G_VARIANT_CLASS_BYTE:
625 s = g_value_get_string (gvalue);
626 if (s == NULL)
627 s = "";
628 ret = g_variant_ref_sink (g_variant_new_bytestring (s));
629 break;
630  
631 case G_VARIANT_CLASS_STRING:
632 as = g_value_get_boxed (gvalue);
633 if (as == NULL)
634 as = empty_strv;
635 ret = g_variant_ref_sink (g_variant_new_strv (as, -1));
636 break;
637  
638 case G_VARIANT_CLASS_OBJECT_PATH:
639 as = g_value_get_boxed (gvalue);
640 if (as == NULL)
641 as = empty_strv;
642 ret = g_variant_ref_sink (g_variant_new_objv (as, -1));
643 break;
644  
645 case G_VARIANT_CLASS_ARRAY:
646 switch (g_variant_type_peek_string (type)[2])
647 {
648 case G_VARIANT_CLASS_BYTE:
649 as = g_value_get_boxed (gvalue);
650 if (as == NULL)
651 as = empty_strv;
652 ret = g_variant_ref_sink (g_variant_new_bytestring_array (as, -1));
653 break;
654  
655 default:
656 ret = g_value_dup_variant (gvalue);
657 break;
658 }
659 break;
660  
661 default:
662 ret = g_value_dup_variant (gvalue);
663 break;
664 }
665 break;
666  
667 case G_VARIANT_CLASS_HANDLE:
668 case G_VARIANT_CLASS_VARIANT:
669 case G_VARIANT_CLASS_MAYBE:
670 case G_VARIANT_CLASS_TUPLE:
671 case G_VARIANT_CLASS_DICT_ENTRY:
672 ret = g_value_dup_variant (gvalue);
673 break;
674 }
675 }
676  
677 /* Could be that the GValue is holding a NULL GVariant - in that case,
678 * we return an "empty" GVariant instead of a NULL GVariant
679 */
680 if (ret == NULL)
681 {
682 GVariant *untrusted_empty;
683 untrusted_empty = g_variant_new_from_data (type, NULL, 0, FALSE, NULL, NULL);
684 ret = g_variant_ref_sink (g_variant_get_normal_form (untrusted_empty));
685 g_variant_unref (untrusted_empty);
686 }
687  
688 g_assert (!g_variant_is_floating (ret));
689  
690 return ret;
691 }