/* IRCfs - IRC FileServ for *nix. * Copyright (C) 2002 Nick 'Zaf' Clifford * For licensing details, refer to the LICENSE file in the source * code directory. */ #include "runtime.h" #include "module.h" #include "user.h" #include "magic.h" #include "event.h" #include "server.h" #include "ctcp.h" #include static int ctcp_each_server(struct server *s); int ctcp_command_privmsg(struct server *s, const char *cmd, int argc, char *argv[],void *appdata); int ctcp_command_notice(struct server *s, const char *cmd, int argc, char *argv[],void *appdata); int ctcp_new_server(struct eventmsg *msg); static int ctcp_event_filter(struct eventmsg *msg, void *filter); static int ctcp_handle_ping(struct eventmsg *msg); MODULE_NAME("ctcp"); MODULE_INIT(ctcp_init); MODULE_DESTROY(ctcp_unload); MODULE_DEPENDS("user","server"); MODULE_REGISTER(ctcp); static struct eventobj *ctcp_eventobj; static DEBUG ctcp_debug; int ctcp_init() { ctcp_debug = debug_register("ctcp"); ctcp_eventobj = event_create_obj(NULL,NULL); server_foreach(ctcp_each_server); event_add_listener(server_get_event_obj(), server_event_new, NULL, ctcp_new_server, NULL); ctcp_eventobj = event_create_obj(NULL,NULL); event_set_filter_func(ctcp_eventobj, ctcp_event_filter); event_add_listener(ctcp_eventobj,ctcp_event_query,"PING", ctcp_handle_ping,NULL); return 0; } int ctcp_unload() { event_del_listener(server_get_event_obj(), server_event_new,NULL,NULL); return 0; } struct eventobj *ctcp_get_event_obj() { return ctcp_eventobj; } int ctcp_new_server(struct eventmsg *msg) { struct server *s; s = (struct server *)msg->msg; return ctcp_each_server(s); } int ctcp_each_server(struct server *s) { server_set_command_handler(s,"PRIVMSG",2, SERVER_TRIGGER_MYNICK, ctcp_command_privmsg,NULL); server_set_command_handler(s,"NOTICE",2, SERVER_TRIGGER_MYNICK, ctcp_command_notice,NULL); return 0; } static int ctcp_handle_ping(struct eventmsg *msg) { struct ctcp_event_msg *cem; cem = (struct ctcp_event_msg *)msg->msg; ASSERT(is_magic(cem,MAGIC_CTCP_EVENT_MSG)); notice(ctcp_debug,"Got CTCP %s from %s", cem->request, user_get_nick(cem->user)); ctcp_send_reply(cem->user, cem->request, cem->data); return 0; } int ctcp_send_reply(struct user *u, const char *type, const char *data) { server_send(user_get_server(u), "NOTICE %s :\01%s%s%s\01", user_get_nick(u), type, data ? " " : "", data ? data : ""); return 0; } int ctcp_command_notice(struct server *s, const char *cmd, int argc, char *argv[],void *appdata) { char type[100]; char *data; const char *cp,*start; int len; struct user *u; static struct ctcp_event_msg cem; if (argc < 3) return 0; cp = argv[3]; while(*cp && *cp != 0x01) cp++; if (!*cp) return 0; cp++; start = cp; while(*cp && *cp != 0x01) cp++; if (!*cp) return 0; len = cp - start; if (len > sizeof(type) - 2) len = sizeof(type) - 2; strncpy(type,start,len); type[len] = 0; for(data = type; *data && !isspace(*data); data++) { } if (*data) { *data = 0; data++; while(isspace(*data)) data++; } u = user_find(s,argv[0]); if (u == NULL) u = user_create(s,argv[0]); set_magic(&cem,MAGIC_CTCP_EVENT_MSG); cem.type = ctcp_event_reply; cem.request = type; cem.data = data; cem.server = s; cem.user = u; info(ctcp_debug,"Got CTCP REPLY %s from %s: %s",type,user_get_nick(u), data); event_raise(ctcp_eventobj,ctcp_event_reply,&cem); return 0; } int ctcp_command_privmsg(struct server *s, const char *cmd, int argc, char *argv[],void *appdata) { char type[100]; char *data; const char *cp,*start; int len; struct user *u; static struct ctcp_event_msg cem; if (argc < 3) return 0; cp = argv[3]; while(*cp && *cp != 0x01) cp++; if (!*cp) return 0; cp++; start = cp; while(*cp && *cp != 0x01) cp++; if (!*cp) return 0; len = cp - start; if (len > sizeof(type) - 2) len = sizeof(type) - 2; strncpy(type,start,len); type[len] = 0; for(data = type; *data && !isspace(*data); data++) { } if (*data) { *data = 0; data++; while(isspace(*data)) data++; } u = user_find(s,argv[0]); if (u == NULL) u = user_create(s,argv[0]); set_magic(&cem,MAGIC_CTCP_EVENT_MSG); cem.type = ctcp_event_query; cem.request = type; cem.data = data; cem.server = s; cem.user = u; info(ctcp_debug,"Got CTCP %s from %s",type,user_get_nick(u)); if (strcasecmp(type,"VERSION") == 0) { server_send(s,"NOTICE %s :\01VERSION %s v%s\01", user_get_nick(u), PACKAGE_NAME, PACKAGE_VERSION); } event_raise(ctcp_eventobj,ctcp_event_query,&cem); return 0; } static int ctcp_event_filter(struct eventmsg *msg, void *filter) { struct ctcp_event_msg *cem; char *name; name = filter; cem = msg->msg; ASSERT(is_magic(cem,MAGIC_CTCP_EVENT_MSG)); if (strcasecmp(name,cem->request) == 0) return 0; return -1; }