Logo Search packages:      
Sourcecode: libtelepathy version File versions

tp-helpers.c

/*
 * tp-helpers.c - Source for various helper functions
 * for telepathy implementation
 *
 * Copyright (C) 2005 Collabora Ltd.
 * Copyright (C) 2005 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <dbus/dbus-glib.h>
#include <stdlib.h>
#include <string.h>
#include "tp-helpers.h"


#define CM_CONFS_DIR   "/telepathy/managers/"
#define CM_CONF_SUFFIX ".manager"
#define CM_CONF_GROUP "ConnectionManager"


static void _list_builder(gpointer key, gpointer value, gpointer data);
static void _prot_param_free (TpConnMgrProtParam *param);
static void _scan_dir (GSList **cmgr_list, const gchar *path);

void
_tp_warn_failure (const char *op, GError *error)
{
  if (error->domain == DBUS_GERROR
      && error->code == DBUS_GERROR_REMOTE_EXCEPTION)
    {
      g_warning ("%s failed: %s (%s)", op, error->message,
          dbus_g_error_get_name (error));
    }
  else
    {
      g_warning ("%s failed: %s (%s code %d)", op, error->message,
          g_quark_to_string (error->domain), error->code);
    }
}

DBusGConnection *
tp_get_bus ()
{
  static DBusGConnection *bus = NULL;

  if (bus == NULL)
    {
      GError *error = NULL;

      bus = dbus_g_bus_get (DBUS_BUS_STARTER, &error);

      if (bus == NULL)
        g_error ("Failed to connect to starter bus: %s", error->message);
    }

  return bus;
}

DBusGProxy *
tp_get_bus_proxy ()
{
  static DBusGProxy *bus_proxy = NULL;

  if (bus_proxy == NULL)
    {
      DBusGConnection *bus = tp_get_bus ();

      bus_proxy = dbus_g_proxy_new_for_name (bus,
                                            "org.freedesktop.DBus",
                                            "/org/freedesktop/DBus",
                                            "org.freedesktop.DBus");

      if (bus_proxy == NULL)
        g_error ("Failed to get proxy object for bus.");
    }

  return bus_proxy;
}

GSList *
tp_hash_to_key_value_list(GHashTable *hash)
{
  GSList *ret = NULL;
  g_hash_table_foreach(hash, _list_builder, &ret);
  return ret;
}

void
tp_key_value_list_free(GSList *list)
{
  GSList *iter;

  for (iter = list; iter; iter = g_slist_next(iter))
  {
    g_free(iter->data);
  }
  g_slist_free(list);
}

static void _list_builder(gpointer key, gpointer value, gpointer data)
{
  GSList **list = (GSList **)data;
  TpKeyValue *kv = g_new0(TpKeyValue, 1);
  kv->key = key;
  kv->value = value;
  *list = g_slist_prepend(*list, kv);
}

static void
_scan_dir (GSList **cmgr_list, const gchar *path)
{
  GDir *dir;
  const gchar *filename;

  if ((dir = g_dir_open (path, 0, NULL)) == NULL)
    return;

  while ((filename = g_dir_read_name (dir)) != NULL)
    if (g_str_has_suffix (filename, CM_CONF_SUFFIX))
    {
      gchar **name;

      name = g_strsplit (filename, ".", 0);
      *cmgr_list = g_slist_append (*cmgr_list, g_strdup (*name));
      g_strfreev (name);
    }

  g_dir_close (dir);
}

GSList *
tp_connmgr_list_cms (void)
{
  GSList *cmgr_list = NULL;
  const gchar * const *data_dirs;
  gchar *path;
  gint index;

  /* Read the configuration file directory */
  path = g_build_filename (g_get_user_data_dir (), CM_CONFS_DIR, NULL);
  _scan_dir (&cmgr_list, path);
  g_free (path);

  data_dirs = g_get_system_data_dirs ();
  for (index = 0; data_dirs[index] != NULL; index++)
  {
    path = g_build_filename (data_dirs[index], CM_CONFS_DIR, NULL);
    _scan_dir (&cmgr_list, path);
    g_free (path);
  }

  return cmgr_list;
}

