Logo Search packages:      
Sourcecode: galago-daemon version File versions  Download package

utils.c

Go to the documentation of this file.
/**
 * @file utils.c Utility functions
 *
 * Copyright (C) 2004-2006 Christian Hammond.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free
 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA  02111-1307  USA
 */
#include "galagod.h"
#include "utils.h"
#include "service-list.h"
#include "person-list.h"
#include "meta-service.h"
#include "meta-person.h"
#include "meta-presence.h"

void
galagod_dbus_send_empty_reply(DBusConnection *dbus_conn, DBusMessage *message)
{
      DBusMessage *reply;

      g_return_if_fail(dbus_conn != NULL);
      g_return_if_fail(message   != NULL);

      if (dbus_message_get_no_reply(message))
            return;

      reply = dbus_message_new_method_return(message);
      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);
}

#define IS_VALID_DBUS_NAME_CHAR(c) \
      (((c) >= '0' && (c) <= '9') || \
       ((c) >= 'A' && (c) <= 'Z') || \
       ((c) >= 'a' && (c) <= 'z'))

const char *
00051 galagod_dbus_normalize_name(const char *name)
{
      static char buffer[BUFSIZ];
      const char *c;
      char *d;

      g_return_val_if_fail(name != NULL, NULL);

      for (c = name, d = buffer; *c != '\0'; c++)
      {
            if (!IS_VALID_DBUS_NAME_CHAR(*c))
            {
                  char escaped_c[9];
                  g_snprintf(escaped_c, sizeof(escaped_c), "_0x%x_", *c);

                  strncpy(d, escaped_c, BUFSIZ - (d - buffer));
                  d += strlen(escaped_c);
            }
            else
            {
                  *d++ = *c;
            }
      }

      *d = '\0';

      return buffer;
}

DBusMessage *
galagod_object_not_found_error_new(DBusMessage *message,
                                                   const char *str, ...)
{
      DBusMessage *err_msg;
      char *error_str = NULL;
      va_list args;

      g_return_val_if_fail(message != NULL, NULL);

      if (str != NULL)
      {
            va_start(args, str);
            error_str = g_strdup_vprintf(str, args);
            va_end(args);
      }

      err_msg = dbus_message_new_error(message,
                                                       GALAGO_DBUS_ERROR_OBJECT_NOT_FOUND,
                                                       error_str);

      if (error_str != NULL)
            g_free(error_str);

      return err_msg;
}

DBusHandlerResult
common_object_set_attribute(DBusConnection *dbus_conn,
                                          DBusMessage *message,
                                          const char *iface,
                                          GalagoObject *object,
                                          GalagoObject *main_object)
{
      DBusMessage *signal;
      DBusMessageIter iter, value_iter;
      DBusMessageIter signal_iter, signal_value_iter;
      gboolean success = TRUE;
      const char *name;
      int arg_type;

      dbus_message_iter_init(message, &iter);

      signal = dbus_message_new_signal(galago_object_get_dbus_path(main_object),
                                                       iface, "AttributeSet");
      dbus_message_iter_init_append(signal, &signal_iter);

      dbus_message_iter_get_basic(&iter, &name);
      dbus_message_iter_next(&iter);
      dbus_message_iter_append_basic(&signal_iter, DBUS_TYPE_STRING, &name);

      dbus_message_iter_recurse(&iter, &value_iter);
      arg_type = dbus_message_iter_get_arg_type(&value_iter);

      switch (arg_type)
      {
            case DBUS_TYPE_STRING:
            {
                  const char *value;
                  dbus_message_iter_get_basic(&value_iter, &value);
                  galago_object_set_attr_string(object, name, value);
                  galago_object_set_attr_string(main_object, name, value);
                  dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_VARIANT,
                                                                   DBUS_TYPE_STRING_AS_STRING,
                                                                   &signal_value_iter);
                  dbus_message_iter_append_basic(&signal_value_iter,
                                                               DBUS_TYPE_STRING, &value);
                  dbus_message_iter_close_container(&signal_iter,
                                                                    &signal_value_iter);
                  break;
            }

            case DBUS_TYPE_BOOLEAN:
            {
                  gboolean value;
                  dbus_message_iter_get_basic(&value_iter, &value);
                  galago_object_set_attr_bool(object, name, value);
                  galago_object_set_attr_bool(main_object, name, value);
                  dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_VARIANT,
                                                                   DBUS_TYPE_BOOLEAN_AS_STRING,
                                                                   &signal_value_iter);
                  dbus_message_iter_append_basic(&signal_value_iter,
                                                               DBUS_TYPE_BOOLEAN, &value);
                  dbus_message_iter_close_container(&signal_iter,
                                                                    &signal_value_iter);
                  break;
            }

            case DBUS_TYPE_UINT32:
            {
                  dbus_uint32_t value;
                  dbus_message_iter_get_basic(&value_iter, &value);
                  galago_object_set_attr_int(object, name, value);
                  galago_object_set_attr_int(main_object, name, value);
                  dbus_message_iter_open_container(&signal_iter, DBUS_TYPE_VARIANT,
                                                                   DBUS_TYPE_UINT32_AS_STRING,
                                                                   &signal_value_iter);
                  dbus_message_iter_append_basic(&signal_value_iter,
                                                               DBUS_TYPE_UINT32, &value);
                  dbus_message_iter_close_container(&signal_iter,
                                                                    &signal_value_iter);
                  break;
            }

            default:
                  g_warning("Invalid property type %d passed to "
                                "SetProperty", arg_type);
                  success = FALSE;
                  break;
      }

      if (success)
            dbus_connection_send(dbus_conn, signal, NULL);

      dbus_message_unref(signal);

      galagod_dbus_send_empty_reply(dbus_conn, message);

      return DBUS_HANDLER_RESULT_HANDLED;
}

