#include "hash.h"
#include "ircd.h"
#include "ircd_chattr.h"
+#include "ircd_features.h"
#include "ircd_log.h"
-#include "ircd_policy.h"
#include "ircd_reply.h"
#include "ircd_string.h"
#include "match.h"
#include "numeric.h"
#include "numnicks.h"
#include "send.h"
-#include "support.h"
#include "whocmds.h"
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
#include <string.h>
/*
- * 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)
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 ?
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;
- if (HasPriv(sptr, PRIV_WHOX))
- log_write(LS_WHO, L_INFO, LOG_NOSNOTICE, "%#C WHO %s %s", sptr,
- (BadPtr(parv[3]) ? parv[1] : parv[3]), parv[2]);
+ 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':
case 'R':
matchsel |= WHO_FIELD_REN;
continue;
+ case 'a':
+ case 'A':
+ matchsel |= WHO_FIELD_ACC;
+ continue;
}
if (ch == '%')
while ((ch = *p++) && (ch != ','))
case 'U':
fields |= WHO_FIELD_UID;
break;
+ case 'a':
+ case 'A':
+ fields |= WHO_FIELD_ACC;
+ break;
+ case 'o':
+ case 'O':
+ fields |= WHO_FIELD_OPL;
+ break;
default:
break;
}
if (!fields)
counter = 7;
-#ifdef HEAD_IN_SAND_WHO_SERVERNAME
- if (!IsAnOper(sptr))
+ if (feature_bool(FEAT_HIS_WHO_SERVERNAME) && !IsAnOper(sptr))
matchsel &= ~WHO_FIELD_SER;
-#endif
if (qrt && (fields & WHO_FIELD_QTY))
{
for (member = chptr->members; member; member = member->next_member)
{
acptr = member->user;
- if ((bitsel & WHOSELECT_OPER) &&
- !(IsAnOper(acptr) && (HasPriv(acptr, PRIV_DISPLAY) ||
- HasPriv(sptr, PRIV_SEE_OPERS))))
+ 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;
else
{
if ((acptr = FindUser(nick)) &&
- ((!(bitsel & WHOSELECT_OPER)) ||
- (IsAnOper(acptr) && (HasPriv(acptr, PRIV_DISPLAY) ||
- HasPriv(sptr, PRIV_SEE_OPERS)))) &&
+ ((!(bitsel & WHOSELECT_OPER)) || SeeOper(sptr,acptr)) &&
Process(acptr) && SHOW_MORE(sptr, counter))
{
do_who(sptr, acptr, 0, fields, qrt);
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;
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 (!(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) && (HasPriv(acptr, PRIV_DISPLAY) ||
- HasPriv(sptr, PRIV_SEE_OPERS))))
+ if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr))
continue;
if ((mask) &&
((!(matchsel & WHO_FIELD_NIC))
&& ((!(matchsel & WHO_FIELD_UID))
|| matchexec(cli_user(acptr)->username, mymask, minlen))
&& ((!(matchsel & WHO_FIELD_SER))
- || (!(cli_flags(cli_user(acptr)->server) & 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(cli_info(acptr), mymask, minlen))
&& ((!(matchsel & WHO_FIELD_NIP))
|| (HasHiddenHost(acptr) && !IsAnOper(sptr))
- || ((((cli_ip(acptr).s_addr & imask.mask.s_addr) !=
- imask.bits.s_addr)) || (imask.fall
- && matchexec(ircd_ntoa((const char*) &(cli_ip(acptr))), mymask, minlen)))))
+ || !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;
{
if (!(IsUser(acptr) && Process(acptr)))
continue;
- if ((bitsel & WHOSELECT_OPER) &&
- !(IsAnOper(acptr) && (HasPriv(acptr, PRIV_DISPLAY) ||
- HasPriv(sptr, PRIV_SEE_OPERS))))
+ if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr))
continue;
if (!(SEE_USER(sptr, acptr, bitsel)))
continue;
&& ((!(matchsel & WHO_FIELD_UID))
|| matchexec(cli_user(acptr)->username, mymask, minlen))
&& ((!(matchsel & WHO_FIELD_SER))
- || (!(cli_flags(cli_user(acptr)->server) & 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(cli_info(acptr), mymask, minlen))
&& ((!(matchsel & WHO_FIELD_NIP))
|| (HasHiddenHost(acptr) && !IsAnOper(sptr))
- || ((((cli_ip(acptr).s_addr & imask.mask.s_addr) != imask.bits.s_addr))
- || (imask.fall
- && matchexec(ircd_ntoa((const char*) &(cli_ip(acptr))), mymask, minlen)))))
+ || !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;
/* Make a clean mask suitable to be sent in the "end of" */
if (mask && (p = strchr(mask, ' ')))
*p = '\0';
- send_reply(sptr, RPL_ENDOFWHO, BadPtr(mask) ? "*" : mask);
-
/* Notify the user if we decided that his query was too long */
if (counter < 0)
- send_reply(sptr, ERR_QUERYTOOLONG, "WHO");
+ send_reply(sptr, ERR_QUERYTOOLONG, BadPtr(mask) ? "*" : mask);
+ send_reply(sptr, RPL_ENDOFWHO, BadPtr(mask) ? "*" : mask);
return 0;
}