Index: protocols/rpc/rpc.c
===================================================================
--- protocols/rpc/rpc.c	(revision 16652e9ee983310dfe4beb4278ddbf0b85e78a71)
+++ protocols/rpc/rpc.c	(revision f3af614c28f7eefb0cba6a41c74339a92ed96f5f)
@@ -128,4 +128,19 @@
 }
 
+static JSON_Value *rpc_ser_bee_user(bee_user_t *bu) {
+	JSON_Value *v = json_value_init_object();
+	JSON_Object *o = json_object(v);
+	json_object_set_string_or_null(o, "handle", bu->handle);
+	json_object_set_string_or_null(o, "fullname", bu->fullname);
+	json_object_set_string_or_null(o, "nick", bu->nick);
+	json_object_set_string_or_null(o, "group", bu->group ? bu->group->name : NULL);
+	json_object_set_number(o, "flags", bu->flags);
+	json_object_set_string_or_null(o, "status", bu->status);
+	json_object_set_string_or_null(o, "status_msg", bu->status_msg);
+	json_object_set_number(o, "login_time", bu->login_time);
+	json_object_set_number(o, "idle_time", bu->idle_time);
+	return v;
+}
+
 static void rpc_init(account_t *acc) {
 	struct rpc_plugin *pd = acc->prpl->data;
@@ -134,4 +149,24 @@
 		JSON_Object *o = json_object(value);
 		set_t *set = set_add(&acc->set, name, json_object_get_string(o, "default"), NULL, acc);
+		/* JSON numbers are floats. The following line "might" be a
+		 * terrible idea. As was JSON, but hey. */
+		set->flags |= (int) json_object_get_number(o, "flags");
+		const char *eval = json_object_get_string(o, "type");
+		if (eval == NULL) {
+		} else if (strcmp(eval, "int") == 0) {
+			set->eval = set_eval_int;
+		} else if (strcmp(eval, "bool") == 0) {
+			set->eval = set_eval_bool;
+		} else {
+			/* Default is string which means no evaluator. */
+		}
+		/* eval_list turns out to be a memory leak so don't implement it
+		 * for now.
+		 * Allowing a plugin to define its own evaluator is not really
+		 * possible without having BitlBee block on it responding which
+		 * I don't want to do.
+		 * Should a module want to override a user's setting, it can
+		 * use set_setstr(). (Though ATM setting changes are not yet
+		 * passed to the module immediately. TODO. */
 	}
 }
@@ -542,4 +577,37 @@
 }
 
