gdbus: use GDBusArgInfo to generate introspection
[framework/connectivity/connman.git] / gdbus / object.c
index 725c0bb..3ac6a0b 100644 (file)
@@ -2,7 +2,7 @@
  *
  *  D-Bus helper library
  *
- *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (C) 2004-2011  Marcel Holtmann <marcel@holtmann.org>
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -59,63 +59,20 @@ struct security_data {
        void *iface_user_data;
 };
 
-static void print_arguments(GString *gstr, const char *sig,
+static void print_arguments(GString *gstr, const GDBusArgInfo *args,
                                                const char *direction)
 {
-       int i;
-
-       for (i = 0; sig[i]; i++) {
-               char type[32];
-               int struct_level, dict_level;
-               unsigned int len;
-               gboolean complete;
-
-               complete = FALSE;
-               struct_level = dict_level = 0;
-               memset(type, 0, sizeof(type));
-
-               /* Gather enough data to have a single complete type */
-               for (len = 0; len < (sizeof(type) - 1) && sig[i]; len++, i++) {
-                       switch (sig[i]){
-                       case '(':
-                               struct_level++;
-                               break;
-                       case ')':
-                               struct_level--;
-                               if (struct_level <= 0 && dict_level <= 0)
-                                       complete = TRUE;
-                               break;
-                       case '{':
-                               dict_level++;
-                               break;
-                       case '}':
-                               dict_level--;
-                               if (struct_level <= 0 && dict_level <= 0)
-                                       complete = TRUE;
-                               break;
-                       case 'a':
-                               break;
-                       default:
-                               if (struct_level <= 0 && dict_level <= 0)
-                                       complete = TRUE;
-                               break;
-                       }
-
-                       type[len] = sig[i];
-
-                       if (complete)
-                               break;
-               }
-
+       for (; args && args->name; args++) {
+               g_string_append_printf(gstr,
+                                       "\t\t\t<arg name=\"%s\" type=\"%s\"",
+                                       args->name, args->signature);
 
                if (direction)
                        g_string_append_printf(gstr,
-                                       "\t\t\t<arg type=\"%s\" direction=\"%s\"/>\n",
-                                       type, direction);
+                                       " direction=\"%s\"/>\n", direction);
                else
-                       g_string_append_printf(gstr,
-                                       "\t\t\t<arg type=\"%s\"/>\n",
-                                       type);
+                       g_string_append_printf(gstr, "/>\n");
+
        }
 }
 
@@ -125,26 +82,27 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
        const GDBusSignalTable *signal;
 
        for (method = iface->methods; method && method->name; method++) {
-               if (!strlen(method->signature) && !strlen(method->reply))
+               if (!(method->in_args && method->in_args->name) &&
+                               !(method->out_args && method->out_args->name))
                        g_string_append_printf(gstr, "\t\t<method name=\"%s\"/>\n",
                                                                method->name);
                else {
                        g_string_append_printf(gstr, "\t\t<method name=\"%s\">\n",
                                                                method->name);
-                       print_arguments(gstr, method->signature, "in");
-                       print_arguments(gstr, method->reply, "out");
+                       print_arguments(gstr, method->in_args, "in");
+                       print_arguments(gstr, method->out_args, "out");
                        g_string_append_printf(gstr, "\t\t</method>\n");
                }
        }
 
        for (signal = iface->signals; signal && signal->name; signal++) {
-               if (!strlen(signal->signature))
+               if (!(signal->args && signal->args->name))
                        g_string_append_printf(gstr, "\t\t<signal name=\"%s\"/>\n",
                                                                signal->name);
                else {
                        g_string_append_printf(gstr, "\t\t<signal name=\"%s\">\n",
                                                                signal->name);
-                       print_arguments(gstr, signal->signature, NULL);
+                       print_arguments(gstr, signal->args, NULL);
                        g_string_append_printf(gstr, "\t\t</signal>\n");
                }
        }
@@ -162,7 +120,7 @@ static void generate_introspection_xml(DBusConnection *conn,
 
        gstr = g_string_new(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
 
-       g_string_append_printf(gstr, "<node name=\"%s\">\n", path);
+       g_string_append_printf(gstr, "<node>\n");
 
        for (list = data->interfaces; list; list = list->next) {
                struct interface_data *iface = list->data;
@@ -201,12 +159,12 @@ static DBusMessage *introspect(DBusConnection *connection,
                return NULL;
        }
 
-       if (!data->introspect)
+       if (data->introspect == NULL)
                generate_introspection_xml(connection, data,
                                                dbus_message_get_path(message));
 
        reply = dbus_message_new_method_return(message);
-       if (!reply)
+       if (reply == NULL)
                return NULL;
 
        dbus_message_append_args(reply, DBUS_TYPE_STRING, &data->introspect,
@@ -255,14 +213,13 @@ void g_dbus_pending_success(DBusConnection *connection,
 
         for (list = pending_security; list; list = list->next) {
                struct security_data *secdata = list->data;
-               DBusHandlerResult result;
 
                if (secdata->pending != pending)
                        continue;
 
                pending_security = g_slist_remove(pending_security, secdata);
 
-               result = process_message(connection, secdata->message,
+               process_message(connection, secdata->message,
                                secdata->method, secdata->iface_user_data);
 
                dbus_message_unref(secdata->message);
@@ -312,6 +269,46 @@ void g_dbus_pending_error(DBusConnection *connection,
        va_end(args);
 }
 
+int polkit_check_authorization(DBusConnection *conn,
+                               const char *action, gboolean interaction,
+                               void (*function) (dbus_bool_t authorized,
+                                                       void *user_data),
+                                               void *user_data, int timeout);
+
+struct builtin_security_data {
+       DBusConnection *conn;
+       GDBusPendingReply pending;
+};
+
+static void builtin_security_result(dbus_bool_t authorized, void *user_data)
+{
+       struct builtin_security_data *data = user_data;
+
+       if (authorized == TRUE)
+               g_dbus_pending_success(data->conn, data->pending);
+       else
+               g_dbus_pending_error(data->conn, data->pending,
+                                               DBUS_ERROR_AUTH_FAILED, NULL);
+
+       g_free(data);
+}
+
+static void builtin_security_function(DBusConnection *conn,
+                                               const char *action,
+                                               gboolean interaction,
+                                               GDBusPendingReply pending)
+{
+       struct builtin_security_data *data;
+
+       data = g_new0(struct builtin_security_data, 1);
+       data->conn = conn;
+       data->pending = pending;
+
+       if (polkit_check_authorization(conn, action, interaction,
+                               builtin_security_result, data, 30000) < 0)
+               g_dbus_pending_error(conn, pending, NULL, NULL);
+}
+
 static gboolean check_privilege(DBusConnection *conn, DBusMessage *msg,
                        const GDBusMethodTable *method, void *iface_user_data)
 {
@@ -338,9 +335,13 @@ static gboolean check_privilege(DBusConnection *conn, DBusMessage *msg,
                else
                        interaction = FALSE;
 
-               if (security->function)
+               if (!(security->flags & G_DBUS_SECURITY_FLAG_BUILTIN) &&
+                                                       security->function)
                        security->function(conn, security->action,
                                                interaction, secdata->pending);
+               else
+                       builtin_security_function(conn, security->action,
+                                               interaction, secdata->pending);
 
                return TRUE;
        }
@@ -361,7 +362,7 @@ static struct interface_data *find_interface(GSList *interfaces,
 {
        GSList *list;
 
-       if (!name)
+       if (name == NULL)
                return NULL;
 
        for (list = interfaces; list; list = list->next) {
@@ -384,7 +385,7 @@ static DBusHandlerResult generic_message(DBusConnection *connection,
        interface = dbus_message_get_interface(message);
 
        iface = find_interface(data->interfaces, interface);
-       if (!iface)
+       if (iface == NULL)
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
        for (method = iface->methods; method &&
@@ -420,7 +421,7 @@ static void invalidate_parent_data(DBusConnection *conn, const char *child_path)
 
        parent_path = g_strdup(child_path);
        slash = strrchr(parent_path, '/');
-       if (!slash)
+       if (slash == NULL)
                goto done;
 
        if (slash == parent_path && parent_path[1] != '\0')
@@ -431,13 +432,14 @@ static void invalidate_parent_data(DBusConnection *conn, const char *child_path)
        if (!strlen(parent_path))
                goto done;
 
-       if (!dbus_connection_get_object_path_data(conn, parent_path,
-                                                       (void *) &data)) {
-               invalidate_parent_data(conn, parent_path);
+       if (dbus_connection_get_object_path_data(conn, parent_path,
+                                                       (void *) &data) == FALSE) {
                goto done;
        }
 
-       if (!data)
+       invalidate_parent_data(conn, parent_path);
+
+       if (data == NULL)
                goto done;
 
        g_free(data->introspect);
@@ -447,8 +449,9 @@ done:
        g_free(parent_path);
 }
 
-static GDBusMethodTable introspect_methods[] = {
-       { "Introspect", "",     "s", introspect },
+static const GDBusMethodTable introspect_methods[] = {
+       { _GDBUS_METHOD("Introspect", "", "s", NULL,
+                       GDBUS_ARGS({ "xml", "s" }), introspect) },
        { }
 };
 
@@ -510,7 +513,7 @@ static gboolean remove_interface(struct generic_data *data, const char *name)
        struct interface_data *iface;
 
        iface = find_interface(data->interfaces, name);
-       if (!iface)
+       if (iface == NULL)
                return FALSE;
 
        data->interfaces = g_slist_remove(data->interfaces, iface);
@@ -557,14 +560,14 @@ static gboolean check_signal(DBusConnection *conn, const char *path,
 
        *args = NULL;
        if (!dbus_connection_get_object_path_data(conn, path,
-                                       (void *) &data) || !data) {
+                                       (void *) &data) || data == NULL) {
                error("dbus_connection_emit_signal: path %s isn't registered",
                                path);
                return FALSE;
        }
 
        iface = find_interface(data->interfaces, interface);
-       if (!iface) {
+       if (iface == NULL) {
                error("dbus_connection_emit_signal: %s does not implement %s",
                                path, interface);
                return FALSE;
@@ -577,7 +580,7 @@ static gboolean check_signal(DBusConnection *conn, const char *path,
                }
        }
 
-       if (!*args) {
+       if (*args == NULL) {
                error("No signal named %s on interface %s", name, interface);
                return FALSE;
        }
@@ -600,7 +603,7 @@ static dbus_bool_t emit_signal_valist(DBusConnection *conn,
                return FALSE;
 
        signal = dbus_message_new_signal(path, interface, name);
-       if (!signal) {
+       if (signal == NULL) {
                error("Unable to allocate new %s.%s signal", interface,  name);
                return FALSE;
        }
@@ -658,7 +661,7 @@ gboolean g_dbus_unregister_interface(DBusConnection *connection,
 {
        struct generic_data *data = NULL;
 
-       if (!path)
+       if (path == NULL)
                return FALSE;
 
        if (dbus_connection_get_object_path_data(connection, path,