Index: /luci2/cbi2/sources/uci.c
===================================================================
--- /luci2/cbi2/sources/uci.c	(revision 5694)
+++ /luci2/cbi2/sources/uci.c	(revision 5696)
@@ -201,10 +201,15 @@
 	if(p->package && p->type && p->option)
 		p->uvl = validate_get_option(ctx, p->package, p->type, p->option);
-	else
-		printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
-
 	if(!p->uvl)
 		CBILOG(e, "failed to load uvl mapping to %s.@%s.%s\n", p->package, p->type, p->option);
 	return 0;
+}
+
+json_object* uci_src_json(struct cbi_ctx *ctx, struct cbi_element *e)
+{
+	json_object *j = json_object_new_object();
+	const char *id = cbi_find_prop(e, "id");
+	json_object_object_add(j, "id", json_object_new_string(id));
+	return j;
 }
 
@@ -223,4 +228,5 @@
 	.caps = SRC_PACKAGE | SCAP_READ | SCAP_READ,
 	.init = uci_src_init,
+	.json = uci_src_json,
 };
 
Index: /luci2/cbi2/cbi.h
===================================================================
--- /luci2/cbi2/cbi.h	(revision 5695)
+++ /luci2/cbi2/cbi.h	(revision 5696)
@@ -3,4 +3,5 @@
 
 #include <string.h>
+#include <json.h>
 #include "list.h"
 #include "uvl.h"
@@ -26,4 +27,5 @@
 	struct list_head pages;
 	struct list_head menus;
+	struct list_head elements;
 	struct list_head sock_handlers;
 	struct uvl_context *uvl;
@@ -58,4 +60,5 @@
 	uint64_t caps;
 	int (*init)(struct cbi_ctx *ctx, struct cbi_element *e);
+	json_object* (*json)(struct cbi_ctx *ctx, struct cbi_element *e);
 };
 
@@ -88,4 +91,5 @@
 	int prop_count;
 	int (*init)(struct cbi_ctx *ctx, struct cbi_element *e);
+	json_object* (*json)(struct cbi_ctx *ctx, struct cbi_element *e);
 };
 
@@ -121,5 +125,5 @@
 {
 	struct list_head list;
-	struct cbi_element e;
+	struct cbi_element *e;
 
 	char *name;
@@ -140,4 +144,5 @@
 const char* cbi_virt_path(struct cbi_ctx *ctx, const char *path, const char *file);
 void cbi_create_instance(struct cbi_ctx *ctx, struct cbi_element *e1, struct cbi_element *e2);
+struct cbi_element* cbi_resolv(struct cbi_ctx *ctx, const char *ref);
 
 void cbi_widget_register(char *name, struct cbi_widget *w);
Index: /luci2/cbi2/widget.c
===================================================================
--- /luci2/cbi2/widget.c	(revision 5692)
+++ /luci2/cbi2/widget.c	(revision 5696)
@@ -55,53 +55,4 @@
 }
 
