[Telepathy-commits] [telepathy-mission-control/master] Load .client files

Alberto Mardegan alberto.mardegan at nokia.com
Mon Nov 17 00:05:16 PST 2008


Scan the $XDG/telepathy/clients/ directories for .client files and parse them
into memory structures.
---
 src/mcd-dispatcher.c |  249 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 247 insertions(+), 2 deletions(-)

diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c
index 46955f6..d6fc7be 100644
--- a/src/mcd-dispatcher.c
+++ b/src/mcd-dispatcher.c
@@ -43,9 +43,15 @@
 #include "mcd-master.h"
 #include "mcd-chan-handler.h"
 #include "mcd-dispatcher-context.h"
+#include "mcd-misc.h"
+#include "_gen/interfaces.h"
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/proxy-subclass.h>
 
 #include <libmcclient/mc-errors.h>
 
+#include <string.h>
+
 #define MCD_DISPATCHER_PRIV(dispatcher) (G_TYPE_INSTANCE_GET_PRIVATE ((dispatcher), \
 				  MCD_TYPE_DISPATCHER, \
 				  McdDispatcherPrivate))
@@ -75,6 +81,41 @@ typedef struct _McdDispatcherArgs
     GPtrArray *channel_handler_caps;
 } McdDispatcherArgs;
 
+#define MCD_FILTER_CHANNEL_TYPE 0x1
+#define MCD_FILTER_HANDLE_TYPE  0x2
+#define MCD_FILTER_REQUESTED    0x4
+typedef struct _McdClientFilter
+{
+    guint field_mask;
+    GQuark channel_type;
+    TpHandleType handle_type;
+    guint requested : 1;
+} McdClientFilter;
+
+typedef enum
+{
+    MCD_CLIENT_APPROVER = 0x1,
+    MCD_CLIENT_HANDLER  = 0x2,
+    MCD_CLIENT_OBSERVER = 0x4,
+} McdClientInterface;
+
+typedef struct _McdClient
+{
+    TpProxy *proxy;
+    gchar *name;
+    McdClientInterface interfaces;
+    guint bypass_approver : 1;
+    /* each element is a McdClientFilter */
+    GList *approver_filters;
+    GList *handler_filters;
+    GList *observer_filters;
+} McdClient;
+
+#define MCD_IFACE_CLIENT "org.freedesktop.Telepathy.Client"
+#define MCD_IFACE_CLIENT_APPROVER "org.freedesktop.Telepathy.Client.Approver"
+#define MCD_IFACE_CLIENT_HANDLER "org.freedesktop.Telepathy.Client.Handler"
+#define MCD_IFACE_CLIENT_OBSERVER "org.freedesktop.Telepathy.Client.Observer"
+
 typedef struct _McdDispatcherPrivate
 {
     /* Pending state machine contexts */
@@ -91,7 +132,10 @@ typedef struct _McdDispatcherPrivate
     /* Array of channel handler's capabilities, stored as a GPtrArray for
      * performance reasons */
     GPtrArray *channel_handler_caps;
-    
+
+    /* each element is a McdClient struct */
+    GList *clients;
+
     McdMaster *master;
  
     gboolean is_disposed;
@@ -133,6 +177,27 @@ static void mcd_dispatcher_context_free (McdDispatcherContext * ctx);
 typedef void (*tp_ch_handle_channel_reply) (DBusGProxy *proxy, GError *error, gpointer userdata);
 
 static void
+mcd_client_filter_free (McdClientFilter *filter)
+{
+    g_slice_free (McdClientFilter, filter);
+}
+
+static void
+mcd_client_free (McdClient *client)
+{
+    if (client->proxy)
+        g_object_unref (client->proxy);
+
+    g_free (client->name);
+    g_list_foreach (client->approver_filters,
+                    (GFunc)mcd_client_filter_free, NULL);
+    g_list_foreach (client->handler_filters,
+                    (GFunc)mcd_client_filter_free, NULL);
+    g_list_foreach (client->observer_filters,
+                    (GFunc)mcd_client_filter_free, NULL);
+}
+
+static void
 tp_ch_handle_channel_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)
 {
   DBusGAsyncData *data = (DBusGAsyncData*) user_data;
@@ -970,7 +1035,9 @@ _mcd_dispatcher_dispose (GObject * object)
 	return;
     }
     priv->is_disposed = TRUE;
