diff --git a/src/irc/bot/Makefile.am b/src/irc/bot/Makefile.am index d2629d89..b7210f23 100644 --- a/src/irc/bot/Makefile.am +++ b/src/irc/bot/Makefile.am @@ -8,18 +8,18 @@ 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 \ - botnet-connection.c + botnet-connection.c \ + botnet-users.c noinst_HEADERS = \ bot.h \ + bot-users.h \ botnet.h \ - bot-commands.h \ - bot-users.h + botnet-users.h EXTRA_DIST = \ users.sample \ diff --git a/src/irc/bot/bot-irc-commands.c b/src/irc/bot/bot-irc-commands.c index 813e46fe..a5b88337 100644 --- a/src/irc/bot/bot-irc-commands.c +++ b/src/irc/bot/bot-irc-commands.c @@ -29,7 +29,7 @@ #include "masks.h" #include "bot-users.h" -#include "bot-commands.h" +#include "botnet-users.h" static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address) diff --git a/src/irc/bot/bot-users.c b/src/irc/bot/bot-users.c index 925268c8..b38a514b 100644 --- a/src/irc/bot/bot-users.c +++ b/src/irc/bot/bot-users.c @@ -98,6 +98,8 @@ static void botuser_config_save(USER_REC *user) GSList *tmp; char *str; + user->last_modify = time(NULL); + node = config_node_traverse(userconfig, "users", TRUE); node = config_node_section(node, user->nick, NODE_TYPE_BLOCK); @@ -107,6 +109,7 @@ static void botuser_config_save(USER_REC *user) g_free_not_null(str); config_node_set_str(userconfig, node, "password", user->password); + config_node_set_int(node, "last_modify", (int) user->last_modify); /* Save masks */ if (user->masks == NULL) @@ -350,6 +353,11 @@ int botuser_verify_password(USER_REC *user, const char *password) return strcmp(user->password, pass) == 0; } +void botuser_save(const char *fname) +{ + config_write(userconfig, fname, 0600); +} + static void event_massjoin(CHANNEL_REC *channel, GSList *nicks) { USER_REC *user; @@ -473,9 +481,10 @@ static void botuser_config_read_user(CONFIG_NODE *node) user->nick = g_strdup(node->key); g_hash_table_insert(users, user->nick, user); - /* password, flags */ + /* password, flags, modify time */ user->password = g_strdup(config_node_get_str(node, "password", NULL)); user->flags = botuser_flags2value(config_node_get_str(node, "flags", "")); + user->last_modify = (time_t) config_node_get_int(node, "last_modify", 0); /* get masks */ user->masks = NULL; diff --git a/src/irc/bot/bot-users.h b/src/irc/bot/bot-users.h index ab498995..8023e9a6 100644 --- a/src/irc/bot/bot-users.h +++ b/src/irc/bot/bot-users.h @@ -32,6 +32,7 @@ typedef struct { int not_flags; /* active not_flags based on current host mask, botuser_find() updates this */ + time_t last_modify; /* last time the user settings were modified */ } USER_REC; int botuser_flags2value(const char *flags); @@ -50,4 +51,6 @@ 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); +void botuser_save(const char *fname); + #endif diff --git a/src/irc/bot/bot.c b/src/irc/bot/bot.c index 4e9cb831..7679b155 100644 --- a/src/irc/bot/bot.c +++ b/src/irc/bot/bot.c @@ -20,9 +20,6 @@ #include "module.h" -void bot_commands_deinit(void); -void bot_commands_init(void); - void bot_irc_commands_deinit(void); void bot_irc_commands_init(void); @@ -38,7 +35,6 @@ void botnet_deinit(void); void irc_bot_init(void) { bot_users_init(); - bot_commands_init(); bot_irc_commands_init(); bot_events_init(); botnet_init(); @@ -47,7 +43,6 @@ void irc_bot_init(void) 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 68c33d0a..387cce45 100644 --- a/src/irc/bot/botnet-connection.c +++ b/src/irc/bot/botnet-connection.c @@ -28,6 +28,7 @@ #include "lib-config/iconfig.h" #include "botnet.h" +#include "bot-users.h" #define BOTNET_RECONNECT_TIME (60*5) @@ -368,6 +369,7 @@ static void botnet_connect_event_uplink(BOT_REC *bot, const char *data) static void botnet_event(BOT_REC *bot, const char *data) { BOT_DOWNLINK_REC *downlink; + char *fname; g_return_if_fail(bot != NULL); g_return_if_fail(data != NULL); @@ -423,6 +425,14 @@ static void botnet_event(BOT_REC *bot, const char *data) botnet_send_links(bot, FALSE); botnet_send_links(bot, TRUE); bot_send_cmdv(bot, "%s - MASTER %s", bot->botnet->nick, bot->botnet->master->nick); + + /* send our current user configuration */ + fname = g_strdup_printf("%s/.irssi/users.temp", g_get_home_dir()); + botuser_save(fname); + botnet_send_file(bot->botnet, bot->nick, fname); + g_free(fname); + + /* send sync msg */ bot_send_cmdv(bot, "%s - SYNC", bot->botnet->nick); return; } diff --git a/src/irc/bot/bot-commands.c b/src/irc/bot/botnet-users.c similarity index 98% rename from src/irc/bot/bot-commands.c rename to src/irc/bot/botnet-users.c index 67d5855f..fda58723 100644 --- a/src/irc/bot/bot-commands.c +++ b/src/irc/bot/botnet-users.c @@ -1,5 +1,5 @@ /* - bot-commands.c : IRC bot plugin for irssi + botnet-users.c : IRC bot plugin for irssi Copyright (C) 1999-2000 Timo Sirainen @@ -185,7 +185,7 @@ static void botnet_event_user_pass(BOT_REC *bot, const char *data, const char *s g_free(params); } -void bot_commands_init(void) +void botnet_users_init(void) { signal_add("botnet event user_add", (SIGNAL_FUNC) botnet_event_user_add); signal_add("botnet event user_flags", (SIGNAL_FUNC) botnet_event_user_flags); @@ -195,7 +195,7 @@ void bot_commands_init(void) signal_add("botnet event user_pass", (SIGNAL_FUNC) botnet_event_user_pass); } -void bot_commands_deinit(void) +void botnet_users_deinit(void) { signal_remove("botnet event user_add", (SIGNAL_FUNC) botnet_event_user_add); signal_remove("botnet event user_flags", (SIGNAL_FUNC) botnet_event_user_flags); diff --git a/src/irc/bot/bot-commands.h b/src/irc/bot/botnet-users.h similarity index 89% rename from src/irc/bot/bot-commands.h rename to src/irc/bot/botnet-users.h index 4fa35d98..303a0890 100644 --- a/src/irc/bot/bot-commands.h +++ b/src/irc/bot/botnet-users.h @@ -1,5 +1,5 @@ -#ifndef __BOT_COMMANDS_H -#define __BOT_COMMANDS_H +#ifndef __BOTNET_USERS_H +#define __BOTNET_USERS_H void botcmd_user_add(const char *nick); void botcmd_user_set_flags(USER_REC *user, int flags); diff --git a/src/irc/bot/botnet.c b/src/irc/bot/botnet.c index e85a9857..4f74a867 100644 --- a/src/irc/bot/botnet.c +++ b/src/irc/bot/botnet.c @@ -32,6 +32,9 @@ void botnet_connection_init(void); void botnet_connection_deinit(void); +void botnet_users_deinit(void); +void botnet_users_init(void); + GSList *botnets; void bot_send_cmd(BOT_REC *bot, char *data) @@ -121,6 +124,73 @@ void botnet_send_cmd(BOTNET_REC *botnet, const char *source, g_free(str); } +static void escape_buffer(char *buffer, int len) +{ + char *dest, *tempbuf, *p; + + dest = buffer; + tempbuf = p = g_malloc(len*2+2); + while (len > 0) { + if (*buffer == '\0') { + *p++ = '\\'; + *p++ = '0'; + } else if (*buffer == '\r') { + *p++ = '\\'; + *p++ = 'r'; + } else if (*buffer == '\n') { + *p++ = '\\'; + *p++ = 'n'; + } else if (*buffer == '\\') { + *p++ = '\\'; + *p++ = '\\'; + } else { + *p++ = *buffer; + } + len--; buffer++; + } + *p++ = '\0'; + + len = (int) (p-tempbuf); + memcpy(dest, tempbuf, len); + g_free(tempbuf); +} + +int botnet_send_file(BOTNET_REC *botnet, const char *target, const char *fname) +{ + GNode *node; + GString *str; + char buffer[1024]; + int f, len; + + node = bot_find_path(botnet, target); + if (node == NULL) { + g_warning("Can't find route for target %s", target); + return FALSE; + } + + f = open(fname, O_RDONLY); + if (f == -1) return FALSE; + + str = g_string_new(NULL); + + g_string_sprintf(str, "%s %s FILE %s", botnet->nick, target, g_basename(fname)); + bot_send_cmd(node->data, str->str); + + while ((len = read(f, buffer, sizeof(buffer)/2-2)) > 0) { + escape_buffer(buffer, len); + + g_string_sprintf(str, "%s %s FILE %s", botnet->nick, target, buffer); + bot_send_cmd(node->data, str->str); + } + + g_string_sprintf(str, "%s %s FILE", botnet->nick, target); + bot_send_cmd(node->data, str->str); + g_string_free(str, TRUE); + + close(f); + return TRUE; +} + BOTNET_REC *botnet_find(const char *name) { GSList *tmp; @@ -485,18 +555,6 @@ static void botnet_event_broadcast(BOT_REC *bot, const char *data) g_free(params); } -#if 0 -static void botnet_event_bcast(BOT_REC *bot, const char *data, const char *sender) -{ - char *str; - - /* broadcast message to all bots */ - str = g_strdup_printf("BCAST %s", data); - 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) { BOTNET_REC *botnet; @@ -526,6 +584,72 @@ static void botnet_event_master(BOT_REC *bot, const char *data, const char *send signal_stop_by_name("botnet event"); } +static int unescape_data(const char *input, char *output) +{ + int len; + + len = 0; + while (*input != '\0') { + if (*input != '\\') + *output++ = *input; + else { + input++; + g_return_val_if_fail(*input != '\0', len); + switch (*input) { + case '\\': + *output++ = '\\'; + break; + case '0': + *output++ = '\0'; + break; + case 'r': + *output++ = '\r'; + break; + case 'n': + *output++ = '\n'; + break; + } + } + input++; + len++; + } + + return len; +} + +static void botnet_event_file(BOT_REC *bot, const char *data, const char *sender, const char *target) +{ + GNode *node; + char *tempbuf, *str; + int len; + + if (g_strcasecmp(target, bot->botnet->nick) != 0) + return; + + node = bot_find_nick(bot->botnet, sender); + g_return_if_fail(node != NULL); + + bot = node->data; + if (bot->file_handle <= 0) { + /* first line - data contains file name */ + str = g_strdup_printf("%s/.irssi/%s", g_get_home_dir(), data); + bot->file_handle = open(str, O_CREAT|O_TRUNC|O_WRONLY, 0600); + g_free(str); + } else if (*data == '\0') { + /* no data - end of file */ + if (bot->file_handle > 0) { + close(bot->file_handle); + bot->file_handle = -1; + } + } else { + /* file data */ + tempbuf = g_malloc(strlen(data)*2+2); + len = unescape_data(data, tempbuf); + write(bot->file_handle, tempbuf, len); + g_free(tempbuf); + } +} + static void botnet_config_read_ips(BOT_DOWNLINK_REC *rec, CONFIG_NODE *node) { GSList *tmp; @@ -673,11 +797,12 @@ void botnet_init(void) { botnet_config_read(); botnet_connection_init(); + botnet_users_init(); signal_add("botnet event", (SIGNAL_FUNC) botnet_event); 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); + signal_add("botnet event file", (SIGNAL_FUNC) botnet_event_file); command_bind("botnet", NULL, (SIGNAL_FUNC) cmd_botnet); autoconnect_botnets(); @@ -689,10 +814,11 @@ void botnet_deinit(void) botnet_destroy(botnets->data); botnet_connection_deinit(); + botnet_users_deinit(); signal_remove("botnet event", (SIGNAL_FUNC) botnet_event); 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); + signal_remove("botnet event file", (SIGNAL_FUNC) botnet_event_file); command_unbind("botnet", (SIGNAL_FUNC) cmd_botnet); } diff --git a/src/irc/bot/botnet.h b/src/irc/bot/botnet.h index 22765f1d..da022b22 100644 --- a/src/irc/bot/botnet.h +++ b/src/irc/bot/botnet.h @@ -48,6 +48,8 @@ typedef struct { int read_tag; void *buffer; + int file_handle; /* if bot is sending a file to us */ + GSList *ircnets; } BOT_REC; @@ -104,6 +106,8 @@ void botnet_broadcast(BOTNET_REC *botnet, BOT_REC *except_bot, void botnet_send_cmd(BOTNET_REC *botnet, const char *source, const char *target, const char *data); +int botnet_send_file(BOTNET_REC *botnet, const char *target, const char *fname); + BOT_REC *botnet_find_master(BOTNET_REC *botnet, BOT_REC *old_master); void botnet_set_master(BOTNET_REC *botnet, BOT_REC *bot);