/*
 * wpa_supplicant - D-Bus introspection
 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
 * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
 * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "utils/includes.h"

#include "utils/common.h"
#include "utils/list.h"
#include "utils/wpabuf.h"
#include "dbus_common_i.h"
#include "dbus_new_helpers.h"


struct interfaces {
	struct dl_list list;
	char *dbus_interface;
	struct wpabuf *xml;
};


static struct interfaces * add_interface(struct dl_list *list,
					 const char *dbus_interface)
{
	struct interfaces *iface;

	dl_list_for_each(iface, list, struct interfaces, list) {
		if (os_strcmp(iface->dbus_interface, dbus_interface) == 0)
			return iface; /* already in the list */
	}

	iface = os_zalloc(sizeof(struct interfaces));
	if (!iface)
		return NULL;
	iface->dbus_interface = os_strdup(dbus_interface);
	iface->xml = wpabuf_alloc(6000);
	if (iface->dbus_interface == NULL || iface->xml == NULL) {
		os_free(iface->dbus_interface);
		wpabuf_free(iface->xml);
		os_free(iface);
		return NULL;
	}
	wpabuf_printf(iface->xml, "<interface name=\"%s\">", dbus_interface);
	dl_list_add_tail(list, &iface->list);
	return iface;
}


static void add_arg(struct wpabuf *xml, const char *name, const char *type,
		    const char *direction)
{
	wpabuf_printf(xml, "<arg name=\"%s\"", name);
	if (type)
		wpabuf_printf(xml, " type=\"%s\"", type);
	if (direction)
		wpabuf_printf(xml, " direction=\"%s\"", direction);
	wpabuf_put_str(xml, "/>");
}


static void add_entry(struct wpabuf *xml, const char *type, const char *name,
		      const struct wpa_dbus_argument *args, int include_dir)
{
	const struct wpa_dbus_argument *arg;

	if (args == NULL || args->name == NULL) {
		wpabuf_printf(xml, "<%s name=\"%s\"/>", type, name);
		return;
	}
	wpabuf_printf(xml, "<%s name=\"%s\">", type, name);
	for (arg = args; arg && arg->name; arg++) {
		add_arg(xml, arg->name, arg->type,
			include_dir ? (arg->dir == ARG_IN ? "in" : "out") :
			NULL);
	}
	wpabuf_printf(xml, "</%s>", type);
}


static void add_property(struct wpabuf *xml,
			 const struct wpa_dbus_property_desc *dsc)
{
	wpabuf_printf(xml, "<property name=\"%s\" type=\"%s\" "
		      "access=\"%s%s\"/>",
		      dsc->dbus_property, dsc->type,
		      dsc->getter ? "read" : "",
		      dsc->setter ? "write" : "");
}


static void extract_interfaces_methods(
	struct dl_list *list, const struct wpa_dbus_method_desc *methods)
{
	const struct wpa_dbus_method_desc *dsc;
	struct interfaces *iface;

	for (dsc = methods; dsc && dsc->dbus_method; dsc++) {
		iface = add_interface(list, dsc->dbus_interface);
		if (iface)
			add_entry(iface->xml, "method", dsc->dbus_method,
				  dsc->args, 1);
	}
}


static void extract_interfaces_signals(
	struct dl_list *list, const struct wpa_dbus_signal_desc *signals)
{
	const struct wpa_dbus_signal_desc *dsc;
	struct interfaces *iface;

	for (dsc = signals; dsc && dsc->dbus_signal; dsc++) {
		iface = add_interface(list, dsc->dbus_interface);
		if (iface)
			add_entry(iface->xml, "signal", dsc->dbus_signal,
				  dsc->args, 0);
	}
}


static void extract_interfaces_properties(
	struct dl_list *list, const struct wpa_dbus_property_desc *properties)
{
	const struct wpa_dbus_property_desc *dsc;
	struct interfaces *iface;

	for (dsc = properties; dsc && dsc->dbus_property; dsc++) {
		iface = add_interface(list, dsc->dbus_interface);
		if (iface)
			add_property(iface->xml, dsc);
	}
}


/**
 * extract_interfaces - Extract interfaces from methods, signals and props
 * @list: Interface list to be filled
 * @obj_dsc: Description of object from which interfaces will be extracted
 *
 * Iterates over all methods, signals, and properties registered with an
 * object and collects all declared DBus interfaces and create interfaces'
 * node in XML root node for each. Returned list elements contain interface
 * name and XML node of corresponding interface.
 */
