summaryrefslogtreecommitdiff
path: root/src/irc
diff options
context:
space:
mode:
authorTimo Sirainen <cras@irssi.org>2000-05-04 10:32:42 +0000
committercras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564>2000-05-04 10:32:42 +0000
commitd3dc9a1307adc40425bf162f1f867a39e535f501 (patch)
treed3c92a8e431391d679ae5341cb4e865f00449761 /src/irc
parentbacfcb060c1b687f70db4d59797e1cbc8bfe0f62 (diff)
downloadirssi-d3dc9a1307adc40425bf162f1f867a39e535f501.zip
.. lots of changes ..
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@197 dbcabf3a-b0e7-0310-adc4-f8d773084564
Diffstat (limited to 'src/irc')
-rw-r--r--src/irc/core/bans.c17
-rw-r--r--src/irc/core/channel-events.c34
-rw-r--r--src/irc/core/channels-query.c4
-rw-r--r--src/irc/core/channels-setup.c85
-rw-r--r--src/irc/core/channels-setup.h3
-rw-r--r--src/irc/core/channels.c19
-rw-r--r--src/irc/core/channels.h1
-rw-r--r--src/irc/core/ctcp.c2
-rw-r--r--src/irc/core/ignore.c5
-rw-r--r--src/irc/core/irc-commands.c59
-rw-r--r--src/irc/core/irc-log.c4
-rw-r--r--src/irc/core/irc-server.c6
-rw-r--r--src/irc/core/irc-server.h1
-rw-r--r--src/irc/core/irc.c1
-rw-r--r--src/irc/core/ircnet-setup.c1
-rw-r--r--src/irc/core/massjoin.c17
-rw-r--r--src/irc/core/modes.c89
-rw-r--r--src/irc/core/netsplit.c80
-rw-r--r--src/irc/core/netsplit.h12
-rw-r--r--src/irc/core/nicklist.c21
-rw-r--r--src/irc/core/nicklist.h2
-rw-r--r--src/irc/core/server-reconnect.c26
-rw-r--r--src/irc/core/server-setup.c129
-rw-r--r--src/irc/core/server-setup.h9
-rw-r--r--src/irc/dcc/Makefile.am4
-rw-r--r--src/irc/dcc/dcc-chat.c2
-rw-r--r--src/irc/dcc/dcc-chat.h7
-rw-r--r--src/irc/dcc/dcc-files.c2
-rw-r--r--src/irc/dcc/dcc-files.h7
-rw-r--r--src/irc/dcc/dcc.c26
-rw-r--r--src/irc/flood/autoignore.c4
-rw-r--r--src/irc/flood/flood.c122
-rw-r--r--src/irc/notifylist/notify-commands.c2
-rw-r--r--src/irc/notifylist/notify-whois.c2
34 files changed, 596 insertions, 209 deletions
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);
diff --git a/src/irc/dcc/Makefile.am b/src/irc/dcc/Makefile.am
index b7cd30e9..6e2b68c7 100644
--- a/src/irc/dcc/Makefile.am
+++ b/src/irc/dcc/Makefile.am
@@ -9,6 +9,4 @@ libirc_dcc_la_SOURCES = \
dcc-files.c
noinst_HEADERS = \
- dcc.h \
- dcc-chat.h \
- dcc-files.h
+ dcc.h
diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c
index 5cddddfa..c01077d3 100644
--- a/src/irc/dcc/dcc-chat.c
+++ b/src/irc/dcc/dcc-chat.c
@@ -307,7 +307,7 @@ static void cmd_dcc_chat(gchar *data, IRC_SERVER_REC *server)
if (server == NULL || !server->connected)
cmd_return_error(CMDERR_NOT_CONNECTED);
- if (!net_getsockname(server->handle, &addr, NULL))
+ if (net_getsockname(server->handle, &addr, NULL) == -1)
cmd_return_error(CMDERR_GETSOCKNAME);
port = settings_get_int("dcc_port");
diff --git a/src/irc/dcc/dcc-chat.h b/src/irc/dcc/dcc-chat.h
deleted file mode 100644
index 9ae9503f..00000000
--- a/src/irc/dcc/dcc-chat.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __DCC_CHAT_H
-#define __DCC_CHAT_H
-
-void dcc_chat_init(void);
-void dcc_chat_deinit(void);
-
-#endif
diff --git a/src/irc/dcc/dcc-files.c b/src/irc/dcc/dcc-files.c
index 23b1cdce..da395196 100644
--- a/src/irc/dcc/dcc-files.c
+++ b/src/irc/dcc/dcc-files.c
@@ -432,7 +432,7 @@ static void dcc_send_init(DCC_REC *dcc)
g_source_remove(dcc->tagread);
close(dcc->handle);
- dcc->fastsend = settings_get_bool("toggle_dcc_fast_send");
+ dcc->fastsend = settings_get_bool("dcc_fast_send");
dcc->handle = handle;
memcpy(&dcc->addr, &addr, sizeof(IPADDR));
net_ip2host(&dcc->addr, dcc->addrstr);
diff --git a/src/irc/dcc/dcc-files.h b/src/irc/dcc/dcc-files.h
deleted file mode 100644
index 3d12ffc1..00000000
--- a/src/irc/dcc/dcc-files.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __DCC_FILES_H
-#define __DCC_FILES_H
-
-void dcc_files_init(void);
-void dcc_files_deinit(void);
-
-#endif
diff --git a/src/irc/dcc/dcc.c b/src/irc/dcc/dcc.c
index 41833744..1c02e65a 100644
--- a/src/irc/dcc/dcc.c
+++ b/src/irc/dcc/dcc.c
@@ -30,6 +30,12 @@
#include "dcc.h"
+void dcc_chat_init(void);
+void dcc_chat_deinit(void);
+
+void dcc_files_init(void);
+void dcc_files_deinit(void);
+
#define DCC_TYPES 5
static gchar *dcc_types[] =
@@ -55,7 +61,7 @@ DCC_REC *dcc_create(gint type, gint handle, gchar *nick, gchar *arg, IRC_SERVER_
dcc = g_new0(DCC_REC, 1);
dcc->type = type == DCC_TYPE_CHAT ? module_get_uniq_id("IRC", WI_IRC_DCC_CHAT) : -1;
- dcc->mirc_ctcp = settings_get_bool("toggle_dcc_mirc_ctcp");
+ dcc->mirc_ctcp = settings_get_bool("dcc_mirc_ctcp");
dcc->created = time(NULL);
dcc->chat = chat;
dcc->dcc_type = type;
@@ -307,7 +313,7 @@ static void dcc_ctcp_msg(gchar *data, IRC_SERVER_REC *server, gchar *sender, gch
case DCC_TYPE_GET:
cstr = settings_get_str("dcc_autoget_masks");
/* check that autoget masks match */
- if (settings_get_bool("toggle_dcc_autoget") && (*cstr == '\0' || irc_masks_match(cstr, sender, sendaddr)) &&
+ if (settings_get_bool("dcc_autoget") && (*cstr == '\0' || irc_masks_match(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)))
{
@@ -507,19 +513,19 @@ void dcc_init(void)
dcc_conns = NULL;
dcc_timeouttag = g_timeout_add(1000, (GSourceFunc) dcc_timeout_func, NULL);
- settings_add_bool("dcc", "toggle_dcc_autorename", FALSE);
- settings_add_bool("dcc", "toggle_dcc_autogete", FALSE);
+ settings_add_bool("dcc", "dcc_autorename", FALSE);
+ settings_add_bool("dcc", "dcc_autoget", FALSE);
settings_add_int("dcc", "dcc_max_autoget_size", 1000);
settings_add_str("dcc", "dcc_download_path", "~");
settings_add_int("dcc", "dcc_file_create_mode", 644);
settings_add_str("dcc", "dcc_autoget_masks", "");
settings_add_str("dcc", "dcc_autochat_masks", "");
- settings_add_bool("dcc", "toggle_dcc_fast_send", TRUE);
+ settings_add_bool("dcc", "dcc_fast_send", TRUE);
settings_add_str("dcc", "dcc_upload_path", "~");
- settings_add_bool("dcc", "toggle_dcc_mirc_ctcp", FALSE);
- settings_add_bool("dcc", "toggle_dcc_autodisplay_dialog", TRUE);
+ settings_add_bool("dcc", "dcc_mirc_ctcp", FALSE);
+ settings_add_bool("dcc", "dcc_autodisplay_dialog", TRUE);
settings_add_int("dcc", "dcc_block_size", 2048);
settings_add_int("dcc", "dcc_port", 0);
settings_add_int("dcc", "dcc_timeout", 300);
@@ -531,10 +537,16 @@ void dcc_init(void)
command_bind("dcc", NULL, (SIGNAL_FUNC) cmd_dcc);
command_bind("dcc close", NULL, (SIGNAL_FUNC) cmd_dcc_close);
signal_add("event 401", (SIGNAL_FUNC) event_no_such_nick);
+
+ dcc_chat_init();
+ dcc_files_init();
}
void dcc_deinit(void)
{
+ dcc_chat_deinit();
+ dcc_files_deinit();
+
signal_remove("server connected", (SIGNAL_FUNC) dcc_server_connected);
signal_remove("server disconnected", (SIGNAL_FUNC) dcc_server_disconnected);
signal_remove("ctcp reply dcc", (SIGNAL_FUNC) dcc_ctcp_reply);
diff --git a/src/irc/flood/autoignore.c b/src/irc/flood/autoignore.c
index 528ac618..da384dd9 100644
--- a/src/irc/flood/autoignore.c
+++ b/src/irc/flood/autoignore.c
@@ -217,11 +217,11 @@ int autoignore_remove(IRC_SERVER_REC *server, const char *mask, int level)
return FALSE;
}
-static void sig_flood(IRC_SERVER_REC *server, const char *nick, const char *host, const char *levelstr)
+static void sig_flood(IRC_SERVER_REC *server, const char *nick, const char *host, gpointer levelp)
{
int level, check_level;
- level = level2bits(levelstr);
+ level = GPOINTER_TO_INT(levelp);
check_level = level2bits(settings_get_str("autoignore_levels"));
if (level & check_level)
diff --git a/src/irc/flood/flood.c b/src/irc/flood/flood.c
index 5522243e..7fb4773d 100644
--- a/src/irc/flood/flood.c
+++ b/src/irc/flood/flood.c
@@ -1,8 +1,7 @@
/*
+ flood.c : Flood protection
- flood.c : Flood protection (see also ctcp.c)
-
- 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
@@ -32,36 +31,59 @@
#include "ignore.h"
typedef struct {
- char *nick;
+ char *target;
int level;
+
int msgcount;
+ time_t first;
+} FLOOD_ITEM_REC;
+
+typedef struct {
+ char *nick;
+ GSList *items;
} FLOOD_REC;
static int flood_tag;
-static int flood_max_msgs;
+static int flood_max_msgs, flood_timecheck;
-static int flood_hash_deinit(const char *key, FLOOD_REC *rec)
+static int flood_hash_deinit(const char *key, FLOOD_REC *flood, gpointer nowp)
{
+ GSList *tmp, *next;
+ time_t now;
+
g_return_val_if_fail(key != NULL, FALSE);
- g_return_val_if_fail(rec != NULL, FALSE);
+ g_return_val_if_fail(flood != NULL, FALSE);
+
+ now = (time_t) GPOINTER_TO_INT(nowp);
+ for (tmp = flood->items; tmp != NULL; tmp = next) {
+ FLOOD_ITEM_REC *rec = tmp->data;
- g_free(rec->nick);
- g_free(rec);
+ next = tmp->next;
+ if (now-rec->first >= flood_timecheck)
+ flood->items = g_slist_remove(flood->items, rec);
+ }
+
+ if (flood->items != NULL)
+ return FALSE;
+
+ g_free(flood->nick);
+ g_free(flood);
return TRUE;
}
-/* timeout function: flood protection */
static int flood_timeout(void)
{
MODULE_SERVER_REC *mserver;
GSList *tmp;
+ time_t now;
- /* remove everyone from flood list */
+ /* remove the old people from flood lists */
+ now = time(NULL);
for (tmp = servers; tmp != NULL; tmp = tmp->next) {
IRC_SERVER_REC *rec = tmp->data;
mserver = MODULE_DATA(rec);
- g_hash_table_foreach_remove(mserver->floodlist, (GHRFunc) flood_hash_deinit, NULL);
+ g_hash_table_foreach_remove(mserver->floodlist, (GHRFunc) flood_hash_deinit, GINT_TO_POINTER((int) now));
}
return 1;
}
@@ -88,6 +110,8 @@ static void flood_deinit_server(IRC_SERVER_REC *server)
mserver = MODULE_DATA(server);
if (mserver != NULL && mserver->floodlist != NULL) {
+ flood_timecheck = 0;
+
g_hash_table_freeze(mserver->floodlist);
g_hash_table_foreach(mserver->floodlist, (GHFunc) flood_hash_deinit, NULL);
g_hash_table_thaw(mserver->floodlist);
@@ -96,34 +120,55 @@ static void flood_deinit_server(IRC_SERVER_REC *server)
g_free(mserver);
}
+static FLOOD_ITEM_REC *flood_find(FLOOD_REC *flood, int level, const char *target)
+{
+ GSList *tmp;
+
+ for (tmp = flood->items; tmp != NULL; tmp = tmp->next) {
+ FLOOD_ITEM_REC *rec = tmp->data;
+
+ if (rec->level == level && g_strcasecmp(rec->target, target) == 0)
+ return rec;
+ }
+
+ return NULL;
+}
+
/* All messages should go through here.. */
static void flood_newmsg(IRC_SERVER_REC *server, int level, const char *nick, const char *host, const char *target)
{
MODULE_SERVER_REC *mserver;
- FLOOD_REC *rec;
- char *levelstr;
+ FLOOD_REC *flood;
+ FLOOD_ITEM_REC *rec;
g_return_if_fail(server != NULL);
g_return_if_fail(nick != NULL);
mserver = MODULE_DATA(server);
- rec = g_hash_table_lookup(mserver->floodlist, nick);
+ flood = g_hash_table_lookup(mserver->floodlist, nick);
+
+ rec = flood == NULL ? NULL : flood_find(flood, level, target);
if (rec != NULL) {
if (++rec->msgcount > flood_max_msgs) {
/* flooding! */
- levelstr = bits2level(rec->level);
- signal_emit("flood", 5, server, nick, host, levelstr, target);
- g_free(levelstr);
+ signal_emit("flood", 5, server, nick, host, GINT_TO_POINTER(rec->level), target);
}
return;
}
- rec = g_new(FLOOD_REC, 1);
+ if (flood == NULL) {
+ flood = g_new0(FLOOD_REC, 1);
+ flood->nick = g_strdup(nick);
+ g_hash_table_insert(mserver->floodlist, flood->nick, flood);
+ }
+
+ rec = g_new0(FLOOD_ITEM_REC, 1);
rec->level = level;
+ rec->first = time(NULL);
rec->msgcount = 1;
- rec->nick = g_strdup(nick);
+ rec->target = g_strdup(target);
- g_hash_table_insert(mserver->floodlist, rec->nick, rec);
+ flood->items = g_slist_append(flood->items, rec);
}
static void flood_privmsg(const char *data, IRC_SERVER_REC *server, const char *nick, const char *addr)
@@ -141,7 +186,7 @@ static void flood_privmsg(const char *data, IRC_SERVER_REC *server, const char *
params = event_get_params(data, 2, &target, &text);
- if (*text == 1) {
+ if (*text == 1 && g_strncasecmp(text+1, "ACTION", 6) != 0) {
/* CTCP */
if (!ignore_check(server, nick, addr, target, text, MSGLEVEL_CTCPS))
flood_newmsg(server, MSGLEVEL_CTCPS, nick, addr, target);
@@ -176,24 +221,37 @@ static void flood_notice(const char *data, IRC_SERVER_REC *server, const char *n
static void read_settings(void)
{
- if (flood_tag != -1) g_source_remove(flood_tag);
- flood_tag = g_timeout_add(settings_get_int("flood_timecheck"), (GSourceFunc) flood_timeout, NULL);
+ int time;
+ flood_timecheck = settings_get_int("flood_timecheck");
flood_max_msgs = settings_get_int("flood_max_msgs");
+
+ time = flood_timecheck > 500 ? 500 :
+ (flood_timecheck > 0 && flood_timecheck < 100) ? 100 :
+ flood_timecheck;
+
+ if (flood_tag != -1) {
+ g_source_remove(flood_tag);
+ flood_tag = -1;
+ }
+
+ if (time > 0 && flood_max_msgs > 0) {
+ flood_tag = g_timeout_add(time, (GSourceFunc) flood_timeout, NULL);
+ signal_add("event privmsg", (SIGNAL_FUNC) flood_privmsg);
+ signal_add("event notice", (SIGNAL_FUNC) flood_notice);
+ }
}
void flood_init(void)
{
- settings_add_int("flood", "flood_timecheck", 1000);
- settings_add_int("flood", "flood_max_msgs", 5);
+ settings_add_int("flood", "flood_timecheck", 5000);
+ settings_add_int("flood", "flood_max_msgs", 4);
flood_tag = -1;
read_settings();
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
signal_add_first("server connected", (SIGNAL_FUNC) flood_init_server);
signal_add("server disconnected", (SIGNAL_FUNC) flood_deinit_server);
- signal_add("event privmsg", (SIGNAL_FUNC) flood_privmsg);
- signal_add("event notice", (SIGNAL_FUNC) flood_notice);
autoignore_init();
}
@@ -202,11 +260,13 @@ void flood_deinit(void)
{
autoignore_deinit();
- if (flood_tag != -1) g_source_remove(flood_tag);
+ if (flood_tag != -1) {
+ g_source_remove(flood_tag);
+ signal_remove("event privmsg", (SIGNAL_FUNC) flood_privmsg);
+ signal_remove("event notice", (SIGNAL_FUNC) flood_notice);
+ }
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
signal_remove("server connected", (SIGNAL_FUNC) flood_init_server);
signal_remove("server disconnected", (SIGNAL_FUNC) flood_deinit_server);
- signal_remove("event privmsg", (SIGNAL_FUNC) flood_privmsg);
- signal_remove("event notice", (SIGNAL_FUNC) flood_notice);
}
diff --git a/src/irc/notifylist/notify-commands.c b/src/irc/notifylist/notify-commands.c
index 9ae5a076..af022dcd 100644
--- a/src/irc/notifylist/notify-commands.c
+++ b/src/irc/notifylist/notify-commands.c
@@ -42,7 +42,7 @@ static void cmd_notify(gchar *data)
if (stristr(args, "-idle") == NULL)
idle_check_time = 0;
else {
- idle_check_time = is_numeric(idletime, 0) ? (atol(idletime)*60) :
+ idle_check_time = is_numeric(idletime, 0) ? (atoi(idletime)*60) :
(settings_get_int("notify_idle_time")*60);
}
diff --git a/src/irc/notifylist/notify-whois.c b/src/irc/notifylist/notify-whois.c
index 439a8af8..c8191b57 100644
--- a/src/irc/notifylist/notify-whois.c
+++ b/src/irc/notifylist/notify-whois.c
@@ -78,7 +78,7 @@ static void event_whois_idle(const char *data, IRC_SERVER_REC *server)
g_return_if_fail(data != NULL);
params = event_get_params(data, 3, NULL, &nick, &secstr);
- secs = atol(secstr);
+ secs = atoi(secstr);
notify = notifylist_find(nick, server->connrec->ircnet);
nickrec = notify_nick_find(server, nick);