diff --git a/src/irc/bot/Makefile.am b/src/irc/bot/Makefile.am index fa7058e7..d2629d89 100644 --- a/src/irc/bot/Makefile.am +++ b/src/irc/bot/Makefile.am @@ -9,6 +9,7 @@ libirc_bot_la_LIBADD = -lcrypt libirc_bot_la_SOURCES = \ bot.c \ bot-commands.c \ + bot-irc-commands.c \ bot-events.c \ bot-users.c \ botnet.c \ @@ -17,6 +18,7 @@ libirc_bot_la_SOURCES = \ noinst_HEADERS = \ bot.h \ botnet.h \ + bot-commands.h \ bot-users.h EXTRA_DIST = \ diff --git a/src/irc/bot/bot-commands.c b/src/irc/bot/bot-commands.c index 9c8e7ee6..c6ee1c93 100644 --- a/src/irc/bot/bot-commands.c +++ b/src/irc/bot/bot-commands.c @@ -29,137 +29,178 @@ #include "masks.h" #include "bot-users.h" +#include "botnet.h" -static void event_privmsg(const char *data, IRC_SERVER_REC *server, - const char *nick, const char *address) +void botcmd_user_add(const char *nick) { - char *params, *target, *msg, *args, *str; + char *str; - g_return_if_fail(data != NULL); + botuser_add(nick); - params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); - if (nick == NULL) nick = server->real_address; - - if (*msg == 1 || ischannel(*target)) { - g_free(params); - return; - } - - /* private message for us */ - str = g_strconcat("bot command ", msg, NULL); - args = strchr(str+12, ' '); - if (args != NULL) *args++ = '\0'; else args = ""; - - g_strdown(str); - if (signal_emit(str, 4, args, server, nick, address)) { - /* msg was a command - the msg event. */ - signal_stop(); - } + str = g_strdup_printf("USER_ADD %s", nick); + botnet_broadcast(NULL, NULL, NULL, str); g_free(str); +} + +void botcmd_user_set_flags(USER_REC *user, int flags) +{ + char *str, *flagstr; + + botuser_set_flags(user, flags); + + flagstr = botuser_value2flags(flags); + str = g_strdup_printf("USER_FLAGS %s %s", user->nick, flagstr); + g_free(flagstr); + + botnet_broadcast(NULL, NULL, NULL, str); + g_free(str); +} + +void botcmd_user_set_channel_flags(USER_REC *user, const char *channel, int flags) +{ + char *str, *flagstr; + + botuser_set_channel_flags(user, channel, flags); + + flagstr = botuser_value2flags(flags); + str = g_strdup_printf("USER_CHAN_FLAGS %s %s %s", user->nick, channel, flagstr); + g_free(flagstr); + + botnet_broadcast(NULL, NULL, NULL, str); + g_free(str); +} + +void botcmd_user_add_mask(USER_REC *user, const char *mask) +{ + char *str; + + botuser_add_mask(user, mask); + + str = g_strdup_printf("USER_ADD_MASK %s %s", user->nick, mask); + botnet_broadcast(NULL, NULL, NULL, str); + g_free(str); +} + +void botcmd_user_set_mask_notflags(USER_REC *user, const char *mask, int not_flags) +{ + char *str, *flagstr; + + botuser_set_mask_notflags(user, mask, not_flags); + + flagstr = botuser_value2flags(not_flags); + str = g_strdup_printf("USER_MASK_NOTFLAGS %s %s %s", user->nick, mask, flagstr); + g_free(flagstr); + + botnet_broadcast(NULL, NULL, NULL, str); + g_free(str); +} + +void botcmd_user_set_password(USER_REC *user, const char *password) +{ + char *str; + + botuser_set_password(user, password); + + str = g_strdup_printf("USER_PASS %s %s", user->nick, password); + botnet_broadcast(NULL, NULL, NULL, str); + g_free(str); +} + +static void botnet_event_user_add(BOT_REC *bot, const char *data, const char *sender) +{ + char *params, *nick; + + params = cmd_get_params(data, 1, &nick); + botuser_add(nick); g_free(params); } -static void botcmd_op(const char *data, IRC_SERVER_REC *server, - const char *nick, const char *address) -{ - CHANNEL_REC *channel; - USER_REC *user; - USER_CHAN_REC *userchan; - GSList *tmp; - - g_return_if_fail(data != NULL); - - if (*data == '\0') { - /* no password given? .. */ - return; - } - - user = botuser_find(nick, address); - if (user == NULL || (user->not_flags & USER_OP) || - !botuser_verify_password(user, data)) { - /* not found, can't op with this mask or failed password */ - return; - } - - /* find the channels where to op.. */ - for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { - channel = tmp->data; - - userchan = g_hash_table_lookup(user->channels, channel->name); - if ((user->flags & USER_OP) || (userchan->flags & USER_OP)) - signal_emit("command op", 3, nick, server, channel); - } -} - -static void botcmd_ident(const char *data, IRC_SERVER_REC *server, - const char *nick, const char *address) +static void botnet_event_user_flags(BOT_REC *bot, const char *data, const char *sender) { USER_REC *user; - char *mask; + char *params, *nick, *flags; - g_return_if_fail(data != NULL); - - user = botuser_find(nick, address); - if (user != NULL) { - /* Already know this host */ - return; - } + params = cmd_get_params(data, 2, &nick, &flags); user = botuser_find(nick, NULL); - if (user == NULL || !botuser_verify_password(user, data)) { - /* failed password */ - return; - } + if (user == NULL) user = botuser_add(nick); + botuser_set_flags(user, botuser_flags2value(flags)); - /* add the new mask */ - mask = irc_get_mask(nick, address, IRC_MASK_USER | IRC_MASK_DOMAIN); - botuser_add_mask(user, mask); - - irc_send_cmdv(server, "NOTICE %s :Added new mask %s", nick, mask); - g_free(mask); + g_free(params); } -static void botcmd_pass(const char *data, IRC_SERVER_REC *server, - const char *nick, const char *address) +static void botnet_event_user_chan_flags(BOT_REC *bot, const char *data, const char *sender) { USER_REC *user; - char *params, *pass, *newpass; + char *params, *nick, *channel, *flags; - g_return_if_fail(data != NULL); + params = cmd_get_params(data, 3, &nick, &channel, &flags); - params = event_get_params(data, 2, &pass, &newpass); + user = botuser_find(nick, NULL); + if (user == NULL) user = botuser_add(nick); + botuser_set_channel_flags(user, channel, botuser_flags2value(flags)); - user = botuser_find(nick, address); - if (user == NULL || *pass == '\0') { - g_free(params); - return; - } + g_free(params); +} - if (user->password != NULL && - (*newpass == '\0' || !botuser_verify_password(user, pass))) { - g_free(params); - return; - } +static void botnet_event_user_add_mask(BOT_REC *bot, const char *data, const char *sender) +{ + USER_REC *user; + char *params, *nick, *mask; - /* change the password */ - botuser_set_password(user, user->password == NULL ? pass : newpass); - irc_send_cmdv(server, "NOTICE %s :Password changed", nick); + params = cmd_get_params(data, 2, &nick, &mask); + + user = botuser_find(nick, NULL); + if (user == NULL) user = botuser_add(nick); + botuser_add_mask(user, mask); + + g_free(params); +} + +static void botnet_event_user_mask_notflags(BOT_REC *bot, const char *data, const char *sender) +{ + USER_REC *user; + char *params, *nick, *mask, *not_flags; + + params = cmd_get_params(data, 3, &nick, &mask, ¬_flags); + + user = botuser_find(nick, NULL); + if (user == NULL) user = botuser_add(nick); + botuser_set_mask_notflags(user, mask, botuser_flags2value(not_flags)); + + g_free(params); +} + +static void botnet_event_user_pass(BOT_REC *bot, const char *data, const char *sender) +{ + USER_REC *user; + char *params, *nick, *pass; + + params = cmd_get_params(data, 2, &nick, &pass); + + user = botuser_find(nick, NULL); + if (user == NULL) user = botuser_add(nick); + botuser_set_password(user, pass); g_free(params); } void bot_commands_init(void) { - signal_add("event privmsg", (SIGNAL_FUNC) event_privmsg); - signal_add_last("bot command op", (SIGNAL_FUNC) botcmd_op); - signal_add_last("bot command ident", (SIGNAL_FUNC) botcmd_ident); - signal_add_last("bot command pass", (SIGNAL_FUNC) botcmd_pass); + signal_add("botnet event user_add", (SIGNAL_FUNC) botnet_event_user_add); + signal_add("botnet event user_flags", (SIGNAL_FUNC) botnet_event_user_flags); + signal_add("botnet event user_chan_flags", (SIGNAL_FUNC) botnet_event_user_chan_flags); + signal_add("botnet event user_add_mask", (SIGNAL_FUNC) botnet_event_user_add_mask); + signal_add("botnet event user_mask_notflags", (SIGNAL_FUNC) botnet_event_user_mask_notflags); + signal_add("botnet event user_pass", (SIGNAL_FUNC) botnet_event_user_pass); } void bot_commands_deinit(void) { - signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg); - signal_remove("bot command op", (SIGNAL_FUNC) botcmd_op); - signal_remove("bot command ident", (SIGNAL_FUNC) botcmd_ident); - signal_remove("bot command pass", (SIGNAL_FUNC) botcmd_pass); + signal_remove("botnet event user_remove", (SIGNAL_FUNC) botnet_event_user_add); + signal_remove("botnet event user_flags", (SIGNAL_FUNC) botnet_event_user_flags); + signal_remove("botnet event user_chan_flags", (SIGNAL_FUNC) botnet_event_user_chan_flags); + signal_remove("botnet event user_remove_mask", (SIGNAL_FUNC) botnet_event_user_add_mask); + signal_remove("botnet event user_mask_notflags", (SIGNAL_FUNC) botnet_event_user_mask_notflags); + signal_remove("botnet event user_pass", (SIGNAL_FUNC) botnet_event_user_pass); } diff --git a/src/irc/bot/bot-commands.h b/src/irc/bot/bot-commands.h new file mode 100644 index 00000000..4fa35d98 --- /dev/null +++ b/src/irc/bot/bot-commands.h @@ -0,0 +1,13 @@ +#ifndef __BOT_COMMANDS_H +#define __BOT_COMMANDS_H + +void botcmd_user_add(const char *nick); +void botcmd_user_set_flags(USER_REC *user, int flags); +void botcmd_user_set_channel_flags(USER_REC *user, const char *channel, int flags); + +void botcmd_user_add_mask(USER_REC *user, const char *mask); +void botcmd_user_set_mask_notflags(USER_REC *user, const char *mask, int not_flags); + +void botcmd_user_set_password(USER_REC *user, const char *password); + +#endif diff --git a/src/irc/bot/bot-irc-commands.c b/src/irc/bot/bot-irc-commands.c new file mode 100644 index 00000000..813e46fe --- /dev/null +++ b/src/irc/bot/bot-irc-commands.c @@ -0,0 +1,166 @@ +/* + bot-irc-commands.c : IRC bot plugin for irssi + + Copyright (C) 1999-2000 Timo Sirainen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "module.h" +#include "signals.h" +#include "commands.h" + +#include "irc.h" +#include "irc-server.h" +#include "channels.h" +#include "nicklist.h" +#include "masks.h" + +#include "bot-users.h" +#include "bot-commands.h" + +static void event_privmsg(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *address) +{ + char *params, *target, *msg, *args, *str; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + if (nick == NULL) nick = server->real_address; + + if (*msg == 1 || ischannel(*target)) { + g_free(params); + return; + } + + /* private message for us */ + str = g_strconcat("bot command ", msg, NULL); + args = strchr(str+12, ' '); + if (args != NULL) *args++ = '\0'; else args = ""; + + g_strdown(str); + if (signal_emit(str, 4, args, server, nick, address)) { + /* msg was a command - the msg event. */ + signal_stop(); + } + g_free(str); + g_free(params); +} + +static void botcmd_op(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *address) +{ + CHANNEL_REC *channel; + USER_REC *user; + USER_CHAN_REC *userchan; + GSList *tmp; + + g_return_if_fail(data != NULL); + + if (*data == '\0') { + /* no password given? .. */ + return; + } + + user = botuser_find(nick, address); + if (user == NULL || (user->not_flags & USER_OP) || + !botuser_verify_password(user, data)) { + /* not found, can't op with this mask or failed password */ + return; + } + + /* find the channels where to op.. */ + for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { + channel = tmp->data; + + userchan = g_hash_table_lookup(user->channels, channel->name); + if ((user->flags & USER_OP) || (userchan->flags & USER_OP)) + signal_emit("command op", 3, nick, server, channel); + } +} + +static void botcmd_ident(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *address) +{ + USER_REC *user; + char *mask; + + g_return_if_fail(data != NULL); + + user = botuser_find(nick, address); + if (user != NULL) { + /* Already know this host */ + return; + } + + user = botuser_find(nick, NULL); + if (user == NULL || !botuser_verify_password(user, data)) { + /* failed password */ + return; + } + + /* add the new mask */ + mask = irc_get_mask(nick, address, IRC_MASK_USER | IRC_MASK_DOMAIN); + botcmd_user_add_mask(user, mask); + + irc_send_cmdv(server, "NOTICE %s :Added new mask %s", nick, mask); + g_free(mask); +} + +static void botcmd_pass(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *address) +{ + USER_REC *user; + char *params, *pass, *newpass; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, &pass, &newpass); + + user = botuser_find(nick, address); + if (user == NULL || *pass == '\0') { + g_free(params); + return; + } + + if (user->password != NULL && + (*newpass == '\0' || !botuser_verify_password(user, pass))) { + g_free(params); + return; + } + + /* change the password */ + botcmd_user_set_password(user, user->password == NULL ? pass : newpass); + irc_send_cmdv(server, "NOTICE %s :Password changed", nick); + + g_free(params); +} + +void bot_irc_commands_init(void) +{ + signal_add("event privmsg", (SIGNAL_FUNC) event_privmsg); + signal_add_last("bot command op", (SIGNAL_FUNC) botcmd_op); + signal_add_last("bot command ident", (SIGNAL_FUNC) botcmd_ident); + signal_add_last("bot command pass", (SIGNAL_FUNC) botcmd_pass); +} + +void bot_irc_commands_deinit(void) +{ + signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg); + signal_remove("bot command op", (SIGNAL_FUNC) botcmd_op); + signal_remove("bot command ident", (SIGNAL_FUNC) botcmd_ident); + signal_remove("bot command pass", (SIGNAL_FUNC) botcmd_pass); +} diff --git a/src/irc/bot/bot-users.c b/src/irc/bot/bot-users.c index 5db917a1..925268c8 100644 --- a/src/irc/bot/bot-users.c +++ b/src/irc/bot/bot-users.c @@ -79,10 +79,15 @@ static void botuser_save_chan(const char *key, USER_CHAN_REC *rec, CONFIG_NODE * CONFIG_NODE *noderec; char *str; + if (rec->flags == 0) { + /* no flags in this channel - no need to save to config */ + config_node_set_str(userconfig, node, rec->channel, NULL); + return; + } + noderec = config_node_section(node, rec->channel, NODE_TYPE_BLOCK); - str = rec->flags == 0 ? NULL : - botuser_value2flags(rec->flags); + str = botuser_value2flags(rec->flags); config_node_set_str(userconfig, noderec, "flags", str); g_free_not_null(str); } @@ -131,26 +136,6 @@ static void botuser_config_save(USER_REC *user) } } -static USER_MASK_REC *botuser_create_mask(USER_REC *user, const char *mask) -{ - USER_MASK_REC *rec; - - rec = g_new0(USER_MASK_REC, 1); - rec->mask = g_strdup(mask); - - user->masks = g_slist_append(user->masks, rec); - return rec; -} - -USER_MASK_REC *botuser_add_mask(USER_REC *user, const char *mask) -{ - USER_MASK_REC *rec; - - rec = botuser_create_mask(user, mask); - botuser_config_save(user); - return rec; -} - static int botuser_find_mask(USER_REC *user, const char *nick, const char *host) { GSList *tmp; @@ -172,6 +157,23 @@ static int botuser_find_mask(USER_REC *user, const char *nick, const char *host) return FALSE; } +static USER_MASK_REC *botuser_find_full_mask(USER_REC *user, const char *mask) +{ + GSList *tmp; + + g_return_val_if_fail(user != NULL, FALSE); + g_return_val_if_fail(mask != NULL, FALSE); + + for (tmp = user->masks; tmp != NULL; tmp = tmp->next) { + USER_MASK_REC *rec = tmp->data; + + if (g_strcasecmp(rec->mask, mask) == 0) + return rec; + } + + return NULL; +} + static void botuser_getusers_hash(void *key, USER_REC *user, GList **list) { *list = g_list_append(*list, user); @@ -238,7 +240,7 @@ USER_REC *botuser_find_rec(CHANNEL_REC *channel, NICK_REC *nick) return user; } -static USER_CHAN_REC *botuser_channel(USER_REC *user, const char *channel) +USER_CHAN_REC *botuser_get_channel(USER_REC *user, const char *channel) { USER_CHAN_REC *rec; @@ -254,6 +256,66 @@ static USER_CHAN_REC *botuser_channel(USER_REC *user, const char *channel) return rec; } +USER_REC *botuser_add(const char *nick) +{ + USER_REC *user; + + /* Add new user */ + user = g_new0(USER_REC, 1); + user->nick = g_strdup(nick); + g_hash_table_insert(users, user->nick, user); + + botuser_config_save(user); + return user; +} + +void botuser_set_flags(USER_REC *user, int flags) +{ + user->flags = flags; + botuser_config_save(user); +} + +void botuser_set_channel_flags(USER_REC *user, const char *channel, int flags) +{ + USER_CHAN_REC *rec; + + rec = botuser_get_channel(user, channel); + if (rec != NULL) rec->flags = flags; + + botuser_config_save(user); +} + +static USER_MASK_REC *botuser_create_mask(USER_REC *user, const char *mask) +{ + USER_MASK_REC *rec; + + rec = g_new0(USER_MASK_REC, 1); + rec->mask = g_strdup(mask); + + user->masks = g_slist_append(user->masks, rec); + return rec; +} + +USER_MASK_REC *botuser_add_mask(USER_REC *user, const char *mask) +{ + USER_MASK_REC *rec; + + rec = botuser_create_mask(user, mask); + botuser_config_save(user); + return rec; +} + +void botuser_set_mask_notflags(USER_REC *user, const char *mask, int not_flags) +{ + USER_MASK_REC *rec; + + rec = botuser_find_full_mask(user, mask); + if (rec == NULL) rec = botuser_create_mask(user, mask); + + rec->not_flags = not_flags; + botuser_config_save(user); +} + void botuser_set_password(USER_REC *user, const char *password) { char *pass, salt[3]; @@ -303,7 +365,7 @@ static void event_massjoin(CHANNEL_REC *channel, GSList *nicks) user = botuser_find(rec->nick, rec->host); if (user != NULL) { - userchan = botuser_channel(user, channel->name); + userchan = botuser_get_channel(user, channel->name); userchan->nickrec = rec; users = g_slist_append(users, user); } @@ -333,7 +395,7 @@ static void sig_channel_sync(CHANNEL_REC *channel) user = botuser_find(rec->nick, rec->host); if (user != NULL) { - userchan = botuser_channel(user, channel->name); + userchan = botuser_get_channel(user, channel->name); userchan->nickrec = rec; } } diff --git a/src/irc/bot/bot-users.h b/src/irc/bot/bot-users.h index c463f09e..ab498995 100644 --- a/src/irc/bot/bot-users.h +++ b/src/irc/bot/bot-users.h @@ -39,7 +39,13 @@ char *botuser_value2flags(int value); USER_REC *botuser_find(const char *nick, const char *host); USER_REC *botuser_find_rec(CHANNEL_REC *channel, NICK_REC *nick); + +USER_REC *botuser_add(const char *nick); +void botuser_set_flags(USER_REC *user, int flags); +void botuser_set_channel_flags(USER_REC *user, const char *channel, int flags); + USER_MASK_REC *botuser_add_mask(USER_REC *user, const char *mask); +void botuser_set_mask_notflags(USER_REC *user, const char *mask, int not_flags); void botuser_set_password(USER_REC *user, const char *password); int botuser_verify_password(USER_REC *user, const char *password); diff --git a/src/irc/bot/bot.c b/src/irc/bot/bot.c index 5bcf7dd0..4e9cb831 100644 --- a/src/irc/bot/bot.c +++ b/src/irc/bot/bot.c @@ -23,6 +23,9 @@ void bot_commands_deinit(void); void bot_commands_init(void); +void bot_irc_commands_deinit(void); +void bot_irc_commands_init(void); + void bot_events_init(void); void bot_events_deinit(void); @@ -36,6 +39,7 @@ void irc_bot_init(void) { bot_users_init(); bot_commands_init(); + bot_irc_commands_init(); bot_events_init(); botnet_init(); } @@ -44,6 +48,7 @@ void irc_bot_deinit(void) { bot_users_deinit(); bot_commands_deinit(); + bot_irc_commands_deinit(); bot_events_deinit(); botnet_deinit(); } diff --git a/src/irc/bot/botnet-connection.c b/src/irc/bot/botnet-connection.c index 2b402e88..6a057758 100644 --- a/src/irc/bot/botnet-connection.c +++ b/src/irc/bot/botnet-connection.c @@ -430,6 +430,8 @@ static void botnet_event_sync(BOT_REC *bot) /* send our downlinks to host */ botnet_send_links(bot, TRUE); + + signal_stop_by_name("botnet event"); } static BOT_REC *bot_add(BOTNET_REC *botnet, const char *nick, const char *parent) @@ -460,12 +462,12 @@ static BOT_REC *bot_add(BOTNET_REC *botnet, const char *nick, const char *parent static void botnet_event_botinfo(BOT_REC *bot, const char *data, const char *sender) { - char *str, *params, *nick, *parent, *priority; + char *params, *nick, *parent, *priority; BOT_REC *rec; - str = g_strdup_printf("BOTINFO %s", data); + /*str = g_strdup_printf("BOTINFO %s", data); botnet_broadcast(bot->botnet, bot, sender, str); - g_free(str); + g_free(str);*/ params = cmd_get_params(data, 3, &nick, &parent, &priority); if (*parent == '-' && parent[1] == '\0') @@ -492,6 +494,8 @@ static void botnet_event_botquit(BOT_REC *bot, const char *data) node = bot_find_nick(bot->botnet, data); if (node != NULL) bot_destroy(node->data); + + signal_stop_by_name("botnet event"); } static void sig_bot_disconnected(BOT_REC *bot) diff --git a/src/irc/bot/botnet.c b/src/irc/bot/botnet.c index 03a1749c..01954703 100644 --- a/src/irc/bot/botnet.c +++ b/src/irc/bot/botnet.c @@ -57,10 +57,8 @@ void bot_send_cmdv(BOT_REC *bot, char *format, ...) va_end(args); } -/* broadcast a message to everyone in bot network, except for `except_bot' - if it's not NULL */ -void botnet_broadcast(BOTNET_REC *botnet, BOT_REC *except_bot, - const char *source, const char *data) +static void botnet_broadcast_single(BOTNET_REC *botnet, BOT_REC *except_bot, + const char *source, const char *data) { GNode *node; char *str; @@ -79,6 +77,44 @@ void botnet_broadcast(BOTNET_REC *botnet, BOT_REC *except_bot, g_free(str); } +/* broadcast a message to everyone in bot network, except for `except_bot' + if it's not NULL. If botnet is NULL, the message is sent to all botnets. */ +void botnet_broadcast(BOTNET_REC *botnet, BOT_REC *except_bot, + const char *source, const char *data) +{ + GSList *tmp; + + g_return_if_fail(botnet != NULL); + g_return_if_fail(data != NULL); + + if (botnet != NULL) { + botnet_broadcast_single(botnet, except_bot, source, data); + return; + } + + /* broadcast to all botnets */ + for (tmp = botnets; tmp != NULL; tmp = tmp->next) { + BOTNET_REC *rec = tmp->data; + + botnet_broadcast_single(rec, except_bot, source, data); + } +} + +void botnet_send_cmd(BOTNET_REC *botnet, const char *source, + const char *target, const char *data) +{ + GNode *node; + char *str; + + node = bot_find_path(botnet, target); + g_return_if_fail(node != NULL); + + str = g_strdup_printf("%s %s %s", source != NULL ? source : + botnet->nick, target, data); + bot_send_cmd(node->data, str); + g_free(str); +} + BOTNET_REC *botnet_find(const char *name) { GSList *tmp; @@ -415,6 +451,35 @@ static void botnet_event(BOT_REC *bot, const char *data) g_free(params); } +/* broadcast the signal forward */ +static void botnet_event_broadcast(BOT_REC *bot, const char *data) +{ + char *params, *source, *target, *command; + + if (!bot->connected) + return; + + params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, + &source, &target, &command); + + if (g_strcasecmp(target, bot->botnet->nick) == 0) { + /* message was for us */ + g_free(params); + return; + } + + if (*target == '-' && target[1] == '\0') { + /* broadcast */ + botnet_broadcast(bot->botnet, bot, source, command); + } else { + /* send to specified target */ + botnet_send_cmd(bot->botnet, source, target, command); + } + + g_free(params); +} + +#if 0 static void botnet_event_bcast(BOT_REC *bot, const char *data, const char *sender) { char *str; @@ -424,6 +489,7 @@ static void botnet_event_bcast(BOT_REC *bot, const char *data, const char *sende botnet_broadcast(bot->botnet, bot, sender, str); g_free(str); } +#endif static void botnet_event_master(BOT_REC *bot, const char *data, const char *sender) { @@ -450,6 +516,8 @@ static void botnet_event_master(BOT_REC *bot, const char *data, const char *send str = g_strdup_printf("MASTER %s", master->nick); botnet_broadcast(botnet, bot, sender, str); g_free(str); + + signal_stop_by_name("botnet event"); } static void botnet_config_read_ips(BOT_DOWNLINK_REC *rec, CONFIG_NODE *node) @@ -601,7 +669,8 @@ void botnet_init(void) botnet_connection_init(); signal_add("botnet event", (SIGNAL_FUNC) botnet_event); - signal_add("botnet event bcast", (SIGNAL_FUNC) botnet_event_bcast); + signal_add_last("botnet event", (SIGNAL_FUNC) botnet_event_broadcast); + //signal_add("botnet event bcast", (SIGNAL_FUNC) botnet_event_bcast); signal_add("botnet event master", (SIGNAL_FUNC) botnet_event_master); command_bind("botnet", NULL, (SIGNAL_FUNC) cmd_botnet); @@ -616,7 +685,8 @@ void botnet_deinit(void) botnet_connection_deinit(); signal_remove("botnet event", (SIGNAL_FUNC) botnet_event); - signal_remove("botnet event bcast", (SIGNAL_FUNC) botnet_event_bcast); + signal_remove("botnet event", (SIGNAL_FUNC) botnet_event_broadcast); + //signal_remove("botnet event bcast", (SIGNAL_FUNC) botnet_event_bcast); signal_remove("botnet event master", (SIGNAL_FUNC) botnet_event_master); command_unbind("botnet", (SIGNAL_FUNC) cmd_botnet); } diff --git a/src/irc/bot/botnet.h b/src/irc/bot/botnet.h index 722ba8be..22765f1d 100644 --- a/src/irc/bot/botnet.h +++ b/src/irc/bot/botnet.h @@ -97,10 +97,13 @@ void bot_send_cmd(BOT_REC *bot, char *data); void bot_send_cmdv(BOT_REC *bot, char *format, ...); /* broadcast a message to everyone in bot network, except for `except_bot' - if it's not NULL */ + if it's not NULL. If botnet is NULL, the message is sent to all botnets. */ void botnet_broadcast(BOTNET_REC *botnet, BOT_REC *except_bot, const char *source, const char *data); +void botnet_send_cmd(BOTNET_REC *botnet, const char *source, + const char *target, const char *data); + BOT_REC *botnet_find_master(BOTNET_REC *botnet, BOT_REC *old_master); void botnet_set_master(BOTNET_REC *botnet, BOT_REC *bot);