added basic ssl support to ircu
[ircu2.10.12-pk.git] / ircd / m_who.c
index d66775bd6eceb9829b837816aaa16d3cfc4dee80..49df47580c393399ab9e97ae91a50dced6cc19a6 100644 (file)
 #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)
@@ -144,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 ?
@@ -175,16 +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;
-          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':
@@ -210,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 != ','))
@@ -260,6 +268,14 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
           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;
         }
@@ -313,11 +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) && (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;
@@ -332,9 +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) && (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);
@@ -347,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;
@@ -364,6 +381,8 @@ 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 */
@@ -378,9 +397,7 @@ 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) && (HasPriv(acptr, PRIV_DISPLAY) ||
-                                   HasPriv(sptr, PRIV_SEE_OPERS))))
+         if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr))
            continue;
           if ((mask) &&
               ((!(matchsel & WHO_FIELD_NIC))
@@ -399,9 +416,9 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
               || 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;
@@ -416,9 +433,7 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
       {
         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;
@@ -439,9 +454,9 @@ int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
             || 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;
@@ -452,11 +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';
-  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;
 }