summaryrefslogtreecommitdiff
path: root/src/irc
diff options
context:
space:
mode:
Diffstat (limited to 'src/irc')
-rw-r--r--src/irc/core/channel-events.c10
-rw-r--r--src/irc/core/channels-query.c7
-rw-r--r--src/irc/core/irc-chatnets.c7
-rw-r--r--src/irc/core/irc-chatnets.h1
-rw-r--r--src/irc/core/irc-nicklist.c19
-rw-r--r--src/irc/core/irc-servers-setup.c22
-rw-r--r--src/irc/core/irc-servers.c5
-rw-r--r--src/irc/core/irc.c34
-rw-r--r--src/irc/core/sasl.c6
-rw-r--r--src/irc/dcc/dcc-chat.c21
-rw-r--r--src/irc/dcc/dcc-get.c19
-rw-r--r--src/irc/dcc/dcc-resume.c2
-rw-r--r--src/irc/dcc/dcc-send.c10
13 files changed, 143 insertions, 20 deletions
diff --git a/src/irc/core/channel-events.c b/src/irc/core/channel-events.c
index 6cb9b088..46bbd5fa 100644
--- a/src/irc/core/channel-events.c
+++ b/src/irc/core/channel-events.c
@@ -37,7 +37,7 @@ static void check_join_failure(IRC_SERVER_REC *server, const char *channel)
channel++; /* server didn't understand !channels */
chanrec = channel_find(SERVER(server), channel);
- if (chanrec == NULL && channel[0] == '!') {
+ if (chanrec == NULL && channel[0] == '!' && strlen(channel) > 6) {
/* it probably replied with the full !channel name,
find the channel with the short name.. */
chan2 = g_strdup_printf("!%s", channel+6);
@@ -138,7 +138,13 @@ static void channel_change_topic(IRC_SERVER_REC *server, const char *channel,
g_free_not_null(chanrec->topic_by);
chanrec->topic_by = g_strdup(setby);
- chanrec->topic_time = settime;
+ if (chanrec->topic_by == NULL) {
+ /* ensure invariant topic_time > 0 <=> topic_by != NULL.
+ this could be triggered by a topic command without sender */
+ chanrec->topic_time = 0;
+ } else {
+ chanrec->topic_time = settime;
+ }
signal_emit("channel topic changed", 1, chanrec);
}
diff --git a/src/irc/core/channels-query.c b/src/irc/core/channels-query.c
index 857ebaf0..d7dadf04 100644
--- a/src/irc/core/channels-query.c
+++ b/src/irc/core/channels-query.c
@@ -119,21 +119,22 @@ static void query_remove_all(IRC_CHANNEL_REC *channel)
int n;
rec = channel->server->chanqueries;
+ if (rec == NULL) return;
/* remove channel from query lists */
for (n = 0; n < CHANNEL_QUERIES; n++)
rec->queries[n] = g_slist_remove(rec->queries[n], channel);
rec->current_queries = g_slist_remove(rec->current_queries, channel);
- query_check(channel->server);
+ if (!channel->server->disconnected)
+ query_check(channel->server);
}
static void sig_channel_destroyed(IRC_CHANNEL_REC *channel)
{
g_return_if_fail(channel != NULL);
- if (IS_IRC_CHANNEL(channel) && !channel->server->disconnected &&
- !channel->synced)
+ if (IS_IRC_CHANNEL(channel))
query_remove_all(channel);
}
diff --git a/src/irc/core/irc-chatnets.c b/src/irc/core/irc-chatnets.c
index 0796e0cb..98ce89c3 100644
--- a/src/irc/core/irc-chatnets.c
+++ b/src/irc/core/irc-chatnets.c
@@ -43,6 +43,9 @@ static void sig_chatnet_read(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
value = config_node_get_str(node, "usermode", NULL);
rec->usermode = (value != NULL && *value != '\0') ? g_strdup(value) : NULL;
+ value = config_node_get_str(node, "alternate_nick", NULL);
+ rec->alternate_nick = (value != NULL && *value != '\0') ? g_strdup(value) : NULL;
+
rec->max_cmds_at_once = config_node_get_int(node, "cmdmax", 0);
rec->cmd_queue_speed = config_node_get_int(node, "cmdspeed", 0);
rec->max_query_chans = config_node_get_int(node, "max_query_chans", 0);
@@ -65,6 +68,9 @@ static void sig_chatnet_saved(IRC_CHATNET_REC *rec, CONFIG_NODE *node)
if (rec->usermode != NULL)
iconfig_node_set_str(node, "usermode", rec->usermode);
+ if (rec->alternate_nick != NULL)
+ iconfig_node_set_str(node, "alternate_nick", rec->alternate_nick);
+
if (rec->max_cmds_at_once > 0)
iconfig_node_set_int(node, "cmdmax", rec->max_cmds_at_once);
if (rec->cmd_queue_speed > 0)
@@ -93,6 +99,7 @@ static void sig_chatnet_destroyed(IRC_CHATNET_REC *rec)
{
if (IS_IRC_CHATNET(rec)) {
g_free(rec->usermode);
+ g_free(rec->alternate_nick);
g_free(rec->sasl_mechanism);
g_free(rec->sasl_username);
g_free(rec->sasl_password);
diff --git a/src/irc/core/irc-chatnets.h b/src/irc/core/irc-chatnets.h
index 2bb10fa9..3fd44472 100644
--- a/src/irc/core/irc-chatnets.h
+++ b/src/irc/core/irc-chatnets.h
@@ -18,6 +18,7 @@ struct _IRC_CHATNET_REC {
#include "chatnet-rec.h"
char *usermode;
+ char *alternate_nick;
char *sasl_mechanism;
char *sasl_username;
diff --git a/src/irc/core/irc-nicklist.c b/src/irc/core/irc-nicklist.c
index 1cb1f3e9..3e16db80 100644
--- a/src/irc/core/irc-nicklist.c
+++ b/src/irc/core/irc-nicklist.c
@@ -323,8 +323,9 @@ static void event_nick_invalid(IRC_SERVER_REC *server, const char *data)
static void event_nick_in_use(IRC_SERVER_REC *server, const char *data)
{
- char *str, *cmd;
+ char *str, *cmd, *params, *nick;
int n;
+ gboolean try_alternate_nick;
g_return_if_fail(data != NULL);
@@ -332,11 +333,21 @@ static void event_nick_in_use(IRC_SERVER_REC *server, const char *data)
/* Already connected, no need to handle this anymore. */
return;
}
+
+ try_alternate_nick = g_ascii_strcasecmp(server->nick, server->connrec->nick) == 0 &&
+ server->connrec->alternate_nick != NULL &&
+ g_ascii_strcasecmp(server->connrec->alternate_nick, server->nick) != 0;
+
+ params = event_get_params(data, 2, NULL, &nick);
+ if (g_ascii_strcasecmp(server->nick, nick) != 0) {
+ /* the server uses a nick different from the one we send */
+ g_free(server->nick);
+ server->nick = g_strdup(nick);
+ }
+ g_free(params);
/* nick already in use - need to change it .. */
- if (g_ascii_strcasecmp(server->nick, server->connrec->nick) == 0 &&
- server->connrec->alternate_nick != NULL &&
- g_ascii_strcasecmp(server->connrec->alternate_nick, server->nick) != 0) {
+ if (try_alternate_nick) {
/* 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/irc-servers-setup.c b/src/irc/core/irc-servers-setup.c
index f425b587..e79557ab 100644
--- a/src/irc/core/irc-servers-setup.c
+++ b/src/irc/core/irc-servers-setup.c
@@ -69,7 +69,10 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
return;
g_return_if_fail(IS_IRCNET(ircnet));
- if (ircnet->nick != NULL) g_free_and_null(conn->alternate_nick);
+ if (ircnet->alternate_nick != NULL) {
+ g_free_and_null(conn->alternate_nick);
+ conn->alternate_nick = g_strdup(ircnet->alternate_nick);
+ }
if (ircnet->usermode != NULL) {
g_free_and_null(conn->usermode);
conn->usermode = g_strdup(ircnet->usermode);
@@ -89,6 +92,8 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
/* Validate the SASL parameters filled by sig_chatnet_read() or cmd_network_add */
conn->sasl_mechanism = SASL_MECHANISM_NONE;
+ conn->sasl_username = NULL;
+ conn->sasl_password = NULL;
if (ircnet->sasl_mechanism != NULL) {
if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "plain")) {
@@ -102,9 +107,7 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
g_warning("The fields sasl_username and sasl_password are either missing or empty");
}
else if (!g_ascii_strcasecmp(ircnet->sasl_mechanism, "external")) {
- conn->sasl_mechanism = SASL_MECHANISM_EXTERNAL;
- conn->sasl_username = NULL;
- conn->sasl_password = NULL;
+ conn->sasl_mechanism = SASL_MECHANISM_EXTERNAL;
}
else
g_warning("Unsupported SASL mechanism \"%s\" selected", ircnet->sasl_mechanism);
@@ -113,14 +116,17 @@ static void sig_server_setup_fill_chatnet(IRC_SERVER_CONNECT_REC *conn,
static void init_userinfo(void)
{
+ unsigned int changed;
const char *set, *nick, *user_name, *str;
+ changed = 0;
/* check if nick/username/realname wasn't read from setup.. */
set = settings_get_str("real_name");
if (set == NULL || *set == '\0') {
str = g_getenv("IRCNAME");
settings_set_str("real_name",
str != NULL ? str : g_get_real_name());
+ changed |= USER_SETTINGS_REAL_NAME;
}
/* username */
@@ -131,6 +137,7 @@ static void init_userinfo(void)
str != NULL ? str : g_get_user_name());
user_name = settings_get_str("user_name");
+ changed |= USER_SETTINGS_USER_NAME;
}
/* nick */
@@ -140,15 +147,20 @@ static void init_userinfo(void)
settings_set_str("nick", str != NULL ? str : user_name);
nick = settings_get_str("nick");
+ changed |= USER_SETTINGS_NICK;
}
/* host name */
set = settings_get_str("hostname");
if (set == NULL || *set == '\0') {
str = g_getenv("IRCHOST");
- if (str != NULL)
+ if (str != NULL) {
settings_set_str("hostname", str);
+ changed |= USER_SETTINGS_HOSTNAME;
+ }
}
+
+ signal_emit("irssi init userinfo changed", 1, GUINT_TO_POINTER(changed));
}
static void sig_server_setup_read(IRC_SERVER_SETUP_REC *rec, CONFIG_NODE *node)
diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c
index 3117e345..4eaab712 100644
--- a/src/irc/core/irc-servers.c
+++ b/src/irc/core/irc-servers.c
@@ -116,11 +116,14 @@ static char **split_line(const SERVER_REC *server, const char *line,
* the code much simpler. It's worth it.
*/
len -= strlen(recoded_start) + strlen(recoded_end);
+ g_warn_if_fail(len > 0);
if (len <= 0) {
/* There is no room for anything. */
g_free(recoded_start);
g_free(recoded_end);
- return NULL;
+ lines = g_new(char *, 1);
+ lines[0] = NULL;
+ return lines;
}
lines = recode_split(server, line, target, len, onspace);
diff --git a/src/irc/core/irc.c b/src/irc/core/irc.c
index 4dce3fcf..a740b0da 100644
--- a/src/irc/core/irc.c
+++ b/src/irc/core/irc.c
@@ -40,6 +40,8 @@ static int signal_server_incoming;
# define MAX_SOCKET_READS 5
#endif
+static void strip_params_colon(char *const);
+
/* The core of the irc_send_cmd* functions. If `raw' is TRUE, the `cmd'
won't be checked at all if it's 512 bytes or not, or if it contains
line feeds or not. Use with extreme caution! */
@@ -269,8 +271,9 @@ char *event_get_params(const char *data, int count, ...)
while (count-- > 0) {
str = (char **) va_arg(args, char **);
if (count == 0 && rest) {
- /* put the rest to last parameter */
- tmp = *datad == ':' ? datad+1 : datad;
+ /* Put the rest into the last parameter. */
+ strip_params_colon(datad);
+ tmp = datad;
} else {
tmp = event_get_param(&datad);
}
@@ -281,6 +284,33 @@ char *event_get_params(const char *data, int count, ...)
return duprec;
}
+/* Given a string containing <params>, strip any colon prefixing <trailing>. */
+static void strip_params_colon(char *const params)
+{
+ char *s;
+
+ if (params == NULL) {
+ return;
+ }
+
+ s = params;
+ while (*s != '\0') {
+ if (*s == ':') {
+ memmove(s, s+1, strlen(s+1)+1);
+ return;
+ }
+
+ s = strchr(s, ' ');
+ if (s == NULL) {
+ return;
+ }
+
+ while (*s == ' ') {
+ s++;
+ }
+ }
+}
+
static void irc_server_event(IRC_SERVER_REC *server, const char *line,
const char *nick, const char *address)
{
diff --git a/src/irc/core/sasl.c b/src/irc/core/sasl.c
index 635b7dfb..2b589579 100644
--- a/src/irc/core/sasl.c
+++ b/src/irc/core/sasl.c
@@ -30,16 +30,16 @@
* Based on IRCv3 SASL Extension Specification:
* http://ircv3.net/specs/extensions/sasl-3.1.html
*/
-#define AUTHENTICATE_CHUNK_SIZE 400 // bytes
+#define AUTHENTICATE_CHUNK_SIZE 400 /* bytes */
/*
* Maximum size to allow the buffer to grow to before the next fragment comes in. Note that
* due to the way fragmentation works, the maximum message size will actually be:
* floor(AUTHENTICATE_MAX_SIZE / AUTHENTICATE_CHUNK_SIZE) + AUTHENTICATE_CHUNK_SIZE - 1
*/
-#define AUTHENTICATE_MAX_SIZE 8192 // bytes
+#define AUTHENTICATE_MAX_SIZE 8192 /* bytes */
-#define SASL_TIMEOUT (20 * 1000) // ms
+#define SASL_TIMEOUT (20 * 1000) /* ms */
static gboolean sasl_timeout(IRC_SERVER_REC *server)
{
diff --git a/src/irc/dcc/dcc-chat.c b/src/irc/dcc/dcc-chat.c
index ca90b8d8..88c577f7 100644
--- a/src/irc/dcc/dcc-chat.c
+++ b/src/irc/dcc/dcc-chat.c
@@ -66,6 +66,13 @@ CHAT_DCC_REC *dcc_chat_create(IRC_SERVER_REC *server,
dcc->id = dcc_chat_get_new_id(nick);
dcc_init_rec(DCC(dcc), server, chat, nick, arg);
+ if (dcc->module_data == NULL) {
+ /* failed to successfully init; TODO: change init_rec API */
+ g_free(dcc->id);
+ g_free(dcc);
+ return NULL;
+ }
+
return dcc;
}
@@ -471,6 +478,7 @@ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server)
/* We are accepting a passive DCC CHAT. */
dcc_chat_passive(dcc);
}
+ cmd_params_free(free_arg);
return;
}
@@ -485,6 +493,11 @@ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server)
cmd_param_error(CMDERR_NOT_CONNECTED);
dcc = dcc_chat_create(server, NULL, nick, "chat");
+ if (dcc == NULL) {
+ cmd_params_free(free_arg);
+ g_warn_if_reached();
+ return;
+ }
if (g_hash_table_lookup(optlist, "passive") == NULL) {
/* Standard DCC CHAT... let's listen for incoming connections */
@@ -627,6 +640,9 @@ static void ctcp_msg_dcc_chat(IRC_SERVER_REC *server, const char *data,
}
passive = paramcount == 4 && g_strcmp0(params[2], "0") == 0;
+ if (nick == NULL)
+ nick = "";
+
dcc = DCC_CHAT(dcc_find_request(DCC_CHAT_TYPE, nick, NULL));
if (dcc != NULL) {
if (dcc_is_listening(dcc)) {
@@ -658,6 +674,11 @@ static void ctcp_msg_dcc_chat(IRC_SERVER_REC *server, const char *data,
}
dcc = dcc_chat_create(server, chat, nick, params[0]);
+ if (dcc == NULL) {
+ g_strfreev(params);
+ g_warn_if_reached();
+ return;
+ }
dcc->target = g_strdup(target);
dcc->port = atoi(params[2]);
diff --git a/src/irc/dcc/dcc-get.c b/src/irc/dcc/dcc-get.c
index 73c1b864..cecbb076 100644
--- a/src/irc/dcc/dcc-get.c
+++ b/src/irc/dcc/dcc-get.c
@@ -43,6 +43,12 @@ GET_DCC_REC *dcc_get_create(IRC_SERVER_REC *server, CHAT_DCC_REC *chat,
dcc->fhandle = -1;
dcc_init_rec(DCC(dcc), server, chat, nick, arg);
+ if (dcc->module_data == NULL) {
+ /* failed to successfully init; TODO: change API */
+ g_free(dcc);
+ return NULL;
+ }
+
return dcc;
}
@@ -382,6 +388,8 @@ int get_file_params_count(char **params, int paramcount)
if (*params[0] == '"') {
/* quoted file name? */
for (pos = 0; pos < paramcount-3; pos++) {
+ if (strlen(params[pos]) == 0)
+ continue;
if (params[pos][strlen(params[pos])-1] == '"' &&
get_params_match(params, pos+1))
return pos+1;
@@ -428,6 +436,11 @@ static void ctcp_msg_dcc_send(IRC_SERVER_REC *server, const char *data,
int p_id = -1;
int passive = FALSE;
+ if (addr == NULL)
+ addr = "";
+ if (nick == NULL)
+ nick = "";
+
/* SEND <file name> <address> <port> <size> [...] */
/* SEND <file name> <address> 0 <size> <id> (DCC SEND passive protocol) */
params = g_strsplit(data, " ", -1);
@@ -506,6 +519,12 @@ static void ctcp_msg_dcc_send(IRC_SERVER_REC *server, const char *data,
dcc_destroy(DCC(dcc)); /* remove the old DCC */
dcc = dcc_get_create(server, chat, nick, fname);
+ if (dcc == NULL) {
+ g_free(address);
+ g_free(fname);
+ g_warn_if_reached();
+ return;
+ }
dcc->target = g_strdup(target);
if (passive && port == 0)
diff --git a/src/irc/dcc/dcc-resume.c b/src/irc/dcc/dcc-resume.c
index 36f84ddf..ce0ac925 100644
--- a/src/irc/dcc/dcc-resume.c
+++ b/src/irc/dcc/dcc-resume.c
@@ -62,6 +62,8 @@ int get_file_params_count_resume(char **params, int paramcount)
if (*params[0] == '"') {
/* quoted file name? */
for (pos = 0; pos < paramcount-2; pos++) {
+ if (strlen(params[pos]) == 0)
+ continue;
if (params[pos][strlen(params[pos])-1] == '"' &&
get_params_match_resume(params, pos+1))
return pos+1;
diff --git a/src/irc/dcc/dcc-send.c b/src/irc/dcc/dcc-send.c
index ca29b9b9..912129b7 100644
--- a/src/irc/dcc/dcc-send.c
+++ b/src/irc/dcc/dcc-send.c
@@ -237,6 +237,12 @@ static SEND_DCC_REC *dcc_send_create(IRC_SERVER_REC *server,
dcc->queue = -1;
dcc_init_rec(DCC(dcc), server, chat, nick, arg);
+ if (dcc->module_data == NULL) {
+ /* failed to successfully init; TODO: change API */
+ g_free(dcc);
+ return NULL;
+ }
+
return dcc;
}
@@ -417,6 +423,10 @@ static int dcc_send_one_file(int queue, const char *target, const char *fname,
dcc = dcc_send_create(server, chat, target, str);
g_free(str);
+ if (dcc == NULL) {
+ g_warn_if_reached();
+ return FALSE;
+ }
dcc->handle = handle;
dcc->port = port;