[dbus-glib/origin/f13/master] - Apply patch to fix property access

Colin Walters walters at fedoraproject.org
Thu Aug 12 21:44:02 UTC 2010


commit 4275e684be6573d266d50b7fb7ac313e8d049dd4
Author: Colin Walters <walters at verbum.org>
Date:   Thu Aug 12 10:29:09 2010 -0400

    - Apply patch to fix property access

 ...perty-access-flags-for-writing-allow-disa.patch | 1109 ++++++++++++++++++++
 dbus-glib.spec                                     |    8 +-
 2 files changed, 1116 insertions(+), 1 deletions(-)
---
diff --git a/0001-Respect-property-access-flags-for-writing-allow-disa.patch b/0001-Respect-property-access-flags-for-writing-allow-disa.patch
new file mode 100644
index 0000000..5efc4c8
--- /dev/null
+++ b/0001-Respect-property-access-flags-for-writing-allow-disa.patch
@@ -0,0 +1,1109 @@
+From 510bdcd63ae4e588a5cb72727696d5ad7fd5298b Mon Sep 17 00:00:00 2001
+From: Colin Walters <walters at verbum.org>
+Date: Mon, 19 Apr 2010 16:47:11 -0400
+Subject: [PATCH] Respect property access flags for writing, allow disabling for reads
+
+Because DBus-GLib originally was designed as a generic "object mapping"
+binding, the handler for org.freedesktop.DBus.Properties simply
+allowed access (read or write) to any GObject property that was
+exported.
+
+Later, the (compile time) introspection XML was added, and while we only
+listed "exported" properties in the dynamic introspection XML, we
+still allowed Get or Set calls to any property that was valid.
+
+With this patch, we deny writes to properties which aren't listed
+in the XML, or are listed as read-only.
+
+For backwards compatibility however, we still allow reads.  A
+service may disable this by calling
+dbus_glib_global_set_disable_legacy_property_access().
+---
+ dbus/dbus-binding-tool-glib.c   |   53 +++++--
+ dbus/dbus-glib.h                |    2 +
+ dbus/dbus-gobject.c             |  293 +++++++++++++++++++++++++++++++++------
+ test/core/my-object.c           |   63 ++++++++-
+ test/core/my-object.h           |    5 +
+ test/core/test-dbus-glib.c      |  252 +++++++++++++++++++++++++++++++--
+ test/core/test-service-glib.xml |    5 +
+ 7 files changed, 601 insertions(+), 72 deletions(-)
+
+diff --git a/dbus/dbus-binding-tool-glib.c b/dbus/dbus-binding-tool-glib.c
+index 872d1f7..97545df 100644
+--- a/dbus/dbus-binding-tool-glib.c
++++ b/dbus/dbus-binding-tool-glib.c
+@@ -38,6 +38,10 @@
+ #include <string.h>
+ #include <unistd.h>
+ 
++/* Remember to grep for ->format_version in the code if you change this,
++ * most changes should be in dbus-gobject.c. */
++#define FORMAT_VERSION 1
++
+ #define MARSHAL_PREFIX "dbus_glib_marshal_"
+ 
+ typedef struct
+@@ -466,14 +470,13 @@ generate_glue_toplevel (BaseInfo *base, DBusBindingToolCData *data, GError **err
+ {
+   GString *object_introspection_data_blob;
+   GIOChannel *channel;
+-  
++
+   channel = data->channel;
+-  
+-  object_introspection_data_blob = g_string_new_len ("", 0);
+ 
++  object_introspection_data_blob = g_string_new_len ("", 0);
+   data->blob = object_introspection_data_blob;
+   data->count = 0;
+-  
++
+   data->signal_blob = g_string_new_len ("", 0);
+   data->property_blob = g_string_new_len ("", 0);
+ 
+@@ -490,10 +493,9 @@ generate_glue_toplevel (BaseInfo *base, DBusBindingToolCData *data, GError **err
+   WRITE_OR_LOSE ("};\n\n");
+   /* Information about the object. */
+ 
+-  if (!write_printf_to_iochannel ("const DBusGObjectInfo dbus_glib_%s_object_info = {\n",
+-                                  channel, error, data->prefix))
++  if (!write_printf_to_iochannel ("const DBusGObjectInfo dbus_glib_%s_object_info = {  %d,\n",
++                                  channel, error, data->prefix, FORMAT_VERSION))
+     goto io_lose;
+-  WRITE_OR_LOSE ("  0,\n");
+   if (!write_printf_to_iochannel ("  dbus_glib_%s_methods,\n", channel, error, data->prefix))
+     goto io_lose;
+   if (!write_printf_to_iochannel ("  %d,\n", channel, error, data->count))
+@@ -753,13 +755,36 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
+       for (tmp = properties; tmp != NULL; tmp = g_slist_next (tmp))
+         {
+           PropertyInfo *prop;
+-	  
+-	  prop = tmp->data;
+-
+-	  g_string_append (data->property_blob, interface_info_get_name (interface));
+-	  g_string_append_c (data->property_blob, '\0');
+-	  g_string_append (data->property_blob, property_info_get_name (prop));
+-	  g_string_append_c (data->property_blob, '\0');
++          PropertyAccessFlags access_flags;
++          const char *access_string;
++          char *uscored;
++
++          prop = tmp->data;
++
++          access_flags = property_info_get_access (prop);
++          if ((access_flags & PROPERTY_READ) && (access_flags & PROPERTY_WRITE))
++            access_string = "readwrite";
++          else if (access_flags & PROPERTY_READ)
++            access_string = "read";
++          else if (access_flags & PROPERTY_WRITE)
++            access_string = "write";
++          else
++            continue;
++
++          /* We append both in the blob so we have to malloc() less when processing
++           * properties */
++          uscored = _dbus_gutils_wincaps_to_uscore (property_info_get_name (prop));
++
++          g_string_append (data->property_blob, interface_info_get_name (interface));
++          g_string_append_c (data->property_blob, '\0');
++          g_string_append (data->property_blob, property_info_get_name (prop));
++          g_string_append_c (data->property_blob, '\0');
++          g_string_append (data->property_blob, uscored);
++          g_string_append_c (data->property_blob, '\0');
++          g_string_append (data->property_blob, access_string);
++          g_string_append_c (data->property_blob, '\0');
++
++          g_free (uscored);
+ 	}
+     }
+   return TRUE;
+diff --git a/dbus/dbus-glib.h b/dbus/dbus-glib.h
+index 1b236d8..baf2567 100644
+--- a/dbus/dbus-glib.h
++++ b/dbus/dbus-glib.h
+@@ -154,6 +154,8 @@ struct _DBusGObjectInfo
+   const char *exported_properties; 
+ };
+ 
++void       dbus_glib_global_set_disable_legacy_property_access (void);
++
+ void       dbus_g_object_type_install_info     (GType                 object_type,
+                                                 const DBusGObjectInfo *info);
+ 
+diff --git a/dbus/dbus-gobject.c b/dbus/dbus-gobject.c
+index 6a1aba4..f340afa 100644
+--- a/dbus/dbus-gobject.c
++++ b/dbus/dbus-gobject.c
+@@ -37,7 +37,7 @@
+ 
+ static char *lookup_property_name (GObject    *object,
+                                    const char *wincaps_propiface,
+-                                   const char *wincaps_propname);
++                                   const char *requested_propname);
+ 
+ typedef struct
+ {
+@@ -46,6 +46,8 @@ typedef struct
+ } DBusGErrorInfo;
+ 
+ static GStaticRWLock globals_lock = G_STATIC_RW_LOCK_INIT;
++/* See comments in check_property_access */
++static gboolean disable_legacy_property_access = FALSE;
+ static GHashTable *marshal_table = NULL;
+ static GData *error_metadata = NULL;
+ 
+@@ -83,6 +85,23 @@ uscore_to_wincaps_full (const char *uscore,
+   return g_string_free (str, FALSE);
+ }
+ 
++/* Ugly yes - but we have to accept strings from both formats */
++static gboolean
++compare_strings_ignoring_uscore_vs_dash (const char *a, const char *b)
++{
++  guint i;
++
++  for (i = 0; a[i] && b[i]; i++)
++    {
++      if ((a[i] == '-' && b[i] == '_')
++          || (a[i] == '_' && b[i] == '-'))
++        continue;
++      if (a[i] != b[i])
++        return FALSE;
++    }
++  return (a[i] == '\0') && (b[i] == '\0');
++}
++
+ static char *
+ uscore_to_wincaps (const char *uscore)
+ {
+@@ -281,7 +300,7 @@ method_output_signature_from_object_info (const DBusGObjectInfo *object,
+ }
+ 
+ static const char *
+-propsig_iterate (const char *data, const char **iface, const char **name)
++signal_iterate (const char *data, const char **iface, const char **name)
+ {
+   *iface = data;
+ 
+@@ -291,6 +310,108 @@ propsig_iterate (const char *data, const char **iface, const char **name)
+   return string_table_next (data);
+ }
+ 
++static const char *
++property_iterate (const char  *data,
++                  int          format_version,
++                  const char **iface,
++                  const char **exported_name,
++                  const char **name_uscored,
++                  const char **access_type)
++{
++  *iface = data;
++
++  data = string_table_next (data);
++  *exported_name = data;
++
++  data = string_table_next (data);
++  if (format_version == 1)
++    {
++      *name_uscored = data;
++      data = string_table_next (data);
++      *access_type = data;
++      return string_table_next (data);
++    }
++  else
++    {
++      /* This tells the caller they need to compute it */
++      *name_uscored = NULL;
++      /* We don't know here, however note that we will still check against the
++       * readable/writable flags from GObject's metadata.
++       */
++      *access_type = "readwrite";
++      return data;
++    }
++}
++
++/**
++ * property_info_from_object_info:
++ * @object: introspection data
++ * @interface_name: (allow-none): Expected interface name, or %NULL for any
++ * @property_name: Expected property name (can use "-" or "_" as separator)
++ * @access_type: (out): Can be one of "read", "write", "readwrite"
++ *
++ * Look up property introspection data for the given interface/name pair.
++ *
++ * Returns: %TRUE if property was found
++ */
++static gboolean
++property_info_from_object_info (const DBusGObjectInfo  *object,
++                                const char             *interface_name,
++                                const char             *property_name,
++                                const char            **access_type)
++{
++  const char *properties_iter;
++
++  properties_iter = object->exported_properties;
++  while (properties_iter != NULL && *properties_iter)
++    {
++      const char *cur_interface_name;
++      const char *cur_property_name;
++      const char *cur_uscore_property_name;
++      const char *cur_access_type;
++
++
++      properties_iter = property_iterate (properties_iter, object->format_version,
++                                          &cur_interface_name, &cur_property_name,
++                                          &cur_uscore_property_name, &cur_access_type);
++
++      if (interface_name && strcmp (interface_name, cur_interface_name) != 0)
++        continue;
++
++      /* This big pile of ugly is necessary to support the matrix resulting from multiplying
++       * (v0 data, v1 data) * (FooBar, foo-bar)
++       * In v1 data we have both forms of string, so we do a comparison against both without
++       * having to malloc.
++       * For v0 data, we need to reconstruct the foo-bar form.
++       *
++       * Adding to the complexity is that we *also* have to ignore the distinction between
++       * '-' and '_', because g_object_{get,set} does.
++       */
++      /* First, compare against the primary property name - no malloc required */
++      if (!compare_strings_ignoring_uscore_vs_dash (property_name, cur_property_name))
++        {
++          if (cur_uscore_property_name != NULL
++              && !compare_strings_ignoring_uscore_vs_dash (property_name, cur_uscore_property_name))
++            continue;
++          else
++            {
++              /* v0 metadata, construct uscore */
++              char *tmp_uscored;
++              gboolean matches;
++              tmp_uscored = _dbus_gutils_wincaps_to_uscore (cur_property_name);
++              matches = compare_strings_ignoring_uscore_vs_dash (property_name, tmp_uscored);
++              g_free (tmp_uscored);
++              if (!matches)
++                continue;
++            }
++        }
++
++      *access_type = cur_access_type;
++      return TRUE;
++    }
++  return FALSE;
++}
++
+ static GQuark
+ dbus_g_object_type_dbus_metadata_quark (void)
+ {
+@@ -578,16 +699,20 @@ write_interface (gpointer key, gpointer val, gpointer user_data)
+ 
+   for (; properties; properties = properties->next)
+     {
++      const char *iface;
+       const char *propname;
++      const char *propname_uscore;
++      const char *access_type;
+       GParamSpec *spec;
+       char *dbus_type;
+       gboolean can_set;
+       gboolean can_get;
+       char *s;
+ 
+-      propname = properties->data;
+       spec = NULL;
+ 
++      property_iterate (properties->data, object_info->format_version, &iface, &propname, &propname_uscore, &access_type);
++
+       s = lookup_property_name (data->object, name, propname);
+ 
+       spec = g_object_class_find_property (g_type_class_peek (data->gtype), s);
+@@ -596,12 +721,13 @@ write_interface (gpointer key, gpointer val, gpointer user_data)
+       
+       dbus_type = _dbus_gtype_to_signature (G_PARAM_SPEC_VALUE_TYPE (spec));
+       g_assert (dbus_type != NULL);
+-      
+-      can_set = ((spec->flags & G_PARAM_WRITABLE) != 0 &&
+-		 (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
+-      
++
++      can_set = strcmp (access_type, "readwrite") == 0
++                    && ((spec->flags & G_PARAM_WRITABLE) != 0
++                    && (spec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
++
+       can_get = (spec->flags & G_PARAM_READABLE) != 0;
+-      
++
+       if (can_set || can_get)
+ 	{
+ 	  g_string_append_printf (xml, "    <property name=\"%s\" ", propname);
+@@ -689,7 +815,7 @@ introspect_interfaces (GObject *object, GString *xml)
+           const char *iface;
+           const char *signame;
+ 
+-          propsig = propsig_iterate (propsig, &iface, &signame);
++          propsig = signal_iterate (propsig, &iface, &signame);
+ 
+           values = lookup_values (interfaces, iface);
+           values->signals = g_slist_prepend (values->signals, (gpointer) signame);
+@@ -700,13 +826,15 @@ introspect_interfaces (GObject *object, GString *xml)
+         {
+           const char *iface;
+           const char *propname;
++          const char *propname_uscore;
++          const char *access_type;
+ 
+-          propsig = propsig_iterate (propsig, &iface, &propname);
++          propsig = property_iterate (propsig, info->format_version, &iface, &propname, &propname_uscore, &access_type);
+ 
+           values = lookup_values (interfaces, iface);
+-          values->properties = g_slist_prepend (values->properties, (gpointer) propname);
++          values->properties = g_slist_prepend (values->properties, (gpointer)iface);
+         }
+-      
++
+       memset (&data, 0, sizeof (data));
+       data.xml = xml;
+       data.gtype = G_TYPE_FROM_INSTANCE (object);
+@@ -925,7 +1053,7 @@ dbus_g_object_type_dbus_shadow_property_quark (void)
+ static char *
+ lookup_property_name (GObject    *object,
+                       const char *wincaps_propiface,
+-                      const char *wincaps_propname)
++                      const char *requested_propname)
+ {
+   const DBusGObjectInfo *object_info;
+   GHashTable *shadow_props;
+@@ -933,9 +1061,9 @@ lookup_property_name (GObject    *object,
+   GType iface_type = 0;
+ 
+   g_assert (wincaps_propiface != NULL);
+-  g_assert (wincaps_propname != NULL);
++  g_assert (requested_propname != NULL);
+ 
+-  uscore_name = _dbus_gutils_wincaps_to_uscore (wincaps_propname);
++  uscore_name = _dbus_gutils_wincaps_to_uscore (requested_propname);
+ 
+   object_info = lookup_object_info_by_iface (object, wincaps_propiface, FALSE, &iface_type);
+   if (!object_info)
+@@ -944,7 +1072,7 @@ lookup_property_name (GObject    *object,
+   shadow_props = (GHashTable *) g_type_get_qdata (iface_type, SHADOW_PROP_QUARK);
+   if (shadow_props)
+     {
+-      shadow_prop_name = g_strdup (g_hash_table_lookup (shadow_props, wincaps_propname));
++      shadow_prop_name = g_strdup (g_hash_table_lookup (shadow_props, requested_propname));
+       if (shadow_prop_name)
+         g_free (uscore_name);
+     }
+@@ -1037,24 +1165,14 @@ get_all_object_properties (DBusConnection        *connection,
+     {
+       const char *prop_ifname;
+       const char *prop_name;
++      const char *prop_uscored;
++      const char *access_flags;
+       GParamSpec *pspec;
+       GType value_gtype;
+       GValue value = {0, };
+       gchar *variant_sig;
+ 
+-      prop_ifname = p;
+-
+-      while (*p != '\0')
+-        p++;
+-      p++;
+-      if (*p == '\0') {
+-        g_warning ("malformed exported_properties in object_info");
+-        break;
+-      }
+-      prop_name = p;
+-      while (*p != '\0')
+-        p++;
+-      p++;
++      p = property_iterate (p, object_info->format_version, &prop_ifname, &prop_name, &prop_uscored, &access_flags);
+ 
+       uscore_propname = lookup_property_name (object, wincaps_propiface, prop_name);
+ 
+@@ -1729,6 +1847,70 @@ invoke_object_method (GObject         *object,
+   goto done;
+ }
+ 
++static gboolean
++check_property_access (DBusConnection  *connection,
++                       DBusMessage     *message,
++                       GObject         *object,
++                       const char      *wincaps_propiface,
++                       const char      *requested_propname,
++                       const char      *uscore_propname,
++                       gboolean         is_set)
++{
++  const DBusGObjectInfo *object_info;
++  const char *access_type;
++  DBusMessage *ret;
++
++  if (!is_set && !disable_legacy_property_access)
++    return TRUE;
++
++  object_info = lookup_object_info_by_iface (object, wincaps_propiface, TRUE, NULL);
++  if (!object_info)
++    {
++      ret = dbus_message_new_error_printf (message,
++                                           DBUS_ERROR_ACCESS_DENIED,
++                                           "Interface \"%s\" isn't exported (or may not exist), can't access property \"%s\"",
++                                           wincaps_propiface,
++                                           requested_propname);
++      dbus_connection_send (connection, ret, NULL);
++      dbus_message_unref (ret);
++      return FALSE;
++    }
++
++  /* Try both forms of property names: "foo_bar" or "FooBar"; for historical
++   * reasons we accept both.
++   */
++  if (object_info
++      && !(property_info_from_object_info (object_info, wincaps_propiface, requested_propname, &access_type)
++           || property_info_from_object_info (object_info, wincaps_propiface, uscore_propname, &access_type)))
++    {
++      ret = dbus_message_new_error_printf (message,
++                                           DBUS_ERROR_ACCESS_DENIED,
++                                           "Property \"%s\" of interface \"%s\" isn't exported (or may not exist)",
++                                           requested_propname,
++                                           wincaps_propiface);
++      dbus_connection_send (connection, ret, NULL);
++      dbus_message_unref (ret);
++      return FALSE;
++    }
++
++  if (strcmp (access_type, "readwrite") == 0)
++    return TRUE;
++  else if (is_set ? strcmp (access_type, "read") == 0
++             : strcmp (access_type, "write") == 0)
++    {
++       ret = dbus_message_new_error_printf (message,
++                                           DBUS_ERROR_ACCESS_DENIED,
++                                           "Property \"%s\" of interface \"%s\" is not %s",
++                                           requested_propname,
++                                           wincaps_propiface,
++                                           is_set ? "settable" : "readable");
++      dbus_connection_send (connection, ret, NULL);
++      dbus_message_unref (ret);
++      return FALSE;
++    }
++  return TRUE;
++}
++
+ static DBusHandlerResult
+ object_registration_message (DBusConnection  *connection,
+                              DBusMessage     *message,
+@@ -1740,7 +1922,7 @@ object_registration_message (DBusConnection  *connection,
+   gboolean getter;
+   gboolean getall;
+   char *s;
+-  const char *wincaps_propname;
++  const char *requested_propname;
+   const char *wincaps_propiface;
+   DBusMessageIter iter;
+   const DBusGMethodInfo *method;
+@@ -1762,7 +1944,8 @@ object_registration_message (DBusConnection  *connection,
+     return invoke_object_method (object, object_info, method, connection, message);
+ 
+   /* If no metainfo, we can still do properties and signals
+-   * via standard GLib introspection
++   * via standard GLib introspection.  Note we do now check
++   * property access against the metainfo if available.
+    */
+   getter = FALSE;
+   setter = FALSE;
+@@ -1811,10 +1994,16 @@ object_registration_message (DBusConnection  *connection,
+           g_warning ("Property get or set does not have a property name string as second arg\n");
+           return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+         }
+-      dbus_message_iter_get_basic (&iter, &wincaps_propname);
++      dbus_message_iter_get_basic (&iter, &requested_propname);
+       dbus_message_iter_next (&iter);
+ 
+-      s = lookup_property_name (object, wincaps_propiface, wincaps_propname);
++      s = lookup_property_name (object, wincaps_propiface, requested_propname);
++
++      if (!check_property_access (connection, message, object, wincaps_propiface, requested_propname, s, setter))
++        {
++          g_free (s);
++          return DBUS_HANDLER_RESULT_HANDLED;
++        }
+ 
+       pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
+                                             s);
+@@ -1850,7 +2039,7 @@ object_registration_message (DBusConnection  *connection,
+         {
+           ret = dbus_message_new_error_printf (message,
+                                                DBUS_ERROR_INVALID_ARGS,
+-                                               "No such property %s", wincaps_propname);
++                                               "No such property %s", requested_propname);
+         }
+     }
+ 
+@@ -1992,8 +2181,8 @@ export_signals (DBusGConnection *connection, const GList *info_list, GObject *ob
+           GClosure *closure;
+           char *s;
+ 
+-          sigdata = propsig_iterate (sigdata, &iface, &signame);
+-          
++          sigdata = signal_iterate (sigdata, &iface, &signame);
++
+           s = _dbus_gutils_wincaps_to_uscore (signame);
+ 
+           id = g_signal_lookup (s, gtype);
+@@ -2167,6 +2356,28 @@ dbus_g_error_info_free (gpointer p)
+  */
+ 
+ /**
++ * dbus_glib_global_set_disable_legacy_property_access:
++ *
++ * For historical reasons, DBus-GLib will allow read-only
++ * access to every GObject property of an object exported
++ * to the bus, regardless of whether or not the property
++ * is listed in the type info installed with
++ * dbus_g_object_type_install_info().  (Write access is
++ * denied however).
++ *
++ * If you wish to restrict even read-only access, you
++ * can call this method to globally change the behavior
++ * for the entire process.
++ *
++ * Since: 0.88
++ */
++void
++dbus_glib_global_set_disable_legacy_property_access (void)
++{
++  disable_legacy_property_access = TRUE;
++}
++
++/**
+  * dbus_g_object_type_install_info:
+  * @object_type: #GType for the object
+  * @info: introspection data generated by #dbus-glib-tool
+@@ -2950,23 +3161,23 @@ _dbus_gobject_test (const char *test_data_dir)
+ 
+   sigdata = dbus_glib_internal_test_object_info.exported_signals;
+   g_assert (*sigdata != '\0');
+-  sigdata = propsig_iterate (sigdata, &iface, &signame);
++  sigdata = signal_iterate (sigdata, &iface, &signame);
+   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.MyObject"));
+   g_assert (!strcmp (signame, "Frobnicate"));
+   g_assert (*sigdata != '\0');
+-  sigdata = propsig_iterate (sigdata, &iface, &signame);
++  sigdata = signal_iterate (sigdata, &iface, &signame);
+   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
+   g_assert (!strcmp (signame, "Sig0"));
+   g_assert (*sigdata != '\0');
+-  sigdata = propsig_iterate (sigdata, &iface, &signame);
++  sigdata = signal_iterate (sigdata, &iface, &signame);
+   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
+   g_assert (!strcmp (signame, "Sig1"));
+   g_assert (*sigdata != '\0');
+-  sigdata = propsig_iterate (sigdata, &iface, &signame);
++  sigdata = signal_iterate (sigdata, &iface, &signame);
+   g_assert (!strcmp (iface, "org.freedesktop.DBus.Tests.FooObject"));
+   g_assert (!strcmp (signame, "Sig2"));
+   g_assert (*sigdata == '\0');
+-  
++
+ 
+   i = 0;
+   while (i < (int) G_N_ELEMENTS (name_pairs))
+diff --git a/test/core/my-object.c b/test/core/my-object.c
+index 0fa8277..acb8afa 100644
+--- a/test/core/my-object.c
++++ b/test/core/my-object.c
+@@ -11,7 +11,10 @@
+ enum
+ {
+   PROP_0,
+-  PROP_THIS_IS_A_STRING
++  PROP_THIS_IS_A_STRING,
++  PROP_NO_TOUCHING,
++  PROP_SUPER_STUDLY,
++  PROP_SHOULD_BE_HIDDEN
+ };
+ 
+ enum
+@@ -53,7 +56,19 @@ my_object_set_property (GObject      *object,
+       g_free (mobject->this_is_a_string);
+       mobject->this_is_a_string = g_value_dup_string (value);
+       break;
+-      
++
++    case PROP_NO_TOUCHING:
++      mobject->notouching = g_value_get_uint (value);
++      break;
++
++    case PROP_SUPER_STUDLY:
++      mobject->super_studly = g_value_get_double (value);
++      break;
++
++    case PROP_SHOULD_BE_HIDDEN:
++      mobject->should_be_hidden = g_value_get_boolean (value);
++      break;
++
+     default:
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       break;
+@@ -75,7 +90,19 @@ my_object_get_property (GObject      *object,
+     case PROP_THIS_IS_A_STRING:
+       g_value_set_string (value, mobject->this_is_a_string);
+       break;
+-      
++
++    case PROP_NO_TOUCHING:
++      g_value_set_uint (value, mobject->notouching);
++      break;
++
++    case PROP_SUPER_STUDLY:
++      g_value_set_double (value, mobject->super_studly);
++      break;
++
++    case PROP_SHOULD_BE_HIDDEN:
++      g_value_set_boolean (value, mobject->should_be_hidden);
++      break;
++
+     default:
+       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       break;
+@@ -86,6 +113,7 @@ static void
+ my_object_init (MyObject *obj)
+ {
+   obj->val = 0;
++  obj->notouching = 42;
+ }
+ 
+ static void
+@@ -107,6 +135,30 @@ my_object_class_init (MyObjectClass *mobject_class)
+                                                         _("Example of a string property"),
+                                                         "default value",
+                                                         G_PARAM_READWRITE));
++  g_object_class_install_property (gobject_class,
++                                   PROP_NO_TOUCHING,
++                                   g_param_spec_uint ("no_touching",
++                                                      _("Don't touch"),
++                                                      _("Example of a readonly property (for export)"),
++                                                      0, 100, 42,
++                                                      G_PARAM_READWRITE));
++
++  g_object_class_install_property (gobject_class,
++                				   PROP_SUPER_STUDLY,
++				                   g_param_spec_double ("super-studly",
++                                                        _("In Studly Caps"),
++                                                        _("Example of a StudlyCaps property"),
++                                                        0, 256, 128,
++                                                        G_PARAM_READWRITE));
++
++  g_object_class_install_property (gobject_class,
++                				   PROP_SHOULD_BE_HIDDEN,
++				                   g_param_spec_boolean ("should-be-hidden",
++                                                        _("A non-exported property"),
++                                                        _("Example of a property we don't want exported"),
++                                                        FALSE,
++                                                        G_PARAM_READWRITE));
++
+   signals[FROBNICATE] =
+     g_signal_new ("frobnicate",
+ 		  G_OBJECT_CLASS_TYPE (mobject_class),
+@@ -785,6 +837,11 @@ my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context)
+   g_idle_add ((GSourceFunc)do_async_error,  data);
+ }
+ 
++void
++my_object_unsafe_disable_legacy_property_access (MyObject *obj)
++{
++  dbus_glib_global_set_disable_legacy_property_access ();
++}
+ 
+ extern GMainLoop *loop;
+ 
+diff --git a/test/core/my-object.h b/test/core/my-object.h
+index df82b66..a93d7fd 100644
+--- a/test/core/my-object.h
++++ b/test/core/my-object.h
+@@ -13,7 +13,10 @@ struct MyObject
+ {
+   GObject parent;
+   char *this_is_a_string;
++  guint notouching;
+   guint val;
++  gdouble super_studly;
++  gboolean should_be_hidden;
+ };
+ 
+ struct MyObjectClass
+@@ -110,4 +113,6 @@ void my_object_async_increment (MyObject *obj, gint32 x, DBusGMethodInvocation *
+ 
+ void my_object_async_throw_error (MyObject *obj, DBusGMethodInvocation *context);
+ 
++void my_object_unsafe_disable_legacy_property_access (MyObject *obj);
++
+ #endif
+diff --git a/test/core/test-dbus-glib.c b/test/core/test-dbus-glib.c
+index 0376f0d..29e0068 100644
+--- a/test/core/test-dbus-glib.c
++++ b/test/core/test-dbus-glib.c
+@@ -324,38 +324,48 @@ test_base_class_get_all (DBusGConnection *connection,
+                             G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
+                             G_TYPE_INVALID,
+                             DBUS_TYPE_G_MAP_OF_VARIANT, &hash, G_TYPE_INVALID))
+-      lose_gerror ("Unexpected error for GetProperty call of base class interface\n", error);
++      lose_gerror ("Unexpected error for GetProperty call of base class interface", error);
+     g_clear_error (&error);
+ 
+     if (!hash)
+       {
+         lose ("%s: Unexpected NULL hash table returned for GetAll call of base "
+-              "class interface\n", object_path);
++              "class interface", object_path);
+       }
+ 
+-    if (g_hash_table_size (hash) != 1)
++    if (g_hash_table_size (hash) != 3)
+       {
+-        lose ("%s: Unexpected hash table size %d (expected 1) returned for GetAll "
+-              " call of base class interface\n", object_path, g_hash_table_size (hash));
++        lose ("%s: Unexpected hash table size %d (expected 3) returned for GetAll "
++              " call of base class interface", object_path, g_hash_table_size (hash));
+       }
+     value = g_hash_table_lookup (hash, "this_is_a_string");
+     if (!value)
+       {
+         lose ("%s: Unexpected missing 'this_is_a_string' property for GetAll "
+-              "call of base class interface\n", object_path);
++              "call of base class interface", object_path);
+       }
+     if (!G_VALUE_HOLDS_STRING (value))
+       {
+         lose ("%s: Unexpected wrong type for 'this_is_a_string' property for "
+-              "GetAll call of base class interface\n", object_path);
++              "GetAll call of base class interface", object_path);
+       }
+     foo = g_value_get_string (value);
+     if (!foo || strcmp (foo, expected_string_value))
+       {
+         lose ("%s: Unexpected value for 'this_is_a_string' property for GetAll "
+-              "call of base class interface\n", object_path);
++              "call of base class interface", object_path);
+       }
+ 
++    value = g_hash_table_lookup (hash, "no-touching");
++    if (!value)
++      lose ("%s: Unexpected missing 'no-touching' property for GetAll "
++            "call of base class interface", object_path);
++    if (!G_VALUE_HOLDS_UINT (value))
++      lose ("%s: Unexpected wrong type for 'no-touching' property for "
++            "GetAll call of base class interface", object_path);
++    if (g_value_get_uint (value) != 42)
++      lose ("%s: Unexpected wrong value \"%d\" for 'no-touching' property for "
++            "GetAll call of base class interface", object_path, g_value_get_uint (value));
+     g_hash_table_destroy (hash);
+     hash = NULL;
+   }
+@@ -1987,9 +1997,10 @@ main (int argc, char **argv)
+ 	  {
+ 	    GSList *elt;
+ 	    gboolean found_manyargs;
+-	    
++	    gboolean found_no_touching = FALSE;
++
+ 	    found_myobject = TRUE;
+-	    
++
+ 	    found_manyargs = FALSE;
+ 	    for (elt = interface_info_get_methods (iface); elt; elt = elt->next)
+ 	      {
+@@ -2004,6 +2015,23 @@ main (int argc, char **argv)
+ 	      }
+ 	    if (!found_manyargs)
+ 	      lose ("Missing method org.freedesktop.DBus.GLib.Tests.MyObject.ManyArgs");
++	    for (elt = interface_info_get_properties (iface); elt; elt = elt->next)
++	      {
++	        PropertyInfo *prop = elt->data;
++
++	        if (strcmp (property_info_get_name (prop), "no-touching") == 0)
++	          {
++	            if (property_info_get_access (prop) != PROPERTY_READ)
++	              lose ("property no-touching had incorrect access %d", property_info_get_access (prop));
++	            else
++	              {
++	                found_no_touching = TRUE;
++	                break;
++	              }
++	          }
++	      }
++	    if (!found_no_touching)
++	      lose ("didn't find property \"no-touching\" in org.freedesktop.DBus.GLib.Tests.MyObject");
+ 	  }
+ 	else if (!found_fooobject && strcmp (interface_info_get_name (iface), "org.freedesktop.DBus.GLib.Tests.FooObject") == 0)
+ 	  found_fooobject = TRUE;
+@@ -2019,6 +2047,8 @@ main (int argc, char **argv)
+ 
+   /* Properties tests */
+   property_proxy = dbus_g_proxy_new_from_proxy (proxy, DBUS_INTERFACE_PROPERTIES, NULL);
++  g_object_unref (proxy);
++  proxy = NULL;
+ 
+   g_print ("Calling GetProperty (1)\n");
+   {
+@@ -2047,6 +2077,48 @@ main (int argc, char **argv)
+     g_value_unset (&value);
+   }
+ 
++  g_print ("Calling GetProperty of read-only property\n");
++  {
++    GValue value = {0,};
++    if (!dbus_g_proxy_call (property_proxy, "Get", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "no-touching",
++                            G_TYPE_INVALID,
++                            G_TYPE_VALUE, &value, G_TYPE_INVALID))
++      lose_gerror ("Failed to complete GetProperty no-touching call", error);
++    g_assert (G_VALUE_HOLDS (&value, G_TYPE_UINT));
++    g_assert (g_value_get_uint (&value) == 42);
++    g_value_unset (&value);
++  }
++
++  g_print ("Calling SetProperty (1)\n");
++  {
++    GValue value = {0,};
++    g_value_init (&value, G_TYPE_UINT);
++    g_value_set_uint (&value, 40);
++    if (dbus_g_proxy_call (property_proxy, "Set", &error,
++                           G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                           G_TYPE_STRING, "no-touching",
++                           G_TYPE_VALUE, &value, G_TYPE_INVALID, G_TYPE_INVALID))
++      lose ("Unexpected success from SetProperty call for read-only value \"no-touching\"");
++    g_clear_error (&error);
++    g_value_unset (&value);
++  }
++
++  g_print ("Calling GetProperty of read-only property (again)\n");
++  {
++    GValue value = {0,};
++    if (!dbus_g_proxy_call (property_proxy, "Get", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "no-touching",
++                            G_TYPE_INVALID,
++                            G_TYPE_VALUE, &value, G_TYPE_INVALID))
++      lose_gerror ("Failed to complete GetProperty call", error);
++    g_assert (G_VALUE_HOLDS (&value, G_TYPE_UINT));
++    g_assert (g_value_get_uint (&value) == 42);
++    g_value_unset (&value);
++  }
++
+   g_print ("Calling GetProperty (2)\n");
+   {
+     GValue value = {0,};
+@@ -2061,7 +2133,46 @@ main (int argc, char **argv)
+     g_value_unset (&value);
+   }
+ 
+-  g_print ("Calling GetProperty (3)\n");
++  g_print ("Calling GetProperty: SuperStudly\n");
++  {
++    GValue value = {0,};
++    if (!dbus_g_proxy_call (property_proxy, "Get", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "SuperStudly",
++                            G_TYPE_INVALID,
++                            G_TYPE_VALUE, &value, G_TYPE_INVALID))
++      lose_gerror ("Failed to complete GetProperty call", error);
++    g_assert (G_VALUE_HOLDS (&value, G_TYPE_DOUBLE));
++    g_value_unset (&value);
++  }
++
++  g_print ("Calling GetProperty: super-studly\n");
++  {
++    GValue value = {0,};
++    if (!dbus_g_proxy_call (property_proxy, "Get", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "super-studly",
++                            G_TYPE_INVALID,
++                            G_TYPE_VALUE, &value, G_TYPE_INVALID))
++      lose_gerror ("Failed to complete GetProperty call", error);
++    g_assert (G_VALUE_HOLDS (&value, G_TYPE_DOUBLE));
++    g_value_unset (&value);
++  }
++
++  g_print ("Calling GetProperty: super_studly\n");
++  {
++    GValue value = {0,};
++    if (!dbus_g_proxy_call (property_proxy, "Get", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "super_studly",
++                            G_TYPE_INVALID,
++                            G_TYPE_VALUE, &value, G_TYPE_INVALID))
++      lose_gerror ("Failed to complete GetProperty call", error);
++    g_assert (G_VALUE_HOLDS (&value, G_TYPE_DOUBLE));
++    g_value_unset (&value);
++  }
++
++  g_print ("Calling GetProperty on unknown property\n");
+   {
+     GValue value = {0,};
+     if (dbus_g_proxy_call (property_proxy, "Get", &error,
+@@ -2069,13 +2180,68 @@ main (int argc, char **argv)
+                             G_TYPE_STRING, "SomeUnknownProperty", 
+                             G_TYPE_INVALID,
+                             G_TYPE_VALUE, &value, G_TYPE_INVALID))
+-      lose_gerror ("Unexpected success for GetProperty call of unknown property", error);
++      lose ("Unexpected success for GetProperty call of unknown property");
+ 
+     g_clear_error (&error);
+   }
+ 
+-  g_object_unref (property_proxy);
+-  property_proxy = NULL;
++  /* These two are expected to pass unless we call disable_legacy_property_access */
++
++  g_print ("Calling GetProperty on not-exported property (legacy enabled)\n");
++  {
++    GValue value = {0,};
++    if (!dbus_g_proxy_call (property_proxy, "Get", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "should-be-hidden",
++                            G_TYPE_INVALID,
++                            G_TYPE_VALUE, &value, G_TYPE_INVALID))
++      lose_gerror ("Failed GetProperty call of \"should-be-hidden\" property", error);
++    g_assert (G_VALUE_HOLDS_BOOLEAN (&value));
++    g_assert (g_value_get_boolean (&value) == FALSE);
++    g_value_unset (&value);
++  }
++
++  g_print ("Calling GetProperty on not-exported property (legacy enabled)\n");
++  {
++    GValue value = {0,};
++    if (!dbus_g_proxy_call (property_proxy, "Get", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "ShouldBeHidden",
++                            G_TYPE_INVALID,
++                            G_TYPE_VALUE, &value, G_TYPE_INVALID))
++      lose_gerror ("Failed GetProperty call of \"ShouldBeHidden\" property", error);
++
++    g_value_unset (&value);
++  }
++
++  g_print ("Calling SetProperty on not-exported property (legacy enabled)\n");
++  {
++    GValue value = {0,};
++    g_value_init (&value, G_TYPE_BOOLEAN);
++    g_value_set_boolean (&value, TRUE);
++    if (dbus_g_proxy_call (property_proxy, "Set", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "should-be-hidden",
++                            G_TYPE_VALUE, &value,
++                            G_TYPE_INVALID, G_TYPE_INVALID))
++      lose ("Unexpected success from SetProperty call of \"should-be-hidden\" property");
++    g_value_unset (&value);
++    g_clear_error (&error);
++  }
++
++  g_print ("Calling GetProperty on not-exported property (legacy enabled)\n");
++  {
++    GValue value = {0,};
++    if (!dbus_g_proxy_call (property_proxy, "Get", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "should-be-hidden",
++                            G_TYPE_INVALID,
++                            G_TYPE_VALUE, &value, G_TYPE_INVALID))
++      lose_gerror ("Failed GetProperty call of \"should-be-hidden\" property", error);
++    g_assert (G_VALUE_HOLDS_BOOLEAN (&value));
++    g_assert (g_value_get_boolean (&value) == FALSE);
++    g_value_unset (&value);
++  }
+ 
+   /* Test GetAll */
+   /* 'testing value' set earlier by the SetProperty tests */
+@@ -2095,6 +2261,64 @@ main (int argc, char **argv)
+    */
+   test_subclass_get_all (connection, "/org/freedesktop/DBus/GLib/Tests/MyTestObjectSubclass");
+ 
++  /* Now, call disable_legacy_property_access */
++
++  g_assert (proxy == NULL);
++  proxy = dbus_g_proxy_new_for_name_owner (connection,
++                                           "org.freedesktop.DBus.GLib.TestService",
++                                           "/org/freedesktop/DBus/GLib/Tests/MyTestObject",
++                                           "org.freedesktop.DBus.GLib.Tests.MyObject",
++                                           &error);
++
++  if (!dbus_g_proxy_call (proxy, "UnsafeDisableLegacyPropertyAccess", &error,
++                          G_TYPE_INVALID, G_TYPE_INVALID))
++    lose_gerror ("Failed to invoke UnsafeDisableLegacyPropertyAccess", error);
++
++  g_object_unref (proxy);
++  proxy = NULL;
++
++  g_print ("Calling GetProperty on not-exported property (legacy *disabled*)\n");
++  {
++    GValue value = {0,};
++    if (dbus_g_proxy_call (property_proxy, "Get", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "should-be-hidden",
++                            G_TYPE_INVALID,
++                            G_TYPE_VALUE, &value, G_TYPE_INVALID))
++      lose ("Unexpected success from GetProperty call of \"should-be-hidden\" property");
++    g_clear_error (&error);
++  }
++
++  g_print ("Calling GetProperty on not-exported property (legacy *disabled*)\n");
++  {
++    GValue value = {0,};
++    if (dbus_g_proxy_call (property_proxy, "Get", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "ShouldBeHidden",
++                            G_TYPE_INVALID,
++                            G_TYPE_VALUE, &value, G_TYPE_INVALID))
++      lose ("Unexpected success from GetProperty call of \"ShouldBeHidden\" property");
++    g_clear_error (&error);
++  }
++
++  g_print ("Calling SetProperty on not-exported property (legacy *disabled*)\n");
++  {
++    GValue value = {0,};
++    g_value_init (&value, G_TYPE_BOOLEAN);
++    g_value_set_boolean (&value, FALSE);
++    if (dbus_g_proxy_call (property_proxy, "Set", &error,
++                            G_TYPE_STRING, "org.freedesktop.DBus.GLib.Tests.MyObject",
++                            G_TYPE_STRING, "should-be-hidden",
++                            G_TYPE_VALUE, &value,
++                            G_TYPE_INVALID, G_TYPE_INVALID))
++      lose ("Unexpected success from SetProperty call of \"should-be-hidden\" property");
++    g_value_unset (&value);
++    g_clear_error (&error);
++  }
++
++  g_object_unref (property_proxy);
++  property_proxy = NULL;
++
+   test_terminate_proxy1 = dbus_g_proxy_new_for_name_owner (connection,
+                             "org.freedesktop.DBus.GLib.TestService",
+                             "/org/freedesktop/DBus/GLib/Tests/MyTestObject",
+diff --git a/test/core/test-service-glib.xml b/test/core/test-service-glib.xml
+index 3bd2de3..84a3c29 100644
+--- a/test/core/test-service-glib.xml
++++ b/test/core/test-service-glib.xml
+@@ -3,6 +3,8 @@
+ <node name="/org/freedesktop/DBus/GLib/Tests/MyTestObject">
+   <interface name="org.freedesktop.DBus.GLib.Tests.MyObject">
+     <property name="this_is_a_string" type="s" access="readwrite"/>
++    <property name="no-touching" type="u" access="read"/>
++    <property name="SuperStudly" type="d" access="readwrite"/>
+ 
+     <method name="DoNothing">
+     </method>
+@@ -173,6 +175,9 @@
+     <method name="EmitFrobnicate">
+     </method>
+ 
++    <method name="UnsafeDisableLegacyPropertyAccess">
++    </method>
++
+     <!-- Export signals -->
+     <signal name="Frobnicate"/>
+ 
+-- 
+1.7.2.1
+
diff --git a/dbus-glib.spec b/dbus-glib.spec
index ebf23d6..13e43bd 100644
--- a/dbus-glib.spec
+++ b/dbus-glib.spec
@@ -8,7 +8,7 @@
 Summary: GLib bindings for D-Bus
 Name: dbus-glib
 Version: 0.86
-Release: 3%{?dist}
+Release: 4%{?dist}
 URL: http://www.freedesktop.org/software/dbus/
 #VCS: git:git://git.freedesktop.org/git/dbus/dbus-glib
 Source0: http://dbus.freedesktop.org/releases/dbus-glib/%{name}-%{version}.tar.gz
@@ -28,6 +28,8 @@ BuildRequires: gobject-introspection-devel
 
 # https://bugs.freedesktop.org/show_bug.cgi?id=28835
 Patch0: 0001-Fix-lookup-of-regular-properties-when-shadow-propert.patch
+# https://bugzilla.redhat.com/585394
+Patch1: 0001-Respect-property-access-flags-for-writing-allow-disa.patch
 
 %description
 
@@ -63,6 +65,7 @@ D-Bus tools written using the gtk+ GUI libaries
 %prep
 %setup -q
 %patch0 -p1
+%patch1 -p1
 
 %build
 %configure --disable-tests \
@@ -125,6 +128,9 @@ rm -rf %{buildroot}
 %endif
 
 %changelog
+* Wed Aug 11 2010 Colin Walters <walters at verbum.org> - 0.86-4
+- Apply patch to fix property access
+
 * Tue Jun 29 2010 Dan Williams <dcbw at redhat.com> - 0.86-3
 - Fix shadow property access (fdo #28835)
 


More information about the scm-commits mailing list