static void extract_interfaces(struct dl_list *list,
			       struct wpa_dbus_object_desc *obj_dsc)
{
	extract_interfaces_methods(list, obj_dsc->methods);
	extract_interfaces_signals(list, obj_dsc->signals);
	extract_interfaces_properties(list, obj_dsc->properties);
}


static void add_interfaces(struct dl_list *list, struct wpabuf *xml)
{
	struct interfaces *iface, *n;

	dl_list_for_each_safe(iface, n, list, struct interfaces, list) {
		if (wpabuf_len(iface->xml) + 20 < wpabuf_tailroom(xml)) {
			wpabuf_put_buf(xml, iface->xml);
			wpabuf_put_str(xml, "</interface>");
		} else {
			wpa_printf(MSG_DEBUG,
				   "dbus: Not enough room for add_interfaces inspect data: tailroom %u, add %u",
				   (unsigned int) wpabuf_tailroom(xml),
				   (unsigned int) wpabuf_len(iface->xml));
		}
		dl_list_del(&iface->list);
		wpabuf_free(iface->xml);
		os_free(iface->dbus_interface);
		os_free(iface);
	}
}


static void add_child_nodes(struct wpabuf *xml, DBusConnection *con,
			    const char *path)
{
	char **children;
	int i;

	/* add child nodes to introspection tree */
	dbus_connection_list_registered(con, path, &children);
	for (i = 0; children[i]; i++)
		wpabuf_printf(xml, "<node name=\"%s\"/>", children[i]);
	dbus_free_string_array(children);
}


static void add_introspectable_interface(struct wpabuf *xml)
{
	wpabuf_printf(xml, "<interface name=\"%s\">"
		      "<method name=\"%s\">"
		      "<arg name=\"data\" type=\"s\" direction=\"out\"/>"
		      "</method>"
		      "</interface>",
		      WPA_DBUS_INTROSPECTION_INTERFACE,
		      WPA_DBUS_INTROSPECTION_METHOD);
}


static void add_properties_interface(struct wpabuf *xml)
{
	wpabuf_printf(xml, "<interface name=\"%s\">",
		      WPA_DBUS_PROPERTIES_INTERFACE);

	wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GET);
	add_arg(xml, "interface", "s", "in");
	add_arg(xml, "propname", "s", "in");
	add_arg(xml, "value", "v", "out");
	wpabuf_put_str(xml, "</method>");

	wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_GETALL);
	add_arg(xml, "interface", "s", "in");
	add_arg(xml, "props", "a{sv}", "out");
	wpabuf_put_str(xml, "</method>");

	wpabuf_printf(xml, "<method name=\"%s\">", WPA_DBUS_PROPERTIES_SET);
	add_arg(xml, "interface", "s", "in");
	add_arg(xml, "propname", "s", "in");
	add_arg(xml, "value", "v", "in");
	wpabuf_put_str(xml, "</method>");

	wpabuf_put_str(xml, "</interface>");
}


static void add_wpas_interfaces(struct wpabuf *xml,
				struct wpa_dbus_object_desc *obj_dsc)
{
	struct dl_list ifaces;

	dl_list_init(&ifaces);
	extract_interfaces(&ifaces, obj_dsc);
	add_interfaces(&ifaces, xml);
}


/**
 * wpa_dbus_introspect - Responds for Introspect calls on object
 * @message: Message with Introspect call
 * @obj_dsc: Object description on which Introspect was called
 * Returns: Message with introspection result XML string as only argument
 *
 * Iterates over all methods, signals and properties registered with
 * object and generates introspection data for the object as XML string.
 */
DBusMessage * wpa_dbus_introspect(DBusMessage *message,
				  struct wpa_dbus_object_desc *obj_dsc)
{

	DBusMessage *reply;
	struct wpabuf *xml;

	xml = wpabuf_alloc(10000);
	if (xml == NULL)
		return NULL;

	wpabuf_put_str(xml, "<?xml version=\"1.0\"?>\n");
	wpabuf_put_str(xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE);
	wpabuf_put_str(xml, "<node>");

	add_introspectable_interface(xml);
	add_properties_interface(xml);
	add_wpas_interfaces(xml, obj_dsc);
	add_child_nodes(xml, obj_dsc->connection,
			dbus_message_get_path(message));

	wpabuf_put_str(xml, "</node>\n");

	reply = dbus_message_new_method_return(message);
	if (reply) {
		const char *intro_str = wpabuf_head(xml);

		dbus_message_append_args(reply, DBUS_TYPE_STRING, &intro_str,
					 DBUS_TYPE_INVALID);
	}
	wpabuf_free(xml);

	return reply;
}
