Package: gupnp-tools
Version: 0.6-1
Severity: normal
Tags: patch

gupnp-universal-cp can send UPnP arguments in the wrong order when invoking actions. The UPnP spec requires that action arguments are sent in the order in which they appear in the SCPD. What's worse, the DLNA spec requires compliant devices to reject invokations from clients that don't respect argument ordering.

In action-dialog.c, the call to gupnp_service_proxy_begin_action_hash (line 715) doesn't contain enough context for the library to correctly order the arguments of the service call. As a result, the arguments are ordered by the iteration order of the hash keys. The correct answer is probably to add enough context to a service proxy object for it to be able to retrieve the order of an action's arguments, but I've attached patches for an incorrect answer - adding an extra function to the library that accepts more context, and changing the call in action-dialog.c.

-- System Information:
Debian Release: 5.0
 APT prefers unstable
 APT policy: (500, 'unstable'), (500, 'testing')
Architecture: i386 (i686)

Kernel: Linux 2.6.26-1-686 (SMP w/2 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash

Versions of packages gupnp-tools depends on:
ii  libc6                      2.7-18        GNU C Library: Shared libraries
ii libglade2-0 1:2.6.3-1 library to load .glade files at ru
ii  libglib2.0-0               2.18.4-2      The GLib library of C routines
ii  libgssdp-1.0-1             0.6.4-1       GObject-based library for SSDP
ii libgtk2.0-0 2.12.11-4 The GTK+ graphical user interface
ii  libgupnp-1.0-2             0.12.6-2      GObject-based library for UPnP
ii libgupnp-av-1.0-1 0.2.1-1 Audio/Visual utility library for G ii libsoup2.4-1 2.24.3-2 an HTTP library implementation in
ii  libuuid1                   1.41.3-1      universally unique id library
ii  libxml2                    2.6.32.dfsg-5 GNOME XML library

gupnp-tools recommends no packages.

gupnp-tools suggests no packages.

-- no debconf information

diff -ur gupnp-0.12.6/libgupnp/gupnp-service-proxy.c 
gupnp-0.12.6-at/libgupnp/gupnp-service-proxy.c
--- gupnp-0.12.6/libgupnp/gupnp-service-proxy.c 2009-01-06 14:32:22.000000000 
+0000
+++ gupnp-0.12.6-at/libgupnp/gupnp-service-proxy.c      2009-03-12 
17:30:01.000000000 +0000
@@ -791,6 +791,52 @@
         return ret;
 }
 
+GUPnPServiceProxyAction *
+gupnp_service_proxy_begin_action_hash_with_ordering
+                                   (GUPnPServiceProxy              *proxy,
+                                    const char                     *action,
+                                    GUPnPServiceProxyActionCallback callback,
+                                    gpointer                        user_data,
+                                    GHashTable                     *hash,
+                                    GUPnPServiceActionInfo         
*action_info)
+{
+        GUPnPServiceProxyAction *ret;
+
+        g_return_val_if_fail (GUPNP_IS_SERVICE_PROXY (proxy), NULL);
+        g_return_val_if_fail (action, NULL);
+        g_return_val_if_fail (callback, NULL);
+
+        /* Create message */
+        ret = begin_action_msg (proxy, action, callback, user_data);
+
+        if (ret->error) {
+                callback (proxy, ret, user_data);
+
+                return ret;
+        }
+
+        GList *iter;
+        for (iter = action_info->arguments; iter; iter = iter->next)
+        {
+                GUPnPServiceActionArgInfo *arg_info = iter->data;
+                GValue *value = g_hash_table_lookup(hash, arg_info->name);
+                if (value != NULL)
+                {
+                        write_in_parameter(arg_info->name, value, 
ret->msg_str);
+                }
+                else
+                {
+                        g_warning("No value supplied for action arg %s", 
arg_info->name);
+                }
+        }
+
+        /* Finish and send off */
+        finish_action_msg (ret, action);
+
+        return ret;
+
+}
+
 /**
  * gupnp_service_proxy_begin_action_hash
  * @proxy: A #GUPnPServiceProxy
diff -ur gupnp-0.12.6/libgupnp/gupnp-service-proxy.h 
gupnp-0.12.6-at/libgupnp/gupnp-service-proxy.h
--- gupnp-0.12.6/libgupnp/gupnp-service-proxy.h 2009-01-06 14:32:22.000000000 
+0000
+++ gupnp-0.12.6-at/libgupnp/gupnp-service-proxy.h      2009-03-12 
17:22:46.000000000 +0000
@@ -159,6 +159,15 @@
                                     gpointer                        user_data,
                                     GHashTable                     *hash);
 
+GUPnPServiceProxyAction *
+gupnp_service_proxy_begin_action_hash_with_ordering
+                                   (GUPnPServiceProxy              *proxy,
+                                    const char                     *action,
+                                    GUPnPServiceProxyActionCallback callback,
+                                    gpointer                        user_data,
+                                    GHashTable                     *hash,
+                                    GUPnPServiceActionInfo         
*action_info);
+
 gboolean
 gupnp_service_proxy_end_action     (GUPnPServiceProxy              *proxy,
                                     GUPnPServiceProxyAction        *action,
diff -ur gupnp-tools-0.6/src/universal-cp/action-dialog.c 
gupnp-tools-0.6-at/src/universal-cp/action-dialog.c
--- gupnp-tools-0.6/src/universal-cp/action-dialog.c    2008-02-25 
10:53:11.000000000 +0000
+++ gupnp-tools-0.6-at/src/universal-cp/action-dialog.c 2009-03-12 
17:41:17.000000000 +0000
@@ -712,11 +712,12 @@
         in_args = retrieve_in_action_arguments (introspection,
                                                 action_info);
 
-        gupnp_service_proxy_begin_action_hash (proxy,
+        gupnp_service_proxy_begin_action_hash_with_ordering(proxy,
                                               action_info->name,
                                               on_action_complete,
                                               NULL,
-                                              in_args);
+                                              in_args,
+                                              action_info);
 
         g_hash_table_destroy (in_args);
         g_object_unref (proxy);

Reply via email to