From d3dc9a1307adc40425bf162f1f867a39e535f501 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Thu, 4 May 2000 10:32:42 +0000 Subject: .. lots of changes .. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@197 dbcabf3a-b0e7-0310-adc4-f8d773084564 --- src/irc/core/bans.c | 17 +++--- src/irc/core/channel-events.c | 34 +++++++++-- src/irc/core/channels-query.c | 4 +- src/irc/core/channels-setup.c | 85 ++++++++++++++++---------- src/irc/core/channels-setup.h | 3 +- src/irc/core/channels.c | 19 ++++-- src/irc/core/channels.h | 1 + src/irc/core/ctcp.c | 2 +- src/irc/core/ignore.c | 5 +- src/irc/core/irc-commands.c | 59 ++++++++++++------ src/irc/core/irc-log.c | 4 +- src/irc/core/irc-server.c | 6 +- src/irc/core/irc-server.h | 1 + src/irc/core/irc.c | 1 + src/irc/core/ircnet-setup.c | 1 + src/irc/core/massjoin.c | 17 +++++- src/irc/core/modes.c | 89 +++++++++++++++++++++++---- src/irc/core/netsplit.c | 80 +++++++++++++++++++------ src/irc/core/netsplit.h | 12 +++- src/irc/core/nicklist.c | 21 ++++++- src/irc/core/nicklist.h | 2 + src/irc/core/server-reconnect.c | 26 +++++--- src/irc/core/server-setup.c | 129 ++++++++++++++++++++++++++++++++-------- src/irc/core/server-setup.h | 9 ++- 24 files changed, 479 insertions(+), 148 deletions(-) (limited to 'src/irc/core') diff --git a/src/irc/core/bans.c b/src/irc/core/bans.c index 962c3c8d..4108f1bd 100644 --- a/src/irc/core/bans.c +++ b/src/irc/core/bans.c @@ -55,7 +55,7 @@ char *ban_get_mask(CHANNEL_REC *channel, const char *nick) host = strchr(++user, '@'); if (host == NULL) return str; - if ((int) (host-user) < 10) { + if ((int) (host-user) > 10) { /* too long user mask */ user[9] = '*'; g_memmove(user+10, host, strlen(host)+1); @@ -112,7 +112,7 @@ void ban_set_type(const char *type) void ban_set(CHANNEL_REC *channel, const char *bans) { GString *str; - char **ban, **banlist; + char **ban, **banlist, *realban; g_return_if_fail(bans != NULL); @@ -121,19 +121,20 @@ void ban_set(CHANNEL_REC *channel, const char *bans) for (ban = banlist; *ban != NULL; ban++) { if (strchr(*ban, '!') != NULL) { /* explicit ban */ - g_string_sprintfa(str, " %s", *ban); + g_string_sprintfa(str, "%s ", *ban); continue; } /* ban nick */ - *ban = ban_get_mask(channel, *ban); - if (*ban != NULL) { - g_string_sprintfa(str, " %s", *ban); - g_free(*ban); + realban = ban_get_mask(channel, *ban); + if (realban != NULL) { + g_string_sprintfa(str, "%s ", realban); + g_free(realban); } } g_strfreev(banlist); + g_string_truncate(str, str->len-1); channel_set_singlemode(channel->server, channel->name, str->str, "+b"); g_string_free(str, TRUE); } @@ -169,7 +170,7 @@ static void command_set_ban(const char *data, IRC_SERVER_REC *server, WI_IRC_REC if (server == NULL || !server->connected || !irc_server_check(server)) cmd_return_error(CMDERR_NOT_CONNECTED); - params = cmd_get_params(data, 3 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, + params = cmd_get_params(data, 2 | PARAM_FLAG_OPTCHAN | PARAM_FLAG_GETREST, item, &channel, &nicks); if (!ischannel(*channel)) cmd_param_error(CMDERR_NOT_JOINED); if (*nicks == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); diff --git a/src/irc/core/channel-events.c b/src/irc/core/channel-events.c index 8f11ee47..8de80cbd 100644 --- a/src/irc/core/channel-events.c +++ b/src/irc/core/channel-events.c @@ -95,6 +95,27 @@ static void event_topic(const char *data, IRC_SERVER_REC *server) g_free(params); } +/* 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) +{ + GSList *tmp; + int len; + + len = strlen(channel); + for (tmp = server->channels; tmp != NULL; tmp = tmp->next) { + CHANNEL_REC *rec = tmp->data; + + if (rec->joined) continue; + + if (g_strncasecmp(channel, rec->name, len) == 0 && + (len > 20 || rec->name[len] == '\0')) + return rec; + } + + return NULL; +} + static void event_join(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address) { char *params, *channel, *tmp; @@ -120,10 +141,8 @@ static void event_join(const char *data, IRC_SERVER_REC *server, const char *nic !channel here to !ABCDEchannel */ char *shortchan; - shortchan = g_strdup(channel); - sprintf(shortchan, "!%s", channel+6); - - chanrec = channel_find(server, shortchan); + shortchan = g_strdup_printf("!%s", channel+6); + chanrec = channel_find_unjoined(server, shortchan); if (chanrec != NULL) { g_free(chanrec->name); chanrec->name = g_strdup(channel); @@ -132,11 +151,16 @@ static void event_join(const char *data, IRC_SERVER_REC *server, const char *nic g_free(shortchan); } - chanrec = channel_find(server, channel); + chanrec = channel_find_unjoined(server, channel); if (chanrec == NULL) { /* didn't get here with /join command.. */ chanrec = channel_create(server, channel, TRUE); } + chanrec->joined = TRUE; + if (strcmp(chanrec->name, channel) != 0) { + g_free(chanrec->name); + chanrec->name = g_strdup(channel); + } g_free(params); } diff --git a/src/irc/core/channels-query.c b/src/irc/core/channels-query.c index 0691d3ef..d8516ff6 100644 --- a/src/irc/core/channels-query.c +++ b/src/irc/core/channels-query.c @@ -232,7 +232,7 @@ static void channel_send_query(IRC_SERVER_REC *server, int query) for (tmp = chans; tmp != NULL; tmp = tmp->next) { chanrec = tmp->data; - server_redirect_event((SERVER_REC *) server, chanrec->name, 4, + server_redirect_event((SERVER_REC *) server, chanrec->name, 2, "event 403", "chanquery mode abort", 1, "event 349", "chanquery eban end", 1, "event 348", "chanquery eban", 1, NULL); @@ -244,7 +244,7 @@ static void channel_send_query(IRC_SERVER_REC *server, int query) for (tmp = chans; tmp != NULL; tmp = tmp->next) { chanrec = tmp->data; - server_redirect_event((SERVER_REC *) server, chanrec->name, 4, + server_redirect_event((SERVER_REC *) server, chanrec->name, 2, "event 403", "chanquery mode abort", 1, "event 347", "chanquery ilist end", 1, "event 346", "chanquery ilist", 1, NULL); diff --git a/src/irc/core/channels-setup.c b/src/irc/core/channels-setup.c index c8400d4e..2991a8bc 100644 --- a/src/irc/core/channels-setup.c +++ b/src/irc/core/channels-setup.c @@ -26,6 +26,7 @@ #include "nicklist.h" #include "irc-server.h" #include "server-setup.h" +#include "special-vars.h" #include "lib-config/iconfig.h" #include "settings.h" @@ -33,30 +34,52 @@ GSList *setupchannels; #define ircnet_match(a, b) \ - ((a[0]) == '\0' || (b != NULL && g_strcasecmp(a, b) == 0)) + ((a) == NULL || (a[0]) == '\0' || (b != NULL && g_strcasecmp(a, b) == 0)) -SETUP_CHANNEL_REC *channels_setup_find(const char *channel, IRC_SERVER_REC *server) +static void channel_config_add(SETUP_CHANNEL_REC *channel) { - GSList *tmp; + CONFIG_NODE *node; - g_return_val_if_fail(channel != NULL, NULL); - g_return_val_if_fail(server != NULL, NULL); + node = iconfig_node_traverse("(channels", TRUE); + node = config_node_section(node, NULL, NODE_TYPE_BLOCK); + + config_node_set_str(node, "name", channel->name); + config_node_set_str(node, "ircnet", channel->ircnet); + if (channel->autojoin) + config_node_set_bool(node, "autojoin", TRUE); + config_node_set_str(node, "password", channel->password); + config_node_set_str(node, "botmasks", channel->botmasks); + config_node_set_str(node, "autosendcmd", channel->autosendcmd); + config_node_set_str(node, "background", channel->background); + config_node_set_str(node, "font", channel->font); +} - for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) { - SETUP_CHANNEL_REC *rec = tmp->data; +static void channel_config_remove(SETUP_CHANNEL_REC *channel) +{ + CONFIG_NODE *node; - if (g_strcasecmp(rec->name, channel) == 0 && - ircnet_match(rec->ircnet, server->connrec->ircnet)) - return rec; + node = iconfig_node_traverse("channels", FALSE); + if (node != NULL) config_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); - return NULL; + channel_config_add(channel); } void channels_setup_destroy(SETUP_CHANNEL_REC *channel) { g_return_if_fail(channel != NULL); + channel_config_remove(channel); + setupchannels = g_slist_remove(setupchannels, channel); + g_free(channel->name); g_free(channel->ircnet); g_free_not_null(channel->password); @@ -65,16 +88,30 @@ void channels_setup_destroy(SETUP_CHANNEL_REC *channel) g_free_not_null(channel->background); g_free_not_null(channel->font); g_free(channel); +} - setupchannels = g_slist_remove(setupchannels, 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, *keys; + GString *chans; GSList *tmp; - int use_keys; g_return_if_fail(server != NULL); @@ -83,9 +120,6 @@ static void event_connected(IRC_SERVER_REC *server) /* join to the channels marked with autojoin in setup */ chans = g_string_new(NULL); - keys = g_string_new(NULL); - - use_keys = FALSE; for (tmp = setupchannels; tmp != NULL; tmp = tmp->next) { SETUP_CHANNEL_REC *rec = tmp->data; @@ -93,21 +127,14 @@ static void event_connected(IRC_SERVER_REC *server) continue; g_string_sprintfa(chans, "%s,", rec->name); - g_string_sprintfa(keys, "%s,", rec->password == NULL ? "x" : rec->password); - if (rec->password != 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); - channels_join(server, chans->str, TRUE); } g_string_free(chans, TRUE); - g_string_free(keys, TRUE); } /* channel wholist received: send the auto send command */ @@ -115,17 +142,17 @@ static void channel_wholist(CHANNEL_REC *channel) { SETUP_CHANNEL_REC *rec; NICK_REC *nick; - char **bots, **bot, *str; + char **bots, **bot; g_return_if_fail(channel != NULL); - rec = channels_setup_find(channel->name, channel->server); + 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. */ - signal_emit("send command", 3, rec->autosendcmd, channel->server, channel); + eval_special_string(rec->autosendcmd, "", channel->server, channel); } /* find first available bot.. */ @@ -136,9 +163,7 @@ static void channel_wholist(CHANNEL_REC *channel) continue; /* got one! */ - str = g_strdup_printf(rec->autosendcmd, nick->nick); - signal_emit("send command", 3, str, channel->server, channel); - g_free(str); + eval_special_string(rec->autosendcmd, nick->nick, channel->server, channel); break; } g_strfreev(bots); diff --git a/src/irc/core/channels-setup.h b/src/irc/core/channels-setup.h index 0556019a..9cd2472c 100644 --- a/src/irc/core/channels-setup.h +++ b/src/irc/core/channels-setup.h @@ -20,8 +20,9 @@ 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, IRC_SERVER_REC *server); +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 index 9f01d57a..4c50ab7b 100644 --- a/src/irc/core/channels.c +++ b/src/irc/core/channels.c @@ -156,10 +156,12 @@ char *channel_get_mode(CHANNEL_REC *channel) void channels_join(IRC_SERVER_REC *server, const char *data, int automatic) { + SETUP_CHANNEL_REC *schannel; CHANNEL_REC *chanrec; GString *outchans, *outkeys; char *params, *channels, *keys; char **chanlist, **keylist, **tmp, **tmpkey, *channel; + int use_keys; g_return_if_fail(data != NULL); if (server == NULL || !server->connected || !irc_server_check(server)) @@ -174,19 +176,24 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic) 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) { - /* already joined this channel */ - signal_emit("gui channel open", 1, chanrec); - } else { + if (chanrec == NULL) { + schannel = channels_setup_find(channel, server->connrec->ircnet); + g_string_sprintfa(outchans, "%s,", channel); - if (*keys != '\0') + if (schannel == NULL || schannel->password == NULL) g_string_sprintfa(outkeys, "%s,", get_join_key(*tmpkey)); + else { + /* get password from setup record */ + use_keys = TRUE; + g_string_sprintfa(outkeys, "%s,", schannel->password); + } channel_create(server, channel + (channel[0] == '!' && channel[1] == '!'), automatic); } @@ -197,7 +204,7 @@ void channels_join(IRC_SERVER_REC *server, const char *data, int automatic) } if (outchans->len > 0) { - irc_send_cmdv(server, *keys == '\0' ? "JOIN %s" : "JOIN %s %s", + irc_send_cmdv(server, use_keys ? "JOIN %s %s" : "JOIN %s", outchans->str, outkeys->str); } diff --git a/src/irc/core/channels.h b/src/irc/core/channels.h index 5cf53aa5..03ae1a6e 100644 --- a/src/irc/core/channels.h +++ b/src/irc/core/channels.h @@ -41,6 +41,7 @@ typedef struct { 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/irc/core/ctcp.c b/src/irc/core/ctcp.c index 5265c2be..55df8098 100644 --- a/src/irc/core/ctcp.c +++ b/src/irc/core/ctcp.c @@ -52,7 +52,7 @@ void ctcp_send_reply(IRC_SERVER_REC *server, const char *data) if (g_slist_length(server->ctcpqueue) < settings_get_int("max_ctcp_queue")) { /* Add to first in idle queue */ - tag = server_idle_add_first(server, data, NULL, 0, NULL); + tag = server_idle_add(server, data, NULL, 0, NULL); server->ctcpqueue = g_slist_append(server->ctcpqueue, GINT_TO_POINTER(tag)); } } diff --git a/src/irc/core/ignore.c b/src/irc/core/ignore.c index ab817ae1..274a8646 100644 --- a/src/irc/core/ignore.c +++ b/src/irc/core/ignore.c @@ -251,6 +251,7 @@ static void read_ignores(void) IGNORE_REC *rec; CONFIG_NODE *node; GSList *tmp; + char *str; while (ignores != NULL) ignore_destroy(ignores->data); @@ -269,8 +270,8 @@ static void read_ignores(void) rec->mask = g_strdup(config_node_get_str(node, "mask", NULL)); rec->pattern = g_strdup(config_node_get_str(node, "pattern", NULL)); - rec->level = level2bits(config_node_get_str(node, "level", 0)); - rec->except_level = level2bits(config_node_get_str(node, "except_level", 0)); + rec->level = level2bits(config_node_get_str(node, "level", "")); + rec->except_level = level2bits(config_node_get_str(node, "except_level", "")); rec->regexp = config_node_get_bool(node, "regexp", FALSE); rec->fullword = config_node_get_bool(node, "fullword", FALSE); diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c index 8fcd4259..b06d9371 100644 --- a/src/irc/core/irc-commands.c +++ b/src/irc/core/irc-commands.c @@ -19,6 +19,7 @@ */ #include "module.h" +#include "network.h" #include "commands.h" #include "misc.h" #include "special-vars.h" @@ -46,23 +47,35 @@ static IRC_SERVER_REC *connect_server(const char *data) { IRC_SERVER_CONNECT_REC *conn; IRC_SERVER_REC *server; - char *params, *addr, *portstr, *password, *nick; - int port; + char *params, *args, *ircnet, *host, *addr, *portstr, *password, *nick; g_return_val_if_fail(data != NULL, NULL); - params = cmd_get_params(data, 4, &addr, &portstr, &password, &nick); + args = "ircnet host"; + params = cmd_get_params(data, 7 | PARAM_FLAG_MULTIARGS, + &args, &ircnet, &host, &addr, + &portstr, &password, &nick); + if (*addr == '+') addr++; if (*addr == '\0') return NULL; if (strcmp(password, "-") == 0) *password = '\0'; - port = 6667; - if (*portstr != '\0') - sscanf(portstr, "%d", &port); - /* connect to server */ - conn = irc_server_create_conn(addr, port, password, nick); + conn = irc_server_create_conn(addr, atoi(portstr), password, nick); + if (*ircnet != '\0') { + g_free_not_null(conn->ircnet); + conn->ircnet = g_strdup(ircnet); + } + if (*host != '\0') { + IPADDR ip; + + if (net_gethostname(host, &ip) == 0) { + if (conn->own_ip == NULL) + conn->own_ip = g_new(IPADDR, 1); + memcpy(conn->own_ip, &ip, sizeof(IPADDR)); + } + } server = irc_server_connect(conn); g_free(params); @@ -92,6 +105,9 @@ static void cmd_disconnect(const char *data, IRC_SERVER_REC *server) if (server == NULL || !irc_server_check(server)) cmd_param_error(CMDERR_NOT_CONNECTED); + if (*msg == '\0') msg = (char *) settings_get_str("quit_message"); + signal_emit("server quit", 2, server, msg); + ircserver = (IRC_SERVER_REC *) server; if (ircserver->handle != -1 && ircserver->buffer != NULL) { /* flush transmit queue */ @@ -100,8 +116,6 @@ static void cmd_disconnect(const char *data, IRC_SERVER_REC *server) ircserver->cmdqueue = NULL; ircserver->cmdcount = 0; - /* then send quit message */ - if (*msg == '\0') msg = (char *) settings_get_str("default_quit_message"); irc_send_cmdv(ircserver, "QUIT :%s", msg); } g_free(params); @@ -111,12 +125,20 @@ static void cmd_disconnect(const char *data, IRC_SERVER_REC *server) static void cmd_server(const char *data, IRC_SERVER_REC *server) { + char *params, *args, *ircnetarg, *hostarg, *addr; char *channels, *away_reason, *usermode, *ircnet; + int no_old_server; g_return_if_fail(data != NULL); - if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); - if (*data == '+' || server == NULL) { + args = "ircnet host"; + params = cmd_get_params(data, 4 | PARAM_FLAG_MULTIARGS, + &args, &ircnetarg, &hostarg, &addr); + if (*addr == '\0' || strcmp(addr, "+") == 0) + cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); + + no_old_server = server == NULL; + if (*addr == '+' || server == NULL) { channels = away_reason = usermode = ircnet = NULL; } else { ircnet = g_strdup(server->connrec->ircnet); @@ -129,20 +151,21 @@ static void cmd_server(const char *data, IRC_SERVER_REC *server) cmd_disconnect("* Changing server", server); } - server = connect_server(data + (*data == '+' ? 1 : 0)); - if (*data == '+' || server == NULL || + server = connect_server(data); + if (*addr == '+' || server == NULL || (ircnet != NULL && server->connrec->ircnet != NULL && g_strcasecmp(ircnet, server->connrec->ircnet) != 0)) { g_free_not_null(channels); g_free_not_null(usermode); g_free_not_null(away_reason); - } else if (server != NULL) { + } else if (server != NULL && !no_old_server) { server->connrec->reconnection = TRUE; server->connrec->channels = channels; server->connrec->usermode = usermode; server->connrec->away_reason = away_reason; } g_free_not_null(ircnet); + g_free(params); } static void cmd_quit(const char *data) @@ -154,7 +177,7 @@ static void cmd_quit(const char *data) g_return_if_fail(data != NULL); quitmsg = *data != '\0' ? data : - settings_get_str("default_quit_message"); + settings_get_str("quit_message"); /* disconnect from every server */ for (tmp = servers; tmp != NULL; tmp = next) { @@ -646,7 +669,7 @@ static void cmd_knockout(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *i if (is_numeric(data, ' ')) { /* first argument is the timeout */ params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &timeoutstr, &nick, &reason); - timeleft = atol(timeoutstr); + timeleft = atoi(timeoutstr); } else { timeleft = 0; params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &nick, &reason); @@ -749,7 +772,7 @@ void irc_commands_init(void) { tmpstr = g_string_new(NULL); - settings_add_str("misc", "default_quit_message", "leaving"); + settings_add_str("misc", "quit_message", "leaving"); settings_add_int("misc", "knockout_time", 300); knockout_tag = g_timeout_add(KNOCKOUT_TIMECHECK, (GSourceFunc) knockout_timeout, NULL); diff --git a/src/irc/core/irc-log.c b/src/irc/core/irc-log.c index 3c9ef760..9871ee64 100644 --- a/src/irc/core/irc-log.c +++ b/src/irc/core/irc-log.c @@ -90,8 +90,8 @@ static void event_unaway(const char *data, IRC_SERVER_REC *server) void irc_log_init(void) { - settings_add_str("misc", "awaylog_file", "~/.irssi/away.log"); - settings_add_str("misc", "awaylog_level", "msgs hilight"); + settings_add_str("log", "awaylog_file", "~/.irssi/away.log"); + settings_add_str("log", "awaylog_level", "msgs hilight"); signal_add("print text stripped", (SIGNAL_FUNC) sig_log); signal_add("event 306", (SIGNAL_FUNC) event_away); diff --git a/src/irc/core/irc-server.c b/src/irc/core/irc-server.c index 2f9e9fb1..a21d9a1f 100644 --- a/src/irc/core/irc-server.c +++ b/src/irc/core/irc-server.c @@ -335,7 +335,7 @@ static int sig_set_user_mode(IRC_SERVER_REC *server) if (g_slist_find(servers, server) == NULL) return 0; /* got disconnected */ - mode = settings_get_str("default_user_mode"); + mode = settings_get_str("usermode"); newmode = server->usermode == NULL ? NULL : modes_join(server->usermode, mode); if (server->usermode == NULL || strcmp(newmode, server->usermode) != 0) @@ -369,7 +369,7 @@ static void event_connected(const char *data, IRC_SERVER_REC *server, const char if (!server->connrec->reconnection) { /* wait a second and then send the user mode */ - mode = settings_get_str("default_user_mode"); + mode = settings_get_str("usermode"); if (*mode != '\0') g_timeout_add(1000, (GSourceFunc) sig_set_user_mode, server); } @@ -414,7 +414,7 @@ static void event_empty(void) void irc_servers_init(void) { - settings_add_str("misc", "default_user_mode", DEFAULT_USER_MODE); + 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); diff --git a/src/irc/core/irc-server.h b/src/irc/core/irc-server.h index 21e3e73c..11172bea 100644 --- a/src/irc/core/irc-server.h +++ b/src/irc/core/irc-server.h @@ -120,6 +120,7 @@ typedef struct { GSList *lastmsgs; /* List of nicks who last send you msg */ 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 */ diff --git a/src/irc/core/irc.c b/src/irc/core/irc.c index c25f32b6..4e37d474 100644 --- a/src/irc/core/irc.c +++ b/src/irc/core/irc.c @@ -48,6 +48,7 @@ static void cmd_send(IRC_SERVER_REC *server, const char *cmd, int send_now, int /* just check that we don't send any longer commands than 512 bytes.. */ strncpy(str, cmd, 510); len = strlen(cmd); + if (len > 510) len = 510; str[len++] = 13; str[len++] = 10; str[len] = '\0'; ptr = str; diff --git a/src/irc/core/ircnet-setup.c b/src/irc/core/ircnet-setup.c index 0e19f3a5..8296a7e8 100644 --- a/src/irc/core/ircnet-setup.c +++ b/src/irc/core/ircnet-setup.c @@ -104,6 +104,7 @@ static void read_ircnets(void) void ircnets_setup_init(void) { + read_ircnets(); signal_add("setup reread", (SIGNAL_FUNC) read_ircnets); } diff --git a/src/irc/core/massjoin.c b/src/irc/core/massjoin.c index 3cd0d31a..51831a1a 100644 --- a/src/irc/core/massjoin.c +++ b/src/irc/core/massjoin.c @@ -20,7 +20,7 @@ #include "module.h" #include "signals.h" -#include "common-setup.h" +#include "settings.h" #include "channels.h" #include "irc.h" @@ -28,6 +28,7 @@ #include "irc-server.h" static int massjoin_tag; +static int massjoin_max_joins; /* Massjoin support - really useful when trying to do things (like op/deop) to people after netjoins. It sends @@ -210,7 +211,7 @@ static void server_check_massjoins(IRC_SERVER_REC *server, time_t max) continue; if (rec->massjoin_start < max || /* We've waited long enough */ - rec->massjoins-5 < rec->last_massjoins) { /* Less than 5 joins since last check */ + rec->massjoins-massjoin_max_joins < rec->last_massjoins) { /* Less than x joins since last check */ /* send them */ massjoin_send(rec); } else { @@ -226,21 +227,30 @@ static int sig_massjoin_timeout(void) GSList *tmp; time_t max; - max = time(NULL)-MAX_MASSJOIN_WAIT; + max = time(NULL)-settings_get_int("massjoin_max_wait"); for (tmp = servers; tmp != NULL; tmp = tmp->next) server_check_massjoins(tmp->data, max); return 1; } +static void read_settings(void) +{ + massjoin_max_joins = settings_get_int("massjoin_max_joins"); +} + void massjoin_init(void) { + settings_add_int("misc", "massjoin_max_wait", 5000); + settings_add_int("misc", "massjoin_max_joins", 3); massjoin_tag = g_timeout_add(1000, (GSourceFunc) sig_massjoin_timeout, NULL); + read_settings(); signal_add("event join", (SIGNAL_FUNC) event_join); signal_add("event part", (SIGNAL_FUNC) event_part); signal_add("event kick", (SIGNAL_FUNC) event_kick); signal_add("event quit", (SIGNAL_FUNC) event_quit); + signal_add("setup changed", (SIGNAL_FUNC) read_settings); } void massjoin_deinit(void) @@ -251,4 +261,5 @@ void massjoin_deinit(void) signal_remove("event part", (SIGNAL_FUNC) event_part); signal_remove("event kick", (SIGNAL_FUNC) event_kick); signal_remove("event quit", (SIGNAL_FUNC) event_quit); + signal_remove("setup changed", (SIGNAL_FUNC) read_settings); } diff --git a/src/irc/core/modes.c b/src/irc/core/modes.c index 9b5c8027..bd31d3ab 100644 --- a/src/irc/core/modes.c +++ b/src/irc/core/modes.c @@ -103,7 +103,7 @@ void parse_channel_modes(CHANNEL_REC *channel, const char *setby, const char *mo ptr = cmd_get_param(&modestr); if (*ptr == '\0') break; - if (strcmp(channel->server->nick, ptr) == 0) + if (g_strcasecmp(channel->server->nick, ptr) == 0) channel->chanop = type == '+' ? TRUE : FALSE; nick_mode_change(channel, ptr, '@', type == '+'); break; @@ -297,6 +297,9 @@ void channel_set_singlemode(IRC_SERVER_REC *server, const char *channel, const c nicklist = g_strsplit(nicks, " ", -1); for (nick = nicklist; *nick != NULL; nick++) { + if (*nick == '\0') + continue; + if (num == 0) { g_string_sprintf(str, "MODE %s %s", channel, mode); @@ -373,28 +376,94 @@ void channel_set_mode(IRC_SERVER_REC *server, const char *channel, const char *m g_free(orig); } -static void cmd_op(gchar *data, IRC_SERVER_REC *server, WI_IRC_REC *item) +static char *get_nicks(WI_IRC_REC *item, const char *data, int op, int voice) +{ + GString *str; + GSList *nicks, *tmp; + char **matches, **match, *ret; + + str = g_string_new(NULL); + matches = g_strsplit(data, " ", -1); + for (match = matches; *match != NULL; match++) { + if (strchr(*match, '*') == NULL && strchr(*match, '?') == NULL) { + /* no wildcards */ + g_string_sprintfa(str, "%s ", *match); + continue; + } + + /* wildcards */ + nicks = nicklist_find_multiple((CHANNEL_REC *) item, data); + for (tmp = nicks; tmp != NULL; tmp = tmp->next) { + NICK_REC *rec = tmp->data; + + if ((op == 1 && !rec->op) || (op == 0 && rec->op) || + (voice == 1 && !rec->voice) || (voice == 0 && rec->voice)) + continue; + + if (g_strcasecmp(rec->nick, item->server->nick) == 0) + continue; + + g_string_sprintfa(str, "%s ", rec->nick); + } + g_slist_free(nicks); + } + + g_string_truncate(str, str->len-1); + ret = str->str; + g_string_free(str, FALSE); + return ret; +} + +static void cmd_op(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - if (!irc_item_channel(item)) return; - channel_set_singlemode(server, item->name, data, "+o"); + char *nicks; + + if (!irc_item_channel(item)) + return; + + nicks = get_nicks(item, data, 0, -1); + if (*nicks != '\0') + channel_set_singlemode(server, item->name, nicks, "+o"); + g_free(nicks); } static void cmd_deop(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - if (!irc_item_channel(item)) return; - channel_set_singlemode(server, item->name, data, "-o"); + char *nicks; + + if (!irc_item_channel(item)) + return; + + nicks = get_nicks(item, data, 1, -1); + if (*nicks != '\0') + channel_set_singlemode(server, item->name, nicks, "-o"); + g_free(nicks); } static void cmd_voice(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - if (!irc_item_channel(item)) return; - channel_set_singlemode(server, item->name, data, "+v"); + char *nicks; + + if (!irc_item_channel(item)) + return; + + nicks = get_nicks(item, data, 0, 0); + if (*nicks != '\0') + channel_set_singlemode(server, item->name, nicks, "+v"); + g_free(nicks); } static void cmd_devoice(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { - if (!irc_item_channel(item)) return; - channel_set_singlemode(server, item->name, data, "-v"); + char *nicks; + + if (!irc_item_channel(item)) + return; + + nicks = get_nicks(item, data, 0, 1); + if (*nicks != '\0') + channel_set_singlemode(server, item->name, nicks, "-v"); + g_free(nicks); } static void cmd_mode(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) diff --git a/src/irc/core/netsplit.c b/src/irc/core/netsplit.c index b455f740..c5a4ff49 100644 --- a/src/irc/core/netsplit.c +++ b/src/irc/core/netsplit.c @@ -29,6 +29,46 @@ static int split_tag; +static NETSPLIT_SERVER_REC *netsplit_server_find(IRC_SERVER_REC *server, const char *servername, const char *destserver) +{ + GSList *tmp; + + for (tmp = server->split_servers; tmp != NULL; tmp = tmp->next) { + NETSPLIT_SERVER_REC *rec = tmp->data; + + if (g_strcasecmp(rec->server, servername) == 0 && + g_strcasecmp(rec->destserver, destserver) == 0) + return rec; + } + + return NULL; +} + +static NETSPLIT_SERVER_REC *netsplit_server_create(IRC_SERVER_REC *server, const char *servername, const char *destserver) +{ + NETSPLIT_SERVER_REC *rec; + + rec = netsplit_server_find(server, servername, destserver); + if (rec != NULL) return rec; + + rec = g_new0(NETSPLIT_SERVER_REC, 1); + rec->server = g_strdup(servername); + rec->destserver = g_strdup(destserver); + + server->split_servers = g_slist_append(server->split_servers, rec); + signal_emit("netsplit new server", 1, rec); + return rec; +} + +static void netsplit_destroy_server(IRC_SERVER_REC *server, NETSPLIT_SERVER_REC *rec) +{ + server->split_servers = g_slist_remove(server->split_servers, rec); + + g_free(rec->server); + g_free(rec->destserver); + g_free(rec); +} + static NETSPLIT_REC *netsplit_add(IRC_SERVER_REC *server, const char *nick, const char *address, const char *servers) { NETSPLIT_REC *rec; @@ -41,6 +81,7 @@ static NETSPLIT_REC *netsplit_add(IRC_SERVER_REC *server, const char *nick, cons g_return_val_if_fail(nick != NULL, NULL); g_return_val_if_fail(address != NULL, NULL); + /* get splitted servers */ dupservers = g_strdup(servers); p = strchr(dupservers, ' '); if (p == NULL) { @@ -54,9 +95,8 @@ static NETSPLIT_REC *netsplit_add(IRC_SERVER_REC *server, const char *nick, cons rec->address = g_strdup(address); rec->destroy = time(NULL)+NETSPLIT_MAX_REMEMBER; - /* get splitted servers */ - rec->server = g_strdup(dupservers); - rec->destserver = g_strdup(p); + rec->server = netsplit_server_create(server, dupservers, p); + rec->server->count++; g_free(dupservers); /* copy the channel nick records.. */ @@ -75,11 +115,12 @@ static NETSPLIT_REC *netsplit_add(IRC_SERVER_REC *server, const char *nick, cons } g_hash_table_insert(server->splits, rec->nick, rec); + signal_emit("netsplit add", 1, rec); return rec; } -static void netsplit_destroy(NETSPLIT_REC *rec) +static void netsplit_destroy(IRC_SERVER_REC *server, NETSPLIT_REC *rec) { GSList *tmp; @@ -93,16 +134,17 @@ static void netsplit_destroy(NETSPLIT_REC *rec) g_free(rec); } - g_free(rec->server); - g_free(rec->destserver); + if (--rec->server->count == 0) + netsplit_destroy_server(server, rec->server); + g_free(rec->nick); g_free(rec->address); g_free(rec); } -static void netsplit_destroy_hash(gpointer key, NETSPLIT_REC *rec) +static void netsplit_destroy_hash(void *key, NETSPLIT_REC *rec, IRC_SERVER_REC *server) { - netsplit_destroy(rec); + netsplit_destroy(server, rec); } NETSPLIT_REC *netsplit_find(IRC_SERVER_REC *server, const char *nick, const char *address) @@ -136,13 +178,15 @@ NICK_REC *netsplit_find_channel(IRC_SERVER_REC *server, const char *nick, const return NULL; } -static int is_split(const char *msg) +int quitmsg_is_split(const char *msg) { char *params, *host1, *host2, *p; int ok; g_return_val_if_fail(msg != NULL, FALSE); + if (msg[strlen(msg)-1] == ' ') msg[strlen(msg)-1] = '\0'; /*FIXME: remove - for debugging!*/ + /* must have only two words */ p = strchr(msg, ' '); if (p == NULL || strchr(p+1, ' ') != NULL) return FALSE; @@ -171,19 +215,19 @@ static int is_split(const char *msg) return ok; } -static void split_set_timeout(gpointer key, NETSPLIT_REC *rec, NETSPLIT_REC *orig) +static void split_set_timeout(void *key, NETSPLIT_REC *rec, NETSPLIT_REC *orig) { if (rec == orig) { /* original nick, destroy it in a few seconds.. */ rec->destroy = time(NULL)+4; - } else if (g_strcasecmp(rec->server, orig->server) == 0 && - g_strcasecmp(rec->destserver, orig->destserver) == 0) { + } else if (g_strcasecmp(rec->server->server, orig->server->server) == 0 && + g_strcasecmp(rec->server->destserver, orig->server->destserver) == 0) { /* same servers -> split over -> destroy old records sooner.. */ rec->destroy = time(NULL)+60; } } -static void event_join(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar *address) +static void event_join(const char *data, IRC_SERVER_REC *server, const char *nick, const char *address) { NETSPLIT_REC *rec; @@ -202,7 +246,7 @@ static void event_join(gchar *data, IRC_SERVER_REC *server, gchar *nick, gchar * } else { /* back from different address.. just destroy it. */ g_hash_table_remove(server->splits, rec->nick); - netsplit_destroy(rec); + netsplit_destroy(server, rec); } } @@ -211,7 +255,7 @@ static void event_quit(const char *data, IRC_SERVER_REC *server, const char *nic g_return_if_fail(data != NULL); if (*data == ':') data++; - if (g_strcasecmp(nick, server->nick) != 0 && is_split(data)) { + if (g_strcasecmp(nick, server->nick) != 0 && quitmsg_is_split(data)) { /* netsplit! */ netsplit_add(server, nick, address, data); } @@ -221,17 +265,17 @@ static void sig_disconnected(IRC_SERVER_REC *server) { g_return_if_fail(server != NULL); - g_hash_table_foreach(server->splits, (GHFunc) netsplit_destroy_hash, NULL); + g_hash_table_foreach(server->splits, (GHFunc) netsplit_destroy_hash, server); g_hash_table_destroy(server->splits); } -static int split_server_check(gpointer key, NETSPLIT_REC *rec, IRC_SERVER_REC *server) +static int split_server_check(void *key, NETSPLIT_REC *rec, IRC_SERVER_REC *server) { /* Check if this split record is too old.. */ if (rec->destroy > time(NULL)) return FALSE; - netsplit_destroy(rec); + netsplit_destroy(server, rec); return TRUE; } diff --git a/src/irc/core/netsplit.h b/src/irc/core/netsplit.h index c2d221da..c95b5c6f 100644 --- a/src/irc/core/netsplit.h +++ b/src/irc/core/netsplit.h @@ -4,10 +4,16 @@ #include "nicklist.h" typedef struct { - char *nick; - char *address; char *server; char *destserver; + int count; +} NETSPLIT_SERVER_REC; + +typedef struct { + NETSPLIT_SERVER_REC *server; + + char *nick; + char *address; GSList *channels; time_t destroy; @@ -24,4 +30,6 @@ void netsplit_deinit(void); NETSPLIT_REC *netsplit_find(IRC_SERVER_REC *server, const char *nick, const char *address); NICK_REC *netsplit_find_channel(IRC_SERVER_REC *server, const char *nick, const char *address, const char *channel); +int quitmsg_is_split(const char *msg); + #endif diff --git a/src/irc/core/nicklist.c b/src/irc/core/nicklist.c index a275d43e..b8947ee6 100644 --- a/src/irc/core/nicklist.c +++ b/src/irc/core/nicklist.c @@ -87,6 +87,22 @@ static NICK_REC *nicklist_find_wildcards(CHANNEL_REC *channel, const char *mask) 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 == NULL ? "" : 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) { @@ -230,7 +246,7 @@ static void event_names_list(const char *data, IRC_SERVER_REC *server) while (*names != '\0' && *names != ' ') names++; if (*names != '\0') *names++ = '\0'; - if (*ptr == '@' && strcmp(server->nick, ptr+1) == 0) + if (*ptr == '@' && g_strcasecmp(server->nick, ptr+1) == 0) chanrec->chanop = TRUE; nicklist_insert(chanrec, ptr+isnickflag(*ptr), *ptr == '@', *ptr == '+', FALSE); @@ -390,7 +406,8 @@ static void event_nick_in_use(const char *data, IRC_SERVER_REC *server) } /* nick already in use - need to change it .. */ - if (strcmp(server->nick, server->connrec->nick) == 0) { + 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); diff --git a/src/irc/core/nicklist.h b/src/irc/core/nicklist.h index 8e83e97f..b5250d18 100644 --- a/src/irc/core/nicklist.h +++ b/src/irc/core/nicklist.h @@ -25,6 +25,8 @@ NICK_REC *nicklist_insert(CHANNEL_REC *channel, const char *nick, int op, int vo 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, ... */ diff --git a/src/irc/core/server-reconnect.c b/src/irc/core/server-reconnect.c index a00b32cf..3e1b993f 100644 --- a/src/irc/core/server-reconnect.c +++ b/src/irc/core/server-reconnect.c @@ -85,7 +85,7 @@ static int server_reconnect_timeout(void) static void sserver_connect(SETUP_SERVER_REC *rec, IRC_SERVER_CONNECT_REC *conn) { - conn->address = g_strdup(rec->server); + conn->address = g_strdup(rec->address); conn->port = rec->port; conn->password = rec->password == NULL ? NULL : g_strdup(rec->password); @@ -143,7 +143,6 @@ static void sig_reconnect(IRC_SERVER_REC *server) return; conn = g_new0(IRC_SERVER_CONNECT_REC, 1); - conn->reconnection = TRUE; server_connect_copy_skeleton(conn, server->connrec); /* save the server status */ @@ -152,6 +151,7 @@ static void sig_reconnect(IRC_SERVER_REC *server) 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); @@ -213,7 +213,7 @@ static void sig_reconnect(IRC_SERVER_REC *server) for (tmp = setupservers; tmp != NULL; ) { SETUP_SERVER_REC *rec = tmp->data; - if (!found && g_strcasecmp(rec->server, server->connrec->address) == 0 && + if (!found && g_strcasecmp(rec->address, server->connrec->address) == 0 && server->connrec->port == rec->port) found = TRUE; else if (found && rec->ircnet != NULL && g_strcasecmp(conn->ircnet, rec->ircnet) == 0) { @@ -286,24 +286,36 @@ static RECONNECT_REC *reconnect_find_tag(int tag) } /* Try to reconnect immediately */ -static void cmd_reconnect(const char *data) +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; - rec = sscanf(data, "%d", &tag) == 1 && tag > 0 ? - reconnect_find_tag(tag) : NULL; + 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(rec->conn); + irc_server_connect(conn); } } diff --git a/src/irc/core/server-setup.c b/src/irc/core/server-setup.c index f56d839f..62c856cb 100644 --- a/src/irc/core/server-setup.c +++ b/src/irc/core/server-setup.c @@ -74,7 +74,7 @@ create_addr_conn(const char *address, int port, const char *password, conn->realname = g_strdup(settings_get_str("real_name")); /* proxy settings */ - if (settings_get_bool("toggle_use_ircproxy")) { + 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")); @@ -91,6 +91,25 @@ create_addr_conn(const char *address, int port, const char *password, sserver = server_setup_find(address, -1); if (sserver == NULL) return conn; + if (sserver->own_ip != NULL) { + /* use already resolved IP */ + if (conn->own_ip == NULL) + conn->own_ip = g_new(IPADDR, 1); + memcpy(conn->own_ip, sserver->own_ip, sizeof(IPADDR)); + } else if (sserver->own_host != NULL) { + /* resolve the IP and use it */ + IPADDR ip; + + if (net_gethostname(sserver->own_host, &ip) == 0) { + if (conn->own_ip == NULL) + conn->own_ip = g_new(IPADDR, 1); + memcpy(conn->own_ip, &ip, sizeof(IPADDR)); + + sserver->own_ip = g_new(IPADDR, 1); + memcpy(sserver->own_ip, &ip, sizeof(IPADDR)); + } + } + sserver->last_connect = time(NULL); if (sserver->ircnet) conn->ircnet = g_strdup(sserver->ircnet); @@ -151,7 +170,7 @@ irc_server_create_conn(const char *dest, int port, const char *password, const c continue; if (n == 1 || !rec->last_failed || rec->last_connect < now-FAILED_RECONNECT_WAIT) - return create_addr_conn(rec->server, port, password, nick); + return create_addr_conn(rec->address, port, password, nick); } } @@ -168,7 +187,7 @@ SETUP_SERVER_REC *server_setup_find(const char *address, int port) for (tmp = setupservers; tmp != NULL; tmp = tmp->next) { SETUP_SERVER_REC *rec = tmp->data; - if (g_strcasecmp(rec->server, address) == 0 && + if (g_strcasecmp(rec->address, address) == 0 && (port == -1 || rec->port == port)) return rec; } @@ -223,19 +242,88 @@ static void init_userinfo(void) 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); + g_free(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); + + config_node_set_str(node, "address", rec->address); + config_node_set_str(node, "ircnet", rec->ircnet); + + config_node_set_int(node, "port", rec->port); + config_node_set_str(node, "password", rec->password); + config_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) config_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(rec->ircnet); + g_free(rec->address); + g_free(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_append(setupservers, rec); + } + + setupservers = g_slist_append(setupservers, rec); + setupserver_config_add(rec); } -static SETUP_SERVER_REC *setupserver_add(CONFIG_NODE *node) +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 *ircnet, *server; + char *server; int port; g_return_val_if_fail(node != NULL, NULL); - ircnet = config_node_get_str(node, "ircnet", NULL); - server = config_node_get_str(node, "server", NULL); - if (ircnet == NULL || server == NULL) return 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(server, port) != NULL) { @@ -245,28 +333,19 @@ static SETUP_SERVER_REC *setupserver_add(CONFIG_NODE *node) } rec = g_new0(SETUP_SERVER_REC, 1); - rec->ircnet = g_strdup(ircnet); - rec->server = g_strdup(server); - rec->password = g_strdup(config_node_get_str(node, "password", "")); + 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 setupserver_destroy(SETUP_SERVER_REC *rec) -{ - setupservers = g_slist_remove(setupservers, rec); - - g_free(rec->ircnet); - g_free(rec->server); - g_free(rec->password); - g_free(rec); -} - static void read_servers(void) { CONFIG_NODE *node; @@ -276,10 +355,10 @@ static void read_servers(void) setupserver_destroy(setupservers->data); /* Read servers */ - node = iconfig_node_traverse("(setupservers", FALSE); + node = iconfig_node_traverse("servers", FALSE); if (node != NULL) { for (tmp = node->value; tmp != NULL; tmp = tmp->next) - setupserver_add(tmp->data); + setupserver_add_node(tmp->data); } } @@ -290,14 +369,14 @@ void servers_setup_init(void) settings_add_int("server", "server_reconnect_time", 300); settings_add_str("server", "hostname", ""); - settings_add_bool("server", "toggle_skip_motd", FALSE); + 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", "toggle_use_ircproxy", FALSE); + 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"); diff --git a/src/irc/core/server-setup.h b/src/irc/core/server-setup.h index a3a3d4ff..5c893044 100644 --- a/src/irc/core/server-setup.h +++ b/src/irc/core/server-setup.h @@ -5,7 +5,7 @@ /* servers */ typedef struct { - char *server; + char *address; int port; char *ircnet; @@ -14,8 +14,8 @@ typedef struct { int max_cmds_at_once; /* override the default if > 0 */ int cmd_queue_speed; /* override the default if > 0 */ - char *own_address; /* address to use when connecting this server */ - IPADDR *own_ip; /* resolved own_address or full of zeros */ + 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; /* if last connection attempt failed */ @@ -31,6 +31,9 @@ extern gboolean source_host_ok; /* Use source_host_ip .. */ IRC_SERVER_CONNECT_REC * irc_server_create_conn(const char *dest, int port, const char *password, const char *nick); +void server_setup_add(SETUP_SERVER_REC *rec); +void server_setup_remove(SETUP_SERVER_REC *rec); + /* Find matching server from setup. Set port to -1 if you don't care about it */ SETUP_SERVER_REC *server_setup_find(const char *address, int port); -- cgit v1.2.3