LCOV - code coverage report
Current view: top level - glib/gio - gdbusutils.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 316 335 94.3 %
Date: 2024-04-16 05:15:53 Functions: 15 15 100.0 %
Branches: 161 180 89.4 %

           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                 :    3821513 : is_valid_bus_name_character (gint c,
      34                 :            :                              gboolean allow_hyphen)
      35                 :            : {
      36                 :            :   return
      37   [ +  +  +  + ]:    3821513 :     (c >= '0' && c <= '9') ||
      38   [ +  +  +  + ]:    3801663 :     (c >= 'A' && c <= 'Z') ||
      39   [ -  +  +  + ]:    3653759 :     (c >= 'a' && c <= 'z') ||
      40   [ +  +  +  + ]:    7643038 :     (c == '_') ||
      41         [ +  + ]:         12 :     (allow_hyphen && c == '-');
      42                 :            : }
      43                 :            : 
      44                 :            : static gboolean
      45                 :     968609 : is_valid_initial_bus_name_character (gint c,
      46                 :            :                                      gboolean allow_initial_digit,
      47                 :            :                                      gboolean allow_hyphen)
      48                 :            : {
      49         [ +  + ]:     968609 :   if (allow_initial_digit)
      50                 :       5945 :     return is_valid_bus_name_character (c, allow_hyphen);
      51                 :            :   else
      52                 :            :     return
      53   [ +  +  +  + ]:     962664 :       (c >= 'A' && c <= 'Z') ||
      54   [ -  +  +  + ]:     594112 :       (c >= 'a' && c <= 'z') ||
      55   [ +  +  +  + ]:    1925334 :       (c == '_') ||
      56         [ +  # ]:          6 :       (allow_hyphen && c == '-');
      57                 :            : }
      58                 :            : 
      59                 :            : static gboolean
      60                 :     302934 : 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                 :     302934 :   ret = FALSE;
      71                 :            : 
      72         [ +  + ]:     302934 :   if (len == 0)
      73                 :          1 :     goto out;
      74                 :            : 
      75                 :     302933 :   s = start;
      76                 :     302933 :   end = s + len;
      77                 :     302933 :   has_dot = FALSE;
      78         [ +  + ]:    4183616 :   while (s != end)
      79                 :            :     {
      80         [ +  + ]:    3880785 :       if (*s == '.')
      81                 :            :         {
      82                 :     607740 :           s += 1;
      83         [ +  + ]:     607740 :           if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, allow_initial_digit, allow_hyphen)))
      84                 :          6 :             goto out;
      85                 :     607725 :           has_dot = TRUE;
      86                 :            :         }
      87         [ +  + ]:    3273045 :       else if (G_UNLIKELY (!is_valid_bus_name_character (*s, allow_hyphen)))
      88                 :            :         {
      89                 :         22 :           goto out;
      90                 :            :         }
      91                 :    3880683 :       s += 1;
      92                 :            :     }
      93                 :            : 
      94         [ +  + ]:     302831 :   if (G_UNLIKELY (!has_dot))
      95                 :          4 :     goto out;
      96                 :            : 
      97                 :     302827 :   ret = TRUE;
      98                 :            : 
      99                 :     302860 :  out:
     100                 :     302860 :   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                 :      36289 : g_dbus_is_name (const gchar *string)
     115                 :            : {
     116                 :            :   guint len;
     117                 :            :   gboolean ret;
     118                 :            :   const gchar *s;
     119                 :            : 
     120                 :      36289 :   g_return_val_if_fail (string != NULL, FALSE);
     121                 :            : 
     122                 :      36289 :   ret = FALSE;
     123                 :            : 
     124                 :      36289 :   len = strlen (string);
     125   [ +  +  +  + ]:      36289 :   if (G_UNLIKELY (len == 0 || len > 255))
     126                 :          4 :     goto out;
     127                 :            : 
     128                 :      36285 :   s = string;
     129         [ +  + ]:      36285 :   if (*s == ':')
     130                 :            :     {
     131                 :            :       /* handle unique name */
     132         [ -  + ]:       5806 :       if (!is_valid_name (s + 1, len - 1, TRUE, TRUE))
     133                 :          0 :         goto out;
     134                 :       5806 :       ret = TRUE;
     135                 :       5806 :       goto out;
     136                 :            :     }
     137         [ +  + ]:      30479 :   else if (G_UNLIKELY (*s == '.'))
     138                 :            :     {
     139                 :            :       /* can't start with a . */
     140                 :          3 :       goto out;
     141                 :            :     }
     142         [ +  + ]:      30476 :   else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, TRUE)))
     143                 :          1 :     goto out;
     144                 :            : 
     145                 :      30474 :   ret = is_valid_name (s + 1, len - 1, FALSE, TRUE);
     146                 :            : 
     147                 :      36286 :  out:
     148                 :      36286 :   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                 :       1190 : g_dbus_is_unique_name (const gchar *string)
     163                 :            : {
     164                 :            :   gboolean ret;
     165                 :            :   guint len;
     166                 :            : 
     167                 :       1190 :   g_return_val_if_fail (string != NULL, FALSE);
     168                 :            : 
     169                 :       1190 :   ret = FALSE;
     170                 :            : 
     171                 :       1190 :   len = strlen (string);
     172   [ +  +  +  + ]:       1190 :   if (G_UNLIKELY (len == 0 || len > 255))
     173                 :          2 :     goto out;
     174                 :            : 
     175         [ +  + ]:       1188 :   if (G_UNLIKELY (*string != ':'))
     176                 :       1053 :     goto out;
     177                 :            : 
     178         [ -  + ]:        135 :   if (G_UNLIKELY (!is_valid_name (string + 1, len - 1, TRUE, TRUE)))
     179                 :          0 :     goto out;
     180                 :            : 
     181                 :        135 :   ret = TRUE;
     182                 :            : 
     183                 :       1190 :  out:
     184                 :       1190 :   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                 :      64060 : g_dbus_is_member_name (const gchar *string)
     199                 :            : {
     200                 :            :   gboolean ret;
     201                 :            :   guint n;
     202                 :            : 
     203                 :      64060 :   ret = FALSE;
     204         [ -  + ]:      64060 :   if (G_UNLIKELY (string == NULL))
     205                 :          0 :     goto out;
     206                 :            : 
     207         [ -  + ]:      64060 :   if (G_UNLIKELY (!is_valid_initial_bus_name_character (string[0], FALSE, FALSE)))
     208                 :          0 :     goto out;
     209                 :            : 
     210         [ +  + ]:     606994 :   for (n = 1; string[n] != '\0'; n++)
     211                 :            :     {
     212         [ +  + ]:     543007 :       if (G_UNLIKELY (!is_valid_bus_name_character (string[n], FALSE)))
     213                 :            :         {
     214                 :         68 :           goto out;
     215                 :            :         }
     216                 :            :     }
     217                 :            : 
     218                 :      63987 :   ret = TRUE;
     219                 :            : 
     220                 :      64055 :  out:
     221                 :      64055 :   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                 :     266571 : g_dbus_is_interface_name (const gchar *string)
     236                 :            : {
     237                 :            :   guint len;
     238                 :            :   gboolean ret;
     239                 :            :   const gchar *s;
     240                 :            : 
     241                 :     266571 :   g_return_val_if_fail (string != NULL, FALSE);
     242                 :            : 
     243                 :     266571 :   ret = FALSE;
     244                 :            : 
     245                 :     266571 :   len = strlen (string);
     246   [ +  +  +  + ]:     266571 :   if (G_UNLIKELY (len == 0 || len > 255))
     247                 :          6 :     goto out;
     248                 :            : 
     249                 :     266565 :   s = string;
     250         [ +  + ]:     266565 :   if (G_UNLIKELY (*s == '.'))
     251                 :            :     {
     252                 :            :       /* can't start with a . */
     253                 :          2 :       goto out;
     254                 :            :     }
     255         [ +  + ]:     266563 :   else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, FALSE)))
     256                 :          8 :     goto out;
     257                 :            : 
     258                 :     266541 :   ret = is_valid_name (s + 1, len - 1, FALSE, FALSE);
     259                 :            : 
     260                 :     266416 :  out:
     261                 :     266416 :   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                 :       1856 : 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                 :       1856 :   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                 :       1978 : g_dbus_is_guid (const gchar *string)
     350                 :            : {
     351                 :            :   gboolean ret;
     352                 :            :   guint n;
     353                 :            : 
     354                 :       1978 :   g_return_val_if_fail (string != NULL, FALSE);
     355                 :            : 
     356                 :       1978 :   ret = FALSE;
     357                 :            : 
     358         [ +  + ]:      65274 :   for (n = 0; n < 32; n++)
     359                 :            :     {
     360         [ -  + ]:      63296 :       if (!g_ascii_isxdigit (string[n]))
     361                 :          0 :         goto out;
     362                 :            :     }
     363         [ -  + ]:       1978 :   if (string[32] != '\0')
     364                 :          0 :     goto out;
     365                 :            : 
     366                 :       1978 :   ret = TRUE;
     367                 :            : 
     368                 :       1978 :  out:
     369                 :       1978 :   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                 :        207 : g_dbus_gvariant_to_gvalue (GVariant  *value,
     395                 :            :                            GValue    *out_gvalue)
     396                 :            : {
     397                 :            :   const GVariantType *type;
     398                 :            :   gchar **array;
     399                 :            : 
     400                 :        207 :   g_return_if_fail (value != NULL);
     401                 :        207 :   g_return_if_fail (out_gvalue != NULL);
     402                 :            : 
     403                 :        207 :   memset (out_gvalue, '\0', sizeof (GValue));
     404                 :            : 
     405   [ +  +  +  +  :        207 :   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                 :         12 :     case G_VARIANT_CLASS_UINT32:
     433                 :         12 :       g_value_init (out_gvalue, G_TYPE_UINT);
     434                 :         12 :       g_value_set_uint (out_gvalue, g_variant_get_uint32 (value));
     435                 :         12 :       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                 :         27 :     case G_VARIANT_CLASS_STRING:
     453                 :         27 :       g_value_init (out_gvalue, G_TYPE_STRING);
     454                 :         27 :       g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
     455                 :         27 :       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                 :         69 :     case G_VARIANT_CLASS_ARRAY:
     468                 :         69 :       type = g_variant_get_type (value);
     469   [ +  +  +  +  :         69 :       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                 :         18 :         case G_VARIANT_CLASS_STRING:
     477                 :         18 :           g_value_init (out_gvalue, G_TYPE_STRV);
     478                 :         18 :           array = g_variant_dup_strv (value, NULL);
     479                 :         18 :           g_value_take_boxed (out_gvalue, array);
     480                 :         18 :           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                 :         21 :         default:
     505                 :         21 :           g_value_init (out_gvalue, G_TYPE_VARIANT);
     506                 :         21 :           g_value_set_variant (out_gvalue, value);
     507                 :         21 :           break;
     508                 :            :         }
     509                 :         69 :       break;
     510                 :            : 
     511                 :          6 :     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                 :          6 :       g_value_init (out_gvalue, G_TYPE_VARIANT);
     517                 :          6 :       g_value_set_variant (out_gvalue, value);
     518                 :          6 :       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 1.14