+++ /dev/null
-/* citadel.c
- * Gaim Citadel plugin.
- *
- * © 2006 David Given.
- * This code is licensed under the GPL v3. See the file COPYING in this
- * directory for the full license text.
- *
- * $Id:citadel.c 4326 2006-02-18 12:26:22Z hjalfi $
- */
-
-#define GAIM_PLUGINS
-#include "internal.h"
-#include "accountopt.h"
-#include "blist.h"
-#include "conversation.h"
-#include "debug.h"
-#include "notify.h"
-#include "prpl.h"
-#include "plugin.h"
-#include "util.h"
-#include "version.h"
-#include "sslconn.h"
-
-#include "lua.h"
-#include "lualib.h"
-#include "lauxlib.h"
-
-#include "interface.h"
-
-extern int tolua_gaim_open(lua_State* L);
-extern void tolua_gaim_close(lua_State* L);
-
-#define VERSION "0.2"
-#define CITADEL_DEFAULT_SERVER "uncensored.citadel.org"
-#define CITADEL_DEFAULT_PORT 504
-#define CITADEL_POLL_INTERVAL 60
-#define LUA_MICROCODE "/plugindata/citadel.lua"
-
-struct citadel {
- GaimAccount* ga;
- GaimConnection* gc;
- GaimSslConnection* gsc;
- int fd;
- lua_State* L;
-};
-
-static GaimConnection* hackgc;
-
-/* ======================================================================= */
-/* LUA CALLIN */
-/* ======================================================================= */
-
-static void wrappedcall(lua_State* L, int inparams, int outparams)
-{
- int i;
-
- i = lua_pcall(L, inparams, outparams, 0);
- if (i)
- {
- gaim_debug(GAIM_DEBUG_MISC, "citadel", "lua error: %s\n",
- lua_tostring(L, -1));
- gaim_connection_error(hackgc, _("Internal error in plugin"));
- return;
- }
-
- lua_getglobal(L, "citadel_schedule_now");
- i = lua_pcall(L, 0, 0, 0);
- if (i)
- {
- gaim_debug(GAIM_DEBUG_MISC, "citadel", "lua error in scheduler: %s\n",
- lua_tostring(L, -1));
- gaim_connection_error(hackgc, _("Internal error in plugin"));
- return;
- }
-}
-
-/* ======================================================================= */
-/* LUA CALLOUT */
-/* ======================================================================= */
-
-/* --- Input ------------------------------------------------------------- */
-
-static void input_cb(gpointer data, gint fd, GaimInputCondition cond)
-{
- GaimConnection* gc = data;
- lua_State* L = gc->proto_data;
-
- lua_getglobal(L, "citadel_input");
- wrappedcall(L, 0, 0);
-}
-
-static void input_ssl_cb(gpointer data, GaimSslConnection* gsc, GaimInputCondition cond)
-{
- GaimConnection* gc = data;
- lua_State* L = gc->proto_data;
-
- lua_getglobal(L, "citadel_input");
- wrappedcall(L, 0, 0);
-}
-
-char* interface_readdata(int fd, GaimSslConnection* gsc)
-{
- static char buffer[1024];
- int len;
-
- /* Read in some data. */
-
- if (gsc)
- len = gaim_ssl_read(gsc, buffer, sizeof(buffer)-1);
- else
- len = read(fd, buffer, sizeof(buffer)-1);
-
- if (len <= 0)
- return NULL;
-
- buffer[len] = '\0';
- return buffer;
-}
-
-int interface_writedata(int fd, GaimSslConnection* gsc, char* buffer)
-{
- int len = strlen(buffer);
- char* p = buffer;
-
- while (len > 0)
- {
- int i;
-
- if (gsc)
- i = gaim_ssl_write(gsc, p, len);
- else
- i = write(fd, p, len);
-
- if (i < 0)
- return 1;
-
- p += i;
- len -= i;
- }
-
- return 0;
-}
-
-/* --- Connection -------------------------------------------------------- */
-
-static void login_cb(gpointer data, gint fd, GaimInputCondition cond)
-{
- GaimConnection* gc = data;
- lua_State* L = gc->proto_data;
-
- if (fd < 0)
- {
- gaim_connection_error(gc, _("Couldn't connect to host"));
- return;
- }
-
- if (!g_list_find(gaim_connections_get_all(), gc))
- {
- close(fd);
- return;
- }
-
- /* Register the input event handler. */
-
- gc->inpa = gaim_input_add(fd, GAIM_INPUT_READ, input_cb, gc);
-
- /* Register this file descriptor and tell Lua. */
-
- lua_getglobal(L, "citadel_setfd");
- lua_pushnumber(L, fd);
- wrappedcall(L, 1, 0);
-}
-
-int interface_connect(GaimAccount* ga, GaimConnection* gc,
- char* server, int port)
-{
- return gaim_proxy_connect(ga, server, port, login_cb, gc);
-}
-
-void interface_disconnect(int fd, GaimSslConnection* gsc)
-{
- if (gsc)
- gaim_ssl_close(gsc);
- else if (fd >= 0)
- close(fd);
-}
-
-/* --- TLS setup --------------------------------------------------------- */
-
-static void ssl_setup_cb(gpointer data, GaimSslConnection* gsc,
- GaimInputCondition cond)
-{
- GaimConnection* gc = data;
- lua_State* L = gc->proto_data;
-
- if (!g_list_find(gaim_connections_get_all(), gc))
- {
- gaim_ssl_close(gsc);
- return;
- }
-
- gaim_debug(GAIM_DEBUG_MISC, "citadel", "using gsc %p\n", gsc);
- gaim_ssl_input_add(gsc, input_ssl_cb, gc);
-
- /* Register this file descriptor and tell Lua. */
-
- lua_getglobal(L, "citadel_setgsc");
- {
- GaimSslConnection** o = lua_newuserdata(L, sizeof(GaimSslConnection));
- *o = gsc;
- }
- wrappedcall(L, 1, 0);
-}
-
-static void ssl_failure_cb(GaimSslConnection *gsc, GaimSslErrorType error,
- gpointer data)
-{
- GaimConnection* gc = data;
-
- switch(error)
- {
- case GAIM_SSL_CONNECT_FAILED:
- gaim_connection_error(gc, _("Connection Failed"));
- break;
-
- case GAIM_SSL_HANDSHAKE_FAILED:
- gaim_connection_error(gc, _("SSL Handshake Failed"));
- break;
- }
-}
-
-void interface_tlson(GaimConnection* gc, GaimAccount* ga, int fd)
-{
- gaim_input_remove(gc->inpa);
- gc->inpa = 0;
- gaim_ssl_connect_fd(ga, fd, ssl_setup_cb, ssl_failure_cb, gc);
-}
-
-/* --- Timer ------------------------------------------------------------- */
-
-static gboolean timer_cb(gpointer data)
-{
- struct lua_State* L = data;
-
- lua_getglobal(L, "citadel_timer");
- wrappedcall(L, 0, 0);
- return TRUE;
-}
-
-int interface_timeron(GaimConnection* gc, time_t interval)
-{
- return gaim_timeout_add(interval, timer_cb, gc->proto_data);
-}
-
-void interface_timeroff(GaimConnection* gc, int timerhandle)
-{
- gaim_timeout_remove(timerhandle);
-}
-
-/* ======================================================================= */
-/* CONNECT/DISCONNECT */
-/* ======================================================================= */
-
-static void citadel_login(GaimAccount *account)
-{
- GaimConnection* gc;
- lua_State* L;
- int i;
-
- /* Set up account settings. */
-
- hackgc = gc = gaim_account_get_connection(account);
- gc->flags |= GAIM_CONNECTION_NO_BGCOLOR
- | GAIM_CONNECTION_FORMATTING_WBFO
- | GAIM_CONNECTION_NO_FONTSIZE
- | GAIM_CONNECTION_NO_URLDESC
- | GAIM_CONNECTION_NO_IMAGES;
-
- /* Initialise our private data. */
-
- gc->proto_data = L = lua_open();
- luaopen_base(L);
- luaopen_table(L);
- luaopen_string(L);
- luaopen_math(L);
- luaopen_debug(L);
- luaopen_io(L);
- tolua_gaim_open(L);
-
- /* Register our private library. */
-
-// luaL_openlib(L, "gaimi", gaim_library, 0);
-
- /* Load in our 'microcode'. */
-
- {
- GString* microcode = g_string_new(gaim_user_dir());
- g_string_append(microcode, LUA_MICROCODE);
-
-
- gaim_debug(GAIM_DEBUG_MISC, "citadel", "loading %s\n", microcode->str);
- i = luaL_loadfile(L, microcode->str) ||
- lua_pcall(L, 0, 0, 0);
- g_string_free(microcode, TRUE);
-
- if (i)
- {
- gaim_debug(GAIM_DEBUG_MISC, "citadel", "lua error on load: %s\n",
- lua_tostring(L, -1));
- gaim_connection_error(gc, _("Unable to initialise plugin"));
- return;
- }
- }
-
- /* Set the reentrancy counter. */
-
- lua_pushnumber(L, 0);
- lua_setglobal(L, " entrycount");
-
- /* Tell the script to start connecting. */
-
- lua_getglobal(L, "citadel_connect");
- {
- GaimAccount** o = lua_newuserdata(L, sizeof(GaimAccount*));
- *o = account;
- }
- wrappedcall(L, 1, 0);
-}
-
-static void citadel_close(GaimConnection* gc)
-{
- lua_State* L = gc->proto_data;
-
- if (gc->inpa)
- {
- gaim_input_remove(gc->inpa);
- gc->inpa = 0;
- }
-
- if (L)
- {
- gaim_debug(GAIM_DEBUG_MISC, "citadel", "telling lua to disconnect\n");
- lua_getglobal(L, "citadel_close");
- wrappedcall(L, 0, 0);
- }
-
- gaim_debug(GAIM_DEBUG_MISC, "citadel", "destroying lua VM\n");
- lua_close(L);
-}
-
-/* ======================================================================= */
-/* MESSAGING */
-/* ======================================================================= */
-
-static int citadel_send_im(GaimConnection* gc, const char* who,
- const char* what, GaimConvImFlags flags)
-{
- lua_State* L = gc->proto_data;
-
- lua_getglobal(L, "citadel_send_im");
- lua_pushstring(L, who);
- lua_pushstring(L, what);
- lua_pushnumber(L, flags);
- wrappedcall(L, 3, 0);
-
- return 1;
-}
-
-/* ======================================================================= */
-/* PRESENCE */
-/* ======================================================================= */
-
-void citadel_add_buddy(GaimConnection* gc, GaimBuddy* buddy, GaimGroup* group)
-{
- lua_State* L = gc->proto_data;
-
- lua_getglobal(L, "citadel_add_buddy");
- lua_pushstring(L, buddy->name);
- wrappedcall(L, 1, 0);
-}
-
-void citadel_remove_buddy(GaimConnection* gc, GaimBuddy* buddy, GaimGroup* group)
-{
- lua_State* L = gc->proto_data;
-
- lua_getglobal(L, "citadel_remove_buddy");
- lua_pushstring(L, buddy->name);
- wrappedcall(L, 1, 0);
-}
-
-void citadel_alias_buddy(GaimConnection* gc, const char* who, const char* alias)
-{
- lua_State* L = gc->proto_data;
-
- lua_getglobal(L, "citadel_alias_buddy");
- lua_pushstring(L, who);
- wrappedcall(L, 1, 0);
-}
-
-void citadel_group_buddy(GaimConnection* gc, const char *who,
- const char *old_group, const char *new_group)
-{
- lua_State* L = gc->proto_data;
-
- lua_getglobal(L, "citadel_group_buddy");
- lua_pushstring(L, who);
- lua_pushstring(L, old_group);
- lua_pushstring(L, new_group);
- wrappedcall(L, 3, 0);
-}
-
-/* This is really just to fill out a hole in the gaim API. */
-
-const char* gaim_group_get_name(GaimGroup* group)
-{
- return group->name;
-}
-
-/* ======================================================================= */
-/* USER INFO */
-/* ======================================================================= */
-
-void citadel_get_info(GaimConnection* gc, const char* name)
-{
- lua_State* L = gc->proto_data;
-
- lua_getglobal(L, "citadel_get_info");
- lua_pushstring(L, name);
- wrappedcall(L, 1, 0);
-}
-
-/* ======================================================================= */
-/* MISCELLANEOUS */
-/* ======================================================================= */
-
-static void citadel_keepalive(GaimConnection* gc)
-{
- lua_State* L = gc->proto_data;
-
- lua_getglobal(L, "citadel_keepalive");
- wrappedcall(L, 0, 0);
-}
-
-static const char* citadel_list_icon(GaimAccount* a, GaimBuddy* b)
-{
- return "citadel";
-}
-
-static void citadel_list_emblems(GaimBuddy* b, char** se, char** sw,
- char** nw, char** ne)
-{
- if (b->present == GAIM_BUDDY_OFFLINE)
- *se = "offline";
-}
-
-/* ======================================================================= */
-/* PLUGIN SETUP */
-/* ======================================================================= */
-
-static GaimPluginProtocolInfo protocol =
-{
- OPT_PROTO_CHAT_TOPIC,
- NULL, /* user_splits */
- NULL, /* protocol_options */
- NO_BUDDY_ICONS, /* icon_spec */
- citadel_list_icon, /* list_icon */
- citadel_list_emblems, /* list_emblems */
- NULL, /* status_text */
- NULL, /* tooltip_text */
- NULL, //irc_away_states, /* away_states */
- NULL, /* blist_node_menu */
- NULL, //irc_chat_join_info, /* chat_info */
- NULL, //irc_chat_info_defaults, /* chat_info_defaults */
- citadel_login, /* login */
- citadel_close, /* close */
- citadel_send_im, /* send_im */
- NULL, /* set_info */
- NULL, /* send_typing */
- citadel_get_info, /* get_info */
- NULL, //irc_set_away, /* set_away */
- NULL, /* set_idle */
- NULL, /* change_passwd */
- citadel_add_buddy, /* add_buddy */
- NULL, /* add_buddies */
- citadel_remove_buddy, /* remove_buddy */
- NULL, /* remove_buddies */
- NULL, /* add_permit */
- NULL, /* add_deny */
- NULL, /* rem_permit */
- NULL, /* rem_deny */
- NULL, /* set_permit_deny */
- NULL, /* warn */
- NULL, //irc_chat_join, /* join_chat */
- NULL, /* reject_chat */
- NULL, //irc_get_chat_name, /* get_chat_name */
- NULL, //irc_chat_invite, /* chat_invite */
- NULL, //irc_chat_leave, /* chat_leave */
- NULL, /* chat_whisper */
- NULL, //irc_chat_send, /* chat_send */
- citadel_keepalive, /* keepalive */
- NULL, /* register_user */
- NULL, /* get_cb_info */
- NULL, /* get_cb_away */
- citadel_alias_buddy, /* alias_buddy */
- citadel_group_buddy, /* group_buddy */
- NULL, /* rename_group */
- NULL, /* buddy_free */
- NULL, /* convo_closed */
- gaim_normalize_nocase, /* normalize */
- NULL, /* set_buddy_icon */
- NULL, /* remove_group */
- NULL, /* get_cb_real_name */
- NULL, //irc_chat_set_topic, /* set_chat_topic */
- NULL, /* find_blist_chat */
- NULL, //irc_roomlist_get_list, /* roomlist_get_list */
- NULL, //irc_roomlist_cancel, /* roomlist_cancel */
- NULL, /* roomlist_expand_category */
- NULL, /* can_receive_file */
- NULL, //irc_dccsend_send_file /* send_file */
-};
-
-static GaimPluginInfo info =
-{
- GAIM_PLUGIN_MAGIC,
- GAIM_MAJOR_VERSION,
- GAIM_MINOR_VERSION,
- GAIM_PLUGIN_PROTOCOL, /**< type */
- NULL, /**< ui_requirement */
- 0, /**< flags */
- NULL, /**< dependencies */
- GAIM_PRIORITY_DEFAULT, /**< priority */
-
- "prpl-citadel", /**< id */
- "Citadel", /**< name */
- VERSION, /**< version */
- N_("Citadel Protocol Plugin"), /** summary */
- N_("Instant Messaging via Citadel"), /** description */
- NULL, /**< author */
- GAIM_WEBSITE, /**< homepage */
-
- NULL, /**< load */
- NULL, /**< unload */
- NULL, /**< destroy */
-
- NULL, /**< ui_info */
- &protocol, /**< extra_info */
- NULL, /**< prefs_info */
- NULL
-};
-
-static void _init_plugin(GaimPlugin *plugin)
-{
- GaimAccountUserSplit *split;
- GaimAccountOption *option;
-
- split = gaim_account_user_split_new(_("Server"), CITADEL_DEFAULT_SERVER, '@');
- protocol.user_splits = g_list_append(protocol.user_splits, split);
-
- option = gaim_account_option_int_new(_("Port"), "port", CITADEL_DEFAULT_PORT);
- protocol.protocol_options = g_list_append(protocol.protocol_options, option);
-
- option = gaim_account_option_bool_new(_("Everyone here's a buddy"), "no_blist", FALSE);
- protocol.protocol_options = g_list_append(protocol.protocol_options, option);
-
- option = gaim_account_option_bool_new(_("Use TLS"), "use_tls", TRUE);
- protocol.protocol_options = g_list_append(protocol.protocol_options, option);
-
- option = gaim_account_option_int_new(_("Polling interval"), "interval", CITADEL_POLL_INTERVAL);
- protocol.protocol_options = g_list_append(protocol.protocol_options, option);
-
- gaim_prefs_add_none("/plugins/prpl/citadel");
-}
-
-GAIM_INIT_PLUGIN(citadel, _init_plugin, info);