From 147ea72710b2ed36e64b23a46ece7b27fd99e45a Mon Sep 17 00:00:00 2001 From: Kevin Easton Date: Mon, 7 Jul 2008 11:55:00 +0000 Subject: [PATCH] Some cleanups in quit message handling. Fixed a bug where a quit from a user that isn't in a channel with the client (god knows how *that* happens, but someone reported the bug...) could crash the client, because a NULL pointer is passed to logmsg(). The bug didn't show under glibc because it handles the NULL pointer OK. git-svn-id: svn://svn.code.sf.net/p/bitchx/code/trunk@58 13b04d17-f746-0410-82c6-800466cd88b0 --- Changelog | 3 ++ include/misc.h | 4 +- include/names.h | 2 +- source/commands.c | 2 +- source/misc.c | 4 +- source/names.c | 19 +++++----- source/notice.c | 2 +- source/parse.c | 96 ++++++++++++++++++++++++++--------------------- 8 files changed, 72 insertions(+), 60 deletions(-) diff --git a/Changelog b/Changelog index 982a33a..cae8f5f 100644 --- a/Changelog +++ b/Changelog @@ -1,5 +1,8 @@ [Changes 1.2c01 ] +* Some cleanups in quit message handling, fixed a bug where a quit from an + unexpected source could crash the client. (caf) + * Cleaned up the handling of channel mode changes a little, including fixing buggy handling of certain key and limit mode changes. (caf) diff --git a/include/misc.h b/include/misc.h index 2cf6fef..df68d65 100644 --- a/include/misc.h +++ b/include/misc.h @@ -67,8 +67,8 @@ extern LastMsg last_sent_ctcp[2]; - void update_stats (int, char *, NickList *, ChannelList *, int); - int check_split (char *, char *, char *); + void update_stats (int, NickList *, ChannelList *, int); + int check_split (char *, char *); void BX_userage (char *, char *); void stats_k_grep_end (void); char *stripansicodes (const unsigned char *); diff --git a/include/names.h b/include/names.h index 003f5d4..18b47b1 100644 --- a/include/names.h +++ b/include/names.h @@ -51,7 +51,7 @@ void list_channels (void); void reconnect_all_channels (int); void switch_channels (char, char *); char *what_channel (char *, int); -char *walk_channels (char *, int, int); +ChannelList *walk_channels (char *, int, int); char *real_channel (void); void BX_rename_nick (char *, char *, int); void update_channel_mode (char *, char *, int, char *, ChannelList *); diff --git a/source/commands.c b/source/commands.c index 307d395..7eb0a37 100644 --- a/source/commands.c +++ b/source/commands.c @@ -4008,7 +4008,7 @@ struct target_type target[4] = if ((chan = lookup_channel(channel, from_server, 0))) { nick = find_nicklist_in_channellist(get_server_nickname(from_server), chan, 0); - update_stats((i == 1) ?PUBLIC_LIST : NOTICE_LIST, channel, nick, chan, 0); + update_stats((i == 1) ?PUBLIC_LIST : NOTICE_LIST, nick, chan, 0); } } } diff --git a/source/misc.c b/source/misc.c index df16bc4..c74eced 100644 --- a/source/misc.c +++ b/source/misc.c @@ -702,7 +702,7 @@ put_it("%s", convert_output_format(" %CIdle user check is %K[%R$0-%K]", "%s", n } -void update_stats(int what, char *channel, NickList *nick, ChannelList *chan, int splitter) +void update_stats(int what, NickList *nick, ChannelList *chan, int splitter) { time_t this_time = now; int t = 0; @@ -1073,7 +1073,7 @@ unsigned char *newline; } -int check_split(char *nick, char *reason, char *chan) +int check_split(char *nick, char *reason) { char *bogus = get_string_var(FAKE_SPLIT_PATS_VAR); char *Reason; diff --git a/source/names.c b/source/names.c index 4cdadb6..cda9bbf 100644 --- a/source/names.c +++ b/source/names.c @@ -398,7 +398,7 @@ ChannelList *BX_add_to_channel(char *channel, char *nick, int server, int oper, if (server1) malloc_strcpy(&new->server, server1); add_nicklist_to_channellist(new, chan); - update_stats(JOINLIST, chan->channel, new, chan, serv_split); + update_stats(JOINLIST, new, chan, serv_split); } malloc_strcpy(&new->host, userhost); if (ischop > 0) @@ -961,7 +961,7 @@ static void apply_channel_modes(char *from, char *mode_str, ThisNick->flags &= ~NICK_HALFOP; } ThisNick = find_nicklist_in_channellist(from, channel, 0); - update_stats(add ? MODEHOPLIST: MODEDEHOPLIST, channel->channel, ThisNick, channel, splitter); + update_stats(add ? MODEHOPLIST: MODEDEHOPLIST, ThisNick, channel, splitter); break; case 'o': { @@ -975,7 +975,7 @@ static void apply_channel_modes(char *from, char *mode_str, do_hook(CHANOP_LIST, "%s", channel->channel); } ThisNick = find_nicklist_in_channellist(from, channel, 0); - update_stats(add ? MODEOPLIST: MODEDEOPLIST, channel->channel, ThisNick, channel, splitter); + update_stats(add ? MODEOPLIST: MODEDEOPLIST, ThisNick, channel, splitter); if ((ThisNick = find_nicklist_in_channellist(person, channel, 0))) { if (add) @@ -1055,7 +1055,7 @@ static void apply_channel_modes(char *from, char *mode_str, break; ThisNick = find_nicklist_in_channellist(from, channel, 0); - update_stats(add?MODEBANLIST:MODEUNBANLIST, channel->channel, ThisNick, channel, splitter); + update_stats(add?MODEBANLIST:MODEUNBANLIST, ThisNick, channel, splitter); if (add) { ThisNick = find_nicklist_in_channellist(person, channel, 0); @@ -1089,7 +1089,7 @@ static void apply_channel_modes(char *from, char *mode_str, break; ThisNick = find_nicklist_in_channellist(from, channel, 0); - update_stats(add?MODEEBANLIST:MODEUNEBANLIST, channel->channel, ThisNick, channel, splitter); + update_stats(add?MODEEBANLIST:MODEUNEBANLIST, ThisNick, channel, splitter); if (add) { ThisNick = find_nicklist_in_channellist(person, channel, 0); @@ -1687,20 +1687,19 @@ char *what_channel(char *nick, int server) return NULL; } -char *walk_channels(char *nick, int init, int server) +ChannelList *walk_channels(char *nick, int init, int server) { static ChannelList *tmp = NULL; - if (init) tmp = get_server_channels(server); else if (tmp) tmp = tmp->next; + for (;tmp ; tmp = tmp->next) { - if ((tmp->server == from_server) && - (find_nicklist_in_channellist(nick, tmp, 0))) - return (tmp->channel); + if (find_nicklist_in_channellist(nick, tmp, 0)) + return tmp; } return NULL; } diff --git a/source/notice.c b/source/notice.c index f3909ab..ef96d34 100644 --- a/source/notice.c +++ b/source/notice.c @@ -713,7 +713,7 @@ void parse_notice(char *from, char **Args) type = NOTICE_LIST; } - update_stats(NOTICELIST, to, nick, tmpc, 0); + update_stats(NOTICELIST, nick, tmpc, 0); set_display_target(target, LOG_NOTICE); doing_notice = 1; diff --git a/source/parse.c b/source/parse.c index f81ab76..de36baf 100644 --- a/source/parse.c +++ b/source/parse.c @@ -354,7 +354,7 @@ ChannelList *tmp; { fake(); return; } if ((tmp = lookup_channel(ArgList[0], from_server, CHAN_NOUNLINK))) { - update_stats(TOPICLIST, tmp->channel, find_nicklist_in_channellist(from, tmp, 0), tmp, 0); + update_stats(TOPICLIST, find_nicklist_in_channellist(from, tmp, 0), tmp, 0); if (tmp->topic_lock) { if (my_stricmp(from, get_server_nickname(from_server))) @@ -561,7 +561,7 @@ static void p_privmsg(char *from, char **Args) } } #endif - update_stats(PUBLICLIST, to, tmpnick, channel, 0); + update_stats(PUBLICLIST, tmpnick, channel, 0); level = set_lastlog_msg_level(log_type); com_do_log = 0; @@ -708,67 +708,77 @@ static void p_privmsg(char *from, char **Args) static void p_quit(char *from, char **ArgList) { int one_prints = 0; - char *chan = NULL; - char *Reason; - char *tmp = NULL; - ChannelList *tmpc; + char *reason; + char *chanlist = NULL; + ChannelList *chan; int netsplit = 0; int ignore; - - PasteArgs(ArgList, 0); if (ArgList[0]) { - Reason = ArgList[0]; - netsplit = check_split(from, Reason, chan); + reason = ArgList[0]; + netsplit = check_split(from, reason); } else - Reason = "?"; - - for (chan = walk_channels(from, 1, from_server); chan; chan = walk_channels(from, 0, -1)) + reason = "?"; + + for (chan = walk_channels(from, 1, from_server); chan; + chan = walk_channels(from, 0, -1)) { - ignore = check_ignore(from, FromUserHost, chan, (netsplit?IGNORE_SPLITS:IGNORE_QUITS), NULL); - if ((tmpc = lookup_channel(chan, from_server, CHAN_NOUNLINK))) - { - update_stats(CHANNELSIGNOFFLIST, chan, find_nicklist_in_channellist(from, tmpc, 0), tmpc, netsplit); + update_stats(CHANNELSIGNOFFLIST, + find_nicklist_in_channellist(from, chan, 0), chan, netsplit); + #ifdef WANT_TCL - if (netsplit) - check_tcl_split(from, FromUserHost, from, chan); - else - check_tcl_sign(from, FromUserHost, from, chan, Reason); -#endif - if (!netsplit) - { - do_logchannel(LOG_PART, tmpc, "%s %s %s %s", from, FromUserHost, chan, Reason?Reason:empty_string); - check_channel_limit(tmpc); - } - } - if (tmp) - m_3cat(&tmp, ",", chan); + if (netsplit) + check_tcl_split(from, FromUserHost, from, chan->channel); else - malloc_strcpy(&tmp, chan); + check_tcl_sign(from, FromUserHost, from, chan->channel, reason); +#endif + + if (!netsplit) + { + do_logchannel(LOG_PART, chan, "%s %s %s %s", from, FromUserHost, + chan->channel, reason); + check_channel_limit(chan); + } + + if (chanlist) + m_3cat(&chanlist, ",", chan->channel); + else + malloc_strcpy(&chanlist, chan->channel); + + ignore = check_ignore(from, FromUserHost, chan->channel, + (netsplit?IGNORE_SPLITS:IGNORE_QUITS), NULL); if (ignore != IGNORED) { - set_display_target(chan, LOG_CRAP); - if (do_hook(CHANNEL_SIGNOFF_LIST, "%s %s %s", chan, from, Reason)) + set_display_target(chan->channel, LOG_CRAP); + if (do_hook(CHANNEL_SIGNOFF_LIST, "%s %s %s", chan->channel, + from, reason)) one_prints = 1; } } + if (one_prints) { - chan = what_channel(from, from_server); - ignore = check_ignore(from, FromUserHost, chan, (netsplit?IGNORE_SPLITS:IGNORE_QUITS), NULL); - set_display_target(chan, LOG_CRAP); - if ((ignore != IGNORED) && do_hook(SIGNOFF_LIST, "%s %s", from, Reason) && !netsplit) - put_it("%s",convert_output_format(fget_string_var(FORMAT_CHANNEL_SIGNOFF_FSET), "%s %s %s %s %s",update_clock(GET_TIME), from, FromUserHost, tmp, Reason)); + char *channel = what_channel(from, from_server); + ignore = check_ignore(from, FromUserHost, channel, + (netsplit?IGNORE_SPLITS:IGNORE_QUITS), NULL); + set_display_target(channel, LOG_CRAP); + if ((ignore != IGNORED) && do_hook(SIGNOFF_LIST, "%s %s", from, reason) + && !netsplit) + put_it("%s", convert_output_format( + fget_string_var(FORMAT_CHANNEL_SIGNOFF_FSET), + "%s %s %s %s %s", update_clock(GET_TIME), from, FromUserHost, + chanlist, reason)); } - logmsg(LOG_PART, from, 0, "%s %s", tmp, Reason?Reason:empty_string); + + logmsg(LOG_PART, from, 0, "%s %s", chanlist ? chanlist : "", reason); check_orig_nick(from); notify_mark(from, FromUserHost, 0, 0); - remove_from_channel(NULL, from, from_server, netsplit, Reason); + remove_from_channel(NULL, from, from_server, netsplit, reason); update_all_status(current_window, NULL, 0); - new_free(&tmp); + new_free(&chanlist); reset_display_target(); #ifdef GUI gui_update_nicklist(NULL); @@ -1583,7 +1593,7 @@ static void p_kick(char *from, char **ArgList) set_display_target(channel, LOG_CRAP); if (channel && who && chan) { - update_stats(KICKLIST, channel, tmpnick, chan, 0); + update_stats(KICKLIST, tmpnick, chan, 0); #ifdef WANT_TCL check_tcl_kick(from, FromUserHost, from, channel, who, comment); #endif @@ -1692,7 +1702,7 @@ static void p_part(char *from, char **ArgList) set_display_target(channel, LOG_CRAP); if ((tmpc = lookup_channel(channel, from_server, CHAN_NOUNLINK))) - update_stats(LEAVELIST, channel, find_nicklist_in_channellist(from, tmpc, 0), tmpc, 0); + update_stats(LEAVELIST, find_nicklist_in_channellist(from, tmpc, 0), tmpc, 0); if ((check_ignore(from, FromUserHost, channel, IGNORE_PARTS, NULL) != IGNORED) && do_hook(LEAVE_LIST, "%s %s %s %s", from, channel, FromUserHost, ArgList[1]?ArgList[1]:empty_string))