X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fwhocmds.c;h=0b166ba0bb0ebd7e8a0dbc94d4382a77efc952fc;hb=refs%2Fheads%2Fupstream;hp=775ad39dcf77df1e94c7b1dbdd068b5c1f9a824e;hpb=33707cfe88b434ba74eeee4bf395be59dd75127b;p=ircu2.10.12-pk.git diff --git a/ircd/whocmds.c b/ircd/whocmds.c index 775ad39..0b166ba 100644 --- a/ircd/whocmds.c +++ b/ircd/whocmds.c @@ -19,16 +19,22 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id$ */ +/** @file + * @brief Support functions for /WHO-like commands. + * @version $Id$ + */ +#include "config.h" + #include "whocmds.h" #include "channel.h" #include "client.h" #include "hash.h" #include "ircd.h" #include "ircd_chattr.h" +#include "ircd_features.h" #include "ircd_reply.h" +#include "ircd_snprintf.h" #include "ircd_string.h" #include "list.h" #include "match.h" @@ -41,16 +47,13 @@ #include "s_misc.h" #include "s_user.h" #include "send.h" -#include "sprintf_irc.h" #include "struct.h" -#include "support.h" #include "sys.h" #include "userload.h" #include "version.h" #include "whowas.h" #include "msg.h" -#include /* inet_ntoa */ #include #include #include @@ -58,14 +61,18 @@ #include #include -/* - * The function that actually prints out the WHO reply for a client found +/** Send a WHO reply to a client who asked. + * @param[in] sptr Client who is searching for other users. + * @param[in] acptr Client who may be shown to \a sptr. + * @param[in] repchan Shared channel that provides visibility. + * @param[in] fields Bitmask of WHO_FIELD_* values, indicating what to show. + * @param[in] qrt Query type string (ignored unless \a fields & WHO_FIELD_QTY). */ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan, int fields, char* qrt) { char *p1; - struct Channel *chptr = repchan; + struct Membership *chan = 0; static char buf1[512]; /* NOTE: with current fields list and sizes this _cannot_ overrun, @@ -78,14 +85,17 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan, unless the listing is for a channel service, we already know that there are no common channels, thus use PubChannel and not SeeChannel */ - if (!chptr && (!fields || (fields & (WHO_FIELD_CHA | WHO_FIELD_FLA))) && - !IsChannelService(acptr)) + if (repchan) + { + chan = find_channel_member(acptr, repchan); + } + else if ((!fields || (fields & (WHO_FIELD_CHA | WHO_FIELD_FLA))) + && !IsChannelService(acptr)) { - struct Membership* chan; - for (chan = cli_user(acptr)->channel; chan && !chptr; chan = chan->next_channel) + for (chan = cli_user(acptr)->channel; chan; chan = chan->next_channel) if (PubChannel(chan->channel) && (acptr == sptr || !IsZombie(chan))) - chptr = chan->channel; + break; } /* Place the fields one by one in the buffer and send it @@ -104,7 +114,7 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan, { char *p2; *(p1++) = ' '; - if ((p2 = (chptr ? chptr->chname : NULL))) + if ((p2 = (chan ? chan->channel->chname : NULL))) while ((*p2) && (*(p1++) = *(p2++))); else *(p1++) = '*'; @@ -119,7 +129,9 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan, if (fields & WHO_FIELD_NIP) { - const char* p2 = ircd_ntoa((const char*) &(cli_ip(acptr))); + const char* p2 = HasHiddenHost(acptr) && !IsAnOper(sptr) ? + feature_str(FEAT_HIDDEN_IP) : + ircd_ntoa(&cli_ip(acptr)); *(p1++) = ' '; while ((*p2) && (*(p1++) = *(p2++))); } @@ -133,7 +145,9 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan, if (!fields || (fields & WHO_FIELD_SER)) { - char *p2 = cli_name(cli_user(acptr)->server); + const char *p2 = (feature_bool(FEAT_HIS_WHO_SERVERNAME) && !IsAnOper(sptr)) ? + feature_str(FEAT_HIS_SERVERNAME) : + cli_name(cli_user(acptr)->server); *(p1++) = ' '; while ((*p2) && (*(p1++) = *(p2++))); } @@ -152,27 +166,34 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan, *(p1++) = 'G'; else *(p1++) = 'H'; - if (IsAnOper(acptr)) + if SeeOper(sptr,acptr) *(p1++) = '*'; - if (fields) { + if (!chan) { + /* No flags possible for the channel, so skip them all. */ + } + else if (fields) { /* If you specified flags then we assume you know how to parse * multiple channel status flags, as this is currently the only * way to know if someone has @'s *and* is +'d. */ - if (chptr && is_chan_op(acptr, chptr)) + if (IsChanOp(chan)) *(p1++) = '@'; - if (chptr && has_voice(acptr, chptr)) + if (HasVoice(chan)) *(p1++) = '+'; - if (chptr && is_zombie(acptr, chptr)) + if (IsZombie(chan)) *(p1++) = '!'; + if (IsDelayedJoin(chan)) + *(p1++) = '<'; } else { - if (chptr && is_chan_op(acptr, chptr)) + if (IsChanOp(chan)) *(p1++) = '@'; - else if (chptr && has_voice(acptr, chptr)) + else if (HasVoice(chan)) *(p1++) = '+'; - else if (chptr && is_zombie(acptr, chptr)) + else if (IsZombie(chan)) *(p1++) = '!'; + else if (IsDelayedJoin(chan)) + *(p1++) = '<'; } if (IsDeaf(acptr)) *(p1++) = 'd'; @@ -185,6 +206,8 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan, if (SendDebug(acptr)) *(p1++) = 'g'; } + if (HasHiddenHost(acptr)) + *(p1++) = 'x'; } if (!fields || (fields & WHO_FIELD_DIS)) @@ -192,18 +215,50 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan, *p1++ = ' '; if (!fields) *p1++ = ':'; /* Place colon here for default reply */ - p1 = sprintf_irc(p1, "%d", cli_hopcount(acptr)); + if (feature_bool(FEAT_HIS_WHO_HOPCOUNT) && !IsAnOper(sptr)) + *p1++ = (sptr == acptr) ? '0' : '3'; + else + /* three digit hopcount maximum */ + p1 += ircd_snprintf(0, p1, 3, "%d", cli_hopcount(acptr)); } if (fields & WHO_FIELD_IDL) { *p1++ = ' '; - if (MyUser(acptr)) { - p1 = sprintf_irc(p1, "%d", CurrentTime - cli_user(acptr)->last); - } - else { - *p1++ = '0'; - } + if (MyUser(acptr) && + (IsAnOper(sptr) || !feature_bool(FEAT_HIS_WHO_SERVERNAME) || + acptr == sptr)) + p1 += ircd_snprintf(0, p1, 11, "%d", + CurrentTime - cli_user(acptr)->last); + else + *p1++ = '0'; + } + + if (fields & WHO_FIELD_ACC) + { + char *p2 = cli_user(acptr)->account; + *(p1++) = ' '; + if (*p2) + while ((*p2) && (*(p1++) = *(p2++))); + else + *(p1++) = '0'; + } + + if (fields & WHO_FIELD_OPL) + { + if (!chan || !IsChanOp(chan)) + { + strcpy(p1, " n/a"); + p1 += 4; + } + else + { + int vis_level = MAXOPLEVEL; + if ((IsGlobalChannel(chan->channel->chname) ? IsOper(sptr) : IsAnOper(sptr)) + || is_chan_op(sptr, chan->channel)) + vis_level = OpLevel(chan); + p1 += ircd_snprintf(0, p1, 5, " %d", vis_level); + } } if (!fields || (fields & WHO_FIELD_REN)) @@ -221,4 +276,3 @@ void do_who(struct Client* sptr, struct Client* acptr, struct Channel* repchan, p1 = buf1; send_reply(sptr, fields ? RPL_WHOSPCRPL : RPL_WHOREPLY, ++p1); } -