Branch data Line data Source code
1 : : /* GDBus - GLib D-Bus Library
2 : : *
3 : : * Copyright (C) 2008-2010 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: David Zeuthen <davidz@redhat.com>
21 : : */
22 : :
23 : : #include "config.h"
24 : :
25 : : #include <stdlib.h>
26 : : #include <string.h>
27 : :
28 : : #include "gdbusutils.h"
29 : :
30 : : #include "glibintl.h"
31 : :
32 : : static gboolean
33 : 4009929 : is_valid_bus_name_character (gint c,
34 : : gboolean allow_hyphen)
35 : : {
36 : : return
37 : 4009929 : (c >= '0' && c <= '9') ||
38 : 3980799 : (c >= 'A' && c <= 'Z') ||
39 : 3820797 : (c >= 'a' && c <= 'z') ||
40 : 8019870 : (c == '_') ||
41 : 12 : (allow_hyphen && c == '-');
42 : : }
43 : :
44 : : static gboolean
45 : 1005708 : is_valid_initial_bus_name_character (gint c,
46 : : gboolean allow_initial_digit,
47 : : gboolean allow_hyphen)
48 : : {
49 : 1005708 : if (allow_initial_digit)
50 : 9764 : return is_valid_bus_name_character (c, allow_hyphen);
51 : : else
52 : : return
53 : 995944 : (c >= 'A' && c <= 'Z') ||
54 : 611365 : (c >= 'a' && c <= 'z') ||
55 : 1991894 : (c == '_') ||
56 : 6 : (allow_hyphen && c == '-');
57 : : }
58 : :
59 : : static gboolean
60 : 315204 : is_valid_name (const gchar *start,
61 : : guint len,
62 : : gboolean allow_initial_digit,
63 : : gboolean allow_hyphen)
64 : : {
65 : : gboolean ret;
66 : : const gchar *s;
67 : : const gchar *end;
68 : : gboolean has_dot;
69 : :
70 : 315204 : ret = FALSE;
71 : :
72 : 315204 : if (len == 0)
73 : 1 : goto out;
74 : :
75 : 315203 : s = start;
76 : 315203 : end = s + len;
77 : 315203 : has_dot = FALSE;
78 : 4363242 : while (s != end)
79 : : {
80 : 4048067 : if (*s == '.')
81 : : {
82 : 630781 : s += 1;
83 : 630781 : if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, allow_initial_digit, allow_hyphen)))
84 : 6 : goto out;
85 : 630775 : has_dot = TRUE;
86 : : }
87 : 3417286 : else if (G_UNLIKELY (!is_valid_bus_name_character (*s, allow_hyphen)))
88 : : {
89 : 22 : goto out;
90 : : }
91 : 4048039 : s += 1;
92 : : }
93 : :
94 : 315175 : if (G_UNLIKELY (!has_dot))
95 : 4 : goto out;
96 : :
97 : 315171 : ret = TRUE;
98 : :
99 : 315204 : out:
100 : 315204 : return ret;
101 : : }
102 : :
103 : : /**
104 : : * g_dbus_is_name:
105 : : * @string: The string to check.
106 : : *
107 : : * Checks if @string is a valid D-Bus bus name (either unique or well-known).
108 : : *
109 : : * Returns: %TRUE if valid, %FALSE otherwise.
110 : : *
111 : : * Since: 2.26
112 : : */
113 : : gboolean
114 : 42396 : g_dbus_is_name (const gchar *string)
115 : : {
116 : : size_t len;
117 : : gboolean ret;
118 : : const gchar *s;
119 : :
120 : 42396 : g_return_val_if_fail (string != NULL, FALSE);
121 : :
122 : 42396 : ret = FALSE;
123 : :
124 : 42396 : len = strlen (string);
125 : 42396 : if (G_UNLIKELY (len == 0 || len > 255))
126 : 4 : goto out;
127 : :
128 : 42392 : s = string;
129 : 42392 : if (*s == ':')
130 : : {
131 : : /* handle unique name */
132 : 9270 : if (!is_valid_name (s + 1, len - 1, TRUE, TRUE))
133 : 0 : goto out;
134 : 9270 : ret = TRUE;
135 : 9270 : goto out;
136 : : }
137 : 33122 : else if (G_UNLIKELY (*s == '.'))
138 : : {
139 : : /* can't start with a . */
140 : 3 : goto out;
141 : : }
142 : 33119 : else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, TRUE)))
143 : 1 : goto out;
144 : :
145 : 33118 : ret = is_valid_name (s + 1, len - 1, FALSE, TRUE);
146 : :
147 : 42396 : out:
148 : 42396 : return ret;
149 : : }
150 : :
151 : : /**
152 : : * g_dbus_is_unique_name:
153 : : * @string: The string to check.
154 : : *
155 : : * Checks if @string is a valid D-Bus unique bus name.
156 : : *
157 : : * Returns: %TRUE if valid, %FALSE otherwise.
158 : : *
159 : : * Since: 2.26
160 : : */
161 : : gboolean
162 : 7510 : g_dbus_is_unique_name (const gchar *string)
163 : : {
164 : : gboolean ret;
165 : : guint len;
166 : :
167 : 7510 : g_return_val_if_fail (string != NULL, FALSE);
168 : :
169 : 7510 : ret = FALSE;
170 : :
171 : 7510 : len = strlen (string);
172 : 7510 : if (G_UNLIKELY (len == 0 || len > 255))
173 : 2 : goto out;
174 : :
175 : 7508 : if (G_UNLIKELY (*string != ':'))
176 : 7066 : goto out;
177 : :
178 : 442 : if (G_UNLIKELY (!is_valid_name (string + 1, len - 1, TRUE, TRUE)))
179 : 0 : goto out;
180 : :
181 : 442 : ret = TRUE;
182 : :
183 : 7510 : out:
184 : 7510 : return ret;
185 : : }
186 : :
187 : : /**
188 : : * g_dbus_is_member_name:
189 : : * @string: The string to check.
190 : : *
191 : : * Checks if @string is a valid D-Bus member (e.g. signal or method) name.
192 : : *
193 : : * Returns: %TRUE if valid, %FALSE otherwise.
194 : : *
195 : : * Since: 2.26
196 : : */
197 : : gboolean
198 : 69426 : g_dbus_is_member_name (const gchar *string)
199 : : {
200 : : gboolean ret;
201 : : guint n;
202 : :
203 : 69426 : ret = FALSE;
204 : 69426 : if (G_UNLIKELY (string == NULL))
205 : 0 : goto out;
206 : :
207 : 69426 : if (G_UNLIKELY (!is_valid_initial_bus_name_character (string[0], FALSE, FALSE)))
208 : 0 : goto out;
209 : :
210 : 652237 : for (n = 1; string[n] != '\0'; n++)
211 : : {
212 : 582879 : if (G_UNLIKELY (!is_valid_bus_name_character (string[n], FALSE)))
213 : : {
214 : 68 : goto out;
215 : : }
216 : : }
217 : :
218 : 69358 : ret = TRUE;
219 : :
220 : 69426 : out:
221 : 69426 : return ret;
222 : : }
223 : :
224 : : /**
225 : : * g_dbus_is_interface_name:
226 : : * @string: The string to check.
227 : : *
228 : : * Checks if @string is a valid D-Bus interface name.
229 : : *
230 : : * Returns: %TRUE if valid, %FALSE otherwise.
231 : : *
232 : : * Since: 2.26
233 : : */
234 : : gboolean
235 : 272388 : g_dbus_is_interface_name (const gchar *string)
236 : : {
237 : : guint len;
238 : : gboolean ret;
239 : : const gchar *s;
240 : :
241 : 272388 : g_return_val_if_fail (string != NULL, FALSE);
242 : :
243 : 272388 : ret = FALSE;
244 : :
245 : 272388 : len = strlen (string);
246 : 272388 : if (G_UNLIKELY (len == 0 || len > 255))
247 : 4 : goto out;
248 : :
249 : 272384 : s = string;
250 : 272384 : if (G_UNLIKELY (*s == '.'))
251 : : {
252 : : /* can't start with a . */
253 : 2 : goto out;
254 : : }
255 : 272382 : else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, FALSE)))
256 : 8 : goto out;
257 : :
258 : 272374 : ret = is_valid_name (s + 1, len - 1, FALSE, FALSE);
259 : :
260 : 272388 : out:
261 : 272388 : return ret;
262 : : }
263 : :
264 : : /**
265 : : * g_dbus_is_error_name:
266 : : * @string: The string to check.
267 : : *
268 : : * Check whether @string is a valid D-Bus error name.
269 : : *
270 : : * This function returns the same result as g_dbus_is_interface_name(),
271 : : * because D-Bus error names are defined to have exactly the
272 : : * same syntax as interface names.
273 : : *
274 : : * Returns: %TRUE if valid, %FALSE otherwise.
275 : : *
276 : : * Since: 2.70
277 : : */
278 : : gboolean
279 : 2199 : g_dbus_is_error_name (const gchar *string)
280 : : {
281 : : /* Error names are the same syntax as interface names.
282 : : * See https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names-error */
283 : 2199 : return g_dbus_is_interface_name (string);
284 : : }
285 : :
286 : : /* ---------------------------------------------------------------------------------------------------- */
287 : :
288 : : /* TODO: maybe move to glib? if so, it should conform to http://en.wikipedia.org/wiki/Guid and/or
289 : : * http://tools.ietf.org/html/rfc4122 - specifically it should have hyphens then.
290 : : */
291 : :
292 : : /**
293 : : * g_dbus_generate_guid:
294 : : *
295 : : * Generate a D-Bus GUID that can be used with
296 : : * e.g. g_dbus_connection_new().
297 : : *
298 : : * See the
299 : : * [D-Bus specification](https://dbus.freedesktop.org/doc/dbus-specification.html#uuids)
300 : : * regarding what strings are valid D-Bus GUIDs. The specification refers to
301 : : * these as ‘UUIDs’ whereas GLib (for historical reasons) refers to them as
302 : : * ‘GUIDs’. The terms are interchangeable.
303 : : *
304 : : * Note that D-Bus GUIDs do not follow
305 : : * [RFC 4122](https://datatracker.ietf.org/doc/html/rfc4122).
306 : : *
307 : : * Returns: A valid D-Bus GUID. Free with g_free().
308 : : *
309 : : * Since: 2.26
310 : : */
311 : : gchar *
312 : 31 : g_dbus_generate_guid (void)
313 : : {
314 : : GString *s;
315 : : guint32 r1;
316 : : guint32 r2;
317 : : guint32 r3;
318 : : gint64 now_us;
319 : :
320 : 31 : s = g_string_new (NULL);
321 : :
322 : 31 : r1 = g_random_int ();
323 : 31 : r2 = g_random_int ();
324 : 31 : r3 = g_random_int ();
325 : 31 : now_us = g_get_real_time ();
326 : :
327 : 31 : g_string_append_printf (s, "%08x", r1);
328 : 31 : g_string_append_printf (s, "%08x", r2);
329 : 31 : g_string_append_printf (s, "%08x", r3);
330 : 31 : g_string_append_printf (s, "%08x", (guint32) (now_us / G_USEC_PER_SEC));
331 : :
332 : 31 : return g_string_free (s, FALSE);
333 : : }
334 : :
335 : : /**
336 : : * g_dbus_is_guid:
337 : : * @string: The string to check.
338 : : *
339 : : * Checks if @string is a D-Bus GUID.
340 : : *
341 : : * See the documentation for g_dbus_generate_guid() for more information about
342 : : * the format of a GUID.
343 : : *
344 : : * Returns: %TRUE if @string is a GUID, %FALSE otherwise.
345 : : *
346 : : * Since: 2.26
347 : : */
348 : : gboolean
349 : 2272 : g_dbus_is_guid (const gchar *string)
350 : : {
351 : : gboolean ret;
352 : : guint n;
353 : :
354 : 2272 : g_return_val_if_fail (string != NULL, FALSE);
355 : :
356 : 2272 : ret = FALSE;
357 : :
358 : 74976 : for (n = 0; n < 32; n++)
359 : : {
360 : 72704 : if (!g_ascii_isxdigit (string[n]))
361 : 0 : goto out;
362 : : }
363 : 2272 : if (string[32] != '\0')
364 : 0 : goto out;
365 : :
366 : 2272 : ret = TRUE;
367 : :
368 : 2272 : out:
369 : 2272 : return ret;
370 : : }
371 : :
372 : : /* ---------------------------------------------------------------------------------------------------- */
373 : :
374 : : /**
375 : : * g_dbus_gvariant_to_gvalue:
376 : : * @value: A #GVariant.
377 : : * @out_gvalue: (out): Return location pointing to a zero-filled (uninitialized) #GValue.
378 : : *
379 : : * Converts a #GVariant to a #GValue. If @value is floating, it is consumed.
380 : : *
381 : : * The rules specified in the g_dbus_gvalue_to_gvariant() function are
382 : : * used - this function is essentially its reverse form. So, a #GVariant
383 : : * containing any basic or string array type will be converted to a #GValue
384 : : * containing a basic value or string array. Any other #GVariant (handle,
385 : : * variant, tuple, dict entry) will be converted to a #GValue containing that
386 : : * #GVariant.
387 : : *
388 : : * The conversion never fails - a valid #GValue is always returned in
389 : : * @out_gvalue.
390 : : *
391 : : * Since: 2.30
392 : : */
393 : : void
394 : 223 : g_dbus_gvariant_to_gvalue (GVariant *value,
395 : : GValue *out_gvalue)
396 : : {
397 : : const GVariantType *type;
398 : : gchar **array;
399 : :
400 : 223 : g_return_if_fail (value != NULL);
401 : 223 : g_return_if_fail (out_gvalue != NULL);
402 : :
403 : 223 : memset (out_gvalue, '\0', sizeof (GValue));
404 : :
405 : 223 : switch (g_variant_classify (value))
406 : : {
407 : 12 : case G_VARIANT_CLASS_BOOLEAN:
408 : 12 : g_value_init (out_gvalue, G_TYPE_BOOLEAN);
409 : 12 : g_value_set_boolean (out_gvalue, g_variant_get_boolean (value));
410 : 12 : break;
411 : :
412 : 6 : case G_VARIANT_CLASS_BYTE:
413 : 6 : g_value_init (out_gvalue, G_TYPE_UCHAR);
414 : 6 : g_value_set_uchar (out_gvalue, g_variant_get_byte (value));
415 : 6 : break;
416 : :
417 : 9 : case G_VARIANT_CLASS_INT16:
418 : 9 : g_value_init (out_gvalue, G_TYPE_INT);
419 : 9 : g_value_set_int (out_gvalue, g_variant_get_int16 (value));
420 : 9 : break;
421 : :
422 : 6 : case G_VARIANT_CLASS_UINT16:
423 : 6 : g_value_init (out_gvalue, G_TYPE_UINT);
424 : 6 : g_value_set_uint (out_gvalue, g_variant_get_uint16 (value));
425 : 6 : break;
426 : :
427 : 15 : case G_VARIANT_CLASS_INT32:
428 : 15 : g_value_init (out_gvalue, G_TYPE_INT);
429 : 15 : g_value_set_int (out_gvalue, g_variant_get_int32 (value));
430 : 15 : break;
431 : :
432 : 13 : case G_VARIANT_CLASS_UINT32:
433 : 13 : g_value_init (out_gvalue, G_TYPE_UINT);
434 : 13 : g_value_set_uint (out_gvalue, g_variant_get_uint32 (value));
435 : 13 : break;
436 : :
437 : 6 : case G_VARIANT_CLASS_INT64:
438 : 6 : g_value_init (out_gvalue, G_TYPE_INT64);
439 : 6 : g_value_set_int64 (out_gvalue, g_variant_get_int64 (value));
440 : 6 : break;
441 : :
442 : 6 : case G_VARIANT_CLASS_UINT64:
443 : 6 : g_value_init (out_gvalue, G_TYPE_UINT64);
444 : 6 : g_value_set_uint64 (out_gvalue, g_variant_get_uint64 (value));
445 : 6 : break;
446 : :
447 : 9 : case G_VARIANT_CLASS_DOUBLE:
448 : 9 : g_value_init (out_gvalue, G_TYPE_DOUBLE);
449 : 9 : g_value_set_double (out_gvalue, g_variant_get_double (value));
450 : 9 : break;
451 : :
452 : 34 : case G_VARIANT_CLASS_STRING:
453 : 34 : g_value_init (out_gvalue, G_TYPE_STRING);
454 : 34 : g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
455 : 34 : break;
456 : :
457 : 12 : case G_VARIANT_CLASS_OBJECT_PATH:
458 : 12 : g_value_init (out_gvalue, G_TYPE_STRING);
459 : 12 : g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
460 : 12 : break;
461 : :
462 : 12 : case G_VARIANT_CLASS_SIGNATURE:
463 : 12 : g_value_init (out_gvalue, G_TYPE_STRING);
464 : 12 : g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
465 : 12 : break;
466 : :
467 : 75 : case G_VARIANT_CLASS_ARRAY:
468 : 75 : type = g_variant_get_type (value);
469 : 75 : switch (g_variant_type_peek_string (type)[1])
470 : : {
471 : 12 : case G_VARIANT_CLASS_BYTE:
472 : 12 : g_value_init (out_gvalue, G_TYPE_STRING);
473 : 12 : g_value_set_string (out_gvalue, g_variant_get_bytestring (value));
474 : 12 : break;
475 : :
476 : 19 : case G_VARIANT_CLASS_STRING:
477 : 19 : g_value_init (out_gvalue, G_TYPE_STRV);
478 : 19 : array = g_variant_dup_strv (value, NULL);
479 : 19 : g_value_take_boxed (out_gvalue, array);
480 : 19 : break;
481 : :
482 : 12 : case G_VARIANT_CLASS_OBJECT_PATH:
483 : 12 : g_value_init (out_gvalue, G_TYPE_STRV);
484 : 12 : array = g_variant_dup_objv (value, NULL);
485 : 12 : g_value_take_boxed (out_gvalue, array);
486 : 12 : break;
487 : :
488 : 6 : case G_VARIANT_CLASS_ARRAY:
489 : 6 : switch (g_variant_type_peek_string (type)[2])
490 : : {
491 : 6 : case G_VARIANT_CLASS_BYTE:
492 : 6 : g_value_init (out_gvalue, G_TYPE_STRV);
493 : 6 : array = g_variant_dup_bytestring_array (value, NULL);
494 : 6 : g_value_take_boxed (out_gvalue, array);
495 : 6 : break;
496 : :
497 : 0 : default:
498 : 0 : g_value_init (out_gvalue, G_TYPE_VARIANT);
499 : 0 : g_value_set_variant (out_gvalue, value);
500 : 0 : break;
501 : : }
502 : 6 : break;
503 : :
504 : 26 : default:
505 : 26 : g_value_init (out_gvalue, G_TYPE_VARIANT);
506 : 26 : g_value_set_variant (out_gvalue, value);
507 : 26 : break;
508 : : }
509 : 75 : break;
510 : :
511 : 8 : case G_VARIANT_CLASS_HANDLE:
512 : : case G_VARIANT_CLASS_VARIANT:
513 : : case G_VARIANT_CLASS_MAYBE:
514 : : case G_VARIANT_CLASS_TUPLE:
515 : : case G_VARIANT_CLASS_DICT_ENTRY:
516 : 8 : g_value_init (out_gvalue, G_TYPE_VARIANT);
517 : 8 : g_value_set_variant (out_gvalue, value);
518 : 8 : break;
519 : : }
520 : : }
521 : :
522 : :
523 : : /**
524 : : * g_dbus_gvalue_to_gvariant:
525 : : * @gvalue: A #GValue to convert to a #GVariant
526 : : * @type: A #GVariantType
527 : : *
528 : : * Converts a #GValue to a #GVariant of the type indicated by the @type
529 : : * parameter.
530 : : *
531 : : * The conversion is using the following rules:
532 : : *
533 : : * - `G_TYPE_STRING`: 's', 'o', 'g' or 'ay'
534 : : * - `G_TYPE_STRV`: 'as', 'ao' or 'aay'
535 : : * - `G_TYPE_BOOLEAN`: 'b'
536 : : * - `G_TYPE_UCHAR`: 'y'
537 : : * - `G_TYPE_INT`: 'i', 'n'
538 : : * - `G_TYPE_UINT`: 'u', 'q'
539 : : * - `G_TYPE_INT64`: 'x'
540 : : * - `G_TYPE_UINT64`: 't'
541 : : * - `G_TYPE_DOUBLE`: 'd'
542 : : * - `G_TYPE_VARIANT`: Any #GVariantType
543 : : *
544 : : * This can fail if e.g. @gvalue is of type %G_TYPE_STRING and @type
545 : : * is 'i', i.e. %G_VARIANT_TYPE_INT32. It will also fail for any #GType
546 : : * (including e.g. %G_TYPE_OBJECT and %G_TYPE_BOXED derived-types) not
547 : : * in the table above.
548 : : *
549 : : * Note that if @gvalue is of type %G_TYPE_VARIANT and its value is
550 : : * %NULL, the empty #GVariant instance (never %NULL) for @type is
551 : : * returned (e.g. 0 for scalar types, the empty string for string types,
552 : : * '/' for object path types, the empty array for any array type and so on).
553 : : *
554 : : * See the g_dbus_gvariant_to_gvalue() function for how to convert a
555 : : * #GVariant to a #GValue.
556 : : *
557 : : * Returns: (transfer full): A #GVariant (never floating) of
558 : : * #GVariantType @type holding the data from @gvalue or an empty #GVariant
559 : : * in case of failure. Free with g_variant_unref().
560 : : *
561 : : * Since: 2.30
562 : : */
563 : : GVariant *
564 : 857 : g_dbus_gvalue_to_gvariant (const GValue *gvalue,
565 : : const GVariantType *type)
566 : : {
567 : : GVariant *ret;
568 : : const gchar *s;
569 : : const gchar * const *as;
570 : 857 : const gchar *empty_strv[1] = {NULL};
571 : :
572 : 857 : g_return_val_if_fail (gvalue != NULL, NULL);
573 : 857 : g_return_val_if_fail (type != NULL, NULL);
574 : :
575 : 857 : ret = NULL;
576 : :
577 : : /* @type can easily be e.g. "s" with the GValue holding a GVariant - for example this
578 : : * can happen when using the org.gtk.GDBus.C.ForceGVariant annotation with the
579 : : * gdbus-codegen(1) tool.
580 : : */
581 : 857 : if (G_VALUE_TYPE (gvalue) == G_TYPE_VARIANT)
582 : : {
583 : 141 : ret = g_value_dup_variant (gvalue);
584 : : }
585 : : else
586 : : {
587 : 716 : switch (g_variant_type_peek_string (type)[0])
588 : : {
589 : 21 : case G_VARIANT_CLASS_BOOLEAN:
590 : 21 : ret = g_variant_ref_sink (g_variant_new_boolean (g_value_get_boolean (gvalue)));
591 : 21 : break;
592 : :
593 : 27 : case G_VARIANT_CLASS_BYTE:
594 : 27 : ret = g_variant_ref_sink (g_variant_new_byte (g_value_get_uchar (gvalue)));
595 : 27 : break;
596 : :
597 : 27 : case G_VARIANT_CLASS_INT16:
598 : 27 : ret = g_variant_ref_sink (g_variant_new_int16 (g_value_get_int (gvalue)));
599 : 27 : break;
600 : :
601 : 21 : case G_VARIANT_CLASS_UINT16:
602 : 21 : ret = g_variant_ref_sink (g_variant_new_uint16 (g_value_get_uint (gvalue)));
603 : 21 : break;
604 : :
605 : 60 : case G_VARIANT_CLASS_INT32:
606 : 60 : ret = g_variant_ref_sink (g_variant_new_int32 (g_value_get_int (gvalue)));
607 : 60 : break;
608 : :
609 : 30 : case G_VARIANT_CLASS_UINT32:
610 : 30 : ret = g_variant_ref_sink (g_variant_new_uint32 (g_value_get_uint (gvalue)));
611 : 30 : break;
612 : :
613 : 21 : case G_VARIANT_CLASS_INT64:
614 : 21 : ret = g_variant_ref_sink (g_variant_new_int64 (g_value_get_int64 (gvalue)));
615 : 21 : break;
616 : :
617 : 21 : case G_VARIANT_CLASS_UINT64:
618 : 21 : ret = g_variant_ref_sink (g_variant_new_uint64 (g_value_get_uint64 (gvalue)));
619 : 21 : break;
620 : :
621 : 45 : case G_VARIANT_CLASS_DOUBLE:
622 : 45 : ret = g_variant_ref_sink (g_variant_new_double (g_value_get_double (gvalue)));
623 : 45 : break;
624 : :
625 : 176 : case G_VARIANT_CLASS_STRING:
626 : 176 : s = g_value_get_string (gvalue);
627 : 176 : if (s == NULL)
628 : 144 : s = "";
629 : 176 : ret = g_variant_ref_sink (g_variant_new_string (s));
630 : 176 : break;
631 : :
632 : 48 : case G_VARIANT_CLASS_OBJECT_PATH:
633 : 48 : s = g_value_get_string (gvalue);
634 : 48 : if (s == NULL)
635 : 42 : s = "/";
636 : 48 : ret = g_variant_ref_sink (g_variant_new_object_path (s));
637 : 48 : break;
638 : :
639 : 48 : case G_VARIANT_CLASS_SIGNATURE:
640 : 48 : s = g_value_get_string (gvalue);
641 : 48 : if (s == NULL)
642 : 42 : s = "";
643 : 48 : ret = g_variant_ref_sink (g_variant_new_signature (s));
644 : 48 : break;
645 : :
646 : 171 : case G_VARIANT_CLASS_ARRAY:
647 : 171 : switch (g_variant_type_peek_string (type)[1])
648 : : {
649 : 48 : case G_VARIANT_CLASS_BYTE:
650 : 48 : s = g_value_get_string (gvalue);
651 : 48 : if (s == NULL)
652 : 39 : s = "";
653 : 48 : ret = g_variant_ref_sink (g_variant_new_bytestring (s));
654 : 48 : break;
655 : :
656 : 54 : case G_VARIANT_CLASS_STRING:
657 : 54 : as = g_value_get_boxed (gvalue);
658 : 54 : if (as == NULL)
659 : 42 : as = empty_strv;
660 : 54 : ret = g_variant_ref_sink (g_variant_new_strv (as, -1));
661 : 54 : break;
662 : :
663 : 48 : case G_VARIANT_CLASS_OBJECT_PATH:
664 : 48 : as = g_value_get_boxed (gvalue);
665 : 48 : if (as == NULL)
666 : 42 : as = empty_strv;
667 : 48 : ret = g_variant_ref_sink (g_variant_new_objv (as, -1));
668 : 48 : break;
669 : :
670 : 21 : case G_VARIANT_CLASS_ARRAY:
671 : 21 : switch (g_variant_type_peek_string (type)[2])
672 : : {
673 : 21 : case G_VARIANT_CLASS_BYTE:
674 : 21 : as = g_value_get_boxed (gvalue);
675 : 21 : if (as == NULL)
676 : 21 : as = empty_strv;
677 : 21 : ret = g_variant_ref_sink (g_variant_new_bytestring_array (as, -1));
678 : 21 : break;
679 : :
680 : 0 : default:
681 : 0 : ret = g_value_dup_variant (gvalue);
682 : 0 : break;
683 : : }
684 : 21 : break;
685 : :
686 : 0 : default:
687 : 0 : ret = g_value_dup_variant (gvalue);
688 : 0 : break;
689 : : }
690 : 171 : break;
691 : :
692 : 0 : case G_VARIANT_CLASS_HANDLE:
693 : : case G_VARIANT_CLASS_VARIANT:
694 : : case G_VARIANT_CLASS_MAYBE:
695 : : case G_VARIANT_CLASS_TUPLE:
696 : : case G_VARIANT_CLASS_DICT_ENTRY:
697 : 0 : ret = g_value_dup_variant (gvalue);
698 : 0 : break;
699 : : }
700 : : }
701 : :
702 : : /* Could be that the GValue is holding a NULL GVariant - in that case,
703 : : * we return an "empty" GVariant instead of a NULL GVariant
704 : : */
705 : 857 : if (ret == NULL)
706 : : {
707 : : GVariant *untrusted_empty;
708 : 111 : untrusted_empty = g_variant_new_from_data (type, NULL, 0, FALSE, NULL, NULL);
709 : 111 : ret = g_variant_take_ref (g_variant_get_normal_form (untrusted_empty));
710 : 111 : g_variant_unref (untrusted_empty);
711 : : }
712 : :
713 : 857 : g_assert (!g_variant_is_floating (ret));
714 : :
715 : 857 : return ret;
716 : : }
717 : :
718 : : /**
719 : : * g_dbus_escape_object_path_bytestring:
720 : : * @bytes: (array zero-terminated=1) (element-type guint8): the string of bytes to escape
721 : : *
722 : : * Escapes @bytes for use in a D-Bus object path component.
723 : : * @bytes is an array of zero or more nonzero bytes in an
724 : : * unspecified encoding, followed by a single zero byte.
725 : : *
726 : : * The escaping method consists of replacing all non-alphanumeric
727 : : * characters (see g_ascii_isalnum()) with their hexadecimal value
728 : : * preceded by an underscore (`_`). For example:
729 : : * `foo.bar.baz` will become `foo_2ebar_2ebaz`.
730 : : *
731 : : * This method is appropriate to use when the input is nearly
732 : : * a valid object path component but is not when your input
733 : : * is far from being a valid object path component.
734 : : * Other escaping algorithms are also valid to use with
735 : : * D-Bus object paths.
736 : : *
737 : : * This can be reversed with g_dbus_unescape_object_path().
738 : : *
739 : : * Returns: an escaped version of @bytes. Free with g_free().
740 : : *
741 : : * Since: 2.68
742 : : *
743 : : */
744 : : gchar *
745 : 20 : g_dbus_escape_object_path_bytestring (const guint8 *bytes)
746 : : {
747 : : GString *escaped;
748 : : const guint8 *p;
749 : :
750 : 20 : g_return_val_if_fail (bytes != NULL, NULL);
751 : :
752 : 20 : if (*bytes == '\0')
753 : 2 : return g_strdup ("_");
754 : :
755 : 18 : escaped = g_string_new (NULL);
756 : 98 : for (p = bytes; *p; p++)
757 : : {
758 : 80 : if (g_ascii_isalnum (*p))
759 : 56 : g_string_append_c (escaped, *p);
760 : : else
761 : 24 : g_string_append_printf (escaped, "_%02x", *p);
762 : : }
763 : :
764 : 18 : return g_string_free (escaped, FALSE);
765 : : }
766 : :
767 : : /**
768 : : * g_dbus_escape_object_path:
769 : : * @s: the string to escape
770 : : *
771 : : * This is a language binding friendly version of g_dbus_escape_object_path_bytestring().
772 : : *
773 : : * Returns: an escaped version of @s. Free with g_free().
774 : : *
775 : : * Since: 2.68
776 : : */
777 : : gchar *
778 : 10 : g_dbus_escape_object_path (const gchar *s)
779 : : {
780 : 10 : return (gchar *) g_dbus_escape_object_path_bytestring ((const guint8 *) s);
781 : : }
782 : :
783 : : /**
784 : : * g_dbus_unescape_object_path:
785 : : * @s: the string to unescape
786 : : *
787 : : * Unescapes an string that was previously escaped with
788 : : * g_dbus_escape_object_path(). If the string is in a format that could
789 : : * not have been returned by g_dbus_escape_object_path(), this function
790 : : * returns %NULL.
791 : : *
792 : : * Encoding alphanumeric characters which do not need to be
793 : : * encoded is not allowed (e.g `_63` is not valid, the string
794 : : * should contain `c` instead).
795 : : *
796 : : * Returns: (array zero-terminated=1) (element-type guint8) (nullable): an
797 : : * unescaped version of @s, or %NULL if @s is not a string returned
798 : : * from g_dbus_escape_object_path(). Free with g_free().
799 : : *
800 : : * Since: 2.68
801 : : */
802 : : guint8 *
803 : 16 : g_dbus_unescape_object_path (const gchar *s)
804 : : {
805 : : GString *unescaped;
806 : : const gchar *p;
807 : :
808 : 16 : g_return_val_if_fail (s != NULL, NULL);
809 : :
810 : 16 : if (g_str_equal (s, "_"))
811 : 1 : return (guint8 *) g_strdup ("");
812 : :
813 : 15 : unescaped = g_string_new (NULL);
814 : 56 : for (p = s; *p; p++)
815 : : {
816 : : gint hi, lo;
817 : :
818 : 47 : if (g_ascii_isalnum (*p))
819 : : {
820 : 29 : g_string_append_c (unescaped, *p);
821 : : }
822 : 18 : else if (*p == '_' &&
823 : 17 : ((hi = g_ascii_xdigit_value (p[1])) >= 0) &&
824 : 15 : ((lo = g_ascii_xdigit_value (p[2])) >= 0) &&
825 : 2 : (hi || lo) && /* \0 is not allowed */
826 : 13 : !g_ascii_isalnum ((hi << 4) | lo)) /* alnums must not be encoded */
827 : : {
828 : 12 : g_string_append_c (unescaped, (hi << 4) | lo);
829 : 12 : p += 2;
830 : : }
831 : : else
832 : : {
833 : : /* the string was not encoded correctly */
834 : 6 : g_string_free (unescaped, TRUE);
835 : 6 : return NULL;
836 : : }
837 : : }
838 : :
839 : 9 : return (guint8 *) g_string_free (unescaped, FALSE);
840 : : }
|