DBusHandlerResult
common_object_remove_attribute(DBusConnection *dbus_conn,
                                             DBusMessage *message,
                                             const char *iface,
                                             GalagoObject *object,
                                             GalagoObject *main_object)
{
      DBusMessage *signal;
      DBusMessageIter iter;
      const char *name;

      dbus_message_iter_init(message, &iter);
      dbus_message_iter_get_basic(&iter, &name);
      galago_object_remove_attribute(object, name);
      galago_object_remove_attribute(main_object, name);

      galagod_dbus_send_empty_reply(dbus_conn, message);

      /* Emit the signal */
      signal = dbus_message_new_signal(galago_object_get_dbus_path(main_object),
                                                       iface, "AttributeUnset");
      dbus_message_iter_init_append(signal, &iter);
      dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
      dbus_connection_send(dbus_conn, signal, NULL);
      dbus_message_unref(signal);

      return DBUS_HANDLER_RESULT_HANDLED;
}

DBusHandlerResult
common_object_get_attribute(DBusConnection *dbus_conn,
                                          DBusMessage *message,
                                          GalagoObject *object)
{
      const GValue *value;
      DBusMessageIter iter;
      DBusMessage *reply = NULL;
      char *name;

      dbus_message_iter_init(message, &iter);
      dbus_message_iter_get_basic(&iter, &name);
      value = galago_object_get_attribute(object, name);

      if (value == NULL)
      {
            reply = dbus_message_new_error_printf(message,
                  GALAGO_DBUS_ERROR_INVALID_ATTRIBUTE,
                  "The property \"%s\" is invalid.", name);
      }
      else
      {
            DBusMessageIter value_iter;

            reply = dbus_message_new_method_return(message);
            dbus_message_iter_init_append(reply, &iter);

            if (G_VALUE_HOLDS(value, G_TYPE_STRING))
            {
                  const char *str = g_value_get_string(value);
                  dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
                                                                   DBUS_TYPE_STRING_AS_STRING,
                                                                   &value_iter);
                  dbus_message_iter_append_basic(&value_iter,
                                                               DBUS_TYPE_STRING, &str);
                  dbus_message_iter_close_container(&iter, &value_iter);
            }
            else if (G_VALUE_HOLDS(value, G_TYPE_BOOLEAN))
            {
                  gboolean b = g_value_get_boolean(value);
                  dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
                                                                   DBUS_TYPE_BOOLEAN_AS_STRING,
                                                                   &value_iter);
                  dbus_message_iter_append_basic(&value_iter,
                                                               DBUS_TYPE_BOOLEAN, &b);
                  dbus_message_iter_close_container(&iter, &value_iter);
            }
            else if (G_VALUE_HOLDS(value, G_TYPE_INT))
            {
                  dbus_uint32_t i = g_value_get_int(value);
                  dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
                                                                   DBUS_TYPE_UINT32_AS_STRING,
                                                                   &value_iter);
                  dbus_message_iter_append_basic(&value_iter,
                                                               DBUS_TYPE_UINT32, &i);
                  dbus_message_iter_close_container(&iter, &value_iter);
            }
            else
            {
                  /* This should never happen. */
                  g_warning("Unknown property type %s for property %s",
                                G_VALUE_TYPE_NAME(value), name);
            }
      }

      if (reply != NULL)
      {
            dbus_connection_send(dbus_conn, reply, NULL);
            dbus_message_unref(reply);
      }

      return DBUS_HANDLER_RESULT_HANDLED;
}

