(root)/
glib-2.79.0/
gio/
gdbusutils.c
       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  is_valid_bus_name_character (gint c,
      34                               gboolean allow_hyphen)
      35  {
      36    return
      37      (c >= '0' && c <= '9') ||
      38      (c >= 'A' && c <= 'Z') ||
      39      (c >= 'a' && c <= 'z') ||
      40      (c == '_') ||
      41      (allow_hyphen && c == '-');
      42  }
      43  
      44  static gboolean
      45  is_valid_initial_bus_name_character (gint c,
      46                                       gboolean allow_initial_digit,
      47                                       gboolean allow_hyphen)
      48  {
      49    if (allow_initial_digit)
      50      return is_valid_bus_name_character (c, allow_hyphen);
      51    else
      52      return
      53        (c >= 'A' && c <= 'Z') ||
      54        (c >= 'a' && c <= 'z') ||
      55        (c == '_') ||
      56        (allow_hyphen && c == '-');
      57  }
      58  
      59  static gboolean
      60  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    ret = FALSE;
      71  
      72    if (len == 0)
      73      goto out;
      74  
      75    s = start;
      76    end = s + len;
      77    has_dot = FALSE;
      78    while (s != end)
      79      {
      80        if (*s == '.')
      81          {
      82            s += 1;
      83            if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, allow_initial_digit, allow_hyphen)))
      84              goto out;
      85            has_dot = TRUE;
      86          }
      87        else if (G_UNLIKELY (!is_valid_bus_name_character (*s, allow_hyphen)))
      88          {
      89            goto out;
      90          }
      91        s += 1;
      92      }
      93  
      94    if (G_UNLIKELY (!has_dot))
      95      goto out;
      96  
      97    ret = TRUE;
      98  
      99   out:
     100    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  g_dbus_is_name (const gchar *string)
     115  {
     116    guint len;
     117    gboolean ret;
     118    const gchar *s;
     119  
     120    g_return_val_if_fail (string != NULL, FALSE);
     121  
     122    ret = FALSE;
     123  
     124    len = strlen (string);
     125    if (G_UNLIKELY (len == 0 || len > 255))
     126      goto out;
     127  
     128    s = string;
     129    if (*s == ':')
     130      {
     131        /* handle unique name */
     132        if (!is_valid_name (s + 1, len - 1, TRUE, TRUE))
     133          goto out;
     134        ret = TRUE;
     135        goto out;
     136      }
     137    else if (G_UNLIKELY (*s == '.'))
     138      {
     139        /* can't start with a . */
     140        goto out;
     141      }
     142    else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, TRUE)))
     143      goto out;
     144  
     145    ret = is_valid_name (s + 1, len - 1, FALSE, TRUE);
     146  
     147   out:
     148    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  g_dbus_is_unique_name (const gchar *string)
     163  {
     164    gboolean ret;
     165    guint len;
     166  
     167    g_return_val_if_fail (string != NULL, FALSE);
     168  
     169    ret = FALSE;
     170  
     171    len = strlen (string);
     172    if (G_UNLIKELY (len == 0 || len > 255))
     173      goto out;
     174  
     175    if (G_UNLIKELY (*string != ':'))
     176      goto out;
     177  
     178    if (G_UNLIKELY (!is_valid_name (string + 1, len - 1, TRUE, TRUE)))
     179      goto out;
     180  
     181    ret = TRUE;
     182  
     183   out:
     184    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  g_dbus_is_member_name (const gchar *string)
     199  {
     200    gboolean ret;
     201    guint n;
     202  
     203    ret = FALSE;
     204    if (G_UNLIKELY (string == NULL))
     205      goto out;
     206  
     207    if (G_UNLIKELY (!is_valid_initial_bus_name_character (string[0], FALSE, FALSE)))
     208      goto out;
     209  
     210    for (n = 1; string[n] != '\0'; n++)
     211      {
     212        if (G_UNLIKELY (!is_valid_bus_name_character (string[n], FALSE)))
     213          {
     214            goto out;
     215          }
     216      }
     217  
     218    ret = TRUE;
     219  
     220   out:
     221    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  g_dbus_is_interface_name (const gchar *string)
     236  {
     237    guint len;
     238    gboolean ret;
     239    const gchar *s;
     240  
     241    g_return_val_if_fail (string != NULL, FALSE);
     242  
     243    ret = FALSE;
     244  
     245    len = strlen (string);
     246    if (G_UNLIKELY (len == 0 || len > 255))
     247      goto out;
     248  
     249    s = string;
     250    if (G_UNLIKELY (*s == '.'))
     251      {
     252        /* can't start with a . */
     253        goto out;
     254      }
     255    else if (G_UNLIKELY (!is_valid_initial_bus_name_character (*s, FALSE, FALSE)))
     256      goto out;
     257  
     258    ret = is_valid_name (s + 1, len - 1, FALSE, FALSE);
     259  
     260   out:
     261    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  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    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  g_dbus_generate_guid (void)
     313  {
     314    GString *s;
     315    guint32 r1;
     316    guint32 r2;
     317    guint32 r3;
     318    gint64 now_us;
     319  
     320    s = g_string_new (NULL);
     321  
     322    r1 = g_random_int ();
     323    r2 = g_random_int ();
     324    r3 = g_random_int ();
     325    now_us = g_get_real_time ();
     326  
     327    g_string_append_printf (s, "%08x", r1);
     328    g_string_append_printf (s, "%08x", r2);
     329    g_string_append_printf (s, "%08x", r3);
     330    g_string_append_printf (s, "%08x", (guint32) (now_us / G_USEC_PER_SEC));
     331  
     332    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  g_dbus_is_guid (const gchar *string)
     350  {
     351    gboolean ret;
     352    guint n;
     353  
     354    g_return_val_if_fail (string != NULL, FALSE);
     355  
     356    ret = FALSE;
     357  
     358    for (n = 0; n < 32; n++)
     359      {
     360        if (!g_ascii_isxdigit (string[n]))
     361          goto out;
     362      }
     363    if (string[32] != '\0')
     364      goto out;
     365  
     366    ret = TRUE;
     367  
     368   out:
     369    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  g_dbus_gvariant_to_gvalue (GVariant  *value,
     395                             GValue    *out_gvalue)
     396  {
     397    const GVariantType *type;
     398    gchar **array;
     399  
     400    g_return_if_fail (value != NULL);
     401    g_return_if_fail (out_gvalue != NULL);
     402  
     403    memset (out_gvalue, '\0', sizeof (GValue));
     404  
     405    switch (g_variant_classify (value))
     406      {
     407      case G_VARIANT_CLASS_BOOLEAN:
     408        g_value_init (out_gvalue, G_TYPE_BOOLEAN);
     409        g_value_set_boolean (out_gvalue, g_variant_get_boolean (value));
     410        break;
     411  
     412      case G_VARIANT_CLASS_BYTE:
     413        g_value_init (out_gvalue, G_TYPE_UCHAR);
     414        g_value_set_uchar (out_gvalue, g_variant_get_byte (value));
     415        break;
     416  
     417      case G_VARIANT_CLASS_INT16:
     418        g_value_init (out_gvalue, G_TYPE_INT);
     419        g_value_set_int (out_gvalue, g_variant_get_int16 (value));
     420        break;
     421  
     422      case G_VARIANT_CLASS_UINT16:
     423        g_value_init (out_gvalue, G_TYPE_UINT);
     424        g_value_set_uint (out_gvalue, g_variant_get_uint16 (value));
     425        break;
     426  
     427      case G_VARIANT_CLASS_INT32:
     428        g_value_init (out_gvalue, G_TYPE_INT);
     429        g_value_set_int (out_gvalue, g_variant_get_int32 (value));
     430        break;
     431  
     432      case G_VARIANT_CLASS_UINT32:
     433        g_value_init (out_gvalue, G_TYPE_UINT);
     434        g_value_set_uint (out_gvalue, g_variant_get_uint32 (value));
     435        break;
     436  
     437      case G_VARIANT_CLASS_INT64:
     438        g_value_init (out_gvalue, G_TYPE_INT64);
     439        g_value_set_int64 (out_gvalue, g_variant_get_int64 (value));
     440        break;
     441  
     442      case G_VARIANT_CLASS_UINT64:
     443        g_value_init (out_gvalue, G_TYPE_UINT64);
     444        g_value_set_uint64 (out_gvalue, g_variant_get_uint64 (value));
     445        break;
     446  
     447      case G_VARIANT_CLASS_DOUBLE:
     448        g_value_init (out_gvalue, G_TYPE_DOUBLE);
     449        g_value_set_double (out_gvalue, g_variant_get_double (value));
     450        break;
     451  
     452      case G_VARIANT_CLASS_STRING:
     453        g_value_init (out_gvalue, G_TYPE_STRING);
     454        g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
     455        break;
     456  
     457      case G_VARIANT_CLASS_OBJECT_PATH:
     458        g_value_init (out_gvalue, G_TYPE_STRING);
     459        g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
     460        break;
     461  
     462      case G_VARIANT_CLASS_SIGNATURE:
     463        g_value_init (out_gvalue, G_TYPE_STRING);
     464        g_value_set_string (out_gvalue, g_variant_get_string (value, NULL));
     465        break;
     466  
     467      case G_VARIANT_CLASS_ARRAY:
     468        type = g_variant_get_type (value);
     469        switch (g_variant_type_peek_string (type)[1])
     470          {
     471          case G_VARIANT_CLASS_BYTE:
     472            g_value_init (out_gvalue, G_TYPE_STRING);
     473            g_value_set_string (out_gvalue, g_variant_get_bytestring (value));
     474            break;
     475  
     476          case G_VARIANT_CLASS_STRING:
     477            g_value_init (out_gvalue, G_TYPE_STRV);
     478            array = g_variant_dup_strv (value, NULL);
     479            g_value_take_boxed (out_gvalue, array);
     480            break;
     481  
     482          case G_VARIANT_CLASS_OBJECT_PATH:
     483            g_value_init (out_gvalue, G_TYPE_STRV);
     484            array = g_variant_dup_objv (value, NULL);
     485            g_value_take_boxed (out_gvalue, array);
     486            break;
     487  
     488          case G_VARIANT_CLASS_ARRAY:
     489            switch (g_variant_type_peek_string (type)[2])
     490              {
     491              case G_VARIANT_CLASS_BYTE:
     492                g_value_init (out_gvalue, G_TYPE_STRV);
     493                array = g_variant_dup_bytestring_array (value, NULL);
     494                g_value_take_boxed (out_gvalue, array);
     495                break;
     496  
     497              default:
     498                g_value_init (out_gvalue, G_TYPE_VARIANT);
     499                g_value_set_variant (out_gvalue, value);
     500                break;
     501              }
     502            break;
     503  
     504          default:
     505            g_value_init (out_gvalue, G_TYPE_VARIANT);
     506            g_value_set_variant (out_gvalue, value);
     507            break;
     508          }
     509        break;
     510  
     511      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        g_value_init (out_gvalue, G_TYPE_VARIANT);
     517        g_value_set_variant (out_gvalue, value);
     518        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  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    const gchar *empty_strv[1] = {NULL};
     571  
     572    g_return_val_if_fail (gvalue != NULL, NULL);
     573    g_return_val_if_fail (type != NULL, NULL);
     574  
     575    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    if (G_VALUE_TYPE (gvalue) == G_TYPE_VARIANT)
     582      {
     583        ret = g_value_dup_variant (gvalue);
     584      }
     585    else
     586      {
     587        switch (g_variant_type_peek_string (type)[0])
     588          {
     589          case G_VARIANT_CLASS_BOOLEAN:
     590            ret = g_variant_ref_sink (g_variant_new_boolean (g_value_get_boolean (gvalue)));
     591            break;
     592  
     593          case G_VARIANT_CLASS_BYTE:
     594            ret = g_variant_ref_sink (g_variant_new_byte (g_value_get_uchar (gvalue)));
     595            break;
     596  
     597          case G_VARIANT_CLASS_INT16:
     598            ret = g_variant_ref_sink (g_variant_new_int16 (g_value_get_int (gvalue)));
     599            break;
     600  
     601          case G_VARIANT_CLASS_UINT16:
     602            ret = g_variant_ref_sink (g_variant_new_uint16 (g_value_get_uint (gvalue)));
     603            break;
     604  
     605          case G_VARIANT_CLASS_INT32:
     606            ret = g_variant_ref_sink (g_variant_new_int32 (g_value_get_int (gvalue)));
     607            break;
     608  
     609          case G_VARIANT_CLASS_UINT32:
     610            ret = g_variant_ref_sink (g_variant_new_uint32 (g_value_get_uint (gvalue)));
     611            break;
     612  
     613          case G_VARIANT_CLASS_INT64:
     614            ret = g_variant_ref_sink (g_variant_new_int64 (g_value_get_int64 (gvalue)));
     615            break;
     616  
     617          case G_VARIANT_CLASS_UINT64:
     618            ret = g_variant_ref_sink (g_variant_new_uint64 (g_value_get_uint64 (gvalue)));
     619            break;
     620  
     621          case G_VARIANT_CLASS_DOUBLE:
     622            ret = g_variant_ref_sink (g_variant_new_double (g_value_get_double (gvalue)));
     623            break;
     624  
     625          case G_VARIANT_CLASS_STRING:
     626            s = g_value_get_string (gvalue);
     627            if (s == NULL)
     628              s = "";
     629            ret = g_variant_ref_sink (g_variant_new_string (s));
     630            break;
     631  
     632          case G_VARIANT_CLASS_OBJECT_PATH:
     633            s = g_value_get_string (gvalue);
     634            if (s == NULL)
     635              s = "/";
     636            ret = g_variant_ref_sink (g_variant_new_object_path (s));
     637            break;
     638  
     639          case G_VARIANT_CLASS_SIGNATURE:
     640            s = g_value_get_string (gvalue);
     641            if (s == NULL)
     642              s = "";
     643            ret = g_variant_ref_sink (g_variant_new_signature (s));
     644            break;
     645  
     646          case G_VARIANT_CLASS_ARRAY:
     647            switch (g_variant_type_peek_string (type)[1])
     648              {
     649              case G_VARIANT_CLASS_BYTE:
     650                s = g_value_get_string (gvalue);
     651                if (s == NULL)
     652                  s = "";
     653                ret = g_variant_ref_sink (g_variant_new_bytestring (s));
     654                break;
     655  
     656              case G_VARIANT_CLASS_STRING:
     657                as = g_value_get_boxed (gvalue);
     658                if (as == NULL)
     659                  as = empty_strv;
     660                ret = g_variant_ref_sink (g_variant_new_strv (as, -1));
     661                break;
     662  
     663              case G_VARIANT_CLASS_OBJECT_PATH:
     664                as = g_value_get_boxed (gvalue);
     665                if (as == NULL)
     666                  as = empty_strv;
     667                ret = g_variant_ref_sink (g_variant_new_objv (as, -1));
     668                break;
     669  
     670              case G_VARIANT_CLASS_ARRAY:
     671                switch (g_variant_type_peek_string (type)[2])
     672                  {
     673                  case G_VARIANT_CLASS_BYTE:
     674                    as = g_value_get_boxed (gvalue);
     675                    if (as == NULL)
     676                      as = empty_strv;
     677                    ret = g_variant_ref_sink (g_variant_new_bytestring_array (as, -1));
     678                    break;
     679  
     680                  default:
     681                    ret = g_value_dup_variant (gvalue);
     682                    break;
     683                  }
     684                break;
     685  
     686              default:
     687                ret = g_value_dup_variant (gvalue);
     688                break;
     689              }
     690            break;
     691  
     692          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            ret = g_value_dup_variant (gvalue);
     698            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    if (ret == NULL)
     706      {
     707        GVariant *untrusted_empty;
     708        untrusted_empty = g_variant_new_from_data (type, NULL, 0, FALSE, NULL, NULL);
     709        ret = g_variant_take_ref (g_variant_get_normal_form (untrusted_empty));
     710        g_variant_unref (untrusted_empty);
     711      }
     712  
     713    g_assert (!g_variant_is_floating (ret));
     714  
     715    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  g_dbus_escape_object_path_bytestring (const guint8 *bytes)
     746  {
     747    GString *escaped;
     748    const guint8 *p;
     749  
     750    g_return_val_if_fail (bytes != NULL, NULL);
     751  
     752    if (*bytes == '\0')
     753      return g_strdup ("_");
     754  
     755    escaped = g_string_new (NULL);
     756    for (p = bytes; *p; p++)
     757      {
     758        if (g_ascii_isalnum (*p))
     759          g_string_append_c (escaped, *p);
     760        else
     761          g_string_append_printf (escaped, "_%02x", *p);
     762      }
     763  
     764    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  g_dbus_escape_object_path (const gchar *s)
     779  {
     780    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  g_dbus_unescape_object_path (const gchar *s)
     804  {
     805    GString *unescaped;
     806    const gchar *p;
     807  
     808    g_return_val_if_fail (s != NULL, NULL);
     809  
     810    if (g_str_equal (s, "_"))
     811      return (guint8 *) g_strdup ("");
     812  
     813    unescaped = g_string_new (NULL);
     814    for (p = s; *p; p++)
     815      {
     816        gint hi, lo;
     817  
     818        if (g_ascii_isalnum (*p))
     819          {
     820            g_string_append_c (unescaped, *p);
     821          }
     822        else if (*p == '_' &&
     823                 ((hi = g_ascii_xdigit_value (p[1])) >= 0) &&
     824                 ((lo = g_ascii_xdigit_value (p[2])) >= 0) &&
     825                 (hi || lo) &&                      /* \0 is not allowed */
     826                 !g_ascii_isalnum ((hi << 4) | lo)) /* alnums must not be encoded */
     827          {
     828            g_string_append_c (unescaped, (hi << 4) | lo);
     829            p += 2;
     830          }
     831        else
     832          {
     833            /* the string was not encoded correctly */
     834            g_string_free (unescaped, TRUE);
     835            return NULL;
     836          }
     837      }
     838  
     839    return (guint8 *) g_string_free (unescaped, FALSE);
     840  }