LCOV - code coverage report
Current view: top level - gio - gdbusutils.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 94.3 % 335 316
Test Date: 2024-11-26 05:23:01 Functions: 100.0 % 15 15
Branches: - 0 0

             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                 :             : }
        

Generated by: LCOV version 2.0-1