]> jfr.im git - irc/quakenet/newserv.git/blobdiff - miscreply/whois.c
CHANSERV: remove accidental sendemail from SETEMAIL command.
[irc/quakenet/newserv.git] / miscreply / whois.c
index d3121a2042d3e04c03ead7bdf650b2940b0d434c..edb75b7c57d7a66e664da3d848a54f9e9eecd055 100644 (file)
 /* whois.c */
 
 #include "miscreply.h"
-#include "msg.h"
-#include "numeric.h"
 #include "../irc/irc.h"
 #include "../core/error.h"
 #include "../core/hooks.h"
-#include "../nick/nick.h"
+#include "../server/server.h"
 
 #include <string.h>
 
 
 
-/* handle remote whois request
- *
- * <source numeric> WHOIS/W <target server numeric> <nick>
- *
- * cargv[0] = target server numeric
- * cargv[1] = nick as given by source
- *            comma separated list of one or more nicks, may contain wildcards
- *            multiple nicks and wildcards currently not supported here
+/* do whois
  *
  */
-int handlewhoismsg(void *source, int cargc, char **cargv) {
+static void do_whois(char *sourcenum, nick *snick, nick *tnick) {
+
+  void *nicks[3];   /* nick array for whois channels hook */
 
-  nick *snick;                                          /* struct nick for source nick */
-  nick *tnick;                                          /* struct nick for target nick */
-  nick *nicks[2];                                       /* struct nick for whois channels trigger */
 
-  char *sourcenum = (char *)source;                     /* source user numeric */
-  char *targetnum = getmynumeric();                     /* target server numeric */
-  char *servernum;                                      /* server numeric parameter */
-  char *nick;                                           /* nick parameter */
+  /* user
+   *
+   * 311 RPL_WHOISUSER "source 311 target nick user host * :realname"
+   *                   "irc.netsplit.net 311 foobar bar foo host.com * :foobar"
+   */
+  /* sethost (usermode +h) */
+  if (IsSetHost(tnick)) {
+       irc_send("%s 311 %s %s %s %s * :%s", getmynumeric(), sourcenum, tnick->nick,
+      tnick->shident->content, tnick->sethost->content, tnick->realname->name->content);
+  /* account and hiddenhost (usermode +rx) */
+  } else if (IsAccount(tnick) && IsHideHost(tnick)) {
+    irc_send("%s 311 %s %s %s %s.%s * :%s", getmynumeric(), sourcenum, tnick->nick,
+      tnick->ident, tnick->authname, HIS_HIDDENHOST, tnick->realname->name->content);
+  /* not hidden */
+  } else {
+    irc_send("%s 311 %s %s %s %s * :%s", getmynumeric(), sourcenum, tnick->nick,
+      tnick->ident, tnick->host->name->content, tnick->realname->name->content);
+  }
 
 
-  /* check parameters */
-  if (cargc < 2) {
-    miscreply_needmoreparams(sourcenum, "WHOIS");
-    return CMD_OK;
+  /* channels
+   *   show channels only when
+   *      target user is not a service (usermode +k) AND
+   *      target user is not hidechan (usermode +n)
+   *      OR user WHOIS'ing himself
+   */
+  if ((!IsService(tnick) && !IsHideChan(tnick) && canseeuser(snick, tnick)) || snick == tnick) {
+    nicks[0] = (char *)snick;
+    nicks[1] = (char *)tnick;
+    nicks[2] = sourcenum;
+    triggerhook(HOOK_NICK_WHOISCHANNELS, nicks);
   }
 
-  /* get the parameters */
-  servernum = cargv[0];
-  nick = cargv[1];
 
-  /* request not for my server
+  /* server
    *
-   *   if newserv can have clients on its downlinks,
-   *   this will need to be changed,
-   *   else remote whois on those users wont work
+   * 312 RPL_WHOISSERVER "source 312 target nick server :description"
+   *                     "irc.netsplit.net 312 foobar barfoo *.netsplit.net :Netsplit Server"
    */
-  if (!IsMeNum(servernum))
-    return CMD_OK;
-
-  /* from a server? */
-  if (IsServer(sourcenum))
-    return CMD_OK;
+  /* show server and description when
+   *   user WHOIS'ing himself, OR to an IRC Operator, OR when HIS_SERVER is 0
+   */
+  if (snick == tnick || IsOper(snick) || !HIS_SERVER) {
+        irc_send("%s 312 %s %s %s :%s", getmynumeric(), sourcenum, tnick->nick,
+      serverlist[homeserver(tnick->numeric)].name->content,
+      serverlist[homeserver(tnick->numeric)].description->content);
+  /* show HIS server and description */
+  } else {
+       irc_send("%s 312 %s %s %s :%s", getmynumeric(), sourcenum, tnick->nick,
+     HIS_SERVERNAME,
+     HIS_SERVERDESC);
+  }
 
-  /* find source user */ 
-  if (!(snick = miscreply_finduser(sourcenum, "WHOIS")))
-    return CMD_OK;
 
-  /* find the target */
-  if (!(tnick = getnickbynick(nick))) {
-    /*
-     * 401 ERR_NOSUCHNICK "source 401 target nick :No such nick"
-     *                    "irc.netsplit.net 391 foobar barfoo :No such nick"
+  /* target user is away */
+  if ((tnick)->away) {
+    /* 
+     * 301 RPL_AWAY "source 301 target nick :awaymsg"
+     *              "irc.netsplit.net 301 foobar barfoo :afk."
      */
-    send_reply(targetnum, ERR_NOSUCHNICK, sourcenum, "%s :No such nick", nick);
-
-  } else {
+    irc_send("%s 301 %s %s :%s", getmynumeric(), sourcenum, tnick->nick, tnick->away->content);
+  }
 
 
-    /* user
-     *
-     * 311 RPL_WHOISUSER "source 311 target nick user host * :realname"
-     *                   "irc.netsplit.net 311 foobar bar foo host.com * :foobar"
+  /* target user is an IRC Operator */
+  if (IsOper(tnick)) {
+    /* 
+     * 313 RPL_WHOISOPERATOR "source 313 target nick :is an IRC Operator"
+     *                       "irc.netsplit.net 313 foobar barfoo :is an IRC Operator"
      */
-    /* sethost (mode +h) */
-    if (IsSetHost(tnick)) {
-      send_reply(targetnum, RPL_WHOISUSER, sourcenum, "%s %s %s * :%s", tnick->nick,
-        tnick->shident->content, tnick->sethost->content, tnick->realname->name->content);
-    /* account and hiddenhost (mode +rx) */
-    } else if (HasHiddenHost(tnick)) {
-      send_reply(targetnum, RPL_WHOISUSER, sourcenum, "%s %s %s.%s * :%s", tnick->nick,
-        tnick->ident, tnick->authname, HIS_HIDDENHOST, tnick->realname->name->content);
-    /* not hidden */
-    } else {
-      send_reply(targetnum, RPL_WHOISUSER, sourcenum, "%s %s %s * :%s", tnick->nick,
-        tnick->ident, tnick->host->name->content, tnick->realname->name->content);
-    }
+    irc_send("%s 313 %s %s :is an IRC Operator", getmynumeric(), sourcenum, tnick->nick);
 
+    /* source user is an IRC Operator, show opername if we have it */
+    if (IsOper(snick) && (tnick->opername && strcmp(tnick->opername->content, "-")))
+      /* 
+       * 343 RPL_WHOISOPERNAME "source 343 target nick opername :is opered as"
+       *                       "irc.netsplit.net 343 foobar barfoo fish :is opered as"
+       *
+       *  note: snircd extension
+       */
+      irc_send("%s 343 %s %s %s :is opered as", getmynumeric(), sourcenum, tnick->nick, tnick->opername->content);
+  }
 
-    /* TODO: these checks are in handlewhoischannels in channel/channelhandlers.c also .. */
-    /* TODO: move whois channels here? */
-    /* channels
-     *   show channels only when
-     *      target user is not a service (mode +k) AND
-     *      target user is not hidechan (mode +n)
-     *      OR user WHOIS'ing himself
-     */
-    if ((!IsService(tnick) && !IsHideChan(tnick)) || snick == tnick) {
-      nicks[0] = snick;
-      nicks[1] = tnick;
-      triggerhook(HOOK_NICK_WHOISCHANNELS, nicks);
-    }
 
 
-    /* server
+  /* target user got an account (usermode +r) */
+  if (IsAccount(tnick)) {
+    /* 
+     * 330 RPL_WHOISACCOUNT "source 330 target nick account :is authed as"
+     *                      "irc.netsplit.net 330 foobar barfoo fish :is authed as"
      *
-     * 312 RPL_WHOISSERVER "source 312 target nick server :description"
-     *                     "irc.netsplit.net 312 foobar barfoo *.netsplit.net :Netsplit Server"
-     */
-    /* show server and description when
-     *   user WHOIS'ing himself, OR to an operator, OR when HIS_SERVER is not set
+     *   note: ircu shows "is logged in as" as text
      */
-    if (snick == tnick || IsOper(snick) || !HIS_SERVER) {
-      send_reply(targetnum, RPL_WHOISSERVER, sourcenum, "%s %s :%s", tnick->nick,
-        serverlist[homeserver(tnick->numeric)].name->content,
-        serverlist[homeserver(tnick->numeric)].description->content);
-    /* show HIS server and description */
-    } else {
-      send_reply(targetnum, RPL_WHOISSERVER, sourcenum, "%s %s :%s", tnick->nick,
-        HIS_SERVERNAME,
-        HIS_SERVERDESC);
-    }
-
+    irc_send("%s 330 %s %s %s :is authed as", getmynumeric(), sourcenum, tnick->nick, tnick->authname);
+  }
 
-    /* target user is away */
-    if (IsAway(tnick)) {
-      /* 
-       * 301 RPL_AWAY "source 301 target nick :awaymsg"
-       *              "irc.netsplit.net 301 foobar barfoo :afk."
-       */
-      send_reply(targetnum, RPL_AWAY, sourcenum, "%s :%s", tnick->nick, tnick->away->content);
-    }
 
 
-    /* target user is an operator */
-    if (IsOper(tnick)) {
-      /* 
-       * 313 RPL_WHOISOPERATOR "source 313 target nick :is an IRC Operator"
-       *                       "irc.netsplit.net 313 foobar barfoo :is an IRC Operator"
-       */
-      send_reply(targetnum, RPL_WHOISOPERATOR, sourcenum, "%s :is an IRC Operator", tnick->nick);
-
-      /* source user is an operator, show opername if we have it */
-      if (IsOper(snick) && HasOperName(tnick))
-        /* 
-         * 343 RPL_WHOISOPERNAME "source 343 target nick opername :is opered as"
-         *                       "irc.netsplit.net 343 foobar barfoo fish :is opered as"
-         *
-         *  note: snircd extension
-         */
-        send_reply(targetnum, RPL_WHOISOPERNAME, sourcenum, "%s %s :is opered as", tnick->nick, tnick->opername->content);
-    }
+  /* target user got a sethost (usermode +h) or has a hiddenhost (usermode +rx) 
+   *   show real host to user WHOIS'ing himself and to an IRC Operator
+   */
+  if ((snick == tnick || IsOper(snick)) && (IsSetHost(tnick) || (IsAccount(tnick) && IsHideHost(tnick)) )) {
+    /* 
+     * 338 RPL_WHOISACTUALLY "source 338 target nick user@host IP :Actual user@host, Actual IP"
+     *                       "irc.netsplit.net 338 foobar barfoo foobar@localhost 127.0.0.1 :Actual user@host, Actual IP"
+     */
+    irc_send("%s 338 %s %s %s@%s %s :Actual user@host, Actual IP", getmynumeric(), sourcenum, tnick->nick,
+      tnick->ident, tnick->host->name->content, IPtostr(tnick->ipaddress));
+  }
 
 
 
-    /* target user got an account (mode +r) */
-    if (IsAccount(tnick)) {
-      /* 
-       * 330 RPL_WHOISACCOUNT "source 330 target nick account :is authed as"
-       *                      "irc.netsplit.net 330 foobar barfoo fish :is authed as"
-       *
-       *   note: ircu shows "is logged in as" as text
-       */      
-      send_reply(targetnum, RPL_WHOISACCOUNT, sourcenum, "%s %s :is authed as", tnick->nick, tnick->authname);
-    }
+  /* my user,
+   *   AND not a service (usermode +k), AND not hiding idle time (usermode +I)
+   *   show idle and signon time
+   */
+  if (mylongnum == homeserver(tnick->numeric) && !IsService(tnick) && !IsHideIdle(tnick)) {
+    /* 
+     * 317 RPL_WHOISIDLE "source 317 target nick idle signon :seconds idle, signon time"
+     *                   "irc.netsplit.net 317 foobar barfoo 5 1084458353"
+     */
+    irc_send("%s 317 %s %s %ld %ld :seconds idle, signon time", getmynumeric(), sourcenum, tnick->nick,
+      (getnettime() - tnick->timestamp) % (((tnick->numeric + tnick->timestamp) % 983) + 7), tnick->timestamp);
+  }
+}
 
 
 
-    /* target user got a sethost (mode +h) or has a hiddenhost (mode +rx) 
-     *   show real host to user WHOIS'ing himself and to an operator
-     */
-    if ((snick == tnick || IsOper(snick)) && (IsSetHost(tnick) || HasHiddenHost(tnick))) {
-      /* 
-       * 338 RPL_WHOISACTUALLY "source 338 target nick user@host IP :Actual user@host, Actual IP"
-       *                       "irc.netsplit.net 338 foobar barfoo foobar@localhost 127.0.0.1 :Actual user@host, Actual IP"
-       */
-      send_reply(targetnum, RPL_WHOISACTUALLY, sourcenum, "%s %s@%s %s :Actual user@host, Actual IP", tnick->nick,
-        tnick->ident, tnick->host->name->content, IPtostr(tnick->p_ipaddr));
-    }
+/* handle remote whois request
+ *
+ * <source numeric> WHOIS/W <target server numeric> <nick>
+ *
+ * cargv[0] = target server numeric
+ * cargv[1] = nick as given by source
+ *            comma separated list of one or more nicks, may contain wildcards
+ *            ircu does not do wildcard matches for remote whois, we dont either
+ *
+ */
+int handlewhoismsg(void *source, int cargc, char **cargv) {
 
+  nick *snick;                        /* struct nick for source nick */
+  nick *tnick;                        /* struct nick for target nick */
+  char *sourcenum = (char *)source;   /* source user numeric */
+  char nicks[BUFSIZE];                /* nick parameter */
+  char *nick;                         /* loop nick */
 
+  /* check parameters */
+  if (cargc < 2) {
+    miscreply_needmoreparams(sourcenum, "WHOIS");
+    return CMD_OK;
+  }
 
-    /* target user is paranoid */
-    if (IsParanoid(tnick) && !IsOper(snick) && snick != tnick) {
-      send_snotice(longtonumeric(tnick->numeric, 5), "whois: %s performed a /WHOIS on you.", snick->nick);
-    }
+  /* get the parameters */
+  strcpy(nicks, cargv[1]);
 
+  /* find source user */ 
+  if (!(snick = miscreply_finduser(sourcenum, "WHOIS")))
+    return CMD_OK;
 
+  /* go through the list of nicks */
+  for (nick = strtok(nicks, ","); nick != NULL; nick = strtok(NULL, ",")) {
 
-    /* target user is myuser, AND not a service (mode +k), AND not hiding idle time (mode +I)
-     *   show idle and signon time
-     */
-    if (MyUser(tnick) && !IsService(tnick) && !IsHideIdle(tnick)) {
-      /* 
-       * 317 RPL_WHOISIDLE "source 317 target nick idle signon :seconds idle, signon time"
-       *                   "irc.netsplit.net 317 foobar barfoo 5 1084458353"
+    /* find the target */
+    if (!(tnick = getnickbynick(nick))) {
+      /*
+       * 401 ERR_NOSUCHNICK "source 401 target nick :No such nick"
+       *                    "irc.netsplit.net 391 foobar barfoo :No such nick"
        */
-      send_reply(targetnum, RPL_WHOISIDLE, sourcenum, "%s %ld %ld :seconds idle, signon time", tnick->nick,
-         (getnettime() - tnick->timestamp) % (((tnick->numeric + tnick->timestamp) % 983) + 7), tnick->timestamp);
+      irc_send("%s 401 %s %s :No such nick", getmynumeric(), sourcenum, nick);
     }
+
+    else
+      do_whois(sourcenum, snick, tnick);
   }
 
 
@@ -211,7 +199,7 @@ int handlewhoismsg(void *source, int cargc, char **cargv) {
    * 318 RPL_ENDOFWHOIS "source 318 target nick :End of /WHOIS list."
    *                    "irc.netsplit.net 318 foobar barfoo :End of /WHOIS list."
    */
-  send_reply(targetnum, RPL_ENDOFWHOIS, sourcenum, "%s :End of /WHOIS list.", nick);
+  irc_send("%s 318 %s %s :End of /WHOIS list.", getmynumeric(), sourcenum, cargv[1]);
 
   return CMD_OK;
 }