+static JSON_Value *rpc_set_getstr(struct im_connection *ic, void *func_, JSON_Array *params) {
+	char *rets = set_getstr(&ic->acc->set, json_array_get_string(params, 0));
+	JSON_Value *ret = json_value_init_object();
+	if (rets)
+		json_object_set_string(json_object(ret), "result", rets);
+	else
+		json_object_set_null(json_object(ret), "result");
+	return ret;
+}
+
+static JSON_Value *rpc_set_setstr(struct im_connection *ic, void *func_, JSON_Array *params) {
+	/* Sadly use of const is very poor in BitlBee. :-( */
+	char *newval = g_strdup(json_array_get_string(params, 1));
+	set_setstr(&ic->acc->set, json_array_get_string(params, 0), newval);
+	g_free(newval);
+	return rpc_set_getstr(ic, func_, params);
+}
+
+static JSON_Value *rpc_set_reset(struct im_connection *ic, void *func_, JSON_Array *params) {
+	set_reset(&ic->acc->set, json_array_get_string(params, 0));
+	return rpc_set_getstr(ic, func_, params);
+}
+
+static JSON_Value *rpc_bee_user_by_handle(struct im_connection *ic, void *func_, JSON_Array *params) {
+	bee_user_t *bu = bee_user_by_handle(ic->bee, ic, json_array_get_string(params, 0));
+	JSON_Value *ret = json_value_init_object();
+	if (bu)
+		json_object_set_value(json_object(ret), "result", rpc_ser_bee_user(bu));
+	else
+		json_object_set_value(json_object(ret), "error", jsonrpc_error(ENOENT, "Contact not found"));
+	return ret;
+}
+
 struct rpc_in_method {
 	char *name;
@@ -551,5 +619,5 @@
 static const struct rpc_in_method methods[] = {
 	/* All these RPCs are equivalent of BitlBee C functions but with the
-	 * struct im_connection* removed. */
+	 * struct im_connection* removed as this is in the object context. */
 	{ "imcb_log", imcb_log, rpc_imcb_log, "s" },
 	{ "imcb_error", imcb_error, rpc_imcb_log, "s" },
@@ -576,4 +644,14 @@
 	{ "imcb_chat_remove_buddy", imcb_chat_remove_buddy, rpc_imcb_chat_remove_buddy, "nss" },
 	{ "imcb_chat_invite", imcb_chat_invite, rpc_imcb_chat_invite, "nsss" },
+
+	/* These are not imcb* functions but should still be exported. */
+	/* Setting functions. Starting with just providing access to account
+	 * settings. See later whether access to chat/chan settings is necessary.
+	 * All of these will return the (new) value of given setting. */
+	{ "set_getstr", NULL, rpc_set_getstr, "s" },
+	{ "set_setstr", NULL, rpc_set_setstr, "ss" },
+	{ "set_reset", NULL, rpc_set_reset, "s" },
+	
+	{ "bee_user_by_handle", NULL, rpc_bee_user_by_handle, "s" },
 
 	{ NULL },
@@ -710,5 +788,5 @@
 	struct prpl *ret = g_new0(struct prpl, 1);
 	
-	JSON_Array *methods_a = json_object_get_array(isup, "methods");
+	JSON_Array *methods_a = json_object_get_array(isup, "method_list");
 	GHashTable *methods = g_hash_table_new(g_str_hash, g_str_equal);
 	for (i = 0; i < json_array_get_count(methods_a); i++)
Index: python/implugin.py
===================================================================
--- python/implugin.py	(revision f3af614c28f7eefb0cba6a41c74339a92ed96f5f)
+++ python/implugin.py	(revision f3af614c28f7eefb0cba6a41c74339a92ed96f5f)
@@ -0,0 +1,103 @@
+#!/usr/bin/python
+
+import sys
+import bjsonrpc
+from bjsonrpc.handlers import BaseHandler
+
+import random
+import re
+import socket
+import time
+
+# List of functions an IM plugin can export. This library will indicate to
+# BitlBee which functions are actually implemented so omitted features
+# will be disabled, but note that some/many functions are simply mandatory.
+SUPPORTED_FUNCTIONS = [
+	'login', 'keepalive', 'logout', 'buddy_msg', 'set_away',
+	'send_typing', 'add_buddy', 'remove_buddy', 'add_permit',
+	'add_deny', 'rem_permit', 'rem_deny', 'get_info', 'chat_invite',
+	'chat_kick', 'chat_leave', 'chat_msg', 'chat_with', 'chat_join',
+	'chat_topic'
+]
+
+class RpcForwarder(object):
+	"""Tiny object that forwards RPCs from local Python code to BitlBee
+	with a marginally nicer syntax. This layer could eventually be
+	used to add basic parameter checking though I don't think that should
+	be done here."""
+	
+	def __init__(self, methods, target):
+		for m in methods:
+			# imc(b)_ prefix is not useful here, chop it.
+			# (Maybe do this in BitlBee already as well.)
+			newname = re.sub("^imcb?_", "", m)
+			self.__setattr__(newname, target.__getattr__(m))
+
+class BitlBeeIMPlugin(BaseHandler):
+	NAME = "rpc-test"
+	
+	# Filled in during initialisation:
+	# Version code in hex. So if you need to do comparisions, for example
+	# check "self.bitlbee_version >= 0x030202" for versions 3.2.2+
+	bitlbee_version = None
+	# Full version string
+	bitlbee_version_str = None
+	
+	@classmethod
+	def _factory(cls, *args, **kwargs):
+		def handler_factory(connection):
+			handler = cls(connection, *args, **kwargs)
+			return handler
+		return handler_factory
+	
+	#def __init__(self, connection, *args, **kwargs):
+	#	BaseHandler.__init__(self,connection)
+
+	def init(self, bee):
+		self.bee = RpcForwarder(bee["method_list"], self._conn.call)
+		self.bitlbee_version = bee["version"]
+		self.bitlbee_version_str = bee["version_str"]
+		# TODO: See how to call into the module here.
+		return {
+			"name": self.NAME,
+			"method_list": list(set(dir(self)) & set(SUPPORTED_FUNCTIONS)),
+			"settings": {
+				"oauth": {
+					"default": "off",
+				},
+				"test": {
+					"default": "123",
+				},
+			},
+		}
+	
+	def login(self, account):
+		print "Logging in with username %s and password %s" % (account['user'], account['pass'])
+		self.bee.log("Blaataap %r" % account)
+		self.bee.error("HALP!")
+		self.bee.connected()
+		return [{1:2,3:4}, {"a":"A", "b":"B"}, 1, 2, True]
+
+	def logout(self):
+		self.bee.error("Ok bye!")
+
+	def add_buddy(self, handle, group):
+		print "%s is my new best friend in %s \o/" % (handle, group)
+		self.bee.add_buddy(handle, group)
+		self.bee.buddy_status(handle, 5, "Friend", "Best friend!")
+		print self.bee.bee_user_by_handle(handle)
+		print self.bee.set_setstr("test", handle)
+		print self.bee.set_reset("test")
+
+def RunPlugin(plugin, debug=True):
+	sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+	sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+	sock.bind("/tmp/rpcplugins/test2")
+	sock.listen(3)
+	
+	srv = bjsonrpc.server.Server(sock, plugin._factory())
+	
+	srv.debug_socket(debug)
+	srv.serve()
+
+RunPlugin(BitlBeeIMPlugin)