TpConnMgrInfo *
tp_connmgr_get_info(const gchar *cm)
{
  GError *error = NULL;
  GKeyFile *file;
  gchar *absolute_filepath;
  gchar *home_dir_confs;
  gchar **groups, **group;
  TpConnMgrInfo *cm_info;

  home_dir_confs = g_build_filename (g_get_user_data_dir (), CM_CONFS_DIR, NULL);
  absolute_filepath = g_strconcat (home_dir_confs, cm, CM_CONF_SUFFIX, NULL);
  g_free (home_dir_confs);
  if (!g_file_test (absolute_filepath, G_FILE_TEST_EXISTS))
  {
    gint  index;
    gchar *dir_confs;
    const gchar * const *data_dirs;

    g_free (absolute_filepath);
    absolute_filepath = NULL;

    data_dirs = g_get_system_data_dirs ();
    for (index = 0; data_dirs[index] != NULL && absolute_filepath == NULL; index++)
    {
      dir_confs = g_build_filename (data_dirs[index], CM_CONFS_DIR, NULL);
      absolute_filepath = g_strconcat (dir_confs, cm, CM_CONF_SUFFIX, NULL);
      g_free (dir_confs);

      if (!g_file_test (absolute_filepath, G_FILE_TEST_EXISTS))
      {
        g_free (absolute_filepath);
        absolute_filepath = NULL;
      }
    }

    if (absolute_filepath == NULL)
    {
      g_warning ("Could not open configuration file for:'%s'", cm);
      return NULL;
    }
  }

  cm_info = g_slice_new0(TpConnMgrInfo);
  cm_info->protocols = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
                                             (GDestroyNotify)g_hash_table_destroy);

  file = g_key_file_new();
  if (!g_key_file_load_from_file
      (file, absolute_filepath, G_KEY_FILE_NONE, &error))
  {
    /* handle error */
    g_printerr("%s", error->message);
    g_error_free(error);
    g_free(absolute_filepath);
    g_key_file_free(file);
    tp_connmgr_info_free(cm_info);
    return NULL;
  }
  g_free (absolute_filepath);

  cm_info->name = g_strdup (cm);

  if (!(cm_info->bus_name = g_key_file_get_string(file, CM_CONF_GROUP,
          "BusName", &error)))
  {
    /* handle error and free dynamic memory */
    g_printerr("%s", error->message);
    g_error_free(error);
    g_key_file_free(file);
    tp_connmgr_info_free(cm_info);
    return NULL;
  }
  if (!(cm_info->object_path = g_key_file_get_string(file,CM_CONF_GROUP,
          "ObjectPath", &error)))
  {
    /* handle error and free dynamic memory */
    g_printerr("%s", error->message);
    g_error_free(error);
    g_key_file_free(file);
    tp_connmgr_info_free(cm_info);
    return NULL;
  }

  groups = g_key_file_get_groups(file, NULL);

  for(group = groups+1; *group; group++)
  {
    gchar **keys, **key;
    gchar *prot_name;
    GHashTable *params;

    if (!g_str_has_prefix(*group, "Protocol "))
      continue;

    params = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
                                   (GDestroyNotify)_prot_param_free);
    keys = g_strsplit(*group, " ", 2);
    prot_name = g_strdup(keys[1]);
    g_strfreev(keys);
    g_hash_table_insert(cm_info->protocols, prot_name, params);

    if (!(keys = g_key_file_get_keys(file, *group, NULL, &error)))
    {
      g_printerr("%s", error->message);
      g_error_free(error);
      continue;
    }

    for (key = keys; *key; key++)
    {
      gchar **strv;
      gchar *param_name;
      gchar *key_value;
      TpConnMgrProtParam *param;

      if (!g_str_has_prefix(*key, "param-") &&
          !g_str_has_prefix(*key, "default-"))
      {
        g_printerr("invalid protocol key");
        continue;
      }

      if (!(key_value = g_key_file_get_string(file, *group, *key, &error)))
      {
        g_printerr("%s", error->message);
        g_error_free(error);
        continue;
      }
      
      strv = g_strsplit(*key, "-", 2);
      param_name = g_strdup(strv[1]);
      param = g_hash_table_lookup(params, param_name);
      if (!param)
      {
        param = g_slice_new0(TpConnMgrProtParam);
        g_hash_table_insert (params, param_name, param);
      }

      if (strcmp(strv[0], "param") == 0)
      {
        gchar **flags, **f;

        flags = g_strsplit(key_value, " ", 0);
        g_free(key_value);
        param->dbus_type = g_strdup(flags[0]);

        for (f = flags + 1; *f; f++)
        {
          if (strcmp(*f, "required") == 0)
            param->flags |= TP_CONNMGR_PROT_PARAM_FLAG_REQUIRED;
          else if (strcmp(*f, "register") == 0)
            param->flags |= TP_CONNMGR_PROT_PARAM_FLAG_REGISTER;
        }
        g_strfreev(flags);
      } else if (strcmp(strv[1], "default"))
      {
        param->default_value = key_value;
        param->flags |= TP_CONNMGR_PROT_PARAM_FLAG_HAS_DEFAULT;
      } else
      {
          g_printerr("invalid param key:%s", *key);
          g_free(key_value);
          g_strfreev(strv);
          continue;
      }
      g_strfreev(strv);
    }
    g_strfreev (keys);
  }

  g_strfreev(groups);
  g_key_file_free (file);
  return cm_info;
}

static void
_prot_param_free (TpConnMgrProtParam *param)
{
  g_free(param->dbus_type);
  g_free(param->default_value);
  g_slice_free(TpConnMgrProtParam, param);
}

void
tp_connmgr_info_free (TpConnMgrInfo *info)
{
  if (!info)
    return;
  g_free(info->name);
  g_free(info->bus_name);
  g_free(info->object_path);
  if (info->protocols)
    g_hash_table_destroy(info->protocols);
  g_slice_free(TpConnMgrInfo, info);
}


Generated by  Doxygen 1.6.0   Back to index