commit 5facf5c15ecc49bad1c12e8f624877fb8637e63b from: Alexander Barton date: Sat Feb 09 22:18:49 2013 UTC irc-info: move static functions at the top of the file commit - 0ad0fe207ab1705a2b042e7f47f1e0d8ce46e2a9 commit + 5facf5c15ecc49bad1c12e8f624877fb8637e63b blob - aaa607ddf32d5248c9b1cdd0c41ea5944da4a796 blob + de4cba279ecb85e960bc3592af340ccd023b9ec3 --- src/ngircd/irc-info.c +++ src/ngircd/irc-info.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors. * * 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 @@ -44,7 +44,442 @@ #include "exp.h" #include "irc-info.h" +/* Local functions */ +static unsigned int +t_diff(time_t *t, const time_t d) +{ + time_t diff, remain; + + diff = *t / d; + remain = diff * d; + *t -= remain; + + return (unsigned int)diff; +} + +static unsigned int +uptime_days(time_t *now) +{ + return t_diff(now, 60 * 60 * 24); +} + +static unsigned int +uptime_hrs(time_t *now) +{ + return t_diff(now, 60 * 60); +} + +static unsigned int +uptime_mins(time_t *now) +{ + return t_diff(now, 60); +} + +static bool +write_whoreply(CLIENT *Client, CLIENT *c, const char *channelname, const char *flags) +{ + return IRC_WriteStrClient(Client, RPL_WHOREPLY_MSG, Client_ID(Client), + channelname, Client_User(c), + Client_HostnameDisplayed(c), + Client_ID(Client_Introducer(c)), Client_ID(c), + flags, Client_Hops(c), Client_Info(c)); +} + +static const char * +who_flags_status(const char *client_modes) +{ + if (strchr(client_modes, 'a')) + return "G"; /* away */ + return "H"; +} + +/** + * Return channel user mode prefix(es). + * + * @param Client The client requesting the mode prefixes. + * @param chan_user_modes String with channel user modes. + * @param str String buffer to which the prefix(es) will be appended. + * @param len Size of "str" buffer. + * @return Pointer to "str". + */ +static char * +who_flags_qualifier(CLIENT *Client, const char *chan_user_modes, + char *str, size_t len) +{ + assert(Client != NULL); + + if (Client_Cap(Client) & CLIENT_CAP_MULTI_PREFIX) { + if (strchr(chan_user_modes, 'q')) + strlcat(str, "~", len); + if (strchr(chan_user_modes, 'a')) + strlcat(str, "&", len); + if (strchr(chan_user_modes, 'o')) + strlcat(str, "@", len); + if (strchr(chan_user_modes, 'h')) + strlcat(str, "%", len); + if (strchr(chan_user_modes, 'v')) + strlcat(str, "+", len); + + return str; + } + + if (strchr(chan_user_modes, 'q')) + strlcat(str, "~", len); + else if (strchr(chan_user_modes, 'a')) + strlcat(str, "&", len); + else if (strchr(chan_user_modes, 'o')) + strlcat(str, "@", len); + else if (strchr(chan_user_modes, 'h')) + strlcat(str, "%", len); + else if (strchr(chan_user_modes, 'v')) + strlcat(str, "+", len); + + return str; +} + +/** + * Send WHO reply for a "channel target" ("WHO #channel"). + * + * @param Client Client requesting the information. + * @param Chan Channel being requested. + * @param OnlyOps Only display IRC operators. + * @return CONNECTED or DISCONNECTED. + */ +static bool +IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) +{ + bool is_visible, is_member, is_ircop; + CL2CHAN *cl2chan; + const char *client_modes; + char flags[10]; + CLIENT *c; + int count = 0; + + assert( Client != NULL ); + assert( Chan != NULL ); + + IRC_SetPenalty(Client, 1); + + is_member = Channel_IsMemberOf(Chan, Client); + + /* Secret channel? */ + if (!is_member && strchr(Channel_Modes(Chan), 's')) + return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, + Client_ID(Client), Channel_Name(Chan)); + + cl2chan = Channel_FirstMember(Chan); + for (; cl2chan ; cl2chan = Channel_NextMember(Chan, cl2chan)) { + c = Channel_GetClient(cl2chan); + + client_modes = Client_Modes(c); + is_ircop = strchr(client_modes, 'o') != NULL; + if (OnlyOps && !is_ircop) + continue; + + is_visible = strchr(client_modes, 'i') == NULL; + if (is_member || is_visible) { + strlcpy(flags, who_flags_status(client_modes), + sizeof(flags)); + if (is_ircop) + strlcat(flags, "*", sizeof(flags)); + + who_flags_qualifier(Client, Channel_UserModes(Chan, c), + flags, sizeof(flags)); + + if (!write_whoreply(Client, c, Channel_Name(Chan), + flags)) + return DISCONNECTED; + count++; + } + } + + /* If there are a lot of clients, augment penalty a bit */ + if (count > MAX_RPL_WHO) + IRC_SetPenalty(Client, 1); + + return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), + Channel_Name(Chan)); +} + +/** + * Send WHO reply for a "mask target" ("WHO m*sk"). + * + * @param Client Client requesting the information. + * @param Mask Mask being requested or NULL for "all" clients. + * @param OnlyOps Only display IRC operators. + * @return CONNECTED or DISCONNECTED. + */ +static bool +IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps) +{ + CLIENT *c; + CL2CHAN *cl2chan; + CHANNEL *chan; + bool client_match, is_visible; + char flags[4]; + int count = 0; + + assert (Client != NULL); + + if (Mask) + ngt_LowerStr(Mask); + + IRC_SetPenalty(Client, 3); + for (c = Client_First(); c != NULL; c = Client_Next(c)) { + if (Client_Type(c) != CLIENT_USER) + continue; + + if (OnlyOps && !Client_HasMode(c, 'o')) + continue; + + if (Mask) { + /* Match pattern against user host/server/name/nick */ + client_match = MatchCaseInsensitive(Mask, + Client_Hostname(c)); + if (!client_match) + client_match = MatchCaseInsensitive(Mask, + Client_ID(Client_Introducer(c))); + if (!client_match) + client_match = MatchCaseInsensitive(Mask, + Client_Info(c)); + if (!client_match) + client_match = MatchCaseInsensitive(Mask, + Client_ID(c)); + if (!client_match) + continue; /* no match: skip this client */ + } + + is_visible = !Client_HasMode(c, 'i'); + + /* Target client is invisible, but mask matches exactly? */ + if (!is_visible && Mask && strcasecmp(Client_ID(c), Mask) == 0) + is_visible = true; + + /* Target still invisible, but are both on the same channel? */ + if (!is_visible) { + cl2chan = Channel_FirstChannelOf(Client); + while (cl2chan && !is_visible) { + chan = Channel_GetChannel(cl2chan); + if (Channel_IsMemberOf(chan, c)) + is_visible = true; + cl2chan = Channel_NextChannelOf(Client, cl2chan); + } + } + + if (!is_visible) /* target user is not visible */ + continue; + + if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO")) + break; + + strlcpy(flags, who_flags_status(Client_Modes(c)), sizeof(flags)); + if (strchr(Client_Modes(c), 'o')) + strlcat(flags, "*", sizeof(flags)); + + if (!write_whoreply(Client, c, "*", flags)) + return DISCONNECTED; + count++; + } + + return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), + Mask ? Mask : "*"); +} + +/** + * Generate WHOIS reply of one actual client. + * + * @param Client The client from which this command has been received. + * @param from The client requesting the information ("originator"). + * @param c The client of which information should be returned. + * @return CONNECTED or DISCONNECTED. + */ +static bool +IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) +{ + char str[LINE_LEN + 1]; + CL2CHAN *cl2chan; + CHANNEL *chan; + + assert(Client != NULL); + assert(from != NULL); + assert(c != NULL); + + /* Nick, user, hostname and client info */ + if (!IRC_WriteStrClient(from, RPL_WHOISUSER_MSG, Client_ID(from), + Client_ID(c), Client_User(c), + Client_HostnameDisplayed(c), Client_Info(c))) + return DISCONNECTED; + + /* Server */ + if (!IRC_WriteStrClient(from, RPL_WHOISSERVER_MSG, Client_ID(from), + Client_ID(c), Client_ID(Client_Introducer(c)), + Client_Info(Client_Introducer(c)))) + return DISCONNECTED; + + /* Channels */ + snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG, + Client_ID(from), Client_ID(c)); + cl2chan = Channel_FirstChannelOf(c); + while (cl2chan) { + chan = Channel_GetChannel(cl2chan); + assert(chan != NULL); + + /* next */ + cl2chan = Channel_NextChannelOf(c, cl2chan); + + /* Secret channel? */ + if (strchr(Channel_Modes(chan), 's') + && !Channel_IsMemberOf(chan, Client)) + continue; + + /* Local channel and request is not from a user? */ + if (Client_Type(Client) == CLIENT_SERVER + && Channel_IsLocal(chan)) + continue; + + /* Concatenate channel names */ + if (str[strlen(str) - 1] != ':') + strlcat(str, " ", sizeof(str)); + + who_flags_qualifier(Client, Channel_UserModes(chan, c), + str, sizeof(str)); + strlcat(str, Channel_Name(chan), sizeof(str)); + + if (strlen(str) > (LINE_LEN - CHANNEL_NAME_LEN - 4)) { + /* Line becomes too long: send it! */ + if (!IRC_WriteStrClient(Client, "%s", str)) + return DISCONNECTED; + snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG, + Client_ID(from), Client_ID(c)); + } + } + if(str[strlen(str) - 1] != ':') { + /* There is data left to send: */ + if (!IRC_WriteStrClient(Client, "%s", str)) + return DISCONNECTED; + } + + /* IRC-Operator? */ + if (Client_HasMode(c, 'o') && + !IRC_WriteStrClient(from, RPL_WHOISOPERATOR_MSG, + Client_ID(from), Client_ID(c))) + return DISCONNECTED; + + /* IRC-Bot? */ + if (Client_HasMode(c, 'B') && + !IRC_WriteStrClient(from, RPL_WHOISBOT_MSG, + Client_ID(from), Client_ID(c))) + return DISCONNECTED; + + /* Connected using SSL? */ + if (Conn_UsesSSL(Client_Conn(c)) && + !IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from), + Client_ID(c))) + return DISCONNECTED; + + /* Registered nickname? */ + if (Client_HasMode(c, 'R') && + !IRC_WriteStrClient(from, RPL_WHOISREGNICK_MSG, + Client_ID(from), Client_ID(c))) + return DISCONNECTED; + + /* Local client and requester is the user itself or an IRC Op? */ + if (Client_Conn(c) > NONE && + (from == c || (!Conf_MorePrivacy && Client_HasMode(from, 'o')))) { + /* Client hostname */ + if (!IRC_WriteStrClient(from, RPL_WHOISHOST_MSG, + Client_ID(from), Client_ID(c), Client_Hostname(c), + Conn_GetIPAInfo(Client_Conn(c)))) + return DISCONNECTED; + /* Client modes */ + if (!IRC_WriteStrClient(from, RPL_WHOISMODES_MSG, + Client_ID(from), Client_ID(c), Client_Modes(c))) + return DISCONNECTED; + } + + /* Idle and signon time (local clients only!) */ + if (!Conf_MorePrivacy && Client_Conn(c) > NONE && + !IRC_WriteStrClient(from, RPL_WHOISIDLE_MSG, + Client_ID(from), Client_ID(c), + (unsigned long)Conn_GetIdle(Client_Conn(c)), + (unsigned long)Conn_GetSignon(Client_Conn(c)))) + return DISCONNECTED; + + /* Away? */ + if (Client_HasMode(c, 'a') && + !IRC_WriteStrClient(from, RPL_AWAY_MSG, + Client_ID(from), Client_ID(c), Client_Away(c))) + return DISCONNECTED; + + return CONNECTED; +} + +static bool +WHOWAS_EntryWrite(CLIENT *prefix, WHOWAS *entry) +{ + char t_str[60]; + + (void)strftime(t_str, sizeof(t_str), "%a %b %d %H:%M:%S %Y", + localtime(&entry->time)); + + if (!IRC_WriteStrClient(prefix, RPL_WHOWASUSER_MSG, Client_ID(prefix), + entry->id, entry->user, entry->host, entry->info)) + return DISCONNECTED; + + return IRC_WriteStrClient(prefix, RPL_WHOISSERVER_MSG, Client_ID(prefix), + entry->id, entry->server, t_str); +} + +static bool +Show_MOTD_Start(CLIENT *Client) +{ + return IRC_WriteStrClient(Client, RPL_MOTDSTART_MSG, + Client_ID( Client ), Client_ID( Client_ThisServer( ))); +} + +static bool +Show_MOTD_Sendline(CLIENT *Client, const char *msg) +{ + return IRC_WriteStrClient(Client, RPL_MOTD_MSG, Client_ID( Client ), msg); +} + +static bool +Show_MOTD_End(CLIENT *Client) +{ + if (!IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG, Client_ID(Client))) + return DISCONNECTED; + + if (*Conf_CloakHost) + return IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG, + Client_ID(Client), + Client_Hostname(Client)); + + return CONNECTED; +} + +#ifdef SSL_SUPPORT +static bool Show_MOTD_SSLInfo(CLIENT *Client) +{ + bool ret = true; + char buf[COMMAND_LEN] = "Connected using Cipher "; + + if (!Conn_GetCipherInfo(Client_Conn(Client), buf + 23, sizeof buf - 23)) + return true; + + if (!Show_MOTD_Sendline(Client, buf)) + ret = false; + + return ret; +} +#else +static inline bool +Show_MOTD_SSLInfo(UNUSED CLIENT *c) +{ return true; } +#endif + +/* Global functions */ + GLOBAL bool IRC_ADMIN(CLIENT *Client, REQUEST *Req ) { @@ -467,40 +902,6 @@ IRC_NAMES( CLIENT *Client, REQUEST *Req ) } /* IRC_NAMES */ -static unsigned int -t_diff(time_t *t, const time_t d) -{ - time_t diff, remain; - - diff = *t / d; - remain = diff * d; - *t -= remain; - - return (unsigned int)diff; -} - - -static unsigned int -uptime_days(time_t *now) -{ - return t_diff(now, 60 * 60 * 24); -} - - -static unsigned int -uptime_hrs(time_t *now) -{ - return t_diff(now, 60 * 60); -} - - -static unsigned int -uptime_mins(time_t *now) -{ - return t_diff(now, 60); -} - - /** * Handler for the IRC command "STATS". * See RFC 2812 section 3.4.4. @@ -785,224 +1186,9 @@ IRC_VERSION( CLIENT *Client, REQUEST *Req ) NGIRCd_DebugLevel, Conf_ServerName, NGIRCd_VersionAddition); } /* IRC_VERSION */ - - -static bool -write_whoreply(CLIENT *Client, CLIENT *c, const char *channelname, const char *flags) -{ - return IRC_WriteStrClient(Client, RPL_WHOREPLY_MSG, Client_ID(Client), - channelname, Client_User(c), - Client_HostnameDisplayed(c), - Client_ID(Client_Introducer(c)), Client_ID(c), - flags, Client_Hops(c), Client_Info(c)); -} -static const char * -who_flags_status(const char *client_modes) -{ - if (strchr(client_modes, 'a')) - return "G"; /* away */ - return "H"; -} - - /** - * Return channel user mode prefix(es). - * - * @param Client The client requesting the mode prefixes. - * @param chan_user_modes String with channel user modes. - * @param str String buffer to which the prefix(es) will be appended. - * @param len Size of "str" buffer. - * @return Pointer to "str". - */ -static char * -who_flags_qualifier(CLIENT *Client, const char *chan_user_modes, - char *str, size_t len) -{ - assert(Client != NULL); - - if (Client_Cap(Client) & CLIENT_CAP_MULTI_PREFIX) { - if (strchr(chan_user_modes, 'q')) - strlcat(str, "~", len); - if (strchr(chan_user_modes, 'a')) - strlcat(str, "&", len); - if (strchr(chan_user_modes, 'o')) - strlcat(str, "@", len); - if (strchr(chan_user_modes, 'h')) - strlcat(str, "%", len); - if (strchr(chan_user_modes, 'v')) - strlcat(str, "+", len); - - return str; - } - - if (strchr(chan_user_modes, 'q')) - strlcat(str, "~", len); - else if (strchr(chan_user_modes, 'a')) - strlcat(str, "&", len); - else if (strchr(chan_user_modes, 'o')) - strlcat(str, "@", len); - else if (strchr(chan_user_modes, 'h')) - strlcat(str, "%", len); - else if (strchr(chan_user_modes, 'v')) - strlcat(str, "+", len); - - return str; -} - - -/** - * Send WHO reply for a "channel target" ("WHO #channel"). - * - * @param Client Client requesting the information. - * @param Chan Channel being requested. - * @param OnlyOps Only display IRC operators. - * @return CONNECTED or DISCONNECTED. - */ -static bool -IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) -{ - bool is_visible, is_member, is_ircop; - CL2CHAN *cl2chan; - const char *client_modes; - char flags[10]; - CLIENT *c; - int count = 0; - - assert( Client != NULL ); - assert( Chan != NULL ); - - IRC_SetPenalty(Client, 1); - - is_member = Channel_IsMemberOf(Chan, Client); - - /* Secret channel? */ - if (!is_member && strchr(Channel_Modes(Chan), 's')) - return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, - Client_ID(Client), Channel_Name(Chan)); - - cl2chan = Channel_FirstMember(Chan); - for (; cl2chan ; cl2chan = Channel_NextMember(Chan, cl2chan)) { - c = Channel_GetClient(cl2chan); - - client_modes = Client_Modes(c); - is_ircop = strchr(client_modes, 'o') != NULL; - if (OnlyOps && !is_ircop) - continue; - - is_visible = strchr(client_modes, 'i') == NULL; - if (is_member || is_visible) { - strlcpy(flags, who_flags_status(client_modes), - sizeof(flags)); - if (is_ircop) - strlcat(flags, "*", sizeof(flags)); - - who_flags_qualifier(Client, Channel_UserModes(Chan, c), - flags, sizeof(flags)); - - if (!write_whoreply(Client, c, Channel_Name(Chan), - flags)) - return DISCONNECTED; - count++; - } - } - - /* If there are a lot of clients, augment penalty a bit */ - if (count > MAX_RPL_WHO) - IRC_SetPenalty(Client, 1); - - return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), - Channel_Name(Chan)); -} - - -/** - * Send WHO reply for a "mask target" ("WHO m*sk"). - * - * @param Client Client requesting the information. - * @param Mask Mask being requested or NULL for "all" clients. - * @param OnlyOps Only display IRC operators. - * @return CONNECTED or DISCONNECTED. - */ -static bool -IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps) -{ - CLIENT *c; - CL2CHAN *cl2chan; - CHANNEL *chan; - bool client_match, is_visible; - char flags[4]; - int count = 0; - - assert (Client != NULL); - - if (Mask) - ngt_LowerStr(Mask); - - IRC_SetPenalty(Client, 3); - for (c = Client_First(); c != NULL; c = Client_Next(c)) { - if (Client_Type(c) != CLIENT_USER) - continue; - - if (OnlyOps && !Client_HasMode(c, 'o')) - continue; - - if (Mask) { - /* Match pattern against user host/server/name/nick */ - client_match = MatchCaseInsensitive(Mask, - Client_Hostname(c)); - if (!client_match) - client_match = MatchCaseInsensitive(Mask, - Client_ID(Client_Introducer(c))); - if (!client_match) - client_match = MatchCaseInsensitive(Mask, - Client_Info(c)); - if (!client_match) - client_match = MatchCaseInsensitive(Mask, - Client_ID(c)); - if (!client_match) - continue; /* no match: skip this client */ - } - - is_visible = !Client_HasMode(c, 'i'); - - /* Target client is invisible, but mask matches exactly? */ - if (!is_visible && Mask && strcasecmp(Client_ID(c), Mask) == 0) - is_visible = true; - - /* Target still invisible, but are both on the same channel? */ - if (!is_visible) { - cl2chan = Channel_FirstChannelOf(Client); - while (cl2chan && !is_visible) { - chan = Channel_GetChannel(cl2chan); - if (Channel_IsMemberOf(chan, c)) - is_visible = true; - cl2chan = Channel_NextChannelOf(Client, cl2chan); - } - } - - if (!is_visible) /* target user is not visible */ - continue; - - if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO")) - break; - - strlcpy(flags, who_flags_status(Client_Modes(c)), sizeof(flags)); - if (strchr(Client_Modes(c), 'o')) - strlcat(flags, "*", sizeof(flags)); - - if (!write_whoreply(Client, c, "*", flags)) - return DISCONNECTED; - count++; - } - - return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), - Mask ? Mask : "*"); -} - - -/** * Handler for the IRC "WHO" command. * * See RFC 2812, 3.6.1 "Who query". @@ -1060,136 +1246,6 @@ IRC_WHO(CLIENT *Client, REQUEST *Req) /** - * Generate WHOIS reply of one actual client. - * - * @param Client The client from which this command has been received. - * @param from The client requesting the information ("originator"). - * @param c The client of which information should be returned. - * @return CONNECTED or DISCONNECTED. - */ -static bool -IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) -{ - char str[LINE_LEN + 1]; - CL2CHAN *cl2chan; - CHANNEL *chan; - - assert(Client != NULL); - assert(from != NULL); - assert(c != NULL); - - /* Nick, user, hostname and client info */ - if (!IRC_WriteStrClient(from, RPL_WHOISUSER_MSG, Client_ID(from), - Client_ID(c), Client_User(c), - Client_HostnameDisplayed(c), Client_Info(c))) - return DISCONNECTED; - - /* Server */ - if (!IRC_WriteStrClient(from, RPL_WHOISSERVER_MSG, Client_ID(from), - Client_ID(c), Client_ID(Client_Introducer(c)), - Client_Info(Client_Introducer(c)))) - return DISCONNECTED; - - /* Channels */ - snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG, - Client_ID(from), Client_ID(c)); - cl2chan = Channel_FirstChannelOf(c); - while (cl2chan) { - chan = Channel_GetChannel(cl2chan); - assert(chan != NULL); - - /* next */ - cl2chan = Channel_NextChannelOf(c, cl2chan); - - /* Secret channel? */ - if (strchr(Channel_Modes(chan), 's') - && !Channel_IsMemberOf(chan, Client)) - continue; - - /* Local channel and request is not from a user? */ - if (Client_Type(Client) == CLIENT_SERVER - && Channel_IsLocal(chan)) - continue; - - /* Concatenate channel names */ - if (str[strlen(str) - 1] != ':') - strlcat(str, " ", sizeof(str)); - - who_flags_qualifier(Client, Channel_UserModes(chan, c), - str, sizeof(str)); - strlcat(str, Channel_Name(chan), sizeof(str)); - - if (strlen(str) > (LINE_LEN - CHANNEL_NAME_LEN - 4)) { - /* Line becomes too long: send it! */ - if (!IRC_WriteStrClient(Client, "%s", str)) - return DISCONNECTED; - snprintf(str, sizeof(str), RPL_WHOISCHANNELS_MSG, - Client_ID(from), Client_ID(c)); - } - } - if(str[strlen(str) - 1] != ':') { - /* There is data left to send: */ - if (!IRC_WriteStrClient(Client, "%s", str)) - return DISCONNECTED; - } - - /* IRC-Operator? */ - if (Client_HasMode(c, 'o') && - !IRC_WriteStrClient(from, RPL_WHOISOPERATOR_MSG, - Client_ID(from), Client_ID(c))) - return DISCONNECTED; - - /* IRC-Bot? */ - if (Client_HasMode(c, 'B') && - !IRC_WriteStrClient(from, RPL_WHOISBOT_MSG, - Client_ID(from), Client_ID(c))) - return DISCONNECTED; - - /* Connected using SSL? */ - if (Conn_UsesSSL(Client_Conn(c)) && - !IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from), - Client_ID(c))) - return DISCONNECTED; - - /* Registered nickname? */ - if (Client_HasMode(c, 'R') && - !IRC_WriteStrClient(from, RPL_WHOISREGNICK_MSG, - Client_ID(from), Client_ID(c))) - return DISCONNECTED; - - /* Local client and requester is the user itself or an IRC Op? */ - if (Client_Conn(c) > NONE && - (from == c || (!Conf_MorePrivacy && Client_HasMode(from, 'o')))) { - /* Client hostname */ - if (!IRC_WriteStrClient(from, RPL_WHOISHOST_MSG, - Client_ID(from), Client_ID(c), Client_Hostname(c), - Conn_GetIPAInfo(Client_Conn(c)))) - return DISCONNECTED; - /* Client modes */ - if (!IRC_WriteStrClient(from, RPL_WHOISMODES_MSG, - Client_ID(from), Client_ID(c), Client_Modes(c))) - return DISCONNECTED; - } - - /* Idle and signon time (local clients only!) */ - if (!Conf_MorePrivacy && Client_Conn(c) > NONE && - !IRC_WriteStrClient(from, RPL_WHOISIDLE_MSG, - Client_ID(from), Client_ID(c), - (unsigned long)Conn_GetIdle(Client_Conn(c)), - (unsigned long)Conn_GetSignon(Client_Conn(c)))) - return DISCONNECTED; - - /* Away? */ - if (Client_HasMode(c, 'a') && - !IRC_WriteStrClient(from, RPL_AWAY_MSG, - Client_ID(from), Client_ID(c), Client_Away(c))) - return DISCONNECTED; - - return CONNECTED; -} /* IRC_WHOIS_SendReply */ - - -/** * Handler for the IRC "WHOIS" command. * * See RFC 2812, 3.6.2 "Whois query". @@ -1309,22 +1365,6 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req ) } /* IRC_WHOIS */ -static bool -WHOWAS_EntryWrite(CLIENT *prefix, WHOWAS *entry) -{ - char t_str[60]; - - (void)strftime(t_str, sizeof(t_str), "%a %b %d %H:%M:%S %Y", - localtime(&entry->time)); - - if (!IRC_WriteStrClient(prefix, RPL_WHOWASUSER_MSG, Client_ID(prefix), - entry->id, entry->user, entry->host, entry->info)) - return DISCONNECTED; - - return IRC_WriteStrClient(prefix, RPL_WHOISSERVER_MSG, Client_ID(prefix), - entry->id, entry->server, t_str); -} - /** * IRC "WHOWAS" function. * This function implements the IRC command "WHOWHAS". It handles local @@ -1501,55 +1541,8 @@ IRC_Send_LUSERS(CLIENT *Client) return CONNECTED; } /* IRC_Send_LUSERS */ - - -static bool -Show_MOTD_Start(CLIENT *Client) -{ - return IRC_WriteStrClient(Client, RPL_MOTDSTART_MSG, - Client_ID( Client ), Client_ID( Client_ThisServer( ))); -} - -static bool -Show_MOTD_Sendline(CLIENT *Client, const char *msg) -{ - return IRC_WriteStrClient(Client, RPL_MOTD_MSG, Client_ID( Client ), msg); -} - -static bool -Show_MOTD_End(CLIENT *Client) -{ - if (!IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG, Client_ID(Client))) - return DISCONNECTED; - - if (*Conf_CloakHost) - return IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG, - Client_ID(Client), - Client_Hostname(Client)); - return CONNECTED; -} -#ifdef SSL_SUPPORT -static bool Show_MOTD_SSLInfo(CLIENT *Client) -{ - bool ret = true; - char buf[COMMAND_LEN] = "Connected using Cipher "; - - if (!Conn_GetCipherInfo(Client_Conn(Client), buf + 23, sizeof buf - 23)) - return true; - - if (!Show_MOTD_Sendline(Client, buf)) - ret = false; - - return ret; -} -#else -static inline bool -Show_MOTD_SSLInfo(UNUSED CLIENT *c) -{ return true; } -#endif - GLOBAL bool IRC_Show_MOTD( CLIENT *Client ) {