-    
+
+    g_list_foreach (priv->clients, (GFunc)mcd_client_free, NULL);
+
     if (priv->master)
     {
 	g_object_unref (priv->master);
@@ -1006,6 +1073,183 @@ mcd_dispatcher_send (McdDispatcher * dispatcher, McdChannel *channel)
     return TRUE;
 }
 
+static McdClientFilter *
+parse_client_filter (GKeyFile *file, const gchar *group)
+{
+    McdClientFilter *filter;
+    gchar **keys;
+    gsize len = 0;
+    guint i;
+
+    filter = g_slice_new0 (McdClientFilter);
+
+    keys = g_key_file_get_keys (file, group, &len, NULL);
+    for (i = 0; i < len; i++)
+    {
+        const gchar *key;
+
+        key = keys[i];
+        if (strcmp (key, TP_IFACE_CHANNEL ".Type s") == 0)
+        {
+            gchar *string;
+
+            string = g_key_file_get_string (file, group, key, NULL);
+            filter->channel_type = g_quark_from_string (string);
+            g_free (string);
+
+            filter->field_mask |= MCD_FILTER_CHANNEL_TYPE;
+        }
+        else if (strcmp (key, TP_IFACE_CHANNEL ".TargetHandleType u") == 0)
+        {
+            filter->handle_type =
+                (guint) g_key_file_get_integer (file, group, key, NULL);
+            filter->field_mask |= MCD_FILTER_HANDLE_TYPE;
+        }
+        else if (strcmp (key, TP_IFACE_CHANNEL ".Requested b") == 0)
+        {
+            filter->requested =
+                g_key_file_get_boolean (file, group, key, NULL);
+            filter->field_mask |= MCD_FILTER_REQUESTED;
+        }
+        else
+        {
+            g_warning ("Invalid key %s in client file", key);
+            continue;
+        }
+    }
+    g_strfreev (keys);
+
+    return filter;
+}
+
+static void
+create_client_proxy (McdDispatcherPrivate *priv, McdClient *client)
+{
+    gchar *bus_name, *object_path;
+
+    bus_name = g_strconcat ("org.freedesktop.Telepathy.Client.",
+                            client->name, NULL);
+    object_path = g_strconcat ("/org/freedesktop/Telepathy/Client/",
+                               client->name, NULL);
+    client->proxy = g_object_new (TP_TYPE_PROXY,
+                                  "dbus-daemon", priv->dbus_daemon,
+                                  "object-path", object_path,
+                                  "bus-name", bus_name,
+                                  NULL);
+    g_free (object_path);
+    g_free (bus_name);
+
+    tp_proxy_add_interface_by_id (client->proxy, MC_IFACE_QUARK_CLIENT);
+    if (client->interfaces & MCD_CLIENT_APPROVER)
+        tp_proxy_add_interface_by_id (client->proxy,
+                                      MC_IFACE_QUARK_CLIENT_APPROVER);
+    if (client->interfaces & MCD_CLIENT_HANDLER)
+        tp_proxy_add_interface_by_id (client->proxy,
+                                      MC_IFACE_QUARK_CLIENT_HANDLER);
+    if (client->interfaces & MCD_CLIENT_OBSERVER)
+        tp_proxy_add_interface_by_id (client->proxy,
+                                      MC_IFACE_QUARK_CLIENT_OBSERVER);
+
+    priv->clients = g_list_prepend (priv->clients, client);
+}
+
+static gboolean
+parse_client_file (const gchar *path, const gchar *filename,
+                   gpointer user_data)
+{
+    McdDispatcherPrivate *priv = user_data;
+    GKeyFile *file;
+    const gchar *extension;
+    gchar **iface_names, **groups;
+    McdClient *client;
+    guint i;
+    gsize len = 0;
+    GError *error = NULL;
+
+    extension = g_strrstr (filename, ".client");
+    if (!extension || extension[7] != 0) return TRUE;
+
+    file = g_key_file_new ();
+    g_key_file_load_from_file (file, path, 0, &error);
+    if (error)
+    {
+        g_warning ("Error loading %s: %s", path, error->message);
+        goto finish;
+    }
+
+    iface_names = g_key_file_get_string_list (file, MCD_IFACE_CLIENT,
+                                              "Interfaces", 0, NULL);
+    if (!iface_names)
+        goto finish;
+
+    client = g_slice_new0 (McdClient);
+    for (i = 0; iface_names[i] != NULL; i++)
+    {
+        if (strcmp (iface_names[i], MCD_IFACE_CLIENT_APPROVER) == 0)
+            client->interfaces |= MCD_CLIENT_APPROVER;
+        else if (strcmp (iface_names[i], MCD_IFACE_CLIENT_HANDLER) == 0)
+            client->interfaces |= MCD_CLIENT_HANDLER;
+        else if (strcmp (iface_names[i], MCD_IFACE_CLIENT_OBSERVER) == 0)
+            client->interfaces |= MCD_CLIENT_OBSERVER;
+    }
+    g_strfreev (iface_names);
+
+    /* parse filtering rules */
+    groups = g_key_file_get_groups (file, &len);
+    for (i = 0; i < len; i++)
+    {
+        if (client->interfaces & MCD_CLIENT_APPROVER &&
+            g_str_has_prefix (groups[i], MCD_IFACE_CLIENT_APPROVER
+                              ".ApproverChannelFilter "))
+        {
+            client->approver_filters =
+                g_list_prepend (client->approver_filters,
+                                parse_client_filter (file, groups[i]));
+        }
+        else if (client->interfaces & MCD_CLIENT_HANDLER &&
+            g_str_has_prefix (groups[i], MCD_IFACE_CLIENT_HANDLER
+                              ".HandlerChannelFilter "))
+        {
+            client->handler_filters =
+                g_list_prepend (client->handler_filters,
+                                parse_client_filter (file, groups[i]));
+        }
+        else if (client->interfaces & MCD_CLIENT_OBSERVER &&
+            g_str_has_prefix (groups[i], MCD_IFACE_CLIENT_OBSERVER
+                              ".ObserverChannelFilter "))
+        {
+            client->observer_filters =
+                g_list_prepend (client->observer_filters,
+                                parse_client_filter (file, groups[i]));
+        }
+    }
+    g_strfreev (groups);
+
+    /* Other client options */
+    client->bypass_approver =
+        g_key_file_get_boolean (file, MCD_IFACE_CLIENT_HANDLER,
+                                "BypassApprover", NULL);
+
+    client->name = g_strndup (filename, extension - filename);
+    g_debug ("%s: adding client %s from .client file",
+             G_STRFUNC, client->name);
+
+    create_client_proxy (priv, client);
+
+finish:
+    g_key_file_free (file);
+    return TRUE;
+}
+
+static void
+mcd_dispatcher_constructed (GObject *object)
+{
+    McdDispatcherPrivate *priv = MCD_DISPATCHER_PRIV (object);
+
+    _mcd_xdg_data_subdir_foreach ("telepathy/clients",
+                                  parse_client_file, priv);
+}
+
 static void
 mcd_dispatcher_class_init (McdDispatcherClass * klass)
 {
@@ -1013,6 +1257,7 @@ mcd_dispatcher_class_init (McdDispatcherClass * klass)
 
     g_type_class_add_private (object_class, sizeof (McdDispatcherPrivate));
 
+    object_class->constructed = mcd_dispatcher_constructed;
     object_class->set_property = _mcd_dispatcher_set_property;
     object_class->get_property = _mcd_dispatcher_get_property;
     object_class->finalize = _mcd_dispatcher_finalize;
-- 
1.5.6.5




More information about the Telepathy-commits mailing list