DBusHandlerResult
common_object_get_attributes(DBusConnection *dbus_conn,
                                           DBusMessage *message,
                                           GalagoObject *object)
{
      DBusMessageIter iter, array_iter, struct_iter, value_iter;
      DBusMessage *reply;
      GList *l;

      reply = dbus_message_new_method_return(message);
      dbus_message_iter_init_append(reply, &iter);

      dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
                                                       DBUS_STRUCT_BEGIN_CHAR_AS_STRING
                                                       DBUS_TYPE_STRING_AS_STRING
                                                       DBUS_TYPE_VARIANT_AS_STRING
                                                       DBUS_STRUCT_END_CHAR_AS_STRING,
                                                       &array_iter);

      for (l = galago_object_get_attributes(object); l != NULL; l = l->next)
      {
            GalagoKeyValue *key_value = (GalagoKeyValue *)l->data;

            dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL,
                                                             &struct_iter);

            dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING,
                                                         &key_value->key);

            if (G_VALUE_HOLDS(key_value->value, G_TYPE_STRING))
            {
                  const char *str = g_value_get_string(key_value->value);
                  dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_VARIANT,
                                                                   DBUS_TYPE_STRING_AS_STRING,
                                                                   &value_iter);
                  dbus_message_iter_append_basic(&value_iter,
                                                               DBUS_TYPE_STRING, &str);
                  dbus_message_iter_close_container(&struct_iter, &value_iter);
            }
            else if (G_VALUE_HOLDS(key_value->value, G_TYPE_BOOLEAN))
            {
                  gboolean b = g_value_get_boolean(key_value->value);
                  dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_VARIANT,
                                                                   DBUS_TYPE_BOOLEAN_AS_STRING,
                                                                   &value_iter);
                  dbus_message_iter_append_basic(&value_iter,
                                                               DBUS_TYPE_BOOLEAN, &b);
                  dbus_message_iter_close_container(&struct_iter, &value_iter);
            }
            else if (G_VALUE_HOLDS(key_value->value, G_TYPE_INT))
            {
                  dbus_uint32_t i = g_value_get_int(key_value->value);
                  dbus_message_iter_open_container(&struct_iter, DBUS_TYPE_VARIANT,
                                                                   DBUS_TYPE_UINT32_AS_STRING,
                                                                   &value_iter);
                  dbus_message_iter_append_basic(&value_iter,
                                                               DBUS_TYPE_UINT32, &i);
                  dbus_message_iter_close_container(&struct_iter, &value_iter);
            }
            else
            {
                  /* This should never happen. */
                  g_warning("Unknown property type %s for property %s",
                                G_VALUE_TYPE_NAME(key_value->value), key_value->key);
            }

            dbus_message_iter_close_container(&array_iter, &struct_iter);
      }

      dbus_message_iter_close_container(&iter, &array_iter);

      dbus_connection_send(dbus_conn, reply, NULL);
      dbus_message_unref(reply);

      return DBUS_HANDLER_RESULT_HANDLED;
}

void
common_meta_object_merge_attributes(GalagoObject *main_object,
                                                      GalagoObject *new_object,
                                                      GList *objects)
{
      GList *l;

      /*
       * TODO: This logic needs to be improved! We need to actually determine
       *       if there's a consensus on attribute values. For now, though,
       *       we're going to be cheap and just copy over attributes.
       */

      for (l = galago_object_get_attributes(new_object); l != NULL; l = l->next)
      {
            GalagoKeyValue *key_value = (GalagoKeyValue *)l->data;
            GValue *new_value;

            if (!strcmp(key_value->key, "uid"))
                  continue;

            new_value = g_new0(GValue, 1);
            g_value_init(new_value, G_VALUE_TYPE(key_value->value));
            g_value_copy(key_value->value, new_value);

            galago_object_set_attribute(main_object, key_value->key, new_value);
      }
}

Generated by  Doxygen 1.6.0   Back to index