-static struct cbi_element* cbi_get_root(struct cbi_element *e)
-{
-	if(e->parent)
-		return cbi_get_root(e->parent);
-	return e;
-}
-
-struct cbi_element* cbi_find_element(struct cbi_element *e, const char *id);
-static struct cbi_element* cbi_resolv_element(struct cbi_element *e, char *ref)
-{
-	char *tok;
-	struct cbi_element *next;
-	tok = strstr(ref, ".");
-	if(!tok)
-		return e;
-	*tok = '\0';
-	tok++;
-	next = cbi_find_element(e, tok);
-	if(next)
-		return cbi_resolv_element(next, tok);
-	return 0;
-}
-
-struct cbi_file* cbi_find_file(struct cbi_ctx *ctx, const char *name);
-struct cbi_element* cbi_resolv(struct cbi_ctx *ctx, struct cbi_element *e, const char *ref)
-{
-	struct cbi_element *root = 0, *ret = 0;
-	char *buf = strdup(ref);
-	char *t;
-	if((t = strstr(buf, ":")))
-	{
-		struct cbi_file *f;
-		*t = '\0';
-		f = cbi_find_file(ctx, buf);
-		if(!f)
-			goto out;
-		root = &f->e;
-		t++;
-		ret = cbi_resolv_element(root, t);
-	} else if(e)
-	{
-		root = cbi_get_root(e);
-		ret = cbi_resolv_element(root, buf);
-	}
-out:
-	free(buf);
-	return ret;
-}
-
 static int widget_abstract(struct cbi_ctx *ctx, struct cbi_element *e)
 {
@@ -110,5 +61,5 @@
 	if(!ref)
 		return 0;
-	r = cbi_resolv(ctx, e, ref);
+	r = cbi_resolv(ctx, ref);
 	if(!r)
 	{
Index: /luci2/cbi2/luci.c
===================================================================
--- /luci2/cbi2/luci.c	(revision 5686)
+++ /luci2/cbi2/luci.c	(revision 5696)
@@ -21,4 +21,5 @@
 #include "lang.h"
 #include "uci.h"
+#include "json.h"
 
 static int loop = 1;
@@ -170,4 +171,11 @@
 		u_sock_register_handler(ctx, "json", cbi_request);
 	}
+	{
+		json_object *j = json_req_node(ctx, "network.internet");
+		if(j)
+			printf("res -> %s\n", json_object_to_json_string(j));
+		else
+			printf("error creating json\n");
+	}
 	while(loop)
 	{
Index: /luci2/cbi2/json.c
===================================================================
--- /luci2/cbi2/json.c	(revision 5684)
+++ /luci2/cbi2/json.c	(revision 5696)
@@ -3,4 +3,44 @@
 #include "cbi.h"
 #include "session.h"
+
+static json_object* json_req_element(struct cbi_ctx *ctx, struct cbi_element *e)
+{
+	struct list_head *p;
+	json_object *j = 0;
+	if(e->broken)
+		return 0;
+	if((CAPS(e) & CAP_DATA) && (e->source))
+		if(e->source->json)
+			j =  e->source->json(ctx, e);
+	if(!j && e->w->json)
+		j = e->w->json(ctx, e);
+	if(!j)
+	{
+		CBILOG(e, "no json handler found\n");
+		e->broken = 1;
+		return 0;
+	}
+	if(!list_empty(&e->elements))
+	{
+		json_object *array = json_object_new_array();
+		list_for_each(p, &e->elements)
+		{
+			struct cbi_element *e2 = container_of(p, struct cbi_element, list);
+			json_object *j2 = json_req_element(ctx, e2);
+			if(j2)
+				json_object_array_add(array, j2);
+		}
+		json_object_object_add(j, "elements", array);
+	}
+	return j;
+}
+
+json_object* json_req_node(struct cbi_ctx *ctx, const char *node)
+{
+	struct cbi_element *e = cbi_resolv(ctx, node);
+	if(!e)
+		return 0;
+	return json_req_element(ctx, e);
+}
 
 json_object* json_req_auth(struct cbi_ctx *ctx, json_object *in)
Index: /luci2/cbi2/json.h
===================================================================
--- /luci2/cbi2/json.h	(revision 5682)
+++ /luci2/cbi2/json.h	(revision 5696)
@@ -6,4 +6,5 @@
 
 json_object* json_request(struct cbi_ctx *ctx, json_object *in);
+json_object* json_req_node(struct cbi_ctx *ctx, const char *node);
 
 #endif
Index: /luci2/cbi2/config/dhcp
===================================================================
--- /luci2/cbi2/config/dhcp	(revision 5696)
+++ /luci2/cbi2/config/dhcp	(revision 5696)
@@ -0,0 +1,3 @@
+config dhcp dhcp
+
+config leases l1
Index: /luci2/cbi2/cbi.c
===================================================================
--- /luci2/cbi2/cbi.c	(revision 5695)
+++ /luci2/cbi2/cbi.c	(revision 5696)
@@ -53,4 +53,5 @@
 	INIT_LIST_HEAD(&ctx->globals);
 	INIT_LIST_HEAD(&ctx->menus);
+	INIT_LIST_HEAD(&ctx->elements);
 
 	return ctx;
@@ -277,7 +278,14 @@
 void cbi_create_instance(struct cbi_ctx *ctx, struct cbi_element *e1, struct cbi_element *e2)
 {
-	struct blob_attr *element = (struct blob_attr*)e2->blob->blob;
-	int rem = e2->blob->rem;
+	struct blob_attr *element;
+	int rem;
 	int sub_count = 0;
+	if(!e2->blob)
+	{
+		CBILOG(e2, "failed to create instance\n");
+		return;
+	}
+	element = (struct blob_attr*)e2->blob->blob;
+	rem = e2->blob->rem;
 	for(;
 		(blob_pad_len(element) <= rem) && (blob_pad_len(element) >= sizeof(struct blob_attr));
@@ -316,4 +324,41 @@
 }
 
+static struct cbi_element* cbi_resolv_element(struct cbi_element *e, char *ref)
+{
+	char *tok;
+	struct cbi_element *next;
+	tok = strstr(ref, ".");
+	if(!tok)
+	{
+		const char *id = cbi_find_prop(e, "id");
+		if(!strcmp(id, ref))
+			return e;
+		else
+			return 0;
+	}
+	*tok = '\0';
+	tok++;
+	next = cbi_find_element(e, tok);
+	if(next)
+		return cbi_resolv_element(next, tok);
+	return 0;
+}
+
+struct cbi_element* cbi_resolv(struct cbi_ctx *ctx, const char *ref)
+{
+	struct cbi_element *ret = 0;
+	struct list_head *p;
+	list_for_each(p, &ctx->elements)
+	{
+		struct cbi_element *e2 = container_of(p, struct cbi_element, list);
+		char *buf = strdup(ref);
+		ret = cbi_resolv_element(e2, buf);
+		free(buf);
+		if(ret)
+			break;
+	}
+	return ret;
+}
+
 void cbi_index_verify(struct cbi_ctx *ctx, struct cbi_element *e)
 {
@@ -335,5 +380,5 @@
 	struct list_head *p;
 	LOG("indexing %s\n", f->name);
-	list_for_each(p, &f->e.elements)
+	list_for_each(p, &f->e->elements)
 	{
 		struct cbi_element *e = container_of(p, struct cbi_element, list);
@@ -362,5 +407,5 @@
 	struct list_head *p;
 	LOG("unindexing %s\n", f->name);
-	list_for_each(p, &f->e.elements)
+	list_for_each(p, &f->e->elements)
 	{
 		struct cbi_element *e = container_of(p, struct cbi_element, list);
@@ -403,5 +448,5 @@
 	cbi_index_remove(file);
 	LOG("dropping %s\n", file->name);
-	list_for_each_safe(p, q, &file->e.elements)
+	list_for_each_safe(p, q, &file->e->elements)
 	{
 		struct cbi_element *e = container_of(p, struct cbi_element, list);
@@ -411,4 +456,5 @@
 	free(file->file);
 	list_del(&file->list);
+	list_del(&file->e->list);
 	free(file);
 }
@@ -476,10 +522,12 @@
 	f->name[strlen(f->name) - 5] = '\0';
 	f->mtime = st.st_mtime;
-	memset(&f->e, 0, sizeof(struct cbi_element));
-	INIT_LIST_HEAD(&f->e.elements);
-	INIT_LIST_HEAD(&f->e.properties);
-	f->e.widget = strdup("file");
-	f->e.w = cbi_widget_find("file");
-	cbi_add_property(&f->e, "src", f->name, 1);
+	f->e = malloc(sizeof(struct cbi_element));
+	memset(f->e, 0, sizeof(struct cbi_element));
+	INIT_LIST_HEAD(&f->e->elements);
+	INIT_LIST_HEAD(&f->e->properties);
+	f->e->namespace = strdup("luci");
+	f->e->widget = strdup("file");
+	f->e->w = cbi_widget_find("file");
+	cbi_add_property(f->e, "src", f->name, 1);
 	blob_for_each_attr(pos, map, rem)
 	{
@@ -487,8 +535,9 @@
 		if(blob_id(pos) != CBI_ELEMENT)
 			continue;
-		e = cbi_parse_element(ctx, pos, &count, &f->e);
+		e = cbi_parse_element(ctx, pos, &count, 0);
 		if(e)
-			list_add_tail(&e->list, &f->e.elements);
-	}
+			list_add_tail(&e->list, &f->e->elements);
+	}
+	list_add_tail(&f->e->list, &ctx->elements);
 	list_add_tail(&f->list, &ctx->files);
 	if(index)
@@ -557,14 +606,10 @@
 void cbi_dump(struct cbi_ctx *ctx)
 {
-	struct list_head *p, *q;
-
-	list_for_each(p, &ctx->files)
-	{
-		struct cbi_file *f = container_of(p, struct cbi_file, list);
-		list_for_each(q, &f->e.elements)
-		{
-			struct cbi_element *e = container_of(q, struct cbi_element, list);
-			cbi_dump_element(e, 0);
-		}
+	struct list_head *p;
+
+	list_for_each(p, &ctx->elements)
+	{
+		struct cbi_element *e = container_of(p, struct cbi_element, list);
+		cbi_dump_element(e, 0);
 	}
 }
