diff options
Diffstat (limited to 'src/irc')
-rw-r--r-- | src/irc/core/channel-events.c | 10 | ||||
-rw-r--r-- | src/irc/core/channels-query.c | 7 | ||||
-rw-r--r-- | src/irc/core/irc-chatnets.c | 7 | ||||
-rw-r--r-- | src/irc/core/irc-chatnets.h | 1 | ||||
-rw-r--r-- | src/irc/core/irc-nicklist.c | 19 | ||||
-rw-r--r-- | src/irc/core/irc-servers-setup.c | 22 | ||||
-rw-r--r-- | src/irc/core/irc-servers.c | 5 | ||||
-rw-r--r-- | src/irc/core/irc.c | 34 | ||||
-rw-r--r-- | src/irc/core/sasl.c | 6 | ||||
-rw-r--r-- | src/irc/dcc/dcc-chat.c | 21 | ||||
-rw-r--r-- | src/irc/dcc/dcc-get.c | 19 | ||||
-rw-r--r-- | src/irc/dcc/dcc-resume.c | 2 | ||||
-rw-r--r-- | src/irc/dcc/dcc-send.c | 10 |
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; |