5 * This code is licensed under the GPL v3. See the file COPYING in this
6 * directory for the full license text.
8 * $Id:citadel.c 4326 2006-02-18 12:26:22Z hjalfi $
13 #include "accountopt.h"
15 #include "conversation.h"
28 #include "interface.h"
30 extern int tolua_gaim_open(lua_State* L);
31 extern void tolua_gaim_close(lua_State* L);
34 #define CITADEL_DEFAULT_SERVER "uncensored.citadel.org"
35 #define CITADEL_DEFAULT_PORT 504
36 #define CITADEL_POLL_INTERVAL 60
37 #define LUA_MICROCODE "/plugindata/citadel.lua"
42 GaimSslConnection* gsc;
47 static GaimConnection* hackgc;
49 /* ======================================================================= */
51 /* ======================================================================= */
53 static void wrappedcall(lua_State* L, int inparams, int outparams)
57 i = lua_pcall(L, inparams, outparams, 0);
60 gaim_debug(GAIM_DEBUG_MISC, "citadel", "lua error: %s\n",
62 gaim_connection_error(hackgc, _("Internal error in plugin"));
66 lua_getglobal(L, "citadel_schedule_now");
67 i = lua_pcall(L, 0, 0, 0);
70 gaim_debug(GAIM_DEBUG_MISC, "citadel", "lua error in scheduler: %s\n",
72 gaim_connection_error(hackgc, _("Internal error in plugin"));
77 /* ======================================================================= */
79 /* ======================================================================= */
81 /* --- Input ------------------------------------------------------------- */
83 static void input_cb(gpointer data, gint fd, GaimInputCondition cond)
85 GaimConnection* gc = data;
86 lua_State* L = gc->proto_data;
88 lua_getglobal(L, "citadel_input");
92 static void input_ssl_cb(gpointer data, GaimSslConnection* gsc, GaimInputCondition cond)
94 GaimConnection* gc = data;
95 lua_State* L = gc->proto_data;
97 lua_getglobal(L, "citadel_input");
101 char* interface_readdata(int fd, GaimSslConnection* gsc)
103 static char buffer[1024];
106 /* Read in some data. */
109 len = gaim_ssl_read(gsc, buffer, sizeof(buffer)-1);
111 len = read(fd, buffer, sizeof(buffer)-1);
120 int interface_writedata(int fd, GaimSslConnection* gsc, char* buffer)
122 int len = strlen(buffer);
130 i = gaim_ssl_write(gsc, p, len);
132 i = write(fd, p, len);
144 /* --- Connection -------------------------------------------------------- */
146 static void login_cb(gpointer data, gint fd, GaimInputCondition cond)
148 GaimConnection* gc = data;
149 lua_State* L = gc->proto_data;
153 gaim_connection_error(gc, _("Couldn't connect to host"));
157 if (!g_list_find(gaim_connections_get_all(), gc))
163 /* Register the input event handler. */
165 gc->inpa = gaim_input_add(fd, GAIM_INPUT_READ, input_cb, gc);
167 /* Register this file descriptor and tell Lua. */
169 lua_getglobal(L, "citadel_setfd");
170 lua_pushnumber(L, fd);
171 wrappedcall(L, 1, 0);
174 int interface_connect(GaimAccount* ga, GaimConnection* gc,
175 char* server, int port)
177 return gaim_proxy_connect(ga, server, port, login_cb, gc);
180 void interface_disconnect(int fd, GaimSslConnection* gsc)
188 /* --- TLS setup --------------------------------------------------------- */
190 static void ssl_setup_cb(gpointer data, GaimSslConnection* gsc,
191 GaimInputCondition cond)
193 GaimConnection* gc = data;
194 lua_State* L = gc->proto_data;
196 if (!g_list_find(gaim_connections_get_all(), gc))
202 gaim_debug(GAIM_DEBUG_MISC, "citadel", "using gsc %p\n", gsc);
203 gaim_ssl_input_add(gsc, input_ssl_cb, gc);
205 /* Register this file descriptor and tell Lua. */
207 lua_getglobal(L, "citadel_setgsc");
209 GaimSslConnection** o = lua_newuserdata(L, sizeof(GaimSslConnection));
212 wrappedcall(L, 1, 0);
215 static void ssl_failure_cb(GaimSslConnection *gsc, GaimSslErrorType error,
218 GaimConnection* gc = data;
222 case GAIM_SSL_CONNECT_FAILED:
223 gaim_connection_error(gc, _("Connection Failed"));
226 case GAIM_SSL_HANDSHAKE_FAILED:
227 gaim_connection_error(gc, _("SSL Handshake Failed"));
232 void interface_tlson(GaimConnection* gc, GaimAccount* ga, int fd)
234 gaim_input_remove(gc->inpa);
236 gaim_ssl_connect_fd(ga, fd, ssl_setup_cb, ssl_failure_cb, gc);
239 /* --- Timer ------------------------------------------------------------- */
241 static gboolean timer_cb(gpointer data)
243 struct lua_State* L = data;
245 lua_getglobal(L, "citadel_timer");
246 wrappedcall(L, 0, 0);
250 int interface_timeron(GaimConnection* gc, time_t interval)
252 return gaim_timeout_add(interval, timer_cb, gc->proto_data);
255 void interface_timeroff(GaimConnection* gc, int timerhandle)
257 gaim_timeout_remove(timerhandle);
260 /* ======================================================================= */
261 /* CONNECT/DISCONNECT */
262 /* ======================================================================= */
264 static void citadel_login(GaimAccount *account)
270 /* Set up account settings. */
272 hackgc = gc = gaim_account_get_connection(account);
273 gc->flags |= GAIM_CONNECTION_NO_BGCOLOR
274 | GAIM_CONNECTION_FORMATTING_WBFO
275 | GAIM_CONNECTION_NO_FONTSIZE
276 | GAIM_CONNECTION_NO_URLDESC
277 | GAIM_CONNECTION_NO_IMAGES;
279 /* Initialise our private data. */
281 gc->proto_data = L = lua_open();
290 /* Register our private library. */
292 // luaL_openlib(L, "gaimi", gaim_library, 0);
294 /* Load in our 'microcode'. */
297 GString* microcode = g_string_new(gaim_user_dir());
298 g_string_append(microcode, LUA_MICROCODE);
301 gaim_debug(GAIM_DEBUG_MISC, "citadel", "loading %s\n", microcode->str);
302 i = luaL_loadfile(L, microcode->str) ||
303 lua_pcall(L, 0, 0, 0);
304 g_string_free(microcode, TRUE);
308 gaim_debug(GAIM_DEBUG_MISC, "citadel", "lua error on load: %s\n",
309 lua_tostring(L, -1));
310 gaim_connection_error(gc, _("Unable to initialise plugin"));
315 /* Set the reentrancy counter. */
317 lua_pushnumber(L, 0);
318 lua_setglobal(L, " entrycount");
320 /* Tell the script to start connecting. */
322 lua_getglobal(L, "citadel_connect");
324 GaimAccount** o = lua_newuserdata(L, sizeof(GaimAccount*));
327 wrappedcall(L, 1, 0);
330 static void citadel_close(GaimConnection* gc)
332 lua_State* L = gc->proto_data;
336 gaim_input_remove(gc->inpa);
342 gaim_debug(GAIM_DEBUG_MISC, "citadel", "telling lua to disconnect\n");
343 lua_getglobal(L, "citadel_close");
344 wrappedcall(L, 0, 0);
347 gaim_debug(GAIM_DEBUG_MISC, "citadel", "destroying lua VM\n");
351 /* ======================================================================= */
353 /* ======================================================================= */
355 static int citadel_send_im(GaimConnection* gc, const char* who,
356 const char* what, GaimConvImFlags flags)
358 lua_State* L = gc->proto_data;
360 lua_getglobal(L, "citadel_send_im");
361 lua_pushstring(L, who);
362 lua_pushstring(L, what);
363 lua_pushnumber(L, flags);
364 wrappedcall(L, 3, 0);
369 /* ======================================================================= */
371 /* ======================================================================= */
373 void citadel_add_buddy(GaimConnection* gc, GaimBuddy* buddy, GaimGroup* group)
375 lua_State* L = gc->proto_data;
377 lua_getglobal(L, "citadel_add_buddy");
378 lua_pushstring(L, buddy->name);
379 wrappedcall(L, 1, 0);
382 void citadel_remove_buddy(GaimConnection* gc, GaimBuddy* buddy, GaimGroup* group)
384 lua_State* L = gc->proto_data;
386 lua_getglobal(L, "citadel_remove_buddy");
387 lua_pushstring(L, buddy->name);
388 wrappedcall(L, 1, 0);
391 void citadel_alias_buddy(GaimConnection* gc, const char* who, const char* alias)
393 lua_State* L = gc->proto_data;
395 lua_getglobal(L, "citadel_alias_buddy");
396 lua_pushstring(L, who);
397 wrappedcall(L, 1, 0);
400 void citadel_group_buddy(GaimConnection* gc, const char *who,
401 const char *old_group, const char *new_group)
403 lua_State* L = gc->proto_data;
405 lua_getglobal(L, "citadel_group_buddy");
406 lua_pushstring(L, who);
407 lua_pushstring(L, old_group);
408 lua_pushstring(L, new_group);
409 wrappedcall(L, 3, 0);
412 /* This is really just to fill out a hole in the gaim API. */
414 const char* gaim_group_get_name(GaimGroup* group)
419 /* ======================================================================= */
421 /* ======================================================================= */
423 void citadel_get_info(GaimConnection* gc, const char* name)
425 lua_State* L = gc->proto_data;
427 lua_getglobal(L, "citadel_get_info");
428 lua_pushstring(L, name);
429 wrappedcall(L, 1, 0);
432 /* ======================================================================= */
434 /* ======================================================================= */
436 static void citadel_keepalive(GaimConnection* gc)
438 lua_State* L = gc->proto_data;
440 lua_getglobal(L, "citadel_keepalive");
441 wrappedcall(L, 0, 0);
444 static const char* citadel_list_icon(GaimAccount* a, GaimBuddy* b)
449 static void citadel_list_emblems(GaimBuddy* b, char** se, char** sw,
450 char** nw, char** ne)
452 if (b->present == GAIM_BUDDY_OFFLINE)
456 /* ======================================================================= */
458 /* ======================================================================= */
460 static GaimPluginProtocolInfo protocol =
462 OPT_PROTO_CHAT_TOPIC,
463 NULL, /* user_splits */
464 NULL, /* protocol_options */
465 NO_BUDDY_ICONS, /* icon_spec */
466 citadel_list_icon, /* list_icon */
467 citadel_list_emblems, /* list_emblems */
468 NULL, /* status_text */
469 NULL, /* tooltip_text */
470 NULL, //irc_away_states, /* away_states */
471 NULL, /* blist_node_menu */
472 NULL, //irc_chat_join_info, /* chat_info */
473 NULL, //irc_chat_info_defaults, /* chat_info_defaults */
474 citadel_login, /* login */
475 citadel_close, /* close */
476 citadel_send_im, /* send_im */
478 NULL, /* send_typing */
479 citadel_get_info, /* get_info */
480 NULL, //irc_set_away, /* set_away */
482 NULL, /* change_passwd */
483 citadel_add_buddy, /* add_buddy */
484 NULL, /* add_buddies */
485 citadel_remove_buddy, /* remove_buddy */
486 NULL, /* remove_buddies */
487 NULL, /* add_permit */
489 NULL, /* rem_permit */
491 NULL, /* set_permit_deny */
493 NULL, //irc_chat_join, /* join_chat */
494 NULL, /* reject_chat */
495 NULL, //irc_get_chat_name, /* get_chat_name */
496 NULL, //irc_chat_invite, /* chat_invite */
497 NULL, //irc_chat_leave, /* chat_leave */
498 NULL, /* chat_whisper */
499 NULL, //irc_chat_send, /* chat_send */
500 citadel_keepalive, /* keepalive */
501 NULL, /* register_user */
502 NULL, /* get_cb_info */
503 NULL, /* get_cb_away */
504 citadel_alias_buddy, /* alias_buddy */
505 citadel_group_buddy, /* group_buddy */
506 NULL, /* rename_group */
507 NULL, /* buddy_free */
508 NULL, /* convo_closed */
509 gaim_normalize_nocase, /* normalize */
510 NULL, /* set_buddy_icon */
511 NULL, /* remove_group */
512 NULL, /* get_cb_real_name */
513 NULL, //irc_chat_set_topic, /* set_chat_topic */
514 NULL, /* find_blist_chat */
515 NULL, //irc_roomlist_get_list, /* roomlist_get_list */
516 NULL, //irc_roomlist_cancel, /* roomlist_cancel */
517 NULL, /* roomlist_expand_category */
518 NULL, /* can_receive_file */
519 NULL, //irc_dccsend_send_file /* send_file */
522 static GaimPluginInfo info =
527 GAIM_PLUGIN_PROTOCOL, /**< type */
528 NULL, /**< ui_requirement */
530 NULL, /**< dependencies */
531 GAIM_PRIORITY_DEFAULT, /**< priority */
533 "prpl-citadel", /**< id */
534 "Citadel", /**< name */
535 VERSION, /**< version */
536 N_("Citadel Protocol Plugin"), /** summary */
537 N_("Instant Messaging via Citadel"), /** description */
539 GAIM_WEBSITE, /**< homepage */
543 NULL, /**< destroy */
545 NULL, /**< ui_info */
546 &protocol, /**< extra_info */
547 NULL, /**< prefs_info */
551 static void _init_plugin(GaimPlugin *plugin)
553 GaimAccountUserSplit *split;
554 GaimAccountOption *option;
556 split = gaim_account_user_split_new(_("Server"), CITADEL_DEFAULT_SERVER, '@');
557 protocol.user_splits = g_list_append(protocol.user_splits, split);
559 option = gaim_account_option_int_new(_("Port"), "port", CITADEL_DEFAULT_PORT);
560 protocol.protocol_options = g_list_append(protocol.protocol_options, option);
562 option = gaim_account_option_bool_new(_("Everyone here's a buddy"), "no_blist", FALSE);
563 protocol.protocol_options = g_list_append(protocol.protocol_options, option);
565 option = gaim_account_option_bool_new(_("Use TLS"), "use_tls", TRUE);
566 protocol.protocol_options = g_list_append(protocol.protocol_options, option);
568 option = gaim_account_option_int_new(_("Polling interval"), "interval", CITADEL_POLL_INTERVAL);
569 protocol.protocol_options = g_list_append(protocol.protocol_options, option);
571 gaim_prefs_add_none("/plugins/prpl/citadel");
574 GAIM_INIT_PLUGIN(citadel, _init_plugin, info);