X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fm_who.c;h=49df47580c393399ab9e97ae91a50dced6cc19a6;hb=refs%2Fheads%2Fupstream-ssl;hp=a658fbd1c758e98d8645b890219f0ede7e983a8e;hpb=7ec4144c6b646292025b62ebeb1f974e02c03698;p=ircu2.10.12-pk.git diff --git a/ircd/m_who.c b/ircd/m_who.c index a658fbd..49df475 100644 --- a/ircd/m_who.c +++ b/ircd/m_who.c @@ -79,19 +79,14 @@ * note: it is guaranteed that parv[0]..parv[parc-1] are all * non-NULL pointers. */ -#if 0 -/* - * No need to include handlers.h here the signatures must match - * and we don't need to force a rebuild of all the handlers everytime - * we add a new one to the list. --Bleep - */ -#include "handlers.h" -#endif /* 0 */ +#include "config.h" + #include "channel.h" #include "client.h" #include "hash.h" #include "ircd.h" #include "ircd_chattr.h" +#include "ircd_features.h" #include "ircd_log.h" #include "ircd_reply.h" #include "ircd_string.h" @@ -99,17 +94,15 @@ #include "numeric.h" #include "numnicks.h" #include "send.h" -#include "support.h" #include "whocmds.h" - -#include +/* #include -- Now using assert in ircd_log.h */ #include /* - * A little spin-marking utility to tell us wich clients we have already - * processed and wich not + * A little spin-marking utility to tell us which clients we have already + * processed and which not */ static int who_marker = 0; static void move_marker(void) @@ -119,15 +112,15 @@ static void move_marker(void) struct Client *cptr = GlobalClientList; while (cptr) { - cptr->marker = 0; - cptr = cptr->next; + cli_marker(cptr) = 0; + cptr = cli_next(cptr); } who_marker++; } } #define CheckMark(x, y) ((x == y) ? 0 : (x = y)) -#define Process(cptr) CheckMark(cptr->marker, who_marker) +#define Process(cptr) CheckMark(cli_marker(cptr), who_marker) /* * m_who - generic message handler @@ -150,7 +143,7 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) struct Client *acptr; /* Client to show */ int bitsel; /* Mask of selectors to apply */ - int matchsel; /* Wich fields the match should apply on */ + int matchsel; /* Which fields the match should apply on */ int counter; /* Query size counter, initially used to count fields */ int commas; /* Does our mask contain any comma ? @@ -181,19 +174,21 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) while (((ch = *(p++))) && (ch != '%') && (ch != ',')) switch (ch) { + case 'd': + case 'D': + bitsel |= WHOSELECT_DELAY; + continue; case 'o': case 'O': bitsel |= WHOSELECT_OPER; continue; case 'x': case 'X': - bitsel |= WHOSELECT_EXTRA; -#ifdef WPATH - if (IsAnOper(sptr)) - write_log(WPATH, "# " TIME_T_FMT " %s!%s@%s WHO %s %s\n", - CurrentTime, sptr->name, sptr->user->username, sptr->user->host, - (BadPtr(parv[3]) ? parv[1] : parv[3]), parv[2]); -#endif /* WPATH */ + if (HasPriv(sptr, PRIV_WHOX) && IsAnOper(sptr)) { + bitsel |= WHOSELECT_EXTRA; + log_write(LS_WHO, L_INFO, LOG_NOSNOTICE, "%#C WHO %s %s", sptr, + (BadPtr(parv[3]) ? parv[1] : parv[3]), parv[2]); + } continue; case 'n': case 'N': @@ -219,6 +214,10 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) case 'R': matchsel |= WHO_FIELD_REN; continue; + case 'a': + case 'A': + matchsel |= WHO_FIELD_ACC; + continue; } if (ch == '%') while ((ch = *p++) && (ch != ',')) @@ -269,326 +268,13 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) case 'U': fields |= WHO_FIELD_UID; break; - default: + case 'a': + case 'A': + fields |= WHO_FIELD_ACC; break; - } - }; - if (ch) - qrt = p; - } - - if (!matchsel) - matchsel = WHO_FIELD_DEF; - if (!fields) - counter = 7; - - if (qrt && (fields & WHO_FIELD_QTY)) - { - p = qrt; - if (!((*p > '9') || (*p < '0'))) - p++; - if (!((*p > '9') || (*p < '0'))) - p++; - if (!((*p > '9') || (*p < '0'))) - p++; - *p = '\0'; - } - else - qrt = 0; - - /* I'd love to add also a check on the number of matches fields per time */ - counter = (2048 / (counter + 4)); - if (mask && (strlen(mask) > 510)) - mask[510] = '\0'; - move_marker(); - commas = (mask && strchr(mask, ',')); - - /* First treat mask as a list of plain nicks/channels */ - if (mask) - { - strcpy(mymask, mask); - for (p = 0, nick = ircd_strtok(&p, mymask, ","); nick; - nick = ircd_strtok(&p, 0, ",")) - { - if (IsChannelName(nick) && (chptr = FindChannel(nick))) - { - isthere = (find_channel_member(sptr, chptr) != 0); - if (isthere || SEE_CHANNEL(sptr, chptr, bitsel)) - { - struct Membership* member; - for (member = chptr->members; member; member = member->next_member) - { - acptr = member->user; - if ((bitsel & WHOSELECT_OPER) && !(IsAnOper(acptr))) - continue; - if ((acptr != sptr) && (member->status & CHFL_ZOMBIE)) - continue; - if (!(isthere || (SEE_USER(sptr, acptr, bitsel)))) - continue; - if (!Process(acptr)) /* This can't be moved before other checks */ - continue; - if (!(isthere || (SHOW_MORE(sptr, counter)))) - break; - do_who(sptr, acptr, chptr, fields, qrt); - } - } - } - else - { - if ((acptr = FindUser(nick)) && - ((!(bitsel & WHOSELECT_OPER)) || IsAnOper(acptr)) && - Process(acptr) && SHOW_MORE(sptr, counter)) - { - do_who(sptr, acptr, 0, fields, qrt); - } - } - } - } - - /* If we didn't have any comma in the mask treat it as a - real mask and try to match all relevant fields */ - if (!(commas || (counter < 1))) - { - int minlen, cset; - static struct in_mask imask; - if (mask) - { - matchcomp(mymask, &minlen, &cset, mask); - if (matchcompIP(&imask, mask)) - matchsel &= ~WHO_FIELD_NIP; - if ((minlen > NICKLEN) || !(cset & NTL_IRCNK)) - matchsel &= ~WHO_FIELD_NIC; - if ((matchsel & WHO_FIELD_SER) && - ((minlen > HOSTLEN) || (!(cset & NTL_IRCHN)) - || (!markMatchexServer(mymask, minlen)))) - matchsel &= ~WHO_FIELD_SER; - if ((minlen > USERLEN) || !(cset & NTL_IRCUI)) - matchsel &= ~WHO_FIELD_UID; - if ((minlen > HOSTLEN) || !(cset & NTL_IRCHN)) - matchsel &= ~WHO_FIELD_HOS; - } - - /* First of all loop through the clients in common channels */ - if ((!(counter < 1)) && matchsel) { - struct Membership* member; - struct Membership* chan; - for (chan = sptr->user->channel; chan; chan = chan->next_channel) { - chptr = chan->channel; - for (member = chptr->members; member; member = member->next_member) - { - acptr = member->user; - if (!(IsUser(acptr) && Process(acptr))) - continue; /* Now Process() is at the beginning, if we fail - we'll never have to show this acptr in this query */ - if ((bitsel & WHOSELECT_OPER) && !IsAnOper(acptr)) - continue; - if ((mask) && - ((!(matchsel & WHO_FIELD_NIC)) - || matchexec(acptr->name, mymask, minlen)) - && ((!(matchsel & WHO_FIELD_UID)) - || matchexec(acptr->user->username, mymask, minlen)) - && ((!(matchsel & WHO_FIELD_SER)) - || (!(acptr->user->server->flags & FLAGS_MAP))) - && ((!(matchsel & WHO_FIELD_HOS)) - || matchexec(acptr->user->host, mymask, minlen)) - && ((!(matchsel & WHO_FIELD_REN)) - || matchexec(acptr->info, mymask, minlen)) - && ((!(matchsel & WHO_FIELD_NIP)) - || ((((acptr->ip.s_addr & imask.mask.s_addr) != - imask.bits.s_addr)) || (imask.fall - && matchexec(ircd_ntoa((const char*) &acptr->ip), mymask, minlen))))) - continue; - if (!SHOW_MORE(sptr, counter)) - break; - do_who(sptr, acptr, chptr, fields, qrt); - } - } - } - /* Loop through all clients :-\, if we still have something to match to - and we can show more clients */ - if ((!(counter < 1)) && matchsel) - for (acptr = me.prev; acptr; acptr = acptr->prev) - { - if (!(IsUser(acptr) && Process(acptr))) - continue; - if ((bitsel & WHOSELECT_OPER) && !IsAnOper(acptr)) - continue; - if (!(SEE_USER(sptr, acptr, bitsel))) - continue; - if ((mask) && - ((!(matchsel & WHO_FIELD_NIC)) - || matchexec(acptr->name, mymask, minlen)) - && ((!(matchsel & WHO_FIELD_UID)) - || matchexec(acptr->user->username, mymask, minlen)) - && ((!(matchsel & WHO_FIELD_SER)) - || (!(acptr->user->server->flags & FLAGS_MAP))) - && ((!(matchsel & WHO_FIELD_HOS)) - || matchexec(acptr->user->host, mymask, minlen)) - && ((!(matchsel & WHO_FIELD_REN)) - || matchexec(acptr->info, mymask, minlen)) - && ((!(matchsel & WHO_FIELD_NIP)) - || ((((acptr->ip.s_addr & imask.mask.s_addr) != imask.bits.s_addr)) - || (imask.fall - && matchexec(ircd_ntoa((const char*) &acptr->ip), mymask, minlen))))) - continue; - if (!SHOW_MORE(sptr, counter)) - break; - do_who(sptr, acptr, 0, fields, qrt); - } - } - - /* Make a clean mask suitable to be sent in the "end of" */ - if (mask && (p = strchr(mask, ' '))) - *p = '\0'; - sendto_one(sptr, rpl_str(RPL_ENDOFWHO), - me.name, parv[0], BadPtr(mask) ? "*" : mask); - - /* Notify the user if we decided that his query was too long */ - if (counter < 0) - sendto_one(sptr, err_str(ERR_QUERYTOOLONG), me.name, parv[0], "WHO"); - - return 0; -} - - -#if 0 -/* - * m_who - * - * parv[0] = sender prefix - * parv[1] = nickname mask list - * parv[2] = additional selection flag, only 'o' for now. - * and %flags to specify what fields to output - * plus a ,querytype if the t flag is specified - * so the final thing will be like o%tnchu,777 - * parv[3] = _optional_ parameter that overrides parv[1] - * This can be used as "/quote who foo % :The Black Hacker - * to find me, parv[3] _can_ contain spaces !. - */ - -int m_who(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) -{ - char *mask; /* The mask we are looking for */ - char ch; /* Scratch char register */ - struct Channel *chptr; /* Channel to show */ - struct Client *acptr; /* Client to show */ - - int bitsel; /* Mask of selectors to apply */ - int matchsel; /* Wich fields the match should apply on */ - int counter; /* Query size counter, - initially used to count fields */ - int commas; /* Does our mask contain any comma ? - If so is a list.. */ - int fields; /* Mask of fields to show */ - int isthere = 0; /* When this set the user is member of chptr */ - char *nick; /* Single element extracted from - the mask list */ - char *p; /* Scratch char pointer */ - char *qrt; /* Pointer to the query type */ - static char mymask[512]; /* To save the mask before corrupting it */ - - /* Let's find where is our mask, and if actually contains something */ - mask = ((parc > 1) ? parv[1] : 0); - if (parc > 3 && parv[3]) - mask = parv[3]; - if (mask && ((mask[0] == '\0') || - (mask[1] == '\0' && ((mask[0] == '0') || (mask[0] == '*'))))) - mask = 0; - - /* Evaluate the flags now, we consider the second parameter - as "matchFlags%fieldsToInclude,querytype" */ - bitsel = fields = counter = matchsel = 0; - qrt = 0; - if (parc > 2 && parv[2] && *parv[2]) - { - p = parv[2]; - while (((ch = *(p++))) && (ch != '%') && (ch != ',')) - switch (ch) - { - case 'o': - case 'O': - bitsel |= WHOSELECT_OPER; - continue; - case 'x': - case 'X': - bitsel |= WHOSELECT_EXTRA; -#ifdef WPATH - if (IsAnOper(sptr)) - write_log(WPATH, "# " TIME_T_FMT " %s!%s@%s WHO %s %s\n", - CurrentTime, sptr->name, sptr->user->username, sptr->user->host, - (BadPtr(parv[3]) ? parv[1] : parv[3]), parv[2]); -#endif /* WPATH */ - continue; - case 'n': - case 'N': - matchsel |= WHO_FIELD_NIC; - continue; - case 'u': - case 'U': - matchsel |= WHO_FIELD_UID; - continue; - case 'h': - case 'H': - matchsel |= WHO_FIELD_HOS; - continue; - case 'i': - case 'I': - matchsel |= WHO_FIELD_NIP; - continue; - case 's': - case 'S': - matchsel |= WHO_FIELD_SER; - continue; - case 'r': - case 'R': - matchsel |= WHO_FIELD_REN; - continue; - } - if (ch == '%') - while ((ch = *p++) && (ch != ',')) - { - counter++; - switch (ch) - { - case 'c': - case 'C': - fields |= WHO_FIELD_CHA; - break; - case 'd': - case 'D': - fields |= WHO_FIELD_DIS; - break; - case 'f': - case 'F': - fields |= WHO_FIELD_FLA; - break; - case 'h': - case 'H': - fields |= WHO_FIELD_HOS; - break; - case 'i': - case 'I': - fields |= WHO_FIELD_NIP; - break; - case 'n': - case 'N': - fields |= WHO_FIELD_NIC; - break; - case 'r': - case 'R': - fields |= WHO_FIELD_REN; - break; - case 's': - case 'S': - fields |= WHO_FIELD_SER; - break; - case 't': - case 'T': - fields |= WHO_FIELD_QTY; - break; - case 'u': - case 'U': - fields |= WHO_FIELD_UID; + case 'o': + case 'O': + fields |= WHO_FIELD_OPL; break; default: break; @@ -603,6 +289,9 @@ int m_who(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) if (!fields) counter = 7; + if (feature_bool(FEAT_HIS_WHO_SERVERNAME) && !IsAnOper(sptr)) + matchsel &= ~WHO_FIELD_SER; + if (qrt && (fields & WHO_FIELD_QTY)) { p = qrt; @@ -640,9 +329,12 @@ int m_who(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) for (member = chptr->members; member; member = member->next_member) { acptr = member->user; - if ((bitsel & WHOSELECT_OPER) && !(IsAnOper(acptr))) + if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr)) continue; - if ((acptr != sptr) && (member->status & CHFL_ZOMBIE)) + if ((acptr != sptr) + && ((member->status & CHFL_ZOMBIE) + || ((member->status & CHFL_DELAYED) + && !(bitsel & WHOSELECT_DELAY)))) continue; if (!(isthere || (SEE_USER(sptr, acptr, bitsel)))) continue; @@ -657,7 +349,7 @@ int m_who(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) else { if ((acptr = FindUser(nick)) && - ((!(bitsel & WHOSELECT_OPER)) || IsAnOper(acptr)) && + ((!(bitsel & WHOSELECT_OPER)) || SeeOper(sptr,acptr)) && Process(acptr) && SHOW_MORE(sptr, counter)) { do_who(sptr, acptr, 0, fields, qrt); @@ -670,12 +362,14 @@ int m_who(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) real mask and try to match all relevant fields */ if (!(commas || (counter < 1))) { + struct irc_in_addr imask; int minlen, cset; - static struct in_mask imask; + unsigned char ibits; + if (mask) { matchcomp(mymask, &minlen, &cset, mask); - if (matchcompIP(&imask, mask)) + if (!ipmask_parse(mask, &imask, &ibits)) matchsel &= ~WHO_FIELD_NIP; if ((minlen > NICKLEN) || !(cset & NTL_IRCNK)) matchsel &= ~WHO_FIELD_NIC; @@ -687,13 +381,15 @@ int m_who(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) matchsel &= ~WHO_FIELD_UID; if ((minlen > HOSTLEN) || !(cset & NTL_IRCHN)) matchsel &= ~WHO_FIELD_HOS; + if ((minlen > ACCOUNTLEN)) + matchsel &= ~WHO_FIELD_ACC; } /* First of all loop through the clients in common channels */ if ((!(counter < 1)) && matchsel) { struct Membership* member; struct Membership* chan; - for (chan = sptr->user->channel; chan; chan = chan->next_channel) { + for (chan = cli_user(sptr)->channel; chan; chan = chan->next_channel) { chptr = chan->channel; for (member = chptr->members; member; member = member->next_member) { @@ -701,23 +397,28 @@ int m_who(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) if (!(IsUser(acptr) && Process(acptr))) continue; /* Now Process() is at the beginning, if we fail we'll never have to show this acptr in this query */ - if ((bitsel & WHOSELECT_OPER) && !IsAnOper(acptr)) - continue; + if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr)) + continue; if ((mask) && ((!(matchsel & WHO_FIELD_NIC)) - || matchexec(acptr->name, mymask, minlen)) + || matchexec(cli_name(acptr), mymask, minlen)) && ((!(matchsel & WHO_FIELD_UID)) - || matchexec(acptr->user->username, mymask, minlen)) + || matchexec(cli_user(acptr)->username, mymask, minlen)) && ((!(matchsel & WHO_FIELD_SER)) - || (!(acptr->user->server->flags & FLAGS_MAP))) + || (!(HasFlag(cli_user(acptr)->server, FLAG_MAP)))) + && ((!(matchsel & WHO_FIELD_HOS)) + || matchexec(cli_user(acptr)->host, mymask, minlen)) && ((!(matchsel & WHO_FIELD_HOS)) - || matchexec(acptr->user->host, mymask, minlen)) + || !HasHiddenHost(acptr) + || !IsAnOper(sptr) + || matchexec(cli_user(acptr)->realhost, mymask, minlen)) && ((!(matchsel & WHO_FIELD_REN)) - || matchexec(acptr->info, mymask, minlen)) + || matchexec(cli_info(acptr), mymask, minlen)) && ((!(matchsel & WHO_FIELD_NIP)) - || ((((acptr->ip.s_addr & imask.mask.s_addr) != - imask.bits.s_addr)) || (imask.fall - && matchexec(inet_ntoa(acptr->ip), mymask, minlen))))) + || (HasHiddenHost(acptr) && !IsAnOper(sptr)) + || !ipmask_check(&cli_ip(acptr), &imask, ibits)) + && ((!(matchsel & WHO_FIELD_ACC)) + || matchexec(cli_user(acptr)->account, mymask, minlen))) continue; if (!SHOW_MORE(sptr, counter)) break; @@ -728,29 +429,34 @@ int m_who(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) /* Loop through all clients :-\, if we still have something to match to and we can show more clients */ if ((!(counter < 1)) && matchsel) - for (acptr = me.prev; acptr; acptr = acptr->prev) + for (acptr = cli_prev(&me); acptr; acptr = cli_prev(acptr)) { if (!(IsUser(acptr) && Process(acptr))) continue; - if ((bitsel & WHOSELECT_OPER) && !IsAnOper(acptr)) - continue; + if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr)) + continue; if (!(SEE_USER(sptr, acptr, bitsel))) continue; if ((mask) && ((!(matchsel & WHO_FIELD_NIC)) - || matchexec(acptr->name, mymask, minlen)) + || matchexec(cli_name(acptr), mymask, minlen)) && ((!(matchsel & WHO_FIELD_UID)) - || matchexec(acptr->user->username, mymask, minlen)) + || matchexec(cli_user(acptr)->username, mymask, minlen)) && ((!(matchsel & WHO_FIELD_SER)) - || (!(acptr->user->server->flags & FLAGS_MAP))) + || (!(HasFlag(cli_user(acptr)->server, FLAG_MAP)))) + && ((!(matchsel & WHO_FIELD_HOS)) + || matchexec(cli_user(acptr)->host, mymask, minlen)) && ((!(matchsel & WHO_FIELD_HOS)) - || matchexec(acptr->user->host, mymask, minlen)) + || !HasHiddenHost(acptr) + || !IsAnOper(sptr) + || matchexec(cli_user(acptr)->realhost, mymask, minlen)) && ((!(matchsel & WHO_FIELD_REN)) - || matchexec(acptr->info, mymask, minlen)) + || matchexec(cli_info(acptr), mymask, minlen)) && ((!(matchsel & WHO_FIELD_NIP)) - || ((((acptr->ip.s_addr & imask.mask.s_addr) != imask.bits.s_addr)) - || (imask.fall - && matchexec(inet_ntoa(acptr->ip), mymask, minlen))))) + || (HasHiddenHost(acptr) && !IsAnOper(sptr)) + || !ipmask_check(&cli_ip(acptr), &imask, ibits)) + && ((!(matchsel & WHO_FIELD_ACC)) + || matchexec(cli_user(acptr)->account, mymask, minlen))) continue; if (!SHOW_MORE(sptr, counter)) break; @@ -761,14 +467,10 @@ int m_who(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) /* Make a clean mask suitable to be sent in the "end of" */ if (mask && (p = strchr(mask, ' '))) *p = '\0'; - sendto_one(sptr, rpl_str(RPL_ENDOFWHO), - me.name, parv[0], BadPtr(mask) ? "*" : mask); - /* Notify the user if we decided that his query was too long */ if (counter < 0) - sendto_one(sptr, err_str(ERR_QUERYTOOLONG), me.name, parv[0], "WHO"); + send_reply(sptr, ERR_QUERYTOOLONG, BadPtr(mask) ? "*" : mask); + send_reply(sptr, RPL_ENDOFWHO, BadPtr(mask) ? "*" : mask); return 0; } -#endif /* 0 */ -