From e395e87dedd9aa85f05e5c74330a76f1ef700371 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Sat, 26 Aug 2000 15:39:44 +0000 Subject: Lots of moving stuff around - hopefully I didn't break too much :) git-svn-id: http://svn.irssi.org/repos/irssi/trunk@632 dbcabf3a-b0e7-0310-adc4-f8d773084564 --- src/core/Makefile.am | 41 +- src/core/channel-rec.h | 21 + src/core/channels-setup.c | 170 ++++++++ src/core/channels-setup.h | 33 ++ src/core/channels.c | 116 +++++ src/core/channels.h | 31 ++ src/core/chatnet-rec.h | 12 + src/core/chatnets.c | 148 +++++++ src/core/chatnets.h | 37 ++ src/core/commands.c | 9 +- src/core/core.c | 20 +- src/core/masks.c | 137 ++++++ src/core/masks.h | 13 + src/core/memdebug.c | 53 ++- src/core/misc.c | 4 +- src/core/misc.h | 2 +- src/core/modules.c | 21 +- src/core/nicklist.c | 268 ++++++++++++ src/core/nicklist.h | 50 +++ src/core/queries.c | 124 ++++++ src/core/queries.h | 32 ++ src/core/query-rec.h | 9 + src/core/server-connect-rec.h | 26 ++ src/core/server-rec.h | 50 +++ src/core/server-redirect.c | 356 --------------- src/core/server-redirect.h | 38 -- src/core/server-setup-rec.h | 19 + src/core/server.c | 304 ------------- src/core/server.h | 83 ---- src/core/servers-reconnect.c | 356 +++++++++++++++ src/core/servers-reconnect.h | 20 + src/core/servers-redirect.c | 359 +++++++++++++++ src/core/servers-redirect.h | 38 ++ src/core/servers-setup.c | 456 ++++++++++++++++++++ src/core/servers-setup.h | 46 ++ src/core/servers.c | 403 +++++++++++++++++ src/core/servers.h | 52 +++ src/core/settings.h | 1 + src/core/signals.c | 3 +- src/core/special-vars.c | 125 +++++- src/core/special-vars.h | 17 +- src/core/window-item-def.h | 9 + src/core/window-item-rec.h | 14 + src/fe-common/core/Makefile.am | 4 +- src/fe-common/core/fe-common-core.c | 2 + src/fe-common/core/fe-log.c | 2 +- src/fe-common/core/fe-server.c | 8 +- src/fe-common/core/fe-settings.c | 2 +- src/fe-common/core/hilight-text.c | 2 +- src/fe-common/core/printtext.c | 2 +- src/fe-common/core/window-activity.c | 2 +- src/fe-common/core/window-commands.c | 4 +- src/fe-common/core/window-items.c | 2 +- src/fe-common/core/window-save.c | 2 +- src/fe-common/core/windows.c | 2 +- src/fe-common/core/windows.h | 24 +- src/fe-common/irc/Makefile.am | 8 +- src/fe-common/irc/dcc/fe-dcc.c | 15 +- src/fe-common/irc/fe-channels.c | 30 +- src/fe-common/irc/fe-common-irc.c | 12 +- src/fe-common/irc/fe-ctcp.c | 4 +- src/fe-common/irc/fe-events-numeric.c | 12 +- src/fe-common/irc/fe-events.c | 34 +- src/fe-common/irc/fe-ignore.c | 2 +- src/fe-common/irc/fe-irc-commands.c | 57 +-- src/fe-common/irc/fe-irc-server.c | 34 +- src/fe-common/irc/fe-ircnet.c | 17 +- src/fe-common/irc/fe-netjoin.c | 2 +- src/fe-common/irc/fe-netsplit.c | 2 +- src/fe-common/irc/fe-queries.c | 330 ++++++++++++++ src/fe-common/irc/fe-queries.h | 7 + src/fe-common/irc/fe-query.c | 331 -------------- src/fe-common/irc/fe-query.h | 7 - src/fe-common/irc/flood/fe-flood.c | 2 +- src/fe-common/irc/irc-completion.c | 43 +- src/fe-common/irc/irc-window-activity.c | 4 +- src/fe-common/irc/notifylist/fe-notifylist.c | 25 +- src/fe-text/gui-readline.c | 2 +- src/fe-text/gui-special-vars.c | 6 +- src/fe-text/gui-textwidget.c | 2 +- src/fe-text/gui-windows.c | 5 +- src/fe-text/gui-windows.h | 2 +- src/fe-text/irssi.c | 2 +- src/fe-text/statusbar-items.c | 16 +- src/fe-text/statusbar.c | 2 +- src/irc/Makefile.am | 4 +- src/irc/bot/bot-events.c | 14 +- src/irc/bot/bot-irc-commands.c | 4 +- src/irc/bot/bot-users.c | 6 +- src/irc/bot/botnet-users.c | 2 +- src/irc/core/Makefile.am | 42 +- src/irc/core/bans.c | 39 +- src/irc/core/bans.h | 8 +- src/irc/core/channel-events.c | 28 +- src/irc/core/channel-rejoin.c | 30 +- src/irc/core/channels-query.c | 63 ++- src/irc/core/channels-setup.c | 253 ----------- src/irc/core/channels-setup.h | 28 -- src/irc/core/channels.c | 228 ---------- src/irc/core/channels.h | 62 --- src/irc/core/ctcp.c | 61 ++- src/irc/core/ignore.c | 16 +- src/irc/core/irc-channels-setup.c | 116 +++++ src/irc/core/irc-channels.c | 213 +++++++++ src/irc/core/irc-channels.h | 42 ++ src/irc/core/irc-chatnets.c | 132 ++++++ src/irc/core/irc-chatnets.h | 33 ++ src/irc/core/irc-commands.c | 163 +++---- src/irc/core/irc-core.c | 14 +- src/irc/core/irc-log.c | 2 +- src/irc/core/irc-masks.c | 97 +++++ src/irc/core/irc-masks.h | 13 + src/irc/core/irc-nicklist.c | 401 +++++++++++++++++ src/irc/core/irc-nicklist.h | 15 + src/irc/core/irc-queries.c | 109 +++++ src/irc/core/irc-queries.h | 25 ++ src/irc/core/irc-rawlog.c | 3 +- src/irc/core/irc-server.c | 500 --------------------- src/irc/core/irc-server.h | 156 ------- src/irc/core/irc-servers-reconnect.c | 118 +++++ src/irc/core/irc-servers-setup.c | 196 +++++++++ src/irc/core/irc-servers-setup.h | 21 + src/irc/core/irc-servers.c | 447 +++++++++++++++++++ src/irc/core/irc-servers.h | 101 +++++ src/irc/core/irc-special-vars.c | 173 ++------ src/irc/core/irc.c | 20 +- src/irc/core/irc.h | 44 +- src/irc/core/ircnet-setup.c | 184 -------- src/irc/core/ircnet-setup.h | 33 -- src/irc/core/lag.c | 4 +- src/irc/core/masks.c | 186 -------- src/irc/core/masks.h | 15 - src/irc/core/massjoin.c | 53 +-- src/irc/core/mode-lists.c | 28 +- src/irc/core/mode-lists.h | 14 +- src/irc/core/modes.c | 100 +++-- src/irc/core/modes.h | 8 +- src/irc/core/netsplit.c | 7 +- src/irc/core/nicklist.c | 623 --------------------------- src/irc/core/nicklist.h | 48 --- src/irc/core/query.c | 160 ------- src/irc/core/query.h | 35 -- src/irc/core/server-idle.c | 8 +- src/irc/core/server-idle.h | 2 +- src/irc/core/server-reconnect.c | 391 ----------------- src/irc/core/server-reconnect.h | 20 - src/irc/core/server-setup.c | 464 -------------------- src/irc/core/server-setup.h | 50 --- src/irc/dcc/dcc-chat.c | 15 +- src/irc/dcc/dcc-files.c | 4 +- src/irc/dcc/dcc.c | 14 +- src/irc/flood/autoignore.c | 2 +- src/irc/flood/flood.c | 2 +- src/irc/notifylist/module.h | 2 +- src/irc/notifylist/notify-ison.c | 8 +- src/irc/notifylist/notify-setup.c | 2 +- src/irc/notifylist/notify-whois.c | 12 +- src/irc/notifylist/notifylist.c | 16 +- src/lib-config/Makefile.am | 4 +- src/lib-config/get.c | 16 + src/lib-config/iconfig.h | 4 + src/lib-config/parse.c | 7 +- src/lib-config/set.c | 20 +- src/lib-popt/Makefile.am | 4 +- src/perl/Makefile.am | 4 +- src/perl/xs/Irssi-query.xs | 4 +- src/perl/xs/Irssi-window.xs | 6 +- src/perl/xs/module.h | 14 +- 168 files changed, 6408 insertions(+), 5426 deletions(-) create mode 100644 src/core/channel-rec.h create mode 100644 src/core/channels-setup.c create mode 100644 src/core/channels-setup.h create mode 100644 src/core/channels.c create mode 100644 src/core/channels.h create mode 100644 src/core/chatnet-rec.h create mode 100644 src/core/chatnets.c create mode 100644 src/core/chatnets.h create mode 100644 src/core/masks.c create mode 100644 src/core/masks.h create mode 100644 src/core/nicklist.c create mode 100644 src/core/nicklist.h create mode 100644 src/core/queries.c create mode 100644 src/core/queries.h create mode 100644 src/core/query-rec.h create mode 100644 src/core/server-connect-rec.h create mode 100644 src/core/server-rec.h delete mode 100644 src/core/server-redirect.c delete mode 100644 src/core/server-redirect.h create mode 100644 src/core/server-setup-rec.h delete mode 100644 src/core/server.c delete mode 100644 src/core/server.h create mode 100644 src/core/servers-reconnect.c create mode 100644 src/core/servers-reconnect.h create mode 100644 src/core/servers-redirect.c create mode 100644 src/core/servers-redirect.h create mode 100644 src/core/servers-setup.c create mode 100644 src/core/servers-setup.h create mode 100644 src/core/servers.c create mode 100644 src/core/servers.h create mode 100644 src/core/window-item-def.h create mode 100644 src/core/window-item-rec.h create mode 100644 src/fe-common/irc/fe-queries.c create mode 100644 src/fe-common/irc/fe-queries.h delete mode 100644 src/fe-common/irc/fe-query.c delete mode 100644 src/fe-common/irc/fe-query.h delete mode 100644 src/irc/core/channels-setup.c delete mode 100644 src/irc/core/channels-setup.h delete mode 100644 src/irc/core/channels.c delete mode 100644 src/irc/core/channels.h create mode 100644 src/irc/core/irc-channels-setup.c create mode 100644 src/irc/core/irc-channels.c create mode 100644 src/irc/core/irc-channels.h create mode 100644 src/irc/core/irc-chatnets.c create mode 100644 src/irc/core/irc-chatnets.h create mode 100644 src/irc/core/irc-masks.c create mode 100644 src/irc/core/irc-masks.h create mode 100644 src/irc/core/irc-nicklist.c create mode 100644 src/irc/core/irc-nicklist.h create mode 100644 src/irc/core/irc-queries.c create mode 100644 src/irc/core/irc-queries.h delete mode 100644 src/irc/core/irc-server.c delete mode 100644 src/irc/core/irc-server.h create mode 100644 src/irc/core/irc-servers-reconnect.c create mode 100644 src/irc/core/irc-servers-setup.c create mode 100644 src/irc/core/irc-servers-setup.h create mode 100644 src/irc/core/irc-servers.c create mode 100644 src/irc/core/irc-servers.h delete mode 100644 src/irc/core/ircnet-setup.c delete mode 100644 src/irc/core/ircnet-setup.h delete mode 100644 src/irc/core/masks.c delete mode 100644 src/irc/core/masks.h delete mode 100644 src/irc/core/nicklist.c delete mode 100644 src/irc/core/nicklist.h delete mode 100644 src/irc/core/query.c delete mode 100644 src/irc/core/query.h delete mode 100644 src/irc/core/server-reconnect.c delete mode 100644 src/irc/core/server-reconnect.h delete mode 100644 src/irc/core/server-setup.c delete mode 100644 src/irc/core/server-setup.h (limited to 'src') diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 2361419f..d7534ee5 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -1,4 +1,4 @@ -noinst_LTLIBRARIES = libcore.la +noinst_LIBRARIES = libcore.a INCLUDES = \ $(GLIB_CFLAGS) \ @@ -13,13 +13,17 @@ else memdebug_src= endif -libcore_la_SOURCES = \ +libcore_a_SOURCES = \ args.c \ + channels.c \ + channels-setup.c \ commands.c \ + chatnets.c \ core.c \ levels.c \ line-split.c \ log.c \ + masks.c \ $(memdebug_src) \ misc.c \ modules.c \ @@ -27,21 +31,38 @@ libcore_la_SOURCES = \ net-nonblock.c \ net-sendbuffer.c \ network.c \ + nicklist.c \ pidwait.c \ + queries.c \ rawlog.c \ - server.c \ - server-redirect.c \ + servers.c \ + servers-reconnect.c \ + servers-redirect.c \ + servers-setup.c \ settings.c \ signals.c \ special-vars.c +structure_headers = \ + chatnet-rec.h \ + channel-rec.h \ + query-rec.h \ + server-rec.h \ + server-setup-rec.h \ + server-connect-rec.h \ + window-item-rec.h + noinst_HEADERS = \ args.h \ + channels.h \ + channels-setup.h \ commands.h \ + chatnets.h \ core.h \ levels.h \ line-split.h \ log.h \ + masks.h \ memdebug.h \ misc.h \ module.h \ @@ -51,13 +72,19 @@ noinst_HEADERS = \ net-nonblock.h \ net-sendbuffer.h \ network.h \ + nicklist.h \ pidwait.h \ + queries.h \ rawlog.h \ - server.h \ - server-redirect.h \ + servers.h \ + servers-reconnect.h \ + servers-redirect.h \ + servers-setup.h \ settings.h \ signals.h \ - special-vars.h + special-vars.h \ + window-item-def.h \ + $(structure_headers) EXTRA_DIST = \ memdebug.c diff --git a/src/core/channel-rec.h b/src/core/channel-rec.h new file mode 100644 index 00000000..d3b3cd0d --- /dev/null +++ b/src/core/channel-rec.h @@ -0,0 +1,21 @@ +/* CHANNEL_REC definition, used for inheritance */ + +#include "window-item-rec.h" + +char *topic; +GHashTable *nicks; /* list of nicks */ + +int no_modes:1; /* channel doesn't support modes */ +char *mode; +int limit; /* user limit */ +char *key; /* password key */ + +int chanop:1; /* You're a channel operator */ +int names_got:1; /* Received /NAMES list */ +int wholist:1; /* WHO list got */ +int synced:1; /* Channel synced - all queries done */ + +int joined:1; /* Have we even received JOIN event for this channel? */ +int left:1; /* You just left the channel */ +int kicked:1; /* You just got kicked */ +int destroying:1; diff --git a/src/core/channels-setup.c b/src/core/channels-setup.c new file mode 100644 index 00000000..6867568d --- /dev/null +++ b/src/core/channels-setup.c @@ -0,0 +1,170 @@ +/* + channels-setup.c : 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 "lib-config/iconfig.h" +#include "settings.h" + +#include "channels.h" +#include "channels-setup.h" +#include "servers-setup.h" + +GSList *setupchannels; + +static CHANNEL_SETUP_REC *channel_setup_read(CONFIG_NODE *node) +{ + CHANNEL_SETUP_REC *rec; + char *channel, *password, *botmasks, *autosendcmd; + + g_return_val_if_fail(node != NULL, NULL); + + channel = config_node_get_str(node, "name", NULL); + if (channel == NULL) { + /* missing information.. */ + return NULL; + } + + password = config_node_get_str(node, "password", NULL); + botmasks = config_node_get_str(node, "botmasks", NULL); + autosendcmd = config_node_get_str(node, "autosendcmd", NULL); + + rec = g_new(CHANNEL_SETUP_REC, 1); + rec->autojoin = config_node_get_bool(node, "autojoin", FALSE); + rec->name = g_strdup(channel); + rec->chatnet = g_strdup(config_node_get_str(node, "chatnet", NULL)); + rec->password = (password == NULL || *password == '\0') ? NULL : g_strdup(password); + rec->botmasks = (botmasks == NULL || *botmasks == '\0') ? NULL : g_strdup(botmasks); + rec->autosendcmd = (autosendcmd == NULL || *autosendcmd == '\0') ? NULL : g_strdup(autosendcmd); + + setupchannels = g_slist_append(setupchannels, rec); + signal_emit("channel setup created", 2, rec, node); + return rec; +} + +static void channel_setup_save(CHANNEL_SETUP_REC *channel) +{ + CONFIG_NODE *parentnode, *node; + int index; + + index = g_slist_index(setupchannels, channel); + + parentnode = iconfig_node_traverse("(channels", TRUE); + node = config_node_index(parentnode, index); + if (node == NULL) + node = config_node_section(parentnode, NULL, NODE_TYPE_BLOCK); + + iconfig_node_clear(node); + iconfig_node_set_str(node, "name", channel->name); + iconfig_node_set_str(node, "chatnet", channel->chatnet); + if (channel->autojoin) + config_node_set_bool(node, "autojoin", TRUE); + iconfig_node_set_str(node, "password", channel->password); + iconfig_node_set_str(node, "botmasks", channel->botmasks); + iconfig_node_set_str(node, "autosendcmd", channel->autosendcmd); +} + +static void channel_config_remove(CHANNEL_SETUP_REC *channel) +{ + CONFIG_NODE *node; + + node = iconfig_node_traverse("channels", FALSE); + if (node != NULL) iconfig_node_list_remove(node, g_slist_index(setupchannels, channel)); +} + +void channels_setup_create(CHANNEL_SETUP_REC *channel) +{ + if (g_slist_find(setupchannels, channel) == NULL) + setupchannels = g_slist_append(setupchannels, channel); + channel_setup_save(channel); + + signal_emit("channel setup created", 1, channel); +} + +static void channels_setup_destroy_rec(CHANNEL_SETUP_REC *channel) +{ + g_return_if_fail(channel != NULL); + + setupchannels = g_slist_remove(setupchannels, channel); + signal_emit("channel setup destroyed", 1, channel); + + g_free(channel->name); + g_free(channel->chatnet); + g_free_not_null(channel->password); + g_free_not_null(channel->botmasks); + g_free_not_null(channel->autosendcmd); + g_free(channel); +} + +void channels_setup_destroy(CHANNEL_SETUP_REC *channel) +{ + channel_config_remove(channel); + channels_setup_destroy_rec(channel); +} + +CHANNEL_SETUP_REC *channels_setup_find(const char *channel, const char *chatnet) +{ + GSList *tmp; + + g_return_val_if_fail(channel != NULL, NULL); + + for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) { + CHANNEL_SETUP_REC *rec = tmp->data; + + if (g_strcasecmp(rec->name, channel) == 0 && + channel_chatnet_match(rec->chatnet, chatnet)) + return rec; + } + + return NULL; +} + +static void channels_read_config(void) +{ + CONFIG_NODE *node; + GSList *tmp; + + while (setupchannels != NULL) + channels_setup_destroy_rec(setupchannels->data); + + /* Read channels */ + node = iconfig_node_traverse("channels", FALSE); + if (node != NULL) { + for (tmp = node->value; tmp != NULL; tmp = tmp->next) + channel_setup_read(tmp->data); + } +} + +void channels_setup_init(void) +{ + source_host_ok = FALSE; + + signal_add("setup reread", (SIGNAL_FUNC) channels_read_config); + signal_add("irssi init read settings", (SIGNAL_FUNC) channels_read_config); +} + +void channels_setup_deinit(void) +{ + while (setupchannels != NULL) + channels_setup_destroy(setupchannels->data); + + signal_remove("setup reread", (SIGNAL_FUNC) channels_read_config); + signal_remove("irssi init read settings", (SIGNAL_FUNC) channels_read_config); +} diff --git a/src/core/channels-setup.h b/src/core/channels-setup.h new file mode 100644 index 00000000..e30893fe --- /dev/null +++ b/src/core/channels-setup.h @@ -0,0 +1,33 @@ +#ifndef __CHANNELS_SETUP_H +#define __CHANNELS_SETUP_H + +#include "modules.h" + +typedef struct { + char *name; + char *chatnet; + char *password; + + char *botmasks; + char *autosendcmd; + + int autojoin:1; + GHashTable *module_data; +} CHANNEL_SETUP_REC; + +extern GSList *setupchannels; + +void channels_setup_init(void); +void channels_setup_deinit(void); + +void channels_setup_create(CHANNEL_SETUP_REC *channel); +void channels_setup_destroy(CHANNEL_SETUP_REC *channel); + +CHANNEL_SETUP_REC *channels_setup_find(const char *channel, + const char *chatnet); + +#define channel_chatnet_match(rec, chatnet) \ + ((rec) == NULL || (rec)[0] == '\0' || \ + ((chatnet) != NULL && g_strcasecmp(rec, chatnet) == 0)) + +#endif diff --git a/src/core/channels.c b/src/core/channels.c new file mode 100644 index 00000000..bc3d8c0b --- /dev/null +++ b/src/core/channels.c @@ -0,0 +1,116 @@ +/* + channel.c : 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 "misc.h" + +#include "channels.h" + +typedef CHANNEL_REC *(*CHANNEL_FIND_FUNC)(SERVER_REC *, const char *); + +GSList *channels; /* List of all channels */ + +void channel_init(CHANNEL_REC *channel, int automatic) +{ + g_return_if_fail(channel != NULL); + g_return_if_fail(channel->name != NULL); + + channels = g_slist_append(channels, channel); + if (channel->server != NULL) { + channel->server->channels = + g_slist_append(channel->server->channels, channel); + } + + MODULE_DATA_INIT(channel); + channel->type = module_get_uniq_id("CHANNEL", 0); + channel->mode = g_strdup(""); + channel->createtime = time(NULL); + + signal_emit("channel created", 2, channel, GINT_TO_POINTER(automatic)); +} + +void channel_destroy(CHANNEL_REC *channel) +{ + g_return_if_fail(IS_CHANNEL(channel)); + + if (channel->destroying) return; + channel->destroying = TRUE; + + channels = g_slist_remove(channels, channel); + if (channel->server != NULL) + channel->server->channels = g_slist_remove(channel->server->channels, channel); + signal_emit("channel destroyed", 1, channel); + + MODULE_DATA_DEINIT(channel); + g_free_not_null(channel->topic); + g_free_not_null(channel->key); + g_free(channel->name); + g_free(channel); +} + +static CHANNEL_REC *channel_find_server(SERVER_REC *server, + const char *name) +{ + GSList *tmp; + + g_return_val_if_fail(IS_SERVER(server), NULL); + + if (server->channel_find_func != NULL) { + /* use the server specific channel find function */ + CHANNEL_FIND_FUNC channel_find_func; + channel_find_func = + (CHANNEL_FIND_FUNC) server->channel_find_func; + return channel_find_func(server, name); + } + + for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { + CHANNEL_REC *rec = tmp->data; + + if (rec->chat_type == server->channel_type && + g_strcasecmp(name, rec->name) == 0) + return rec; + } + + return NULL; +} + +CHANNEL_REC *channel_find(SERVER_REC *server, const char *name) +{ + g_return_val_if_fail(server == NULL || IS_SERVER(server), NULL); + g_return_val_if_fail(name != NULL, NULL); + + if (server != NULL) + return channel_find_server(server, name); + + /* find from any server */ + return gslist_foreach_find(servers, + (FOREACH_FIND_FUNC) channel_find_server, + (void *) name); +} + +void channels_init(void) +{ +} + +void channels_deinit(void) +{ + module_uniq_destroy("CHANNEL"); +} diff --git a/src/core/channels.h b/src/core/channels.h new file mode 100644 index 00000000..f413e658 --- /dev/null +++ b/src/core/channels.h @@ -0,0 +1,31 @@ +#ifndef __CHANNELS_H +#define __CHANNELS_H + +#include "servers.h" + +#define IS_CHANNEL(channel) \ + ((channel) != NULL && \ + module_find_id("CHANNEL", ((CHANNEL_REC *) (channel))->type) != -1) + +/* Returns CHANNEL_REC if it's channel, NULL if it isn't. */ +#define CHANNEL(channel) \ + (IS_CHANNEL(channel) ? (CHANNEL_REC *) (channel) : NULL) + +#define STRUCT_SERVER_REC SERVER_REC +typedef struct { +#include "channel-rec.h" +} CHANNEL_REC; + +extern GSList *channels; + +void channels_init(void); +void channels_deinit(void); + +/* Create new channel record */ +void channel_init(CHANNEL_REC *channel, int automatic); +void channel_destroy(CHANNEL_REC *channel); + +/* find channel by name, if `server' is NULL, search from all servers */ +CHANNEL_REC *channel_find(SERVER_REC *server, const char *name); + +#endif diff --git a/src/core/chatnet-rec.h b/src/core/chatnet-rec.h new file mode 100644 index 00000000..e166627a --- /dev/null +++ b/src/core/chatnet-rec.h @@ -0,0 +1,12 @@ +int type; /* should always be "CHATNET" */ +int chat_type; + +char *name; + +char *nick; +char *username; +char *realname; + +char *own_host; /* address to use when connecting this server */ +char *autosendcmd; /* command to send after connecting to this ircnet */ +IPADDR *own_ip; /* resolved own_address if not NULL */ diff --git a/src/core/chatnets.c b/src/core/chatnets.c new file mode 100644 index 00000000..5b1b811d --- /dev/null +++ b/src/core/chatnets.c @@ -0,0 +1,148 @@ +/* + chatnets.c : 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 "network.h" +#include "signals.h" +#include "special-vars.h" +#include "lib-config/iconfig.h" +#include "settings.h" + +#include "chatnets.h" +#include "servers.h" + +GSList *chatnets; /* list of available chat networks */ + +void chatnet_read(CHATNET_REC *chatnet, void *nodep) +{ + CONFIG_NODE *node = nodep; + + g_return_if_fail(chatnet != NULL); + g_return_if_fail(node != NULL); + g_return_if_fail(node->key != NULL); + + chatnet->type = module_get_uniq_id("CHATNET", 0); + chatnet->name = g_strdup(node->key); + chatnet->nick = g_strdup(config_node_get_str(node, "nick", NULL)); + chatnet->username = g_strdup(config_node_get_str(node, "username", NULL)); + chatnet->realname = g_strdup(config_node_get_str(node, "realname", NULL)); + chatnet->own_host = g_strdup(config_node_get_str(node, "host", NULL)); + chatnet->autosendcmd = g_strdup(config_node_get_str(node, "autosendcmd", NULL)); + + chatnets = g_slist_append(chatnets, chatnet); +} + +void *chatnet_save(CHATNET_REC *chatnet, void *parentnode) +{ + CONFIG_NODE *node = parentnode; + + g_return_val_if_fail(parentnode != NULL, NULL); + g_return_val_if_fail(IS_CHATNET(chatnet), NULL); + + node = config_node_section(node, chatnet->name, NODE_TYPE_BLOCK); + iconfig_node_clear(node); + + iconfig_node_set_str(node, "nick", chatnet->nick); + iconfig_node_set_str(node, "username", chatnet->username); + iconfig_node_set_str(node, "realname", chatnet->realname); + iconfig_node_set_str(node, "host", chatnet->own_host); + iconfig_node_set_str(node, "autosendcmd", chatnet->autosendcmd); + return node; +} + +void chatnet_create(CHATNET_REC *chatnet) +{ + g_return_if_fail(chatnet != NULL); + + chatnet->type = module_get_uniq_id("CHATNET", 0); + if (g_slist_find(chatnets, chatnet) == NULL) + chatnets = g_slist_append(chatnets, chatnet); + + signal_emit("chatnet created", 1, chatnet); +} + +void chatnet_remove(CHATNET_REC *chatnet) +{ + g_return_if_fail(IS_CHATNET(chatnet)); + + signal_emit("chatnet removed", 1, chatnet); + chatnet_destroy(chatnet); +} + +void chatnet_destroy(CHATNET_REC *chatnet) +{ + g_return_if_fail(IS_CHATNET(chatnet)); + + chatnets = g_slist_remove(chatnets, chatnet); + signal_emit("chatnet destroyed", 1, chatnet); + + g_free(chatnet->name); + g_free_not_null(chatnet->nick); + g_free_not_null(chatnet->username); + g_free_not_null(chatnet->realname); + g_free_not_null(chatnet->own_host); + g_free_not_null(chatnet->autosendcmd); + g_free(chatnet); +} + +/* Find the irc network by name */ +CHATNET_REC *chatnet_find(const char *name) +{ + GSList *tmp; + + g_return_val_if_fail(name != NULL, NULL); + + for (tmp = chatnets; tmp != NULL; tmp = tmp->next) { + CHATNET_REC *rec = tmp->data; + + if (g_strcasecmp(rec->name, name) == 0) + return rec; + } + + return NULL; +} + +static void sig_connected(SERVER_REC *server) +{ + CHATNET_REC *rec; + + g_return_if_fail(IS_SERVER(server)); + + if (server->connrec->chatnet == NULL) + return; + + rec = chatnet_find(server->connrec->chatnet); + if (rec != NULL && rec->autosendcmd) + eval_special_string(rec->autosendcmd, "", server, NULL); +} + +void chatnets_init(void) +{ + signal_add("event connected", (SIGNAL_FUNC) sig_connected); +} + +void chatnets_deinit(void) +{ + while (chatnets != NULL) + chatnet_destroy(chatnets->data); + + signal_remove("event connected", (SIGNAL_FUNC) sig_connected); + module_uniq_destroy("CHATNET"); +} diff --git a/src/core/chatnets.h b/src/core/chatnets.h new file mode 100644 index 00000000..724421cf --- /dev/null +++ b/src/core/chatnets.h @@ -0,0 +1,37 @@ +#ifndef __CHATNETS_H +#define __CHATNETS_H + +#include "modules.h" + +#define IS_CHATNET(chatnet) \ + ((chatnet) != NULL && \ + module_find_id("CHATNET", (chatnet)->type) != -1) + +/* Returns CHATNET_REC if it's chatnet, NULL if it isn't. */ +#define CHATNET(chatnet) \ + (IS_CHATNET(chatnet) ? (CHATNET_REC *) (chatnet) : NULL) + +typedef struct { +#include "chatnet-rec.h" +} CHATNET_REC; + +extern GSList *chatnets; /* list of available chat networks */ + +/* read/save to configuration file */ +void chatnet_read(CHATNET_REC *chatnet, void *node); +void *chatnet_save(CHATNET_REC *chatnet, void *parentnode); + +/* add the chatnet to chat networks list */ +void chatnet_create(CHATNET_REC *chatnet); +/* remove the chatnet from chat networks list */ +void chatnet_remove(CHATNET_REC *chatnet); +/* destroy the chatnet structure. doesn't remove from config file */ +void chatnet_destroy(CHATNET_REC *chatnet); + +/* Find the irc network by name */ +CHATNET_REC *chatnet_find(const char *name); + +void chatnets_init(void); +void chatnets_deinit(void); + +#endif diff --git a/src/core/commands.c b/src/core/commands.c index 174824a3..ff35a0b6 100644 --- a/src/core/commands.c +++ b/src/core/commands.c @@ -19,12 +19,11 @@ */ #include "module.h" -#include "modules.h" #include "signals.h" #include "commands.h" #include "misc.h" -#include "server.h" -#include "server-redirect.h" +#include "servers.h" +#include "servers-redirect.h" #include "special-vars.h" #include "lib-config/iconfig.h" @@ -617,6 +616,8 @@ static void parse_command(const char *command, int expand_aliases, const char *alias, *newcmd; char *cmd, *orig, *args, *oldcmd; + g_return_if_fail(command != NULL); + cmd = orig = g_strconcat("command ", command, NULL); args = strchr(cmd+8, ' '); if (args != NULL) *args++ = '\0'; else args = ""; @@ -643,7 +644,7 @@ static void parse_command(const char *command, int expand_aliases, cmd = g_strconcat("command ", newcmd, NULL); if (server != NULL) - server_redirect_default((SERVER_REC *) server, cmd); + server_redirect_default(SERVER(server), cmd); g_strdown(cmd); oldcmd = current_command; diff --git a/src/core/core.c b/src/core/core.c index 642aa47b..48f4af8f 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -1,7 +1,7 @@ /* core.c : irssi - Copyright (C) 1999 Timo Sirainen + 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 @@ -20,7 +20,6 @@ #include "module.h" -#include "modules.h" #include "pidwait.h" #include "net-disconnect.h" @@ -28,12 +27,17 @@ #include "signals.h" #include "settings.h" -#include "server.h" +#include "servers.h" +#include "chatnets.h" #include "commands.h" #include "log.h" #include "rawlog.h" #include "special-vars.h" +#include "channels.h" +#include "queries.h" +#include "nicklist.h" + int irssi_gui; void core_init(void) @@ -47,18 +51,28 @@ void core_init(void) settings_init(); commands_init(); + chatnets_init(); servers_init(); log_init(); rawlog_init(); special_vars_init(); + + channels_init(); + queries_init(); + nicklist_init(); } void core_deinit(void) { + nicklist_deinit(); + queries_deinit(); + channels_deinit(); + special_vars_deinit(); rawlog_deinit(); log_deinit(); servers_deinit(); + chatnets_deinit(); commands_deinit(); settings_deinit(); diff --git a/src/core/masks.c b/src/core/masks.c new file mode 100644 index 00000000..38fbdf45 --- /dev/null +++ b/src/core/masks.c @@ -0,0 +1,137 @@ +/* + masks.c : 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 "network.h" +#include "misc.h" + +#include "servers.h" + +typedef int (*MASK_MATCH_FUNC) (const char *, const char *); + +/* Returns TRUE if mask contains '!' ie. address should be checked too. + Also checks if mask contained any wildcards. */ +static int check_address(const char *mask, int *wildcards) +{ + int ret; + + ret = FALSE; + while (*mask != '\0') { + if (*mask == '!') { + if (*wildcards) return TRUE; + ret = TRUE; + } + + if (*mask == '?' || *mask == '*') { + *wildcards = TRUE; + if (ret) return TRUE; + } + mask++; + } + + return ret; +} + +static int check_mask(SERVER_REC *server, const char *mask, + const char *str, int wildcards) +{ + MASK_MATCH_FUNC mask_match_func; + + if (server != NULL && server->mask_match_func != NULL) { + /* use server specified mask match function */ + mask_match_func = (MASK_MATCH_FUNC)server->mask_match_func; + return mask_match_func(mask, str); + } + + return wildcards ? match_wildcards(mask, str) : + g_strcasecmp(mask, str) == 0; +} + +int mask_match(SERVER_REC *server, const char *mask, + const char *nick, const char *user, const char *host) +{ + char *str; + int ret, wildcards; + + g_return_val_if_fail(server == NULL || IS_SERVER(server), FALSE); + g_return_val_if_fail(mask != NULL && nick != NULL && + nick != NULL && host != NULL, FALSE); + + str = !check_address(mask, &wildcards) ? (char *) nick : + g_strdup_printf("%s!%s@%s", nick, user, host); + ret = check_mask(server, mask, str, wildcards); + if (str != nick) g_free(str); + + return ret; +} + +int mask_match_address(SERVER_REC *server, const char *mask, + const char *nick, const char *address) +{ + char *str; + int ret, wildcards; + + g_return_val_if_fail(server == NULL || IS_SERVER(server), FALSE); + g_return_val_if_fail(mask != NULL && nick != NULL, FALSE); + if (address == NULL) address = ""; + + str = !check_address(mask, &wildcards) ? (char *) nick : + g_strdup_printf("%s!%s", nick, address); + ret = check_mask(server, mask, str, wildcards); + if (str != nick) g_free(str); + + return ret; +} + +int masks_match(SERVER_REC *server, const char *masks, + const char *nick, const char *address) +{ + MASK_MATCH_FUNC mask_match_func; + char **list, **tmp, *mask; + int found; + + g_return_val_if_fail(server == NULL || IS_SERVER(server), FALSE); + g_return_val_if_fail(masks != NULL && + nick != NULL && address != NULL, FALSE); + + mask_match_func = server != NULL && server->mask_match_func != NULL ? + (MASK_MATCH_FUNC) server->mask_match_func : + (MASK_MATCH_FUNC) match_wildcards; + + found = FALSE; + mask = g_strdup_printf("%s!%s", nick, address); + list = g_strsplit(masks, " ", -1); + for (tmp = list; *tmp != NULL; tmp++) { + if (strchr(*tmp, '!') == NULL && + g_strcasecmp(*tmp, nick) == 0) { + found = TRUE; + break; + } + + if (mask_match_func(*tmp, mask)) { + found = TRUE; + break; + } + } + g_strfreev(list); + g_free(mask); + + return found; +} diff --git a/src/core/masks.h b/src/core/masks.h new file mode 100644 index 00000000..437c8cb4 --- /dev/null +++ b/src/core/masks.h @@ -0,0 +1,13 @@ +#ifndef __MASKS_H +#define __MASKS_H + +#include "servers.h" + +int mask_match(SERVER_REC *server, const char *mask, + const char *nick, const char *user, const char *host); +int mask_match_address(SERVER_REC *server, const char *mask, + const char *nick, const char *address); +int masks_match(SERVER_REC *server, const char *masks, + const char *nick, const char *address); + +#endif diff --git a/src/core/memdebug.c b/src/core/memdebug.c index 807d1c56..3dbed391 100644 --- a/src/core/memdebug.c +++ b/src/core/memdebug.c @@ -38,7 +38,7 @@ typedef struct { static GHashTable *data = NULL, *preallocs = NULL; static const char *comment = ""; -static void add_flow_checks(guchar *p, unsigned long size) +static void add_flow_checks(char *p, unsigned long size) { #ifdef ENABLE_BUFFER_CHECKS int n; @@ -75,7 +75,7 @@ static void mem_check(void) #endif } -static void data_add(void *p, int size, const char *file, int line) +static void data_add(char *p, int size, const char *file, int line) { MEM_REC *rec; @@ -106,7 +106,19 @@ static void data_add(void *p, int size, const char *file, int line) mem_check(); } -static void *data_remove(void *p, const char *file, int line) +static void data_clear(char *p) +{ + MEM_REC *rec; + + if (g_hash_table_lookup(preallocs, p) != NULL) + p += BUFFER_CHECK_SIZE; + + rec = g_hash_table_lookup(data, p); + if (rec != NULL && rec->size > 0) + memset(p, 'F', rec->size); +} + +static void *data_remove(char *p, const char *file, int line) { MEM_REC *rec; @@ -132,34 +144,34 @@ static void *data_remove(void *p, const char *file, int line) void *ig_malloc(int size, const char *file, int line) { - void *p; + char *p; size += BUFFER_CHECK_SIZE*2; p = g_malloc(size); data_add(p, size, file, line); - return p+BUFFER_CHECK_SIZE; + return (void *) (p+BUFFER_CHECK_SIZE); } void *ig_malloc0(int size, const char *file, int line) { - void *p; + char *p; size += BUFFER_CHECK_SIZE*2; p = g_malloc0(size); data_add(p, size, file, line); - return p+BUFFER_CHECK_SIZE; + return (void *) (p+BUFFER_CHECK_SIZE); } void *ig_realloc(void *mem, unsigned long size, const char *file, int line) { - void *p; + char *p, *oldmem = mem; size += BUFFER_CHECK_SIZE*2; - mem -= BUFFER_CHECK_SIZE; - data_remove(mem, file, line); - p = g_realloc(mem, size); + oldmem -= BUFFER_CHECK_SIZE; + data_remove(oldmem, file, line); + p = g_realloc(oldmem, size); data_add(p, size, file, line); - return p+BUFFER_CHECK_SIZE; + return (void *) (p+BUFFER_CHECK_SIZE); } char *ig_strdup(const char *str, const char *file, int line) @@ -252,11 +264,14 @@ char *ig_strdup_vprintf(const char *file, int line, const char *format, va_list void ig_free(void *p) { - if (p == NULL) g_error("ig_free() : trying to free NULL"); + char *cp = p; + + if (cp == NULL) g_error("ig_free() : trying to free NULL"); - p -= BUFFER_CHECK_SIZE; - p = data_remove(p, "??", 0); - if (p != NULL) g_free(p); + cp -= BUFFER_CHECK_SIZE; + data_clear(cp); + cp = data_remove(cp, "??", 0); + if (cp != NULL) g_free(cp); } GString *ig_string_new(const char *file, int line, const char *str) @@ -264,13 +279,13 @@ GString *ig_string_new(const char *file, int line, const char *str) GString *ret; ret = g_string_new(str); - data_add(ret, INT_MIN, file, line); + data_add((void *) ret, INT_MIN, file, line); return ret; } void ig_string_free(const char *file, int line, GString *str, gboolean freeit) { - data_remove(str, file, line); + data_remove((void *) str, file, line); if (!freeit) data_add(str->str, INT_MIN, file, line); @@ -304,7 +319,7 @@ void ig_profile_line(void *key, MEM_REC *rec) strcmp(rec->file, "ig_strdup_vprintf") == 0 || strcmp(rec->file, "ig_strconcat") == 0 || strcmp(rec->file, "ig_string_free (free = FALSE)") == 0)) - data = rec->p + BUFFER_CHECK_SIZE; + data = (char *) rec->p + BUFFER_CHECK_SIZE; else data = rec->comment; fprintf(stderr, "%s:%d %d bytes (%s)\n", rec->file, rec->line, rec->size, data); diff --git a/src/core/misc.c b/src/core/misc.c index c9abeb07..2f7d8049 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -196,12 +196,12 @@ GSList *gslist_find_icase_string(GSList *list, const char *key) return NULL; } -void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, void *data) +void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, const void *data) { void *ret; while (list != NULL) { - ret = func(list->data, data); + ret = func(list->data, (void *) data); if (ret != NULL) return ret; list = list->next; diff --git a/src/core/misc.h b/src/core/misc.h index 3dc50dc1..2bcdb67c 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -23,7 +23,7 @@ GSList *gslist_find_icase_string(GSList *list, const char *key); GList *glist_find_string(GList *list, const char *key); GList *glist_find_icase_string(GList *list, const char *key); -void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, void *data); +void *gslist_foreach_find(GSList *list, FOREACH_FIND_FUNC func, const void *data); /* `list' contains pointer to structure with a char* to string. */ char *gslistptr_to_string(GSList *list, int offset, const char *delimiter); diff --git a/src/core/modules.c b/src/core/modules.c index 1749c6fb..fc10487d 100644 --- a/src/core/modules.c +++ b/src/core/modules.c @@ -324,6 +324,11 @@ void module_unload(MODULE_REC *module) g_free(module); } +static void uniq_get_modules(char *key, void *value, GSList **list) +{ + *list = g_slist_append(*list, key); +} + void modules_init(void) { modules = NULL; @@ -342,11 +347,19 @@ void modules_init(void) void modules_deinit(void) { - g_hash_table_foreach(idlookup, (GHFunc) module_uniq_destroy, NULL); - g_hash_table_destroy(idlookup); - g_hash_table_destroy(uniqids); + GSList *list; - g_hash_table_foreach(stridlookup, (GHFunc) module_uniq_destroy, NULL); + list = NULL; + g_hash_table_foreach(idlookup, (GHFunc) uniq_get_modules, &list); + g_hash_table_foreach(stridlookup, (GHFunc) uniq_get_modules, &list); + + while (list != NULL) { + module_uniq_destroy(list->data); + list = g_slist_remove(list, list->data); + } + + g_hash_table_destroy(idlookup); g_hash_table_destroy(stridlookup); + g_hash_table_destroy(uniqids); g_hash_table_destroy(uniqstrids); } diff --git a/src/core/nicklist.c b/src/core/nicklist.c new file mode 100644 index 00000000..1ba78f94 --- /dev/null +++ b/src/core/nicklist.c @@ -0,0 +1,268 @@ +/* + nicklist.c : 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 "misc.h" + +#include "nicklist.h" +#include "masks.h" + +/* Add new nick to list */ +NICK_REC *nicklist_insert(CHANNEL_REC *channel, const char *nick, + int op, int voice, int send_massjoin) +{ + NICK_REC *rec; + + g_return_val_if_fail(IS_CHANNEL(channel), NULL); + g_return_val_if_fail(nick != NULL, NULL); + + rec = g_new0(NICK_REC, 1); + + if (op) rec->op = TRUE; + if (voice) rec->voice = TRUE; + + rec->send_massjoin = send_massjoin; + rec->nick = g_strdup(nick); + rec->host = NULL; + + g_hash_table_insert(channel->nicks, rec->nick, rec); + signal_emit("nicklist new", 2, channel, rec); + return rec; +} + +static void nicklist_destroy(CHANNEL_REC *channel, NICK_REC *nick) +{ + signal_emit("nicklist remove", 2, channel, nick); + + g_free(nick->nick); + g_free_not_null(nick->realname); + g_free_not_null(nick->host); + g_free(nick); +} + +/* remove nick from list */ +void nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick) +{ + g_return_if_fail(IS_CHANNEL(channel)); + g_return_if_fail(nick != NULL); + + g_hash_table_remove(channel->nicks, nick->nick); + nicklist_destroy(channel, nick); +} + +static NICK_REC *nicklist_find_wildcards(CHANNEL_REC *channel, + const char *mask) +{ + GSList *nicks, *tmp; + NICK_REC *nick; + + nicks = nicklist_getnicks(channel); + nick = NULL; + for (tmp = nicks; tmp != NULL; tmp = tmp->next) { + nick = tmp->data; + + if (mask_match_address(channel->server, mask, + nick->nick, nick->host)) + break; + } + g_slist_free(nicks); + return tmp == NULL ? NULL : nick; +} + +GSList *nicklist_find_multiple(CHANNEL_REC *channel, const char *mask) +{ + GSList *nicks, *tmp, *next; + + g_return_val_if_fail(IS_CHANNEL(channel), NULL); + g_return_val_if_fail(mask != NULL, NULL); + + nicks = nicklist_getnicks(channel); + for (tmp = nicks; tmp != NULL; tmp = next) { + NICK_REC *nick = tmp->data; + + next = tmp->next; + if (!mask_match_address(channel->server, mask, + nick->nick, nick->host)) + nicks = g_slist_remove(nicks, tmp->data); + } + + return nicks; +} + +/* Find nick record from list */ +NICK_REC *nicklist_find(CHANNEL_REC *channel, const char *mask) +{ + NICK_REC *nickrec; + char *nick, *host; + + g_return_val_if_fail(IS_CHANNEL(channel), NULL); + g_return_val_if_fail(mask != NULL, NULL); + + nick = g_strdup(mask); + host = strchr(nick, '!'); + if (host != NULL) *host++ = '\0'; + + if (strchr(nick, '*') || strchr(nick, '?')) { + g_free(nick); + return nicklist_find_wildcards(channel, mask); + } + + nickrec = g_hash_table_lookup(channel->nicks, nick); + + if (nickrec != NULL && host != NULL && + (nickrec->host == NULL || !match_wildcards(host, nickrec->host))) { + /* hosts didn't match */ + nickrec = NULL; + } + g_free(nick); + return nickrec; +} + +static void get_nicks_hash(gpointer key, NICK_REC *rec, GSList **list) +{ + *list = g_slist_append(*list, rec); +} + +/* Get list of nicks */ +GSList *nicklist_getnicks(CHANNEL_REC *channel) +{ + GSList *list; + + g_return_val_if_fail(IS_CHANNEL(channel), NULL); + + list = NULL; + g_hash_table_foreach(channel->nicks, (GHFunc) get_nicks_hash, &list); + return list; +} + +typedef struct { + CHANNEL_REC *channel; + const char *nick; + GSList *list; +} NICKLIST_GET_SAME_REC; + +static void get_nicks_same_hash(gpointer key, NICK_REC *nick, + NICKLIST_GET_SAME_REC *rec) +{ + if (g_strcasecmp(nick->nick, rec->nick) == 0) { + rec->list = g_slist_append(rec->list, rec->channel); + rec->list = g_slist_append(rec->list, nick); + } +} + +GSList *nicklist_get_same(SERVER_REC *server, const char *nick) +{ + NICKLIST_GET_SAME_REC rec; + GSList *tmp; + + g_return_val_if_fail(IS_SERVER(server), NULL); + + rec.nick = nick; + rec.list = NULL; + for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { + rec.channel = tmp->data; + g_hash_table_foreach(rec.channel->nicks, + (GHFunc) get_nicks_same_hash, &rec); + } + return rec.list; +} + +/* nick record comparision for sort functions */ +int nicklist_compare(NICK_REC *p1, NICK_REC *p2) +{ + if (p1 == NULL) return -1; + if (p2 == NULL) return 1; + + if (p1->op && !p2->op) return -1; + if (!p1->op && p2->op) return 1; + + if (!p1->op) { + if (p1->voice && !p2->voice) return -1; + if (!p1->voice && p2->voice) return 1; + } + + return g_strcasecmp(p1->nick, p2->nick); +} + +void nicklist_update_flags(SERVER_REC *server, const char *nick, + int gone, int serverop) +{ + GSList *nicks, *tmp; + CHANNEL_REC *channel; + NICK_REC *rec; + + g_return_if_fail(IS_SERVER(server)); + g_return_if_fail(nick != NULL); + + nicks = nicklist_get_same(server, nick); + for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) { + channel = tmp->data; + rec = tmp->next->data; + + rec->last_check = time(NULL); + + if (gone != -1 && rec->gone != gone) { + rec->gone = gone; + signal_emit("nick gone changed", 2, channel, rec); + } + + if (serverop != -1 && rec->serverop != serverop) { + rec->serverop = serverop; + signal_emit("nick serverop changed", 2, channel, rec); + } + } + g_slist_free(nicks); +} + +static void sig_channel_created(CHANNEL_REC *channel) +{ + g_return_if_fail(IS_CHANNEL(channel)); + + channel->nicks = g_hash_table_new((GHashFunc) g_istr_hash, + (GCompareFunc) g_istr_equal); +} + +static void nicklist_remove_hash(gpointer key, NICK_REC *nick, + CHANNEL_REC *channel) +{ + nicklist_destroy(channel, nick); +} + +static void sig_channel_destroyed(CHANNEL_REC *channel) +{ + g_return_if_fail(IS_CHANNEL(channel)); + + g_hash_table_foreach(channel->nicks, + (GHFunc) nicklist_remove_hash, channel); + g_hash_table_destroy(channel->nicks); +} + +void nicklist_init(void) +{ + signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created); + signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); +} + +void nicklist_deinit(void) +{ + signal_remove("channel created", (SIGNAL_FUNC) sig_channel_created); + signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); +} diff --git a/src/core/nicklist.h b/src/core/nicklist.h new file mode 100644 index 00000000..cd9276c3 --- /dev/null +++ b/src/core/nicklist.h @@ -0,0 +1,50 @@ +#ifndef __NICKLIST_H +#define __NICKLIST_H + +#include "servers.h" +#include "channels.h" + +typedef struct { + time_t last_check; /* last time gone was checked */ + + char *nick; + char *host; + char *realname; + int hops; + + /* status in server */ + int gone:1; + int serverop:1; + + /* status in channel */ + int send_massjoin:1; /* Waiting to be sent in massjoin signal */ + int op:1; + int halfop:1; + int voice:1; +} NICK_REC; + +/* Add new nick to list */ +NICK_REC *nicklist_insert(CHANNEL_REC *channel, const char *nick, + int op, int voice, int send_massjoin); +/* remove nick from list */ +void nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick); +/* Find nick record from list */ +NICK_REC *nicklist_find(CHANNEL_REC *channel, const char *mask); +/* Get list of nicks that match the mask */ +GSList *nicklist_find_multiple(CHANNEL_REC *channel, const char *mask); +/* Get list of nicks */ +GSList *nicklist_getnicks(CHANNEL_REC *channel); +/* Get all the nick records of `nick'. Returns channel, nick, channel, ... */ +GSList *nicklist_get_same(SERVER_REC *server, const char *nick); + +/* Update specified nick's status in server. */ +void nicklist_update_flags(SERVER_REC *server, const char *nick, + int gone, int ircop); + +/* Nick record comparision for sort functions */ +int nicklist_compare(NICK_REC *p1, NICK_REC *p2); + +void nicklist_init(void); +void nicklist_deinit(void); + +#endif diff --git a/src/core/queries.c b/src/core/queries.c new file mode 100644 index 00000000..17a371f9 --- /dev/null +++ b/src/core/queries.c @@ -0,0 +1,124 @@ +/* + queries.c : 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 "misc.h" + +#include "queries.h" + +GSList *queries; + +typedef QUERY_REC *(*QUERY_FIND_FUNC)(SERVER_REC *, const char *); + +void query_init(QUERY_REC *query, int automatic) +{ + g_return_if_fail(query != NULL); + g_return_if_fail(query->name != NULL); + + queries = g_slist_append(queries, query); + if (query->server != NULL) { + query->server->queries = + g_slist_append(query->server->queries, query); + } + + MODULE_DATA_INIT(query); + query->type = module_get_uniq_id("QUERY", 0); + if (query->server != NULL) + query->server_tag = g_strdup(query->server->tag); + + signal_emit("query created", 2, query, GINT_TO_POINTER(automatic)); +} + +void query_destroy(QUERY_REC *query) +{ + g_return_if_fail(IS_QUERY(query)); + + if (query->destroying) return; + query->destroying = TRUE; + + queries = g_slist_remove(queries, query); + if (query->server != NULL) { + query->server->queries = + g_slist_remove(query->server->queries, query); + } + signal_emit("query destroyed", 1, query); + + MODULE_DATA_DEINIT(query); + g_free_not_null(query->address); + g_free(query->name); + g_free(query->server_tag); + g_free(query); +} + +static QUERY_REC *query_find_server(SERVER_REC *server, const char *nick) +{ + GSList *tmp; + + g_return_val_if_fail(IS_SERVER(server), NULL); + + if (server->query_find_func != NULL) { + /* use the server specific query find function */ + QUERY_FIND_FUNC query_find_func; + query_find_func = (QUERY_FIND_FUNC) server->query_find_func; + return query_find_func(server, nick); + } + + for (tmp = server->queries; tmp != NULL; tmp = tmp->next) { + QUERY_REC *rec = tmp->data; + + if (rec->chat_type == server->query_type && + g_strcasecmp(nick, rec->name) == 0) + return rec; + } + + return NULL; +} + +QUERY_REC *query_find(SERVER_REC *server, const char *nick) +{ + g_return_val_if_fail(server == NULL || IS_SERVER(server), NULL); + g_return_val_if_fail(nick != NULL, NULL); + + if (server != NULL) + return query_find_server(server, nick); + + /* find from any server */ + return gslist_foreach_find(servers, + (FOREACH_FIND_FUNC) query_find_server, + (void *) nick); +} + +void query_change_server(QUERY_REC *query, SERVER_REC *server) +{ + g_return_if_fail(IS_QUERY(query)); + + query->server = server; + signal_emit("query server changed", 2, query, server); +} + +void queries_init(void) +{ +} + +void queries_deinit(void) +{ + module_uniq_destroy("QUERY"); +} diff --git a/src/core/queries.h b/src/core/queries.h new file mode 100644 index 00000000..106b4ca7 --- /dev/null +++ b/src/core/queries.h @@ -0,0 +1,32 @@ +#ifndef __QUERIES_H +#define __QUERIES_H + +#include "servers.h" + +#define IS_QUERY(query) \ + ((query) != NULL && \ + module_find_id("QUERY", ((QUERY_REC *) (query))->type) != -1) + +/* Returns QUERY_REC if it's query, NULL if it isn't. */ +#define QUERY(query) \ + (IS_QUERY(query) ? (QUERY_REC *) (query) : NULL) + +#define STRUCT_SERVER_REC SERVER_REC +typedef struct { +#include "query-rec.h" +} QUERY_REC; + +extern GSList *queries; + +void query_init(QUERY_REC *query, int automatic); +void query_destroy(QUERY_REC *query); + +/* Find query by name, if `server' is NULL, search from all servers */ +QUERY_REC *query_find(SERVER_REC *server, const char *nick); + +void query_change_server(QUERY_REC *query, SERVER_REC *server); + +void queries_init(void); +void queries_deinit(void); + +#endif diff --git a/src/core/query-rec.h b/src/core/query-rec.h new file mode 100644 index 00000000..8b587f5e --- /dev/null +++ b/src/core/query-rec.h @@ -0,0 +1,9 @@ +/* QUERY_REC definition, used for inheritance */ + +#include "window-item-rec.h" + +char *address; +char *server_tag; +int unwanted:1; /* TRUE if the other side closed or + some error occured (DCC chats!) */ +int destroying:1; diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h new file mode 100644 index 00000000..863235de --- /dev/null +++ b/src/core/server-connect-rec.h @@ -0,0 +1,26 @@ +/* SERVER_CONNECT_REC definition, used for inheritance */ + +int type; +int chat_type; + +/* if we're connecting via proxy, or just NULLs */ +char *proxy; +int proxy_port; +char *proxy_string; + +char *address; +int port; +char *chatnet; + +IPADDR *own_ip; + +char *password; +char *nick; +char *username; +char *realname; + +/* when reconnecting, the old server status */ +int reconnection:1; /* we're trying to reconnect */ +char *channels; +char *away_reason; +char *usermode; diff --git a/src/core/server-rec.h b/src/core/server-rec.h new file mode 100644 index 00000000..8aaabed2 --- /dev/null +++ b/src/core/server-rec.h @@ -0,0 +1,50 @@ +/* SERVER_REC definition, used for inheritance */ + +int type; /* should always be "SERVER" */ +int chat_type; + +STRUCT_SERVER_CONNECT_REC *connrec; +time_t connect_time; /* connection time */ +time_t real_connect_time; /* time when server replied that we really are connected */ + +char *tag; /* tag name for addressing server */ +char *nick; /* current nick */ + +int connected:1; /* connected to server */ +int connection_lost:1; /* Connection lost unintentionally */ + +void *handle; /* NET_SENDBUF_REC socket */ +int readtag; /* input tag */ + +/* for net_connect_nonblock() */ +int connect_pipe[2]; +int connect_tag; +int connect_pid; + +/* For deciding if event should be handled internally */ +GHashTable *eventtable; /* "event xxx" : GSList* of REDIRECT_RECs */ +GHashTable *eventgrouptable; /* event group : GSList* of REDIRECT_RECs */ +GHashTable *cmdtable; /* "command xxx" : REDIRECT_CMD_REC* */ + +void *rawlog; +void *buffer; /* receive buffer */ +GHashTable *module_data; + +char *version; /* server version */ +char *away_reason; +int server_operator:1; +int usermode_away:1; +int banned:1; /* not allowed to connect to this server */ + +GSList *channels; +GSList *queries; + +/* support for multiple server types */ +void *channel_find_func; +void *query_find_func; +int channel_type; +int query_type; + +void *mask_match_func; + +#undef STRUCT_SERVER_CONNECT_REC diff --git a/src/core/server-redirect.c b/src/core/server-redirect.c deleted file mode 100644 index cd5e0d04..00000000 --- a/src/core/server-redirect.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - server-redirect.c : 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 "misc.h" - -#include "server.h" -#include "server-redirect.h" - -static int redirect_group; - -static void server_eventtable_destroy(char *key, GSList *value) -{ - GSList *tmp; - - g_free(key); - - for (tmp = value; tmp != NULL; tmp = tmp->next) { - REDIRECT_REC *rec = tmp->data; - - g_free_not_null(rec->arg); - g_free(rec->name); - g_free(rec); - } - g_slist_free(value); -} - -static void server_eventgrouptable_destroy(gpointer key, GSList *value) -{ - g_slist_foreach(value, (GFunc) g_free, NULL); - g_slist_free(value); -} - -static void server_cmdtable_destroy(char *key, REDIRECT_CMD_REC *value) -{ - g_free(key); - - g_slist_foreach(value->events, (GFunc) g_free, NULL); - g_slist_free(value->events); - g_free(value); -} - -static void sig_disconnected(SERVER_REC *server) -{ - g_return_if_fail(server != NULL); - - if (server->eventtable != NULL) { - g_hash_table_foreach(server->eventtable, - (GHFunc) server_eventtable_destroy, NULL); - g_hash_table_destroy(server->eventtable); - } - - g_hash_table_foreach(server->eventgrouptable, - (GHFunc) server_eventgrouptable_destroy, NULL); - g_hash_table_destroy(server->eventgrouptable); - - if (server->cmdtable != NULL) { - g_hash_table_foreach(server->cmdtable, - (GHFunc) server_cmdtable_destroy, NULL); - g_hash_table_destroy(server->cmdtable); - } -} - -void server_redirect_initv(SERVER_REC *server, const char *command, - int last, GSList *list) -{ - REDIRECT_CMD_REC *rec; - - g_return_if_fail(server != NULL); - g_return_if_fail(command != NULL); - g_return_if_fail(last > 0); - - if (g_hash_table_lookup(server->cmdtable, command) != NULL) { - /* already in hash table. list of events SHOULD be the same. */ - g_slist_foreach(list, (GFunc) g_free, NULL); - g_slist_free(list); - return; - } - - rec = g_new(REDIRECT_CMD_REC, 1); - rec->last = last; - rec->events = list; - g_hash_table_insert(server->cmdtable, g_strdup(command), rec); -} - -void server_redirect_init(SERVER_REC *server, const char *command, - int last, ...) -{ - va_list args; - GSList *list; - char *event; - - va_start(args, last); - list = NULL; - while ((event = va_arg(args, gchar *)) != NULL) - list = g_slist_append(list, g_strdup(event)); - va_end(args); - - server_redirect_initv(server, command, last, list); -} - -int server_redirect_single_event(SERVER_REC *server, const char *arg, - int last, int group, const char *event, - const char *signal, int argpos) -{ - REDIRECT_REC *rec; - GSList *list, *grouplist; - char *origkey; - - g_return_val_if_fail(server != NULL, 0); - g_return_val_if_fail(event != NULL, 0); - g_return_val_if_fail(signal != NULL, 0); - g_return_val_if_fail(arg != NULL || argpos == -1, 0); - - if (group == 0) group = ++redirect_group; - - rec = g_new0(REDIRECT_REC, 1); - rec->arg = arg == NULL ? NULL : g_strdup(arg); - rec->argpos = argpos; - rec->name = g_strdup(signal); - rec->group = group; - rec->last = last; - - if (g_hash_table_lookup_extended(server->eventtable, event, - (gpointer *) &origkey, - (gpointer *) &list)) { - g_hash_table_remove(server->eventtable, origkey); - } else { - list = NULL; - origkey = g_strdup(event); - } - - grouplist = g_hash_table_lookup(server->eventgrouptable, - GINT_TO_POINTER(group)); - if (grouplist != NULL) { - g_hash_table_remove(server->eventgrouptable, - GINT_TO_POINTER(group)); - } - - list = g_slist_append(list, rec); - grouplist = g_slist_append(grouplist, g_strdup(event)); - - g_hash_table_insert(server->eventtable, origkey, list); - g_hash_table_insert(server->eventgrouptable, - GINT_TO_POINTER(group), grouplist); - - return group; -} - -void server_redirect_event(SERVER_REC *server, const char *arg, int last, ...) -{ - va_list args; - char *event, *signal; - int argpos, group; - - g_return_if_fail(server != NULL); - - va_start(args, last); - - group = 0; - while ((event = va_arg(args, gchar *)) != NULL) { - signal = va_arg(args, gchar *); - argpos = va_arg(args, gint); - - group = server_redirect_single_event(server, arg, last > 0, - group, event, signal, - argpos); - last--; - } - - va_end(args); -} - -void server_redirect_default(SERVER_REC *server, const char *command) -{ - REDIRECT_CMD_REC *cmdrec; - REDIRECT_REC *rec; - GSList *events, *list, *grouplist; - char *event, *origkey; - int last; - - g_return_if_fail(server != NULL); - g_return_if_fail(command != NULL); - - if (server->cmdtable == NULL) - return; /* not connected yet */ - - cmdrec = g_hash_table_lookup(server->cmdtable, command); - if (cmdrec == NULL) return; - - /* add all events used by command to eventtable and eventgrouptable */ - redirect_group++; grouplist = NULL; last = cmdrec->last; - for (events = cmdrec->events; events != NULL; events = events->next) { - event = events->data; - - if (g_hash_table_lookup_extended(server->eventtable, event, - (gpointer *) &origkey, - (gpointer *) &list)) { - g_hash_table_remove(server->eventtable, origkey); - } else { - list = NULL; - origkey = g_strdup(event); - } - - rec = g_new0(REDIRECT_REC, 1); - rec->argpos = -1; - rec->name = g_strdup(event); - rec->group = redirect_group; - rec->last = last > 0; - - grouplist = g_slist_append(grouplist, g_strdup(event)); - list = g_slist_append(list, rec); - g_hash_table_insert(server->eventtable, origkey, list); - - last--; - } - - g_hash_table_insert(server->eventgrouptable, - GINT_TO_POINTER(redirect_group), grouplist); -} - -void server_redirect_remove_next(SERVER_REC *server, const char *event, - GSList *item) -{ - REDIRECT_REC *rec; - GSList *grouplist, *list, *events, *tmp; - char *origkey; - int group; - - g_return_if_fail(server != NULL); - g_return_if_fail(event != NULL); - - if (!g_hash_table_lookup_extended(server->eventtable, event, - (gpointer *) &origkey, - (gpointer *) &list)) - return; - - rec = item == NULL ? list->data : item->data; - if (!rec->last) { - /* this wasn't last expected event */ - return; - } - group = rec->group; - - /* get list of events from this group */ - grouplist = g_hash_table_lookup(server->eventgrouptable, - GINT_TO_POINTER(group)); - - /* remove all of them */ - for (list = grouplist; list != NULL; list = list->next) { - char *event = list->data; - - if (!g_hash_table_lookup_extended(server->eventtable, event, - (gpointer *) &origkey, - (gpointer *) &events)) { - g_warning("server_redirect_remove_next() : " - "event in eventgrouptable but not in " - "eventtable"); - continue; - } - - /* remove the right group */ - for (tmp = events; tmp != NULL; tmp = tmp->next) { - rec = tmp->data; - - if (rec->group == group) - break; - } - - if (rec == NULL) { - g_warning("server_redirect_remove_next() : " - "event in eventgrouptable but not in " - "eventtable (group)"); - continue; - } - - g_free(event); - - events = g_slist_remove(events, rec); - g_free_not_null(rec->arg); - g_free(rec->name); - g_free(rec); - - /* update hash table */ - g_hash_table_remove(server->eventtable, origkey); - if (events == NULL) - g_free(origkey); - else { - g_hash_table_insert(server->eventtable, - origkey, events); - } - } - - g_hash_table_remove(server->eventgrouptable, GINT_TO_POINTER(group)); - g_slist_free(grouplist); -} - -GSList *server_redirect_getqueue(SERVER_REC *server, const char *event, - const char *args) -{ - REDIRECT_REC *rec; - GSList *list; - char **arglist; - int found; - - list = g_hash_table_lookup(server->eventtable, event); - - for (; list != NULL; list = list->next) { - rec = list->data; - if (rec->argpos == -1) - break; - - if (rec->arg == NULL) - continue; - - /* we need to check that the argument is right.. */ - arglist = g_strsplit(args, " ", -1); - found = (strarray_length(arglist) > rec->argpos && - find_substr(rec->arg, arglist[rec->argpos])); - g_strfreev(arglist); - - if (found) break; - } - - return list; -} - -void servers_redirect_init(void) -{ - redirect_group = 0; - - signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected); -} - -void servers_redirect_deinit(void) -{ - signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected); -} diff --git a/src/core/server-redirect.h b/src/core/server-redirect.h deleted file mode 100644 index 977dded1..00000000 --- a/src/core/server-redirect.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __SERVER_REDIRECT_H -#define __SERVER_REDIRECT_H - -#include "server.h" - -typedef struct { - int last; /* number of "last" events at the start of the events list */ - GSList *events; /* char* list of events */ -} REDIRECT_CMD_REC; - -typedef struct { - char *name; /* event name */ - - char *arg; /* argument for event we are expecting or NULL */ - int argpos; /* argument position */ - - int group; /* group of events this belongs to */ - int last; /* if this event is received, remove all the events in this group */ -} -REDIRECT_REC; - -void server_redirect_init(SERVER_REC *server, const char *command, int last, ...); -void server_redirect_initv(SERVER_REC *server, const char *command, int last, GSList *list); -/* ... = char *event1, char *event2, ..., NULL */ - -void server_redirect_event(SERVER_REC *server, const char *arg, int last, ...); -/* ... = char *event, char *callback_signal, int argpos, ..., NULL */ - -int server_redirect_single_event(SERVER_REC *server, const char *arg, int last, int group, - const char *event, const char *signal, int argpos); -void server_redirect_default(SERVER_REC *server, const char *command); -void server_redirect_remove_next(SERVER_REC *server, const char *event, GSList *item); -GSList *server_redirect_getqueue(SERVER_REC *server, const char *event, const char *args); - -void servers_redirect_init(void); -void servers_redirect_deinit(void); - -#endif diff --git a/src/core/server-setup-rec.h b/src/core/server-setup-rec.h new file mode 100644 index 00000000..5158780d --- /dev/null +++ b/src/core/server-setup-rec.h @@ -0,0 +1,19 @@ +int type; +int chat_type; + +char *chatnet; + +char *address; +int port; +char *password; + +char *own_host; /* address to use when connecting this server */ +IPADDR *own_ip; /* resolved own_address if not NULL */ + +time_t last_connect; /* to avoid reconnecting too fast.. */ + +int autoconnect:1; +int last_failed:1; /* if last connection attempt failed */ +int banned:1; /* if we're banned from this server */ + +GHashTable *module_data; diff --git a/src/core/server.c b/src/core/server.c deleted file mode 100644 index 029433c5..00000000 --- a/src/core/server.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - server.c : 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 "modules.h" -#include "signals.h" -#include "line-split.h" -#include "net-nonblock.h" -#include "net-sendbuffer.h" -#include "rawlog.h" -#include "misc.h" -#include "server.h" -#include "server-redirect.h" -#include "settings.h" - -GSList *servers, *lookup_servers; - -/* connection to server failed */ -static void server_cant_connect(SERVER_REC *server, const char *msg) -{ - g_return_if_fail(server != NULL); - - lookup_servers = g_slist_remove(lookup_servers, server); - - signal_emit("server connect failed", 2, server, msg); - if (server->connect_tag != -1) - g_source_remove(server->connect_tag); - if (server->handle != NULL) - net_sendbuffer_destroy(server->handle, TRUE); - - if (server->connect_pipe[0] != -1) { - close(server->connect_pipe[0]); - close(server->connect_pipe[1]); - } - - MODULE_DATA_DEINIT(server); - g_free_not_null(server->nick); - g_free(server->tag); - g_free(server); -} - -/* generate tag from server's address */ -static char *server_create_address_tag(const char *address) -{ - const char *start, *end; - - /* try to generate a reasonable server tag */ - if (strchr(address, '.') == NULL) { - start = end = NULL; - } else if (g_strncasecmp(address, "irc", 3) == 0 || - g_strncasecmp(address, "chat", 4) == 0) { - /* irc-2.cs.hut.fi -> hut, chat.bt.net -> bt */ - end = strrchr(address, '.'); - start = end-1; - while (start > address && *start != '.') start--; - } else { - /* efnet.cs.hut.fi -> efnet */ - end = strchr(address, '.'); - start = end; - } - - if (start == end) start = address; else start++; - if (end == NULL) end = address + strlen(address); - - return g_strndup(start, (int) (end-start)); -} - -/* create unique tag for server. prefer ircnet's name or - generate it from server's address */ -static char *server_create_tag(SERVER_CONNECT_REC *conn) -{ - GString *str; - char *tag; - int num; - - tag = conn->ircnet != NULL ? g_strdup(conn->ircnet) : - server_create_address_tag(conn->address); - - /* then just append numbers after tag until unused is found.. */ - str = g_string_new(tag); - for (num = 2; server_find_tag(str->str) != NULL; num++) - g_string_sprintf(str, "%s%d", tag, num); - g_free(tag); - - tag = str->str; - g_string_free(str, FALSE); - return tag; -} - -static void server_connect_callback_init(SERVER_REC *server, int handle) -{ - int error; - - error = net_geterror(handle); - if (error != 0) { - server->connection_lost = TRUE; - server_cant_connect(server, g_strerror(error)); - return; - } - - lookup_servers = g_slist_remove(lookup_servers, server); - - g_source_remove(server->connect_tag); - server->connect_tag = -1; - server->connect_time = time(NULL); - server->rawlog = rawlog_create(); - servers = g_slist_append(servers, server); - - signal_emit("server connected", 1, server); -} - -static void server_connect_callback_readpipe(SERVER_REC *server) -{ - SERVER_CONNECT_REC *conn; - RESOLVED_IP_REC iprec; - const char *errormsg; - int handle; - - g_source_remove(server->connect_tag); - server->connect_tag = -1; - - net_gethostbyname_return(server->connect_pipe[0], &iprec); - - close(server->connect_pipe[0]); - close(server->connect_pipe[1]); - - server->connect_pipe[0] = -1; - server->connect_pipe[1] = -1; - - conn = server->connrec; - handle = iprec.error != 0 ? -1 : - net_connect_ip(&iprec.ip, conn->proxy != NULL ? - conn->proxy_port : conn->port, - conn->own_ip != NULL ? conn->own_ip : NULL); - if (handle == -1) { - /* failed */ - if (iprec.error == 0 || !net_hosterror_notfound(iprec.error)) { - /* reconnect back only if either - 1) connect() failed - 2) host name lookup failed not because the host - wasn't found, but because there was some - other error in nameserver */ - server->connection_lost = TRUE; - } - - if (iprec.error == 0) { - /* connect() failed */ - errormsg = g_strerror(errno); - } else { - /* gethostbyname() failed */ - errormsg = iprec.errorstr != NULL ? iprec.errorstr : - "Host lookup failed"; - } - server_cant_connect(server, errormsg); - g_free_not_null(iprec.errorstr); - return; - } - - server->handle = net_sendbuffer_create(handle, 0); - server->connect_tag = - g_input_add(handle, G_INPUT_WRITE | G_INPUT_READ, - (GInputFunction) server_connect_callback_init, - server); - signal_emit("server connecting", 2, server, &iprec.ip); -} - -int server_connect(SERVER_REC *server) -{ - const char *connect_address; - - g_return_val_if_fail(server != NULL, FALSE); - - MODULE_DATA_INIT(server); - - if (pipe(server->connect_pipe) != 0) { - g_warning("server_connect(): pipe() failed."); - return FALSE; - } - - server->tag = server_create_tag(server->connrec); - - connect_address = server->connrec->proxy != NULL ? - server->connrec->proxy : server->connrec->address; - server->connect_pid = - net_gethostbyname_nonblock(connect_address, - server->connect_pipe[1]); - server->connect_tag = - g_input_add(server->connect_pipe[0], G_INPUT_READ, - (GInputFunction) server_connect_callback_readpipe, - server); - - lookup_servers = g_slist_append(lookup_servers, server); - - signal_emit("server looking", 1, server); - return TRUE; -} - -void server_disconnect(SERVER_REC *server) -{ - g_return_if_fail(server != NULL); - - if (server->connect_tag != -1) { - /* still connecting to server.. */ - if (server->connect_pid != -1) - net_disconnect_nonblock(server->connect_pid); - server_cant_connect(server, NULL); - return; - } - - servers = g_slist_remove(servers, server); - - signal_emit("server disconnected", 1, server); - - if (server->handle != NULL) - net_sendbuffer_destroy(server->handle, TRUE); - if (server->readtag > 0) - g_source_remove(server->readtag); - - MODULE_DATA_DEINIT(server); - rawlog_destroy(server->rawlog); - line_split_free(server->buffer); - g_free_not_null(server->version); - g_free_not_null(server->away_reason); - g_free(server->nick); - g_free(server->tag); - g_free(server); -} - -SERVER_REC *server_find_tag(const char *tag) -{ - GSList *tmp; - - g_return_val_if_fail(tag != NULL, NULL); - if (*tag == '\0') return NULL; - - for (tmp = servers; tmp != NULL; tmp = tmp->next) { - SERVER_REC *server = tmp->data; - - if (g_strcasecmp(server->tag, tag) == 0) - return server; - } - - for (tmp = lookup_servers; tmp != NULL; tmp = tmp->next) { - SERVER_REC *server = tmp->data; - - if (g_strcasecmp(server->tag, tag) == 0) - return server; - } - - return NULL; -} - -SERVER_REC *server_find_ircnet(const char *ircnet) -{ - GSList *tmp; - - g_return_val_if_fail(ircnet != NULL, NULL); - if (*ircnet == '\0') return NULL; - - for (tmp = servers; tmp != NULL; tmp = tmp->next) { - SERVER_REC *server = tmp->data; - - if (server->connrec->ircnet != NULL && - g_strcasecmp(server->connrec->ircnet, ircnet) == 0) - return server; - } - - return NULL; -} - -void servers_init(void) -{ - lookup_servers = servers = NULL; - - servers_redirect_init(); -} - -void servers_deinit(void) -{ - while (servers != NULL) - server_disconnect(servers->data); - while (lookup_servers != NULL) - server_cant_connect(lookup_servers->data, NULL); - - servers_redirect_deinit(); -} diff --git a/src/core/server.h b/src/core/server.h deleted file mode 100644 index 25073379..00000000 --- a/src/core/server.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef __SERVER_H -#define __SERVER_H - -#ifndef __NETWORK_H -typedef struct _ipaddr IPADDR; -#endif - -/* all strings should be either NULL or dynamically allocated */ -/* address and nick are mandatory, rest are optional */ -typedef struct { - /* if we're connecting via proxy, or just NULLs */ - char *proxy; - int proxy_port; - char *proxy_string; - - char *address; - int port; - char *ircnet; - - IPADDR *own_ip; - - char *password; - char *nick; - char *username; - char *realname; - - /* when reconnecting, the old server status */ - int reconnection:1; /* we're trying to reconnect */ - char *channels; - char *away_reason; - char *usermode; -} SERVER_CONNECT_REC; - -typedef struct { - int type; /* server type */ - - SERVER_CONNECT_REC *connrec; - time_t connect_time; /* connection time */ - time_t real_connect_time; /* time when server replied that we really are connected */ - - char *tag; /* tag name for addressing server */ - char *nick; /* current nick */ - - int connected:1; /* connected to server */ - int connection_lost:1; /* Connection lost unintentionally */ - - void *handle; /* NET_SENDBUF_REC socket */ - int readtag; /* input tag */ - - /* for net_connect_nonblock() */ - int connect_pipe[2]; - int connect_tag; - int connect_pid; - - /* For deciding if event should be handled internally */ - GHashTable *eventtable; /* "event xxx" : GSList* of REDIRECT_RECs */ - GHashTable *eventgrouptable; /* event group : GSList* of REDIRECT_RECs */ - GHashTable *cmdtable; /* "command xxx" : REDIRECT_CMD_REC* */ - - void *rawlog; - void *buffer; /* receive buffer */ - GHashTable *module_data; - - char *version; /* server version */ - char *away_reason; - int usermode_away:1; - int banned:1; /* not allowed to connect to this server */ -} SERVER_REC; - -extern GSList *servers, *lookup_servers; - -/* Connect to server */ -int server_connect(SERVER_REC *server); -/* Disconnect from server */ -void server_disconnect(SERVER_REC *server); - -SERVER_REC *server_find_tag(const char *tag); -SERVER_REC *server_find_ircnet(const char *ircnet); - -void servers_init(void); -void servers_deinit(void); - -#endif diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c new file mode 100644 index 00000000..d4d8b942 --- /dev/null +++ b/src/core/servers-reconnect.c @@ -0,0 +1,356 @@ +/* + servers-reconnect.c : 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 "commands.h" +#include "network.h" +#include "signals.h" + +#include "servers-setup.h" +#include "servers-reconnect.h" + +#include "settings.h" + +GSList *reconnects; +static int last_reconnect_tag; +static int reconnect_timeout_tag; +static int reconnect_time; + +static void server_reconnect_add(SERVER_CONNECT_REC *conn, + time_t next_connect) +{ + RECONNECT_REC *rec; + + g_return_if_fail(IS_SERVER_CONNECT(conn)); + + rec = g_new(RECONNECT_REC, 1); + rec->tag = ++last_reconnect_tag; + rec->conn = conn; + rec->next_connect = next_connect; + + reconnects = g_slist_append(reconnects, rec); +} + +static void server_reconnect_destroy(RECONNECT_REC *rec, int free_conn) +{ + g_return_if_fail(rec != NULL); + + reconnects = g_slist_remove(reconnects, rec); + + signal_emit("server reconnect remove", 1, rec); + if (free_conn) server_connect_free(rec->conn); + g_free(rec); + + if (reconnects == NULL) + last_reconnect_tag = 0; +} + +static int server_reconnect_timeout(void) +{ + SERVER_CONNECT_REC *conn; + GSList *list, *tmp; + time_t now; + + /* If server_connect() removes the next reconnection in queue, + we're screwed. I don't think this should happen anymore, but just + to be sure we don't crash, do this safely. */ + list = g_slist_copy(reconnects); + now = time(NULL); + for (tmp = list; tmp != NULL; tmp = tmp->next) { + RECONNECT_REC *rec = tmp->data; + + if (g_slist_find(reconnects, rec) == NULL) + continue; + + if (rec->next_connect <= now) { + conn = rec->conn; + server_reconnect_destroy(rec, FALSE); + server_connect(conn); + } + } + + g_slist_free(list); + return 1; +} + +static void sserver_connect(SERVER_SETUP_REC *rec, SERVER_CONNECT_REC *conn) +{ + conn->address = g_strdup(rec->address); + conn->port = rec->port; + + server_setup_fill_reconn(conn, rec); + if (rec->last_connect > time(NULL)-reconnect_time) { + /* can't reconnect this fast, wait.. */ + server_reconnect_add(conn, rec->last_connect+reconnect_time); + } else { + /* connect to server.. */ + server_connect(conn); + } +} + +static SERVER_CONNECT_REC * +server_connect_copy_skeleton(SERVER_CONNECT_REC *src) +{ + SERVER_CONNECT_REC *dest; + + dest = NULL; + signal_emit("server connect copy", 2, &dest, src); + g_return_val_if_fail(dest != NULL, NULL); + + dest->proxy = g_strdup(src->proxy); + dest->proxy_port = src->proxy_port; + dest->proxy_string = g_strdup(src->proxy_string); + + dest->chatnet = g_strdup(src->chatnet); + dest->nick = g_strdup(src->nick); + dest->username = g_strdup(src->username); + dest->realname = g_strdup(src->realname); + + if (src->own_ip != NULL) { + dest->own_ip = g_new(IPADDR, 1); + memcpy(dest->own_ip, src->own_ip, sizeof(IPADDR)); + } + + dest->channels = g_strdup(src->channels); + dest->away_reason = g_strdup(src->away_reason); + + return dest; +} + +#define server_should_reconnect(server) \ + ((server)->connection_lost && \ + ((server)->connrec->chatnet != NULL || !(server)->banned)) + +static void sig_reconnect(SERVER_REC *server) +{ + SERVER_CONNECT_REC *conn; + SERVER_SETUP_REC *sserver; + GSList *tmp; + int found, through; + time_t now; + + g_return_if_fail(IS_SERVER(server)); + + if (reconnect_time == -1 || !server_should_reconnect(server)) + return; + + conn = server_connect_copy_skeleton(server->connrec); + + /* save the server status */ + if (server->connected) { + conn->reconnection = TRUE; + + g_free_not_null(conn->away_reason); + conn->away_reason = !server->usermode_away ? NULL : + g_strdup(server->away_reason); + + signal_emit("server reconnect save status", 2, conn, server); + } + + sserver = server_setup_find(server->connrec->address, + server->connrec->port); + + if (sserver != NULL) { + /* save the last connection time/status */ + sserver->last_connect = server->connect_time == 0 ? + time(NULL) : server->connect_time; + sserver->last_failed = !server->connected; + if (server->banned) sserver->banned = TRUE; + } + + if (sserver == NULL || conn->chatnet == NULL) { + /* not in any chatnet, just reconnect back to same server */ + conn->address = g_strdup(server->connrec->address); + conn->port = server->connrec->port; + conn->password = server->connrec->password == NULL ? NULL : + g_strdup(server->connrec->password); + + if (server->connect_time != 0 && + time(NULL)-server->connect_time > reconnect_time) { + /* there's been enough time since last connection, + reconnect back immediately */ + server_connect(conn); + } else { + /* reconnect later.. */ + server_reconnect_add(conn, (server->connect_time == 0 ? time(NULL) : + server->connect_time) + reconnect_time); + } + return; + } + + /* always try to first connect to the first on the list where we + haven't got unsuccessful connection attempts for the last half + an hour. */ + + now = time(NULL); + for (tmp = setupservers; tmp != NULL; tmp = tmp->next) { + SERVER_SETUP_REC *rec = tmp->data; + + if (rec->chatnet != NULL && g_strcasecmp(conn->chatnet, rec->chatnet) == 0 && + !rec->banned && (!rec->last_connect || !rec->last_failed || + rec->last_connect < now-FAILED_RECONNECT_WAIT)) { + sserver_connect(rec, conn); + return; + } + } + + /* just try the next server in list */ + found = through = FALSE; + for (tmp = setupservers; tmp != NULL; ) { + SERVER_SETUP_REC *rec = tmp->data; + + if (!found && g_strcasecmp(rec->address, server->connrec->address) == 0 && + server->connrec->port == rec->port) + found = TRUE; + else if (found && !rec->banned && rec->chatnet != NULL && + g_strcasecmp(conn->chatnet, rec->chatnet) == 0) { + sserver_connect(rec, conn); + break; + } + + if (tmp->next != NULL) { + tmp = tmp->next; + continue; + } + + if (through) { + /* shouldn't happen unless there's no servers in + this chatnet in setup.. */ + server_connect_free(conn); + break; + } + + tmp = setupservers; + found = through = TRUE; + } +} + +/* Remove all servers from reconnect list */ +/* SYNTAX: RMRECONNS */ +static void cmd_rmreconns(void) +{ + while (reconnects != NULL) + server_reconnect_destroy(reconnects->data, TRUE); +} + +static RECONNECT_REC *reconnect_find_tag(int tag) +{ + GSList *tmp; + + for (tmp = reconnects; tmp != NULL; tmp = tmp->next) { + RECONNECT_REC *rec = tmp->data; + + if (rec->tag == tag) + return rec; + } + + return NULL; +} + +/* Try to reconnect immediately */ +/* SYNTAX: RECONNECT */ +static void cmd_reconnect(const char *data, SERVER_REC *server) +{ + SERVER_CONNECT_REC *conn; + RECONNECT_REC *rec; + char *str; + int tag; + + if (*data == '\0') { + /* reconnect back to same server */ + if (server == NULL) cmd_return_error(CMDERR_NOT_CONNECTED); + str = g_strdup_printf("%s %d %s %s", server->connrec->address, + server->connrec->port, server->connrec->password, + server->connrec->nick); + signal_emit("command server", 2, str, server); + g_free(str); + return; + } + + if (g_strncasecmp(data, "RECON-", 6) == 0) + data += 6; + + tag = atoi(data); + rec = tag <= 0 ? NULL : reconnect_find_tag(tag); + + if (rec == NULL) + signal_emit("server reconnect not found", 1, data); + else { + conn = rec->conn; + server_reconnect_destroy(rec, FALSE); + server_connect(conn); + } +} + +static void cmd_disconnect(const char *data, SERVER_REC *server) +{ + RECONNECT_REC *rec; + int tag; + + if (g_strncasecmp(data, "RECON-", 6) != 0) + return; /* handle only reconnection removing */ + + rec = sscanf(data+6, "%d", &tag) == 1 && tag > 0 ? + reconnect_find_tag(tag) : NULL; + + if (rec == NULL) + signal_emit("server reconnect not found", 1, data); + else + server_reconnect_destroy(rec, TRUE); + signal_stop(); +} + +static void read_settings(void) +{ + reconnect_time = settings_get_int("server_reconnect_time"); +} + +void servers_reconnect_init(void) +{ + settings_add_int("server", "server_reconnect_time", 300); + + reconnects = NULL; + last_reconnect_tag = 0; + + reconnect_timeout_tag = g_timeout_add(1000, (GSourceFunc) server_reconnect_timeout, NULL); + read_settings(); + + signal_add("server connect failed", (SIGNAL_FUNC) sig_reconnect); + signal_add("server disconnected", (SIGNAL_FUNC) sig_reconnect); + command_bind("rmreconns", NULL, (SIGNAL_FUNC) cmd_rmreconns); + command_bind("reconnect", NULL, (SIGNAL_FUNC) cmd_reconnect); + command_bind_first("disconnect", NULL, (SIGNAL_FUNC) cmd_disconnect); + signal_add("setup changed", (SIGNAL_FUNC) read_settings); +} + +void servers_reconnect_deinit(void) +{ + g_source_remove(reconnect_timeout_tag); + + while (reconnects != NULL) + server_reconnect_destroy(reconnects->data, TRUE); + + signal_remove("server connect failed", (SIGNAL_FUNC) sig_reconnect); + signal_remove("server disconnected", (SIGNAL_FUNC) sig_reconnect); + command_unbind("rmreconns", (SIGNAL_FUNC) cmd_rmreconns); + command_unbind("reconnect", (SIGNAL_FUNC) cmd_reconnect); + command_unbind("disconnect", (SIGNAL_FUNC) cmd_disconnect); + signal_remove("setup changed", (SIGNAL_FUNC) read_settings); +} diff --git a/src/core/servers-reconnect.h b/src/core/servers-reconnect.h new file mode 100644 index 00000000..6b1da025 --- /dev/null +++ b/src/core/servers-reconnect.h @@ -0,0 +1,20 @@ +#ifndef __SERVER_RECONNECT_H +#define __SERVER_RECONNECT_H + +/* wait for half an hour before trying to reconnect to host where last + connection failed */ +#define FAILED_RECONNECT_WAIT (60*30) + +typedef struct { + int tag; + time_t next_connect; + + SERVER_CONNECT_REC *conn; +} RECONNECT_REC; + +extern GSList *reconnects; + +void servers_reconnect_init(void); +void servers_reconnect_deinit(void); + +#endif diff --git a/src/core/servers-redirect.c b/src/core/servers-redirect.c new file mode 100644 index 00000000..ca340fc6 --- /dev/null +++ b/src/core/servers-redirect.c @@ -0,0 +1,359 @@ +/* + server-redirect.c : 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 "misc.h" + +#include "servers.h" +#include "servers-redirect.h" + +static int redirect_group; + +static void server_eventtable_destroy(char *key, GSList *value) +{ + GSList *tmp; + + g_free(key); + + for (tmp = value; tmp != NULL; tmp = tmp->next) { + REDIRECT_REC *rec = tmp->data; + + g_free_not_null(rec->arg); + g_free(rec->name); + g_free(rec); + } + g_slist_free(value); +} + +static void server_eventgrouptable_destroy(gpointer key, GSList *value) +{ + g_slist_foreach(value, (GFunc) g_free, NULL); + g_slist_free(value); +} + +static void server_cmdtable_destroy(char *key, REDIRECT_CMD_REC *value) +{ + g_free(key); + + g_slist_foreach(value->events, (GFunc) g_free, NULL); + g_slist_free(value->events); + g_free(value); +} + +static void sig_disconnected(SERVER_REC *server) +{ + g_return_if_fail(IS_SERVER(server)); + + if (server->eventtable != NULL) { + g_hash_table_foreach(server->eventtable, + (GHFunc) server_eventtable_destroy, NULL); + g_hash_table_destroy(server->eventtable); + } + + g_hash_table_foreach(server->eventgrouptable, + (GHFunc) server_eventgrouptable_destroy, NULL); + g_hash_table_destroy(server->eventgrouptable); + + if (server->cmdtable != NULL) { + g_hash_table_foreach(server->cmdtable, + (GHFunc) server_cmdtable_destroy, NULL); + g_hash_table_destroy(server->cmdtable); + } +} + +void server_redirect_initv(SERVER_REC *server, const char *command, + int last, GSList *list) +{ + REDIRECT_CMD_REC *rec; + + g_return_if_fail(IS_SERVER(server)); + g_return_if_fail(command != NULL); + g_return_if_fail(last > 0); + + if (g_hash_table_lookup(server->cmdtable, command) != NULL) { + /* already in hash table. list of events SHOULD be the same. */ + g_slist_foreach(list, (GFunc) g_free, NULL); + g_slist_free(list); + return; + } + + rec = g_new(REDIRECT_CMD_REC, 1); + rec->last = last; + rec->events = list; + g_hash_table_insert(server->cmdtable, g_strdup(command), rec); +} + +void server_redirect_init(SERVER_REC *server, const char *command, + int last, ...) +{ + va_list args; + GSList *list; + char *event; + + va_start(args, last); + list = NULL; + while ((event = va_arg(args, gchar *)) != NULL) + list = g_slist_append(list, g_strdup(event)); + va_end(args); + + server_redirect_initv(server, command, last, list); +} + +int server_redirect_single_event(SERVER_REC *server, const char *arg, + int last, int group, const char *event, + const char *signal, int argpos) +{ + REDIRECT_REC *rec; + GSList *list, *grouplist; + char *origkey; + + g_return_val_if_fail(IS_SERVER(server), 0); + g_return_val_if_fail(event != NULL, 0); + g_return_val_if_fail(signal != NULL, 0); + g_return_val_if_fail(arg != NULL || argpos == -1, 0); + + if (group == 0) group = ++redirect_group; + + rec = g_new0(REDIRECT_REC, 1); + rec->arg = arg == NULL ? NULL : g_strdup(arg); + rec->argpos = argpos; + rec->name = g_strdup(signal); + rec->group = group; + rec->last = last; + + if (g_hash_table_lookup_extended(server->eventtable, event, + (gpointer *) &origkey, + (gpointer *) &list)) { + g_hash_table_remove(server->eventtable, origkey); + } else { + list = NULL; + origkey = g_strdup(event); + } + + grouplist = g_hash_table_lookup(server->eventgrouptable, + GINT_TO_POINTER(group)); + if (grouplist != NULL) { + g_hash_table_remove(server->eventgrouptable, + GINT_TO_POINTER(group)); + } + + list = g_slist_append(list, rec); + grouplist = g_slist_append(grouplist, g_strdup(event)); + + g_hash_table_insert(server->eventtable, origkey, list); + g_hash_table_insert(server->eventgrouptable, + GINT_TO_POINTER(group), grouplist); + + return group; +} + +void server_redirect_event(SERVER_REC *server, const char *arg, int last, ...) +{ + va_list args; + char *event, *signal; + int argpos, group; + + g_return_if_fail(IS_SERVER(server)); + + va_start(args, last); + + group = 0; + while ((event = va_arg(args, gchar *)) != NULL) { + signal = va_arg(args, gchar *); + argpos = va_arg(args, gint); + + group = server_redirect_single_event(server, arg, last > 0, + group, event, signal, + argpos); + last--; + } + + va_end(args); +} + +void server_redirect_default(SERVER_REC *server, const char *command) +{ + REDIRECT_CMD_REC *cmdrec; + REDIRECT_REC *rec; + GSList *events, *list, *grouplist; + char *event, *origkey; + int last; + + g_return_if_fail(IS_SERVER(server)); + g_return_if_fail(command != NULL); + + if (server->cmdtable == NULL) + return; /* not connected yet */ + + cmdrec = g_hash_table_lookup(server->cmdtable, command); + if (cmdrec == NULL) return; + + /* add all events used by command to eventtable and eventgrouptable */ + redirect_group++; grouplist = NULL; last = cmdrec->last; + for (events = cmdrec->events; events != NULL; events = events->next) { + event = events->data; + + if (g_hash_table_lookup_extended(server->eventtable, event, + (gpointer *) &origkey, + (gpointer *) &list)) { + g_hash_table_remove(server->eventtable, origkey); + } else { + list = NULL; + origkey = g_strdup(event); + } + + rec = g_new0(REDIRECT_REC, 1); + rec->argpos = -1; + rec->name = g_strdup(event); + rec->group = redirect_group; + rec->last = last > 0; + + grouplist = g_slist_append(grouplist, g_strdup(event)); + list = g_slist_append(list, rec); + g_hash_table_insert(server->eventtable, origkey, list); + + last--; + } + + g_hash_table_insert(server->eventgrouptable, + GINT_TO_POINTER(redirect_group), grouplist); +} + +void server_redirect_remove_next(SERVER_REC *server, const char *event, + GSList *item) +{ + REDIRECT_REC *rec; + GSList *grouplist, *list, *events, *tmp; + char *origkey; + int group; + + g_return_if_fail(IS_SERVER(server)); + g_return_if_fail(event != NULL); + + if (!g_hash_table_lookup_extended(server->eventtable, event, + (gpointer *) &origkey, + (gpointer *) &list)) + return; + + rec = item == NULL ? list->data : item->data; + if (!rec->last) { + /* this wasn't last expected event */ + return; + } + group = rec->group; + + /* get list of events from this group */ + grouplist = g_hash_table_lookup(server->eventgrouptable, + GINT_TO_POINTER(group)); + + /* remove all of them */ + for (list = grouplist; list != NULL; list = list->next) { + char *event = list->data; + + if (!g_hash_table_lookup_extended(server->eventtable, event, + (gpointer *) &origkey, + (gpointer *) &events)) { + g_warning("server_redirect_remove_next() : " + "event in eventgrouptable but not in " + "eventtable"); + continue; + } + + /* remove the right group */ + for (tmp = events; tmp != NULL; tmp = tmp->next) { + rec = tmp->data; + + if (rec->group == group) + break; + } + + if (rec == NULL) { + g_warning("server_redirect_remove_next() : " + "event in eventgrouptable but not in " + "eventtable (group)"); + continue; + } + + g_free(event); + + events = g_slist_remove(events, rec); + g_free_not_null(rec->arg); + g_free(rec->name); + g_free(rec); + + /* update hash table */ + g_hash_table_remove(server->eventtable, origkey); + if (events == NULL) + g_free(origkey); + else { + g_hash_table_insert(server->eventtable, + origkey, events); + } + } + + g_hash_table_remove(server->eventgrouptable, GINT_TO_POINTER(group)); + g_slist_free(grouplist); +} + +GSList *server_redirect_getqueue(SERVER_REC *server, const char *event, + const char *args) +{ + REDIRECT_REC *rec; + GSList *list; + char **arglist; + int found; + + g_return_val_if_fail(IS_SERVER(server), NULL); + g_return_val_if_fail(event != NULL, NULL); + + list = g_hash_table_lookup(server->eventtable, event); + + for (; list != NULL; list = list->next) { + rec = list->data; + if (rec->argpos == -1) + break; + + if (rec->arg == NULL || args == NULL) + continue; + + /* we need to check that the argument is right.. */ + arglist = g_strsplit(args, " ", -1); + found = (strarray_length(arglist) > rec->argpos && + find_substr(rec->arg, arglist[rec->argpos])); + g_strfreev(arglist); + + if (found) break; + } + + return list; +} + +void servers_redirect_init(void) +{ + redirect_group = 0; + + signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected); +} + +void servers_redirect_deinit(void) +{ + signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected); +} diff --git a/src/core/servers-redirect.h b/src/core/servers-redirect.h new file mode 100644 index 00000000..b47f7b3d --- /dev/null +++ b/src/core/servers-redirect.h @@ -0,0 +1,38 @@ +#ifndef __SERVERS_REDIRECT_H +#define __SERVERS_REDIRECT_H + +#include "servers.h" + +typedef struct { + int last; /* number of "last" events at the start of the events list */ + GSList *events; /* char* list of events */ +} REDIRECT_CMD_REC; + +typedef struct { + char *name; /* event name */ + + char *arg; /* argument for event we are expecting or NULL */ + int argpos; /* argument position */ + + int group; /* group of events this belongs to */ + int last; /* if this event is received, remove all the events in this group */ +} +REDIRECT_REC; + +void server_redirect_init(SERVER_REC *server, const char *command, int last, ...); +void server_redirect_initv(SERVER_REC *server, const char *command, int last, GSList *list); +/* ... = char *event1, char *event2, ..., NULL */ + +void server_redirect_event(SERVER_REC *server, const char *arg, int last, ...); +/* ... = char *event, char *callback_signal, int argpos, ..., NULL */ + +int server_redirect_single_event(SERVER_REC *server, const char *arg, int last, int group, + const char *event, const char *signal, int argpos); +void server_redirect_default(SERVER_REC *server, const char *command); +void server_redirect_remove_next(SERVER_REC *server, const char *event, GSList *item); +GSList *server_redirect_getqueue(SERVER_REC *server, const char *event, const char *args); + +void servers_redirect_init(void); +void servers_redirect_deinit(void); + +#endif diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c new file mode 100644 index 00000000..b314ca95 --- /dev/null +++ b/src/core/servers-setup.c @@ -0,0 +1,456 @@ +/* + servers-setup.c : 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 "network.h" +#include "lib-config/iconfig.h" +#include "settings.h" + +#include "servers.h" +#include "servers-setup.h" +#include "chatnets.h" + +GSList *setupservers; + +int source_host_ok; /* Use source_host_ip .. */ +IPADDR *source_host_ip; /* Resolved address */ + +static void get_source_host_ip(void) +{ + IPADDR ip; + + if (source_host_ok) + return; + + /* FIXME: This will block! */ + source_host_ok = *settings_get_str("hostname") != '\0' && + net_gethostbyname(settings_get_str("hostname"), &ip) == 0; + if (source_host_ok) { + if (source_host_ip == NULL) + source_host_ip = g_new(IPADDR, 1); + memcpy(source_host_ip, &ip, sizeof(IPADDR)); + } +} + +static void conn_set_ip(SERVER_CONNECT_REC *conn, + IPADDR **own_ip, const char *own_host) +{ + IPADDR ip; + + if (*own_ip != NULL) { + /* use already resolved IP */ + if (conn->own_ip == NULL) + conn->own_ip = g_new(IPADDR, 1); + memcpy(conn->own_ip, *own_ip, sizeof(IPADDR)); + return; + } + + + /* resolve the IP and use it */ + if (net_gethostbyname(own_host, &ip) == 0) { + if (conn->own_ip == NULL) + conn->own_ip = g_new(IPADDR, 1); + memcpy(conn->own_ip, &ip, sizeof(IPADDR)); + + *own_ip = g_new(IPADDR, 1); + memcpy(*own_ip, &ip, sizeof(IPADDR)); + } +} + +/* Fill information to connection from server setup record */ +void server_setup_fill_reconn(SERVER_CONNECT_REC *conn, + SERVER_SETUP_REC *sserver) +{ + g_return_if_fail(IS_SERVER_CONNECT(conn)); + g_return_if_fail(IS_SERVER_SETUP(sserver)); + + if (sserver->own_host != NULL) + conn_set_ip(conn, &sserver->own_ip, sserver->own_host); + + if (sserver->chatnet != NULL && conn->chatnet == NULL) + conn->chatnet = g_strdup(sserver->chatnet); + + if (sserver->password != NULL && conn->password == NULL) + conn->password = g_strdup(sserver->password); + + signal_emit("server setup fill reconn", 2, conn, sserver); +} + +static void server_setup_fill(SERVER_CONNECT_REC *conn, + const char *address, int port) +{ + g_return_if_fail(conn != NULL); + g_return_if_fail(address != NULL); + + conn->type = module_get_uniq_id("SERVER CONNECT", 0); + + conn->address = g_strdup(address); + conn->port = port > 0 ? port : 6667; + + if (!conn->nick) conn->nick = g_strdup(settings_get_str("default_nick")); + conn->username = g_strdup(settings_get_str("user_name")); + conn->realname = g_strdup(settings_get_str("real_name")); + + /* proxy settings */ + if (settings_get_bool("use_proxy")) { + conn->proxy = g_strdup(settings_get_str("proxy_address")); + conn->proxy_port = settings_get_int("proxy_port"); + conn->proxy_string = g_strdup(settings_get_str("proxy_string")); + } + + /* source IP */ + get_source_host_ip(); + if (source_host_ok) { + conn->own_ip = g_new(IPADDR, 1); + memcpy(conn->own_ip, source_host_ip, sizeof(IPADDR)); + } +} + +static void server_setup_fill_server(SERVER_CONNECT_REC *conn, + SERVER_SETUP_REC *sserver) +{ + g_return_if_fail(IS_SERVER_CONNECT(conn)); + g_return_if_fail(IS_SERVER_SETUP(sserver)); + + sserver->last_connect = time(NULL); + + if (sserver->port > 0) conn->port = sserver->port; + server_setup_fill_reconn(conn, sserver); + + signal_emit("server setup fill server", 2, conn, sserver); +} + +static void server_setup_fill_chatnet(SERVER_CONNECT_REC *conn, + CHATNET_REC *chatnet) +{ + g_return_if_fail(IS_SERVER_CONNECT(conn)); + g_return_if_fail(IS_CHATNET(chatnet)); + + if (chatnet->nick) { + g_free(conn->nick); + conn->nick = g_strdup(chatnet->nick);; + } + if (chatnet->username) { + g_free(conn->username); + conn->username = g_strdup(chatnet->username);; + } + if (chatnet->realname) { + g_free(conn->realname); + conn->realname = g_strdup(chatnet->realname);; + } + if (chatnet->own_host != NULL) + conn_set_ip(conn, &chatnet->own_ip, chatnet->own_host); + + signal_emit("server setup fill chatnet", 2, conn, chatnet); +} + +static SERVER_CONNECT_REC * +create_addr_conn(const char *address, int port, + const char *password, const char *nick) +{ + SERVER_CONNECT_REC *conn; + SERVER_SETUP_REC *sserver; + CHATNET_REC *chatnet; + + g_return_val_if_fail(address != NULL, NULL); + + sserver = server_setup_find(address, port); + chatnet = sserver->chatnet == NULL ? NULL : + chatnet_find(sserver->chatnet); + conn = NULL; + signal_emit("server setup connect", 2, &conn, chatnet); + if (conn == NULL) { + /* no chat protocol wanted this server? */ + return NULL; + } + + /* fill in the defaults */ + server_setup_fill(conn, address, port); + + /* fill the rest from chat network settings */ + if (chatnet != NULL) + server_setup_fill_chatnet(conn, chatnet); + + /* fill the information from setup */ + if (sserver != NULL) + server_setup_fill_server(conn, sserver); + + /* nick / password given in command line overrides all settings */ + if (password && *password) { + g_free_not_null(conn->password); + conn->password = g_strdup(password); + } + if (nick && *nick) { + g_free_not_null(conn->nick); + conn->nick = g_strdup(nick); + } + + return conn; +} + +/* Connect to server where last connect succeeded (or we haven't tried to + connect yet). If there's no such server, connect to server where we + haven't connected for the longest time */ +static SERVER_CONNECT_REC * +create_chatnet_conn(const char *dest, int port, + const char *password, const char *nick) +{ + SERVER_SETUP_REC *bestrec; + GSList *tmp; + time_t now, besttime; + + now = time(NULL); + bestrec = NULL; besttime = now; + for (tmp = setupservers; tmp != NULL; tmp = tmp->next) { + SERVER_SETUP_REC *rec = tmp->data; + + if (rec->chatnet == NULL || + g_strcasecmp(rec->chatnet, dest) != 0) + continue; + + if (!rec->last_failed) { + bestrec = rec; + break; + } + + if (bestrec == NULL || besttime > rec->last_connect) { + bestrec = rec; + besttime = rec->last_connect; + } + } + + return bestrec == NULL ? NULL : + create_addr_conn(bestrec->address, 0, NULL, nick); +} + +/* Create server connection record. `dest' is required, rest can be NULL. + `dest' is either a server address or chat network */ +SERVER_CONNECT_REC * +server_create_conn(const char *dest, int port, + const char *password, const char *nick) +{ + SERVER_CONNECT_REC *rec; + + g_return_val_if_fail(dest != NULL, NULL); + + if (chatnet_find(dest)) { + rec = create_chatnet_conn(dest, port, password, nick); + if (rec != NULL) + return rec; + } + + return create_addr_conn(dest, port, password, nick); +} + +/* Find matching server from setup. Try to find record with a same port, + but fallback to any server with the same address. */ +SERVER_SETUP_REC *server_setup_find(const char *address, int port) +{ + SERVER_SETUP_REC *server; + GSList *tmp; + + g_return_val_if_fail(address != NULL, NULL); + + server = NULL; + for (tmp = setupservers; tmp != NULL; tmp = tmp->next) { + SERVER_SETUP_REC *rec = tmp->data; + + if (g_strcasecmp(rec->address, address) == 0) { + server = rec; + if (rec->port == port) + break; + } + } + + return server; +} + +/* Find matching server from setup. Ports must match or NULL is returned. */ +SERVER_SETUP_REC *server_setup_find_port(const char *address, int port) +{ + SERVER_SETUP_REC *rec; + + rec = server_setup_find(address, port); + return rec == NULL || rec->port != port ? NULL : rec; +} + +static SERVER_SETUP_REC *server_setup_read(CONFIG_NODE *node) +{ + SERVER_SETUP_REC *rec; + char *server, *chatnet; + int port; + + g_return_val_if_fail(node != NULL, NULL); + + server = config_node_get_str(node, "address", NULL); + if (server == NULL) + return NULL; + + port = config_node_get_int(node, "port", 6667); + if (server_setup_find_port(server, port) != NULL) { + /* already exists - don't let it get there twice or + server reconnects will screw up! */ + return NULL; + } + + rec = NULL; + chatnet = config_node_get_str(node, "chatnet", NULL); + signal_emit("server setup read", 3, &rec, node, + chatnet == NULL ? NULL : chatnet_find(chatnet)); + if (rec == NULL) { + /* no chat protocol wanted this server? */ + return NULL; + } + + rec->type = module_get_uniq_id("SERVER SETUP", 0); + rec->chatnet = g_strdup(chatnet); + rec->address = g_strdup(server); + rec->password = g_strdup(config_node_get_str(node, "password", NULL)); + rec->port = port; + rec->autoconnect = config_node_get_bool(node, "autoconnect", FALSE); + rec->own_host = g_strdup(config_node_get_str(node, "own_host", 0)); + + setupservers = g_slist_append(setupservers, rec); + return rec; +} + +static void server_setup_save(SERVER_SETUP_REC *rec) +{ + CONFIG_NODE *parentnode, *node; + int index; + + index = g_slist_index(setupservers, rec); + + parentnode = iconfig_node_traverse("(servers", TRUE); + node = config_node_index(parentnode, index); + if (node == NULL) + node = config_node_section(parentnode, NULL, NODE_TYPE_BLOCK); + + iconfig_node_clear(node); + iconfig_node_set_str(node, "address", rec->address); + iconfig_node_set_str(node, "chatnet", rec->chatnet); + + config_node_set_int(node, "port", rec->port); + iconfig_node_set_str(node, "password", rec->password); + iconfig_node_set_str(node, "own_host", rec->own_host); + + if (rec->autoconnect) + config_node_set_bool(node, "autoconnect", TRUE); + + signal_emit("server setup saved", 2, rec, node); +} + +static void server_setup_remove_config(SERVER_SETUP_REC *rec) +{ + CONFIG_NODE *node; + int index; + + node = iconfig_node_traverse("servers", FALSE); + if (node != NULL) { + index = g_slist_index(setupservers, rec); + iconfig_node_list_remove(node, index); + } +} + +static void server_setup_destroy(SERVER_SETUP_REC *rec) +{ + setupservers = g_slist_remove(setupservers, rec); + signal_emit("server setup destroyed", 1, rec); + + g_free_not_null(rec->own_host); + g_free_not_null(rec->own_ip); + g_free_not_null(rec->chatnet); + g_free(rec->address); + g_free_not_null(rec->password); + g_free(rec); +} + +void server_setup_add(SERVER_SETUP_REC *rec) +{ + if (g_slist_find(setupservers, rec) == NULL) + setupservers = g_slist_append(setupservers, rec); + server_setup_save(rec); +} + +void server_setup_remove(SERVER_SETUP_REC *rec) +{ + server_setup_remove_config(rec); + server_setup_destroy(rec); +} + +static void read_servers(void) +{ + CONFIG_NODE *node; + GSList *tmp; + + while (setupservers != NULL) + server_setup_destroy(setupservers->data); + + /* Read servers */ + node = iconfig_node_traverse("servers", FALSE); + if (node != NULL) { + for (tmp = node->value; tmp != NULL; tmp = tmp->next) + server_setup_read(tmp->data); + } +} + +static void read_settings(void) +{ + g_free_and_null(source_host_ip); + + source_host_ok = FALSE; + get_source_host_ip(); +} + +void servers_setup_init(void) +{ + settings_add_str("server", "hostname", ""); + + settings_add_str("server", "default_nick", NULL); + settings_add_str("server", "user_name", NULL); + settings_add_str("server", "real_name", NULL); + + settings_add_bool("proxy", "use_proxy", FALSE); + settings_add_str("proxy", "proxy_address", ""); + settings_add_int("proxy", "proxy_port", 6667); + settings_add_str("proxy", "proxy_string", "CONNECT %s %d"); + + source_host_ip = NULL; + read_settings(); + + signal_add("setup changed", (SIGNAL_FUNC) read_settings); + signal_add("setup reread", (SIGNAL_FUNC) read_servers); + signal_add("irssi init read settings", (SIGNAL_FUNC) read_servers); +} + +void servers_setup_deinit(void) +{ + g_free_not_null(source_host_ip); + + while (setupservers != NULL) + server_setup_destroy(setupservers->data); + + signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + signal_remove("setup reread", (SIGNAL_FUNC) read_servers); + signal_remove("irssi init read settings", (SIGNAL_FUNC) read_servers); + + module_uniq_destroy("SERVER SETUP"); +} diff --git a/src/core/servers-setup.h b/src/core/servers-setup.h new file mode 100644 index 00000000..247189ff --- /dev/null +++ b/src/core/servers-setup.h @@ -0,0 +1,46 @@ +#ifndef __SERVERS_SETUP_H +#define __SERVERS_SETUP_H + +#include "servers.h" + +#define IS_SERVER_SETUP(server) \ + ((server) != NULL && \ + module_find_id("SERVER SETUP", (server)->type) != -1) + +#define SERVER_SETUP(server) \ + (IS_SERVER_SETUP(server) ? (SERVER_SETUP_REC *) (server) : NULL) + +/* servers */ +typedef struct { +#include "server-setup-rec.h" +} SERVER_SETUP_REC; + +extern GSList *setupservers; + +extern IPADDR *source_host_ip; /* Resolved address */ +extern int source_host_ok; /* Use source_host_ip .. */ + +/* Fill reconnection specific information to connection + from server setup record */ +void server_setup_fill_reconn(SERVER_CONNECT_REC *conn, + SERVER_SETUP_REC *sserver); + +/* Create server connection record. `dest' is required, rest can be NULL. + `dest' is either a server address or chat network */ +SERVER_CONNECT_REC * +server_create_conn(const char *dest, int port, + const char *password, const char *nick); + +/* Find matching server from setup. Try to find record with a same port, + but fallback to any server with the same address. */ +SERVER_SETUP_REC *server_setup_find(const char *address, int port); +/* Find matching server from setup. Ports must match or NULL is returned. */ +SERVER_SETUP_REC *server_setup_find_port(const char *address, int port); + +void server_setup_add(SERVER_SETUP_REC *rec); +void server_setup_remove(SERVER_SETUP_REC *rec); + +void servers_setup_init(void); +void servers_setup_deinit(void); + +#endif diff --git a/src/core/servers.c b/src/core/servers.c new file mode 100644 index 00000000..f6f353d6 --- /dev/null +++ b/src/core/servers.c @@ -0,0 +1,403 @@ +/* + server.c : 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 "line-split.h" +#include "net-nonblock.h" +#include "net-sendbuffer.h" +#include "misc.h" +#include "rawlog.h" +#include "settings.h" + +#include "servers.h" +#include "servers-redirect.h" +#include "servers-setup.h" +#include "channels.h" +#include "queries.h" + +GSList *servers, *lookup_servers; + +/* connection to server failed */ +static void server_cant_connect(SERVER_REC *server, const char *msg) +{ + g_return_if_fail(IS_SERVER(server)); + + lookup_servers = g_slist_remove(lookup_servers, server); + + signal_emit("server connect failed", 2, server, msg); + if (server->connect_tag != -1) + g_source_remove(server->connect_tag); + if (server->handle != NULL) + net_sendbuffer_destroy(server->handle, TRUE); + + if (server->connect_pipe[0] != -1) { + close(server->connect_pipe[0]); + close(server->connect_pipe[1]); + } + + MODULE_DATA_DEINIT(server); + server_connect_free(server->connrec); + g_free_not_null(server->nick); + g_free(server->tag); + g_free(server); +} + +/* generate tag from server's address */ +static char *server_create_address_tag(const char *address) +{ + const char *start, *end; + + g_return_val_if_fail(address != NULL, NULL); + + /* try to generate a reasonable server tag */ + if (strchr(address, '.') == NULL) { + start = end = NULL; + } else if (g_strncasecmp(address, "irc", 3) == 0 || + g_strncasecmp(address, "chat", 4) == 0) { + /* irc-2.cs.hut.fi -> hut, chat.bt.net -> bt */ + end = strrchr(address, '.'); + start = end-1; + while (start > address && *start != '.') start--; + } else { + /* efnet.cs.hut.fi -> efnet */ + end = strchr(address, '.'); + start = end; + } + + if (start == end) start = address; else start++; + if (end == NULL) end = address + strlen(address); + + return g_strndup(start, (int) (end-start)); +} + +/* create unique tag for server. prefer ircnet's name or + generate it from server's address */ +static char *server_create_tag(SERVER_CONNECT_REC *conn) +{ + GString *str; + char *tag; + int num; + + g_return_val_if_fail(IS_SERVER_CONNECT(conn), NULL); + + tag = conn->chatnet != NULL ? g_strdup(conn->chatnet) : + server_create_address_tag(conn->address); + + /* then just append numbers after tag until unused is found.. */ + str = g_string_new(tag); + for (num = 2; server_find_tag(str->str) != NULL; num++) + g_string_sprintf(str, "%s%d", tag, num); + g_free(tag); + + tag = str->str; + g_string_free(str, FALSE); + return tag; +} + +static void server_connect_callback_init(SERVER_REC *server, int handle) +{ + int error; + + g_return_if_fail(IS_SERVER(server)); + + error = net_geterror(handle); + if (error != 0) { + server->connection_lost = TRUE; + server_cant_connect(server, g_strerror(error)); + return; + } + + lookup_servers = g_slist_remove(lookup_servers, server); + + g_source_remove(server->connect_tag); + server->connect_tag = -1; + server->connect_time = time(NULL); + server->rawlog = rawlog_create(); + + server->eventtable = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); + server->eventgrouptable = g_hash_table_new((GHashFunc) g_direct_hash, (GCompareFunc) g_direct_equal); + server->cmdtable = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); + + servers = g_slist_append(servers, server); + signal_emit("server connected", 1, server); +} + +static void server_connect_callback_readpipe(SERVER_REC *server) +{ + SERVER_CONNECT_REC *conn; + RESOLVED_IP_REC iprec; + const char *errormsg; + int handle; + + g_return_if_fail(IS_SERVER(server)); + + g_source_remove(server->connect_tag); + server->connect_tag = -1; + + net_gethostbyname_return(server->connect_pipe[0], &iprec); + + close(server->connect_pipe[0]); + close(server->connect_pipe[1]); + + server->connect_pipe[0] = -1; + server->connect_pipe[1] = -1; + + conn = server->connrec; + handle = iprec.error != 0 ? -1 : + net_connect_ip(&iprec.ip, conn->proxy != NULL ? + conn->proxy_port : conn->port, + conn->own_ip != NULL ? conn->own_ip : NULL); + if (handle == -1) { + /* failed */ + if (iprec.error == 0 || !net_hosterror_notfound(iprec.error)) { + /* reconnect back only if either + 1) connect() failed + 2) host name lookup failed not because the host + wasn't found, but because there was some + other error in nameserver */ + server->connection_lost = TRUE; + } + + if (iprec.error == 0) { + /* connect() failed */ + errormsg = g_strerror(errno); + } else { + /* gethostbyname() failed */ + errormsg = iprec.errorstr != NULL ? iprec.errorstr : + "Host lookup failed"; + } + server_cant_connect(server, errormsg); + g_free_not_null(iprec.errorstr); + return; + } + + server->handle = net_sendbuffer_create(handle, 0); + server->connect_tag = + g_input_add(handle, G_INPUT_WRITE | G_INPUT_READ, + (GInputFunction) server_connect_callback_init, + server); + signal_emit("server connecting", 2, server, &iprec.ip); +} + +int server_start_connect(SERVER_REC *server) +{ + const char *connect_address; + + g_return_val_if_fail(server != NULL, FALSE); + + MODULE_DATA_INIT(server); + server->type = module_get_uniq_id("SERVER", 0); + + if (pipe(server->connect_pipe) != 0) { + g_warning("server_connect(): pipe() failed."); + return FALSE; + } + + server->tag = server_create_tag(server->connrec); + + connect_address = server->connrec->proxy != NULL ? + server->connrec->proxy : server->connrec->address; + server->connect_pid = + net_gethostbyname_nonblock(connect_address, + server->connect_pipe[1]); + server->connect_tag = + g_input_add(server->connect_pipe[0], G_INPUT_READ, + (GInputFunction) server_connect_callback_readpipe, + server); + + lookup_servers = g_slist_append(lookup_servers, server); + + signal_emit("server looking", 1, server); + return TRUE; +} + +/* Connect to server */ +SERVER_REC *server_connect(SERVER_CONNECT_REC *conn) +{ + SERVER_REC *server; + + g_return_val_if_fail(IS_SERVER_CONNECT(conn), NULL); + + server = NULL; + signal_emit("server connect", 2, &server, conn); + return server; +} + +static int server_remove_channels(SERVER_REC *server) +{ + GSList *tmp; + int found; + + g_return_val_if_fail(server != NULL, FALSE); + + found = FALSE; + for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { + CHANNEL_REC *channel = tmp->data; + + channel->server = NULL; + channel_destroy(channel); + found = TRUE; + } + + for (tmp = server->queries; tmp != NULL; tmp = tmp->next) + query_change_server(tmp->data, NULL); + + g_slist_free(server->channels); + g_slist_free(server->queries); + + return found; +} + +void server_disconnect(SERVER_REC *server) +{ + int chans; + + g_return_if_fail(IS_SERVER(server)); + + if (server->connect_tag != -1) { + /* still connecting to server.. */ + if (server->connect_pid != -1) + net_disconnect_nonblock(server->connect_pid); + server_cant_connect(server, NULL); + return; + } + + servers = g_slist_remove(servers, server); + + signal_emit("server disconnected", 1, server); + + /* close all channels */ + chans = server_remove_channels(server); + + if (server->handle != NULL) { + if (!chans || server->connection_lost) + net_sendbuffer_destroy(server->handle, TRUE); + else { + /* we were on some channels, try to let the server + disconnect so that our quit message is guaranteed + to get displayed */ + net_disconnect_later(net_sendbuffer_handle(server->handle)); + net_sendbuffer_destroy(server->handle, FALSE); + } + server->handle = NULL; + } + + if (server->readtag > 0) + g_source_remove(server->readtag); + + MODULE_DATA_DEINIT(server); + server_connect_free(server->connrec); + rawlog_destroy(server->rawlog); + line_split_free(server->buffer); + g_free_not_null(server->version); + g_free_not_null(server->away_reason); + g_free(server->nick); + g_free(server->tag); + g_free(server); +} + +SERVER_REC *server_find_tag(const char *tag) +{ + GSList *tmp; + + g_return_val_if_fail(tag != NULL, NULL); + if (*tag == '\0') return NULL; + + for (tmp = servers; tmp != NULL; tmp = tmp->next) { + SERVER_REC *server = tmp->data; + + if (g_strcasecmp(server->tag, tag) == 0) + return server; + } + + for (tmp = lookup_servers; tmp != NULL; tmp = tmp->next) { + SERVER_REC *server = tmp->data; + + if (g_strcasecmp(server->tag, tag) == 0) + return server; + } + + return NULL; +} + +SERVER_REC *server_find_chatnet(const char *chatnet) +{ + GSList *tmp; + + g_return_val_if_fail(chatnet != NULL, NULL); + if (*chatnet == '\0') return NULL; + + for (tmp = servers; tmp != NULL; tmp = tmp->next) { + SERVER_REC *server = tmp->data; + + if (server->connrec->chatnet != NULL && + g_strcasecmp(server->connrec->chatnet, chatnet) == 0) + return server; + } + + return NULL; +} + +void server_connect_free(SERVER_CONNECT_REC *conn) +{ + g_return_if_fail(IS_SERVER_CONNECT(conn)); + + signal_emit("server connect free", 1, conn); + g_free_not_null(conn->proxy); + g_free_not_null(conn->proxy_string); + + g_free_not_null(conn->address); + g_free_not_null(conn->chatnet); + + g_free_not_null(conn->own_ip); + + g_free_not_null(conn->password); + g_free_not_null(conn->nick); + g_free_not_null(conn->username); + g_free_not_null(conn->realname); + + g_free_not_null(conn->channels); + g_free_not_null(conn->away_reason); + g_free_not_null(conn->usermode); + g_free(conn); +} + +void servers_init(void) +{ + lookup_servers = servers = NULL; + + servers_redirect_init(); + servers_setup_init(); +} + +void servers_deinit(void) +{ + while (servers != NULL) + server_disconnect(servers->data); + while (lookup_servers != NULL) + server_cant_connect(lookup_servers->data, NULL); + + servers_setup_deinit(); + servers_redirect_deinit(); + + module_uniq_destroy("SERVER"); + module_uniq_destroy("SERVER CONNECT"); +} diff --git a/src/core/servers.h b/src/core/servers.h new file mode 100644 index 00000000..169c8e88 --- /dev/null +++ b/src/core/servers.h @@ -0,0 +1,52 @@ +#ifndef __SERVERS_H +#define __SERVERS_H + +#include "modules.h" + +#ifndef __NETWORK_H +typedef struct _ipaddr IPADDR; +#endif + +#define IS_SERVER(server) \ + ((server) != NULL && module_find_id("SERVER", (server)->type) != -1) + +#define IS_SERVER_CONNECT(conn) \ + ((conn) != NULL && \ + module_find_id("SERVER CONNECT", (conn)->type) != -1) + +/* Returns SERVER_REC if it's server, NULL if it isn't. */ +#define SERVER(server) \ + (IS_SERVER(server) ? (SERVER_REC *) (server) : NULL) + +/* Returns SERVER_CONNECT_REC if it's server connection, NULL if it isn't. */ +#define SERVER_CONNECT(conn) \ + (IS_SERVER_CONNECT(conn) ? (SERVER_CONNECT_REC *) (conn) : NULL) + +/* all strings should be either NULL or dynamically allocated */ +/* address and nick are mandatory, rest are optional */ +typedef struct { +#include "server-connect-rec.h" +} SERVER_CONNECT_REC; + +#define STRUCT_SERVER_CONNECT_REC SERVER_CONNECT_REC +typedef struct { +#include "server-rec.h" +} SERVER_REC; + +extern GSList *servers, *lookup_servers; + +void servers_init(void); +void servers_deinit(void); + +/* Connect to server */ +SERVER_REC *server_connect(SERVER_CONNECT_REC *conn); +/* Disconnect from server */ +void server_disconnect(SERVER_REC *server); + +SERVER_REC *server_find_tag(const char *tag); +SERVER_REC *server_find_chatnet(const char *chatnet); + +int server_start_connect(SERVER_REC *server); +void server_connect_free(SERVER_CONNECT_REC *conn); + +#endif diff --git a/src/core/settings.h b/src/core/settings.h index 0a53a6ee..a887797a 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -32,6 +32,7 @@ typedef struct { #define iconfig_node_set_str(a, b, c) config_node_set_str(mainconfig, a, b, c) #define iconfig_node_list_remove(a, b) config_node_list_remove(mainconfig, a, b) #define iconfig_node_remove(a, b) config_node_remove(mainconfig, a, b) +#define iconfig_node_clear(a) config_node_clear(mainconfig, a) extern CONFIG_REC *mainconfig; diff --git a/src/core/signals.c b/src/core/signals.c index 1b62f55c..7b309785 100644 --- a/src/core/signals.c +++ b/src/core/signals.c @@ -310,7 +310,8 @@ void signal_stop_by_name(const char *signal) static void signal_remove_module(void *signal, SIGNAL_REC *rec, const char *module) { - int signal_id, list, index; + unsigned int index; + int signal_id, list; signal_id = GPOINTER_TO_INT(signal); diff --git a/src/core/special-vars.c b/src/core/special-vars.c index 20f82e10..1aa081e9 100644 --- a/src/core/special-vars.c +++ b/src/core/special-vars.c @@ -25,6 +25,10 @@ #include "misc.h" #include "irssi-version.h" +#include "channels.h" +#include "queries.h" +#include "window-item-def.h" + #include #define ALIGN_RIGHT 0x01 @@ -99,7 +103,7 @@ static char *get_internal_setting(const char *key, int type, int *free_ret) return NULL; } -static char *get_long_variable_value(const char *key, void *server, +static char *get_long_variable_value(const char *key, SERVER_REC *server, void *item, int *free_ret) { EXPANDO_FUNC func; @@ -126,7 +130,7 @@ static char *get_long_variable_value(const char *key, void *server, return NULL; } -static char *get_long_variable(char **cmd, void *server, +static char *get_long_variable(char **cmd, SERVER_REC *server, void *item, int *free_ret) { char *start, *var, *ret; @@ -142,7 +146,7 @@ static char *get_long_variable(char **cmd, void *server, } /* return the value of the variable found from `cmd' */ -static char *get_variable(char **cmd, void *server, void *item, +static char *get_variable(char **cmd, SERVER_REC *server, void *item, char **arglist, int *free_ret, int *arg_used) { if (isdigit(**cmd) || **cmd == '*' || **cmd == '-' || **cmd == '~') { @@ -183,7 +187,7 @@ static char *get_history(char **cmd, void *item, int *free_ret) return ret; } -static char *get_special_value(char **cmd, void *server, void *item, +static char *get_special_value(char **cmd, SERVER_REC *server, void *item, char **arglist, int *free_ret, int *arg_used) { char command, *value, *p; @@ -313,7 +317,7 @@ static char *get_alignment(const char *text, int align, int flags, char pad) /* Parse and expand text after '$' character. return value has to be g_free()'d if `free_ret' is TRUE. */ -char *parse_special(char **cmd, void *server, void *item, +char *parse_special(char **cmd, SERVER_REC *server, void *item, char **arglist, int *free_ret, int *arg_used) { static char **nested_orig_cmd = NULL; /* FIXME: KLUDGE! */ @@ -405,7 +409,7 @@ char *parse_special(char **cmd, void *server, void *item, } /* parse the whole string. $ and \ chars are replaced */ -char *parse_special_string(const char *cmd, void *server, void *item, +char *parse_special_string(const char *cmd, SERVER_REC *server, void *item, const char *data, int *arg_used) { char code, **arglist, *ret; @@ -466,7 +470,7 @@ char *parse_special_string(const char *cmd, void *server, void *item, /* execute the commands in string - commands can be split with ';' */ void eval_special_string(const char *cmd, const char *data, - void *server, void *item) + SERVER_REC *server, void *item) { const char *cmdchars; char *orig, *str, *start, *ret; @@ -556,40 +560,101 @@ void special_history_func_set(SPECIAL_HISTORY_FUNC func) history_func = func; } +/* text of your AWAY message, if any */ +static char *expando_awaymsg(SERVER_REC *server, void *item, int *free_ret) +{ + return server == NULL ? "" : server->away_reason; +} + +/* current channel */ +static char *expando_channel(SERVER_REC *server, void *item, int *free_ret) +{ + return !IS_CHANNEL(item) ? NULL : CHANNEL(item)->name; +} + /* time client was started, $time() format */ -static char *expando_clientstarted(void *server, void *item, int *free_ret) +static char *expando_clientstarted(SERVER_REC *server, void *item, int *free_ret) { *free_ret = TRUE; return g_strdup_printf("%ld", (long) client_start_time); } /* client version text string */ -static char *expando_version(void *server, void *item, int *free_ret) +static char *expando_version(SERVER_REC *server, void *item, int *free_ret) { return IRSSI_VERSION; } /* current value of CMDCHARS */ -static char *expando_cmdchars(void *server, void *item, int *free_ret) +static char *expando_cmdchars(SERVER_REC *server, void *item, int *free_ret) { return (char *) settings_get_str("cmdchars"); } +/* modes of current channel, if any */ +static char *expando_chanmode(SERVER_REC *server, void *item, int *free_ret) +{ + return !IS_CHANNEL(item) ? NULL : CHANNEL(item)->mode; +} + +/* current nickname */ +static char *expando_nick(SERVER_REC *server, void *item, int *free_ret) +{ + return server == NULL ? "" : server->nick; +} + +/* value of STATUS_OPER if you are an irc operator */ +static char *expando_statusoper(SERVER_REC *server, void *item, int *free_ret) +{ + return server == NULL || !server->server_operator ? "" : + (char *) settings_get_str("STATUS_OPER"); +} + +/* if you are a channel operator in $C, expands to a '@' */ +static char *expando_chanop(SERVER_REC *server, void *item, int *free_ret) +{ + return IS_CHANNEL(item) && CHANNEL(item)->chanop ? "@" : ""; +} + +/* nickname of whomever you are QUERYing */ +static char *expando_query(SERVER_REC *server, void *item, int *free_ret) +{ + return !IS_QUERY(item) ? "" : QUERY(item)->name; +} + +/* version of current server */ +static char *expando_serverversion(SERVER_REC *server, void *item, int *free_ret) +{ + return server == NULL ? "" : server->version; +} + +/* target of current input (channel or QUERY nickname) */ +static char *expando_target(SERVER_REC *server, void *item, int *free_ret) +{ + return ((WI_ITEM_REC *) item)->name; +} + /* client release date (numeric version string) */ -static char *expando_releasedate(void *server, void *item, int *free_ret) +static char *expando_releasedate(SERVER_REC *server, void *item, int *free_ret) { return IRSSI_VERSION_DATE; } /* current working directory */ -static char *expando_workdir(void *server, void *item, int *free_ret) +static char *expando_workdir(SERVER_REC *server, void *item, int *free_ret) { *free_ret = TRUE; return g_get_current_dir(); } +/* value of REALNAME */ +static char *expando_realname(SERVER_REC *server, void *item, int *free_ret) +{ + return server == NULL ? "" : server->connrec->realname; +} + /* time of day (hh:mm) */ -static char *expando_time(void *server, void *item, int *free_ret) +static char *expando_time(SERVER_REC *server, void *item, int *free_ret) { time_t now = time(NULL); struct tm *tm; @@ -600,13 +665,13 @@ static char *expando_time(void *server, void *item, int *free_ret) } /* a literal '$' */ -static char *expando_dollar(void *server, void *item, int *free_ret) +static char *expando_dollar(SERVER_REC *server, void *item, int *free_ret) { return "$"; } /* system name */ -static char *expando_sysname(void *server, void *item, int *free_ret) +static char *expando_sysname(SERVER_REC *server, void *item, int *free_ret) { struct utsname un; @@ -619,7 +684,7 @@ static char *expando_sysname(void *server, void *item, int *free_ret) } /* system release */ -static char *expando_sysrelease(void *server, void *item, int *free_ret) +static char *expando_sysrelease(SERVER_REC *server, void *item, int *free_ret) { struct utsname un; @@ -631,8 +696,22 @@ static char *expando_sysrelease(void *server, void *item, int *free_ret) } +/* Server tag */ +static char *expando_servertag(SERVER_REC *server, void *item, int *free_ret) +{ + return server == NULL ? "" : server->tag; +} + +/* Server chatnet */ +static char *expando_chatnet(SERVER_REC *server, void *item, int *free_ret) +{ + return server == NULL ? "" : server->connrec->chatnet; +} + void special_vars_init(void) { + settings_add_str("misc", "STATUS_OPER", "*"); + client_start_time = time(NULL); memset(char_expandos, 0, sizeof(char_expandos)); @@ -640,22 +719,36 @@ void special_vars_init(void) (GCompareFunc) g_str_equal); history_func = NULL; + char_expandos['A'] = expando_awaymsg; + char_expandos['C'] = expando_channel; char_expandos['F'] = expando_clientstarted; char_expandos['J'] = expando_version; char_expandos['K'] = expando_cmdchars; + char_expandos['M'] = expando_chanmode; + char_expandos['N'] = expando_nick; + char_expandos['O'] = expando_statusoper; + char_expandos['P'] = expando_chanop; + char_expandos['Q'] = expando_query; + char_expandos['R'] = expando_serverversion; + char_expandos['T'] = expando_target; char_expandos['V'] = expando_releasedate; char_expandos['W'] = expando_workdir; + char_expandos['Y'] = expando_realname; char_expandos['Z'] = expando_time; char_expandos['$'] = expando_dollar; expando_create("sysname", expando_sysname); expando_create("sysrelease", expando_sysrelease); + expando_create("tag", expando_servertag); + expando_create("chatnet", expando_chatnet); } void special_vars_deinit(void) { expando_destroy("sysname", expando_sysname); expando_destroy("sysrelease", expando_sysrelease); + expando_destroy("tag", expando_servertag); + expando_destroy("chatnet", expando_chatnet); g_hash_table_destroy(expandos); } diff --git a/src/core/special-vars.h b/src/core/special-vars.h index c40a2fcb..729ac991 100644 --- a/src/core/special-vars.h +++ b/src/core/special-vars.h @@ -1,18 +1,25 @@ #ifndef __SPECIAL_VARS_H #define __SPECIAL_VARS_H -typedef char* (*EXPANDO_FUNC) (void *server, void *item, int *free_ret); -typedef char* (*SPECIAL_HISTORY_FUNC) (const char *text, void *item, int *free_ret); +#include "servers.h" + +typedef char* (*EXPANDO_FUNC) + (SERVER_REC *server, void *item, int *free_ret); +typedef char* (*SPECIAL_HISTORY_FUNC) + (const char *text, void *item, int *free_ret); /* Parse and expand text after '$' character. return value has to be g_free()'d if `free_ret' is TRUE. */ -char *parse_special(char **cmd, void *server, void *item, char **arglist, int *free_ret, int *arg_used); +char *parse_special(char **cmd, SERVER_REC *server, void *item, + char **arglist, int *free_ret, int *arg_used); /* parse the whole string. $ and \ chars are replaced */ -char *parse_special_string(const char *cmd, void *server, void *item, const char *data, int *arg_used); +char *parse_special_string(const char *cmd, SERVER_REC *server, void *item, + const char *data, int *arg_used); /* execute the commands in string - commands can be split with ';' */ -void eval_special_string(const char *cmd, const char *data, void *server, void *item); +void eval_special_string(const char *cmd, const char *data, + SERVER_REC *server, void *item); /* Create expando - overrides any existing ones. */ void expando_create(const char *key, EXPANDO_FUNC func); diff --git a/src/core/window-item-def.h b/src/core/window-item-def.h new file mode 100644 index 00000000..5b54414a --- /dev/null +++ b/src/core/window-item-def.h @@ -0,0 +1,9 @@ +#ifndef __WINDOW_ITEM_DEF_H +#define __WINDOW_ITEM_DEF_H + +#define STRUCT_SERVER_REC SERVER_REC +typedef struct { +#include "window-item-rec.h" +} WI_ITEM_REC; + +#endif diff --git a/src/core/window-item-rec.h b/src/core/window-item-rec.h new file mode 100644 index 00000000..9cbfbabe --- /dev/null +++ b/src/core/window-item-rec.h @@ -0,0 +1,14 @@ +/* WI_ITEM_REC definition, used for inheritance */ + +int type; /* window item type - channel/query/.. */ +int chat_type; /* chat server type - irc/silc/.. */ +GHashTable *module_data; + +STRUCT_SERVER_REC *server; +char *name; + +time_t createtime; +int new_data; +int last_color; /* if NEWDATA_HILIGHT is set, color number could be specified here */ + +#undef STRUCT_SERVER_REC diff --git a/src/fe-common/core/Makefile.am b/src/fe-common/core/Makefile.am index ec9d99e9..90e64d55 100644 --- a/src/fe-common/core/Makefile.am +++ b/src/fe-common/core/Makefile.am @@ -1,4 +1,4 @@ -noinst_LTLIBRARIES = libfe_common_core.la +noinst_LIBRARIES = libfe_common_core.a INCLUDES = \ $(GLIB_CFLAGS) \ @@ -6,7 +6,7 @@ INCLUDES = \ -DHELPDIR=\""$(datadir)/irssi/help"\" \ -DSYSCONFDIR=\""$(sysconfdir)"\" -libfe_common_core_la_SOURCES = \ +libfe_common_core_a_SOURCES = \ autorun.c \ command-history.c \ completion.c \ diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index d192136b..1a802ace 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -133,6 +133,8 @@ void fe_common_core_finish_init(void) { WINDOW_REC *window; + signal_emit("irssi init read settings", 0); + signal(SIGPIPE, SIG_IGN); windows_restore(); diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index eef4dade..bd1aa2cc 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -22,7 +22,7 @@ #include "module-formats.h" #include "signals.h" #include "commands.h" -#include "server.h" +#include "servers.h" #include "levels.h" #include "misc.h" #include "log.h" diff --git a/src/fe-common/core/fe-server.c b/src/fe-common/core/fe-server.c index fff3d1fc..5e5483a6 100644 --- a/src/fe-common/core/fe-server.c +++ b/src/fe-common/core/fe-server.c @@ -19,13 +19,13 @@ */ #include "module.h" -#include "module-formats.h" #include "signals.h" -#include "settings.h" #include "network.h" - #include "levels.h" -#include "server.h" +#include "servers.h" +#include "settings.h" + +#include "module-formats.h" static void sig_server_looking(SERVER_REC *server) { diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c index f164d130..4c2bf823 100644 --- a/src/fe-common/core/fe-settings.c +++ b/src/fe-common/core/fe-settings.c @@ -22,7 +22,7 @@ #include "module-formats.h" #include "signals.h" #include "commands.h" -#include "server.h" +#include "servers.h" #include "misc.h" #include "lib-config/iconfig.h" #include "settings.h" diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 06f30123..b31f9cbd 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -27,7 +27,7 @@ #include "settings.h" #include "levels.h" -#include "server.h" +#include "servers.h" #include "hilight-text.h" diff --git a/src/fe-common/core/printtext.c b/src/fe-common/core/printtext.c index 85661d6f..155b580f 100644 --- a/src/fe-common/core/printtext.c +++ b/src/fe-common/core/printtext.c @@ -27,7 +27,7 @@ #include "settings.h" #include "levels.h" -#include "server.h" +#include "servers.h" #include "translation.h" #include "themes.h" diff --git a/src/fe-common/core/window-activity.c b/src/fe-common/core/window-activity.c index 47b82079..f86078be 100644 --- a/src/fe-common/core/window-activity.c +++ b/src/fe-common/core/window-activity.c @@ -21,7 +21,7 @@ #include "module.h" #include "signals.h" #include "levels.h" -#include "server.h" +#include "servers.h" #include "misc.h" #include "settings.h" diff --git a/src/fe-common/core/window-commands.c b/src/fe-common/core/window-commands.c index 14d1d94a..e31d827b 100644 --- a/src/fe-common/core/window-commands.c +++ b/src/fe-common/core/window-commands.c @@ -23,7 +23,7 @@ #include "signals.h" #include "commands.h" #include "misc.h" -#include "server.h" +#include "servers.h" #include "levels.h" @@ -183,7 +183,7 @@ static void cmd_window_server(const char *data) else if (active_win->active == NULL) { window_change_server(active_win, server); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_SERVER_CHANGED, server->tag, server->connrec->address, - server->connrec->ircnet == NULL ? "" : server->connrec->ircnet); + server->connrec->chatnet == NULL ? "" : server->connrec->chatnet); } } diff --git a/src/fe-common/core/window-items.c b/src/fe-common/core/window-items.c index bda4ee96..443ca586 100644 --- a/src/fe-common/core/window-items.c +++ b/src/fe-common/core/window-items.c @@ -22,7 +22,7 @@ #include "module-formats.h" #include "modules.h" #include "signals.h" -#include "server.h" +#include "servers.h" #include "settings.h" #include "levels.h" diff --git a/src/fe-common/core/window-save.c b/src/fe-common/core/window-save.c index fdf253a3..14174168 100644 --- a/src/fe-common/core/window-save.c +++ b/src/fe-common/core/window-save.c @@ -21,7 +21,7 @@ #include "module.h" #include "signals.h" #include "misc.h" -#include "server.h" +#include "servers.h" #include "lib-config/iconfig.h" #include "settings.h" diff --git a/src/fe-common/core/windows.c b/src/fe-common/core/windows.c index 77b8b3e2..5b362af9 100644 --- a/src/fe-common/core/windows.c +++ b/src/fe-common/core/windows.c @@ -23,7 +23,7 @@ #include "modules.h" #include "signals.h" #include "commands.h" -#include "server.h" +#include "servers.h" #include "misc.h" #include "settings.h" diff --git a/src/fe-common/core/windows.h b/src/fe-common/core/windows.h index 9c40235d..16fff673 100644 --- a/src/fe-common/core/windows.h +++ b/src/fe-common/core/windows.h @@ -1,6 +1,11 @@ #ifndef __WINDOWS_H #define __WINDOWS_H +#include "servers.h" + +#define STRUCT_SERVER_REC SERVER_REC +#include "window-item-def.h" + enum { NEWDATA_TEXT = 1, NEWDATA_MSG, @@ -8,30 +13,13 @@ enum { NEWDATA_CUSTOM }; -/* All window items *MUST* have these variables in same order - at the start of the structure - the server's type can of course be - replaced with the preferred record type. - - !!!! So IF YOU CHANGE THIS: REMEMBER TO UPDATE WI_IRC_REC, CHANNEL_REC - and QUERY_REC !!!! (I already forgot this once :) */ -typedef struct { - int type; - GHashTable *module_data; - - void *server; - char *name; - - int new_data; - int last_color; /* if NEWDATA_HILIGHT is set, color number could be specified here */ -} WI_ITEM_REC; - typedef struct { int refnum; char *name; GSList *items; WI_ITEM_REC *active; - void *active_server; + SERVER_REC *active_server; GSList *waiting_channels; /* list of " " */ diff --git a/src/fe-common/irc/Makefile.am b/src/fe-common/irc/Makefile.am index eeb27f50..1bc23a0d 100644 --- a/src/fe-common/irc/Makefile.am +++ b/src/fe-common/irc/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS = dcc flood notifylist -noinst_LTLIBRARIES = libfe_common_irc.la +noinst_LIBRARIES = libfe_common_irc.a INCLUDES = \ $(GLIB_CFLAGS) \ @@ -11,7 +11,7 @@ INCLUDES = \ -DHELPDIR=\""$(datadir)/irssi/help"\" \ -DSYSCONFDIR=\""$(sysconfdir)"\" -libfe_common_irc_la_SOURCES = \ +libfe_common_irc_a_SOURCES = \ fe-channels.c \ fe-irc-commands.c \ fe-irc-server.c \ @@ -22,7 +22,7 @@ libfe_common_irc_la_SOURCES = \ fe-ignore.c \ fe-netjoin.c \ fe-netsplit.c \ - fe-query.c \ + fe-queries.c \ fe-common-irc.c \ irc-completion.c \ irc-window-activity.c \ @@ -32,7 +32,7 @@ libfe_common_irc_la_SOURCES = \ noinst_HEADERS = \ fe-common-irc.h \ - fe-query.h \ + fe-queries.h \ irc-hilight-text.h \ module.h \ module-formats.h diff --git a/src/fe-common/irc/dcc/fe-dcc.c b/src/fe-common/irc/dcc/fe-dcc.c index 43f8ce32..fb9a8d81 100644 --- a/src/fe-common/irc/dcc/fe-dcc.c +++ b/src/fe-common/irc/dcc/fe-dcc.c @@ -19,7 +19,6 @@ */ #include "module.h" -#include "./module-formats.h" #include "signals.h" #include "commands.h" #include "network.h" @@ -27,7 +26,7 @@ #include "levels.h" #include "irc.h" #include "channels.h" -#include "query.h" +#include "irc-queries.h" #include "irc/dcc/dcc.h" @@ -35,6 +34,8 @@ #include "themes.h" #include "windows.h" +#include "module-formats.h" + static void dcc_connected(DCC_REC *dcc) { char *sender; @@ -47,7 +48,7 @@ static void dcc_connected(DCC_REC *dcc) printformat(dcc->server, sender, MSGLEVEL_DCC, IRCTXT_DCC_CHAT_CONNECTED, dcc->nick, dcc->addrstr, dcc->port); if (query_find(NULL, sender) == NULL) - query_create(dcc->server, sender, TRUE); + irc_query_create(dcc->server, sender, TRUE); g_free(sender); break; case DCC_TYPE_SEND: @@ -278,10 +279,10 @@ static void sig_query_destroyed(QUERY_REC *query) { DCC_REC *dcc; - if (*query->nick != '=') + if (*query->name != '=') return; - dcc = dcc_find_item(DCC_TYPE_CHAT, query->nick+1, NULL); + dcc = dcc_find_item(DCC_TYPE_CHAT, query->name+1, NULL); if (dcc != NULL && !dcc->destroyed) { /* DCC query window closed, close the dcc chat too. */ signal_emit("dcc closed", 1, dcc); @@ -318,7 +319,7 @@ static void cmd_msg(const char *data) cmd_params_free(free_arg); } -static void cmd_me(const char *data, SERVER_REC *server, WI_IRC_REC *item) +static void cmd_me(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { DCC_REC *dcc; @@ -331,7 +332,7 @@ static void cmd_me(const char *data, SERVER_REC *server, WI_IRC_REC *item) IRCTXT_OWN_DCC_ME, dcc->mynick, data); } -static void cmd_action(const char *data, SERVER_REC *server, WI_IRC_REC *item) +static void cmd_action(const char *data, SERVER_REC *server, WI_ITEM_REC *item) { DCC_REC *dcc; char *target, *text; diff --git a/src/fe-common/irc/fe-channels.c b/src/fe-common/irc/fe-channels.c index 1d41c70f..94f56cae 100644 --- a/src/fe-common/irc/fe-channels.c +++ b/src/fe-common/irc/fe-channels.c @@ -28,7 +28,7 @@ #include "settings.h" #include "irc.h" -#include "channels.h" +#include "irc-channels.h" #include "channels-setup.h" #include "nicklist.h" @@ -70,12 +70,12 @@ static void signal_channel_destroyed(CHANNEL_REC *channel) static void signal_window_item_removed(WINDOW_REC *window, WI_ITEM_REC *item) { - CHANNEL_REC *channel; + IRC_CHANNEL_REC *channel; g_return_if_fail(window != NULL); - channel = irc_item_channel(item); - if (channel != NULL) channel_destroy(channel); + channel = IRC_CHANNEL(item); + if (channel != NULL) channel_destroy(CHANNEL(channel)); } static void sig_disconnected(IRC_SERVER_REC *server) @@ -84,7 +84,7 @@ static void sig_disconnected(IRC_SERVER_REC *server) GSList *tmp; g_return_if_fail(server != NULL); - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server)) return; for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { @@ -101,7 +101,7 @@ static void signal_window_item_changed(WINDOW_REC *window, WI_ITEM_REC *item) g_return_if_fail(window != NULL); if (item == NULL) return; - if (g_slist_length(window->items) > 1 && irc_item_channel(item)) { + if (g_slist_length(window->items) > 1 && IS_IRC_CHANNEL(item)) { printformat(item->server, item->name, MSGLEVEL_CLIENTNOTICE, IRCTXT_TALKING_IN, item->name); signal_stop(); @@ -146,7 +146,7 @@ static void cmd_wjoin_post(const char *data) static void cmd_channel_list_joined(void) { - CHANNEL_REC *channel; + IRC_CHANNEL_REC *channel; GString *nicks; GSList *nicklist, *tmp, *ntmp; @@ -156,7 +156,7 @@ static void cmd_channel_list_joined(void) } /* print active channel */ - channel = irc_item_channel(active_win->active); + channel = IRC_CHANNEL(active_win->active); if (channel != NULL) printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_CURRENT_CHANNEL, channel->name); @@ -165,7 +165,7 @@ static void cmd_channel_list_joined(void) for (tmp = channels; tmp != NULL; tmp = tmp->next) { channel = tmp->data; - nicklist = nicklist_getnicks(channel); + nicklist = nicklist_getnicks(CHANNEL(channel)); nicks = g_string_new(NULL); for (ntmp = nicklist; ntmp != NULL; ntmp = ntmp->next) { NICK_REC *rec = ntmp->data; @@ -191,7 +191,7 @@ static void cmd_channel_list(void) str = g_string_new(NULL); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_CHANSETUP_HEADER); for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) { - SETUP_CHANNEL_REC *rec = tmp->data; + CHANNEL_SETUP_REC *rec = tmp->data; g_string_truncate(str, 0); if (rec->autojoin) @@ -203,7 +203,7 @@ static void cmd_channel_list(void) if (str->len > 2) g_string_truncate(str, str->len-2); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_CHANSETUP_LINE, - rec->name, rec->ircnet == NULL ? "" : rec->ircnet, + rec->name, rec->chatnet == NULL ? "" : rec->chatnet, rec->password == NULL ? "" : rec->password, str->str); } g_string_free(str, TRUE); @@ -225,7 +225,7 @@ static void cmd_channel(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *i static void cmd_channel_add(const char *data) { GHashTable *optlist; - SETUP_CHANNEL_REC *rec; + CHANNEL_SETUP_REC *rec; char *botarg, *botcmdarg, *ircnet, *channel, *password; void *free_arg; @@ -240,9 +240,9 @@ static void cmd_channel_add(const char *data) cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); rec = channels_setup_find(channel, ircnet); if (rec == NULL) { - rec = g_new0(SETUP_CHANNEL_REC, 1); + rec = g_new0(CHANNEL_SETUP_REC, 1); rec->name = g_strdup(channel); - rec->ircnet = g_strdup(ircnet); + rec->chatnet = g_strdup(ircnet); } else { if (g_hash_table_lookup(optlist, "bots")) g_free_and_null(rec->botmasks); if (g_hash_table_lookup(optlist, "botcmd")) g_free_and_null(rec->autosendcmd); @@ -262,7 +262,7 @@ static void cmd_channel_add(const char *data) /* SYNTAX: CHANNEL REMOVE */ static void cmd_channel_remove(const char *data) { - SETUP_CHANNEL_REC *rec; + CHANNEL_SETUP_REC *rec; char *ircnet, *channel; void *free_arg; diff --git a/src/fe-common/irc/fe-common-irc.c b/src/fe-common/irc/fe-common-irc.c index f1f1a515..651266f5 100644 --- a/src/fe-common/irc/fe-common-irc.c +++ b/src/fe-common/irc/fe-common-irc.c @@ -26,7 +26,7 @@ #include "lib-config/iconfig.h" #include "settings.h" -#include "server-setup.h" +#include "servers-setup.h" #include "themes.h" #include "completion.h" @@ -181,12 +181,12 @@ void fe_common_irc_finish_init(void) /* connect to autoconnect servers */ ircnets = NULL; for (tmp = setupservers; tmp != NULL; tmp = tmp->next) { - SETUP_SERVER_REC *rec = tmp->data; + SERVER_SETUP_REC *rec = tmp->data; - if (rec->autoconnect && (rec->ircnet == NULL || *rec->ircnet == '\0' || - gslist_find_icase_string(ircnets, rec->ircnet) == NULL)) { - if (rec->ircnet != NULL && *rec->ircnet != '\0') - ircnets = g_slist_append(ircnets, rec->ircnet); + if (rec->autoconnect && (rec->chatnet == NULL || *rec->chatnet == '\0' || + gslist_find_icase_string(ircnets, rec->chatnet) == NULL)) { + if (rec->chatnet != NULL && *rec->chatnet != '\0') + ircnets = g_slist_append(ircnets, rec->chatnet); str = g_strdup_printf("%s %d", rec->address, rec->port); signal_emit("command connect", 1, str); diff --git a/src/fe-common/irc/fe-ctcp.c b/src/fe-common/irc/fe-ctcp.c index ffb5ae62..e2b3e4ed 100644 --- a/src/fe-common/irc/fe-ctcp.c +++ b/src/fe-common/irc/fe-ctcp.c @@ -25,9 +25,9 @@ #include "irc.h" #include "levels.h" -#include "server.h" +#include "servers.h" #include "channels.h" -#include "query.h" +#include "queries.h" #include "ignore.h" #include "windows.h" diff --git a/src/fe-common/irc/fe-events-numeric.c b/src/fe-common/irc/fe-events-numeric.c index ed634ac5..ca739c35 100644 --- a/src/fe-common/irc/fe-events-numeric.c +++ b/src/fe-common/irc/fe-events-numeric.c @@ -26,8 +26,8 @@ #include "irc.h" #include "levels.h" -#include "server.h" -#include "channels.h" +#include "servers.h" +#include "irc-channels.h" #include "nicklist.h" static char *last_away_nick = NULL; @@ -64,7 +64,7 @@ static void event_names_list(const char *data, IRC_SERVER_REC *server) g_return_if_fail(data != NULL); params = event_get_params(data, 4, NULL, NULL, &channel, &names); - if (channel_find(server, channel) == NULL) + if (irc_channel_find(server, channel) == NULL) printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_NAMES, channel, names); g_free(params); } @@ -160,17 +160,17 @@ static void display_nicks(CHANNEL_REC *channel) static void event_end_of_names(const char *data, IRC_SERVER_REC *server) { char *params, *channel; - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; g_return_if_fail(data != NULL); params = event_get_params(data, 2, NULL, &channel); - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec == NULL) printformat(server, channel, MSGLEVEL_CRAP, IRCTXT_ENDOFNAMES, channel, 0, 0, 0, 0); else - display_nicks(chanrec); + display_nicks(CHANNEL(chanrec)); g_free(params); } diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c index ff37ff69..061a37ac 100644 --- a/src/fe-common/irc/fe-events.c +++ b/src/fe-common/irc/fe-events.c @@ -26,15 +26,15 @@ #include "irc.h" #include "levels.h" -#include "server.h" -#include "server-redirect.h" -#include "server-reconnect.h" -#include "channels.h" -#include "query.h" -#include "nicklist.h" +#include "servers.h" +#include "servers-redirect.h" +#include "servers-reconnect.h" +#include "queries.h" #include "ignore.h" -#include "fe-query.h" +#include "fe-queries.h" +#include "irc-channels.h" +#include "irc-nicklist.h" #include "irc-hilight-text.h" #include "windows.h" @@ -47,17 +47,18 @@ static void print_channel_msg(IRC_SERVER_REC *server, const char *msg, const char *nick, const char *addr, const char *target) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; NICK_REC *nickrec; const char *nickmode; int for_me, print_channel; char *color; - chanrec = channel_find(server, target); + chanrec = irc_channel_find(server, target); for_me = irc_nick_match(server->nick, msg); color = for_me ? NULL : irc_hilight_find_nick(target, nick, addr, MSGLEVEL_PUBLIC, msg); - nickrec = chanrec == NULL ? NULL : nicklist_find(chanrec, nick); + nickrec = chanrec == NULL ? NULL : + nicklist_find(CHANNEL(chanrec), nick); nickmode = (!settings_get_bool("show_nickmode") || nickrec == NULL) ? "" : (nickrec->op ? "@" : nickrec->voice ? "+" : " "); @@ -139,7 +140,7 @@ static void ctcp_msg_check_action(const char *data, IRC_SERVER_REC *server, if (ischannel(*target)) { /* channel action */ - item = (WI_ITEM_REC *) channel_find(server, target); + item = (WI_ITEM_REC *) irc_channel_find(server, target); if (window_item_is_active(item)) { /* message to active channel in window */ @@ -245,9 +246,10 @@ static void event_quit(const char *data, IRC_SERVER_REC *server, const char *nic count = 0; windows = NULL; chans = !once ? NULL : g_string_new(NULL); for (tmp = channels; tmp != NULL; tmp = tmp->next) { - CHANNEL_REC *rec = tmp->data; + IRC_CHANNEL_REC *rec = tmp->data; - if (rec->server != server || !nicklist_find(rec, nick) || + if (!IS_IRC_CHANNEL(rec) || rec->server != server || + !nicklist_find(CHANNEL(rec), nick) || ignore_check(server, nick, addr, rec->name, data, MSGLEVEL_QUITS)) continue; @@ -338,10 +340,10 @@ static void event_nick(gchar *data, IRC_SERVER_REC *server, gchar *sender, gchar WINDOW_REC *window = window_item_window((WI_ITEM_REC *) query); - if (g_strcasecmp(query->nick, sender) == 0 && + if (g_strcasecmp(query->name, sender) == 0 && g_slist_find(windows, window) == NULL) { windows = g_slist_append(windows, window); - print_nick_change(server, query->nick, newnick, sender, addr, ownnick); + print_nick_change(server, query->name, newnick, sender, addr, ownnick); msgprint = TRUE; } } @@ -561,7 +563,7 @@ static void sig_server_reconnect_removed(RECONNECT_REC *reconnect) printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_RECONNECT_REMOVED, reconnect->conn->address, reconnect->conn->port, - reconnect->conn->ircnet == NULL ? "" : reconnect->conn->ircnet); + reconnect->conn->chatnet == NULL ? "" : reconnect->conn->chatnet); } static void sig_server_reconnect_not_found(const char *tag) diff --git a/src/fe-common/irc/fe-ignore.c b/src/fe-common/irc/fe-ignore.c index 2de35d94..5869b3bc 100644 --- a/src/fe-common/irc/fe-ignore.c +++ b/src/fe-common/irc/fe-ignore.c @@ -26,7 +26,7 @@ #include "misc.h" #include "irc.h" -#include "irc-server.h" +#include "irc-servers.h" #include "ignore.h" static void fe_unignore(IGNORE_REC *rec); diff --git a/src/fe-common/irc/fe-irc-commands.c b/src/fe-common/irc/fe-irc-commands.c index 5a3ae50c..2bd0c761 100644 --- a/src/fe-common/irc/fe-irc-commands.c +++ b/src/fe-common/irc/fe-irc-commands.c @@ -28,13 +28,13 @@ #include "levels.h" #include "irc.h" #include "irc-commands.h" -#include "server.h" +#include "servers.h" #include "mode-lists.h" #include "nicklist.h" -#include "channels.h" -#include "query.h" +#include "irc-channels.h" +#include "irc-queries.h" -#include "fe-query.h" +#include "fe-queries.h" #include "windows.h" #include "window-items.h" @@ -42,7 +42,7 @@ static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { GHashTable *optlist; WINDOW_REC *window; - CHANNEL_REC *channel; + IRC_CHANNEL_REC *channel; NICK_REC *nickrec; const char *nickmode; char *target, *msg, *freestr, *newtarget; @@ -67,9 +67,9 @@ static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) free_ret = FALSE; if (strcmp(target, ",") == 0 || strcmp(target, ".") == 0) - newtarget = parse_special(&target, server, item, NULL, &free_ret, NULL); + newtarget = parse_special(&target, SERVER(server), item, NULL, &free_ret, NULL); else if (strcmp(target, "*") == 0 && - (irc_item_channel(item) || irc_item_query(item))) + (IS_IRC_CHANNEL(item) || IS_IRC_QUERY(item))) newtarget = item->name; else newtarget = target; @@ -83,7 +83,7 @@ static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) target = newtarget; if (server == NULL || !server->connected) cmd_param_error(CMDERR_NOT_CONNECTED); - channel = channel_find(server, target); + channel = irc_channel_find(server, target); freestr = !free_ret ? NULL : target; if (*target == '@' && ischannel(target[1])) @@ -92,7 +92,8 @@ static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) if (ischannel(*target)) { /* msg to channel */ - nickrec = channel == NULL ? NULL : nicklist_find(channel, server->nick); + nickrec = channel == NULL ? NULL : + nicklist_find(CHANNEL(channel), server->nick); nickmode = !settings_get_bool("show_nickmode") || nickrec == NULL ? "" : nickrec->op ? "@" : nickrec->voice ? "+" : " "; @@ -128,11 +129,11 @@ static void cmd_msg(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) } /* SYNTAX: ME */ -static void cmd_me(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_me(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { g_return_if_fail(data != NULL); - if (!irc_item_check(item)) + if (!IS_IRC_ITEM(item)) return; if (server == NULL || !server->connected) @@ -237,21 +238,21 @@ static void cmd_nctcp(const char *data, IRC_SERVER_REC *server) cmd_params_free(free_arg); } -static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *channame, *msg; void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (server == NULL || !server->connected || !IS_IRC_SERVER(server)) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg)) return; if (*msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - chanrec = channel_find(server, channame); + chanrec = irc_channel_find(server, channame); if (chanrec == NULL) cmd_param_error(CMDERR_CHAN_NOT_FOUND); printformat(server, chanrec->name, MSGLEVEL_NOTICES, IRCTXT_OWN_WALL, chanrec->name, msg); @@ -260,7 +261,7 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) } static void bans_ask_channel(const char *channel, IRC_SERVER_REC *server, - WI_IRC_REC *item) + WI_ITEM_REC *item) { GString *str; @@ -274,7 +275,7 @@ static void bans_ask_channel(const char *channel, IRC_SERVER_REC *server, g_string_free(str, TRUE); } -static void bans_show_channel(CHANNEL_REC *channel, IRC_SERVER_REC *server) +static void bans_show_channel(IRC_CHANNEL_REC *channel, IRC_SERVER_REC *server) { GSList *tmp; @@ -309,9 +310,9 @@ static void bans_show_channel(CHANNEL_REC *channel, IRC_SERVER_REC *server) /* SYNTAX: BAN [] [] */ static void cmd_ban(const char *data, IRC_SERVER_REC *server, - WI_IRC_REC *item) + WI_ITEM_REC *item) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *channel, *nicks; void *free_arg; @@ -331,12 +332,12 @@ static void cmd_ban(const char *data, IRC_SERVER_REC *server, } /* display bans */ - chanrec = irc_item_channel(item); + chanrec = IRC_CHANNEL(item); if (chanrec == NULL && *channel == '\0') cmd_param_error(CMDERR_NOT_JOINED); if (*channel != '\0' && strcmp(channel, "*") != 0) - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec == NULL) { /* not joined to such channel, @@ -351,21 +352,21 @@ static void cmd_ban(const char *data, IRC_SERVER_REC *server, } /* SYNTAX: INVITELIST [] */ -static void cmd_invitelist(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_invitelist(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { - CHANNEL_REC *channel, *cur_channel; + IRC_CHANNEL_REC *channel, *cur_channel; GSList *tmp; g_return_if_fail(data != NULL); if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); - cur_channel = irc_item_channel(item); + cur_channel = IRC_CHANNEL(item); if (cur_channel == NULL) cmd_return_error(CMDERR_NOT_JOINED); if (strcmp(data, "*") == 0 || *data == '\0') channel = cur_channel; else - channel = channel_find(server, data); + channel = irc_channel_find(server, data); if (channel == NULL) cmd_return_error(CMDERR_CHAN_NOT_FOUND); for (tmp = channel->invitelist; tmp != NULL; tmp = tmp->next) @@ -395,15 +396,15 @@ static void cmd_nick(const char *data, IRC_SERVER_REC *server) } /* SYNTAX: VER [] */ -static void cmd_ver(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_ver(gchar *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { char *str; g_return_if_fail(data != NULL); - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); - if (*data == '\0' && !irc_item_check(item)) + if (*data == '\0' && !IS_IRC_ITEM(item)) cmd_return_error(CMDERR_NOT_JOINED); str = g_strdup_printf("%s VERSION", *data == '\0' ? item->name : data); diff --git a/src/fe-common/irc/fe-irc-server.c b/src/fe-common/irc/fe-irc-server.c index 3094c5bd..18093737 100644 --- a/src/fe-common/irc/fe-irc-server.c +++ b/src/fe-common/irc/fe-irc-server.c @@ -24,10 +24,12 @@ #include "commands.h" #include "misc.h" +#include "servers-setup.h" + #include "levels.h" -#include "irc-server.h" -#include "server-reconnect.h" -#include "server-setup.h" +#include "irc-servers.h" +#include "servers-reconnect.h" +#include "irc-servers-setup.h" #include "windows.h" @@ -40,7 +42,7 @@ static void print_servers(void) printformat(NULL, NULL, MSGLEVEL_CRAP, IRCTXT_SERVER_LIST, rec->tag, rec->connrec->address, rec->connrec->port, - rec->connrec->ircnet == NULL ? "" : rec->connrec->ircnet, rec->connrec->nick); + rec->connrec->chatnet == NULL ? "" : rec->connrec->chatnet, rec->connrec->nick); } } @@ -52,7 +54,7 @@ static void print_lookup_servers(void) printformat(NULL, NULL, MSGLEVEL_CRAP, IRCTXT_SERVER_LOOKUP_LIST, rec->tag, rec->connrec->address, rec->connrec->port, - rec->connrec->ircnet == NULL ? "" : rec->connrec->ircnet, rec->connrec->nick); + rec->connrec->chatnet == NULL ? "" : rec->connrec->chatnet, rec->connrec->nick); } } @@ -64,14 +66,14 @@ static void print_reconnects(void) for (tmp = reconnects; tmp != NULL; tmp = tmp->next) { RECONNECT_REC *rec = tmp->data; - IRC_SERVER_CONNECT_REC *conn = rec->conn; + SERVER_CONNECT_REC *conn = rec->conn; tag = g_strdup_printf("RECON-%d", rec->tag); left = rec->next_connect-time(NULL); next_connect = g_strdup_printf("%02d:%02d", left/60, left%60); printformat(NULL, NULL, MSGLEVEL_CRAP, IRCTXT_SERVER_RECONNECT_LIST, tag, conn->address, conn->port, - conn->ircnet == NULL ? "" : conn->ircnet, + conn->chatnet == NULL ? "" : conn->chatnet, conn->nick, next_connect); g_free(next_connect); g_free(tag); @@ -84,7 +86,7 @@ static void print_reconnects(void) static void cmd_server_add(const char *data) { GHashTable *optlist; - SETUP_SERVER_REC *rec; + IRC_SERVER_SETUP_REC *rec; char *addr, *portstr, *password, *value; void *free_arg; int port; @@ -96,16 +98,16 @@ static void cmd_server_add(const char *data) if (*addr == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); port = *portstr == '\0' ? 6667 : atoi(portstr); - rec = server_setup_find_port(addr, port); + rec = IRC_SERVER_SETUP(server_setup_find_port(addr, port)); if (rec == NULL) { - rec = g_new0(SETUP_SERVER_REC, 1); + rec = g_new0(IRC_SERVER_SETUP_REC, 1); rec->address = g_strdup(addr); rec->port = port; } else { value = g_hash_table_lookup(optlist, "port"); if (value != NULL && *value != '\0') rec->port = atoi(value); - if (g_hash_table_lookup(optlist, "ircnet")) g_free_and_null(rec->ircnet); + if (g_hash_table_lookup(optlist, "ircnet")) g_free_and_null(rec->chatnet); if (*password != '\0') g_free_and_null(rec->password); if (g_hash_table_lookup(optlist, "host")) { g_free_and_null(rec->own_host); @@ -118,7 +120,7 @@ static void cmd_server_add(const char *data) if (*password != '\0' && strcmp(password, "-") != 0) rec->password = g_strdup(password); value = g_hash_table_lookup(optlist, "ircnet"); - if (value != NULL && *value != '\0') rec->ircnet = g_strdup(value); + if (value != NULL && *value != '\0') rec->chatnet = g_strdup(value); value = g_hash_table_lookup(optlist, "host"); if (value != NULL && *value != '\0') { rec->own_host = g_strdup(value); @@ -129,7 +131,7 @@ static void cmd_server_add(const char *data) value = g_hash_table_lookup(optlist, "cmdmax"); if (value != NULL && *value != '\0') rec->max_cmds_at_once = atoi(value); - server_setup_add(rec); + server_setup_add(SERVER_SETUP(rec)); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_SETUPSERVER_ADDED, addr, port); cmd_params_free(free_arg); @@ -138,7 +140,7 @@ static void cmd_server_add(const char *data) /* SYNTAX: SERVER REMOVE
[] */ static void cmd_server_remove(const char *data) { - SETUP_SERVER_REC *rec; + SERVER_SETUP_REC *rec; char *addr, *portstr; void *free_arg; int port; @@ -168,7 +170,7 @@ static void cmd_server_list(const char *data) str = g_string_new(NULL); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_SETUPSERVER_HEADER); for (tmp = setupservers; tmp != NULL; tmp = tmp->next) { - SETUP_SERVER_REC *rec = tmp->data; + IRC_SERVER_SETUP_REC *rec = tmp->data; g_string_truncate(str, 0); if (rec->password != NULL) @@ -185,7 +187,7 @@ static void cmd_server_list(const char *data) if (str->len > 1) g_string_truncate(str, str->len-2); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_SETUPSERVER_LINE, rec->address, rec->port, - rec->ircnet == NULL ? "" : rec->ircnet, + rec->chatnet == NULL ? "" : rec->chatnet, str->str); } printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_SETUPSERVER_FOOTER); diff --git a/src/fe-common/irc/fe-ircnet.c b/src/fe-common/irc/fe-ircnet.c index 34f1642a..f770fff6 100644 --- a/src/fe-common/irc/fe-ircnet.c +++ b/src/fe-common/irc/fe-ircnet.c @@ -24,9 +24,10 @@ #include "commands.h" #include "levels.h" #include "misc.h" +#include "chatnets.h" -#include "irc-server.h" -#include "ircnet-setup.h" +#include "irc-servers.h" +#include "irc-chatnets.h" static void cmd_ircnet_list(void) { @@ -35,8 +36,8 @@ static void cmd_ircnet_list(void) str = g_string_new(NULL); printformat(NULL, NULL, MSGLEVEL_CLIENTCRAP, IRCTXT_IRCNET_HEADER); - for (tmp = ircnets; tmp != NULL; tmp = tmp->next) { - IRCNET_REC *rec = tmp->data; + for (tmp = chatnets; tmp != NULL; tmp = tmp->next) { + IRC_CHATNET_REC *rec = tmp->data; g_string_truncate(str, 0); if (rec->nick != NULL) @@ -81,7 +82,7 @@ static void cmd_ircnet_add(const char *data) GHashTable *optlist; char *name, *value; void *free_arg; - IRCNET_REC *rec; + IRC_CHATNET_REC *rec; if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS, "ircnet add", &optlist, &name)) @@ -90,7 +91,7 @@ static void cmd_ircnet_add(const char *data) rec = ircnet_find(name); if (rec == NULL) { - rec = g_new0(IRCNET_REC, 1); + rec = g_new0(IRC_CHATNET_REC, 1); rec->name = g_strdup(name); } else { if (g_hash_table_lookup(optlist, "nick")) g_free_and_null(rec->nick); @@ -142,7 +143,7 @@ static void cmd_ircnet_add(const char *data) /* SYNTAX: IRCNET REMOVE */ static void cmd_ircnet_remove(const char *data) { - IRCNET_REC *rec; + IRC_CHATNET_REC *rec; if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -151,7 +152,7 @@ static void cmd_ircnet_remove(const char *data) printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_IRCNET_NOT_FOUND, data); else { printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_IRCNET_REMOVED, data); - ircnet_destroy(rec); + chatnet_destroy(CHATNET(rec)); } } diff --git a/src/fe-common/irc/fe-netjoin.c b/src/fe-common/irc/fe-netjoin.c index e6c50c1e..ffbd817b 100644 --- a/src/fe-common/irc/fe-netjoin.c +++ b/src/fe-common/irc/fe-netjoin.c @@ -26,7 +26,7 @@ #include "settings.h" #include "irc.h" -#include "irc-server.h" +#include "irc-servers.h" #include "modes.h" #include "ignore.h" #include "netsplit.h" diff --git a/src/fe-common/irc/fe-netsplit.c b/src/fe-common/irc/fe-netsplit.c index 2d834871..7bb31612 100644 --- a/src/fe-common/irc/fe-netsplit.c +++ b/src/fe-common/irc/fe-netsplit.c @@ -26,7 +26,7 @@ #include "settings.h" #include "irc.h" -#include "irc-server.h" +#include "irc-servers.h" #include "ignore.h" #include "netsplit.h" diff --git a/src/fe-common/irc/fe-queries.c b/src/fe-common/irc/fe-queries.c new file mode 100644 index 00000000..20bea852 --- /dev/null +++ b/src/fe-common/irc/fe-queries.c @@ -0,0 +1,330 @@ +/* + fe-queries.c : 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 "module-formats.h" +#include "modules.h" +#include "signals.h" +#include "commands.h" +#include "settings.h" + +#include "irc.h" +#include "irc-commands.h" +#include "levels.h" +#include "irc-queries.h" + +#include "windows.h" +#include "window-items.h" + +static int queryclose_tag, query_auto_close; + +/* Return query where to put the private message. */ +QUERY_REC *privmsg_get_query(IRC_SERVER_REC *server, const char *nick, int own) +{ + QUERY_REC *query; + + query = irc_query_find(server, nick); + if (query == NULL && settings_get_bool("autocreate_query") && + (!own || settings_get_bool("autocreate_own_query"))) + query = irc_query_create(server, nick, TRUE); + + return query; +} + +static void signal_query_created(QUERY_REC *query, gpointer automatic) +{ + if (window_item_find(query->server, query->name) != NULL) + return; + + window_item_create((WI_ITEM_REC *) query, GPOINTER_TO_INT(automatic)); + printformat(query->server, query->name, MSGLEVEL_CLIENTNOTICE, + IRCTXT_QUERY_STARTED, query->name); +} + +static void signal_query_created_curwin(QUERY_REC *query) +{ + g_return_if_fail(query != NULL); + + window_add_item(active_win, (WI_ITEM_REC *) query, FALSE); +} + +static void signal_query_destroyed(QUERY_REC *query) +{ + WINDOW_REC *window; + + g_return_if_fail(query != NULL); + + window = window_item_window((WI_ITEM_REC *) query); + if (window != NULL) { + window_remove_item(window, (WI_ITEM_REC *) query); + + if (window->items == NULL && windows->next != NULL && + !query->unwanted && settings_get_bool("autoclose_windows")) + window_destroy(window); + } +} + +static void signal_window_item_removed(WINDOW_REC *window, WI_ITEM_REC *item) +{ + QUERY_REC *query; + + g_return_if_fail(window != NULL); + + query = IRC_QUERY(item); + if (query != NULL) query_destroy(query); +} + +static void sig_server_connected(IRC_SERVER_REC *server) +{ + GSList *tmp; + + if (!IS_IRC_SERVER(server)) + return; + + /* check if there's any queries without server */ + for (tmp = queries; tmp != NULL; tmp = tmp->next) { + QUERY_REC *rec = tmp->data; + + if (rec->server == NULL && + g_strcasecmp(rec->server_tag, server->tag) == 0) { + window_item_change_server((WI_ITEM_REC *) rec, server); + server->queries = g_slist_append(server->queries, rec); + } + } +} + +static void cmd_window_server(const char *data) +{ + SERVER_REC *server; + + g_return_if_fail(data != NULL); + + server = server_find_tag(data); + if (IS_IRC_SERVER(server) && IS_IRC_QUERY(active_win->active)) { + /* /WINDOW SERVER used in a query window */ + query_change_server((QUERY_REC *) active_win->active, server); + window_change_server(active_win, server); + + printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_QUERY_SERVER_CHANGED, server->tag, server->connrec->address, + server->connrec->chatnet == NULL ? "" : server->connrec->chatnet); + + signal_stop(); + } +} + +/* SYNTAX: UNQUERY [] */ +static void cmd_unquery(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) +{ + QUERY_REC *query; + + g_return_if_fail(data != NULL); + + if (*data == '\0') { + /* remove current query */ + query = IRC_QUERY(item); + if (query == NULL) return; + } else { + query = irc_query_find(server, data); + if (query == NULL) { + printformat(server, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_NO_QUERY, data); + return; + } + } + + query_destroy(query); +} + +/* SYNTAX: QUERY [-window] */ +static void cmd_query(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) +{ + GHashTable *optlist; + WINDOW_REC *window; + QUERY_REC *query; + char *nick; + void *free_arg; + + g_return_if_fail(data != NULL); + + if (*data == '\0') { + /* remove current query */ + cmd_unquery("", server, item); + return; + } + + if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | + PARAM_FLAG_UNKNOWN_OPTIONS, + "query", &optlist, &nick)) + return; + if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + server = irccmd_options_get_server("query", optlist, server); + if (server == NULL) { + cmd_params_free(free_arg); + return; + } + + if (*nick != '=' && (server == NULL || !server->connected)) + cmd_param_error(CMDERR_NOT_CONNECTED); + + if (g_hash_table_lookup(optlist, "window") != NULL) { + signal_add("query created", + (SIGNAL_FUNC) signal_query_created_curwin); + } + + query = irc_query_find(server, nick); + if (query == NULL) + irc_query_create(server, nick, FALSE); + else { + /* query already existed - change to query window */ + window = window_item_window((WI_ITEM_REC *) query); + g_return_if_fail(window != NULL); + + window_set_active(window); + window_item_set_active(window, (WI_ITEM_REC *) query); + } + + if (g_hash_table_lookup(optlist, "window") != NULL) { + signal_remove("query created", + (SIGNAL_FUNC) signal_query_created_curwin); + } + + cmd_params_free(free_arg); +} + +static int window_has_query(WINDOW_REC *window) +{ + GSList *tmp; + + g_return_val_if_fail(window != NULL, FALSE); + + for (tmp = window->items; tmp != NULL; tmp = tmp->next) { + if (IS_IRC_QUERY(tmp->data)) + return TRUE; + } + + return FALSE; +} + +static void sig_window_changed(WINDOW_REC *window, WINDOW_REC *old_window) +{ + if (query_auto_close <= 0) + return; + + /* reset the window's last_line timestamp so that query doesn't get + closed immediately after switched to the window, or after changed + to some other window from it */ + if (window != NULL && window_has_query(window)) + window->last_line = time(NULL); + if (old_window != NULL && window_has_query(old_window)) + old_window->last_line = time(NULL); +} + +static void sig_window_restore_item(WINDOW_REC *window, const char *item) +{ + IRC_SERVER_REC *server; + QUERY_REC *rec; + char *tag, *nick; + + tag = g_strdup(item); + nick = strchr(tag, ' '); + if (nick == NULL || ischannel(*(nick+1))) { + g_free(tag); + return; + } + + server = (IRC_SERVER_REC *) server_find_tag(tag); + + rec = irc_query_create(server, nick+1, TRUE); + if (server == NULL) + rec->server_tag = g_strdup(tag); + + g_free(tag); + signal_stop(); +} + +static int sig_query_autoclose(void) +{ + WINDOW_REC *window; + GSList *tmp, *next; + time_t now; + + now = time(NULL); + for (tmp = queries; tmp != NULL; tmp = next) { + QUERY_REC *rec = tmp->data; + + next = tmp->next; + window = window_item_window((WI_ITEM_REC *) rec); + if (window != active_win && rec->new_data == 0 && + now-window->last_line > query_auto_close) + query_destroy(rec); + } + return 1; +} + +static void read_settings(void) +{ + query_auto_close = settings_get_int("autoclose_query"); + if (query_auto_close > 0 && queryclose_tag == -1) + queryclose_tag = g_timeout_add(5000, (GSourceFunc) sig_query_autoclose, NULL); + else if (query_auto_close <= 0 && queryclose_tag != -1) { + g_source_remove(queryclose_tag); + queryclose_tag = -1; + } +} + +void fe_query_init(void) +{ + settings_add_bool("lookandfeel", "autocreate_query", TRUE); + settings_add_bool("lookandfeel", "autocreate_own_query", TRUE); + settings_add_int("lookandfeel", "autoclose_query", 0); + + queryclose_tag = -1; + read_settings(); + + signal_add("query created", (SIGNAL_FUNC) signal_query_created); + signal_add("query destroyed", (SIGNAL_FUNC) signal_query_destroyed); + signal_add("window item remove", (SIGNAL_FUNC) signal_window_item_removed); + signal_add("server connected", (SIGNAL_FUNC) sig_server_connected); + signal_add("window changed", (SIGNAL_FUNC) sig_window_changed); + signal_add("window restore item", (SIGNAL_FUNC) sig_window_restore_item); + signal_add("setup changed", (SIGNAL_FUNC) read_settings); + + command_bind("query", NULL, (SIGNAL_FUNC) cmd_query); + command_bind("unquery", NULL, (SIGNAL_FUNC) cmd_unquery); + command_bind("window server", NULL, (SIGNAL_FUNC) cmd_window_server); + + command_set_options("query", "window"); +} + +void fe_query_deinit(void) +{ + if (queryclose_tag != -1) g_source_remove(queryclose_tag); + + signal_remove("query created", (SIGNAL_FUNC) signal_query_created); + signal_remove("query destroyed", (SIGNAL_FUNC) signal_query_destroyed); + signal_remove("window item remove", (SIGNAL_FUNC) signal_window_item_removed); + signal_remove("server connected", (SIGNAL_FUNC) sig_server_connected); + signal_remove("window changed", (SIGNAL_FUNC) sig_window_changed); + signal_remove("window restore item", (SIGNAL_FUNC) sig_window_restore_item); + signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + + command_unbind("query", (SIGNAL_FUNC) cmd_query); + command_unbind("unquery", (SIGNAL_FUNC) cmd_unquery); + command_unbind("window server", (SIGNAL_FUNC) cmd_window_server); +} diff --git a/src/fe-common/irc/fe-queries.h b/src/fe-common/irc/fe-queries.h new file mode 100644 index 00000000..494e277a --- /dev/null +++ b/src/fe-common/irc/fe-queries.h @@ -0,0 +1,7 @@ +#ifndef __FE_QUERIES_H +#define __FE_QUERIES_H + +/* Return query where to put the private message. */ +QUERY_REC *privmsg_get_query(IRC_SERVER_REC *server, const char *nick, int own); + +#endif diff --git a/src/fe-common/irc/fe-query.c b/src/fe-common/irc/fe-query.c deleted file mode 100644 index f48505be..00000000 --- a/src/fe-common/irc/fe-query.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - fe-query.c : 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 "module-formats.h" -#include "modules.h" -#include "signals.h" -#include "commands.h" -#include "settings.h" - -#include "irc.h" -#include "irc-commands.h" -#include "levels.h" -#include "query.h" - -#include "windows.h" -#include "window-items.h" - -static int queryclose_tag, query_auto_close; - -/* Return query where to put the private message. */ -QUERY_REC *privmsg_get_query(IRC_SERVER_REC *server, const char *nick, int own) -{ - QUERY_REC *query; - - query = query_find(server, nick); - if (query == NULL && settings_get_bool("autocreate_query") && - (!own || settings_get_bool("autocreate_own_query"))) - query = query_create(server, nick, TRUE); - - return query; -} - -static void signal_query_created(QUERY_REC *query, gpointer automatic) -{ - if (window_item_find(query->server, query->nick) != NULL) - return; - - window_item_create((WI_ITEM_REC *) query, GPOINTER_TO_INT(automatic)); - printformat(query->server, query->nick, MSGLEVEL_CLIENTNOTICE, - IRCTXT_QUERY_STARTED, query->nick); -} - -static void signal_query_created_curwin(QUERY_REC *query) -{ - g_return_if_fail(query != NULL); - - window_add_item(active_win, (WI_ITEM_REC *) query, FALSE); -} - -static void signal_query_destroyed(QUERY_REC *query) -{ - WINDOW_REC *window; - - g_return_if_fail(query != NULL); - - window = window_item_window((WI_ITEM_REC *) query); - if (window != NULL) { - window_remove_item(window, (WI_ITEM_REC *) query); - - if (window->items == NULL && windows->next != NULL && - !query->unwanted && settings_get_bool("autoclose_windows")) - window_destroy(window); - } -} - -static void signal_window_item_removed(WINDOW_REC *window, WI_ITEM_REC *item) -{ - QUERY_REC *query; - - g_return_if_fail(window != NULL); - - query = irc_item_query(item); - if (query != NULL) query_destroy(query); -} - -static void sig_server_connected(IRC_SERVER_REC *server) -{ - GSList *tmp; - - if (!irc_server_check(server)) - return; - - /* check if there's any queries without server */ - for (tmp = queries; tmp != NULL; tmp = tmp->next) { - QUERY_REC *rec = tmp->data; - - if (rec->server == NULL && - g_strcasecmp(rec->server_tag, server->tag) == 0) { - window_item_change_server((WI_ITEM_REC *) rec, server); - server->queries = g_slist_append(server->queries, rec); - } - } -} - -static void cmd_window_server(const char *data) -{ - SERVER_REC *server; - - g_return_if_fail(data != NULL); - - server = server_find_tag(data); - if (irc_server_check(server) && irc_item_query(active_win->active)) { - /* /WINDOW SERVER used in a query window */ - query_change_server((QUERY_REC *) active_win->active, - (IRC_SERVER_REC *) server); - window_change_server(active_win, server); - - printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_QUERY_SERVER_CHANGED, server->tag, server->connrec->address, - server->connrec->ircnet == NULL ? "" : server->connrec->ircnet); - - signal_stop(); - } -} - -/* SYNTAX: UNQUERY [] */ -static void cmd_unquery(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) -{ - QUERY_REC *query; - - g_return_if_fail(data != NULL); - - if (*data == '\0') { - /* remove current query */ - query = irc_item_query(item); - if (query == NULL) return; - } else { - query = query_find(server, data); - if (query == NULL) { - printformat(server, NULL, MSGLEVEL_CLIENTERROR, IRCTXT_NO_QUERY, data); - return; - } - } - - query_destroy(query); -} - -/* SYNTAX: QUERY [-window] */ -static void cmd_query(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) -{ - GHashTable *optlist; - WINDOW_REC *window; - QUERY_REC *query; - char *nick; - void *free_arg; - - g_return_if_fail(data != NULL); - - if (*data == '\0') { - /* remove current query */ - cmd_unquery("", server, item); - return; - } - - if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | - PARAM_FLAG_UNKNOWN_OPTIONS, - "query", &optlist, &nick)) - return; - if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - server = irccmd_options_get_server("query", optlist, server); - if (server == NULL) { - cmd_params_free(free_arg); - return; - } - - if (*nick != '=' && (server == NULL || !server->connected)) - cmd_param_error(CMDERR_NOT_CONNECTED); - - if (g_hash_table_lookup(optlist, "window") != NULL) { - signal_add("query created", - (SIGNAL_FUNC) signal_query_created_curwin); - } - - query = query_find(server, nick); - if (query == NULL) - query_create(server, nick, FALSE); - else { - /* query already existed - change to query window */ - window = window_item_window((WI_ITEM_REC *) query); - g_return_if_fail(window != NULL); - - window_set_active(window); - window_item_set_active(window, (WI_ITEM_REC *) query); - } - - if (g_hash_table_lookup(optlist, "window") != NULL) { - signal_remove("query created", - (SIGNAL_FUNC) signal_query_created_curwin); - } - - cmd_params_free(free_arg); -} - -static int window_has_query(WINDOW_REC *window) -{ - GSList *tmp; - - g_return_val_if_fail(window != NULL, FALSE); - - for (tmp = window->items; tmp != NULL; tmp = tmp->next) { - if (irc_item_query(tmp->data)) - return TRUE; - } - - return FALSE; -} - -static void sig_window_changed(WINDOW_REC *window, WINDOW_REC *old_window) -{ - if (query_auto_close <= 0) - return; - - /* reset the window's last_line timestamp so that query doesn't get - closed immediately after switched to the window, or after changed - to some other window from it */ - if (window != NULL && window_has_query(window)) - window->last_line = time(NULL); - if (old_window != NULL && window_has_query(old_window)) - old_window->last_line = time(NULL); -} - -static void sig_window_restore_item(WINDOW_REC *window, const char *item) -{ - IRC_SERVER_REC *server; - QUERY_REC *rec; - char *tag, *nick; - - tag = g_strdup(item); - nick = strchr(tag, ' '); - if (nick == NULL || ischannel(*(nick+1))) { - g_free(tag); - return; - } - - server = (IRC_SERVER_REC *) server_find_tag(tag); - - rec = query_create(server, nick+1, TRUE); - if (server == NULL) - rec->server_tag = g_strdup(tag); - - g_free(tag); - signal_stop(); -} - -static int sig_query_autoclose(void) -{ - WINDOW_REC *window; - GSList *tmp, *next; - time_t now; - - now = time(NULL); - for (tmp = queries; tmp != NULL; tmp = next) { - QUERY_REC *rec = tmp->data; - - next = tmp->next; - window = window_item_window((WI_ITEM_REC *) rec); - if (window != active_win && rec->new_data == 0 && - now-window->last_line > query_auto_close) - query_destroy(rec); - } - return 1; -} - -static void read_settings(void) -{ - query_auto_close = settings_get_int("autoclose_query"); - if (query_auto_close > 0 && queryclose_tag == -1) - queryclose_tag = g_timeout_add(5000, (GSourceFunc) sig_query_autoclose, NULL); - else if (query_auto_close <= 0 && queryclose_tag != -1) { - g_source_remove(queryclose_tag); - queryclose_tag = -1; - } -} - -void fe_query_init(void) -{ - settings_add_bool("lookandfeel", "autocreate_query", TRUE); - settings_add_bool("lookandfeel", "autocreate_own_query", TRUE); - settings_add_int("lookandfeel", "autoclose_query", 0); - - queryclose_tag = -1; - read_settings(); - - signal_add("query created", (SIGNAL_FUNC) signal_query_created); - signal_add("query destroyed", (SIGNAL_FUNC) signal_query_destroyed); - signal_add("window item remove", (SIGNAL_FUNC) signal_window_item_removed); - signal_add("server connected", (SIGNAL_FUNC) sig_server_connected); - signal_add("window changed", (SIGNAL_FUNC) sig_window_changed); - signal_add("window restore item", (SIGNAL_FUNC) sig_window_restore_item); - signal_add("setup changed", (SIGNAL_FUNC) read_settings); - - command_bind("query", NULL, (SIGNAL_FUNC) cmd_query); - command_bind("unquery", NULL, (SIGNAL_FUNC) cmd_unquery); - command_bind("window server", NULL, (SIGNAL_FUNC) cmd_window_server); - - command_set_options("query", "window"); -} - -void fe_query_deinit(void) -{ - if (queryclose_tag != -1) g_source_remove(queryclose_tag); - - signal_remove("query created", (SIGNAL_FUNC) signal_query_created); - signal_remove("query destroyed", (SIGNAL_FUNC) signal_query_destroyed); - signal_remove("window item remove", (SIGNAL_FUNC) signal_window_item_removed); - signal_remove("server connected", (SIGNAL_FUNC) sig_server_connected); - signal_remove("window changed", (SIGNAL_FUNC) sig_window_changed); - signal_remove("window restore item", (SIGNAL_FUNC) sig_window_restore_item); - signal_remove("setup changed", (SIGNAL_FUNC) read_settings); - - command_unbind("query", (SIGNAL_FUNC) cmd_query); - command_unbind("unquery", (SIGNAL_FUNC) cmd_unquery); - command_unbind("window server", (SIGNAL_FUNC) cmd_window_server); -} diff --git a/src/fe-common/irc/fe-query.h b/src/fe-common/irc/fe-query.h deleted file mode 100644 index a9cbaaaf..00000000 --- a/src/fe-common/irc/fe-query.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __FE_QUERY_H -#define __FE_QUERY_H - -/* Return query where to put the private message. */ -QUERY_REC *privmsg_get_query(IRC_SERVER_REC *server, const char *nick, int own); - -#endif diff --git a/src/fe-common/irc/flood/fe-flood.c b/src/fe-common/irc/flood/fe-flood.c index eca1a3b3..ce96699f 100644 --- a/src/fe-common/irc/flood/fe-flood.c +++ b/src/fe-common/irc/flood/fe-flood.c @@ -23,7 +23,7 @@ #include "signals.h" #include "levels.h" -#include "irc-server.h" +#include "irc-servers.h" #include "irc/flood/autoignore.h" #include "themes.h" diff --git a/src/fe-common/irc/irc-completion.c b/src/fe-common/irc/irc-completion.c index 91e7fecf..1f2bde8e 100644 --- a/src/fe-common/irc/irc-completion.c +++ b/src/fe-common/irc/irc-completion.c @@ -27,10 +27,11 @@ #include "irc.h" #include "irc-commands.h" -#include "server.h" -#include "channels.h" +#include "servers.h" +#include "irc-channels.h" +#include "irc-queries.h" #include "channels-setup.h" -#include "nicklist.h" +#include "irc-nicklist.h" #include "completion.h" #include "window-items.h" @@ -65,7 +66,7 @@ GList *completion_get_channels(IRC_SERVER_REC *server, const char *word) /* get channels from setup */ for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) { - SETUP_CHANNEL_REC *rec = tmp->data; + CHANNEL_SETUP_REC *rec = tmp->data; if (g_strncasecmp(rec->name, word, len) == 0) list = g_list_append(list, g_strdup(rec->name)); @@ -146,7 +147,7 @@ static int nick_completion_timeout(void) for (tmp = servers; tmp != NULL; tmp = tmp->next) { IRC_SERVER_REC *rec = tmp->data; - if (!irc_server_check(rec)) + if (!IS_IRC_SERVER(rec)) continue; mserver = MODULE_DATA(rec); @@ -226,9 +227,9 @@ static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char * if (ischannel(*target)) { /* channel message */ MODULE_CHANNEL_REC *mchannel; - CHANNEL_REC *channel; + IRC_CHANNEL_REC *channel; - channel = channel_find(server, target); + channel = irc_channel_find(server, target); if (channel == NULL) { g_free(params); return; @@ -405,7 +406,7 @@ static void complete_from_nicklist(GList **outlist, GSList *list, } } -static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick, const char *prefix) +static GList *completion_channel_nicks(IRC_CHANNEL_REC *channel, const char *nick, const char *prefix) { MODULE_CHANNEL_REC *mchannel; GSList *nicks, *tmp; @@ -424,7 +425,7 @@ static GList *completion_channel_nicks(CHANNEL_REC *channel, const char *nick, c /* and add the rest of the nicks too */ len = strlen(nick); - nicks = nicklist_getnicks(channel); + nicks = nicklist_getnicks(CHANNEL(channel)); for (tmp = nicks; tmp != NULL; tmp = tmp->next) { NICK_REC *rec = tmp->data; @@ -464,7 +465,7 @@ static void sig_complete_word(GList **list, WINDOW_REC *window, const char *word, const char *linestart) { IRC_SERVER_REC *server; - CHANNEL_REC *channel; + IRC_CHANNEL_REC *channel; GList *tmplist; const char *cmdchars, *nickprefix; char *prefix; @@ -480,7 +481,7 @@ static void sig_complete_word(GList **list, WINDOW_REC *window, return; } - server = window->active_server; + server = IRC_SERVER(window->active_server); if (server == NULL || !server->connected) return; @@ -498,7 +499,7 @@ static void sig_complete_word(GList **list, WINDOW_REC *window, /* nick completion .. we could also be completing a nick after /MSG from nicks in channel */ - channel = irc_item_channel(window->active); + channel = IRC_CHANNEL(window->active); if (channel == NULL) return; @@ -539,7 +540,7 @@ static void sig_complete_msg(GList **list, WINDOW_REC *window, g_return_if_fail(word != NULL); g_return_if_fail(line != NULL); - server = window->active_server; + server = IRC_SERVER(window->active_server); if (server == NULL || !server->connected) return; @@ -549,7 +550,7 @@ static void sig_complete_msg(GList **list, WINDOW_REC *window, } /* expand \n, \t and \\ - FIXME: this doesn't work right */ -static char *expand_escapes(const char *line, IRC_SERVER_REC *server, WI_IRC_REC *item) +static char *expand_escapes(const char *line, IRC_SERVER_REC *server, WI_ITEM_REC *item) { char *ptr, *ret; @@ -590,15 +591,15 @@ static char *expand_escapes(const char *line, IRC_SERVER_REC *server, WI_IRC_REC return ret; } -static void event_text(gchar *line, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void event_text(gchar *line, IRC_SERVER_REC *server, WI_ITEM_REC *item) { - CHANNEL_REC *channel; + IRC_CHANNEL_REC *channel; GList *comp; gchar *str, *ptr; g_return_if_fail(line != NULL); - if (!irc_item_check(item)) + if (!IS_IRC_ITEM(item)) return; /* FIXME: this really should go to fe-common/core. */ @@ -617,10 +618,10 @@ static void event_text(gchar *line, IRC_SERVER_REC *server, WI_IRC_REC *item) ptr = strchr(line, *settings_get_str("completion_char")); if (ptr != NULL) *ptr++ = '\0'; - channel = irc_item_channel(item); + channel = IRC_CHANNEL(item); comp = ptr == NULL || channel == NULL || - nicklist_find(channel, line) != NULL ? NULL : + nicklist_find(CHANNEL(channel), line) != NULL ? NULL : completion_channel_nicks(channel, line, NULL); } @@ -653,7 +654,7 @@ static void completion_init_server(IRC_SERVER_REC *server) g_return_if_fail(server != NULL); - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server)) return; rec = g_new0(MODULE_SERVER_REC, 1); @@ -666,7 +667,7 @@ static void completion_deinit_server(IRC_SERVER_REC *server) g_return_if_fail(server != NULL); - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server)) return; mserver = MODULE_DATA(server); diff --git a/src/fe-common/irc/irc-window-activity.c b/src/fe-common/irc/irc-window-activity.c index 16a24256..4cb2fae8 100644 --- a/src/fe-common/irc/irc-window-activity.c +++ b/src/fe-common/irc/irc-window-activity.c @@ -24,8 +24,8 @@ #include "irc.h" #include "ignore.h" -#include "irc-server.h" -#include "nicklist.h" +#include "irc-servers.h" +#include "irc-nicklist.h" #include "completion.h" #include "windows.h" diff --git a/src/fe-common/irc/notifylist/fe-notifylist.c b/src/fe-common/irc/notifylist/fe-notifylist.c index c13e5c8a..b5a87f5d 100644 --- a/src/fe-common/irc/notifylist/fe-notifylist.c +++ b/src/fe-common/irc/notifylist/fe-notifylist.c @@ -23,12 +23,13 @@ #include "signals.h" #include "commands.h" #include "misc.h" +#include "chatnets.h" #include "lib-config/iconfig.h" #include "settings.h" #include "levels.h" -#include "irc-server.h" -#include "ircnet-setup.h" +#include "irc-servers.h" +#include "irc-chatnets.h" #include "irc/notifylist/notifylist.h" #include "themes.h" @@ -100,10 +101,12 @@ static void cmd_notify_show(void) offline = g_slist_copy(nicks); /* print the notifies on specific ircnets */ - for (tmp = ircnets; tmp != NULL; tmp = tmp->next) { - IRCNET_REC *rec = tmp->data; + for (tmp = chatnets; tmp != NULL; tmp = tmp->next) { + IRC_CHATNET_REC *rec = tmp->data; - server = (IRC_SERVER_REC *) server_find_ircnet(rec->name); + if (!IS_IRCNET(rec)) continue; + + server = (IRC_SERVER_REC *) server_find_chatnet(rec->name); if (server == NULL) continue; print_notify_onserver(server, nicks, &offline, rec->name); @@ -113,7 +116,7 @@ static void cmd_notify_show(void) for (tmp = servers; tmp != NULL; tmp = tmp->next) { server = tmp->data; - if (server->connrec->ircnet != NULL) + if (server->connrec->chatnet != NULL) continue; print_notify_onserver(server, nicks, &offline, server->tag); } @@ -182,7 +185,7 @@ static void notifylist_joined(IRC_SERVER_REC *server, const char *nick, printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_JOIN, nick, username, host, realname, - server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet); + server->connrec->chatnet == NULL ? "IRC" : server->connrec->chatnet); } static void notifylist_left(IRC_SERVER_REC *server, const char *nick, @@ -193,7 +196,7 @@ static void notifylist_left(IRC_SERVER_REC *server, const char *nick, printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_PART, nick, username, host, realname, - server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet); + server->connrec->chatnet == NULL ? "IRC" : server->connrec->chatnet); } static void notifylist_away(IRC_SERVER_REC *server, const char *nick, @@ -205,11 +208,11 @@ static void notifylist_away(IRC_SERVER_REC *server, const char *nick, if (awaymsg != NULL) { printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_AWAY, nick, username, host, realname, awaymsg, - server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet); + server->connrec->chatnet == NULL ? "IRC" : server->connrec->chatnet); } else { printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_UNAWAY, nick, username, host, realname, - server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet); + server->connrec->chatnet == NULL ? "IRC" : server->connrec->chatnet); } } @@ -221,7 +224,7 @@ static void notifylist_unidle(IRC_SERVER_REC *server, const char *nick, printformat(server, NULL, MSGLEVEL_CLIENTNOTICE, IRCTXT_NOTIFY_UNIDLE, nick, username, host, realname, awaymsg != NULL ? awaymsg : "", - server->connrec->ircnet == NULL ? "IRC" : server->connrec->ircnet); + server->connrec->chatnet == NULL ? "IRC" : server->connrec->chatnet); } void fe_irc_notifylist_init(void) diff --git a/src/fe-text/gui-readline.c b/src/fe-text/gui-readline.c index 51f763bb..22d1fb19 100644 --- a/src/fe-text/gui-readline.c +++ b/src/fe-text/gui-readline.c @@ -20,7 +20,7 @@ #include "module.h" #include "signals.h" -#include "server.h" +#include "servers.h" #include "misc.h" #include "completion.h" diff --git a/src/fe-text/gui-special-vars.c b/src/fe-text/gui-special-vars.c index f0a66727..df936c84 100644 --- a/src/fe-text/gui-special-vars.c +++ b/src/fe-text/gui-special-vars.c @@ -25,7 +25,7 @@ #include "gui-readline.h" /* idle time */ -static char *expando_idletime(void *server, void *item, int *free_ret) +static char *expando_idletime(SERVER_REC *server, void *item, int *free_ret) { int diff; @@ -35,13 +35,13 @@ static char *expando_idletime(void *server, void *item, int *free_ret) } /* current contents of the input line */ -static char *expando_inputline(void *server, void *item, int *free_ret) +static char *expando_inputline(SERVER_REC *server, void *item, int *free_ret) { return gui_entry_get_text(); } /* FIXME: value of cutbuffer */ -static char *expando_cutbuffer(void *server, void *item, int *free_ret) +static char *expando_cutbuffer(SERVER_REC *server, void *item, int *free_ret) { return cutbuffer; } diff --git a/src/fe-text/gui-textwidget.c b/src/fe-text/gui-textwidget.c index f3604260..9b16e691 100644 --- a/src/fe-text/gui-textwidget.c +++ b/src/fe-text/gui-textwidget.c @@ -26,7 +26,7 @@ #include "levels.h" #include "settings.h" -#include "irc-server.h" +#include "irc-servers.h" #include "windows.h" #include "screen.h" diff --git a/src/fe-text/gui-windows.c b/src/fe-text/gui-windows.c index b905684c..8e915454 100644 --- a/src/fe-text/gui-windows.c +++ b/src/fe-text/gui-windows.c @@ -21,7 +21,7 @@ #include "module.h" #include "signals.h" #include "commands.h" -#include "server.h" +#include "servers.h" #include "misc.h" #include "settings.h" @@ -244,9 +244,6 @@ void gui_window_newline(GUI_WINDOW_REC *gui, int visible) scrollok(gui->parent->curses_win, TRUE); wscrl(gui->parent->curses_win, 1); scrollok(gui->parent->curses_win, FALSE); - - wmove(gui->parent->curses_win, gui->parent->lines, 0); - wclrtoeol(gui->parent->curses_win); } } diff --git a/src/fe-text/gui-windows.h b/src/fe-text/gui-windows.h index ecadd775..6304a05d 100644 --- a/src/fe-text/gui-windows.h +++ b/src/fe-text/gui-windows.h @@ -1,7 +1,7 @@ #ifndef __GUI_WINDOWS_H #define __GUI_WINDOWS_H -#include "server.h" +#include "servers.h" #include "mainwindows.h" #define WINDOW_GUI(a) ((GUI_WINDOW_REC *) ((a)->gui_data)) diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index 53a48dcc..ec7f979a 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -88,7 +88,7 @@ static void textui_init(void) fe_common_core_init(); fe_common_irc_init(); - theme_register(gui_text_formats); + theme_register(gui_text_formats); signal_add("gui exit", (SIGNAL_FUNC) sig_exit); } diff --git a/src/fe-text/statusbar-items.c b/src/fe-text/statusbar-items.c index d4759401..ca1342ef 100644 --- a/src/fe-text/statusbar-items.c +++ b/src/fe-text/statusbar-items.c @@ -20,14 +20,14 @@ #include "module.h" #include "signals.h" -#include "server.h" +#include "servers.h" #include "misc.h" #include "settings.h" #include "irc.h" #include "channels.h" -#include "query.h" -#include "irc-server.h" +#include "queries.h" +#include "irc-servers.h" #include "nicklist.h" #include "windows.h" @@ -150,7 +150,7 @@ static void statusbar_nick(SBAR_ITEM_REC *item, int ypos) strncpy(nick, server->nick, 9); nick[9] = '\0'; - channel = irc_item_channel(active_win->active); + channel = CHANNEL(active_win->active); nickrec = channel == NULL ? NULL : nicklist_find(channel, server->nick); } @@ -224,7 +224,7 @@ static void statusbar_channel(SBAR_ITEM_REC *item, int ypos) ltoa(winnum, window == NULL ? 0 : window->refnum); - witem = window != NULL && irc_item_check(window->active) ? + witem = window != NULL && (IS_CHANNEL(window->active) || IS_QUERY(window->active)) ? window->active : NULL; if (witem == NULL) { @@ -242,7 +242,7 @@ static void statusbar_channel(SBAR_ITEM_REC *item, int ypos) strncpy(channame, tmpname, 20); channame[20] = '\0'; g_free(tmpname); - channel = irc_item_channel(witem); + channel = CHANNEL(witem); if (channel == NULL) { mode_size = 0; } else { @@ -681,8 +681,8 @@ static void statusbar_topic(SBAR_ITEM_REC *item, int ypos) return; topic = NULL; - channel = irc_item_channel(active_win->active); - query = irc_item_query(active_win->active); + channel = CHANNEL(active_win->active); + query = QUERY(active_win->active); if (channel != NULL && channel->topic != NULL) topic = channel->topic; if (query != NULL && query->address != NULL) topic = query->address; diff --git a/src/fe-text/statusbar.c b/src/fe-text/statusbar.c index efaa7f59..53501067 100644 --- a/src/fe-text/statusbar.c +++ b/src/fe-text/statusbar.c @@ -20,7 +20,7 @@ #include "module.h" #include "signals.h" -#include "server.h" +#include "servers.h" #include "settings.h" #include "windows.h" diff --git a/src/irc/Makefile.am b/src/irc/Makefile.am index e308a7dc..651fedc6 100644 --- a/src/irc/Makefile.am +++ b/src/irc/Makefile.am @@ -4,6 +4,6 @@ endif SUBDIRS = core $(BOT) dcc flood notifylist -noinst_LTLIBRARIES = libirc.la +noinst_LIBRARIES = libirc.a -libirc_la_SOURCES = irc.c +libirc_a_SOURCES = irc.c diff --git a/src/irc/bot/bot-events.c b/src/irc/bot/bot-events.c index d344bb12..ffc403b1 100644 --- a/src/irc/bot/bot-events.c +++ b/src/irc/bot/bot-events.c @@ -23,7 +23,7 @@ #include "commands.h" #include "irc.h" -#include "irc-server.h" +#include "irc-servers.h" #include "channels.h" #include "nicklist.h" #include "modes.h" @@ -31,7 +31,7 @@ #include "bot-users.h" -static int get_flags(USER_REC *user, CHANNEL_REC *channel) +static int get_flags(USER_REC *user, IRC_CHANNEL_REC *channel) { USER_CHAN_REC *userchan; @@ -43,7 +43,7 @@ static int get_flags(USER_REC *user, CHANNEL_REC *channel) (~user->not_flags); } -static void event_massjoin(CHANNEL_REC *channel, GSList *users) +static void event_massjoin(IRC_CHANNEL_REC *channel, GSList *users) { USER_REC *user; USER_CHAN_REC *userchan; @@ -86,7 +86,7 @@ static void event_massjoin(CHANNEL_REC *channel, GSList *users) } /* Parse channel mode string */ -static void parse_channel_mode(CHANNEL_REC *channel, const char *mode, +static void parse_channel_mode(IRC_CHANNEL_REC *channel, const char *mode, const char *nick, const char *address) { NICK_REC *nickrec, *splitnick; @@ -140,7 +140,7 @@ static void parse_channel_mode(CHANNEL_REC *channel, const char *mode, continue; /* check that op is valid */ - nickrec = nicklist_find(channel, ptr); + nickrec = nicklist_find(CHANNEL(channel), ptr); if (nickrec == NULL || nickrec->host == NULL) continue; @@ -169,7 +169,7 @@ static void parse_channel_mode(CHANNEL_REC *channel, const char *mode, static void event_mode(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *params, *channel, *mode; g_return_if_fail(data != NULL); @@ -178,7 +178,7 @@ static void event_mode(const char *data, IRC_SERVER_REC *server, if (ischannel(*channel)) { /* channel mode change */ - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec != NULL) parse_channel_mode(chanrec, mode, nick, address); } diff --git a/src/irc/bot/bot-irc-commands.c b/src/irc/bot/bot-irc-commands.c index f4b2b7f3..5713ccca 100644 --- a/src/irc/bot/bot-irc-commands.c +++ b/src/irc/bot/bot-irc-commands.c @@ -23,10 +23,10 @@ #include "commands.h" #include "irc.h" -#include "irc-server.h" +#include "irc-servers.h" #include "channels.h" #include "nicklist.h" -#include "masks.h" +#include "irc-masks.h" #include "bot-users.h" #include "botnet-users.h" diff --git a/src/irc/bot/bot-users.c b/src/irc/bot/bot-users.c index 2a012b66..26354188 100644 --- a/src/irc/bot/bot-users.c +++ b/src/irc/bot/bot-users.c @@ -28,7 +28,7 @@ #include "lib-config/iconfig.h" #include "channels.h" -#include "nicklist.h" +#include "irc-nicklist.h" #include "masks.h" #include "bot-users.h" @@ -154,7 +154,7 @@ static int botuser_find_mask(USER_REC *user, const char *nick, const char *host) for (tmp = user->masks; tmp != NULL; tmp = tmp->next) { USER_MASK_REC *rec = tmp->data; - if (irc_mask_match_address(rec->mask, nick, host)) { + if (mask_match_address(NULL, rec->mask, nick, host)) { user->not_flags = rec->not_flags; return TRUE; } @@ -194,7 +194,7 @@ USER_REC *botuser_find(const char *nick, const char *host) g_return_val_if_fail(nick != NULL, NULL); /* First check for user with same nick */ - stripnick = nick_strip(nick); + stripnick = irc_nick_strip(nick); user = g_hash_table_lookup(users, stripnick); g_free(stripnick); diff --git a/src/irc/bot/botnet-users.c b/src/irc/bot/botnet-users.c index 3b366ac6..4f5d6c06 100644 --- a/src/irc/bot/botnet-users.c +++ b/src/irc/bot/botnet-users.c @@ -23,7 +23,7 @@ #include "commands.h" #include "irc.h" -#include "irc-server.h" +#include "irc-servers.h" #include "channels.h" #include "nicklist.h" #include "masks.h" diff --git a/src/irc/core/Makefile.am b/src/irc/core/Makefile.am index 86148ed3..c0b8075c 100644 --- a/src/irc/core/Makefile.am +++ b/src/irc/core/Makefile.am @@ -1,56 +1,54 @@ -noinst_LTLIBRARIES = libirc_core.la +noinst_LIBRARIES = libirc_core.a INCLUDES = \ $(GLIB_CFLAGS) \ -DSYSCONFDIR=\""$(sysconfdir)"\" \ -I$(top_srcdir)/src -I$(top_srcdir)/src/core -libirc_core_la_SOURCES = \ +libirc_core_a_SOURCES = \ bans.c \ ctcp.c \ - channels.c \ channels-query.c \ - channels-setup.c \ channel-events.c \ channel-rejoin.c \ ignore.c \ irc.c \ irc-core.c \ + irc-channels.c \ + irc-channels-setup.c \ + irc-chatnets.c \ irc-commands.c \ irc-log.c \ + irc-masks.c \ + irc-nicklist.c \ + irc-queries.c \ irc-rawlog.c \ - irc-server.c \ + irc-servers.c \ + irc-servers-reconnect.c \ + irc-servers-setup.c \ irc-special-vars.c \ - ircnet-setup.c \ lag.c \ - masks.c \ massjoin.c \ modes.c \ mode-lists.c \ netsplit.c \ - nicklist.c \ - query.c \ - server-idle.c \ - server-reconnect.c \ - server-setup.c + server-idle.c noinst_HEADERS = \ bans.h \ ctcp.h \ - channels.h \ - channels-setup.h \ ignore.h \ irc.h \ + irc-channels.h \ + irc-chatnets.h \ irc-commands.h \ - irc-server.h \ - ircnet-setup.h \ - masks.h \ + irc-masks.h \ + irc-nicklist.h \ + irc-queries.h \ + irc-servers.h \ + irc-servers-setup.h \ modes.h \ mode-lists.h \ module.h \ netsplit.h \ - nicklist.h \ - query.h \ - server-idle.h \ - server-reconnect.h \ - server-setup.h + server-idle.h diff --git a/src/irc/core/bans.c b/src/irc/core/bans.c index b5b4e886..f6d68da4 100644 --- a/src/irc/core/bans.c +++ b/src/irc/core/bans.c @@ -19,12 +19,11 @@ */ #include "module.h" - +#include "signals.h" #include "commands.h" #include "misc.h" -#include "signals.h" -#include "masks.h" +#include "irc-masks.h" #include "modes.h" #include "mode-lists.h" #include "irc.h" @@ -33,15 +32,15 @@ static int bantype; /* Get ban mask */ -char *ban_get_mask(CHANNEL_REC *channel, const char *nick) +char *ban_get_mask(IRC_CHANNEL_REC *channel, const char *nick) { NICK_REC *rec; char *str, *user, *host; - g_return_val_if_fail(channel != NULL, NULL); + g_return_val_if_fail(IS_IRC_CHANNEL(channel), NULL); g_return_val_if_fail(nick != NULL, NULL); - rec = nicklist_find(channel, nick); + rec = nicklist_find(CHANNEL(channel), nick); if (rec == NULL || rec->host == NULL) return NULL; str = irc_get_mask(nick, rec->host, bantype); @@ -109,7 +108,7 @@ void ban_set_type(const char *type) signal_emit("ban type changed", 1, bantypestr); } -void ban_set(CHANNEL_REC *channel, const char *bans) +void ban_set(IRC_CHANNEL_REC *channel, const char *bans) { GString *str; char **ban, **banlist, *realban; @@ -136,12 +135,13 @@ void ban_set(CHANNEL_REC *channel, const char *bans) if (str->len > 0) { g_string_truncate(str, str->len-1); - channel_set_singlemode(channel->server, channel->name, str->str, "+b"); + channel_set_singlemode(channel->server, channel->name, + str->str, "+b"); } g_string_free(str, TRUE); } -void ban_remove(CHANNEL_REC *channel, const char *bans) +void ban_remove(IRC_CHANNEL_REC *channel, const char *bans) { GString *str; GSList *tmp; @@ -160,18 +160,19 @@ void ban_remove(CHANNEL_REC *channel, const char *bans) g_strfreev(banlist); if (str->len > 0) - channel_set_singlemode(channel->server, channel->name, str->str, "-b"); + channel_set_singlemode(channel->server, channel->name, + str->str, "-b"); g_string_free(str, TRUE); } -static void command_set_ban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item, int set) +static void command_set_ban(const char *data, IRC_SERVER_REC *server, void *item, int set) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *channel, *nicks; void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (server == NULL || !server->connected || !IS_IRC_SERVER(server)) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, @@ -184,9 +185,11 @@ static void command_set_ban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC nicks = (char *) data; } - chanrec = channel_find(server, channel); - if (chanrec == NULL) cmd_param_error(CMDERR_CHAN_NOT_FOUND); - if (!chanrec->wholist) cmd_param_error(CMDERR_CHAN_NOT_SYNCED); + chanrec = irc_channel_find(server, channel); + if (chanrec == NULL) + cmd_param_error(CMDERR_CHAN_NOT_FOUND); + if (!chanrec->wholist) + cmd_param_error(CMDERR_CHAN_NOT_SYNCED); if (set) ban_set(chanrec, nicks); @@ -204,13 +207,13 @@ static void cmd_bantype(const char *data) } /* SYNTAX: BAN */ -static void cmd_ban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_ban(const char *data, IRC_SERVER_REC *server, void *item) { command_set_ban(data, server, item, TRUE); } /* SYNTAX: UNBAN */ -static void cmd_unban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_unban(const char *data, IRC_SERVER_REC *server, void *item) { command_set_ban(data, server, item, FALSE); } diff --git a/src/irc/core/bans.h b/src/irc/core/bans.h index aa6ff346..9a6587a7 100644 --- a/src/irc/core/bans.h +++ b/src/irc/core/bans.h @@ -1,15 +1,15 @@ #ifndef __BANS_H #define __BANS_H -#include "channels.h" +#include "irc-channels.h" void bans_init(void); void bans_deinit(void); -char *ban_get_mask(CHANNEL_REC *channel, const char *nick); +char *ban_get_mask(IRC_CHANNEL_REC *channel, const char *nick); void ban_set_type(const char *type); -void ban_set(CHANNEL_REC *channel, const char *bans); -void ban_remove(CHANNEL_REC *channel, const char *ban); +void ban_set(IRC_CHANNEL_REC *channel, const char *bans); +void ban_remove(IRC_CHANNEL_REC *channel, const char *ban); #endif diff --git a/src/irc/core/channel-events.c b/src/irc/core/channel-events.c index 26603cd4..936ca0e2 100644 --- a/src/irc/core/channel-events.c +++ b/src/irc/core/channel-events.c @@ -20,10 +20,10 @@ #include "module.h" #include "signals.h" - #include "misc.h" -#include "channels.h" + #include "irc.h" +#include "irc-channels.h" static void event_cannot_join(const char *data, IRC_SERVER_REC *server) { @@ -37,12 +37,12 @@ static void event_cannot_join(const char *data, IRC_SERVER_REC *server) if (channel[0] == '!' && channel[1] == '!') channel++; /* server didn't understand !channels */ - chanrec = channel_find(server, channel); + chanrec = channel_find(SERVER(server), channel); if (chanrec == NULL && channel[0] == '!') { /* it probably replied with the full !channel name, find the channel with the short name.. */ channel = g_strdup_printf("!%s", channel+6); - chanrec = channel_find(server, channel); + chanrec = channel_find(SERVER(server), channel); g_free(channel); } @@ -73,7 +73,7 @@ static void channel_change_topic(IRC_SERVER_REC *server, const char *channel, co { CHANNEL_REC *chanrec; - chanrec = channel_find(server, channel); + chanrec = channel_find(SERVER(server), channel); if (chanrec != NULL) { g_free_not_null(chanrec->topic); chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic); @@ -105,16 +105,18 @@ static void event_topic(const char *data, IRC_SERVER_REC *server) /* Find any unjoined channel that matches `channel'. Long channel names are also a bit problematic, so find a channel where start of the name matches. */ -static CHANNEL_REC *channel_find_unjoined(IRC_SERVER_REC *server, const char *channel) +static IRC_CHANNEL_REC *channel_find_unjoined(IRC_SERVER_REC *server, + const char *channel) { GSList *tmp; int len; len = strlen(channel); for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { - CHANNEL_REC *rec = tmp->data; + IRC_CHANNEL_REC *rec = tmp->data; - if (rec->joined) continue; + if (!IS_IRC_CHANNEL(rec) || rec->joined) + continue; if (g_strncasecmp(channel, rec->name, len) == 0 && (len > 20 || rec->name[len] == '\0')) @@ -127,7 +129,7 @@ static CHANNEL_REC *channel_find_unjoined(IRC_SERVER_REC *server, const char *ch static void event_join(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address) { char *params, *channel, *tmp; - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; g_return_if_fail(data != NULL); @@ -159,7 +161,7 @@ static void event_join(const char *data, IRC_SERVER_REC *server, const char *nic g_free(shortchan); } - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec != NULL && chanrec->joined) { /* already joined this channel - this check was added here because of broken irssi proxy :) */ @@ -170,7 +172,7 @@ static void event_join(const char *data, IRC_SERVER_REC *server, const char *nic chanrec = channel_find_unjoined(server, channel); if (chanrec == NULL) { /* didn't get here with /join command.. */ - chanrec = channel_create(server, channel, TRUE); + chanrec = irc_channel_create(server, channel, TRUE); } chanrec->joined = TRUE; if (strcmp(chanrec->name, channel) != 0) { @@ -195,7 +197,7 @@ static void event_part(const char *data, IRC_SERVER_REC *server, const char *nic params = event_get_params(data, 2, &channel, &reason); - chanrec = channel_find(server, channel); + chanrec = channel_find(SERVER(server), channel); if (chanrec != NULL) { chanrec->left = TRUE; channel_destroy(chanrec); @@ -219,7 +221,7 @@ static void event_kick(const char *data, IRC_SERVER_REC *server) return; } - chanrec = channel_find(server, channel); + chanrec = channel_find(SERVER(server), channel); if (chanrec != NULL) { chanrec->kicked = TRUE; channel_destroy(chanrec); diff --git a/src/irc/core/channel-rejoin.c b/src/irc/core/channel-rejoin.c index b255e228..0715952e 100644 --- a/src/irc/core/channel-rejoin.c +++ b/src/irc/core/channel-rejoin.c @@ -21,25 +21,29 @@ #include "module.h" #include "signals.h" - #include "misc.h" -#include "channels.h" + #include "irc.h" +#include "irc-channels.h" #define REJOIN_TIMEOUT (1000*60*5) /* try to rejoin every 5 minutes */ static int rejoin_tag; +#define channel_have_key(chan) \ + ((chan) != NULL && (chan)->key != NULL && (chan)->key[0] != '\0') + static void channel_rejoin(IRC_SERVER_REC *server, const char *channel) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *str; - chanrec = channel_find(server, channel); - str = chanrec == NULL || chanrec->key == NULL || *chanrec->key == '\0' ? - g_strdup(channel) : g_strdup_printf("%s %s", channel, chanrec->key); + chanrec = irc_channel_find(server, channel); + str = channel_have_key(chanrec) ? g_strdup(channel) : + g_strdup_printf("%s %s", channel, chanrec->key); - server->rejoin_channels = g_slist_append(server->rejoin_channels, str); + server->rejoin_channels = + g_slist_append(server->rejoin_channels, str); } static void event_target_unavailable(const char *data, IRC_SERVER_REC *server) @@ -59,7 +63,7 @@ static void event_target_unavailable(const char *data, IRC_SERVER_REC *server) static void sig_disconnected(IRC_SERVER_REC *server) { - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server)) return; g_slist_foreach(server->rejoin_channels, (GFunc) g_free, NULL); @@ -71,8 +75,9 @@ static void server_rejoin_channels(IRC_SERVER_REC *server) while (server->rejoin_channels != NULL) { char *channel = server->rejoin_channels->data; - channels_join(server, channel, TRUE); - server->rejoin_channels = g_slist_remove(server->rejoin_channels, channel); + irc_channels_join(server, channel, TRUE); + server->rejoin_channels = + g_slist_remove(server->rejoin_channels, channel); } } @@ -83,7 +88,7 @@ static int sig_rejoin(void) for (tmp = servers; tmp != NULL; tmp = tmp->next) { IRC_SERVER_REC *rec = tmp->data; - if (irc_server_check(rec)) + if (IS_IRC_SERVER(rec)) server_rejoin_channels(rec); } @@ -92,7 +97,8 @@ static int sig_rejoin(void) void channel_rejoin_init(void) { - rejoin_tag = g_timeout_add(REJOIN_TIMEOUT, (GSourceFunc) sig_rejoin, NULL); + rejoin_tag = g_timeout_add(REJOIN_TIMEOUT, + (GSourceFunc) sig_rejoin, NULL); signal_add_first("event 437", (SIGNAL_FUNC) event_target_unavailable); signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected); diff --git a/src/irc/core/channels-query.c b/src/irc/core/channels-query.c index 2070e979..ae6c4f71 100644 --- a/src/irc/core/channels-query.c +++ b/src/irc/core/channels-query.c @@ -39,7 +39,6 @@ loop: */ #include "module.h" -#include "modules.h" #include "misc.h" #include "signals.h" @@ -48,8 +47,8 @@ loop: #include "modes.h" #include "mode-lists.h" #include "nicklist.h" -#include "irc-server.h" -#include "server-redirect.h" +#include "irc-servers.h" +#include "servers-redirect.h" enum { CHANNEL_QUERY_MODE, @@ -73,7 +72,7 @@ static void sig_connected(IRC_SERVER_REC *server) SERVER_QUERY_REC *rec; g_return_if_fail(server != NULL); - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server)) return; rec = g_new0(SERVER_QUERY_REC, 1); @@ -86,7 +85,7 @@ static void sig_disconnected(IRC_SERVER_REC *server) int n; g_return_if_fail(server != NULL); - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server)) return; rec = server->chanqueries; @@ -99,7 +98,7 @@ static void sig_disconnected(IRC_SERVER_REC *server) } /* Add channel to query list */ -static void channel_query_add(CHANNEL_REC *channel, int query) +static void channel_query_add(IRC_CHANNEL_REC *channel, int query) { SERVER_QUERY_REC *rec; @@ -111,7 +110,7 @@ static void channel_query_add(CHANNEL_REC *channel, int query) rec->queries[query] = g_slist_append(rec->queries[query], channel); } -static void channel_query_remove_all(CHANNEL_REC *channel) +static void channel_query_remove_all(IRC_CHANNEL_REC *channel) { SERVER_QUERY_REC *rec; int n; @@ -125,7 +124,7 @@ static void channel_query_remove_all(CHANNEL_REC *channel) } -static void sig_channel_destroyed(CHANNEL_REC *channel) +static void sig_channel_destroyed(IRC_CHANNEL_REC *channel) { g_return_if_fail(channel != NULL); @@ -138,9 +137,9 @@ static int channels_have_all_names(IRC_SERVER_REC *server) GSList *tmp; for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { - CHANNEL_REC *rec = tmp->data; + IRC_CHANNEL_REC *rec = tmp->data; - if (!rec->names_got) + if (IS_IRC_CHANNEL(rec) && !rec->names_got) return 0; } @@ -162,7 +161,7 @@ static int find_next_query(SERVER_QUERY_REC *server) static void channel_send_query(IRC_SERVER_REC *server, int query) { SERVER_QUERY_REC *rec; - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; GSList *tmp, *chans; char *cmd, *chanstr_commas, *chanstr; int onlyone; @@ -183,8 +182,8 @@ static void channel_send_query(IRC_SERVER_REC *server, int query) chans = rec->queries[query]; - chanstr_commas = gslistptr_to_string(rec->queries[query], G_STRUCT_OFFSET(CHANNEL_REC, name), ","); - chanstr_spaces = gslistptr_to_string(rec->queries[query], G_STRUCT_OFFSET(CHANNEL_REC, name), " "); + chanstr_commas = gslistptr_to_string(rec->queries[query], G_STRUCT_OFFSET(IRC_CHANNEL_REC, name), ","); + chanstr_spaces = gslistptr_to_string(rec->queries[query], G_STRUCT_OFFSET(IRC_CHANNEL_REC, name), " "); chanstr = g_strconcat(chanstr_commas, " ", chanstr_spaces, NULL); g_free(chanstr_spaces); @@ -304,7 +303,7 @@ static void channels_query_check(IRC_SERVER_REC *server) channel_send_query(server, query); } -static void sig_channel_query(CHANNEL_REC *channel) +static void sig_channel_query(IRC_CHANNEL_REC *channel) { SERVER_QUERY_REC *rec; @@ -328,7 +327,7 @@ static void sig_channel_query(CHANNEL_REC *channel) } /* if there's no more queries in queries in buffer, send the sync signal */ -static void channel_checksync(CHANNEL_REC *channel) +static void channel_checksync(IRC_CHANNEL_REC *channel) { SERVER_QUERY_REC *rec; int n; @@ -350,7 +349,7 @@ static void channel_checksync(CHANNEL_REC *channel) signal_emit("channel sync", 1, channel); } -static void channel_got_query(IRC_SERVER_REC *server, CHANNEL_REC *chanrec, const char *channel) +static void channel_got_query(IRC_SERVER_REC *server, IRC_CHANNEL_REC *chanrec, const char *channel) { SERVER_QUERY_REC *rec; @@ -371,13 +370,13 @@ static void channel_got_query(IRC_SERVER_REC *server, CHANNEL_REC *chanrec, cons static void event_channel_mode(char *data, IRC_SERVER_REC *server, const char *nick) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *params, *channel, *mode; g_return_if_fail(data != NULL); params = event_get_params(data, 3 | PARAM_FLAG_GETREST, NULL, &channel, &mode); - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec != NULL) parse_channel_modes(chanrec, nick, mode); channel_got_query(server, chanrec, channel); @@ -395,7 +394,7 @@ static void multi_query_remove(IRC_SERVER_REC *server, const char *event, const static void event_end_of_who(const char *data, IRC_SERVER_REC *server) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; NICK_REC *nick; char *params, *channel, **chans; int n, onewho; @@ -414,14 +413,14 @@ static void event_end_of_who(const char *data, IRC_SERVER_REC *server) /* check that the WHO actually did return something (that it understood #chan1,#chan2,..) */ - chanrec = channel_find(server, chans[0]); - nick = nicklist_find(chanrec, server->nick); + chanrec = irc_channel_find(server, chans[0]); + nick = nicklist_find(CHANNEL(chanrec), server->nick); if (nick->host == NULL) server->no_multi_who = TRUE; } for (n = 0; chans[n] != NULL; n++) { - chanrec = channel_find(server, chans[n]); + chanrec = irc_channel_find(server, chans[n]); if (chanrec == NULL) continue; @@ -449,13 +448,13 @@ static void event_end_of_who(const char *data, IRC_SERVER_REC *server) static void event_end_of_banlist(const char *data, IRC_SERVER_REC *server) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *params, *channel; g_return_if_fail(data != NULL); params = event_get_params(data, 2, NULL, &channel); - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); channel_got_query(server, chanrec, channel); @@ -464,13 +463,13 @@ static void event_end_of_banlist(const char *data, IRC_SERVER_REC *server) static void event_end_of_ebanlist(const char *data, IRC_SERVER_REC *server) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *params, *channel; g_return_if_fail(data != NULL); params = event_get_params(data, 2, NULL, &channel); - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); channel_got_query(server, chanrec, channel); @@ -479,13 +478,13 @@ static void event_end_of_ebanlist(const char *data, IRC_SERVER_REC *server) static void event_end_of_invitelist(const char *data, IRC_SERVER_REC *server) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *params, *channel; g_return_if_fail(data != NULL); params = event_get_params(data, 2, NULL, &channel); - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); channel_got_query(server, chanrec, channel); @@ -494,9 +493,9 @@ static void event_end_of_invitelist(const char *data, IRC_SERVER_REC *server) static void channel_lost(IRC_SERVER_REC *server, const char *channel) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec != NULL) { /* channel not found - probably created a new channel and left it immediately. */ @@ -508,7 +507,7 @@ static void channel_lost(IRC_SERVER_REC *server, const char *channel) static void multi_command_error(IRC_SERVER_REC *server, const char *data, int query, const char *event) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *params, *channel, **chans; int n; @@ -519,7 +518,7 @@ static void multi_command_error(IRC_SERVER_REC *server, const char *data, int qu chans = g_strsplit(channel, ",", -1); for (n = 0; chans[n] != NULL; n++) { - chanrec = channel_find(server, chans[n]); + chanrec = irc_channel_find(server, chans[n]); if (chanrec != NULL) channel_query_add(chanrec, query); } diff --git a/src/irc/core/channels-setup.c b/src/irc/core/channels-setup.c deleted file mode 100644 index 1252854a..00000000 --- a/src/irc/core/channels-setup.c +++ /dev/null @@ -1,253 +0,0 @@ -/* - channels-setup.c : 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 "irc.h" -#include "channels.h" -#include "channels-setup.h" -#include "nicklist.h" -#include "irc-server.h" -#include "server-setup.h" -#include "special-vars.h" - -#include "lib-config/iconfig.h" -#include "settings.h" - -GSList *setupchannels; - -#define ircnet_match(a, b) \ - ((a) == NULL || (a[0]) == '\0' || (b != NULL && g_strcasecmp(a, b) == 0)) - -static void channel_config_add(SETUP_CHANNEL_REC *channel) -{ - CONFIG_NODE *node; - - node = iconfig_node_traverse("(channels", TRUE); - node = config_node_section(node, NULL, NODE_TYPE_BLOCK); - - iconfig_node_set_str(node, "name", channel->name); - iconfig_node_set_str(node, "ircnet", channel->ircnet); - if (channel->autojoin) - config_node_set_bool(node, "autojoin", TRUE); - iconfig_node_set_str(node, "password", channel->password); - iconfig_node_set_str(node, "botmasks", channel->botmasks); - iconfig_node_set_str(node, "autosendcmd", channel->autosendcmd); - iconfig_node_set_str(node, "background", channel->background); - iconfig_node_set_str(node, "font", channel->font); -} - -static void channel_config_remove(SETUP_CHANNEL_REC *channel) -{ - CONFIG_NODE *node; - - node = iconfig_node_traverse("channels", FALSE); - if (node != NULL) iconfig_node_list_remove(node, g_slist_index(setupchannels, channel)); -} - -void channels_setup_create(SETUP_CHANNEL_REC *channel) -{ - if (g_slist_find(setupchannels, channel) != NULL) { - channel_config_remove(channel); - setupchannels = g_slist_remove(setupchannels, channel); - } - setupchannels = g_slist_append(setupchannels, channel); - - channel_config_add(channel); -} - -static void channels_setup_destroy_rec(SETUP_CHANNEL_REC *channel) -{ - g_return_if_fail(channel != NULL); - - setupchannels = g_slist_remove(setupchannels, channel); - - g_free(channel->name); - g_free(channel->ircnet); - g_free_not_null(channel->password); - g_free_not_null(channel->botmasks); - g_free_not_null(channel->autosendcmd); - g_free_not_null(channel->background); - g_free_not_null(channel->font); - g_free(channel); -} - -void channels_setup_destroy(SETUP_CHANNEL_REC *channel) -{ - channel_config_remove(channel); - channels_setup_destroy_rec(channel); -} - -SETUP_CHANNEL_REC *channels_setup_find(const char *channel, const char *ircnet) -{ - GSList *tmp; - - g_return_val_if_fail(channel != NULL, NULL); - - for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) { - SETUP_CHANNEL_REC *rec = tmp->data; - - if (g_strcasecmp(rec->name, channel) == 0 && - ircnet_match(rec->ircnet, ircnet)) - return rec; - } - - return NULL; -} - -/* connected to server, autojoin to channels. */ -static void event_connected(IRC_SERVER_REC *server) -{ - GString *chans; - GSList *tmp; - - g_return_if_fail(server != NULL); - - if (server->connrec->reconnection) - return; - - /* join to the channels marked with autojoin in setup */ - chans = g_string_new(NULL); - for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) { - SETUP_CHANNEL_REC *rec = tmp->data; - - if (!rec->autojoin || !ircnet_match(rec->ircnet, server->connrec->ircnet)) - continue; - - g_string_sprintfa(chans, "%s,", rec->name); - } - - if (chans->len > 0) { - g_string_truncate(chans, chans->len-1); - channels_join(server, chans->str, TRUE); - } - - g_string_free(chans, TRUE); -} - -/* channel wholist received: send the auto send command */ -static void channel_wholist(CHANNEL_REC *channel) -{ - SETUP_CHANNEL_REC *rec; - NICK_REC *nick; - char **bots, **bot; - - g_return_if_fail(channel != NULL); - - rec = channels_setup_find(channel->name, channel->server->connrec->ircnet); - if (rec == NULL || rec->autosendcmd == NULL || !*rec->autosendcmd) - return; - - if (rec->botmasks == NULL || !*rec->botmasks) { - /* just send the command. */ - eval_special_string(rec->autosendcmd, "", channel->server, channel); - return; - } - - /* find first available bot.. */ - bots = g_strsplit(rec->botmasks, " ", -1); - for (bot = bots; *bot != NULL; bot++) { - const char *botnick = *bot; - - nick = nicklist_find(channel, isnickflag(*botnick) ? - botnick+1 : botnick); - if (nick == NULL) - continue; - if ((*botnick == '@' && !nick->op) || - (*botnick == '+' && !nick->voice && !nick->op)) - continue; - - /* got one! */ - eval_special_string(rec->autosendcmd, nick->nick, channel->server, channel); - break; - } - g_strfreev(bots); -} - -static SETUP_CHANNEL_REC *setupchannel_add(CONFIG_NODE *node) -{ - SETUP_CHANNEL_REC *rec; - char *channel, *ircnet, *password, *botmasks, *autosendcmd, *background, *font; - - g_return_val_if_fail(node != NULL, NULL); - - channel = config_node_get_str(node, "name", NULL); - ircnet = config_node_get_str(node, "ircnet", NULL); - if (channel == NULL || ircnet == NULL) { - /* missing information.. */ - return NULL; - } - - password = config_node_get_str(node, "password", NULL); - botmasks = config_node_get_str(node, "botmasks", NULL); - autosendcmd = config_node_get_str(node, "autosendcmd", NULL); - background = config_node_get_str(node, "background", NULL); - font = config_node_get_str(node, "font", NULL); - - rec = g_new(SETUP_CHANNEL_REC, 1); - rec->autojoin = config_node_get_bool(node, "autojoin", FALSE); - rec->name = g_strdup(channel); - rec->ircnet = g_strdup(ircnet); - rec->password = (password == NULL || *password == '\0') ? NULL : g_strdup(password); - rec->botmasks = (botmasks == NULL || *botmasks == '\0') ? NULL : g_strdup(botmasks); - rec->autosendcmd = (autosendcmd == NULL || *autosendcmd == '\0') ? NULL : g_strdup(autosendcmd); - rec->background = (background == NULL || *background == '\0') ? NULL : g_strdup(background); - rec->font = (font == NULL || *font == '\0') ? NULL : g_strdup(font); - - setupchannels = g_slist_append(setupchannels, rec); - return rec; -} - -static void channels_read_config(void) -{ - CONFIG_NODE *node; - GSList *tmp; - - while (setupchannels != NULL) - channels_setup_destroy_rec(setupchannels->data); - - /* Read channels */ - node = iconfig_node_traverse("channels", FALSE); - if (node != NULL) { - for (tmp = node->value; tmp != NULL; tmp = tmp->next) - setupchannel_add(tmp->data); - } -} - -void channels_setup_init(void) -{ - source_host_ok = FALSE; - - channels_read_config(); - signal_add("event connected", (SIGNAL_FUNC) event_connected); - signal_add("channel wholist", (SIGNAL_FUNC) channel_wholist); - signal_add("setup reread", (SIGNAL_FUNC) channels_read_config); -} - -void channels_setup_deinit(void) -{ - while (setupchannels != NULL) - channels_setup_destroy(setupchannels->data); - - signal_remove("event connected", (SIGNAL_FUNC) event_connected); - signal_remove("channel wholist", (SIGNAL_FUNC) channel_wholist); - signal_remove("setup reread", (SIGNAL_FUNC) channels_read_config); -} diff --git a/src/irc/core/channels-setup.h b/src/irc/core/channels-setup.h deleted file mode 100644 index 9cd2472c..00000000 --- a/src/irc/core/channels-setup.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __CHANNELS_SETUP_H -#define __CHANNELS_SETUP_H - -typedef struct { - int autojoin; - - char *name; - char *ircnet; - char *password; - - char *botmasks; - char *autosendcmd; - - char *background; - char *font; -} SETUP_CHANNEL_REC; - -extern GSList *setupchannels; - -void channels_setup_init(void); -void channels_setup_deinit(void); - -void channels_setup_create(SETUP_CHANNEL_REC *channel); -void channels_setup_destroy(SETUP_CHANNEL_REC *channel); - -SETUP_CHANNEL_REC *channels_setup_find(const char *channel, const char *ircnet); - -#endif diff --git a/src/irc/core/channels.c b/src/irc/core/channels.c deleted file mode 100644 index 158abede..00000000 --- a/src/irc/core/channels.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - channels.c : irssi - - Copyright (C) 1999 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 "modules.h" -#include "misc.h" - -#include "bans.h" -#include "channels.h" -#include "channels-setup.h" -#include "irc.h" -#include "modes.h" -#include "levels.h" -#include "mode-lists.h" -#include "nicklist.h" - -void channels_query_init(void); -void channels_query_deinit(void); - -void channel_events_init(void); -void channel_events_deinit(void); - -void channel_rejoin_init(void); -void channel_rejoin_deinit(void); - -void massjoin_init(void); -void massjoin_deinit(void); - -GSList *channels; /* List of all channels */ - -CHANNEL_REC *channel_create(IRC_SERVER_REC *server, const char *channel, int automatic) -{ - CHANNEL_REC *rec; - - g_return_val_if_fail(channel != NULL, NULL); - - rec = g_new0(CHANNEL_REC, 1); - channels = g_slist_append(channels, rec); - if (server != NULL) - server->channels = g_slist_append(server->channels, rec); - - MODULE_DATA_INIT(rec); - rec->type = module_get_uniq_id("IRC", WI_IRC_CHANNEL); - rec->name = g_strdup(channel); - rec->server = server; - rec->createtime = time(NULL); - rec->mode = g_strdup(""); - - if (*channel == '+') - rec->no_modes = TRUE; - - signal_emit("channel created", 2, rec, GINT_TO_POINTER(automatic)); - - return rec; -} - -void channel_destroy(CHANNEL_REC *channel) -{ - g_return_if_fail(channel != NULL); - - if (channel->destroying) return; - channel->destroying = TRUE; - - channels = g_slist_remove(channels, channel); - if (channel->server != NULL) - channel->server->channels = g_slist_remove(channel->server->channels, channel); - signal_emit("channel destroyed", 1, channel); - - if (channel->server != NULL && !channel->left && !channel->kicked) { - /* destroying channel record without actually left the channel yet */ - irc_send_cmdv(channel->server, "PART %s", channel->name); - } - - MODULE_DATA_DEINIT(channel); - g_free_not_null(channel->topic); - g_free_not_null(channel->key); - g_free(channel->name); - g_free(channel); -} - -static CHANNEL_REC *channel_find_server(IRC_SERVER_REC *server, const char *channel) -{ - GSList *tmp; - - for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { - CHANNEL_REC *rec = tmp->data; - - if (g_strcasecmp(channel, rec->name) == 0) - return rec; - - /* check after removing ABCDE from !ABCDEchannel */ - if (*channel == '!' && *rec->name == '!' && - g_strcasecmp(channel+1, rec->name+6) == 0) - return rec; - } - - return NULL; -} - -CHANNEL_REC *channel_find(IRC_SERVER_REC *server, const char *channel) -{ - g_return_val_if_fail(channel != NULL, NULL); - - if (server != NULL) - return channel_find_server(server, channel); - - /* find from any server */ - return gslist_foreach_find(servers, (FOREACH_FIND_FUNC) channel_find_server, (void *) channel); -} - - -#define get_join_key(key) \ - (((key) == NULL || *(key) == '\0') ? "x" : (key)) - -void channels_join(IRC_SERVER_REC *server, const char *data, int automatic) -{ - SETUP_CHANNEL_REC *schannel; - CHANNEL_REC *chanrec; - GString *outchans, *outkeys; - char *channels, *keys, *key; - char **chanlist, **keylist, **tmp, **tmpkey, *channel; - void *free_arg; - int use_keys; - - g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) - cmd_return_error(CMDERR_NOT_CONNECTED); - - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &channels, &keys)) - return; - if (*channels == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - - chanlist = g_strsplit(channels, ",", -1); - keylist = g_strsplit(keys, ",", -1); - - outchans = g_string_new(NULL); - outkeys = g_string_new(NULL); - - use_keys = *keys != '\0'; - tmpkey = keylist; - for (tmp = chanlist; *tmp != NULL; tmp++) { - channel = ischannel(**tmp) ? g_strdup(*tmp) : - g_strdup_printf("#%s", *tmp); - - chanrec = channel_find(server, channel); - if (chanrec == NULL) { - schannel = channels_setup_find(channel, server->connrec->ircnet); - - g_string_sprintfa(outchans, "%s,", channel); - if (*tmpkey != NULL && **tmpkey != '\0') - key = *tmpkey; - else if (schannel != NULL && schannel->password != NULL) { - /* get password from setup record */ - use_keys = TRUE; - key = schannel->password; - } else key = NULL; - - g_string_sprintfa(outkeys, "%s,", get_join_key(key)); - chanrec = channel_create(server, channel + (channel[0] == '!' && channel[1] == '!'), automatic); - if (key != NULL) chanrec->key = g_strdup(key); - } - g_free(channel); - - if (*tmpkey != NULL) - tmpkey++; - } - - if (outchans->len > 0) { - g_string_truncate(outchans, outchans->len-1); - g_string_truncate(outkeys, outkeys->len-1); - irc_send_cmdv(server, use_keys ? "JOIN %s %s" : "JOIN %s", - outchans->str, outkeys->str); - } - - g_string_free(outchans, TRUE); - g_string_free(outkeys, TRUE); - - g_strfreev(chanlist); - g_strfreev(keylist); - - cmd_params_free(free_arg); -} - -void channels_init(void) -{ - channel_events_init(); - channel_rejoin_init(); - channels_query_init(); - channels_setup_init(); - - bans_init(); - modes_init(); - mode_lists_init(); - massjoin_init(); - nicklist_init(); -} - -void channels_deinit(void) -{ - channel_events_deinit(); - channel_rejoin_deinit(); - channels_query_deinit(); - channels_setup_deinit(); - - bans_deinit(); - modes_deinit(); - mode_lists_deinit(); - massjoin_deinit(); - nicklist_deinit(); -} diff --git a/src/irc/core/channels.h b/src/irc/core/channels.h deleted file mode 100644 index bda4db1d..00000000 --- a/src/irc/core/channels.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef __CHANNELS_H -#define __CHANNELS_H - -#include "irc-server.h" - -typedef struct { - int type; - GHashTable *module_data; - - IRC_SERVER_REC *server; - char *name; - - int new_data; - int last_color; - - time_t createtime; - - GHashTable *nicks; /* list of nicks */ - GSList *banlist; /* list of bans */ - GSList *ebanlist; /* list of ban exceptions */ - GSList *invitelist; /* invite list */ - - char *topic; - - /* channel mode */ - int no_modes:1; /* channel doesn't support modes */ - char *mode; - int limit; /* user limit */ - char *key; /* password key */ - - int chanop:1; /* You're a channel operator */ - - int names_got:1; /* Received /NAMES list */ - int wholist:1; /* WHO list got */ - int synced:1; /* Channel synced - all queries done */ - - int joined:1; /* Have we even received JOIN event for this channel? */ - int left:1; /* You just left the channel */ - int kicked:1; /* You just got kicked */ - int destroying:1; - - time_t massjoin_start; /* Massjoin start time */ - int massjoins; /* Number of nicks waiting for massjoin signal.. */ - int last_massjoins; /* Massjoins when last checked in timeout function */ -} CHANNEL_REC; - -extern GSList *channels; - -void channels_init(void); -void channels_deinit(void); - -/* Create new channel record */ -CHANNEL_REC *channel_create(IRC_SERVER_REC *server, const char *channel, int automatic); -void channel_destroy(CHANNEL_REC *channel); - -/* find channel by name, if `server' is NULL, search from all servers */ -CHANNEL_REC *channel_find(IRC_SERVER_REC *server, const char *channel); - -/* Join to channels. `data' contains channels and channel keys */ -void channels_join(IRC_SERVER_REC *server, const char *data, int automatic); - -#endif diff --git a/src/irc/core/ctcp.c b/src/irc/core/ctcp.c index c3173cb7..8bcd4684 100644 --- a/src/irc/core/ctcp.c +++ b/src/irc/core/ctcp.c @@ -1,7 +1,7 @@ /* ctcp.c : irssi - Copyright (C) 1999 Timo Sirainen + 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 @@ -25,7 +25,7 @@ #include "settings.h" #include "irc.h" -#include "irc-server.h" +#include "irc-servers.h" #include "server-idle.h" #include "ignore.h" @@ -35,8 +35,10 @@ static void ctcp_queue_clean(IRC_SERVER_REC *server) for (tmp = server->ctcpqueue; tmp != NULL; tmp = tmp->next) { next = tmp->next; - if (!server_idle_find(server, GPOINTER_TO_INT(tmp->data))) - server->ctcpqueue = g_slist_remove(server->ctcpqueue, tmp->data); + if (!server_idle_find(server, GPOINTER_TO_INT(tmp->data))) { + server->ctcpqueue = + g_slist_remove(server->ctcpqueue, tmp->data); + } } } @@ -50,15 +52,19 @@ void ctcp_send_reply(IRC_SERVER_REC *server, const char *data) ctcp_queue_clean(server); - if (g_slist_length(server->ctcpqueue) < settings_get_int("max_ctcp_queue")) { - /* Add to first in idle queue */ - tag = server_idle_add(server, data, NULL, 0, NULL); - server->ctcpqueue = g_slist_append(server->ctcpqueue, GINT_TO_POINTER(tag)); - } + if ((int)g_slist_length(server->ctcpqueue) >= + settings_get_int("max_ctcp_queue")) + return; + + /* Add to first in idle queue */ + tag = server_idle_add(server, data, NULL, 0, NULL); + server->ctcpqueue = + g_slist_append(server->ctcpqueue, GINT_TO_POINTER(tag)); } /* CTCP ping */ -static void ctcp_ping(const char *data, IRC_SERVER_REC *server, const char *nick) +static void ctcp_ping(const char *data, IRC_SERVER_REC *server, + const char *nick) { char *str; @@ -72,14 +78,16 @@ static void ctcp_ping(const char *data, IRC_SERVER_REC *server, const char *nick } /* CTCP version */ -static void ctcp_version(const char *data, IRC_SERVER_REC *server, const char *nick) +static void ctcp_version(const char *data, IRC_SERVER_REC *server, + const char *nick) { char *str, *reply; g_return_if_fail(server != NULL); g_return_if_fail(nick != NULL); - reply = parse_special_string(settings_get_str("ctcp_version_reply"), server, NULL, "", NULL); + reply = parse_special_string(settings_get_str("ctcp_version_reply"), + SERVER(server), NULL, "", NULL); str = g_strdup_printf("NOTICE %s :\001VERSION %s\001", nick, reply); ctcp_send_reply(server, str); g_free(str); @@ -107,7 +115,8 @@ static void ctcp_time(const char *data, IRC_SERVER_REC *server, const char *nick g_free(reply); } -static void ctcp_msg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target) +static void ctcp_msg(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *addr, const char *target) { char *args, *str; @@ -119,12 +128,15 @@ static void ctcp_msg(const char *data, IRC_SERVER_REC *server, const char *nick, if (args != NULL) *args++ = '\0'; else args = ""; g_strdown(str+9); - if (!signal_emit(str, 5, args, server, nick, addr, target)) - signal_emit("default ctcp msg", 5, data, server, nick, addr, target); + if (!signal_emit(str, 5, args, server, nick, addr, target)) { + signal_emit("default ctcp msg", 5, + data, server, nick, addr, target); + } g_free(str); } -static void ctcp_reply(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr, const char *target) +static void ctcp_reply(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *addr, const char *target) { char *args, *str; @@ -136,12 +148,15 @@ static void ctcp_reply(const char *data, IRC_SERVER_REC *server, const char *nic if (args != NULL) *args++ = '\0'; else args = ""; g_strdown(str+11); - if (!signal_emit(str, 5, args, server, nick, addr, target)) - signal_emit("default ctcp reply", 5, data, server, nick, addr, target); + if (!signal_emit(str, 5, args, server, nick, addr, target)) { + signal_emit("default ctcp reply", 5, + data, server, nick, addr, target); + } g_free(str); } -static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr) +static void event_privmsg(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *addr) { char *params, *target, *msg, *ptr; @@ -162,7 +177,8 @@ static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char * g_free(params); } -static void event_notice(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr) +static void event_notice(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *addr) { char *params, *target, *ptr, *msg; @@ -186,7 +202,7 @@ static void sig_disconnected(IRC_SERVER_REC *server) { g_return_if_fail(server != NULL); - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server)) return; g_slist_free(server->ctcpqueue); @@ -194,7 +210,8 @@ static void sig_disconnected(IRC_SERVER_REC *server) void ctcp_init(void) { - settings_add_str("misc", "ctcp_version_reply", PACKAGE" v$J - running on $sysname"); + settings_add_str("misc", "ctcp_version_reply", + PACKAGE" v$J - running on $sysname"); settings_add_int("flood", "max_ctcp_queue", 5); signal_add("server disconnected", (SIGNAL_FUNC) sig_disconnected); diff --git a/src/irc/core/ignore.c b/src/irc/core/ignore.c index 705d60c3..ae85a22b 100644 --- a/src/irc/core/ignore.c +++ b/src/irc/core/ignore.c @@ -26,10 +26,10 @@ #include "settings.h" #include "irc.h" -#include "masks.h" -#include "irc-server.h" -#include "channels.h" -#include "nicklist.h" +#include "irc-masks.h" +#include "irc-servers.h" +#include "irc-channels.h" +#include "irc-nicklist.h" #include "ignore.h" @@ -39,7 +39,7 @@ GSList *ignores; static int ignore_check_replies(IGNORE_REC *rec, IRC_SERVER_REC *server, const char *channel, const char *text) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; GSList *nicks, *tmp; g_return_val_if_fail(rec != NULL, FALSE); @@ -47,10 +47,10 @@ static int ignore_check_replies(IGNORE_REC *rec, IRC_SERVER_REC *server, g_return_val_if_fail(channel != NULL, FALSE); g_return_val_if_fail(text != NULL, FALSE); - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec == NULL) return FALSE; - nicks = nicklist_find_multiple(chanrec, rec->mask); + nicks = nicklist_find_multiple(CHANNEL(chanrec), rec->mask); if (nicks == NULL) return FALSE; for (tmp = nicks; tmp != NULL; tmp = tmp->next) { @@ -103,7 +103,7 @@ int ignore_check(IRC_SERVER_REC *server, const char *nick, const char *host, ok = ((host == NULL || *host == '\0')) ? match_wildcards(rec->mask, nick) : - irc_mask_match_address(rec->mask, nick, host); + mask_match_address(SERVER(server), rec->mask, nick, host); if (!ok) { /* nick didn't match, but maybe this is a reply to nick? */ if (!rec->replies || channel == NULL || text == NULL || diff --git a/src/irc/core/irc-channels-setup.c b/src/irc/core/irc-channels-setup.c new file mode 100644 index 00000000..52949783 --- /dev/null +++ b/src/irc/core/irc-channels-setup.c @@ -0,0 +1,116 @@ +/* + irc-channels-setup.c : 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 "nicklist.h" +#include "servers.h" +#include "special-vars.h" + +#include "servers-setup.h" +#include "channels-setup.h" + +#include "irc.h" +#include "irc-chatnets.h" +#include "irc-servers.h" +#include "irc-channels.h" + +/* connected to server, autojoin to channels. */ +static void event_connected(IRC_SERVER_REC *server) +{ + GString *chans; + GSList *tmp; + + g_return_if_fail(server != NULL); + + if (server->connrec->reconnection) + return; + + /* join to the channels marked with autojoin in setup */ + chans = g_string_new(NULL); + for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) { + CHANNEL_SETUP_REC *rec = tmp->data; + + if (!rec->autojoin || + !channel_chatnet_match(rec->chatnet, + server->connrec->chatnet)) + continue; + + g_string_sprintfa(chans, "%s,", rec->name); + } + + if (chans->len > 0) { + g_string_truncate(chans, chans->len-1); + irc_channels_join(server, chans->str, TRUE); + } + + g_string_free(chans, TRUE); +} + +/* channel wholist received: send the auto send command */ +static void channel_wholist(CHANNEL_REC *channel) +{ + CHANNEL_SETUP_REC *rec; + NICK_REC *nick; + char **bots, **bot; + + g_return_if_fail(channel != NULL); + + rec = channels_setup_find(channel->name, channel->server->connrec->chatnet); + if (rec == NULL || rec->autosendcmd == NULL || !*rec->autosendcmd) + return; + + if (rec->botmasks == NULL || !*rec->botmasks) { + /* just send the command. */ + eval_special_string(rec->autosendcmd, "", channel->server, channel); + return; + } + + /* find first available bot.. */ + bots = g_strsplit(rec->botmasks, " ", -1); + for (bot = bots; *bot != NULL; bot++) { + const char *botnick = *bot; + + nick = nicklist_find(channel, isnickflag(*botnick) ? + botnick+1 : botnick); + if (nick == NULL) + continue; + if ((*botnick == '@' && !nick->op) || + (*botnick == '+' && !nick->voice && !nick->op)) + continue; + + /* got one! */ + eval_special_string(rec->autosendcmd, nick->nick, channel->server, channel); + break; + } + g_strfreev(bots); +} + +void irc_channels_setup_init(void) +{ + signal_add("event connected", (SIGNAL_FUNC) event_connected); + signal_add("channel wholist", (SIGNAL_FUNC) channel_wholist); +} + +void irc_channels_setup_deinit(void) +{ + signal_remove("event connected", (SIGNAL_FUNC) event_connected); + signal_remove("channel wholist", (SIGNAL_FUNC) channel_wholist); +} diff --git a/src/irc/core/irc-channels.c b/src/irc/core/irc-channels.c new file mode 100644 index 00000000..72a5d8ec --- /dev/null +++ b/src/irc/core/irc-channels.c @@ -0,0 +1,213 @@ +/* + irc-channels.c : 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 "misc.h" + +#include "bans.h" +#include "irc-channels.h" +#include "channels-setup.h" +#include "irc.h" +#include "modes.h" +#include "levels.h" +#include "mode-lists.h" +#include "irc-nicklist.h" + +void channels_query_init(void); +void channels_query_deinit(void); + +void channel_events_init(void); +void channel_events_deinit(void); + +void channel_rejoin_init(void); +void channel_rejoin_deinit(void); + +void massjoin_init(void); +void massjoin_deinit(void); + +IRC_CHANNEL_REC *irc_channel_create(IRC_SERVER_REC *server, + const char *name, int automatic) +{ + IRC_CHANNEL_REC *rec; + + g_return_val_if_fail(server == NULL || IS_IRC_SERVER(server), NULL); + g_return_val_if_fail(name != NULL, NULL); + + rec = g_new0(IRC_CHANNEL_REC, 1); + rec->chat_type = module_get_uniq_id("IRC CHANNEL", 0); + rec->name = g_strdup(name); + rec->server = server; + if (*name == '+') rec->no_modes = TRUE; + + channel_init((CHANNEL_REC *) rec, automatic); + return rec; +} + +void sig_channel_destroyed(IRC_CHANNEL_REC *channel) +{ + if (!IS_IRC_CHANNEL(channel)) + return; + + if (channel->server != NULL && !channel->left && !channel->kicked) { + /* destroying channel record without actually + having left the channel yet */ + irc_send_cmdv(channel->server, "PART %s", channel->name); + } +} + +#define get_join_key(key) \ + (((key) == NULL || *(key) == '\0') ? "x" : (key)) + +void irc_channels_join(IRC_SERVER_REC *server, const char *data, int automatic) +{ + CHANNEL_SETUP_REC *schannel; + IRC_CHANNEL_REC *chanrec; + GString *outchans, *outkeys; + char *channels, *keys, *key; + char **chanlist, **keylist, **tmp, **tmpkey, *channel; + void *free_arg; + int use_keys; + + g_return_if_fail(data != NULL); + if (!IS_IRC_SERVER(server) || !server->connected) + cmd_return_error(CMDERR_NOT_CONNECTED); + + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &channels, &keys)) + return; + if (*channels == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + chanlist = g_strsplit(channels, ",", -1); + keylist = g_strsplit(keys, ",", -1); + + outchans = g_string_new(NULL); + outkeys = g_string_new(NULL); + + use_keys = *keys != '\0'; + tmpkey = keylist; + for (tmp = chanlist; *tmp != NULL; tmp++) { + channel = ischannel(**tmp) ? g_strdup(*tmp) : + g_strdup_printf("#%s", *tmp); + + chanrec = irc_channel_find(server, channel); + if (chanrec == NULL) { + schannel = channels_setup_find(channel, server->connrec->chatnet); + + g_string_sprintfa(outchans, "%s,", channel); + if (*tmpkey != NULL && **tmpkey != '\0') + key = *tmpkey; + else if (schannel != NULL && schannel->password != NULL) { + /* get password from setup record */ + use_keys = TRUE; + key = schannel->password; + } else key = NULL; + + g_string_sprintfa(outkeys, "%s,", get_join_key(key)); + chanrec = irc_channel_create(server, channel + (channel[0] == '!' && channel[1] == '!'), automatic); + if (key != NULL) chanrec->key = g_strdup(key); + } + g_free(channel); + + if (*tmpkey != NULL) + tmpkey++; + } + + if (outchans->len > 0) { + g_string_truncate(outchans, outchans->len-1); + g_string_truncate(outkeys, outkeys->len-1); + irc_send_cmdv(server, use_keys ? "JOIN %s %s" : "JOIN %s", + outchans->str, outkeys->str); + } + + g_string_free(outchans, TRUE); + g_string_free(outkeys, TRUE); + + g_strfreev(chanlist); + g_strfreev(keylist); + + cmd_params_free(free_arg); +} + +/* function for finding IRC channels - adds support for !channels */ +static CHANNEL_REC *irc_channel_find_server(SERVER_REC *server, + const char *channel) +{ + GSList *tmp; + + for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { + CHANNEL_REC *rec = tmp->data; + + if (rec->chat_type != server->channel_type) + continue; + + if (g_strcasecmp(channel, rec->name) == 0) + return rec; + + /* check after removing ABCDE from !ABCDEchannel */ + if (*channel == '!' && *rec->name == '!' && + g_strcasecmp(channel+1, rec->name+6) == 0) + return rec; + } + + return NULL; +} + +static void sig_connected(SERVER_REC *server) +{ + if (!IS_IRC_SERVER(server)) + return; + + server->channel_find_func = (void *) irc_channel_find_server; + server->channel_type = module_get_uniq_id("IRC CHANNEL", 0);; +} + +void irc_channels_init(void) +{ + signal_add("server connected", (SIGNAL_FUNC) sig_connected); + + channel_events_init(); + channel_rejoin_init(); + channels_query_init(); + channels_setup_init(); + + bans_init(); + modes_init(); + mode_lists_init(); + massjoin_init(); + irc_nicklist_init(); +} + +void irc_channels_deinit(void) +{ + signal_remove("server connected", (SIGNAL_FUNC) sig_connected); + + channel_events_deinit(); + channel_rejoin_deinit(); + channels_query_deinit(); + channels_setup_deinit(); + + bans_deinit(); + modes_deinit(); + mode_lists_deinit(); + massjoin_deinit(); + irc_nicklist_deinit(); + + module_uniq_destroy("IRC CHANNEL"); +} diff --git a/src/irc/core/irc-channels.h b/src/irc/core/irc-channels.h new file mode 100644 index 00000000..aaaf73a7 --- /dev/null +++ b/src/irc/core/irc-channels.h @@ -0,0 +1,42 @@ +#ifndef __IRC_CHANNELS_H +#define __IRC_CHANNELS_H + +#include "channels.h" +#include "irc-servers.h" + +#define IS_IRC_CHANNEL(channel) \ + ((channel) != NULL && \ + module_find_id("IRC CHANNEL", \ + ((IRC_CHANNEL_REC *) (channel))->chat_type) != -1) + +/* Returns IRC_CHANNEL_REC if it's IRC channel, NULL if it isn't. */ +#define IRC_CHANNEL(channel) \ + (IS_IRC_CHANNEL(channel) ? (IRC_CHANNEL_REC *) (channel) : NULL) + +#define STRUCT_SERVER_REC IRC_SERVER_REC +typedef struct { +#include "channel-rec.h" + + GSList *banlist; /* list of bans */ + GSList *ebanlist; /* list of ban exceptions */ + GSList *invitelist; /* invite list */ + + time_t massjoin_start; /* Massjoin start time */ + int massjoins; /* Number of nicks waiting for massjoin signal.. */ + int last_massjoins; /* Massjoins when last checked in timeout function */ +} IRC_CHANNEL_REC; + +void irc_channels_init(void); +void irc_channels_deinit(void); + +/* Create new IRC channel record */ +IRC_CHANNEL_REC *irc_channel_create(IRC_SERVER_REC *server, + const char *name, int automatic); + +#define irc_channel_find(server, name) \ + IRC_CHANNEL(channel_find(SERVER(server), name)) + +/* Join to channels. `data' contains channels and channel keys */ +void irc_channels_join(IRC_SERVER_REC *server, const char *data, int automatic); + +#endif diff --git a/src/irc/core/irc-chatnets.c b/src/irc/core/irc-chatnets.c new file mode 100644 index 00000000..5128d57f --- /dev/null +++ b/src/irc/core/irc-chatnets.c @@ -0,0 +1,132 @@ +/* + irc-chatnets.c : 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 "servers.h" +#include "chatnets.h" +#include "special-vars.h" +#include "lib-config/iconfig.h" +#include "settings.h" + +#include "irc-chatnets.h" + +static void ircnet_read(CONFIG_NODE *node) +{ + IRC_CHATNET_REC *rec; + + if (node == NULL || node->key == NULL) + return; + + rec = g_new0(IRC_CHATNET_REC, 1); + rec->chat_type = module_get_uniq_id("IRC CHATNET", 0); + + rec->max_cmds_at_once = config_node_get_int(node, "cmdmax", 0); + rec->cmd_queue_speed = config_node_get_int(node, "cmdspeed", 0); + + rec->max_kicks = config_node_get_int(node, "max_kicks", 0); + rec->max_msgs = config_node_get_int(node, "max_msgs", 0); + rec->max_modes = config_node_get_int(node, "max_modes", 0); + rec->max_whois = config_node_get_int(node, "max_whois", 0); + + chatnet_read((CHATNET_REC *) rec, node); +} + +static void ircnet_save(IRC_CHATNET_REC *rec) +{ + CONFIG_NODE *node; + + g_return_if_fail(IS_IRC_CHATNET(rec)); + + node = iconfig_node_traverse("ircnets", TRUE); + node = chatnet_save(CHATNET(rec), node); + + if (rec->max_cmds_at_once > 0) + config_node_set_int(node, "cmdmax", rec->max_cmds_at_once); + if (rec->cmd_queue_speed > 0) + config_node_set_int(node, "cmdspeed", rec->cmd_queue_speed); + + if (rec->max_kicks > 0) + config_node_set_int(node, "max_kicks", rec->max_kicks); + if (rec->max_msgs > 0) + config_node_set_int(node, "max_msgs", rec->max_msgs); + if (rec->max_modes > 0) + config_node_set_int(node, "max_modes", rec->max_modes); + if (rec->max_whois > 0) + config_node_set_int(node, "max_whois", rec->max_whois); +} + +static void ircnet_remove(IRC_CHATNET_REC *rec) +{ + CONFIG_NODE *node; + + g_return_if_fail(IS_IRC_CHATNET(rec)); + + node = iconfig_node_traverse("ircnets", FALSE); + if (node != NULL) iconfig_node_set_str(node, rec->name, NULL); +} + +void ircnet_create(IRC_CHATNET_REC *rec) +{ + g_return_if_fail(rec != NULL); + + rec->chat_type = module_get_uniq_id("IRC CHATNET", 0); + + ircnet_save(rec); + chatnet_create(CHATNET(rec)); +} + +static void read_ircnets(void) +{ + CONFIG_NODE *node; + GSList *tmp; + + while (chatnets != NULL) + chatnet_destroy(chatnets->data); + + /* read ircnets */ + node = iconfig_node_traverse("ircnets", FALSE); + if (node != NULL) { + for (tmp = node->value; tmp != NULL; tmp = tmp->next) + ircnet_read(tmp->data); + } +} + +static void sig_chatnet_removed(IRC_CHATNET_REC *rec) +{ + if (IS_IRC_CHATNET(rec)) + ircnet_remove(rec); +} + +void irc_chatnets_init(void) +{ + read_ircnets(); + + signal_add("chatnet removed", (SIGNAL_FUNC) sig_chatnet_removed); + signal_add("setup reread", (SIGNAL_FUNC) read_ircnets); +} + +void irc_chatnets_deinit(void) +{ + signal_remove("chatnet removed", (SIGNAL_FUNC) sig_chatnet_removed); + signal_remove("setup reread", (SIGNAL_FUNC) read_ircnets); + + module_uniq_destroy("IRC CHATNET"); +} diff --git a/src/irc/core/irc-chatnets.h b/src/irc/core/irc-chatnets.h new file mode 100644 index 00000000..25ce05e8 --- /dev/null +++ b/src/irc/core/irc-chatnets.h @@ -0,0 +1,33 @@ +#ifndef __IRC_CHATNETS_H +#define __IRC_CHATNETS_H + +#define IS_IRC_CHATNET(chatnet) \ + ((chatnet) != NULL && \ + module_find_id("IRC CHATNET", (chatnet)->chat_type) != -1) + +/* returns IRC_CHATNET_REC if it's IRC network, NULL if it isn't */ +#define IRC_CHATNET(chatnet) \ + (IS_IRC_CHATNET(chatnet) ? (IRC_CHATNET_REC *) (chatnet) : NULL) + +#define IS_IRCNET(ircnet) IS_IRC_CHATNET(ircnet) +#define IRCNET(ircnet) IRC_CHATNET(ircnet) + +typedef struct { +#include "chatnet-rec.h" + int max_cmds_at_once; + int cmd_queue_speed; + + /* max. number of kicks/msgs/mode/whois per command */ + int max_kicks, max_msgs, max_modes, max_whois; +} IRC_CHATNET_REC; + +void ircnet_create(IRC_CHATNET_REC *rec); + +#define irc_chatnet_find(name) \ + IRC_CHATNET(chatnet_find(name)) +#define ircnet_find(name) irc_chatnet_find(name) + +void irc_chatnets_init(void); +void irc_chatnets_deinit(void); + +#endif diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c index 479ccfd7..4b75e24e 100644 --- a/src/irc/core/irc-commands.c +++ b/src/irc/core/irc-commands.c @@ -24,20 +24,23 @@ #include "misc.h" #include "special-vars.h" #include "settings.h" +#include "window-item-def.h" + +#include "nicklist.h" +#include "servers-redirect.h" +#include "servers-setup.h" #include "bans.h" -#include "channels.h" -#include "irc-server.h" #include "irc.h" -#include "nicklist.h" -#include "server-redirect.h" -#include "server-setup.h" +#include "irc-servers.h" +#include "irc-channels.h" +#include "irc-queries.h" /* How often to check if there's anyone to be unbanned in knockout list */ #define KNOCKOUT_TIMECHECK 10000 typedef struct { - CHANNEL_REC *channel; + IRC_CHANNEL_REC *channel; char *ban; int timeleft; } KNOCKOUT_REC; @@ -85,7 +88,7 @@ IRC_SERVER_REC *irccmd_options_get_server(const char *cmd, static IRC_SERVER_REC *connect_server(const char *data) { - IRC_SERVER_CONNECT_REC *conn; + SERVER_CONNECT_REC *conn; IRC_SERVER_REC *server; GHashTable *optlist; char *addr, *portstr, *password, *nick, *ircnet, *host; @@ -107,11 +110,11 @@ static IRC_SERVER_REC *connect_server(const char *data) *password = '\0'; /* connect to server */ - conn = irc_server_create_conn(addr, atoi(portstr), password, nick); + conn = server_create_conn(addr, atoi(portstr), password, nick); ircnet = g_hash_table_lookup(optlist, "ircnet"); if (ircnet != NULL && *ircnet != '\0') { - g_free_not_null(conn->ircnet); - conn->ircnet = g_strdup(ircnet); + g_free_not_null(conn->chatnet); + conn->chatnet = g_strdup(ircnet); } host = g_hash_table_lookup(optlist, "host"); if (host != NULL && *host != '\0') { @@ -123,7 +126,7 @@ static IRC_SERVER_REC *connect_server(const char *data) memcpy(conn->own_ip, &ip, sizeof(IPADDR)); } } - server = irc_server_connect(conn); + server = irc_server_connect(IRC_SERVER_CONNECT(conn)); cmd_params_free(free_arg); return server; @@ -146,15 +149,12 @@ static void cmd_disconnect(const char *data, IRC_SERVER_REC *server) g_return_if_fail(data != NULL); - if (g_strncasecmp(data, "RECON-", 6) == 0) - return; /* remove reconnection, handle in server-reconnect.c */ - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &tag, &msg)) return; if (*tag != '\0' && strcmp(tag, "*") != 0) server = (IRC_SERVER_REC *) server_find_tag(tag); - if (server == NULL || !irc_server_check(server)) + if (server == NULL || !IS_IRC_SERVER(server)) cmd_param_error(CMDERR_NOT_CONNECTED); if (*msg == '\0') msg = (char *) settings_get_str("quit_message"); @@ -192,7 +192,7 @@ static void cmd_server(const char *data, IRC_SERVER_REC *server) if (*addr == '+' || server == NULL) { channels = away_reason = usermode = ircnet = NULL; } else { - ircnet = g_strdup(server->connrec->ircnet); + ircnet = g_strdup(server->connrec->chatnet); channels = irc_server_get_channels((IRC_SERVER_REC *) server); if (*channels == '\0') g_free_and_null(channels); @@ -204,8 +204,8 @@ static void cmd_server(const char *data, IRC_SERVER_REC *server) server = connect_server(data); if (*addr == '+' || server == NULL || - (ircnet != NULL && server->connrec->ircnet != NULL && - g_strcasecmp(ircnet, server->connrec->ircnet) != 0)) { + (ircnet != NULL && server->connrec->chatnet != NULL && + g_strcasecmp(ircnet, server->connrec->chatnet) != 0)) { g_free_not_null(channels); g_free_not_null(usermode); g_free_not_null(away_reason); @@ -244,7 +244,7 @@ static void cmd_quit(const char *data) } /* SYNTAX: MSG [-] */ -static void cmd_msg(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_msg(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { GHashTable *optlist; char *target, *msg; @@ -260,14 +260,14 @@ static void cmd_msg(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) if (*target == '\0' || *msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); server = irccmd_options_get_server("msg", optlist, server); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_param_error(CMDERR_NOT_CONNECTED); free_ret = FALSE; if (strcmp(target, ",") == 0 || strcmp(target, ".") == 0) - target = parse_special(&target, server, item, NULL, &free_ret, NULL); + target = parse_special(&target, SERVER(server), item, NULL, &free_ret, NULL); else if (strcmp(target, "*") == 0 && - (irc_item_channel(item) || irc_item_query(item))) + (IS_IRC_CHANNEL(item) || IS_IRC_QUERY(item))) target = item->name; if (target != NULL) { g_string_sprintf(tmpstr, "PRIVMSG %s :%s", target, msg); @@ -286,7 +286,7 @@ static void cmd_notice(const char *data, IRC_SERVER_REC *server) void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) @@ -306,7 +306,7 @@ static void cmd_ctcp(const char *data, IRC_SERVER_REC *server) void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) @@ -330,7 +330,7 @@ static void cmd_nctcp(const char *data, IRC_SERVER_REC *server) void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_GETREST, &target, &ctcpcmd, &ctcpdata)) @@ -352,7 +352,7 @@ static void cmd_join(const char *data, IRC_SERVER_REC *server) void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | PARAM_FLAG_UNKNOWN_OPTIONS | @@ -361,32 +361,32 @@ static void cmd_join(const char *data, IRC_SERVER_REC *server) if (g_hash_table_lookup(optlist, "invite")) { if (server->last_invite != NULL) - channels_join(server, server->last_invite, FALSE); + irc_channels_join(server, server->last_invite, FALSE); } else { /* - */ server = irccmd_options_get_server("join", optlist, server); - if (server != NULL) channels_join(server, channels, FALSE); + if (server != NULL) irc_channels_join(server, channels, FALSE); } cmd_params_free(free_arg); } /* SYNTAX: PART [] [] */ -static void cmd_part(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_part(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *channame, *msg; void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channame, &msg)) return; if (*channame == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - chanrec = channel_find(server, channame); + chanrec = irc_channel_find(server, channame); if (chanrec == NULL) cmd_param_error(CMDERR_CHAN_NOT_FOUND); irc_send_cmdv(server, *msg == '\0' ? "PART %s" : "PART %s :%s", @@ -396,13 +396,13 @@ static void cmd_part(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) } /* SYNTAX: KICK [] [] */ -static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { char *channame, *nicks, *reason; void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 3 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, @@ -419,14 +419,14 @@ static void cmd_kick(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) } /* SYNTAX: TOPIC [-delete] [] [] */ -static void cmd_topic(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_topic(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { GHashTable *optlist; char *channame, *topic; void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | @@ -442,13 +442,13 @@ static void cmd_topic(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item } /* SYNTAX: INVITE [] */ -static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { char *nick, *channame; void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2, &nick, &channame)) @@ -456,7 +456,7 @@ static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *ite if (*nick == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*channame == '\0' || strcmp(channame, "*") == 0) { - if (!irc_item_channel(item)) + if (!IS_IRC_CHANNEL(item)) cmd_param_error(CMDERR_NOT_JOINED); channame = item->name; @@ -467,14 +467,14 @@ static void cmd_invite(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *ite } /* SYNTAX: LIST [-yes] [] */ -static void cmd_list(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_list(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { GHashTable *optlist; char *str; void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | @@ -492,20 +492,20 @@ static void cmd_list(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) } /* SYNTAX: WHO ||** */ -static void cmd_who(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_who(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { char *channel, *rest; void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &channel, &rest)) return; if (strcmp(channel, "*") == 0 || *channel == '\0') { - if (!irc_item_channel(item)) + if (!IS_IRC_CHANNEL(item)) cmd_param_error(CMDERR_NOT_JOINED); channel = item->name; @@ -524,16 +524,16 @@ static void cmd_who(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) } /* SYNTAX: NAMES [-yes] [] */ -static void cmd_names(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_names(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (*data == '\0') cmd_return_error(CMDERR_NOT_GOOD_IDEA); if (strcmp(data, "*") == 0) { - if (!irc_item_channel(item)) + if (!IS_IRC_CHANNEL(item)) cmd_return_error(CMDERR_NOT_JOINED); data = item->name; @@ -572,7 +572,7 @@ static void cmd_whois(const char *data, IRC_SERVER_REC *server) int free_nick; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2, &qserver, &query)) @@ -642,7 +642,7 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server) int free_nick; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2, &nicks, &count)) @@ -662,17 +662,17 @@ static void cmd_whowas(const char *data, IRC_SERVER_REC *server) } /* SYNTAX: PING */ -static void cmd_ping(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_ping(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { GTimeVal tv; char *str; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (*data == '\0' || strcmp(data, "*") == 0) { - if (!irc_item_check(item)) + if (!IS_IRC_ITEM(item)) cmd_return_error(CMDERR_NOT_JOINED); data = item->name; @@ -701,7 +701,7 @@ static void cmd_away(const char *data, IRC_SERVER_REC *server) void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 1 | PARAM_FLAG_OPTIONS | @@ -719,7 +719,7 @@ static void cmd_away(const char *data, IRC_SERVER_REC *server) static void cmd_deop(const char *data, IRC_SERVER_REC *server) { g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (*data == '\0') @@ -730,7 +730,7 @@ static void cmd_deop(const char *data, IRC_SERVER_REC *server) static void cmd_sconnect(const char *data, IRC_SERVER_REC *server) { g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -741,7 +741,7 @@ static void cmd_sconnect(const char *data, IRC_SERVER_REC *server) static void cmd_quote(const char *data, IRC_SERVER_REC *server) { g_return_if_fail(data != NULL); - if (server == NULL || !irc_server_check(server)) + if (server == NULL || !IS_IRC_SERVER(server)) cmd_return_error(CMDERR_NOT_CONNECTED); irc_send_cmd(server, data); @@ -753,15 +753,15 @@ static void cmd_wall_hash(gpointer key, NICK_REC *nick, GSList **nicks) } /* SYNTAX: WALL [] */ -static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { char *channame, *msg, *args; void *free_arg; - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; GSList *tmp, *nicks; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN | @@ -769,7 +769,7 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) return; if (*msg == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - chanrec = channel_find(server, channame); + chanrec = irc_channel_find(server, channame); if (chanrec == NULL) cmd_param_error(CMDERR_CHAN_NOT_FOUND); /* send notice to all ops */ @@ -777,7 +777,8 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) g_hash_table_foreach(chanrec->nicks, (GHFunc) cmd_wall_hash, &nicks); args = g_strconcat(chanrec->name, " ", msg, NULL); - msg = parse_special_string(settings_get_str("wall_format"), server, item, args, NULL); + msg = parse_special_string(settings_get_str("wall_format"), + SERVER(server), item, args, NULL); g_free(args); for (tmp = nicks; tmp != NULL; tmp = tmp->next) { @@ -793,21 +794,21 @@ static void cmd_wall(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) } /* SYNTAX: CYCLE [] [] */ -static void cmd_cycle(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_cycle(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *channame, *msg; void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_OPTCHAN, item, &channame, &msg)) return; if (*channame == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); - chanrec = channel_find(server, channame); + chanrec = irc_channel_find(server, channame); if (chanrec == NULL) cmd_param_error(CMDERR_CHAN_NOT_FOUND); irc_send_cmdv(server, *msg == '\0' ? "PART %s" : "PART %s :%s", @@ -819,7 +820,7 @@ static void cmd_cycle(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item } /* SYNTAX: KICKBAN [] */ -static void cmd_kickban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_kickban(const char *data, IRC_SERVER_REC *server, WI_ITEM_REC *item) { char *nick; void *free_arg; @@ -850,7 +851,7 @@ static void knockout_timeout_server(IRC_SERVER_REC *server) g_return_if_fail(server != NULL); - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server)) return; t = server->knockout_lastcheck == 0 ? 0 : @@ -878,19 +879,19 @@ static int knockout_timeout(void) } /* SYNTAX: KNOCKOUT [] */ -static void cmd_knockout(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_knockout(const char *data, IRC_SERVER_REC *server, + IRC_CHANNEL_REC *channel) { KNOCKOUT_REC *rec; - CHANNEL_REC *channel; char *nick, *reason, *timeoutstr, *str; void *free_arg; int timeleft; g_return_if_fail(data != NULL); - if (server == NULL) cmd_return_error(CMDERR_NOT_CONNECTED); - - channel = irc_item_channel(item); - if (channel == NULL) cmd_return_error(CMDERR_NOT_JOINED); + if (!IS_IRC_SERVER(server) || !server->connected) + cmd_return_error(CMDERR_NOT_CONNECTED); + if (!IS_IRC_CHANNEL(channel)) + cmd_return_error(CMDERR_NOT_JOINED); if (is_numeric(data, ' ')) { /* first argument is the timeout */ @@ -928,7 +929,7 @@ static void sig_server_disconnected(IRC_SERVER_REC *server) { g_return_if_fail(server != NULL); - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server)) return; while (server->knockoutlist != NULL) @@ -936,12 +937,12 @@ static void sig_server_disconnected(IRC_SERVER_REC *server) } /* destroy all knockouts in channel */ -static void sig_channel_destroyed(CHANNEL_REC *channel) +static void sig_channel_destroyed(IRC_CHANNEL_REC *channel) { GSList *tmp, *next; - g_return_if_fail(channel != NULL); - if (channel->server == NULL) return; + if (!IS_IRC_CHANNEL(channel) || !IS_IRC_SERVER(channel->server)) + return; for (tmp = channel->server->knockoutlist; tmp != NULL; tmp = next) { KNOCKOUT_REC *rec = tmp->data; @@ -959,7 +960,7 @@ static void cmd_oper(const char *data, IRC_SERVER_REC *server) void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2, &nick, &password)) @@ -977,7 +978,7 @@ static void cmd_oper(const char *data, IRC_SERVER_REC *server) static void command_self(const char *data, IRC_SERVER_REC *server) { g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); irc_send_cmdv(server, *data == '\0' ? "%s" : "%s %s", current_command, data); @@ -986,7 +987,7 @@ static void command_self(const char *data, IRC_SERVER_REC *server) static void command_1self(const char *data, IRC_SERVER_REC *server) { g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); @@ -999,7 +1000,7 @@ static void command_2self(const char *data, IRC_SERVER_REC *server) void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (!IS_IRC_SERVER(server) || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &text)) diff --git a/src/irc/core/irc-core.c b/src/irc/core/irc-core.c index d54db954..932ede83 100644 --- a/src/irc/core/irc-core.c +++ b/src/irc/core/irc-core.c @@ -20,9 +20,9 @@ #include "module.h" -#include "irc-server.h" -#include "channels.h" -#include "query.h" +#include "irc-servers.h" +#include "irc-channels.h" +#include "irc-queries.h" #include "ctcp.h" #include "ignore.h" @@ -47,8 +47,8 @@ void lag_deinit(void); void irc_core_init(void) { irc_servers_init(); - channels_init(); - query_init(); + irc_channels_init(); + irc_queries_init(); ctcp_init(); irc_commands_init(); @@ -72,8 +72,8 @@ void irc_core_deinit(void) irc_commands_deinit(); ctcp_deinit(); - query_deinit(); - channels_deinit(); + irc_queries_deinit(); + irc_channels_deinit(); irc_irc_deinit(); irc_servers_deinit(); } diff --git a/src/irc/core/irc-log.c b/src/irc/core/irc-log.c index 3006f58d..abe557c5 100644 --- a/src/irc/core/irc-log.c +++ b/src/irc/core/irc-log.c @@ -24,7 +24,7 @@ #include "log.h" #include "settings.h" -#include "irc-server.h" +#include "irc-servers.h" static LOG_REC *awaylog; static int away_filepos; diff --git a/src/irc/core/irc-masks.c b/src/irc/core/irc-masks.c new file mode 100644 index 00000000..1c895998 --- /dev/null +++ b/src/irc/core/irc-masks.c @@ -0,0 +1,97 @@ +/* + masks.c : 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 "network.h" + +#include "irc.h" +#include "irc-masks.h" + +static char *get_domain_mask(char *host) +{ + char *ptr; + + if (strchr(host, '.') == NULL) { + /* no dots - toplevel domain or IPv6 address */ + ptr = strrchr(host, ':'); + if (ptr != NULL) { + /* IPv6 address, ban the last 64k addresses */ + if (ptr[1] != '\0') strcpy(ptr+1, "*"); + } + + return host; + } + + if (is_ipv4_address(host)) { + /* it's an IP address, change last digit to * */ + ptr = strrchr(host, '.'); + if (ptr != NULL && isdigit(ptr[1])) + strcpy(ptr+1, "*"); + } else { + /* if more than one dot, skip the first + (dyn123.blah.net -> *.blah.net) */ + ptr = strchr(host, '.'); + if (ptr != NULL && strchr(ptr+1, '.') != NULL) { + host = ptr-1; + host[0] = '*'; + } + } + + return host; +} + +char *irc_get_mask(const char *nick, const char *address, int flags) +{ + char *ret, *user, *host; + + /* strip -, ^ or ~ from start.. */ + user = g_strconcat("*", ishostflag(*address) ? + address+1 : address, NULL); + + /* split user and host */ + host = strchr(user, '@'); + if (host == NULL) { + g_free(user); + return NULL; + } + *host++ = '\0'; + + switch (flags & (IRC_MASK_HOST|IRC_MASK_DOMAIN)) { + case IRC_MASK_HOST: + /* we already have the host */ + break; + case IRC_MASK_DOMAIN: + /* domain - *.blah.org */ + host = get_domain_mask(host); + break; + default: + /* no domain/host */ + host = "*"; + break; + } + + ret = g_strdup_printf("%s!%s@%s", + (flags & IRC_MASK_NICK) ? nick : "*", + (flags & IRC_MASK_USER) ? user : "*", + host); + g_free(user); + + return ret; +} diff --git a/src/irc/core/irc-masks.h b/src/irc/core/irc-masks.h new file mode 100644 index 00000000..680877c9 --- /dev/null +++ b/src/irc/core/irc-masks.h @@ -0,0 +1,13 @@ +#ifndef __IRC_MASKS_H +#define __IRC_MASKS_H + +#include "masks.h" + +#define IRC_MASK_NICK 0x01 +#define IRC_MASK_USER 0x02 +#define IRC_MASK_HOST 0x04 +#define IRC_MASK_DOMAIN 0x08 + +char *irc_get_mask(const char *nick, const char *address, int flags); + +#endif diff --git a/src/irc/core/irc-nicklist.c b/src/irc/core/irc-nicklist.c new file mode 100644 index 00000000..e8eb14f2 --- /dev/null +++ b/src/irc/core/irc-nicklist.c @@ -0,0 +1,401 @@ +/* + irc-nicklist.c : 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 "misc.h" + +#include "irc.h" +#include "irc-channels.h" +#include "irc-masks.h" +#include "irc-nicklist.h" +#include "modes.h" +#include "servers.h" + +#define isnickchar(a) \ + (isalnum((int) (a)) || (a) == '`' || (a) == '-' || (a) == '_' || \ + (a) == '[' || (a) == ']' || (a) == '{' || (a) == '}' || \ + (a) == '|' || (a) == '\\' || (a) == '^') + +/* Remove all "extra" characters from `nick'. Like _nick_ -> nick */ +char *irc_nick_strip(const char *nick) +{ + char *stripped, *spos; + + g_return_val_if_fail(nick != NULL, NULL); + + spos = stripped = g_strdup(nick); + while (isnickchar(*nick)) { + if (isalnum((int) *nick)) + *spos++ = *nick; + nick++; + } + if ((unsigned char) *nick >= 128) + *spos++ = *nick; /* just add it so that nicks won't match.. */ + *spos = '\0'; + return stripped; +} + +/* Check is `msg' is meant for `nick'. */ +int irc_nick_match(const char *nick, const char *msg) +{ + char *stripnick, *stripmsg; + int ret, len; + + g_return_val_if_fail(nick != NULL, FALSE); + g_return_val_if_fail(msg != NULL, FALSE); + + len = strlen(nick); + if (g_strncasecmp(msg, nick, len) == 0 && !isalnum((int) msg[len])) + return TRUE; + + stripnick = irc_nick_strip(nick); + stripmsg = irc_nick_strip(msg); + + len = strlen(stripnick); + ret = len > 0 && g_strncasecmp(stripmsg, stripnick, len) == 0 && + !isalnum((int) stripmsg[len]) && + (unsigned char) stripmsg[len] < 128; + + g_free(stripnick); + g_free(stripmsg); + return ret; +} + +static void event_names_list(const char *data, SERVER_REC *server) +{ + CHANNEL_REC *chanrec; + char *params, *type, *channel, *names, *ptr; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 4, NULL, &type, &channel, &names); + + chanrec = channel_find(server, channel); + if (chanrec == NULL || chanrec->names_got) { + /* unknown channel / names list already read */ + g_free(params); + return; + } + + /* type = '=' = public, '*' = private, '@' = secret. + + This is actually pretty useless to check here, but at least we + get to know if the channel is +p or +s a few seconds before + we receive the MODE reply... */ + if (*type == '*') + parse_channel_modes(IRC_CHANNEL(chanrec), NULL, "+p"); + else if (*type == '@') + parse_channel_modes(IRC_CHANNEL(chanrec), NULL, "+s"); + + while (*names != '\0') { + while (*names == ' ') names++; + ptr = names; + while (*names != '\0' && *names != ' ') names++; + if (*names != '\0') *names++ = '\0'; + + if (*ptr == '@' && g_strcasecmp(server->nick, ptr+1) == 0) + chanrec->chanop = TRUE; + + nicklist_insert(chanrec, ptr+isnickflag(*ptr), + *ptr == '@', *ptr == '+', FALSE); + } + + g_free(params); +} + +static void event_end_of_names(const char *data, SERVER_REC *server) +{ + char *params, *channel; + IRC_CHANNEL_REC *chanrec; + + g_return_if_fail(server != NULL); + + params = event_get_params(data, 2, NULL, &channel); + + chanrec = irc_channel_find(server, channel); + if (chanrec != NULL && !chanrec->names_got) { + chanrec->names_got = TRUE; + signal_emit("channel query", 1, chanrec); + } + + g_free(params); +} + +static void event_who(const char *data, SERVER_REC *server) +{ + char *params, *nick, *channel, *user, *host, *stat, *realname, *hops; + CHANNEL_REC *chanrec; + NICK_REC *nickrec; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 8, NULL, &channel, &user, &host, + NULL, &nick, &stat, &realname); + + /* get hop count */ + hops = realname; + while (*realname != '\0' && *realname != ' ') realname++; + *realname++ = '\0'; + while (*realname == ' ') realname++; + + /* update host, realname, hopcount */ + chanrec = channel_find(server, channel); + nickrec = chanrec == NULL ? NULL : + nicklist_find(chanrec, nick); + if (nickrec != NULL) { + if (nickrec->host == NULL) + nickrec->host = g_strdup_printf("%s@%s", user, host); + if (nickrec->realname == NULL) + nickrec->realname = g_strdup(realname); + sscanf(hops, "%d", &nickrec->hops); + } + + nicklist_update_flags(server, nick, + strchr(stat, 'G') != NULL, /* gone */ + strchr(stat, '*') != NULL); /* ircop */ + + g_free(params); +} + +static void event_whois(const char *data, IRC_SERVER_REC *server) +{ + char *params, *nick, *realname; + GSList *nicks, *tmp; + NICK_REC *rec; + + g_return_if_fail(data != NULL); + + server->whois_coming = TRUE; + + /* first remove the gone-flag, if user is gone + it will be set later.. */ + params = event_get_params(data, 6, NULL, &nick, NULL, + NULL, NULL, &realname); + + nicks = nicklist_get_same(SERVER(server), nick); + for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) { + rec = tmp->next->data; + + if (rec->realname == NULL) + rec->realname = g_strdup(realname); + } + g_slist_free(nicks); + + /* reset gone and ircop status, we'll handle them in the following + WHOIS replies */ + nicklist_update_flags(SERVER(server), nick, FALSE, FALSE); + g_free(params); +} + +static void event_whois_away(const char *data, SERVER_REC *server) +{ + char *params, *nick, *awaymsg; + + g_return_if_fail(data != NULL); + + /* set user's gone flag.. */ + params = event_get_params(data, 3, NULL, &nick, &awaymsg); + nicklist_update_flags(server, nick, TRUE, -1); + g_free(params); +} + +static void event_whois_ircop(const char *data, SERVER_REC *server) +{ + char *params, *nick, *awaymsg; + + g_return_if_fail(data != NULL); + + /* set user's gone flag.. */ + params = event_get_params(data, 3, NULL, &nick, &awaymsg); + nicklist_update_flags(server, nick, -1, TRUE); + g_free(params); +} + +static void event_end_of_whois(const char *data, IRC_SERVER_REC *server) +{ + server->whois_coming = FALSE; +} + +static void event_nick_in_use(const char *data, IRC_SERVER_REC *server) +{ + char *str; + int n; + + g_return_if_fail(data != NULL); + + if (server->connected) { + /* Already connected, no need to handle this anymore. */ + return; + } + + /* nick already in use - need to change it .. */ + if (strcmp(server->nick, server->connrec->nick) == 0 && + server->connrec->alternate_nick != NULL) { + /* first try, so try the alternative nick.. */ + g_free(server->nick); + server->nick = g_strdup(server->connrec->alternate_nick); + } + else if (strlen(server->nick) < 9) { + /* keep adding '_' to end of nick.. */ + str = g_strdup_printf("%s_", server->nick); + g_free(server->nick); + server->nick = str; + } else { + /* nick full, keep adding number at the end */ + for (n = 8; n > 0; n--) { + if (server->nick[n] < '0' || server->nick[n] > '9') { + server->nick[n] = '1'; + break; + } + + if (server->nick[n] < '9') { + server->nick[n]++; + break; + } + server->nick[n] = '0'; + } + } + + irc_send_cmdv(server, "NICK %s", server->nick); +} + +static void event_target_unavailable(const char *data, IRC_SERVER_REC *server) +{ + char *params, *channel; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2, NULL, &channel); + if (!ischannel(*channel)) { + /* nick is unavailable. */ + event_nick_in_use(data, server); + } + + g_free(params); +} + +static void event_nick(const char *data, SERVER_REC *server, + const char *orignick) +{ + IRC_CHANNEL_REC *channel; + NICK_REC *nickrec; + GSList *nicks, *tmp; + char *params, *nick; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 1, &nick); + + if (g_strcasecmp(orignick, server->nick) == 0) { + /* You changed your nick */ + g_free(server->connrec->nick); + g_free(server->nick); + server->connrec->nick = g_strdup(nick); + server->nick = g_strdup(nick); + signal_emit("server nick changed", 1, server); + } + + nicks = nicklist_get_same(server, orignick); + for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) { + channel = tmp->data; + nickrec = tmp->next->data; + + /* remove old nick from hash table */ + g_hash_table_remove(channel->nicks, nickrec->nick); + + g_free(nickrec->nick); + nickrec->nick = g_strdup(nick); + + /* add new nick to hash table */ + g_hash_table_insert(channel->nicks, nickrec->nick, nickrec); + + signal_emit("nicklist changed", 3, channel, nickrec, orignick); + } + g_slist_free(nicks); + + g_free(params); +} + +static void event_userhost(const char *data, SERVER_REC *server) +{ + char *params, *hosts, **phosts, **pos, *ptr; + + g_return_if_fail(data != NULL); + + /* set user's gone flag.. */ + params = event_get_params(data, 2, NULL, &hosts); + + phosts = g_strsplit(hosts, " ", -1); + for (pos = phosts; *pos != NULL; pos++) { + ptr = strchr(*pos, '='); + if (ptr == NULL) continue; + *ptr++ = '\0'; + + nicklist_update_flags(server, *pos, *ptr == '-', -1); + } + g_strfreev(phosts); + g_free(params); +} + +static void sig_usermode(SERVER_REC *server) +{ + g_return_if_fail(IS_SERVER(server)); + + nicklist_update_flags(server, server->nick, server->usermode_away, -1); +} + +void irc_nicklist_init(void) +{ + signal_add("event nick", (SIGNAL_FUNC) event_nick); + signal_add_first("event 352", (SIGNAL_FUNC) event_who); + signal_add("silent event who", (SIGNAL_FUNC) event_who); + signal_add("silent event whois", (SIGNAL_FUNC) event_whois); + signal_add_first("event 311", (SIGNAL_FUNC) event_whois); + signal_add_first("event 301", (SIGNAL_FUNC) event_whois_away); + signal_add_first("event 313", (SIGNAL_FUNC) event_whois_ircop); + signal_add("event 318", (SIGNAL_FUNC) event_end_of_whois); + signal_add("event 353", (SIGNAL_FUNC) event_names_list); + signal_add("event 366", (SIGNAL_FUNC) event_end_of_names); + signal_add("event 433", (SIGNAL_FUNC) event_nick_in_use); + signal_add("event 437", (SIGNAL_FUNC) event_target_unavailable); + signal_add("event 302", (SIGNAL_FUNC) event_userhost); + signal_add("userhost event", (SIGNAL_FUNC) event_userhost); + signal_add("user mode changed", (SIGNAL_FUNC) sig_usermode); +} + +void irc_nicklist_deinit(void) +{ + signal_remove("event nick", (SIGNAL_FUNC) event_nick); + signal_remove("event 352", (SIGNAL_FUNC) event_who); + signal_remove("silent event who", (SIGNAL_FUNC) event_who); + signal_remove("silent event whois", (SIGNAL_FUNC) event_whois); + signal_remove("event 311", (SIGNAL_FUNC) event_whois); + signal_remove("event 301", (SIGNAL_FUNC) event_whois_away); + signal_remove("event 313", (SIGNAL_FUNC) event_whois_ircop); + signal_remove("event 318", (SIGNAL_FUNC) event_end_of_whois); + signal_remove("event 353", (SIGNAL_FUNC) event_names_list); + signal_remove("event 366", (SIGNAL_FUNC) event_end_of_names); + signal_remove("event 433", (SIGNAL_FUNC) event_nick_in_use); + signal_remove("event 437", (SIGNAL_FUNC) event_target_unavailable); + signal_remove("event 302", (SIGNAL_FUNC) event_userhost); + signal_remove("userhost event", (SIGNAL_FUNC) event_userhost); + signal_remove("user mode changed", (SIGNAL_FUNC) sig_usermode); +} diff --git a/src/irc/core/irc-nicklist.h b/src/irc/core/irc-nicklist.h new file mode 100644 index 00000000..d5cf78d3 --- /dev/null +++ b/src/irc/core/irc-nicklist.h @@ -0,0 +1,15 @@ +#ifndef __IRC_NICKLIST_H +#define __IRC_NICKLIST_H + +#include "nicklist.h" + +void irc_nicklist_init(void); +void irc_nicklist_deinit(void); + +/* Remove all "extra" characters from `nick'. Like _nick_ -> nick */ +char *irc_nick_strip(const char *nick); + +/* Check is `msg' is meant for `nick'. */ +int irc_nick_match(const char *nick, const char *msg); + +#endif diff --git a/src/irc/core/irc-queries.c b/src/irc/core/irc-queries.c new file mode 100644 index 00000000..b013d9cf --- /dev/null +++ b/src/irc/core/irc-queries.c @@ -0,0 +1,109 @@ +/* + irc-queries.c : 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 "misc.h" + +#include "irc.h" +#include "irc-queries.h" + +QUERY_REC *irc_query_create(IRC_SERVER_REC *server, + const char *nick, int automatic) +{ + QUERY_REC *rec; + + g_return_val_if_fail(server == NULL || IS_IRC_SERVER(server), NULL); + g_return_val_if_fail(nick != NULL, NULL); + + rec = g_new0(QUERY_REC, 1); + rec->chat_type = module_get_uniq_id("IRC QUERY", 0); + rec->name = g_strdup(nick); + rec->server = (SERVER_REC *) server; + query_init(rec, automatic); + return rec; +} + +static void sig_connected(SERVER_REC *server) +{ + if (!IS_IRC_SERVER(server)) + return; + + server->query_type = module_get_uniq_id("IRC QUERY", 0);; +} + +static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr) +{ + char *params, *target, *msg; + QUERY_REC *query; + + g_return_if_fail(data != NULL); + + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + + if (addr != NULL && !ischannel(*target)) { + /* save nick's address to query */ + query = irc_query_find(server, nick); + if (query != NULL && (query->address == NULL || strcmp(query->address, addr) != 0)) { + g_free_not_null(query->address); + query->address = g_strdup(addr); + + signal_emit("query address changed", 1, query); + } + } + + g_free(params); +} + +static void event_nick(const char *data, IRC_SERVER_REC *server, const char *orignick) +{ + char *params, *nick; + GSList *tmp; + + params = event_get_params(data, 1, &nick); + + for (tmp = server->queries; tmp != NULL; tmp = tmp->next) { + QUERY_REC *rec = tmp->data; + + if (g_strcasecmp(rec->name, orignick) == 0) { + g_free(rec->name); + rec->name = g_strdup(nick); + signal_emit("query nick changed", 1, rec); + } + } + + g_free(params); +} + +void irc_queries_init(void) +{ + signal_add("server connected", (SIGNAL_FUNC) sig_connected); + signal_add_last("event privmsg", (SIGNAL_FUNC) event_privmsg); + signal_add("event nick", (SIGNAL_FUNC) event_nick); +} + +void irc_queries_deinit(void) +{ + signal_remove("server connected", (SIGNAL_FUNC) sig_connected); + signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg); + signal_remove("event nick", (SIGNAL_FUNC) event_nick); + + module_uniq_destroy("IRC QUERY"); +} diff --git a/src/irc/core/irc-queries.h b/src/irc/core/irc-queries.h new file mode 100644 index 00000000..5c2725ac --- /dev/null +++ b/src/irc/core/irc-queries.h @@ -0,0 +1,25 @@ +#ifndef __IRC_QUERIES_H +#define __IRC_QUERIES_H + +#include "queries.h" +#include "irc-servers.h" + +#define IS_IRC_QUERY(query) \ + ((query) != NULL && \ + module_find_id("IRC QUERY", \ + ((QUERY_REC *) (query))->chat_type) != -1) + +/* Returns IRC_QUERY_REC if it's IRC query, NULL if it isn't. */ +#define IRC_QUERY(query) \ + (IS_IRC_QUERY(query) ? (QUERY_REC *) (query) : NULL) + +void irc_queries_init(void); +void irc_queries_deinit(void); + +#define irc_query_find(server, name) \ + query_find(SERVER(server), name) + +QUERY_REC *irc_query_create(IRC_SERVER_REC *server, + const char *nick, int automatic); + +#endif diff --git a/src/irc/core/irc-rawlog.c b/src/irc/core/irc-rawlog.c index 962564ec..a76fcf45 100644 --- a/src/irc/core/irc-rawlog.c +++ b/src/irc/core/irc-rawlog.c @@ -20,12 +20,11 @@ #include "module.h" #include "rawlog.h" -#include "modules.h" #include "signals.h" #include "misc.h" #include "commands.h" -#include "server.h" +#include "servers.h" #include "settings.h" diff --git a/src/irc/core/irc-server.c b/src/irc/core/irc-server.c deleted file mode 100644 index 6c8efd98..00000000 --- a/src/irc/core/irc-server.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - irc-server.c : 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 "net-nonblock.h" -#include "net-sendbuffer.h" -#include "line-split.h" -#include "signals.h" -#include "modules.h" -#include "rawlog.h" -#include "misc.h" - -#include "irc-server.h" -#include "server-idle.h" -#include "server-reconnect.h" -#include "server-setup.h" -#include "ircnet-setup.h" -#include "channels.h" -#include "modes.h" -#include "irc.h" -#include "query.h" - -#include "settings.h" - -#define DEFAULT_MAX_KICKS 1 -#define DEFAULT_MAX_MODES 3 -#define DEFAULT_MAX_WHOIS 4 -#define DEFAULT_MAX_MSGS 1 - -#define DEFAULT_USER_MODE "+i" -#define DEFAULT_CMD_QUEUE_SPEED 2200 -#define DEFAULT_CMDS_MAX_AT_ONCE 5 - -static int cmd_tag; - -void irc_server_connect_free(IRC_SERVER_CONNECT_REC *rec) -{ - g_return_if_fail(rec != NULL); - - g_free_not_null(rec->proxy); - g_free_not_null(rec->proxy_string); - g_free_not_null(rec->ircnet); - g_free_not_null(rec->password); - g_free_not_null(rec->nick); - g_free_not_null(rec->alternate_nick); - g_free_not_null(rec->username); - g_free_not_null(rec->realname); - g_free_not_null(rec->own_ip); - g_free_not_null(rec->channels); - g_free_not_null(rec->away_reason); - g_free_not_null(rec->usermode); - g_free_not_null(rec->address); - g_free(rec); -} - -static void server_init(IRC_SERVER_REC *server) -{ - IRC_SERVER_CONNECT_REC *conn; - char hostname[100], *address, *ptr; - - g_return_if_fail(server != NULL); - - conn = server->connrec; - - if (conn->proxy_string != NULL) - irc_send_cmdv(server, conn->proxy_string, conn->address, conn->port); - - if (conn->password != NULL && *conn->password != '\0') { - /* send password */ - server->cmdcount = 0; - irc_send_cmdv(server, "PASS %s", conn->password); - } - - /* send nick */ - server->cmdcount = 0; - irc_send_cmdv(server, "NICK %s", conn->nick); - - /* send user/realname */ - server->cmdcount = 0; - - if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0') - strcpy(hostname, "xx"); - - address = server->connrec->address; - ptr = strrchr(address, ':'); - if (ptr != NULL) { - /* IPv6 address .. doesn't work here, use the string after - the last : char */ - address = ptr+1; - } - irc_send_cmdv(server, "USER %s %s %s :%s", conn->username, hostname, - address, conn->realname); - - server->cmdcount = 0; -} - -IRC_SERVER_REC *irc_server_connect(IRC_SERVER_CONNECT_REC *conn) -{ - IRC_SERVER_REC *server; - - g_return_val_if_fail(conn != NULL, NULL); - if (conn->address == NULL || *conn->address == '\0') return NULL; - if (conn->nick == NULL || *conn->nick == '\0') return NULL; - - server = g_new0(IRC_SERVER_REC, 1); - server->type = module_get_uniq_id("IRC SERVER", SERVER_TYPE_IRC); - - server->connrec = conn; - if (conn->port <= 0) conn->port = 6667; - if (conn->username == NULL || *conn->username == '\0') { - g_free_not_null(conn->username); - - conn->username = g_get_user_name(); - if (*conn->username == '\0') conn->username = "-"; - conn->username = g_strdup(conn->username); - } - if (conn->realname == NULL || *conn->realname == '\0') { - g_free_not_null(conn->realname); - - conn->realname = g_get_real_name(); - if (*conn->realname == '\0') conn->realname = "-"; - conn->realname = g_strdup(conn->realname); - } - - server->nick = g_strdup(conn->nick); - - server->cmd_queue_speed = conn->cmd_queue_speed > 0 ? - conn->cmd_queue_speed : settings_get_int("cmd_queue_speed"); - server->max_cmds_at_once = conn->max_cmds_at_once > 0 ? - conn->max_cmds_at_once : settings_get_int("cmds_max_at_once"); - - server->max_kicks_in_cmd = conn->max_kicks > 0 ? - conn->max_kicks : DEFAULT_MAX_KICKS; - server->max_modes_in_cmd = conn->max_modes > 0 ? - conn->max_modes : DEFAULT_MAX_MODES; - server->max_whois_in_cmd = conn->max_whois > 0 ? - conn->max_whois : DEFAULT_MAX_WHOIS; - server->max_msgs_in_cmd = conn->max_msgs > 0 ? - conn->max_msgs : DEFAULT_MAX_MSGS; - - if (!server_connect((SERVER_REC *) server)) { - irc_server_connect_free(conn); - g_free(server->nick); - g_free(server); - return NULL; - } - return server; -} - -static void sig_connected(IRC_SERVER_REC *server) -{ - if (!irc_server_check(server)) - return; - - server->eventtable = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); - server->eventgrouptable = g_hash_table_new((GHashFunc) g_direct_hash, (GCompareFunc) g_direct_equal); - server->cmdtable = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); - server->splits = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); - - server_init(server); -} - -static int server_remove_channels(IRC_SERVER_REC *server) -{ - GSList *tmp; - int found; - - g_return_val_if_fail(server != NULL, FALSE); - - found = FALSE; - for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { - CHANNEL_REC *channel = tmp->data; - - channel->server = NULL; - channel_destroy(channel); - found = TRUE; - } - - for (tmp = server->queries; tmp != NULL; tmp = tmp->next) - query_change_server(tmp->data, NULL); - - g_slist_free(server->channels); - g_slist_free(server->queries); - - return found; -} - -static void sig_disconnected(IRC_SERVER_REC *server) -{ - int chans; - - if (!irc_server_check(server)) - return; - - /* close all channels */ - chans = server_remove_channels(server); - - g_slist_foreach(server->cmdqueue, (GFunc) g_free, NULL); - g_slist_free(server->cmdqueue); - - if (server->handle != NULL) { - if (!chans || server->connection_lost) - net_sendbuffer_destroy(server->handle, TRUE); - else { - /* we were on some channels, try to let the server - disconnect so that our quit message is guaranteed - to get displayed */ - net_disconnect_later(net_sendbuffer_handle(server->handle)); - net_sendbuffer_destroy(server->handle, FALSE); - } - server->handle = NULL; - } - - irc_server_connect_free(server->connrec); - g_free_not_null(server->real_address); - g_free_not_null(server->usermode); - g_free_not_null(server->userhost); - g_free_not_null(server->last_invite); -} - -static void sig_connect_failed(IRC_SERVER_REC *server) -{ - if (!irc_server_check(server)) - return; - - server_remove_channels(server); - irc_server_connect_free(server->connrec); -} - -static void server_cmd_timeout(IRC_SERVER_REC *server, GTimeVal *now) -{ - long usecs; - char *cmd; - int len, add_rawlog; - - if (!irc_server_check(server)) - return; - - if (server->cmdcount == 0 && server->cmdqueue == NULL) - return; - - if (!server->cmd_last_split) { - usecs = get_timeval_diff(now, &server->last_cmd); - if (usecs < server->cmd_queue_speed) - return; - } - - server->cmdcount--; - if (server->cmdqueue == NULL) return; - - /* send command */ - cmd = server->cmdqueue->data; - len = strlen(cmd); - - add_rawlog = !server->cmd_last_split; - - if (net_sendbuffer_send(server->handle, cmd, len) == -1) { - /* something bad happened */ - g_warning("net_sendbuffer_send() failed: %s", g_strerror(errno)); - return; - } - - memcpy(&server->last_cmd, now, sizeof(GTimeVal)); - if (server->cmd_last_split) - server->cmd_last_split = FALSE; - - if (add_rawlog) { - /* add to rawlog without CR+LF */ - int slen; - - slen = strlen(cmd); - cmd[slen-2] = '\0'; - rawlog_output(server->rawlog, cmd); - cmd[slen-2] = '\r'; - } - - /* remove from queue */ - g_free(cmd); - server->cmdqueue = g_slist_remove(server->cmdqueue, cmd); -} - -/* check every now and then if there's data to be sent in command buffer */ -static int servers_cmd_timeout(void) -{ - GTimeVal now; - - g_get_current_time(&now); - g_slist_foreach(servers, (GFunc) server_cmd_timeout, &now); - return 1; -} - -/* Return a string of all channels (and keys, if any have them) in server, - like "#a,#b,#c,#d x,b_chan_key,x,x" or just "#e,#f,#g" */ -char *irc_server_get_channels(IRC_SERVER_REC *server) -{ - GSList *tmp; - GString *chans, *keys; - char *ret; - int use_keys; - - g_return_val_if_fail(server != NULL, FALSE); - - chans = g_string_new(NULL); - keys = g_string_new(NULL); - - use_keys = FALSE; - for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { - CHANNEL_REC *channel = tmp->data; - - g_string_sprintfa(chans, "%s,", channel->name); - g_string_sprintfa(keys, "%s,", channel->key == NULL ? "x" : channel->key); - if (channel->key != NULL) - use_keys = TRUE; - } - - if (chans->len > 0) { - g_string_truncate(chans, chans->len-1); - g_string_truncate(keys, keys->len-1); - if (use_keys) g_string_sprintfa(chans, " %s", keys->str); - } - - ret = chans->str; - g_string_free(chans, FALSE); - g_string_free(keys, TRUE); - - return ret; -} - -static int sig_set_user_mode(IRC_SERVER_REC *server) -{ - const char *mode; - char *newmode; - - if (g_slist_find(servers, server) == NULL) - return 0; /* got disconnected */ - - mode = settings_get_str("usermode"); - newmode = server->usermode == NULL ? NULL : - modes_join(server->usermode, mode); - if (server->usermode == NULL || strcmp(newmode, server->usermode) != 0) - irc_send_cmdv(server, "MODE %s %s", server->nick, mode); - g_free_not_null(newmode); - return 0; -} - -static void event_connected(const char *data, IRC_SERVER_REC *server, const char *from) -{ - char *params, *nick; - const char *mode; - - g_return_if_fail(server != NULL); - - params = event_get_params(data, 1, &nick); - - if (strcmp(server->nick, nick) != 0) { - /* nick changed unexpectedly .. connected via proxy, etc. */ - g_free(server->nick); - server->nick = g_strdup(nick); - } - - if (server->real_address == NULL) { - /* set the server address */ - server->real_address = from == NULL ? - g_strdup(server->connrec->address) : /* shouldn't happen.. */ - g_strdup(from); - } - - /* last welcome message found - commands can be sent to server now. */ - server->connected = 1; - server->real_connect_time = time(NULL); - - if (!server->connrec->reconnection) { - /* wait a second and then send the user mode */ - mode = settings_get_str("usermode"); - if (*mode != '\0') - g_timeout_add(1000, (GSourceFunc) sig_set_user_mode, server); - } - - signal_emit("event connected", 1, server); - g_free(params); -} - -static void event_server_info(const char *data, IRC_SERVER_REC *server) -{ - char *params, *ircd_version, *usermodes, *chanmodes; - - g_return_if_fail(server != NULL); - - params = event_get_params(data, 5, NULL, NULL, &ircd_version, &usermodes, &chanmodes); - - /* check if server understands I and e channel modes */ - if (strchr(chanmodes, 'I') && strchr(chanmodes, 'e')) - server->emode_known = TRUE; - - /* save server version */ - g_free_not_null(server->version); - server->version = g_strdup(ircd_version); - - g_free(params); -} - -static void event_server_banned(const char *data, IRC_SERVER_REC *server) -{ - g_return_if_fail(server != NULL); - - server->banned = TRUE; -} - -static void event_error(const char *data, IRC_SERVER_REC *server) -{ - g_return_if_fail(server != NULL); - - if (!server->connected && (stristr(data, "Unauthorized") != NULL || - stristr(data, "K-lined") != NULL)) - server->banned = TRUE; -} - -static void event_ping(const char *data, IRC_SERVER_REC *server) -{ - char *str; - - g_return_if_fail(data != NULL); - - str = g_strdup_printf("PONG %s", data); - irc_send_cmd_now(server, str); - g_free(str); -} - -static void event_empty(void) -{ -} - -void irc_servers_init(void) -{ - settings_add_str("misc", "usermode", DEFAULT_USER_MODE); - settings_add_int("flood", "cmd_queue_speed", DEFAULT_CMD_QUEUE_SPEED); - settings_add_int("flood", "cmds_max_at_once", DEFAULT_CMDS_MAX_AT_ONCE); - - cmd_tag = g_timeout_add(500, (GSourceFunc) servers_cmd_timeout, NULL); - - signal_add_first("server connected", (SIGNAL_FUNC) sig_connected); - signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected); - signal_add_last("server connect failed", (SIGNAL_FUNC) sig_connect_failed); - signal_add("event 001", (SIGNAL_FUNC) event_connected); - signal_add("event 004", (SIGNAL_FUNC) event_server_info); - signal_add("event 465", (SIGNAL_FUNC) event_server_banned); - signal_add("event error", (SIGNAL_FUNC) event_error); - signal_add("event ping", (SIGNAL_FUNC) event_ping); - signal_add("event empty", (SIGNAL_FUNC) event_empty); - - servers_setup_init(); - ircnets_setup_init(); - servers_idle_init(); - servers_reconnect_init(); -} - -void irc_servers_deinit(void) -{ - while (servers != NULL) - server_disconnect(servers->data); - while (lookup_servers != NULL) - server_disconnect(lookup_servers->data); - - g_source_remove(cmd_tag); - - signal_remove("server connected", (SIGNAL_FUNC) sig_connected); - signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected); - signal_remove("server connect failed", (SIGNAL_FUNC) sig_connect_failed); - signal_remove("event 001", (SIGNAL_FUNC) event_connected); - signal_remove("event 004", (SIGNAL_FUNC) event_server_info); - signal_remove("event 465", (SIGNAL_FUNC) event_server_banned); - signal_remove("event error", (SIGNAL_FUNC) event_error); - signal_remove("event ping", (SIGNAL_FUNC) event_ping); - signal_remove("event empty", (SIGNAL_FUNC) event_empty); - - servers_setup_deinit(); - ircnets_setup_deinit(); - servers_idle_deinit(); - servers_reconnect_deinit(); - - module_uniq_destroy("IRC SERVER"); -} diff --git a/src/irc/core/irc-server.h b/src/irc/core/irc-server.h deleted file mode 100644 index bc51839f..00000000 --- a/src/irc/core/irc-server.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef __IRC_SERVER_H -#define __IRC_SERVER_H - -#include "server.h" - -enum { - SERVER_TYPE_IRC -}; - -/* return if `server' doesn't point to IRC server record. */ -#define irc_server_check(server) \ - ((server) != NULL && module_find_id("IRC SERVER", (server)->type) != -1) - -/* all strings should be either NULL or dynamically allocated */ -/* address and nick are mandatory, rest are optional */ -typedef struct { - /* -- GENERIC SERVER_CONNECT_REC - don't change! -- */ - /* if we're connecting via proxy, or just NULLs */ - char *proxy; - int proxy_port; - char *proxy_string; - - /* server where we want to connect */ - char *address; - int port; - char *ircnet; - - IPADDR *own_ip; - - char *password; - char *nick; - char *username; - char *realname; - - /* when reconnecting, the old server status */ - int reconnection:1; /* we're trying to reconnect */ - char *channels; - char *away_reason; - char *usermode; - - /* -- IRC specific - change if you wish -- */ - char *alternate_nick; - - int max_cmds_at_once; - int cmd_queue_speed; - int max_kicks, max_msgs, max_modes, max_whois; -} IRC_SERVER_CONNECT_REC; - -typedef struct { - /* -- GENERIC SERVER_REC - don't change! -- */ - int type; /* server type */ - - IRC_SERVER_CONNECT_REC *connrec; - time_t connect_time; /* connection time */ - time_t real_connect_time; /* time when server replied that we really are connected */ - - char *tag; /* tag name for addressing server */ - char *nick; /* current nick */ - - int connected:1; /* connected to server */ - int connection_lost:1; /* Connection lost unintentionally */ - - void *handle; /* NET_SENDBUF_REC socket */ - int readtag; /* input tag */ - - /* for net_connect_nonblock() */ - int connect_pipe[2]; - int connect_tag; - int connect_pid; - - /* For deciding if event should be handled internally */ - GHashTable *eventtable; /* "event xxx" : GSList* of REDIRECT_RECs */ - GHashTable *eventgrouptable; /* event group : GSList* of REDIRECT_RECs */ - GHashTable *cmdtable; /* "command xxx" : REDIRECT_CMD_REC* */ - - void *rawlog; - void *buffer; /* receive buffer */ - GHashTable *module_data; - - char *version; /* server version - taken from 004 event */ - char *away_reason; - int usermode_away:1; - int banned:1; /* not allowed to connect to this server */ - - /* -- IRC specific - change if you wish -- */ - char *real_address; /* address the irc server gives */ - char *usermode; /* The whole mode string .. */ - char *userhost; /* /USERHOST - set when joined to first channel */ - char *last_invite; /* channel where you were last invited */ - int server_operator:1; - - int whois_coming:1; /* Mostly just to display away message right.. */ - int whois_found:1; /* Did WHOIS return any entries? */ - int whowas_found:1; /* Did WHOWAS return any entries? */ - - int emode_known:1; /* Server understands ban exceptions and invite lists */ - int no_multi_mode:1; /* Server doesn't understand MODE #chan1,#chan2,... */ - int no_multi_who:1; /* Server doesn't understand WHO #chan1,#chan2,... */ - int one_endofwho:1; /* /WHO #a,#b,.. replies only with one End of WHO message */ - - int max_kicks_in_cmd; /* max. number of people to kick with one /KICK command */ - int max_modes_in_cmd; /* max. number of mode changes in one /MODE command */ - int max_whois_in_cmd; /* max. number of nicks in one /WHOIS command */ - int max_msgs_in_cmd; /* max. number of targets in one /MSG */ - - /* Command sending queue */ - int cmdcount; /* number of commands in `cmdqueue'. Can be more than - there actually is, to make flood control remember - how many messages can be sent before starting the - flood control */ - int cmd_last_split; /* Last command wasn't sent entirely to server. - First item in `cmdqueue' should be re-sent. */ - GSList *cmdqueue; - GTimeVal last_cmd; /* last time command was sent to server */ - - int max_cmds_at_once; /* How many messages can be sent immediately before timeouting starts */ - int cmd_queue_speed; /* Timeout between sending commands */ - - GSList *idles; /* Idle queue - send these commands to server - if there's nothing else to do */ - - GSList *ctcpqueue; /* CTCP flood protection - list of tags in idle queue */ - - /* /knockout ban list */ - GSList *knockoutlist; - time_t knockout_lastcheck; - - GHashTable *splits; /* For keeping track of netsplits */ - GSList *split_servers; /* Servers that are currently in split */ - - time_t lag_sent; /* 0 or time when last lag query was sent to server */ - time_t lag_last_check; /* last time we checked lag */ - int lag; /* server lag in milliseconds */ - - GSList *channels; - GSList *queries; - - GSList *rejoin_channels; /* try to join to these channels after a while - - channels go here if they're "temporarily unavailable" - because of netsplits */ - gpointer chanqueries; -} IRC_SERVER_REC; - -IRC_SERVER_REC *irc_server_connect(IRC_SERVER_CONNECT_REC *conn); - -/* Return a string of all channels (and keys, if any have them) in server, - like "#a,#b,#c,#d x,b_chan_key,x,x" or just "#e,#f,#g" */ -char *irc_server_get_channels(IRC_SERVER_REC *server); - -/* INTERNAL: Free memory used by connection record */ -void irc_server_connect_free(IRC_SERVER_CONNECT_REC *rec); - -void irc_servers_init(void); -void irc_servers_deinit(void); - -#endif diff --git a/src/irc/core/irc-servers-reconnect.c b/src/irc/core/irc-servers-reconnect.c new file mode 100644 index 00000000..4ba1d51a --- /dev/null +++ b/src/irc/core/irc-servers-reconnect.c @@ -0,0 +1,118 @@ +/* + servers-reconnect.c : 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 "commands.h" +#include "network.h" +#include "signals.h" + +#include "irc.h" +#include "modes.h" +#include "irc-servers.h" + +#include "settings.h" + +static void sig_server_connect_copy(SERVER_CONNECT_REC **dest, + IRC_SERVER_CONNECT_REC *src) +{ + IRC_SERVER_CONNECT_REC *rec; + + g_return_if_fail(dest != NULL); + if (!IS_IRC_SERVER_CONNECT(src)) + return; + + rec = g_new0(IRC_SERVER_CONNECT_REC, 1); + rec->chat_type = module_get_uniq_id("IRC SERVER CONNECT", 0); + rec->cmd_queue_speed = src->cmd_queue_speed; + rec->max_kicks = src->max_kicks; + rec->max_modes = src->max_modes; + rec->max_msgs = src->max_msgs; + rec->usermode = g_strdup(src->usermode); + *dest = (SERVER_CONNECT_REC *) rec; +} + +static void sig_server_reconnect_save_status(IRC_SERVER_CONNECT_REC *conn, + IRC_SERVER_REC *server) +{ + if (!IS_IRC_SERVER_CONNECT(conn)) + return; + g_return_if_fail(IS_IRC_SERVER(server)); + + g_free_not_null(conn->channels); + conn->channels = irc_server_get_channels(server); + + g_free_not_null(conn->usermode); + conn->usermode = g_strdup(server->usermode); +} + +static int sig_set_user_mode(IRC_SERVER_REC *server) +{ + const char *mode; + char *newmode; + + if (g_slist_find(servers, server) == NULL) + return 0; /* got disconnected */ + + mode = server->connrec->usermode; + if (mode == NULL) return 0; + + newmode = server->usermode == NULL ? NULL : + modes_join(server->usermode, mode); + + if (server->usermode == NULL) { + /* server didn't set user mode, just set the new one */ + irc_send_cmdv(server, "MODE %s %s", server->nick, mode); + } else { + if (strcmp(newmode, server->usermode) != 0) + irc_send_cmdv(server, "MODE %s -%s+%s", server->nick, server->usermode, mode); + } + + g_free_not_null(newmode); + return 0; +} + +static void sig_connected(IRC_SERVER_REC *server) +{ + if (!server->connrec->reconnection) + return; + + if (server->connrec->channels != NULL) + irc_channels_join(server, server->connrec->channels, TRUE); + if (server->connrec->away_reason != NULL) + signal_emit("command away", 2, server->connrec->away_reason, server, NULL); + if (server->connrec->usermode != NULL) { + /* wait a second and then send the user mode */ + g_timeout_add(1000, (GSourceFunc) sig_set_user_mode, server); + } +} + +void irc_servers_reconnect_init(void) +{ + signal_add("server connect copy", (SIGNAL_FUNC) sig_server_connect_copy); + signal_add("server reconnect save status", (SIGNAL_FUNC) sig_server_reconnect_save_status); + signal_add("event connected", (SIGNAL_FUNC) sig_connected); +} + +void irc_servers_reconnect_deinit(void) +{ + signal_remove("server connect copy", (SIGNAL_FUNC) sig_server_connect_copy); + signal_remove("server reconnect save status", (SIGNAL_FUNC) sig_server_reconnect_save_status); + signal_remove("event connected", (SIGNAL_FUNC) sig_connected); +} diff --git a/src/irc/core/irc-servers-setup.c b/src/irc/core/irc-servers-setup.c new file mode 100644 index 00000000..7ccf29e3 --- /dev/null +++ b/src/irc/core/irc-servers-setup.c @@ -0,0 +1,196 @@ +/* + servers-setup.c : 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 "network.h" +#include "servers-setup.h" +#include "lib-config/iconfig.h" +#include "settings.h" + +#include "irc-chatnets.h" +#include "irc-servers-setup.h" +#include "irc-servers.h" + +/* Fill information to connection from server setup record */ +static void sig_server_setup_fill_reconn(IRC_SERVER_CONNECT_REC *conn, + IRC_SERVER_SETUP_REC *sserver) +{ + if (!IS_IRC_SERVER_CONNECT(conn) || + !IS_IRC_SERVER_SETUP(sserver)) + return; + + if (sserver->cmd_queue_speed > 0) + conn->cmd_queue_speed = sserver->cmd_queue_speed; + if (sserver->max_cmds_at_once > 0) + conn->max_cmds_at_once = sserver->max_cmds_at_once; +} + +/* Create server connection record. `address' is required, rest can be NULL */ +static void sig_server_create_conn(SERVER_CONNECT_REC **conn, + IRC_CHATNET_REC *ircnet) +{ + IRC_SERVER_CONNECT_REC *rec; + + g_return_if_fail(conn != NULL); + + if (ircnet != NULL && !IS_IRCNET(ircnet)) + return; + + rec = g_new0(IRC_SERVER_CONNECT_REC, 1); + rec->chat_type = module_get_uniq_id("IRC SERVER CONNECT", 0); + rec->alternate_nick = g_strdup(settings_get_str("alternate_nick")); + + *conn = (SERVER_CONNECT_REC *) rec; + signal_stop(); +} + +static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn, + IRC_CHATNET_REC *ircnet) +{ + if (!IS_IRC_SERVER_CONNECT(conn)) + return; + g_return_if_fail(IS_IRCNET(ircnet)); + + if (ircnet->nick) g_free_and_null(conn->alternate_nick); + + if (ircnet->max_kicks > 0) conn->max_kicks = ircnet->max_kicks; + if (ircnet->max_msgs > 0) conn->max_msgs = ircnet->max_msgs; + if (ircnet->max_modes > 0) conn->max_modes = ircnet->max_modes; + if (ircnet->max_whois > 0) conn->max_whois = ircnet->max_whois; + + if (ircnet->max_cmds_at_once > 0) + conn->max_cmds_at_once = ircnet->max_cmds_at_once; + if (ircnet->cmd_queue_speed > 0) + conn->cmd_queue_speed = ircnet->cmd_queue_speed; +} + +static void init_userinfo(void) +{ + const char *set, *default_nick, *user_name; + char *str; + + /* check if nick/username/realname wasn't read from setup.. */ + set = settings_get_str("real_name"); + if (set == NULL || *set == '\0') { + str = g_getenv("IRCNAME"); + iconfig_set_str("settings", "real_name", + str != NULL ? str : g_get_real_name()); + } + + /* username */ + user_name = settings_get_str("user_name"); + if (user_name == NULL || *user_name == '\0') { + str = g_getenv("IRCUSER"); + iconfig_set_str("settings", "user_name", + str != NULL ? str : g_get_user_name()); + + user_name = settings_get_str("user_name"); + } + + /* nick */ + default_nick = settings_get_str("default_nick"); + if (default_nick == NULL || *default_nick == '\0') { + str = g_getenv("IRCNICK"); + iconfig_set_str("settings", "default_nick", + str != NULL ? str : user_name); + + default_nick = settings_get_str("default_nick"); + } + + /* alternate nick */ + set = settings_get_str("alternate_nick"); + if (set == NULL || *set == '\0') { + if (strlen(default_nick) < 9) + str = g_strconcat(default_nick, "_", NULL); + else { + str = g_strdup(default_nick); + str[strlen(str)-1] = '_'; + } + iconfig_set_str("settings", "alternate_nick", str); + g_free(str); + } + + /* host name */ + set = settings_get_str("hostname"); + if (set == NULL || *set == '\0') { + str = g_getenv("IRCHOST"); + if (str != NULL) + iconfig_set_str("settings", "hostname", str); + } +} + +static void sig_server_setup_read(SERVER_SETUP_REC **setuprec, + CONFIG_NODE *node, + IRC_CHATNET_REC *chatnet) +{ + IRC_SERVER_SETUP_REC *rec; + + g_return_if_fail(setuprec != NULL); + g_return_if_fail(node != NULL); + + if (chatnet != NULL && !IS_IRCNET(chatnet)) + return; + + rec = g_new0(IRC_SERVER_SETUP_REC, 1); + rec->chat_type = module_get_uniq_id("IRC SERVER SETUP", 0); + + rec->max_cmds_at_once = config_node_get_int(node, "cmds_max_at_once", 0); + rec->cmd_queue_speed = config_node_get_int(node, "cmd_queue_speed", 0); + + *setuprec = (SERVER_SETUP_REC *) rec; + signal_stop(); +} + +static void sig_server_setup_saved(IRC_SERVER_SETUP_REC *rec, + CONFIG_NODE *node) +{ + if (!IS_IRC_SERVER_SETUP(rec)) + return; + + if (rec->max_cmds_at_once > 0) + config_node_set_int(node, "cmds_max_at_once", rec->max_cmds_at_once); + if (rec->cmd_queue_speed > 0) + config_node_set_int(node, "cmd_queue_speed", rec->cmd_queue_speed); +} + +void irc_servers_setup_init(void) +{ + settings_add_bool("server", "skip_motd", FALSE); + settings_add_str("server", "alternate_nick", NULL); + + init_userinfo(); + signal_add("server setup fill reconn", (SIGNAL_FUNC) sig_server_setup_fill_reconn); + signal_add("server setup connect", (SIGNAL_FUNC) sig_server_create_conn); + signal_add("server setup fill chatnet", (SIGNAL_FUNC) sig_server_setup_fill_chatnet); + signal_add("server setup read", (SIGNAL_FUNC) sig_server_setup_read); + signal_add("server setup saved", (SIGNAL_FUNC) sig_server_setup_saved); +} + +void irc_servers_setup_deinit(void) +{ + signal_remove("server setup fill reconn", (SIGNAL_FUNC) sig_server_setup_fill_reconn); + signal_remove("server setup connect", (SIGNAL_FUNC) sig_server_create_conn); + signal_remove("server setup fill chatnet", (SIGNAL_FUNC) sig_server_setup_fill_chatnet); + signal_remove("server setup read", (SIGNAL_FUNC) sig_server_setup_read); + signal_remove("server setup saved", (SIGNAL_FUNC) sig_server_setup_saved); + + module_uniq_destroy("IRC SERVER SETUP"); +} diff --git a/src/irc/core/irc-servers-setup.h b/src/irc/core/irc-servers-setup.h new file mode 100644 index 00000000..f29f55c0 --- /dev/null +++ b/src/irc/core/irc-servers-setup.h @@ -0,0 +1,21 @@ +#ifndef __IRC_SERVERS_SETUP_H +#define __IRC_SERVERS_SETUP_H + +#define IS_IRC_SERVER_SETUP(server) \ + ((server) != NULL && \ + module_find_id("IRC SERVER SETUP", (server)->chat_type) != -1) + +#define IRC_SERVER_SETUP(server) \ + (IS_IRC_SERVER_SETUP(server) ? \ + (IRC_SERVER_SETUP_REC *) (server) : NULL) + +typedef struct { +#include "server-setup-rec.h" + int max_cmds_at_once; /* override the default if > 0 */ + int cmd_queue_speed; /* override the default if > 0 */ +} IRC_SERVER_SETUP_REC; + +void irc_servers_setup_init(void); +void irc_servers_setup_deinit(void); + +#endif diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c new file mode 100644 index 00000000..aeb3070d --- /dev/null +++ b/src/irc/core/irc-servers.c @@ -0,0 +1,447 @@ +/* + irc-server.c : 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 "net-nonblock.h" +#include "net-sendbuffer.h" +#include "line-split.h" +#include "signals.h" +#include "rawlog.h" +#include "misc.h" + +#include "channels.h" +#include "queries.h" + +#include "irc.h" +#include "irc-chatnets.h" +#include "irc-servers-setup.h" +#include "irc-servers.h" +#include "server-idle.h" +#include "servers-reconnect.h" +#include "modes.h" + +#include "settings.h" + +#define DEFAULT_MAX_KICKS 1 +#define DEFAULT_MAX_MODES 3 +#define DEFAULT_MAX_WHOIS 4 +#define DEFAULT_MAX_MSGS 1 + +#define DEFAULT_USER_MODE "+i" +#define DEFAULT_CMD_QUEUE_SPEED 2200 +#define DEFAULT_CMDS_MAX_AT_ONCE 5 + +void irc_servers_reconnect_init(void); +void irc_servers_reconnect_deinit(void); + +static int cmd_tag; + +static void sig_server_connect_free(IRC_SERVER_CONNECT_REC *conn) +{ + if (!IS_IRC_SERVER_CONNECT(conn)) + return; + + g_free_not_null(conn->alternate_nick); +} + +static void server_init(IRC_SERVER_REC *server) +{ + IRC_SERVER_CONNECT_REC *conn; + char hostname[100], *address, *ptr; + + g_return_if_fail(server != NULL); + + conn = server->connrec; + + if (conn->proxy_string != NULL) + irc_send_cmdv(server, conn->proxy_string, conn->address, conn->port); + + if (conn->password != NULL && *conn->password != '\0') { + /* send password */ + server->cmdcount = 0; + irc_send_cmdv(server, "PASS %s", conn->password); + } + + /* send nick */ + server->cmdcount = 0; + irc_send_cmdv(server, "NICK %s", conn->nick); + + /* send user/realname */ + server->cmdcount = 0; + + if (gethostname(hostname, sizeof(hostname)) != 0 || *hostname == '\0') + strcpy(hostname, "xx"); + + address = server->connrec->address; + ptr = strrchr(address, ':'); + if (ptr != NULL) { + /* IPv6 address .. doesn't work here, use the string after + the last : char */ + address = ptr+1; + } + irc_send_cmdv(server, "USER %s %s %s :%s", conn->username, hostname, + address, conn->realname); + + server->cmdcount = 0; +} + +IRC_SERVER_REC *irc_server_connect(IRC_SERVER_CONNECT_REC *conn) +{ + IRC_SERVER_REC *server; + + g_return_val_if_fail(IS_IRC_SERVER_CONNECT(conn), NULL); + if (conn->address == NULL || *conn->address == '\0') return NULL; + if (conn->nick == NULL || *conn->nick == '\0') return NULL; + + server = g_new0(IRC_SERVER_REC, 1); + server->chat_type = module_get_uniq_id("IRC SERVER", 0); + + server->connrec = conn; + if (conn->port <= 0) conn->port = 6667; + if (conn->username == NULL || *conn->username == '\0') { + g_free_not_null(conn->username); + + conn->username = g_get_user_name(); + if (*conn->username == '\0') conn->username = "-"; + conn->username = g_strdup(conn->username); + } + if (conn->realname == NULL || *conn->realname == '\0') { + g_free_not_null(conn->realname); + + conn->realname = g_get_real_name(); + if (*conn->realname == '\0') conn->realname = "-"; + conn->realname = g_strdup(conn->realname); + } + + server->nick = g_strdup(conn->nick); + + server->cmd_queue_speed = conn->cmd_queue_speed > 0 ? + conn->cmd_queue_speed : settings_get_int("cmd_queue_speed"); + server->max_cmds_at_once = conn->max_cmds_at_once > 0 ? + conn->max_cmds_at_once : settings_get_int("cmds_max_at_once"); + + server->max_kicks_in_cmd = conn->max_kicks > 0 ? + conn->max_kicks : DEFAULT_MAX_KICKS; + server->max_modes_in_cmd = conn->max_modes > 0 ? + conn->max_modes : DEFAULT_MAX_MODES; + server->max_whois_in_cmd = conn->max_whois > 0 ? + conn->max_whois : DEFAULT_MAX_WHOIS; + server->max_msgs_in_cmd = conn->max_msgs > 0 ? + conn->max_msgs : DEFAULT_MAX_MSGS; + + if (!server_start_connect((SERVER_REC *) server)) { + server_connect_free(SERVER_CONNECT(conn)); + g_free(server->nick); + g_free(server); + return NULL; + } + return server; +} + +static void sig_server_connect(IRC_SERVER_REC **server, + IRC_SERVER_CONNECT_REC *conn) +{ + g_return_if_fail(server != NULL); + if (!IS_IRC_SERVER_CONNECT(conn)) + return; + + *server = irc_server_connect(conn); + signal_stop(); +} + +static void sig_connected(IRC_SERVER_REC *server) +{ + if (!IS_IRC_SERVER(server)) + return; + + server->splits = g_hash_table_new((GHashFunc) g_istr_hash, (GCompareFunc) g_istr_equal); + server_init(server); +} + +static void sig_disconnected(IRC_SERVER_REC *server) +{ + if (!IS_IRC_SERVER(server)) + return; + + g_slist_foreach(server->cmdqueue, (GFunc) g_free, NULL); + g_slist_free(server->cmdqueue); + + g_free_not_null(server->real_address); + g_free_not_null(server->usermode); + g_free_not_null(server->userhost); + g_free_not_null(server->last_invite); +} + +static void server_cmd_timeout(IRC_SERVER_REC *server, GTimeVal *now) +{ + long usecs; + char *cmd; + int len, add_rawlog; + + if (!IS_IRC_SERVER(server)) + return; + + if (server->cmdcount == 0 && server->cmdqueue == NULL) + return; + + if (!server->cmd_last_split) { + usecs = get_timeval_diff(now, &server->last_cmd); + if (usecs < server->cmd_queue_speed) + return; + } + + server->cmdcount--; + if (server->cmdqueue == NULL) return; + + /* send command */ + cmd = server->cmdqueue->data; + len = strlen(cmd); + + add_rawlog = !server->cmd_last_split; + + if (net_sendbuffer_send(server->handle, cmd, len) == -1) { + /* something bad happened */ + g_warning("net_sendbuffer_send() failed: %s", g_strerror(errno)); + return; + } + + memcpy(&server->last_cmd, now, sizeof(GTimeVal)); + if (server->cmd_last_split) + server->cmd_last_split = FALSE; + + if (add_rawlog) { + /* add to rawlog without CR+LF */ + int slen; + + slen = strlen(cmd); + cmd[slen-2] = '\0'; + rawlog_output(server->rawlog, cmd); + cmd[slen-2] = '\r'; + } + + /* remove from queue */ + g_free(cmd); + server->cmdqueue = g_slist_remove(server->cmdqueue, cmd); +} + +/* check every now and then if there's data to be sent in command buffer */ +static int servers_cmd_timeout(void) +{ + GTimeVal now; + + g_get_current_time(&now); + g_slist_foreach(servers, (GFunc) server_cmd_timeout, &now); + return 1; +} + +/* Return a string of all channels (and keys, if any have them) in server, + like "#a,#b,#c,#d x,b_chan_key,x,x" or just "#e,#f,#g" */ +char *irc_server_get_channels(IRC_SERVER_REC *server) +{ + GSList *tmp; + GString *chans, *keys; + char *ret; + int use_keys; + + g_return_val_if_fail(server != NULL, FALSE); + + chans = g_string_new(NULL); + keys = g_string_new(NULL); + + use_keys = FALSE; + for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { + CHANNEL_REC *channel = tmp->data; + + g_string_sprintfa(chans, "%s,", channel->name); + g_string_sprintfa(keys, "%s,", channel->key == NULL ? "x" : channel->key); + if (channel->key != NULL) + use_keys = TRUE; + } + + if (chans->len > 0) { + g_string_truncate(chans, chans->len-1); + g_string_truncate(keys, keys->len-1); + if (use_keys) g_string_sprintfa(chans, " %s", keys->str); + } + + ret = chans->str; + g_string_free(chans, FALSE); + g_string_free(keys, TRUE); + + return ret; +} + +static int sig_set_user_mode(IRC_SERVER_REC *server) +{ + const char *mode; + char *newmode; + + if (g_slist_find(servers, server) == NULL) + return 0; /* got disconnected */ + + mode = settings_get_str("usermode"); + newmode = server->usermode == NULL ? NULL : + modes_join(server->usermode, mode); + if (server->usermode == NULL || strcmp(newmode, server->usermode) != 0) + irc_send_cmdv(server, "MODE %s %s", server->nick, mode); + g_free_not_null(newmode); + return 0; +} + +static void event_connected(const char *data, IRC_SERVER_REC *server, const char *from) +{ + char *params, *nick; + const char *mode; + + g_return_if_fail(server != NULL); + + params = event_get_params(data, 1, &nick); + + if (strcmp(server->nick, nick) != 0) { + /* nick changed unexpectedly .. connected via proxy, etc. */ + g_free(server->nick); + server->nick = g_strdup(nick); + } + + if (server->real_address == NULL) { + /* set the server address */ + server->real_address = from == NULL ? + g_strdup(server->connrec->address) : /* shouldn't happen.. */ + g_strdup(from); + } + + /* last welcome message found - commands can be sent to server now. */ + server->connected = 1; + server->real_connect_time = time(NULL); + + if (!server->connrec->reconnection) { + /* wait a second and then send the user mode */ + mode = settings_get_str("usermode"); + if (*mode != '\0') + g_timeout_add(1000, (GSourceFunc) sig_set_user_mode, server); + } + + signal_emit("event connected", 1, server); + g_free(params); +} + +static void event_server_info(const char *data, IRC_SERVER_REC *server) +{ + char *params, *ircd_version, *usermodes, *chanmodes; + + g_return_if_fail(server != NULL); + + params = event_get_params(data, 5, NULL, NULL, &ircd_version, &usermodes, &chanmodes); + + /* check if server understands I and e channel modes */ + if (strchr(chanmodes, 'I') && strchr(chanmodes, 'e')) + server->emode_known = TRUE; + + /* save server version */ + g_free_not_null(server->version); + server->version = g_strdup(ircd_version); + + g_free(params); +} + +static void event_server_banned(const char *data, IRC_SERVER_REC *server) +{ + g_return_if_fail(server != NULL); + + server->banned = TRUE; +} + +static void event_error(const char *data, IRC_SERVER_REC *server) +{ + g_return_if_fail(server != NULL); + + if (!server->connected && (stristr(data, "Unauthorized") != NULL || + stristr(data, "K-lined") != NULL)) + server->banned = TRUE; +} + +static void event_ping(const char *data, IRC_SERVER_REC *server) +{ + char *str; + + g_return_if_fail(data != NULL); + + str = g_strdup_printf("PONG %s", data); + irc_send_cmd_now(server, str); + g_free(str); +} + +static void event_empty(void) +{ +} + +void irc_servers_init(void) +{ + settings_add_str("misc", "usermode", DEFAULT_USER_MODE); + settings_add_int("flood", "cmd_queue_speed", DEFAULT_CMD_QUEUE_SPEED); + settings_add_int("flood", "cmds_max_at_once", DEFAULT_CMDS_MAX_AT_ONCE); + + cmd_tag = g_timeout_add(500, (GSourceFunc) servers_cmd_timeout, NULL); + + signal_add("server connect free", (SIGNAL_FUNC) sig_server_connect_free); + signal_add("server connect", (SIGNAL_FUNC) sig_server_connect); + signal_add_first("server connected", (SIGNAL_FUNC) sig_connected); + signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected); + signal_add("event 001", (SIGNAL_FUNC) event_connected); + signal_add("event 004", (SIGNAL_FUNC) event_server_info); + signal_add("event 465", (SIGNAL_FUNC) event_server_banned); + signal_add("event error", (SIGNAL_FUNC) event_error); + signal_add("event ping", (SIGNAL_FUNC) event_ping); + signal_add("event empty", (SIGNAL_FUNC) event_empty); + + irc_servers_setup_init(); + irc_chatnets_init(); + irc_servers_reconnect_init(); + servers_idle_init(); +} + +void irc_servers_deinit(void) +{ + while (servers != NULL) + server_disconnect(servers->data); + while (lookup_servers != NULL) + server_disconnect(lookup_servers->data); + + g_source_remove(cmd_tag); + + signal_remove("server connect free", (SIGNAL_FUNC) sig_server_connect_free); + signal_remove("server connect", (SIGNAL_FUNC) sig_server_connect); + signal_remove("server connected", (SIGNAL_FUNC) sig_connected); + signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected); + signal_remove("event 001", (SIGNAL_FUNC) event_connected); + signal_remove("event 004", (SIGNAL_FUNC) event_server_info); + signal_remove("event 465", (SIGNAL_FUNC) event_server_banned); + signal_remove("event error", (SIGNAL_FUNC) event_error); + signal_remove("event ping", (SIGNAL_FUNC) event_ping); + signal_remove("event empty", (SIGNAL_FUNC) event_empty); + + irc_servers_setup_deinit(); + irc_chatnets_deinit(); + irc_servers_reconnect_deinit(); + servers_idle_deinit(); + + module_uniq_destroy("IRC SERVER"); +} diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h new file mode 100644 index 00000000..9199a698 --- /dev/null +++ b/src/irc/core/irc-servers.h @@ -0,0 +1,101 @@ +#ifndef __IRC_SERVERS_H +#define __IRC_SERVERS_H + +#include "servers.h" + +#define IS_IRC_SERVER(server) \ + ((server) != NULL && \ + module_find_id("IRC SERVER", (server)->chat_type) != -1) + +#define IS_IRC_SERVER_CONNECT(conn) \ + ((conn) != NULL && \ + module_find_id("IRC SERVER CONNECT", (conn)->chat_type) != -1) + +/* returns IRC_SERVER_REC if it's IRC server, NULL if it isn't */ +#define IRC_SERVER(server) \ + (IS_IRC_SERVER(server) ? (IRC_SERVER_REC *) (server) : NULL) + +#define IRC_SERVER_CONNECT(conn) \ + (IS_IRC_SERVER_CONNECT(conn) ? \ + (IRC_SERVER_CONNECT_REC *) (conn) : NULL) + +/* all strings should be either NULL or dynamically allocated */ +/* address and nick are mandatory, rest are optional */ +typedef struct { +#include "server-connect-rec.h" + + char *alternate_nick; + + int max_cmds_at_once; + int cmd_queue_speed; + int max_kicks, max_msgs, max_modes, max_whois; +} IRC_SERVER_CONNECT_REC; + +#define STRUCT_SERVER_CONNECT_REC IRC_SERVER_CONNECT_REC +typedef struct { +#include "server-rec.h" + + char *real_address; /* address the irc server gives */ + char *usermode; /* The whole mode string .. */ + char *userhost; /* /USERHOST - set when joined to first channel */ + char *last_invite; /* channel where you were last invited */ + + int whois_coming:1; /* Mostly just to display away message right.. */ + int whois_found:1; /* Did WHOIS return any entries? */ + int whowas_found:1; /* Did WHOWAS return any entries? */ + + int emode_known:1; /* Server understands ban exceptions and invite lists */ + int no_multi_mode:1; /* Server doesn't understand MODE #chan1,#chan2,... */ + int no_multi_who:1; /* Server doesn't understand WHO #chan1,#chan2,... */ + int one_endofwho:1; /* /WHO #a,#b,.. replies only with one End of WHO message */ + + int max_kicks_in_cmd; /* max. number of people to kick with one /KICK command */ + int max_modes_in_cmd; /* max. number of mode changes in one /MODE command */ + int max_whois_in_cmd; /* max. number of nicks in one /WHOIS command */ + int max_msgs_in_cmd; /* max. number of targets in one /MSG */ + + /* Command sending queue */ + int cmdcount; /* number of commands in `cmdqueue'. Can be more than + there actually is, to make flood control remember + how many messages can be sent before starting the + flood control */ + int cmd_last_split; /* Last command wasn't sent entirely to server. + First item in `cmdqueue' should be re-sent. */ + GSList *cmdqueue; + GTimeVal last_cmd; /* last time command was sent to server */ + + int max_cmds_at_once; /* How many messages can be sent immediately before timeouting starts */ + int cmd_queue_speed; /* Timeout between sending commands */ + + GSList *idles; /* Idle queue - send these commands to server + if there's nothing else to do */ + + GSList *ctcpqueue; /* CTCP flood protection - list of tags in idle queue */ + + /* /knockout ban list */ + GSList *knockoutlist; + time_t knockout_lastcheck; + + GHashTable *splits; /* For keeping track of netsplits */ + GSList *split_servers; /* Servers that are currently in split */ + + time_t lag_sent; /* 0 or time when last lag query was sent to server */ + time_t lag_last_check; /* last time we checked lag */ + int lag; /* server lag in milliseconds */ + + GSList *rejoin_channels; /* try to join to these channels after a while - + channels go here if they're "temporarily unavailable" + because of netsplits */ + void *chanqueries; +} IRC_SERVER_REC; + +IRC_SERVER_REC *irc_server_connect(IRC_SERVER_CONNECT_REC *conn); + +/* Return a string of all channels (and keys, if any have them) in server, + like "#a,#b,#c,#d x,b_chan_key,x,x" or just "#e,#f,#g" */ +char *irc_server_get_channels(IRC_SERVER_REC *server); + +void irc_servers_init(void); +void irc_servers_deinit(void); + +#endif diff --git a/src/irc/core/irc-special-vars.c b/src/irc/core/irc-special-vars.c index 03335114..0943db36 100644 --- a/src/irc/core/irc-special-vars.c +++ b/src/irc/core/irc-special-vars.c @@ -22,65 +22,49 @@ #include "misc.h" #include "special-vars.h" #include "settings.h" +#include "window-item-def.h" #include "irc.h" -#include "irc-server.h" +#include "irc-servers.h" #include "channels.h" -#include "query.h" +#include "queries.h" static char *last_privmsg_from; static char *last_sent_msg, *last_sent_msg_body; static char *last_join, *last_public_from; /* last person who sent you a MSG */ -static char *expando_lastmsg(void *server, void *item, int *free_ret) +static char *expando_lastmsg(SERVER_REC *server, void *item, int *free_ret) { return last_privmsg_from; } /* last person to whom you sent a MSG */ -static char *expando_lastmymsg(void *server, void *item, int *free_ret) +static char *expando_lastmymsg(SERVER_REC *server, void *item, int *free_ret) { return last_sent_msg; } /* last person to join a channel you are on */ -static char *expando_lastjoin(void *server, void *item, int *free_ret) +static char *expando_lastjoin(SERVER_REC *server, void *item, int *free_ret) { return last_join; } /* last person to send a public message to a channel you are on */ -static char *expando_lastpublic(void *server, void *item, int *free_ret) +static char *expando_lastpublic(SERVER_REC *server, void *item, int *free_ret) { return last_public_from; } -/* text of your AWAY message, if any */ -static char *expando_awaymsg(void *server, void *item, int *free_ret) -{ - IRC_SERVER_REC *ircserver = server; - - return ircserver == NULL ? "" : ircserver->away_reason; -} - /* body of last MSG you sent */ -static char *expando_lastmymsg_body(void *server, void *item, int *free_ret) +static char *expando_lastmymsg_body(SERVER_REC *server, void *item, int *free_ret) { return last_sent_msg_body; } -/* current channel */ -static char *expando_channel(void *server, void *item, int *free_ret) -{ - CHANNEL_REC *channel; - - channel = irc_item_channel(item); - return channel == NULL ? NULL : channel->name; -} - /* current server numeric being processed */ -static char *expando_server_numeric(void *server, void *item, int *free_ret) +static char *expando_server_numeric(SERVER_REC *server, void *item, int *free_ret) { return current_server_event == NULL || !is_numeric(current_server_event, 0) ? NULL : @@ -88,90 +72,30 @@ static char *expando_server_numeric(void *server, void *item, int *free_ret) } /* channel you were last INVITEd to */ -static char *expando_last_invite(void *server, void *item, int *free_ret) +static char *expando_last_invite(SERVER_REC *server, void *item, int *free_ret) { - IRC_SERVER_REC *ircserver = server; + IRC_SERVER_REC *ircserver = IRC_SERVER(server); return ircserver == NULL ? "" : ircserver->last_invite; } -/* modes of current channel, if any */ -static char *expando_chanmode(void *server, void *item, int *free_ret) -{ - CHANNEL_REC *channel; - - channel = irc_item_channel(item); - return channel == NULL ? NULL : channel->mode; -} - -/* current nickname */ -static char *expando_nick(void *server, void *item, int *free_ret) -{ - IRC_SERVER_REC *ircserver = server; - - return ircserver == NULL ? "" : ircserver->nick; -} - -/* value of STATUS_OPER if you are an irc operator */ -static char *expando_statusoper(void *server, void *item, int *free_ret) -{ - IRC_SERVER_REC *ircserver = server; - - return ircserver == NULL || !ircserver->server_operator ? "" : - (char *) settings_get_str("STATUS_OPER"); -} - -/* if you are a channel operator in $C, expands to a '@' */ -static char *expando_chanop(void *server, void *item, int *free_ret) -{ - CHANNEL_REC *channel; - - channel = irc_item_channel(item); - if (channel == NULL) return NULL; - - return channel->chanop ? "@" : ""; -} - -/* nickname of whomever you are QUERYing */ -static char *expando_query(void *server, void *item, int *free_ret) -{ - QUERY_REC *query; - - query = irc_item_query(item); - return query == NULL ? NULL : query->nick; -} - -/* version of current server */ -static char *expando_serverversion(void *server, void *item, int *free_ret) -{ - IRC_SERVER_REC *ircserver = server; - - return ircserver == NULL ? "" : ircserver->version; -} - /* current server name */ -static char *expando_servername(void *server, void *item, int *free_ret) +static char *expando_servername(SERVER_REC *server, void *item, int *free_ret) { - IRC_SERVER_REC *ircserver = server; + IRC_SERVER_REC *ircserver = IRC_SERVER(server); return ircserver == NULL ? "" : ircserver->real_address; } -/* target of current input (channel or QUERY nickname) */ -static char *expando_target(void *server, void *item, int *free_ret) -{ - if (!irc_item_check(item)) - return NULL; - - return ((WI_IRC_REC *) item)->name; -} /* your /userhost $N address (user@host) */ -static char *expando_userhost(void *server, void *item, int *free_ret) +static char *expando_userhost(SERVER_REC *server, void *item, int *free_ret) { - IRC_SERVER_REC *ircserver = server; + IRC_SERVER_REC *ircserver; const char *username; char hostname[100]; + ircserver = IRC_SERVER(server); + /* prefer the _real_ /userhost reply */ if (ircserver != NULL && ircserver->userhost != NULL) return ircserver->userhost; @@ -188,31 +112,8 @@ static char *expando_userhost(void *server, void *item, int *free_ret) return g_strconcat(username, "@", hostname, NULL);; } -/* value of REALNAME */ -static char *expando_realname(void *server, void *item, int *free_ret) -{ - IRC_SERVER_REC *ircserver = server; - - return ircserver == NULL ? "" : ircserver->connrec->realname; -} - -/* Server tag */ -static char *expando_servertag(void *server, void *item, int *free_ret) -{ - IRC_SERVER_REC *ircserver = server; - - return ircserver == NULL ? "" : ircserver->tag; -} - -/* Server ircnet */ -static char *expando_ircnet(void *server, void *item, int *free_ret) -{ - IRC_SERVER_REC *ircserver = server; - - return ircserver == NULL ? "" : ircserver->connrec->ircnet; -} - -static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr) +static void event_privmsg(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *addr) { char *params, *target, *msg; @@ -238,9 +139,12 @@ static void cmd_msg(const char *data, IRC_SERVER_REC *server) g_return_if_fail(data != NULL); - if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, &target, &msg)) + if (!cmd_get_params(data, &free_arg, 2 | PARAM_FLAG_GETREST, + &target, &msg)) return; - if (*target != '\0' && *msg != '\0' && !ischannel(*target) && isalpha(*target)) { + + if (*target != '\0' && *msg != '\0' && + !ischannel(*target) && isalpha(*target)) { g_free_not_null(last_sent_msg); g_free_not_null(last_sent_msg_body); last_sent_msg = g_strdup(target); @@ -250,7 +154,8 @@ static void cmd_msg(const char *data, IRC_SERVER_REC *server) cmd_params_free(free_arg); } -static void event_join(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address) +static void event_join(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *address) { g_return_if_fail(nick != NULL); @@ -262,8 +167,6 @@ static void event_join(const char *data, IRC_SERVER_REC *server, const char *nic void irc_special_vars_init(void) { - settings_add_str("misc", "STATUS_OPER", "*"); - last_privmsg_from = NULL; last_sent_msg = NULL; last_sent_msg_body = NULL; last_join = NULL; last_public_from = NULL; @@ -272,23 +175,11 @@ void irc_special_vars_init(void) expando_create(".", expando_lastmymsg); expando_create(":", expando_lastjoin); expando_create(";", expando_lastpublic); - expando_create("A", expando_awaymsg); expando_create("B", expando_lastmymsg_body); - expando_create("C", expando_channel); expando_create("H", expando_server_numeric); expando_create("I", expando_last_invite); - expando_create("M", expando_chanmode); - expando_create("N", expando_nick); - expando_create("O", expando_statusoper); - expando_create("P", expando_chanop); - expando_create("Q", expando_query); - expando_create("R", expando_serverversion); expando_create("S", expando_servername); - expando_create("T", expando_target); expando_create("X", expando_userhost); - expando_create("Y", expando_realname); - expando_create("tag", expando_servertag); - expando_create("ircnet", expando_ircnet); signal_add("event privmsg", (SIGNAL_FUNC) event_privmsg); signal_add("event join", (SIGNAL_FUNC) event_join); @@ -305,23 +196,11 @@ void irc_special_vars_deinit(void) expando_destroy(".", expando_lastmymsg); expando_destroy(":", expando_lastjoin); expando_destroy(";", expando_lastpublic); - expando_destroy("A", expando_awaymsg); expando_destroy("B", expando_lastmymsg_body); - expando_destroy("C", expando_channel); expando_destroy("H", expando_server_numeric); expando_destroy("I", expando_last_invite); - expando_destroy("M", expando_chanmode); - expando_destroy("N", expando_nick); - expando_destroy("O", expando_statusoper); - expando_destroy("P", expando_chanop); - expando_destroy("Q", expando_query); - expando_destroy("R", expando_serverversion); expando_destroy("S", expando_servername); - expando_destroy("T", expando_target); expando_destroy("X", expando_userhost); - expando_destroy("Y", expando_realname); - expando_destroy("tag", expando_servertag); - expando_destroy("ircnet", expando_ircnet); signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg); signal_remove("event join", (SIGNAL_FUNC) event_join); diff --git a/src/irc/core/irc.c b/src/irc/core/irc.c index 681510e4..1b366850 100644 --- a/src/irc/core/irc.c +++ b/src/irc/core/irc.c @@ -26,9 +26,9 @@ #include "rawlog.h" #include "irc.h" -#include "irc-server.h" -#include "channels.h" -#include "server-redirect.h" +#include "irc-servers.h" +#include "irc-channels.h" +#include "servers-redirect.h" char *current_server_event; static int signal_send_command; @@ -355,31 +355,29 @@ static void irc_init_server(IRC_SERVER_REC *server) static char *irc_cmd_get_func(const char *data, int *count, va_list *vargs) { - WI_IRC_REC *item; - CHANNEL_REC *channel; + IRC_CHANNEL_REC *channel; char *ret, *args, *chan, *p; if ((*count & PARAM_FLAG_OPTCHAN) == 0) return g_strdup(data); *count &= ~PARAM_FLAG_OPTCHAN; - item = (WI_IRC_REC *) va_arg(*vargs, WI_IRC_REC *); - channel = irc_item_channel(item); + channel = (void *) va_arg(*vargs, void *); + channel = IRC_CHANNEL(channel); /* change first argument in data to full channel name. */ p = args = g_strdup(data); chan = isoptchan(args) ? cmd_get_param(&args) : NULL; - if (chan != NULL && *chan == '!') { + if (chan != NULL && *chan == '!' && channel != NULL) { /* whenever trying to send something to !channel, change it to the real joined !XXXXXchannel */ - channel = channel_find(channel->server, chan); + channel = irc_channel_find(channel->server, chan); if (channel != NULL) chan = channel->name; } - if (chan == NULL || strcmp(chan, "*") == 0) { + if (chan == NULL || strcmp(chan, "*") == 0) chan = channel == NULL ? "*" : channel->name; - } ret = g_strconcat(chan, " ", args, NULL); g_free(p); diff --git a/src/irc/core/irc.h b/src/irc/core/irc.h index baa692df..12065cb1 100644 --- a/src/irc/core/irc.h +++ b/src/irc/core/irc.h @@ -1,8 +1,7 @@ #ifndef __IRC_H #define __IRC_H -#include "modules.h" -#include "irc-server.h" +#include "irc-servers.h" /* From ircd 2.9.5: none I line with ident @@ -26,46 +25,7 @@ (a) == '!' || /* secure */ \ (a) == '+') /* modeless */ -/* values returned by module_category() */ -enum { - WI_IRC_CHANNEL, - WI_IRC_QUERY -}; - -/* *MUST* have the same contents as WI_ITEM_REC in same order. */ -typedef struct { - int type; - GHashTable *module_data; - - IRC_SERVER_REC *server; - char *name; - - int new_data; - int last_color; -} WI_IRC_REC; - -/* return TRUE if `item' is an IRC type. */ -#define irc_item_check(item) \ - (item != NULL && module_find_id("IRC", ((WI_IRC_REC *) (item))->type) != -1) - -/* return `item' type, or -1 if it's not IRC type. */ -#define irc_item_get(item) \ - (item == NULL ? -1 : module_find_id("IRC", ((WI_IRC_REC *) (item))->type)) - -/* Return `item' if it's channel, NULL if it isn't. */ -#define irc_item_channel(item) \ - (item != NULL && module_find_id("IRC", ((WI_IRC_REC *) (item))->type) == WI_IRC_CHANNEL ? \ - (void *) (item) : NULL) - -/* Return `item' if it's query, NULL if it isn't. */ -#define irc_item_query(item) \ - (item != NULL && module_find_id("IRC", ((WI_IRC_REC *) (item))->type) == WI_IRC_QUERY ? \ - (void *) (item) : NULL) - -/* Return `item' if it's DCC chat, NULL if it isn't. */ -#define irc_item_dcc_chat(item) \ - (item != NULL && module_find_id("IRC", ((WI_IRC_REC *) (item))->type) == WI_IRC_DCC_CHAT ? \ - (void *) (item) : NULL) +#define IS_IRC_ITEM(rec) (IS_IRC_CHANNEL(rec) || IS_IRC_QUERY(rec)) extern char *current_server_event; /* current server event being processed */ diff --git a/src/irc/core/ircnet-setup.c b/src/irc/core/ircnet-setup.c deleted file mode 100644 index 2c5eeb82..00000000 --- a/src/irc/core/ircnet-setup.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - ircnet-setup.c : 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 "network.h" -#include "signals.h" -#include "lib-config/iconfig.h" -#include "settings.h" - -#include "irc-server.h" -#include "ircnet-setup.h" -#include "special-vars.h" - -GSList *ircnets; /* list of available ircnets */ - -static void ircnet_config_add(IRCNET_REC *ircnet) -{ - CONFIG_NODE *node; - - node = iconfig_node_traverse("ircnets", TRUE); - iconfig_node_set_str(node, ircnet->name, NULL); - node = config_node_section(node, ircnet->name, NODE_TYPE_BLOCK); - - iconfig_node_set_str(node, "nick", ircnet->nick); - iconfig_node_set_str(node, "username", ircnet->username); - iconfig_node_set_str(node, "realname", ircnet->realname); - iconfig_node_set_str(node, "host", ircnet->own_host); - iconfig_node_set_str(node, "autosendcmd", ircnet->autosendcmd); - - if (ircnet->max_cmds_at_once > 0) - config_node_set_int(node, "cmdmax", ircnet->max_cmds_at_once); - if (ircnet->cmd_queue_speed > 0) - config_node_set_int(node, "cmdspeed", ircnet->cmd_queue_speed); - - if (ircnet->max_kicks > 0) - config_node_set_int(node, "max_kicks", ircnet->max_kicks); - if (ircnet->max_msgs > 0) - config_node_set_int(node, "max_msgs", ircnet->max_msgs); - if (ircnet->max_modes > 0) - config_node_set_int(node, "max_modes", ircnet->max_modes); - if (ircnet->max_whois > 0) - config_node_set_int(node, "max_whois", ircnet->max_whois); - -} - -static void ircnet_config_remove(IRCNET_REC *ircnet) -{ - CONFIG_NODE *node; - - node = iconfig_node_traverse("ircnets", FALSE); - if (node != NULL) iconfig_node_set_str(node, ircnet->name, NULL); -} - -void ircnet_create(IRCNET_REC *ircnet) -{ - if (g_slist_find(ircnets, ircnet) == NULL) - ircnets = g_slist_append(ircnets, ircnet); - - ircnet_config_add(ircnet); -} - -static void ircnet_destroy_rec(IRCNET_REC *ircnet) -{ - ircnets = g_slist_remove(ircnets, ircnet); - - g_free(ircnet->name); - g_free_not_null(ircnet->nick); - g_free_not_null(ircnet->username); - g_free_not_null(ircnet->realname); - g_free_not_null(ircnet->own_host); - g_free_not_null(ircnet->autosendcmd); - g_free(ircnet); -} - -void ircnet_destroy(IRCNET_REC *ircnet) -{ - ircnet_config_remove(ircnet); - ircnet_destroy_rec(ircnet); -} - -/* Find the irc network by name */ -IRCNET_REC *ircnet_find(const char *name) -{ - GSList *tmp; - - g_return_val_if_fail(name != NULL, NULL); - - for (tmp = ircnets; tmp != NULL; tmp = tmp->next) { - IRCNET_REC *rec = tmp->data; - - if (g_strcasecmp(rec->name, name) == 0) - return rec; - } - - return NULL; -} - -static IRCNET_REC *ircnet_add(CONFIG_NODE *node) -{ - IRCNET_REC *rec; - - g_return_val_if_fail(node != NULL, NULL); - if (node->key == NULL) return NULL; - - rec = g_new0(IRCNET_REC, 1); - - rec->name = g_strdup(node->key); - rec->nick = g_strdup(config_node_get_str(node, "nick", NULL)); - rec->username = g_strdup(config_node_get_str(node, "username", NULL)); - rec->realname = g_strdup(config_node_get_str(node, "realname", NULL)); - rec->own_host = g_strdup(config_node_get_str(node, "host", NULL)); - rec->autosendcmd = g_strdup(config_node_get_str(node, "autosendcmd", NULL)); - - rec->max_cmds_at_once = config_node_get_int(node, "cmdmax", 0); - rec->cmd_queue_speed = config_node_get_int(node, "cmdspeed", 0); - - rec->max_kicks = config_node_get_int(node, "max_kicks", 0); - rec->max_msgs = config_node_get_int(node, "max_msgs", 0); - rec->max_modes = config_node_get_int(node, "max_modes", 0); - rec->max_whois = config_node_get_int(node, "max_whois", 0); - - ircnets = g_slist_append(ircnets, rec); - return rec; -} - -static void read_ircnets(void) -{ - CONFIG_NODE *node; - GSList *tmp; - - while (ircnets != NULL) - ircnet_destroy_rec(ircnets->data); - - /* read ircnets */ - node = iconfig_node_traverse("ircnets", FALSE); - if (node != NULL) { - for (tmp = node->value; tmp != NULL; tmp = tmp->next) - ircnet_add(tmp->data); - } -} - -static void sig_connected(IRC_SERVER_REC *server) -{ - IRCNET_REC *ircnet; - - if (server->connrec->ircnet == NULL) return; - - ircnet = ircnet_find(server->connrec->ircnet); - if (ircnet != NULL && ircnet->autosendcmd) - eval_special_string(ircnet->autosendcmd, "", server, NULL); -} - -void ircnets_setup_init(void) -{ - read_ircnets(); - signal_add("setup reread", (SIGNAL_FUNC) read_ircnets); - signal_add("event connected", (SIGNAL_FUNC) sig_connected); -} - -void ircnets_setup_deinit(void) -{ - while (ircnets != NULL) - ircnet_destroy(ircnets->data); - - signal_remove("setup reread", (SIGNAL_FUNC) read_ircnets); - signal_remove("event connected", (SIGNAL_FUNC) sig_connected); -} diff --git a/src/irc/core/ircnet-setup.h b/src/irc/core/ircnet-setup.h deleted file mode 100644 index 8339cc07..00000000 --- a/src/irc/core/ircnet-setup.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __IRCNET_SETUP_H -#define __IRCNET_SETUP_H - -typedef struct { - char *name; - - char *nick; - char *username; - char *realname; - - char *own_host; /* address to use when connecting this server */ - char *autosendcmd; /* command to send after connecting to this ircnet */ - IPADDR *own_ip; /* resolved own_address if not NULL */ - - int max_cmds_at_once; - int cmd_queue_speed; - - /* max. number of kicks/msgs/mode/whois per command */ - int max_kicks, max_msgs, max_modes, max_whois; -} IRCNET_REC; - -extern GSList *ircnets; /* list of available ircnets */ - -void ircnet_create(IRCNET_REC *ircnet); -void ircnet_destroy(IRCNET_REC *ircnet); - -/* Find the irc network by name */ -IRCNET_REC *ircnet_find(const char *name); - -void ircnets_setup_init(void); -void ircnets_setup_deinit(void); - -#endif diff --git a/src/irc/core/lag.c b/src/irc/core/lag.c index 5b52fcce..3ab8b13b 100644 --- a/src/irc/core/lag.c +++ b/src/irc/core/lag.c @@ -24,7 +24,7 @@ #include "settings.h" #include "irc.h" -#include "irc-server.h" +#include "irc-servers.h" typedef struct { IRC_SERVER_REC *server; @@ -130,7 +130,7 @@ static int sig_check_lag(void) IRC_SERVER_REC *rec = tmp->data; next = tmp->next; - if (!irc_server_check(rec)) + if (!IS_IRC_SERVER(rec)) continue; if (rec->lag_sent != 0) { diff --git a/src/irc/core/masks.c b/src/irc/core/masks.c deleted file mode 100644 index 35364da2..00000000 --- a/src/irc/core/masks.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - masks.c : 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 "network.h" -#include "misc.h" - -#include "irc.h" -#include "masks.h" - -static int check_mask(const char *mask, int *wildcards) -{ - while (*mask != '\0') { - if (*mask == '!') - return TRUE; - - if (*mask == '?' || *mask == '*') - *wildcards = TRUE; - mask++; - } - - return FALSE; -} - -int irc_mask_match(const char *mask, const char *nick, - const char *user, const char *host) -{ - char *str; - int ret, wildcards; - - g_return_val_if_fail(mask != NULL, FALSE); - g_return_val_if_fail(nick != NULL, FALSE); - g_return_val_if_fail(user != NULL, FALSE); - g_return_val_if_fail(host != NULL, FALSE); - - if (!check_mask(mask, &wildcards)) { - return wildcards ? - match_wildcards(mask, nick) : - g_strcasecmp(mask, nick) == 0; - } - - str = g_strdup_printf("%s!%s@%s", nick, user, host); - ret = match_wildcards(mask, str); - g_free(str); - - return ret; -} - -int irc_mask_match_address(const char *mask, const char *nick, - const char *address) -{ - char *str; - int ret, wildcards; - - g_return_val_if_fail(mask != NULL, FALSE); - g_return_val_if_fail(nick != NULL, FALSE); - - if (!check_mask(mask, &wildcards)) { - return wildcards ? - match_wildcards(mask, nick) : - g_strcasecmp(mask, nick) == 0; - } - - str = g_strdup_printf("%s!%s", nick, address != NULL ? address : ""); - ret = match_wildcards(mask, str); - g_free(str); - - return ret; -} - -int irc_masks_match(const char *masks, const char *nick, const char *address) -{ - char **list, **tmp, *mask; - int found; - - g_return_val_if_fail(masks != NULL, FALSE); - - found = FALSE; - mask = g_strdup_printf("%s!%s", nick, address); - list = g_strsplit(masks, " ", -1); - for (tmp = list; *tmp != NULL; tmp++) { - if (strchr(*tmp, '!') == NULL && - g_strcasecmp(*tmp, nick) == 0) { - found = TRUE; - break; - } - - if (match_wildcards(*tmp, mask)) { - found = TRUE; - break; - } - } - g_strfreev(list); - g_free(mask); - - return found; -} - -static char *get_domain_mask(char *host) -{ - char *ptr; - - if (strchr(host, '.') == NULL) { - /* no dots - toplevel domain or IPv6 address */ - ptr = strrchr(host, ':'); - if (ptr != NULL) { - /* IPv6 address, ban the last 64k addresses */ - if (ptr[1] != '\0') strcpy(ptr+1, "*"); - } - - return host; - } - - if (is_ipv4_address(host)) { - /* it's an IP address, change last digit to * */ - ptr = strrchr(host, '.'); - if (ptr != NULL && isdigit(ptr[1])) - strcpy(ptr+1, "*"); - } else { - /* if more than one dot, skip the first - (dyn123.blah.net -> *.blah.net) */ - ptr = strchr(host, '.'); - if (ptr != NULL && strchr(ptr+1, '.') != NULL) { - host = ptr-1; - host[0] = '*'; - } - } - - return host; -} - -char *irc_get_mask(const char *nick, const char *address, int flags) -{ - char *ret, *user, *host; - - /* strip -, ^ or ~ from start.. */ - user = g_strconcat("*", ishostflag(*address) ? - address+1 : address, NULL); - - /* split user and host */ - host = strchr(user, '@'); - if (host == NULL) { - g_free(user); - return NULL; - } - *host++ = '\0'; - - switch (flags & (IRC_MASK_HOST|IRC_MASK_DOMAIN)) { - case IRC_MASK_HOST: - /* we already have the host */ - break; - case IRC_MASK_DOMAIN: - /* domain - *.blah.org */ - host = get_domain_mask(host); - break; - default: - /* no domain/host */ - host = "*"; - break; - } - - ret = g_strdup_printf("%s!%s@%s", - (flags & IRC_MASK_NICK) ? nick : "*", - (flags & IRC_MASK_USER) ? user : "*", - host); - g_free(user); - - return ret; -} diff --git a/src/irc/core/masks.h b/src/irc/core/masks.h deleted file mode 100644 index a735dd9d..00000000 --- a/src/irc/core/masks.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __MASKS_H -#define __MASKS_H - -#define IRC_MASK_NICK 0x01 -#define IRC_MASK_USER 0x02 -#define IRC_MASK_HOST 0x04 -#define IRC_MASK_DOMAIN 0x08 - -int irc_mask_match(const char *mask, const char *nick, const char *user, const char *host); -int irc_mask_match_address(const char *mask, const char *nick, const char *address); -int irc_masks_match(const char *masks, const char *nick, const char *address); - -char *irc_get_mask(const char *nick, const char *address, int flags); - -#endif diff --git a/src/irc/core/massjoin.c b/src/irc/core/massjoin.c index 553e5ed6..a1ffb0b1 100644 --- a/src/irc/core/massjoin.c +++ b/src/irc/core/massjoin.c @@ -22,10 +22,10 @@ #include "signals.h" #include "settings.h" -#include "channels.h" #include "irc.h" +#include "irc-servers.h" +#include "irc-channels.h" #include "nicklist.h" -#include "irc-server.h" static int massjoin_tag; static int massjoin_max_joins; @@ -33,10 +33,11 @@ static int massjoin_max_joins; /* Massjoin support - really useful when trying to do things (like op/deop) to people after netjoins. It sends "massjoin #channel nick!user@host nick2!user@host ..." signals */ -static void event_join(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address) +static void event_join(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *address) { char *params, *channel, *ptr; - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; NICK_REC *nickrec; GSList *nicks, *tmp; @@ -52,12 +53,12 @@ static void event_join(const char *data, IRC_SERVER_REC *server, const char *nic if (ptr != NULL) *ptr = '\0'; /* find channel */ - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); g_free(params); if (chanrec == NULL) return; /* add user to nicklist */ - nickrec = nicklist_insert(chanrec, nick, FALSE, FALSE, TRUE); + nickrec = nicklist_insert(CHANNEL(chanrec), nick, FALSE, FALSE, TRUE); nickrec->host = g_strdup(address); if (chanrec->massjoins == 0) { @@ -69,7 +70,7 @@ static void event_join(const char *data, IRC_SERVER_REC *server, const char *nic if (nickrec->realname == NULL) { /* Check if user is already in some other channel, get the realname and other stuff from there */ - nicks = nicklist_get_same(server, nick); + nicks = nicklist_get_same(SERVER(server), nick); for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) { NICK_REC *rec = tmp->next->data; @@ -86,10 +87,11 @@ static void event_join(const char *data, IRC_SERVER_REC *server, const char *nic chanrec->massjoins++; } -static void event_part(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr) +static void event_part(const char *data, IRC_SERVER_REC *server, + const char *nick, const char *addr) { char *params, *channel, *reason; - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; NICK_REC *nickrec; g_return_if_fail(data != NULL); @@ -102,28 +104,29 @@ static void event_part(const char *data, IRC_SERVER_REC *server, const char *nic params = event_get_params(data, 2, &channel, &reason); /* find channel */ - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec == NULL) { g_free(params); return; } /* remove user from nicklist */ - nickrec = nicklist_find(chanrec, nick); + nickrec = nicklist_find(CHANNEL(chanrec), nick); if (nickrec != NULL) { if (nickrec->send_massjoin) { /* quick join/part after which it's useless to send nick in massjoin */ chanrec->massjoins--; } - nicklist_remove(chanrec, nickrec); + nicklist_remove(CHANNEL(chanrec), nickrec); } g_free(params); } -static void event_quit(const char *data, IRC_SERVER_REC *server, const char *nick) +static void event_quit(const char *data, IRC_SERVER_REC *server, + const char *nick) { - CHANNEL_REC *channel; + IRC_CHANNEL_REC *channel; NICK_REC *nickrec; GSList *nicks, *tmp; @@ -135,7 +138,7 @@ static void event_quit(const char *data, IRC_SERVER_REC *server, const char *nic } /* Remove nick from all channels */ - nicks = nicklist_get_same(server, nick); + nicks = nicklist_get_same(SERVER(server), nick); for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) { channel = tmp->data; nickrec = tmp->next->data; @@ -145,7 +148,7 @@ static void event_quit(const char *data, IRC_SERVER_REC *server, const char *nic send nick in massjoin */ channel->massjoins--; } - nicklist_remove(channel, nickrec); + nicklist_remove(CHANNEL(channel), nickrec); } g_slist_free(nicks); } @@ -153,7 +156,7 @@ static void event_quit(const char *data, IRC_SERVER_REC *server, const char *nic static void event_kick(const char *data, IRC_SERVER_REC *server) { char *params, *channel, *nick, *reason; - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; NICK_REC *nickrec; g_return_if_fail(data != NULL); @@ -167,15 +170,17 @@ static void event_kick(const char *data, IRC_SERVER_REC *server) } /* Remove user from nicklist */ - chanrec = channel_find(server, channel); - nickrec = chanrec == NULL ? NULL : nicklist_find(chanrec, nick); + chanrec = irc_channel_find(server, channel); + nickrec = chanrec == NULL ? NULL : + nicklist_find(CHANNEL(chanrec), nick); + if (chanrec != NULL && nickrec != NULL) { if (nickrec->send_massjoin) { /* quick join/kick after which it's useless to send nick in massjoin */ chanrec->massjoins--; } - nicklist_remove(chanrec, nickrec); + nicklist_remove(CHANNEL(chanrec), nickrec); } g_free(params); @@ -190,7 +195,7 @@ static void massjoin_send_hash(gpointer key, NICK_REC *nick, GSList **list) } /* Send channel's massjoin list signal */ -static void massjoin_send(CHANNEL_REC *channel) +static void massjoin_send(IRC_CHANNEL_REC *channel) { GSList *list; @@ -208,9 +213,9 @@ static void server_check_massjoins(IRC_SERVER_REC *server, time_t max) /* Scan all channels through for massjoins */ for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { - CHANNEL_REC *rec = tmp->data; + IRC_CHANNEL_REC *rec = tmp->data; - if (rec->massjoins <= 0) + if (!IS_IRC_CHANNEL(rec) || rec->massjoins <= 0) continue; if (rec->massjoin_start < max || /* We've waited long enough */ @@ -234,7 +239,7 @@ static int sig_massjoin_timeout(void) for (tmp = servers; tmp != NULL; tmp = tmp->next) { IRC_SERVER_REC *server = tmp->data; - if (irc_server_check(server)) + if (IS_IRC_SERVER(server)) server_check_massjoins(server, max); } diff --git a/src/irc/core/mode-lists.c b/src/irc/core/mode-lists.c index 44df5189..5f9b5977 100644 --- a/src/irc/core/mode-lists.c +++ b/src/irc/core/mode-lists.c @@ -43,7 +43,7 @@ void banlist_free(GSList *banlist) ban_free(&banlist, banlist->data); } -BAN_REC *banlist_add(CHANNEL_REC *channel, const char *ban, +BAN_REC *banlist_add(IRC_CHANNEL_REC *channel, const char *ban, const char *nick, time_t time) { BAN_REC *rec; @@ -79,7 +79,7 @@ static BAN_REC *banlist_find(GSList *list, const char *ban) return NULL; } -void banlist_remove(CHANNEL_REC *channel, const char *ban) +void banlist_remove(IRC_CHANNEL_REC *channel, const char *ban) { BAN_REC *rec; @@ -93,7 +93,7 @@ void banlist_remove(CHANNEL_REC *channel, const char *ban) } } -BAN_REC *banlist_exception_add(CHANNEL_REC *channel, const char *ban, +BAN_REC *banlist_exception_add(IRC_CHANNEL_REC *channel, const char *ban, const char *nick, time_t time) { BAN_REC *rec; @@ -113,7 +113,7 @@ BAN_REC *banlist_exception_add(CHANNEL_REC *channel, const char *ban, return rec; } -void banlist_exception_remove(CHANNEL_REC *channel, const char *ban) +void banlist_exception_remove(IRC_CHANNEL_REC *channel, const char *ban) { BAN_REC *rec; @@ -127,7 +127,7 @@ void banlist_exception_remove(CHANNEL_REC *channel, const char *ban) } } -static void invitelist_free(CHANNEL_REC *channel) +static void invitelist_free(IRC_CHANNEL_REC *channel) { g_return_if_fail(channel != NULL); @@ -135,7 +135,7 @@ static void invitelist_free(CHANNEL_REC *channel) g_slist_free(channel->invitelist); } -void invitelist_add(CHANNEL_REC *channel, const char *mask) +void invitelist_add(IRC_CHANNEL_REC *channel, const char *mask) { g_return_if_fail(channel != NULL); g_return_if_fail(mask != NULL); @@ -145,7 +145,7 @@ void invitelist_add(CHANNEL_REC *channel, const char *mask) signal_emit("invitelist new", 2, channel, mask); } -void invitelist_remove(CHANNEL_REC *channel, const char *mask) +void invitelist_remove(IRC_CHANNEL_REC *channel, const char *mask) { GSList *tmp; @@ -160,7 +160,7 @@ void invitelist_remove(CHANNEL_REC *channel, const char *mask) channel->invitelist = g_slist_remove(channel->invitelist, tmp->data); } -static void channel_destroyed(CHANNEL_REC *channel) +static void channel_destroyed(IRC_CHANNEL_REC *channel) { g_return_if_fail(channel != NULL); @@ -171,14 +171,14 @@ static void channel_destroyed(CHANNEL_REC *channel) static void event_banlist(const char *data, IRC_SERVER_REC *server) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *params, *channel, *ban, *setby, *tims; time_t tim; g_return_if_fail(data != NULL); params = event_get_params(data, 5, NULL, &channel, &ban, &setby, &tims); - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec != NULL) { tim = (time_t) atol(tims); banlist_add(chanrec, ban, setby, tim); @@ -188,14 +188,14 @@ static void event_banlist(const char *data, IRC_SERVER_REC *server) static void event_ebanlist(const char *data, IRC_SERVER_REC *server) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *params, *channel, *ban, *setby, *tims; time_t tim; g_return_if_fail(data != NULL); params = event_get_params(data, 5, NULL, &channel, &ban, &setby, &tims); - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec != NULL) { tim = (time_t) atol(tims); banlist_exception_add(chanrec, ban, setby, tim); @@ -205,13 +205,13 @@ static void event_ebanlist(const char *data, IRC_SERVER_REC *server) static void event_invite_list(const char *data, IRC_SERVER_REC *server) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *params, *channel, *invite; g_return_if_fail(data != NULL); params = event_get_params(data, 3, NULL, &channel, &invite); - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec != NULL) invitelist_add(chanrec, invite); diff --git a/src/irc/core/mode-lists.h b/src/irc/core/mode-lists.h index 473ba5be..ef13ae3c 100644 --- a/src/irc/core/mode-lists.h +++ b/src/irc/core/mode-lists.h @@ -1,7 +1,7 @@ #ifndef __MODE_LISTS_H #define __MODE_LISTS_H -#include "channels.h" +#include "irc-channels.h" typedef struct { char *ban; @@ -9,14 +9,14 @@ typedef struct { time_t time; } BAN_REC; -BAN_REC *banlist_add(CHANNEL_REC *channel, const char *ban, const char *nick, time_t time); -void banlist_remove(CHANNEL_REC *channel, const char *ban); +BAN_REC *banlist_add(IRC_CHANNEL_REC *channel, const char *ban, const char *nick, time_t time); +void banlist_remove(IRC_CHANNEL_REC *channel, const char *ban); -BAN_REC *banlist_exception_add(CHANNEL_REC *channel, const char *ban, const char *nick, time_t time); -void banlist_exception_remove(CHANNEL_REC *channel, const char *ban); +BAN_REC *banlist_exception_add(IRC_CHANNEL_REC *channel, const char *ban, const char *nick, time_t time); +void banlist_exception_remove(IRC_CHANNEL_REC *channel, const char *ban); -void invitelist_add(CHANNEL_REC *channel, const char *mask); -void invitelist_remove(CHANNEL_REC *channel, const char *mask); +void invitelist_add(IRC_CHANNEL_REC *channel, const char *mask); +void invitelist_remove(IRC_CHANNEL_REC *channel, const char *mask); void mode_lists_init(void); void mode_lists_deinit(void); diff --git a/src/irc/core/modes.c b/src/irc/core/modes.c index ad4154b4..b33cf6b8 100644 --- a/src/irc/core/modes.c +++ b/src/irc/core/modes.c @@ -28,15 +28,15 @@ #include "nicklist.h" /* Change nick's mode in channel */ -static void nick_mode_change(CHANNEL_REC *channel, const char *nick, +static void nick_mode_change(IRC_CHANNEL_REC *channel, const char *nick, const char mode, int type) { NICK_REC *nickrec; - g_return_if_fail(channel != NULL); + g_return_if_fail(IS_IRC_CHANNEL(channel)); g_return_if_fail(nick != NULL); - nickrec = nicklist_find(channel, nick); + nickrec = nicklist_find(CHANNEL(channel), nick); if (nickrec == NULL) return; /* No /names list got yet */ if (mode == '@') nickrec->op = type == '+'; @@ -185,22 +185,22 @@ static void mode_set_arg(GString *str, char type, char mode, const char *arg) mode_add_sorted(str, mode, arg); } -int channel_mode_is_set(CHANNEL_REC *channel, char mode) +int channel_mode_is_set(IRC_CHANNEL_REC *channel, char mode) { - g_return_val_if_fail(channel != NULL, FALSE); + g_return_val_if_fail(IS_IRC_CHANNEL(channel), FALSE); return channel->mode == NULL ? FALSE : mode_is_set(channel->mode, mode); } /* Parse channel mode string */ -void parse_channel_modes(CHANNEL_REC *channel, const char *setby, +void parse_channel_modes(IRC_CHANNEL_REC *channel, const char *setby, const char *mode) { GString *newmode; char *dup, *modestr, *arg, *curmode, type; - g_return_if_fail(channel != NULL); + g_return_if_fail(IS_IRC_CHANNEL(channel)); g_return_if_fail(mode != NULL); type = '+'; @@ -336,7 +336,7 @@ static void parse_user_mode(IRC_SERVER_REC *server, const char *modestr) { char *newmode, *oldmode; - g_return_if_fail(server != NULL); + g_return_if_fail(IS_IRC_SERVER(server)); g_return_if_fail(modestr != NULL); newmode = modes_join(server->usermode, modestr); @@ -360,21 +360,23 @@ static void event_user_mode(const char *data, IRC_SERVER_REC *server) g_free(params); } -static void event_mode(const char *data, IRC_SERVER_REC *server, const char *nick) +static void event_mode(const char *data, IRC_SERVER_REC *server, + const char *nick) { - CHANNEL_REC *chanrec; + IRC_CHANNEL_REC *chanrec; char *params, *channel, *mode; g_return_if_fail(data != NULL); - params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &mode); + params = event_get_params(data, 2 | PARAM_FLAG_GETREST, + &channel, &mode); if (!ischannel(*channel)) { /* user mode change */ parse_user_mode(server, mode); } else { /* channel mode change */ - chanrec = channel_find(server, channel); + chanrec = irc_channel_find(server, channel); if (chanrec != NULL) parse_channel_modes(chanrec, nick, mode); } @@ -406,10 +408,8 @@ void channel_set_singlemode(IRC_SERVER_REC *server, const char *channel, int num, modepos; char **nick, **nicklist; - g_return_if_fail(server != NULL); - g_return_if_fail(channel != NULL); - g_return_if_fail(nicks != NULL); - g_return_if_fail(mode != NULL); + g_return_if_fail(IS_IRC_SERVER(server)); + g_return_if_fail(channel != NULL && nicks != NULL && mode != NULL); if (*nicks == '\0') return; num = modepos = 0; @@ -450,9 +450,8 @@ void channel_set_mode(IRC_SERVER_REC *server, const char *channel, GString *tmode, *targs; int count; - g_return_if_fail(server != NULL); - g_return_if_fail(channel != NULL); - g_return_if_fail(mode != NULL); + g_return_if_fail(IS_IRC_SERVER(server)); + g_return_if_fail(channel != NULL && mode != NULL); tmode = g_string_new(NULL); targs = g_string_new(NULL); @@ -468,7 +467,8 @@ void channel_set_mode(IRC_SERVER_REC *server, const char *channel, if (count == server->max_modes_in_cmd && HAS_MODE_ARG(type, *curmode)) { - irc_send_cmdv(server, "MODE %s %s%s", channel, tmode->str, targs->str); + irc_send_cmdv(server, "MODE %s %s%s", + channel, tmode->str, targs->str); count = 0; g_string_truncate(tmode, 0); @@ -486,21 +486,24 @@ void channel_set_mode(IRC_SERVER_REC *server, const char *channel, } } - if (tmode->len > 0) - irc_send_cmdv(server, "MODE %s %s%s", channel, tmode->str, targs->str); + if (tmode->len > 0) { + irc_send_cmdv(server, "MODE %s %s%s", + channel, tmode->str, targs->str); + } g_string_free(tmode, TRUE); g_string_free(targs, TRUE); g_free(orig); } -static char *get_nicks(WI_IRC_REC *item, const char *data, int op, int voice) +static char *get_nicks(IRC_CHANNEL_REC *channel, + const char *data, int op, int voice) { GString *str; GSList *nicks, *tmp; char **matches, **match, *ret; - g_return_val_if_fail(item != NULL, NULL); + g_return_val_if_fail(channel != NULL, NULL); g_return_val_if_fail(data != NULL, NULL); if (*data == '\0') return NULL; @@ -514,7 +517,7 @@ static char *get_nicks(WI_IRC_REC *item, const char *data, int op, int voice) } /* wildcards */ - nicks = nicklist_find_multiple((CHANNEL_REC *) item, data); + nicks = nicklist_find_multiple(CHANNEL(channel), data); for (tmp = nicks; tmp != NULL; tmp = tmp->next) { NICK_REC *rec = tmp->data; @@ -522,7 +525,7 @@ static char *get_nicks(WI_IRC_REC *item, const char *data, int op, int voice) (voice == 1 && !rec->voice) || (voice == 0 && rec->voice)) continue; - if (g_strcasecmp(rec->nick, item->server->nick) == 0) + if (g_strcasecmp(rec->nick, channel->server->nick) == 0) continue; g_string_sprintfa(str, "%s ", rec->nick); @@ -537,69 +540,74 @@ static char *get_nicks(WI_IRC_REC *item, const char *data, int op, int voice) } /* SYNTAX: OP */ -static void cmd_op(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_op(const char *data, IRC_SERVER_REC *server, + IRC_CHANNEL_REC *channel) { char *nicks; - if (!irc_item_channel(item)) + if (!IS_IRC_CHANNEL(channel)) return; - nicks = get_nicks(item, data, 0, -1); + nicks = get_nicks(channel, data, 0, -1); if (nicks != NULL && *nicks != '\0') - channel_set_singlemode(server, item->name, nicks, "+o"); + channel_set_singlemode(server, channel->name, nicks, "+o"); g_free_not_null(nicks); } /* SYNTAX: DEOP */ -static void cmd_deop(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_deop(const char *data, IRC_SERVER_REC *server, + IRC_CHANNEL_REC *channel) { char *nicks; - if (!irc_item_channel(item)) + if (!IS_IRC_CHANNEL(channel)) return; - nicks = get_nicks(item, data, 1, -1); + nicks = get_nicks(channel, data, 1, -1); if (nicks != NULL && *nicks != '\0') - channel_set_singlemode(server, item->name, nicks, "-o"); + channel_set_singlemode(server, channel->name, nicks, "-o"); g_free_not_null(nicks); } /* SYNTAX: VOICE */ -static void cmd_voice(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_voice(const char *data, IRC_SERVER_REC *server, + IRC_CHANNEL_REC *channel) { char *nicks; - if (!irc_item_channel(item)) + if (!IS_IRC_CHANNEL(channel)) return; - nicks = get_nicks(item, data, 0, 0); + nicks = get_nicks(channel, data, 0, 0); if (nicks != NULL && *nicks != '\0') - channel_set_singlemode(server, item->name, nicks, "+v"); + channel_set_singlemode(server, channel->name, nicks, "+v"); g_free_not_null(nicks); } /* SYNTAX: DEVOICE */ -static void cmd_devoice(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_devoice(const char *data, IRC_SERVER_REC *server, + IRC_CHANNEL_REC *channel) { char *nicks; - if (!irc_item_channel(item)) + if (!IS_IRC_CHANNEL(channel)) return; - nicks = get_nicks(item, data, 0, 1); + nicks = get_nicks(channel, data, 0, 1); if (nicks != NULL && *nicks != '\0') - channel_set_singlemode(server, item->name, nicks, "-v"); + channel_set_singlemode(server, channel->name, nicks, "-v"); g_free_not_null(nicks); } /* SYNTAX: MODE | [ []] */ -static void cmd_mode(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_mode(const char *data, IRC_SERVER_REC *server, + IRC_CHANNEL_REC *channel) { char *target, *mode; void *free_arg; g_return_if_fail(data != NULL); - if (server == NULL || !server->connected || !irc_server_check(server)) + if (server == NULL || !server->connected || !IS_IRC_SERVER(server)) cmd_return_error(CMDERR_NOT_CONNECTED); if (*data == '+' || *data == '-') { @@ -612,10 +620,10 @@ static void cmd_mode(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) } if (strcmp(target, "*") == 0) { - if (!irc_item_channel(item)) + if (!IS_IRC_CHANNEL(channel)) cmd_param_error(CMDERR_NOT_JOINED); - target = item->name; + target = channel->name; } if (*target == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); diff --git a/src/irc/core/modes.h b/src/irc/core/modes.h index d175c083..be318d94 100644 --- a/src/irc/core/modes.h +++ b/src/irc/core/modes.h @@ -1,8 +1,8 @@ #ifndef __MODES_H #define __MODES_H -#include "server.h" -#include "channels.h" +#include "irc-servers.h" +#include "irc-channels.h" /* modes that have argument always */ #define HAS_MODE_ARG_ALWAYS(mode) \ @@ -26,9 +26,9 @@ void modes_deinit(void); /* add `mode' to `old' - return newly allocated mode. */ char *modes_join(const char *old, const char *mode); -int channel_mode_is_set(CHANNEL_REC *channel, char mode); +int channel_mode_is_set(IRC_CHANNEL_REC *channel, char mode); -void parse_channel_modes(CHANNEL_REC *channel, const char *setby, +void parse_channel_modes(IRC_CHANNEL_REC *channel, const char *setby, const char *modestr); void channel_set_singlemode(IRC_SERVER_REC *server, const char *channel, diff --git a/src/irc/core/netsplit.c b/src/irc/core/netsplit.c index 78f1f02c..2831ec3a 100644 --- a/src/irc/core/netsplit.c +++ b/src/irc/core/netsplit.c @@ -19,12 +19,11 @@ */ #include "module.h" -#include "modules.h" #include "signals.h" #include "commands.h" #include "misc.h" -#include "irc-server.h" +#include "irc-servers.h" #include "netsplit.h" /* How long to keep netsplits in memory (seconds) */ @@ -284,7 +283,7 @@ static void sig_disconnected(IRC_SERVER_REC *server) { g_return_if_fail(server != NULL); - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server)) return; g_hash_table_foreach(server->splits, (GHFunc) netsplit_destroy_hash, server); @@ -308,7 +307,7 @@ static int split_check_old(void) for (tmp = servers; tmp != NULL; tmp = tmp->next) { IRC_SERVER_REC *server = tmp->data; - if (irc_server_check(server)) + if (IS_IRC_SERVER(server)) g_hash_table_foreach_remove(server->splits, (GHRFunc) split_server_check, server); } diff --git a/src/irc/core/nicklist.c b/src/irc/core/nicklist.c deleted file mode 100644 index 0143ca6d..00000000 --- a/src/irc/core/nicklist.c +++ /dev/null @@ -1,623 +0,0 @@ -/* - nicklist.c : 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 "misc.h" - -#include "channels.h" -#include "irc.h" -#include "masks.h" -#include "modes.h" -#include "nicklist.h" -#include "irc-server.h" - -/* Add new nick to list */ -NICK_REC *nicklist_insert(CHANNEL_REC *channel, const char *nick, - int op, int voice, int send_massjoin) -{ - NICK_REC *rec; - - g_return_val_if_fail(channel != NULL, NULL); - g_return_val_if_fail(nick != NULL, NULL); - - rec = g_new0(NICK_REC, 1); - - if (op) rec->op = TRUE; - if (voice) rec->voice = TRUE; - - rec->send_massjoin = send_massjoin; - rec->nick = g_strdup(nick); - rec->host = NULL; - - g_hash_table_insert(channel->nicks, rec->nick, rec); - signal_emit("nicklist new", 2, channel, rec); - return rec; -} - -static void nicklist_destroy(CHANNEL_REC *channel, NICK_REC *nick) -{ - signal_emit("nicklist remove", 2, channel, nick); - - g_free(nick->nick); - g_free_not_null(nick->realname); - g_free_not_null(nick->host); - g_free(nick); -} - -/* remove nick from list */ -void nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick) -{ - g_return_if_fail(channel != NULL); - g_return_if_fail(nick != NULL); - - g_hash_table_remove(channel->nicks, nick->nick); - nicklist_destroy(channel, nick); -} - -static NICK_REC *nicklist_find_wildcards(CHANNEL_REC *channel, - const char *mask) -{ - GSList *nicks, *tmp; - NICK_REC *nick; - - nicks = nicklist_getnicks(channel); - nick = NULL; - for (tmp = nicks; tmp != NULL; tmp = tmp->next) { - nick = tmp->data; - - if (irc_mask_match_address(mask, nick->nick, nick->host)) - break; - } - g_slist_free(nicks); - return tmp == NULL ? NULL : nick; -} - -GSList *nicklist_find_multiple(CHANNEL_REC *channel, const char *mask) -{ - GSList *nicks, *tmp, *next; - - nicks = nicklist_getnicks(channel); - for (tmp = nicks; tmp != NULL; tmp = next) { - NICK_REC *nick = tmp->data; - - next = tmp->next; - if (!irc_mask_match_address(mask, nick->nick, nick->host)) - nicks = g_slist_remove(nicks, tmp->data); - } - - return nicks; -} - -/* Find nick record from list */ -NICK_REC *nicklist_find(CHANNEL_REC *channel, const char *mask) -{ - NICK_REC *nickrec; - char *nick, *host; - - g_return_val_if_fail(channel != NULL, NULL); - g_return_val_if_fail(mask != NULL, NULL); - - nick = g_strdup(mask); - host = strchr(nick, '!'); - if (host != NULL) *host++ = '\0'; - - if (strchr(nick, '*') || strchr(nick, '?')) { - g_free(nick); - return nicklist_find_wildcards(channel, mask); - } - - nickrec = g_hash_table_lookup(channel->nicks, nick); - - if (nickrec != NULL && host != NULL && - (nickrec->host == NULL || !match_wildcards(host, nickrec->host))) { - /* hosts didn't match */ - nickrec = NULL; - } - g_free(nick); - return nickrec; -} - -static void get_nicks_hash(gpointer key, NICK_REC *rec, GSList **list) -{ - *list = g_slist_append(*list, rec); -} - -/* Get list of nicks */ -GSList *nicklist_getnicks(CHANNEL_REC *channel) -{ - GSList *list; - - list = NULL; - g_hash_table_foreach(channel->nicks, (GHFunc) get_nicks_hash, &list); - return list; -} - -typedef struct { - CHANNEL_REC *channel; - const char *nick; - GSList *list; -} NICKLIST_GET_SAME_REC; - -static void get_nicks_same_hash(gpointer key, NICK_REC *nick, NICKLIST_GET_SAME_REC *rec) -{ - if (g_strcasecmp(nick->nick, rec->nick) == 0) { - rec->list = g_slist_append(rec->list, rec->channel); - rec->list = g_slist_append(rec->list, nick); - } -} - -GSList *nicklist_get_same(IRC_SERVER_REC *server, const char *nick) -{ - NICKLIST_GET_SAME_REC rec; - GSList *tmp; - - rec.nick = nick; - rec.list = NULL; - for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { - rec.channel = tmp->data; - g_hash_table_foreach(rec.channel->nicks, - (GHFunc) get_nicks_same_hash, &rec); - } - return rec.list; -} - -/* nick record comparision for sort functions */ -int nicklist_compare(NICK_REC *p1, NICK_REC *p2) -{ - if (p1 == NULL) return -1; - if (p2 == NULL) return 1; - - if (p1->op && !p2->op) return -1; - if (!p1->op && p2->op) return 1; - - if (!p1->op) { - if (p1->voice && !p2->voice) return -1; - if (!p1->voice && p2->voice) return 1; - } - - return g_strcasecmp(p1->nick, p2->nick); -} - -#define isnickchar(a) \ - (isalnum(a) || (a) == '`' || (a) == '-' || (a) == '_' || \ - (a) == '[' || (a) == ']' || (a) == '{' || (a) == '}' || \ - (a) == '|' || (a) == '\\' || (a) == '^') - -/* Remove all "extra" characters from `nick'. Like _nick_ -> nick */ -char *nick_strip(const char *nick) -{ - char *stripped, *spos; - - g_return_val_if_fail(nick != NULL, NULL); - - spos = stripped = g_strdup(nick); - while (isnickchar(*nick)) { - if (isalnum((gint) *nick)) *spos++ = *nick; - nick++; - } - if ((unsigned char) *nick >= 128) - *spos++ = *nick; /* just add it so that nicks won't match.. */ - *spos = '\0'; - return stripped; -} - -/* Check is `msg' is meant for `nick'. */ -int irc_nick_match(const char *nick, const char *msg) -{ - char *stripnick, *stripmsg; - int ret, len; - - g_return_val_if_fail(nick != NULL, FALSE); - g_return_val_if_fail(msg != NULL, FALSE); - - len = strlen(nick); - if (g_strncasecmp(msg, nick, len) == 0 && !isalnum((int) msg[len])) - return TRUE; - - stripnick = nick_strip(nick); - stripmsg = nick_strip(msg); - - len = strlen(stripnick); - ret = len > 0 && g_strncasecmp(stripmsg, stripnick, len) == 0 && - !isalnum((int) stripmsg[len]) && - (unsigned char) stripmsg[len] < 128; - - g_free(stripnick); - g_free(stripmsg); - return ret; -} - -static void event_names_list(const char *data, IRC_SERVER_REC *server) -{ - CHANNEL_REC *chanrec; - char *params, *type, *channel, *names, *ptr; - - g_return_if_fail(data != NULL); - - params = event_get_params(data, 4, NULL, &type, &channel, &names); - - chanrec = channel_find(server, channel); - if (chanrec == NULL || chanrec->names_got) { - /* unknown channel / names list already read */ - g_free(params); - return; - } - - /* type = '=' = public, '*' = private, '@' = secret. - - This is actually pretty useless to check here, but at least we - get to know if the channel is +p or +s a few seconds before - we receive the MODE reply... */ - if (*type == '*') - parse_channel_modes(chanrec, NULL, "+p"); - else if (*type == '@') - parse_channel_modes(chanrec, NULL, "+s"); - - while (*names != '\0') { - while (*names == ' ') names++; - ptr = names; - while (*names != '\0' && *names != ' ') names++; - if (*names != '\0') *names++ = '\0'; - - if (*ptr == '@' && g_strcasecmp(server->nick, ptr+1) == 0) - chanrec->chanop = TRUE; - - nicklist_insert(chanrec, ptr+isnickflag(*ptr), - *ptr == '@', *ptr == '+', FALSE); - } - - g_free(params); -} - -static void event_end_of_names(const char *data, IRC_SERVER_REC *server) -{ - char *params, *channel; - CHANNEL_REC *chanrec; - - g_return_if_fail(server != NULL); - - params = event_get_params(data, 2, NULL, &channel); - - chanrec = channel_find(server, channel); - if (chanrec != NULL && !chanrec->names_got) { - chanrec->names_got = TRUE; - signal_emit("channel query", 1, chanrec); - } - - g_free(params); -} - -static void nicklist_update_flags(IRC_SERVER_REC *server, const char *nick, - int gone, int ircop) -{ - GSList *nicks, *tmp; - CHANNEL_REC *channel; - NICK_REC *rec; - - g_return_if_fail(server != NULL); - g_return_if_fail(nick != NULL); - - nicks = nicklist_get_same(server, nick); - for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) { - channel = tmp->data; - rec = tmp->next->data; - - rec->last_check = time(NULL); - - if (gone != -1 && rec->gone != gone) { - rec->gone = gone; - signal_emit("nick gone changed", 2, channel, rec); - } - - if (ircop != -1 && rec->ircop != ircop) { - rec->ircop = ircop; - signal_emit("nick ircop changed", 2, channel, rec); - } - } - g_slist_free(nicks); -} - -static void event_who(const char *data, IRC_SERVER_REC *server) -{ - char *params, *nick, *channel, *user, *host, *stat, *realname, *hops; - CHANNEL_REC *chanrec; - NICK_REC *nickrec; - - g_return_if_fail(data != NULL); - - params = event_get_params(data, 8, NULL, &channel, &user, &host, - NULL, &nick, &stat, &realname); - - /* get hop count */ - hops = realname; - while (*realname != '\0' && *realname != ' ') realname++; - *realname++ = '\0'; - while (*realname == ' ') realname++; - - /* update host, realname, hopcount */ - chanrec = channel_find(server, channel); - nickrec = chanrec == NULL ? NULL : nicklist_find(chanrec, nick); - if (nickrec != NULL) { - if (nickrec->host == NULL) - nickrec->host = g_strdup_printf("%s@%s", user, host); - if (nickrec->realname == NULL) - nickrec->realname = g_strdup(realname); - sscanf(hops, "%d", &nickrec->hops); - } - - nicklist_update_flags(server, nick, - strchr(stat, 'G') != NULL, /* gone */ - strchr(stat, '*') != NULL); /* ircop */ - - g_free(params); -} - -static void event_whois(const char *data, IRC_SERVER_REC *server) -{ - char *params, *nick, *realname; - GSList *nicks, *tmp; - NICK_REC *rec; - - g_return_if_fail(data != NULL); - - server->whois_coming = TRUE; - - /* first remove the gone-flag, if user is gone - it will be set later.. */ - params = event_get_params(data, 6, NULL, &nick, NULL, - NULL, NULL, &realname); - - nicks = nicklist_get_same(server, nick); - for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) { - rec = tmp->next->data; - - if (rec->realname == NULL) - rec->realname = g_strdup(realname); - } - g_slist_free(nicks); - - /* reset gone and ircop status, we'll handle them in the following - WHOIS replies */ - nicklist_update_flags(server, nick, FALSE, FALSE); - g_free(params); -} - -static void event_whois_away(const char *data, IRC_SERVER_REC *server) -{ - char *params, *nick, *awaymsg; - - g_return_if_fail(data != NULL); - - /* set user's gone flag.. */ - params = event_get_params(data, 3, NULL, &nick, &awaymsg); - nicklist_update_flags(server, nick, TRUE, -1); - g_free(params); -} - -static void event_whois_ircop(const char *data, IRC_SERVER_REC *server) -{ - char *params, *nick, *awaymsg; - - g_return_if_fail(data != NULL); - - /* set user's gone flag.. */ - params = event_get_params(data, 3, NULL, &nick, &awaymsg); - nicklist_update_flags(server, nick, -1, TRUE); - g_free(params); -} - -static void event_end_of_whois(const char *data, IRC_SERVER_REC *server) -{ - server->whois_coming = FALSE; -} - -static void event_nick_in_use(const char *data, IRC_SERVER_REC *server) -{ - char *str; - int n; - - g_return_if_fail(data != NULL); - - if (server->connected) { - /* Already connected, no need to handle this anymore. */ - return; - } - - /* nick already in use - need to change it .. */ - if (strcmp(server->nick, server->connrec->nick) == 0 && - server->connrec->alternate_nick != NULL) { - /* first try, so try the alternative nick.. */ - g_free(server->nick); - server->nick = g_strdup(server->connrec->alternate_nick); - } - else if (strlen(server->nick) < 9) { - /* keep adding '_' to end of nick.. */ - str = g_strdup_printf("%s_", server->nick); - g_free(server->nick); - server->nick = str; - } else { - /* nick full, keep adding number at the end */ - for (n = 8; n > 0; n--) { - if (server->nick[n] < '0' || server->nick[n] > '9') { - server->nick[n] = '1'; - break; - } - - if (server->nick[n] < '9') { - server->nick[n]++; - break; - } - server->nick[n] = '0'; - } - } - - irc_send_cmdv(server, "NICK %s", server->nick); -} - -static void event_target_unavailable(const char *data, IRC_SERVER_REC *server) -{ - char *params, *channel; - - g_return_if_fail(data != NULL); - - params = event_get_params(data, 2, NULL, &channel); - if (!ischannel(*channel)) { - /* nick is unavailable. */ - event_nick_in_use(data, server); - } - - g_free(params); -} - -static void event_nick(const char *data, IRC_SERVER_REC *server, - const char *orignick) -{ - CHANNEL_REC *channel; - NICK_REC *nickrec; - GSList *nicks, *tmp; - char *params, *nick; - - g_return_if_fail(data != NULL); - - params = event_get_params(data, 1, &nick); - - if (g_strcasecmp(orignick, server->nick) == 0) { - /* You changed your nick */ - g_free(server->connrec->nick); - g_free(server->nick); - server->connrec->nick = g_strdup(nick); - server->nick = g_strdup(nick); - signal_emit("server nick changed", 1, server); - } - - nicks = nicklist_get_same(server, orignick); - for (tmp = nicks; tmp != NULL; tmp = tmp->next->next) { - channel = tmp->data; - nickrec = tmp->next->data; - - /* remove old nick from hash table */ - g_hash_table_remove(channel->nicks, nickrec->nick); - - g_free(nickrec->nick); - nickrec->nick = g_strdup(nick); - - /* add new nick to hash table */ - g_hash_table_insert(channel->nicks, nickrec->nick, nickrec); - - signal_emit("nicklist changed", 3, channel, nickrec, orignick); - } - g_slist_free(nicks); - - g_free(params); -} - -static void event_userhost(const char *data, IRC_SERVER_REC *server) -{ - char *params, *hosts, **phosts, **pos, *ptr; - - g_return_if_fail(data != NULL); - - /* set user's gone flag.. */ - params = event_get_params(data, 2, NULL, &hosts); - - phosts = g_strsplit(hosts, " ", -1); - for (pos = phosts; *pos != NULL; pos++) { - ptr = strchr(*pos, '='); - if (ptr == NULL) continue; - *ptr++ = '\0'; - - nicklist_update_flags(server, *pos, *ptr == '-', -1); - } - g_strfreev(phosts); - g_free(params); -} - -static void sig_usermode(IRC_SERVER_REC *server) -{ - g_return_if_fail(server != NULL); - - nicklist_update_flags(server, server->nick, server->usermode_away, -1); -} - -static void sig_channel_created(CHANNEL_REC *channel) -{ - g_return_if_fail(channel != NULL); - - channel->nicks = g_hash_table_new((GHashFunc) g_istr_hash, - (GCompareFunc) g_istr_equal); -} - -static void nicklist_remove_hash(gpointer key, NICK_REC *nick, - CHANNEL_REC *channel) -{ - nicklist_destroy(channel, nick); -} - -static void sig_channel_destroyed(CHANNEL_REC *channel) -{ - g_return_if_fail(channel != NULL); - - g_hash_table_foreach(channel->nicks, - (GHFunc) nicklist_remove_hash, channel); - g_hash_table_destroy(channel->nicks); -} - -void nicklist_init(void) -{ - signal_add("event nick", (SIGNAL_FUNC) event_nick); - signal_add_first("event 352", (SIGNAL_FUNC) event_who); - signal_add("silent event who", (SIGNAL_FUNC) event_who); - signal_add("silent event whois", (SIGNAL_FUNC) event_whois); - signal_add_first("event 311", (SIGNAL_FUNC) event_whois); - signal_add_first("event 301", (SIGNAL_FUNC) event_whois_away); - signal_add_first("event 313", (SIGNAL_FUNC) event_whois_ircop); - signal_add("event 318", (SIGNAL_FUNC) event_end_of_whois); - signal_add("event 353", (SIGNAL_FUNC) event_names_list); - signal_add("event 366", (SIGNAL_FUNC) event_end_of_names); - signal_add("event 433", (SIGNAL_FUNC) event_nick_in_use); - signal_add("event 437", (SIGNAL_FUNC) event_target_unavailable); - signal_add("event 302", (SIGNAL_FUNC) event_userhost); - signal_add("userhost event", (SIGNAL_FUNC) event_userhost); - signal_add("user mode changed", (SIGNAL_FUNC) sig_usermode); - signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created); - signal_add("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); -} - -void nicklist_deinit(void) -{ - signal_remove("event nick", (SIGNAL_FUNC) event_nick); - signal_remove("event 352", (SIGNAL_FUNC) event_who); - signal_remove("silent event who", (SIGNAL_FUNC) event_who); - signal_remove("silent event whois", (SIGNAL_FUNC) event_whois); - signal_remove("event 311", (SIGNAL_FUNC) event_whois); - signal_remove("event 301", (SIGNAL_FUNC) event_whois_away); - signal_remove("event 313", (SIGNAL_FUNC) event_whois_ircop); - signal_remove("event 318", (SIGNAL_FUNC) event_end_of_whois); - signal_remove("event 353", (SIGNAL_FUNC) event_names_list); - signal_remove("event 366", (SIGNAL_FUNC) event_end_of_names); - signal_remove("event 433", (SIGNAL_FUNC) event_nick_in_use); - signal_remove("event 437", (SIGNAL_FUNC) event_target_unavailable); - signal_remove("event 302", (SIGNAL_FUNC) event_userhost); - signal_remove("userhost event", (SIGNAL_FUNC) event_userhost); - signal_remove("user mode changed", (SIGNAL_FUNC) sig_usermode); - signal_remove("channel created", (SIGNAL_FUNC) sig_channel_created); - signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed); -} diff --git a/src/irc/core/nicklist.h b/src/irc/core/nicklist.h deleted file mode 100644 index c40ec8cb..00000000 --- a/src/irc/core/nicklist.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __NICKLIST_H -#define __NICKLIST_H - -#include "irc-server.h" -#include "channels.h" - -typedef struct { - time_t last_check; /* last time gone was checked */ - int send_massjoin; /* Waiting to be sent in massjoin signal */ - - char *nick; - char *host; - char *realname; - - int hops; - - int op:1; - int halfop:1; - int voice:1; - int gone:1; - int ircop:1; -} NICK_REC; - -/* Add new nick to list */ -NICK_REC *nicklist_insert(CHANNEL_REC *channel, const char *nick, int op, int voice, int send_massjoin); -/* remove nick from list */ -void nicklist_remove(CHANNEL_REC *channel, NICK_REC *nick); -/* Find nick record from list */ -NICK_REC *nicklist_find(CHANNEL_REC *channel, const char *mask); -/* Get list of nicks that match the mask */ -GSList *nicklist_find_multiple(CHANNEL_REC *channel, const char *mask); -/* Get list of nicks */ -GSList *nicklist_getnicks(CHANNEL_REC *channel); -/* Get all the nick records of `nick'. Returns channel, nick, channel, ... */ -GSList *nicklist_get_same(IRC_SERVER_REC *server, const char *nick); - -/* Nick record comparision for sort functions */ -int nicklist_compare(NICK_REC *p1, NICK_REC *p2); - -/* Remove all "extra" characters from `nick'. Like _nick_ -> nick */ -char *nick_strip(const char *nick); -/* Check is `msg' is meant for `nick'. */ -int irc_nick_match(const char *nick, const char *msg); - -void nicklist_init(void); -void nicklist_deinit(void); - -#endif diff --git a/src/irc/core/query.c b/src/irc/core/query.c deleted file mode 100644 index 89a2f9f7..00000000 --- a/src/irc/core/query.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - query.c : irssi - - Copyright (C) 1999 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 "misc.h" -#include "signals.h" -#include "modules.h" - -#include "irc.h" -#include "query.h" - -GSList *queries; - -QUERY_REC *query_create(IRC_SERVER_REC *server, const char *nick, int automatic) -{ - QUERY_REC *rec; - - g_return_val_if_fail(nick != NULL, NULL); - - rec = g_new0(QUERY_REC, 1); - queries = g_slist_append(queries, rec); - if (server != NULL) server->queries = g_slist_append(server->queries, rec); - - MODULE_DATA_INIT(rec); - rec->type = module_get_uniq_id("IRC", WI_IRC_QUERY); - rec->nick = g_strdup(nick); - if (server != NULL) { - rec->server_tag = g_strdup(server->tag); - rec->server = server; - } - - signal_emit("query created", 2, rec, GINT_TO_POINTER(automatic)); - return rec; -} - -void query_destroy(QUERY_REC *query) -{ - g_return_if_fail(query != NULL); - - if (query->destroying) return; - query->destroying = TRUE; - - queries = g_slist_remove(queries, query); - if (query->server != NULL) - query->server->queries = g_slist_remove(query->server->queries, query); - signal_emit("query destroyed", 1, query); - - MODULE_DATA_DEINIT(query); - g_free_not_null(query->address); - g_free(query->nick); - g_free(query->server_tag); - g_free(query); -} - - -static QUERY_REC *query_find_server(IRC_SERVER_REC *server, const char *nick) -{ - GSList *tmp; - - for (tmp = server->queries; tmp != NULL; tmp = tmp->next) { - QUERY_REC *rec = tmp->data; - - if (g_strcasecmp(nick, rec->nick) == 0) - return rec; - } - - return NULL; -} - -QUERY_REC *query_find(IRC_SERVER_REC *server, const char *nick) -{ - g_return_val_if_fail(nick != NULL, NULL); - - if (server != NULL) - return query_find_server(server, nick); - - /* find from any server */ - return gslist_foreach_find(servers, (FOREACH_FIND_FUNC) query_find_server, (void *) nick); -} - -void query_change_server(QUERY_REC *query, IRC_SERVER_REC *server) -{ - g_return_if_fail(query != NULL); - - query->server = server; - signal_emit("query server changed", 2, query, server); -} - -static void event_privmsg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr) -{ - char *params, *target, *msg; - QUERY_REC *query; - - g_return_if_fail(data != NULL); - - params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); - - if (addr != NULL && !ischannel(*target)) { - /* save nick's address to query */ - query = query_find(server, nick); - if (query != NULL && (query->address == NULL || strcmp(query->address, addr) != 0)) { - g_free_not_null(query->address); - query->address = g_strdup(addr); - - signal_emit("query address changed", 1, query); - } - } - - g_free(params); -} - -static void event_nick(const char *data, IRC_SERVER_REC *server, const char *orignick) -{ - char *params, *nick; - GSList *tmp; - - params = event_get_params(data, 1, &nick); - - for (tmp = server->queries; tmp != NULL; tmp = tmp->next) { - QUERY_REC *rec = tmp->data; - - if (g_strcasecmp(rec->nick, orignick) == 0) { - g_free(rec->nick); - rec->nick = g_strdup(nick); - signal_emit("query nick changed", 1, rec); - } - } - - g_free(params); -} - -void query_init(void) -{ - signal_add_last("event privmsg", (SIGNAL_FUNC) event_privmsg); - signal_add("event nick", (SIGNAL_FUNC) event_nick); -} - -void query_deinit(void) -{ - signal_remove("event privmsg", (SIGNAL_FUNC) event_privmsg); - signal_remove("event nick", (SIGNAL_FUNC) event_nick); -} diff --git a/src/irc/core/query.h b/src/irc/core/query.h deleted file mode 100644 index 20ce79cc..00000000 --- a/src/irc/core/query.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __QUERY_H -#define __QUERY_H - -#include "server.h" - -typedef struct { - int type; - GHashTable *module_data; - - IRC_SERVER_REC *server; - char *nick; - - int new_data; - int last_color; - - char *address; - char *server_tag; - int unwanted:1; /* TRUE if the other side closed or some error occured (DCC chats!) */ - int destroying:1; -} QUERY_REC; - -extern GSList *queries; - -QUERY_REC *query_create(IRC_SERVER_REC *server, const char *nick, int automatic); -void query_destroy(QUERY_REC *query); - -/* Find query by name, if `server' is NULL, search from all servers */ -QUERY_REC *query_find(IRC_SERVER_REC *server, const char *nick); - -void query_change_server(QUERY_REC *query, IRC_SERVER_REC *server); - -void query_init(void); -void query_deinit(void); - -#endif diff --git a/src/irc/core/server-idle.c b/src/irc/core/server-idle.c index 1f4b7858..dd85282b 100644 --- a/src/irc/core/server-idle.c +++ b/src/irc/core/server-idle.c @@ -21,9 +21,9 @@ #include "module.h" #include "signals.h" -#include "irc-server.h" +#include "irc-servers.h" #include "server-idle.h" -#include "server-redirect.h" +#include "servers-redirect.h" #include "irc.h" typedef struct { @@ -217,7 +217,7 @@ static void sig_disconnected(IRC_SERVER_REC *server) { g_return_if_fail(server != NULL); - if (!irc_server_check(server)) + if (!IS_IRC_SERVER(server)) return; while (server->idles != NULL) @@ -232,7 +232,7 @@ static int sig_idle_timeout(void) for (tmp = servers; tmp != NULL; tmp = tmp->next) { IRC_SERVER_REC *rec = tmp->data; - if (irc_server_check(rec) && + if (IS_IRC_SERVER(rec) && rec->idles != NULL && rec->cmdcount == 0) { /* We're idling and we have idle commands to run! */ server_idle_next(rec); diff --git a/src/irc/core/server-idle.h b/src/irc/core/server-idle.h index a8ef8ec6..73761dae 100644 --- a/src/irc/core/server-idle.h +++ b/src/irc/core/server-idle.h @@ -1,7 +1,7 @@ #ifndef __SERVER_IDLE_H #define __SERVER_IDLE_H -#include "irc-server.h" +#include "irc-servers.h" /* Add new idle command to queue */ int server_idle_add(IRC_SERVER_REC *server, const char *cmd, const char *arg, int last, ...); diff --git a/src/irc/core/server-reconnect.c b/src/irc/core/server-reconnect.c deleted file mode 100644 index a6ae23cb..00000000 --- a/src/irc/core/server-reconnect.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - server-reconnect.c : irssi - - Copyright (C) 1999 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 "modules.h" -#include "commands.h" -#include "network.h" -#include "signals.h" - -#include "irc.h" -#include "modes.h" -#include "irc-server.h" -#include "server-setup.h" -#include "server-reconnect.h" - -#include "settings.h" - -GSList *reconnects; -static int last_reconnect_tag; -static int reconnect_timeout_tag; -static int reconnect_time; - -static void server_reconnect_add(IRC_SERVER_CONNECT_REC *conn, time_t next_connect) -{ - RECONNECT_REC *rec; - - rec = g_new(RECONNECT_REC, 1); - rec->tag = ++last_reconnect_tag; - rec->conn = conn; - rec->next_connect = next_connect; - - reconnects = g_slist_append(reconnects, rec); -} - -static void server_reconnect_destroy(RECONNECT_REC *rec, int free_conn) -{ - reconnects = g_slist_remove(reconnects, rec); - - signal_emit("server reconnect remove", 1, rec); - if (free_conn) irc_server_connect_free(rec->conn); - g_free(rec); - - if (reconnects == NULL) - last_reconnect_tag = 0; -} - -static int server_reconnect_timeout(void) -{ - IRC_SERVER_CONNECT_REC *conn; - GSList *list, *tmp; - time_t now; - - /* If irc_server_connect() removes the next reconnection in queue, - we're screwed. I don't think this should happen anymore, but just - to be sure we don't crash, do this safely. */ - list = g_slist_copy(reconnects); - now = time(NULL); - for (tmp = list; tmp != NULL; tmp = tmp->next) { - RECONNECT_REC *rec = tmp->data; - - if (g_slist_find(reconnects, rec) == NULL) - continue; - - if (rec->next_connect <= now) { - conn = rec->conn; - server_reconnect_destroy(rec, FALSE); - irc_server_connect(conn); - } - } - - g_slist_free(list); - return 1; -} - -static void sserver_connect(SETUP_SERVER_REC *rec, IRC_SERVER_CONNECT_REC *conn) -{ - conn->address = g_strdup(rec->address); - conn->port = rec->port; - - server_setup_fill_conn(conn, rec); - if (rec->last_connect > time(NULL)-reconnect_time) { - /* can't reconnect this fast, wait.. */ - server_reconnect_add(conn, rec->last_connect+reconnect_time); - } else { - /* connect to server.. */ - irc_server_connect(conn); - } -} - -static void server_connect_copy_skeleton(IRC_SERVER_CONNECT_REC *dest, IRC_SERVER_CONNECT_REC *src) -{ - dest->proxy = g_strdup(src->proxy); - dest->proxy_port = src->proxy_port; - dest->proxy_string = g_strdup(src->proxy_string); - - dest->ircnet = g_strdup(src->ircnet); - dest->nick = g_strdup(src->nick); - dest->username = g_strdup(src->username); - dest->realname = g_strdup(src->realname); - - if (src->own_ip != NULL) { - dest->own_ip = g_new(IPADDR, 1); - memcpy(dest->own_ip, src->own_ip, sizeof(IPADDR)); - } - - dest->cmd_queue_speed = src->cmd_queue_speed; - dest->max_kicks = src->max_kicks; - dest->max_modes = src->max_modes; - dest->max_msgs = src->max_msgs; -} - -#define server_should_reconnect(server) \ - (irc_server_check(server) && (server)->connection_lost && \ - ((server)->connrec->ircnet != NULL || !(server)->banned)) - -static void sig_reconnect(IRC_SERVER_REC *server) -{ - IRC_SERVER_CONNECT_REC *conn; - SETUP_SERVER_REC *sserver; - GSList *tmp; - int found, through; - time_t now; - - g_return_if_fail(server != NULL); - - if (reconnect_time == -1 || !server_should_reconnect(server)) - return; - - conn = g_new0(IRC_SERVER_CONNECT_REC, 1); - server_connect_copy_skeleton(conn, server->connrec); - - /* save the server status */ - if (!server->connected) { - conn->channels = g_strdup(server->connrec->channels); - conn->away_reason = g_strdup(server->connrec->away_reason); - conn->usermode = g_strdup(server->connrec->usermode); - } else { - conn->reconnection = TRUE; - conn->channels = irc_server_get_channels(server); - conn->away_reason = !server->usermode_away ? NULL : - g_strdup(server->away_reason); - conn->usermode = g_strdup(server->usermode); - } - - sserver = server_setup_find(server->connrec->address, - server->connrec->port); - - if (sserver != NULL) { - /* save the last connection time/status */ - sserver->last_connect = server->connect_time == 0 ? - time(NULL) : server->connect_time; - sserver->last_failed = !server->connected; - if (server->banned) sserver->banned = TRUE; - } - - if (sserver == NULL || conn->ircnet == NULL) { - /* not in any ircnet, just reconnect back to same server */ - conn->address = g_strdup(server->connrec->address); - conn->port = server->connrec->port; - conn->password = server->connrec->password == NULL ? NULL : - g_strdup(server->connrec->password); - - if (server->connect_time != 0 && - time(NULL)-server->connect_time > reconnect_time) { - /* there's been enough time since last connection, - reconnect back immediately */ - irc_server_connect(conn); - } else { - /* reconnect later.. */ - server_reconnect_add(conn, (server->connect_time == 0 ? time(NULL) : - server->connect_time) + reconnect_time); - } - return; - } - - /* always try to first connect to the first on the list where we - haven't got unsuccessful connection attempts for the last half - an hour. */ - - now = time(NULL); - for (tmp = setupservers; tmp != NULL; tmp = tmp->next) { - SETUP_SERVER_REC *rec = tmp->data; - - if (rec->ircnet != NULL && g_strcasecmp(conn->ircnet, rec->ircnet) == 0 && - !rec->banned && (!rec->last_connect || !rec->last_failed || - rec->last_connect < now-FAILED_RECONNECT_WAIT)) { - sserver_connect(rec, conn); - return; - } - } - - /* just try the next server in list */ - found = through = FALSE; - for (tmp = setupservers; tmp != NULL; ) { - SETUP_SERVER_REC *rec = tmp->data; - - if (!found && g_strcasecmp(rec->address, server->connrec->address) == 0 && - server->connrec->port == rec->port) - found = TRUE; - else if (found && !rec->banned && rec->ircnet != NULL && - g_strcasecmp(conn->ircnet, rec->ircnet) == 0) { - sserver_connect(rec, conn); - break; - } - - if (tmp->next != NULL) { - tmp = tmp->next; - continue; - } - - if (through) { - /* shouldn't happen unless there's no servers in - this ircnet in setup.. */ - irc_server_connect_free(conn); - break; - } - - tmp = setupservers; - found = through = TRUE; - } -} - -/* Remove all servers from reconnect list */ -/* SYNTAX: RMRECONNS */ -static void cmd_rmreconns(void) -{ - while (reconnects != NULL) - server_reconnect_destroy(reconnects->data, TRUE); -} - -static RECONNECT_REC *reconnect_find_tag(int tag) -{ - GSList *tmp; - - for (tmp = reconnects; tmp != NULL; tmp = tmp->next) { - RECONNECT_REC *rec = tmp->data; - - if (rec->tag == tag) - return rec; - } - - return NULL; -} - -/* Try to reconnect immediately */ -/* SYNTAX: RECONNECT */ -static void cmd_reconnect(const char *data, IRC_SERVER_REC *server) -{ - IRC_SERVER_CONNECT_REC *conn; - RECONNECT_REC *rec; - char *str; - int tag; - - if (*data == '\0') { - /* reconnect back to same server */ - if (server == NULL) cmd_return_error(CMDERR_NOT_CONNECTED); - str = g_strdup_printf("%s %d %s %s", server->connrec->address, - server->connrec->port, server->connrec->password, - server->connrec->nick); - signal_emit("command server", 2, str, server); - g_free(str); - return; - } - - if (g_strncasecmp(data, "RECON-", 6) == 0) - data += 6; - - tag = atoi(data); - rec = tag <= 0 ? NULL : reconnect_find_tag(tag); - - if (rec == NULL) - signal_emit("server reconnect not found", 1, data); - else { - conn = rec->conn; - server_reconnect_destroy(rec, FALSE); - irc_server_connect(conn); - } -} - -static void cmd_disconnect(const char *data, SERVER_REC *server) -{ - RECONNECT_REC *rec; - int tag; - - if (g_strncasecmp(data, "RECON-", 6) != 0) - return; /* handle only reconnection removing */ - - rec = sscanf(data+6, "%d", &tag) == 1 && tag > 0 ? - reconnect_find_tag(tag) : NULL; - - if (rec == NULL) - signal_emit("server reconnect not found", 1, data); - else - server_reconnect_destroy(rec, TRUE); -} - -static int sig_set_user_mode(IRC_SERVER_REC *server) -{ - const char *mode; - char *newmode; - - if (g_slist_find(servers, server) == NULL) - return 0; /* got disconnected */ - - mode = server->connrec->usermode; - if (mode == NULL) return 0; - - newmode = server->usermode == NULL ? NULL : - modes_join(server->usermode, mode); - - if (server->usermode == NULL) { - /* server didn't set user mode, just set the new one */ - irc_send_cmdv(server, "MODE %s %s", server->nick, mode); - } else { - if (strcmp(newmode, server->usermode) != 0) - irc_send_cmdv(server, "MODE %s -%s+%s", server->nick, server->usermode, mode); - } - - g_free_not_null(newmode); - return 0; -} - -static void sig_connected(IRC_SERVER_REC *server) -{ - if (!server->connrec->reconnection) - return; - - if (server->connrec->channels != NULL) - channels_join(server, server->connrec->channels, TRUE); - if (server->connrec->away_reason != NULL) - signal_emit("command away", 2, server->connrec->away_reason, server, NULL); - if (server->connrec->usermode != NULL) { - /* wait a second and then send the user mode */ - g_timeout_add(1000, (GSourceFunc) sig_set_user_mode, server); - } -} - -static void read_settings(void) -{ - reconnect_time = settings_get_int("server_reconnect_time"); -} - -void servers_reconnect_init(void) -{ - reconnects = NULL; - last_reconnect_tag = 0; - - reconnect_timeout_tag = g_timeout_add(1000, (GSourceFunc) server_reconnect_timeout, NULL); - read_settings(); - - signal_add("server connect failed", (SIGNAL_FUNC) sig_reconnect); - signal_add("server disconnected", (SIGNAL_FUNC) sig_reconnect); - signal_add("event connected", (SIGNAL_FUNC) sig_connected); - command_bind("rmreconns", NULL, (SIGNAL_FUNC) cmd_rmreconns); - command_bind("reconnect", NULL, (SIGNAL_FUNC) cmd_reconnect); - command_bind("disconnect", NULL, (SIGNAL_FUNC) cmd_disconnect); - signal_add("setup changed", (SIGNAL_FUNC) read_settings); -} - -void servers_reconnect_deinit(void) -{ - g_source_remove(reconnect_timeout_tag); - - while (reconnects != NULL) - server_reconnect_destroy(reconnects->data, TRUE); - - signal_remove("server connect failed", (SIGNAL_FUNC) sig_reconnect); - signal_remove("server disconnected", (SIGNAL_FUNC) sig_reconnect); - signal_remove("event connected", (SIGNAL_FUNC) sig_connected); - command_unbind("rmreconns", (SIGNAL_FUNC) cmd_rmreconns); - command_unbind("reconnect", (SIGNAL_FUNC) cmd_reconnect); - command_unbind("disconnect", (SIGNAL_FUNC) cmd_disconnect); - signal_remove("setup changed", (SIGNAL_FUNC) read_settings); -} diff --git a/src/irc/core/server-reconnect.h b/src/irc/core/server-reconnect.h deleted file mode 100644 index 9df7f2cc..00000000 --- a/src/irc/core/server-reconnect.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __SERVER_RECONNECT_H -#define __SERVER_RECONNECT_H - -/* wait for half an hour before trying to reconnect to host where last - connection failed */ -#define FAILED_RECONNECT_WAIT (60*30) - -typedef struct { - int tag; - time_t next_connect; - - IRC_SERVER_CONNECT_REC *conn; -} RECONNECT_REC; - -extern GSList *reconnects; - -void servers_reconnect_init(void); -void servers_reconnect_deinit(void); - -#endif diff --git a/src/irc/core/server-setup.c b/src/irc/core/server-setup.c deleted file mode 100644 index 299e703e..00000000 --- a/src/irc/core/server-setup.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - server-setup.c : 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 "network.h" -#include "lib-config/iconfig.h" -#include "settings.h" - -#include "irc-server.h" -#include "server-setup.h" -#include "server-reconnect.h" -#include "ircnet-setup.h" - -GSList *setupservers; /* list of irc servers */ - -int source_host_ok; /* Use source_host_ip .. */ -IPADDR *source_host_ip; /* Resolved address */ - -static void get_source_host_ip(void) -{ - IPADDR ip; - - /* FIXME: This will block! */ - if (!source_host_ok) { - source_host_ok = *settings_get_str("hostname") != '\0' && - net_gethostbyname(settings_get_str("hostname"), &ip) == 0; - if (source_host_ok) { - if (source_host_ip == NULL) - source_host_ip = g_new(IPADDR, 1); - memcpy(source_host_ip, &ip, sizeof(IPADDR)); - } - } -} - -static void conn_set_ip(IRC_SERVER_CONNECT_REC *conn, IPADDR **own_ip, const char *own_host) -{ - IPADDR ip; - - if (*own_ip != NULL) { - /* use already resolved IP */ - if (conn->own_ip == NULL) - conn->own_ip = g_new(IPADDR, 1); - memcpy(conn->own_ip, *own_ip, sizeof(IPADDR)); - return; - } - - - /* resolve the IP and use it */ - if (net_gethostbyname(own_host, &ip) == 0) { - if (conn->own_ip == NULL) - conn->own_ip = g_new(IPADDR, 1); - memcpy(conn->own_ip, &ip, sizeof(IPADDR)); - - *own_ip = g_new(IPADDR, 1); - memcpy(*own_ip, &ip, sizeof(IPADDR)); - } -} - -/* Fill information to connection from server setup record */ -void server_setup_fill_conn(IRC_SERVER_CONNECT_REC *conn, SETUP_SERVER_REC *sserver) -{ - if (sserver->own_host != NULL) - conn_set_ip(conn, &sserver->own_ip, sserver->own_host); - - if (sserver->ircnet != NULL && conn->ircnet == NULL) - conn->ircnet = g_strdup(sserver->ircnet); - - if (sserver->password != NULL && conn->password == NULL) - conn->password = g_strdup(sserver->password); - if (sserver->cmd_queue_speed > 0) - conn->cmd_queue_speed = sserver->cmd_queue_speed; - if (sserver->max_cmds_at_once > 0) - conn->max_cmds_at_once = sserver->max_cmds_at_once; -} - -/* Create server connection record. `address' is required, rest can be NULL */ -static IRC_SERVER_CONNECT_REC * -create_addr_conn(const char *address, int port, const - char *password, const char *nick) -{ - IRC_SERVER_CONNECT_REC *conn; - SETUP_SERVER_REC *sserver; - IRCNET_REC *ircnet; - - g_return_val_if_fail(address != NULL, NULL); - - conn = g_new0(IRC_SERVER_CONNECT_REC, 1); - - conn->address = g_strdup(address); - conn->port = port > 0 ? port : 6667; - - if (password && *password) conn->password = g_strdup(password); - if (nick && *nick) conn->nick = g_strdup(nick); - - if (!conn->nick) conn->nick = g_strdup(settings_get_str("default_nick")); - conn->alternate_nick = g_strdup(settings_get_str("alternate_nick")); - conn->username = g_strdup(settings_get_str("user_name")); - conn->realname = g_strdup(settings_get_str("real_name")); - - /* proxy settings */ - if (settings_get_bool("use_ircproxy")) { - conn->proxy = g_strdup(settings_get_str("proxy_address")); - conn->proxy_port = settings_get_int("proxy_port"); - conn->proxy_string = g_strdup(settings_get_str("proxy_string")); - } - - /* source IP */ - get_source_host_ip(); - if (source_host_ok) { - conn->own_ip = g_new(IPADDR, 1); - memcpy(conn->own_ip, source_host_ip, sizeof(IPADDR)); - } - - /* fill the information from setup */ - sserver = server_setup_find(conn->address, conn->port); - if (sserver == NULL) return conn; - - if (sserver->port > 0) conn->port = sserver->port; - server_setup_fill_conn(conn, sserver); - sserver->last_connect = time(NULL); - - /* fill the rest from IRC network settings */ - ircnet = sserver->ircnet == NULL ? NULL : ircnet_find(sserver->ircnet); - if (ircnet == NULL) return conn; - - if (ircnet->nick && !(nick && *nick)) { - g_free_and_null(conn->alternate_nick); - g_free(conn->nick); - conn->nick = g_strdup(ircnet->nick);; - } - if (ircnet->username) { - g_free(conn->username); - conn->username = g_strdup(ircnet->username);; - } - if (ircnet->realname) { - g_free(conn->realname); - conn->realname = g_strdup(ircnet->realname);; - } - if (ircnet->max_kicks > 0) conn->max_kicks = ircnet->max_kicks; - if (ircnet->max_msgs > 0) conn->max_msgs = ircnet->max_msgs; - if (ircnet->max_modes > 0) conn->max_modes = ircnet->max_modes; - if (ircnet->max_whois > 0) conn->max_whois = ircnet->max_whois; - - if (ircnet->max_cmds_at_once > 0 && sserver->max_cmds_at_once <= 0) - conn->max_cmds_at_once = ircnet->max_cmds_at_once; - if (ircnet->cmd_queue_speed > 0 && sserver->cmd_queue_speed <= 0) - conn->cmd_queue_speed = ircnet->cmd_queue_speed; - - if (sserver->own_host == NULL && ircnet->own_host != NULL) - conn_set_ip(conn, &ircnet->own_ip, ircnet->own_host); - - return conn; -} - -/* Connect to server where last connect succeeded (or we haven't tried to - connect yet). If there's no such server, connect to server where we - haven't connected for the longest time */ -static IRC_SERVER_CONNECT_REC * -create_ircnet_conn(const char *dest, int port, - const char *password, const char *nick) -{ - SETUP_SERVER_REC *bestrec; - GSList *tmp; - time_t now, besttime; - - now = time(NULL); - bestrec = NULL; besttime = now; - for (tmp = setupservers; tmp != NULL; tmp = tmp->next) { - SETUP_SERVER_REC *rec = tmp->data; - - if (rec->ircnet == NULL || g_strcasecmp(rec->ircnet, dest) != 0) - continue; - - if (!rec->last_failed) { - bestrec = rec; - break; - } - - if (bestrec == NULL || besttime > rec->last_connect) { - bestrec = rec; - besttime = rec->last_connect; - } - } - - return bestrec == NULL ? NULL : - create_addr_conn(bestrec->address, port, password, nick); -} - -/* Create server connection record. `dest' is required, rest can be NULL. - `dest' is either a server address or irc network */ -IRC_SERVER_CONNECT_REC * -irc_server_create_conn(const char *dest, int port, - const char *password, const char *nick) -{ - IRC_SERVER_CONNECT_REC *rec; - - g_return_val_if_fail(dest != NULL, NULL); - - if (ircnet_find(dest) != NULL) { - rec = create_ircnet_conn(dest, port, password, nick); - if (rec != NULL) - return rec; - } - - return create_addr_conn(dest, port, password, nick); -} - -/* Find matching server from setup. Try to find record with a same port, - but fallback to any server with the same address. */ -SETUP_SERVER_REC *server_setup_find(const char *address, int port) -{ - SETUP_SERVER_REC *server; - GSList *tmp; - - g_return_val_if_fail(address != NULL, NULL); - - server = NULL; - for (tmp = setupservers; tmp != NULL; tmp = tmp->next) { - SETUP_SERVER_REC *rec = tmp->data; - - if (g_strcasecmp(rec->address, address) == 0) { - server = rec; - if (rec->port == port) - break; - } - } - - return server; -} - -/* Find matching server from setup. Ports must match or NULL is returned. */ -SETUP_SERVER_REC *server_setup_find_port(const char *address, int port) -{ - SETUP_SERVER_REC *rec; - - rec = server_setup_find(address, port); - return rec == NULL || rec->port != port ? NULL : rec; -} - -static void init_userinfo(void) -{ - const char *set, *default_nick, *user_name; - char *str; - - /* check if nick/username/realname wasn't read from setup.. */ - set = settings_get_str("real_name"); - if (set == NULL || *set == '\0') { - str = g_getenv("IRCNAME"); - iconfig_set_str("settings", "real_name", - str != NULL ? str : g_get_real_name()); - } - - /* username */ - user_name = settings_get_str("user_name"); - if (user_name == NULL || *user_name == '\0') { - str = g_getenv("IRCUSER"); - iconfig_set_str("settings", "user_name", - str != NULL ? str : g_get_user_name()); - - user_name = settings_get_str("user_name"); - } - - /* nick */ - default_nick = settings_get_str("default_nick"); - if (default_nick == NULL || *default_nick == '\0') { - str = g_getenv("IRCNICK"); - iconfig_set_str("settings", "default_nick", - str != NULL ? str : user_name); - - default_nick = settings_get_str("default_nick"); - } - - /* alternate nick */ - set = settings_get_str("alternate_nick"); - if (set == NULL || *set == '\0') { - if (strlen(default_nick) < 9) - str = g_strconcat(default_nick, "_", NULL); - else { - str = g_strdup(default_nick); - str[strlen(str)-1] = '_'; - } - iconfig_set_str("settings", "alternate_nick", str); - g_free(str); - } - - /* host name */ - set = settings_get_str("hostname"); - if (set == NULL || *set == '\0') { - str = g_getenv("IRCHOST"); - if (str != NULL) - iconfig_set_str("settings", "hostname", str); - } -} - -void setupserver_config_add(SETUP_SERVER_REC *rec) -{ - CONFIG_NODE *node; - - node = iconfig_node_traverse("(servers", TRUE); - node = config_node_section(node, NULL, NODE_TYPE_BLOCK); - - iconfig_node_set_str(node, "address", rec->address); - iconfig_node_set_str(node, "ircnet", rec->ircnet); - - config_node_set_int(node, "port", rec->port); - iconfig_node_set_str(node, "password", rec->password); - iconfig_node_set_str(node, "own_host", rec->own_host); - - if (rec->autoconnect) - config_node_set_bool(node, "autoconnect", TRUE); - - if (rec->max_cmds_at_once > 0) - config_node_set_int(node, "cmds_max_at_once", rec->max_cmds_at_once); - if (rec->cmd_queue_speed > 0) - config_node_set_int(node, "cmd_queue_speed", rec->cmd_queue_speed); -} - -void setupserver_config_remove(SETUP_SERVER_REC *rec) -{ - CONFIG_NODE *node; - - node = iconfig_node_traverse("servers", FALSE); - if (node != NULL) iconfig_node_list_remove(node, g_slist_index(setupservers, rec)); -} - -static void setupserver_destroy(SETUP_SERVER_REC *rec) -{ - setupservers = g_slist_remove(setupservers, rec); - - g_free_not_null(rec->own_host); - g_free_not_null(rec->own_ip); - g_free_not_null(rec->ircnet); - g_free(rec->address); - g_free_not_null(rec->password); - g_free(rec); -} - -void server_setup_add(SETUP_SERVER_REC *rec) -{ - if (g_slist_find(setupservers, rec) != NULL) { - setupserver_config_remove(rec); - setupservers = g_slist_remove(setupservers, rec); - } - - setupservers = g_slist_append(setupservers, rec); - setupserver_config_add(rec); -} - -void server_setup_remove(SETUP_SERVER_REC *rec) -{ - setupserver_config_remove(rec); - setupserver_destroy(rec); -} - -static SETUP_SERVER_REC *setupserver_add_node(CONFIG_NODE *node) -{ - SETUP_SERVER_REC *rec; - char *server; - int port; - - g_return_val_if_fail(node != NULL, NULL); - - server = config_node_get_str(node, "address", NULL); - if (server == NULL) return NULL; - - port = config_node_get_int(node, "port", 6667); - if (server_setup_find_port(server, port) != NULL) { - /* already exists - don't let it get there twice or - server reconnects will screw up! */ - return NULL; - } - - rec = g_new0(SETUP_SERVER_REC, 1); - rec->ircnet = g_strdup(config_node_get_str(node, "ircnet", NULL)); - rec->address = g_strdup(server); - rec->password = g_strdup(config_node_get_str(node, "password", NULL)); - rec->port = port; - rec->autoconnect = config_node_get_bool(node, "autoconnect", FALSE); - rec->max_cmds_at_once = config_node_get_int(node, "cmds_max_at_once", 0); - rec->cmd_queue_speed = config_node_get_int(node, "cmd_queue_speed", 0); - rec->own_host = g_strdup(config_node_get_str(node, "own_host", 0)); - - setupservers = g_slist_append(setupservers, rec); - return rec; -} - -static void read_servers(void) -{ - CONFIG_NODE *node; - GSList *tmp; - - while (setupservers != NULL) - setupserver_destroy(setupservers->data); - - /* Read servers */ - node = iconfig_node_traverse("servers", FALSE); - if (node != NULL) { - for (tmp = node->value; tmp != NULL; tmp = tmp->next) - setupserver_add_node(tmp->data); - } -} - -static void read_settings(void) -{ - g_free_and_null(source_host_ip); - - source_host_ok = FALSE; - get_source_host_ip(); -} - -void servers_setup_init(void) -{ - settings_add_int("server", "server_reconnect_time", 300); - settings_add_str("server", "hostname", ""); - settings_add_bool("server", "skip_motd", FALSE); - - settings_add_str("server", "default_nick", NULL); - settings_add_str("server", "alternate_nick", NULL); - settings_add_str("server", "user_name", NULL); - settings_add_str("server", "real_name", NULL); - - settings_add_bool("ircproxy", "use_ircproxy", FALSE); - settings_add_str("ircproxy", "proxy_address", ""); - settings_add_int("ircproxy", "proxy_port", 6667); - settings_add_str("ircproxy", "proxy_string", "CONNECT %s %d"); - - init_userinfo(); - read_servers(); - - source_host_ip = NULL; - read_settings(); - - signal_add("setup changed", (SIGNAL_FUNC) read_settings); - signal_add("setup reread", (SIGNAL_FUNC) read_servers); -} - -void servers_setup_deinit(void) -{ - g_free_not_null(source_host_ip); - - while (setupservers != NULL) - setupserver_destroy(setupservers->data); - - signal_remove("setup changed", (SIGNAL_FUNC) read_settings); - signal_remove("setup reread", (SIGNAL_FUNC) read_servers); -} diff --git a/src/irc/core/server-setup.h b/src/irc/core/server-setup.h deleted file mode 100644 index 8803669c..00000000 --- a/src/irc/core/server-setup.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __SERVER_SETUP_H -#define __SERVER_SETUP_H - -#include "irc-server.h" - -/* servers */ -typedef struct { - char *address; - int port; - - char *ircnet; - char *password; - int autoconnect; - int max_cmds_at_once; /* override the default if > 0 */ - int cmd_queue_speed; /* override the default if > 0 */ - - char *own_host; /* address to use when connecting this server */ - IPADDR *own_ip; /* resolved own_address if not NULL */ - - time_t last_connect; /* to avoid reconnecting too fast.. */ - int last_failed:1; /* if last connection attempt failed */ - int banned:1; /* if we're banned from this server */ -} SETUP_SERVER_REC; - -extern GSList *setupservers; /* list of irc servers */ - -extern IPADDR *source_host_ip; /* Resolved address */ -extern gboolean source_host_ok; /* Use source_host_ip .. */ - -/* Create server connection record. `dest' is required, rest can be NULL. - `dest' is either a server address or irc network */ -IRC_SERVER_CONNECT_REC * -irc_server_create_conn(const char *dest, int port, const char *password, const char *nick); - -/* Fill information to connection from server setup record */ -void server_setup_fill_conn(IRC_SERVER_CONNECT_REC *conn, SETUP_SERVER_REC *sserver); - -void server_setup_add(SETUP_SERVER_REC *rec); -void server_setup_remove(SETUP_SERVER_REC *rec); - -/* Find matching server from setup. Try to find record with a same port, - but fallback to any server with the same address. */ -SETUP_SERVER_REC *server_setup_find(const char *address, int port); -/* Find matching server from setup. Ports must match or NULL is returned. */ -SETUP_SERVER_REC *server_setup_find_port(const char *address, int port); - -void servers_setup_init(void); -void servers_setup_deinit(void); - -#endif diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c index f1d9daba..59b4a776 100644 --- a/src/irc/dcc/dcc-chat.c +++ b/src/irc/dcc/dcc-chat.c @@ -29,8 +29,8 @@ #include "masks.h" #include "irc.h" -#include "server-setup.h" -#include "query.h" +#include "servers-setup.h" +#include "irc-queries.h" #include "dcc.h" @@ -50,10 +50,11 @@ DCC_REC *item_get_dcc(void *item) { QUERY_REC *query; - query = irc_item_query(item); - if (query == NULL || *query->nick != '=') return NULL; + query = IRC_QUERY(item); + if (query == NULL || *query->name != '=') + return NULL; - return dcc_find_item(DCC_TYPE_CHAT, query->nick+1, NULL); + return dcc_find_item(DCC_TYPE_CHAT, query->name+1, NULL); } /* Send text to DCC chat */ @@ -81,7 +82,7 @@ static void cmd_msg(const char *data) signal_stop(); } -static void cmd_me(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_me(const char *data, IRC_SERVER_REC *server, QUERY_REC *item) { DCC_REC *dcc; char *str; @@ -309,7 +310,7 @@ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server) } /* SYNTAX: MIRCDCC ON|OFF */ -static void cmd_mircdcc(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_mircdcc(const char *data, IRC_SERVER_REC *server, QUERY_REC *item) { DCC_REC *dcc; diff --git a/src/irc/dcc/dcc-files.c b/src/irc/dcc/dcc-files.c index 0f9facec..4eb3c5f3 100644 --- a/src/irc/dcc/dcc-files.c +++ b/src/irc/dcc/dcc-files.c @@ -29,7 +29,7 @@ #include "masks.h" #include "irc.h" -#include "server-setup.h" +#include "servers-setup.h" #include "dcc.h" @@ -495,7 +495,7 @@ static void dcc_send_init(DCC_REC *dcc) } /* SYNTAX: DCC SEND */ -static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, void *item) { char *target, *fname, *str, *ptr; void *free_arg; diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c index f3f96a20..e6f35668 100644 --- a/src/irc/dcc/dcc.c +++ b/src/irc/dcc/dcc.c @@ -76,7 +76,7 @@ DCC_REC *dcc_create(int type, int handle, const char *nick, const char *arg, dcc->ircnet = server == NULL ? (chat == NULL || chat->ircnet == NULL ? NULL : g_strdup(chat->ircnet)) : - (server->connrec->ircnet == NULL ? NULL : g_strdup(server->connrec->ircnet)); + (server->connrec->chatnet == NULL ? NULL : g_strdup(server->connrec->chatnet)); dcc_conns = g_slist_append(dcc_conns, dcc); signal_emit("dcc created", 1, dcc); @@ -222,14 +222,14 @@ static void dcc_server_connected(IRC_SERVER_REC *server) g_return_if_fail(server != NULL); - if (server->connrec->ircnet == NULL) + if (server->connrec->chatnet == NULL) return; for (tmp = dcc_conns; tmp != NULL; tmp = tmp->next) { DCC_REC *dcc = tmp->data; if (dcc->server == NULL && dcc->ircnet != NULL && - g_strcasecmp(dcc->ircnet, server->connrec->ircnet) == 0) { + g_strcasecmp(dcc->ircnet, server->connrec->chatnet) == 0) { dcc->server = server; g_free(dcc->mynick); dcc->mynick = g_strdup(server->nick); @@ -253,7 +253,7 @@ static void dcc_server_disconnected(IRC_SERVER_REC *server) if (dcc->ircnet == NULL) dcc->server = NULL; else { - dcc->server = (IRC_SERVER_REC *) server_find_ircnet(dcc->ircnet); + dcc->server = (IRC_SERVER_REC *) server_find_chatnet(dcc->ircnet); if (dcc->server != NULL) { g_free(dcc->mynick); dcc->mynick = g_strdup(dcc->server->nick); @@ -309,7 +309,7 @@ static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char case DCC_TYPE_GET: cstr = settings_get_str("dcc_autoget_masks"); /* check that autoget masks match */ - if (settings_get_bool("dcc_autoget") && (*cstr == '\0' || irc_masks_match(cstr, sender, sendaddr)) && + if (settings_get_bool("dcc_autoget") && (*cstr == '\0' || masks_match(SERVER(server), cstr, sender, sendaddr)) && /* check file size limit, FIXME: it's possible to send a bogus file size and then just send what ever sized file.. */ (settings_get_int("dcc_max_autoget_size") <= 0 || (settings_get_int("dcc_max_autoget_size") > 0 && size <= settings_get_int("dcc_max_autoget_size")*1024))) { @@ -327,7 +327,7 @@ static void dcc_ctcp_msg(char *data, IRC_SERVER_REC *server, char *sender, char case DCC_TYPE_CHAT: cstr = settings_get_str("dcc_autochat_masks"); - if (*cstr != '\0' && irc_masks_match(cstr, sender, sendaddr)) + if (*cstr != '\0' && masks_match(SERVER(server), cstr, sender, sendaddr)) { /* automatically accept chat */ str = g_strdup_printf("CHAT %s", dcc->nick); @@ -454,7 +454,7 @@ static void cmd_dcc_close(char *data, IRC_SERVER_REC *server) cmd_params_free(free_arg); } -static void cmd_dcc(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static void cmd_dcc(const char *data, IRC_SERVER_REC *server, void *item) { command_runsub("dcc", data, server, item); } diff --git a/src/irc/flood/autoignore.c b/src/irc/flood/autoignore.c index 83f4da68..44425a9f 100644 --- a/src/irc/flood/autoignore.c +++ b/src/irc/flood/autoignore.c @@ -26,7 +26,7 @@ #include "misc.h" #include "settings.h" -#include "irc-server.h" +#include "irc-servers.h" #include "ignore.h" #include "autoignore.h" diff --git a/src/irc/flood/flood.c b/src/irc/flood/flood.c index 87cb2966..edd6566b 100644 --- a/src/irc/flood/flood.c +++ b/src/irc/flood/flood.c @@ -26,7 +26,7 @@ #include "settings.h" #include "irc.h" -#include "irc-server.h" +#include "irc-servers.h" #include "autoignore.h" #include "ignore.h" diff --git a/src/irc/notifylist/module.h b/src/irc/notifylist/module.h index 43110540..ec67bcbb 100644 --- a/src/irc/notifylist/module.h +++ b/src/irc/notifylist/module.h @@ -25,7 +25,7 @@ typedef struct { GSList *ison_tempusers; /* Temporary list for saving /ISON events.. */ } MODULE_SERVER_REC; -#include "irc-server.h" +#include "irc-servers.h" NOTIFY_NICK_REC *notify_nick_create(IRC_SERVER_REC *server, const char *nick); void notify_nick_destroy(NOTIFY_NICK_REC *rec); diff --git a/src/irc/notifylist/notify-ison.c b/src/irc/notifylist/notify-ison.c index b03f9a2e..c3b459b2 100644 --- a/src/irc/notifylist/notify-ison.c +++ b/src/irc/notifylist/notify-ison.c @@ -24,8 +24,8 @@ #include "settings.h" #include "irc.h" -#include "irc-server.h" -#include "server-redirect.h" +#include "irc-servers.h" +#include "servers-redirect.h" #include "notifylist.h" @@ -127,7 +127,7 @@ static void notifylist_timeout_server(IRC_SERVER_REC *server) for (tmp = notifies; tmp != NULL; tmp = tmp->next) { NOTIFYLIST_REC *rec = tmp->data; - if (!notifylist_ircnets_match(rec, server->connrec->ircnet)) + if (!notifylist_ircnets_match(rec, server->connrec->chatnet)) continue; nick = g_strdup(rec->mask); @@ -251,7 +251,7 @@ static void ison_check_joins(IRC_SERVER_REC *server) for (tmp = mserver->ison_tempusers; tmp != NULL; tmp = tmp->next) { char *nick = tmp->data; - notify = notifylist_find(nick, server->connrec->ircnet); + notify = notifylist_find(nick, server->connrec->chatnet); send_whois = notify != NULL && (notify->away_check || notify->idle_check_time > 0); diff --git a/src/irc/notifylist/notify-setup.c b/src/irc/notifylist/notify-setup.c index df1dc541..aba7742a 100644 --- a/src/irc/notifylist/notify-setup.c +++ b/src/irc/notifylist/notify-setup.c @@ -22,7 +22,7 @@ #include "lib-config/iconfig.h" #include "settings.h" -#include "irc-server.h" +#include "irc-servers.h" #include "notifylist.h" void notifylist_add_config(NOTIFYLIST_REC *rec) diff --git a/src/irc/notifylist/notify-whois.c b/src/irc/notifylist/notify-whois.c index 5a9500cc..45ec8479 100644 --- a/src/irc/notifylist/notify-whois.c +++ b/src/irc/notifylist/notify-whois.c @@ -23,7 +23,7 @@ #include "special-vars.h" #include "irc.h" -#include "irc-server.h" +#include "irc-servers.h" #include "masks.h" #include "notifylist.h" @@ -41,8 +41,8 @@ static void event_whois(const char *data, IRC_SERVER_REC *server) params = event_get_params(data, 6, NULL, &nick, &user, &host, NULL, &realname); - notify = notifylist_find(nick, server->connrec->ircnet); - if (notify != NULL && !irc_mask_match(notify->mask, nick, user, host)) { + notify = notifylist_find(nick, server->connrec->chatnet); + if (notify != NULL && !mask_match(SERVER(server), notify->mask, nick, user, host)) { /* user or host didn't match */ g_free(params); return; @@ -80,7 +80,7 @@ static void event_whois_idle(const char *data, IRC_SERVER_REC *server) params = event_get_params(data, 3, NULL, &nick, &secstr); secs = atol(secstr); - notify = notifylist_find(nick, server->connrec->ircnet); + notify = notifylist_find(nick, server->connrec->chatnet); nickrec = notify_nick_find(server, nick); if (notify != NULL && nickrec != NULL) { nickrec->idle_changed = secs < nickrec->idle_time && @@ -127,7 +127,7 @@ static void event_whois_end(const char *data, IRC_SERVER_REC *server) if (rec->realname == NULL) continue; - notify = notifylist_find(rec->nick, server->connrec->ircnet); + notify = notifylist_find(rec->nick, server->connrec->chatnet); if (notify == NULL) continue; away_ok = !notify->away_check || !rec->away; @@ -155,7 +155,7 @@ static void event_whois_end(const char *data, IRC_SERVER_REC *server) } /* last person that NOTIFY detected a signon for */ -static char *expando_lastnotify(void *server, void *item, int *free_ret) +static char *expando_lastnotify(SERVER_REC *server, void *item, int *free_ret) { return last_notify_nick; } diff --git a/src/irc/notifylist/notifylist.c b/src/irc/notifylist/notifylist.c index de19ed0c..f16cf16c 100644 --- a/src/irc/notifylist/notifylist.c +++ b/src/irc/notifylist/notifylist.c @@ -23,8 +23,8 @@ #include "signals.h" #include "irc.h" -#include "irc-server.h" -#include "server-redirect.h" +#include "irc-channels.h" +#include "servers-redirect.h" #include "masks.h" #include "nicklist.h" @@ -149,7 +149,7 @@ static IRC_SERVER_REC *notifylist_ison_serverlist(const char *nick, const char * server = NULL; for (tmp = list; *tmp != NULL; tmp++) { - server = (IRC_SERVER_REC *) server_find_ircnet(*tmp); + server = (IRC_SERVER_REC *) server_find_chatnet(*tmp); if (server != NULL && notifylist_ison_server(server, nick)) break; @@ -227,7 +227,7 @@ static void notifylist_idle_reset(IRC_SERVER_REC *server, const char *nick) NOTIFY_NICK_REC *rec; NOTIFYLIST_REC *notify; - notify = notifylist_find(nick, server->connrec->ircnet); + notify = notifylist_find(nick, server->connrec->chatnet); rec = notify_nick_find(server, nick); if (notify != NULL && rec != NULL && notify->idle_check_time > 0 && @@ -257,7 +257,7 @@ static void notifylist_check_join(IRC_SERVER_REC *server, const char *nick, NOTIFY_NICK_REC *rec; char *user, *host; - notify = notifylist_find(nick, server->connrec->ircnet); + notify = notifylist_find(nick, server->connrec->chatnet); if (notify == NULL) return; rec = notify_nick_find(server, nick); @@ -268,7 +268,7 @@ static void notifylist_check_join(IRC_SERVER_REC *server, const char *nick, host = strchr(user, '@'); if (host != NULL) *host++ = '\0'; else host = ""; - if (!irc_mask_match(notify->mask, nick, user, host)) { + if (!mask_match(SERVER(server), notify->mask, nick, user, host)) { g_free(user); return; } @@ -309,11 +309,11 @@ static void event_join(const char *data, IRC_SERVER_REC *server, const char *nic notifylist_check_join(server, nick, address, "", -1); } -static void sig_channel_wholist(CHANNEL_REC *channel) +static void sig_channel_wholist(IRC_CHANNEL_REC *channel) { GSList *nicks, *tmp; - nicks = nicklist_getnicks(channel); + nicks = nicklist_getnicks(CHANNEL(channel)); for (tmp = nicks; tmp != NULL; tmp = tmp->next) { NICK_REC *rec = tmp->data; diff --git a/src/lib-config/Makefile.am b/src/lib-config/Makefile.am index 00969218..3907ac3d 100644 --- a/src/lib-config/Makefile.am +++ b/src/lib-config/Makefile.am @@ -1,10 +1,10 @@ -noinst_LTLIBRARIES = libirssi_config.la +noinst_LIBRARIES = libirssi_config.a INCLUDES = \ $(GLIB_CFLAGS) \ -I$(top_srcdir)/src -libirssi_config_la_SOURCES = \ +libirssi_config_a_SOURCES = \ get.c \ set.c \ parse.c \ diff --git a/src/lib-config/get.c b/src/lib-config/get.c index c4cde5b8..4db6b4b7 100644 --- a/src/lib-config/get.c +++ b/src/lib-config/get.c @@ -291,3 +291,19 @@ char **config_node_get_list(CONFIG_NODE *node) g_string_free(values, TRUE); return ret; } + +/* Returns n'th node from list. */ +CONFIG_NODE *config_node_index(CONFIG_NODE *node, int index) +{ + GSList *tmp; + + g_return_val_if_fail(node != NULL, NULL); + g_return_val_if_fail(is_node_list(node), NULL); + + for (tmp = node->value; tmp != NULL; tmp = tmp->next, index--) { + if (index == 0) + return tmp->data; + } + + return NULL; +} diff --git a/src/lib-config/iconfig.h b/src/lib-config/iconfig.h index 86659a13..f6910642 100644 --- a/src/lib-config/iconfig.h +++ b/src/lib-config/iconfig.h @@ -98,6 +98,8 @@ int config_get_bool(CONFIG_REC *rec, const char *section, const char *key, int d const char *config_list_find(CONFIG_REC *rec, const char *section, const char *key, const char *value, const char *value_key); /* Like config_list_find(), but return node instead of it's value */ CONFIG_NODE *config_list_find_node(CONFIG_REC *rec, const char *section, const char *key, const char *value, const char *value_key); +/* Returns n'th node from list. */ +CONFIG_NODE *config_node_index(CONFIG_NODE *node, int index); /* Setting values */ int config_set_str(CONFIG_REC *rec, const char *section, const char *key, const char *value); @@ -135,6 +137,8 @@ void config_node_remove(CONFIG_REC *rec, CONFIG_NODE *parent, CONFIG_NODE *node) /* Remove n'th node from a list */ void config_node_list_remove(CONFIG_REC *rec, CONFIG_NODE *node, int index); +/* Clear all data inside node, but leave the node */ +void config_node_clear(CONFIG_REC *rec, CONFIG_NODE *node); /* Clear the entire configuration */ void config_nodes_remove_all(CONFIG_REC *rec); diff --git a/src/lib-config/parse.c b/src/lib-config/parse.c index ba5d9b34..05b76975 100644 --- a/src/lib-config/parse.c +++ b/src/lib-config/parse.c @@ -116,7 +116,8 @@ static void config_parse_peek_token(GScanner *scanner, CONFIG_NODE *node) } /* get optional token, optionally warn if it's missing */ -static void config_parse_warn_missing(CONFIG_REC *rec, CONFIG_NODE *node, int expected_token, int print_warning) +static void config_parse_warn_missing(CONFIG_REC *rec, CONFIG_NODE *node, + GTokenType expected_token, int print_warning) { config_parse_peek_token(rec->scanner, node); if (rec->scanner->next_token == expected_token) { @@ -128,7 +129,7 @@ static void config_parse_warn_missing(CONFIG_REC *rec, CONFIG_NODE *node, int ex g_scanner_warn(rec->scanner, "Warning: missing '%c'", expected_token); } -static void config_parse_loop(CONFIG_REC *rec, CONFIG_NODE *node, int expect); +static void config_parse_loop(CONFIG_REC *rec, CONFIG_NODE *node, GTokenType expect); static int config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node) { @@ -215,7 +216,7 @@ static int config_parse_symbol(CONFIG_REC *rec, CONFIG_NODE *node) return G_TOKEN_NONE; } -static void config_parse_loop(CONFIG_REC *rec, CONFIG_NODE *node, int expect) +static void config_parse_loop(CONFIG_REC *rec, CONFIG_NODE *node, GTokenType expect) { int expected_token; diff --git a/src/lib-config/set.c b/src/lib-config/set.c index 4b887558..f750c40a 100644 --- a/src/lib-config/set.c +++ b/src/lib-config/set.c @@ -59,17 +59,23 @@ void config_node_remove(CONFIG_REC *rec, CONFIG_NODE *parent, CONFIG_NODE *node) /* Remove n'th node from a list */ void config_node_list_remove(CONFIG_REC *rec, CONFIG_NODE *node, int index) { - GSList *tmp; + CONFIG_NODE *child; g_return_if_fail(node != NULL); g_return_if_fail(is_node_list(node)); - for (tmp = node->value; tmp != NULL; tmp = tmp->next, index--) { - if (index == 0) { - config_node_remove(rec, node, tmp->data); - break; - } - } + child = config_node_index(node, index); + if (child != NULL) config_node_remove(rec, node, child); +} + +/* Clear all data inside node, but leave the node */ +void config_node_clear(CONFIG_REC *rec, CONFIG_NODE *node) +{ + g_return_if_fail(node != NULL); + g_return_if_fail(is_node_list(node)); + + while (node->value != NULL) + config_node_remove(rec, node, node->value); } void config_nodes_remove_all(CONFIG_REC *rec) diff --git a/src/lib-popt/Makefile.am b/src/lib-popt/Makefile.am index 04f9145c..928e5c0b 100644 --- a/src/lib-popt/Makefile.am +++ b/src/lib-popt/Makefile.am @@ -1,10 +1,10 @@ -noinst_LTLIBRARIES = libpopt.la +noinst_LIBRARIES = libpopt.a INCLUDES = \ $(GLIB_CFLAGS) \ -I$(top_srcdir)/src -libpopt_la_SOURCES = \ +libpopt_a_SOURCES = \ findme.c popt.c poptconfig.c popthelp.c poptparse.c noinst_HEADERS = \ diff --git a/src/perl/Makefile.am b/src/perl/Makefile.am index 1a9a895b..6cae6a40 100644 --- a/src/perl/Makefile.am +++ b/src/perl/Makefile.am @@ -1,4 +1,4 @@ -noinst_LTLIBRARIES = libperl.la +noinst_LIBRARIES = libperl.a irssi-perl.c: perl-signals.h @@ -8,7 +8,7 @@ INCLUDES = $(GLIB_CFLAGS) \ -I$(top_srcdir)/src \ -I$(top_srcdir)/src/core -libperl_la_SOURCES = \ +libperl_a_SOURCES = \ irssi-perl.c \ xsinit.c diff --git a/src/perl/xs/Irssi-query.xs b/src/perl/xs/Irssi-query.xs index 95275dce..3f68a273 100644 --- a/src/perl/xs/Irssi-query.xs +++ b/src/perl/xs/Irssi-query.xs @@ -28,7 +28,7 @@ PPCODE: } Irssi::Query -query_create(server, nick, automatic) +irc_query_create(server, nick, automatic) Irssi::Server server char *nick int automatic @@ -56,7 +56,7 @@ PPCODE: stash = gv_stashpv("Irssi::Server", 0); hv_store(hv, "server", 6, sv_bless(newRV_noinc(newSViv(GPOINTER_TO_INT(query->server))), stash), 0); - hv_store(hv, "nick", 4, new_pv(query->nick), 0); + hv_store(hv, "name", 4, new_pv(query->name), 0); hv_store(hv, "new_data", 8, newSViv(query->new_data), 0); hv_store(hv, "address", 7, new_pv(query->address), 0); diff --git a/src/perl/xs/Irssi-window.xs b/src/perl/xs/Irssi-window.xs index f1766ffa..65382bbb 100644 --- a/src/perl/xs/Irssi-window.xs +++ b/src/perl/xs/Irssi-window.xs @@ -1,7 +1,7 @@ MODULE = Irssi PACKAGE = Irssi void -command(cmd, server=active_win->active_server, item=active_win->active) +command(cmd, server=IRC_SERVER(active_win->active_server), item=active_win->active) char *cmd Irssi::Server server Irssi::Windowitem item @@ -18,7 +18,7 @@ OUTPUT: Irssi::Server active_server() CODE: - RETVAL = active_win->active_server; + RETVAL = IRC_SERVER(active_win->active_server); OUTPUT: RETVAL @@ -47,7 +47,7 @@ command(server, cmd, item=active_win->active) Irssi::Server server Irssi::Windowitem item CODE: - if (item != NULL && item->server != server) + if (item != NULL && item->server != SERVER(server)) item = NULL; signal_emit("send command", 3, cmd, server, item); diff --git a/src/perl/xs/module.h b/src/perl/xs/module.h index bbb0a127..8f003fdc 100644 --- a/src/perl/xs/module.h +++ b/src/perl/xs/module.h @@ -6,20 +6,20 @@ #include "common.h" #include "network.h" #include "commands.h" -#include "server.h" +#include "servers.h" #include "log.h" #include "rawlog.h" #include "settings.h" +#include "masks.h" #include "irc/core/bans.h" -#include "irc/core/channels.h" -#include "irc/core/query.h" #include "irc/core/irc.h" -#include "irc/core/irc-server.h" +#include "irc/core/irc-servers.h" #include "irc/core/server-reconnect.h" #include "irc/core/server-setup.h" -#include "irc/core/nicklist.h" -#include "irc/core/masks.h" +#include "irc/core/irc-channels.h" +#include "irc/core/irc-queries.h" +#include "irc/core/irc-nicklist.h" #include "irc/core/modes.h" #include "irc/core/mode-lists.h" #include "irc/core/netsplit.h" @@ -37,7 +37,7 @@ typedef COMMAND_REC *Irssi__Command; typedef LOG_REC *Irssi__Log; typedef RAWLOG_REC *Irssi__Rawlog; -typedef CHANNEL_REC *Irssi__Channel; +typedef IRC_CHANNEL_REC *Irssi__Channel; typedef QUERY_REC *Irssi__Query; typedef IRC_SERVER_REC *Irssi__Server; typedef IRC_SERVER_CONNECT_REC *Irssi__Connect; -- cgit v1.2.3