]> jfr.im git - irc/quakenet/newserv.git/blobdiff - nick/nickhandlers.c
CHANSERV: remove accidental sendemail from SETEMAIL command.
[irc/quakenet/newserv.git] / nick / nickhandlers.c
index 56529726b460e2bb0c5e34731d52621ea8a7776f..6ab0d93d554be131863ffbbef9d457b987566f1d 100644 (file)
@@ -13,6 +13,7 @@
 #include "../parser/parser.h"
 #include <stdlib.h>
 #include <string.h>
+#include <stdint.h>
 
 /*
  * handlenickmsg:
@@ -28,11 +29,14 @@ int handlenickmsg(void *source, int cargc, char **cargv) {
   char *fakehost;
   char *accountts;
   char *accountflags;
-  struct irc_in_addr ipaddress;
+  struct irc_in_addr ipaddress, ipaddress_canonical;
   char *accountid;
   unsigned long userid;
   
   if (cargc==2) { /* rename */
+    char oldnick[NICKLEN+1];
+    void *harg[2];
+
     /* Nyklon 1017697578 */
     timestamp=strtol(cargv[1],NULL,10);
     np=getnickbynumericstr(sender);
@@ -40,19 +44,25 @@ int handlenickmsg(void *source, int cargc, char **cargv) {
       Error("nick",ERR_ERROR,"Rename from non-existent sender %s",sender);
       return CMD_OK;
     }
+
+    strncpy(oldnick,np->nick,NICKLEN);
+    oldnick[NICKLEN]='\0';
+    harg[0]=(void *)np;
+    harg[1]=(void *)oldnick;
+
     np2=getnickbynick(cargv[0]);
     if (np==np2) {
       /* The new and old nickname have the same hash, this means a rename to the same name in 
        * different case, e.g. Flash -> flash.  In this case the timestamp for the change should
        * match the existing timestamp, and we can bypass all the collision checking and hash fettling. */
       if (np->timestamp!=timestamp) {
-        Error("nick",ERR_WARNING,"Rename to same nickname with different timestamp (%s(%d) -> %s(%d))",
-                            np->nick,np->timestamp,cargv[0],timestamp);
+        Error("nick",ERR_WARNING,"Rename to same nickname with different timestamp (%s(%jd) -> %s(%jd))",
+                            np->nick,(intmax_t)np->timestamp,cargv[0], (intmax_t)timestamp);
         np->timestamp=timestamp;
       }
       strncpy(np->nick,cargv[0],NICKLEN);
       np->nick[NICKLEN]='\0';
-      triggerhook(HOOK_NICK_RENAME,np);        
+      triggerhook(HOOK_NICK_RENAME,harg);
       return CMD_OK;
     }
     if (np2!=NULL) {
@@ -83,7 +93,7 @@ int handlenickmsg(void *source, int cargc, char **cargv) {
     strncpy(np->nick,cargv[0],NICKLEN);
     np->nick[NICKLEN]='\0';
     addnicktohash(np);
-    triggerhook(HOOK_NICK_RENAME,np);
+    triggerhook(HOOK_NICK_RENAME,harg);
   } else if (cargc>=8) { /* new nick */
     /* Jupiler 2 1016645147 ~Jupiler www.iglobal.be +ir moo [FUTURE CRAP HERE] DV74O] BNBd7 :Jupiler */
     timestamp=strtol(cargv[2],NULL,10);
@@ -118,10 +128,6 @@ int handlenickmsg(void *source, int cargc, char **cargv) {
     }
 
     base64toip(cargv[cargc-3], &ipaddress);
-    if (!irc_in_addr_valid(&ipaddress)) {
-      Error("nick",ERR_ERROR,"Received NICK with invalid ipaddress for %s from %s.",cargv[0],sender);
-      return CMD_ERROR;
-    }
 
     /* At this stage the nick is cleared to proceed */
     np=newnick();
@@ -138,18 +144,25 @@ int handlenickmsg(void *source, int cargc, char **cargv) {
     np->realname->nicks=np;
     np->timestamp=timestamp;
 
-    base64toip(cargv[cargc-3], &ipaddress);
-    np->ipnode = refnode(iptree, &ipaddress, PATRICIA_MAXBITS);
+    memcpy(&(np->ipaddress), &ipaddress, sizeof(ipaddress));
+
+    ip_canonicalize_tunnel(&ipaddress_canonical, &ipaddress);
+    np->ipnode = refnode(iptree, &ipaddress_canonical, PATRICIA_MAXBITS);
     node_increment_usercount(np->ipnode);
 
+    np->away=NULL;
     np->shident=NULL;
     np->sethost=NULL;
     np->opername=NULL;
     np->umodes=0;
     np->marker=0;
     memset(np->exts, 0, MAXNICKEXTS * sizeof(void *));
-    np->authname[0]='\0';
+    np->authname=NULLAUTHNAME;
     np->auth=NULL;
+    np->accountts=0;
+    np->cloak_count = 0;
+    np->cloak_extra = NULL;
+    np->message = NULL;
     if(cargc>=9) {
       int sethostarg = 6, opernamearg = 6, accountarg = 6;
 
@@ -166,29 +179,26 @@ int handlenickmsg(void *source, int cargc, char **cargv) {
         sethostarg++;
 
         if ((accountts=strchr(cargv[accountarg],':'))) {
+          userid=0;
           *accountts++='\0';
           np->accountts=strtoul(accountts,&accountid,10);
           if(accountid) {
             userid=strtoul(accountid + 1,&accountflags,10);
-            if(!userid) {
-              np->auth=NULL;
-            } else {
+            if(userid) {
               np->auth=findorcreateauthname(userid, cargv[accountarg]);
+              np->authname=np->auth->name;
               np->auth->usercount++;
               np->nextbyauthname=np->auth->nicks;
               np->auth->nicks=np;
               if(accountflags)
-                np->auth->flags=strtoul(accountflags + 1,NULL,10);
+                np->auth->flags=strtoull(accountflags + 1,NULL,10);
             }
-          } else {
-            np->auth=NULL;
           }
-        } else {
-          np->accountts=0;
-          np->auth=NULL;
+          if(!userid) {
+            np->authname=malloc(strlen(cargv[accountarg]) + 1);
+            strcpy(np->authname,cargv[accountarg]);
+          }
         }        
-        strncpy(np->authname,cargv[accountarg],ACCOUNTLEN);
-        np->authname[ACCOUNTLEN]='\0';
       } 
       if (IsSetHost(np) && (fakehost=strchr(cargv[sethostarg],'@'))) {
        /* valid sethost */
@@ -274,6 +284,7 @@ int handleusermodemsg(void *source, int cargc, char **cargv) {
   nick *np;
   flag_t oldflags;
   char *fakehost;
+  void *args[2];
   
   if (cargc<2) {
     Error("nick",ERR_WARNING,"Mode message with too few parameters");
@@ -296,6 +307,10 @@ int handleusermodemsg(void *source, int cargc, char **cargv) {
     oldflags=np->umodes;
     setflags(&(np->umodes),UMODE_ALL,cargv[1],umodeflags,REJECT_NONE);
 
+    args[0] = np;
+    args[1] = (void *)oldflags;
+    triggerhook(HOOK_NICK_MODECHANGE, args);
+
     if (strchr(cargv[1],'o')) { /* o always comes on its own when being set */
       if(serverlist[myhub].flags & SMODE_OPERNAME) {
         if((np->umodes & UMODE_OPER)) {
@@ -332,65 +347,13 @@ int handleusermodemsg(void *source, int cargc, char **cargv) {
   return CMD_OK;
 }
 
-int handlewhoismsg(void *source, int cargc, char **cargv) {
-  nick *sender,*target;
-  nick *nicks[2];
-  
-  if (cargc<2)
-    return CMD_OK;
-  
-  if (strncmp(cargv[0],mynumeric->content,2)) {
-    return CMD_OK;
-  }
-  
-  /* Find the sender... */  
-  if ((sender=getnickbynumericstr((char *)source))==NULL) {
-    Error("localuser",ERR_WARNING,"WHOIS message from non existent numeric %s",(char *)source);
-    return CMD_OK;
-  }
-  
-  /* :hub.splidge.netsplit.net 311 moo splidge splidge ground.stbarnab.as * :splidge
-     :hub.splidge.netsplit.net 312 moo splidge splidge.netsplit.net :splidge's netsplit leaf
-     :hub.splidge.netsplit.net 313 moo splidge :is an IRC Operator
-     :hub.splidge.netsplit.net 318 moo splidge :End of /WHOIS list.
-  */
-  
-  /* And the target... */
-  if ((target=getnickbynick(cargv[1]))==NULL) {
-    irc_send(":%s 401 %s %s :No such nick",myserver->content,sender->nick,cargv[1]);
-  } else {
-    irc_send(":%s 311 %s %s %s %s * :%s",myserver->content,sender->nick,target->nick,target->ident,
-        target->host->name->content, target->realname->name->content);
-    nicks[0]=sender; nicks[1]=target;
-    triggerhook(HOOK_NICK_WHOISCHANNELS,nicks);
-    if (IsOper(sender) || !HIS_SERVER ) {
-      irc_send(":%s 312 %s %s %s :%s",myserver->content,sender->nick,target->nick,
-          serverlist[homeserver(target->numeric)].name->content,
-          serverlist[homeserver(target->numeric)].description->content);
-    } else {
-      irc_send(":%s 312 %s %s " HIS_SERVERNAME " :" HIS_SERVERDESC,myserver->content,sender->nick,target->nick);
-    }
-    if (IsOper(target)) {
-      irc_send(":%s 313 %s %s :is an IRC Operator",myserver->content,sender->nick,target->nick);
-    }
-    if (IsAccount(target)) {
-      irc_send(":%s 330 %s %s %s :is authed as",myserver->content,sender->nick,target->nick,target->authname);
-    }
-    if (homeserver(target->numeric)==mylongnum && !IsService(target) && !IsHideIdle(target)) {
-      irc_send(":%s 317 %s %s %ld %ld :seconds idle, signon time",myserver->content,sender->nick,target->nick,
-         (getnettime() - target->timestamp) % (((target->numeric + target->timestamp) % 983) + 7),target->timestamp);
-    }
-  }
-  
-  irc_send(":%s 318 %s %s :End of /WHOIS list.",myserver->content,sender->nick,cargv[1]);
-  return CMD_OK;
-}  
-
 int handleaccountmsg(void *source, int cargc, char **cargv) {
   nick *target;
   unsigned long userid;
-  
-  if (cargc<2) {
+  time_t accountts;
+  u_int64_t accountflags=0, oldflags;
+
+  if (cargc<4) {
     return CMD_OK;
   }
   
@@ -398,95 +361,55 @@ int handleaccountmsg(void *source, int cargc, char **cargv) {
     return CMD_OK;
   }
   
+  accountts=strtoul(cargv[2],NULL,10);
+  userid=strtoul(cargv[3],NULL,10);
+  if(cargc>=5)
+    accountflags=strtoull(cargv[4],NULL,10);
+
+  /* allow user flags to change if all fields match */
   if (IsAccount(target)) {
-    return CMD_OK;
-  }
-  
-  SetAccount(target);
-  strncpy(target->authname,cargv[1],ACCOUNTLEN);
-  target->authname[ACCOUNTLEN]='\0';
-  
-  if (cargc>=3) {
-    target->accountts=strtoul(cargv[2],NULL,10);
-    if (cargc>=4) {
-      userid=strtoul(cargv[3],NULL,10);
-      if(!userid) {
-        target->auth=NULL;
-      } else {
-        target->auth=findorcreateauthname(userid, target->authname);
-        target->auth->usercount++;
-        target->nextbyauthname = target->auth->nicks;
-        target->auth->nicks = target;
-        if (cargc>=5)
-          target->auth->flags=strtoul(cargv[4],NULL,10);
-      }
-    } else {
-      target->auth=NULL;
+    void *arg[2];
+
+    if (!target->auth || strcmp(target->auth->name,cargv[1]) || (target->auth->userid != userid) || (target->accountts != accountts)) {
+      return CMD_OK;
     }
-  } else {
-    target->accountts=0;
-    target->auth=NULL;
-  }
-  
-  triggerhook(HOOK_NICK_ACCOUNT, (void *)target);
 
-  return CMD_OK;
-}
+    oldflags = target->auth->flags;
+    arg[0] = target->auth;
+    arg[1] = &oldflags;
+    
+    if (cargc>=5)
+      target->auth->flags=accountflags;
+
+    triggerhook(HOOK_AUTH_FLAGSUPDATED, (void *)arg);
 
-int handlestatsmsg(void *source, int cargc, char **cargv) {
-  int sourceserver;
-  char *sender=(char *)source;
-  char *replytarget;
-  char *fromstring;
-  nick *np;
-  
-  if (cargc<2) {
-    Error("nick",ERR_WARNING,"STATS request without enough parameters!");
     return CMD_OK;
   }
   
-  if (strlen(sender)==5) {
-    /* client */
-    np=getnickbynumericstr(sender);
-    if (!np) {
-      Error("nick",ERR_WARNING,"STATS request from unknown client %s",sender);
-      return CMD_OK;
-    }
-    replytarget=np->nick;
-  } else {
-    Error("nick",ERR_WARNING,"STATS request from odd source %s",sender);
-    return CMD_OK;
-  }
+  SetAccount(target);
+  target->accountts=accountts;
 
-  /* Reply to stats for ANY server.. including any we are juping */
-  sourceserver=numerictolong(cargv[1],2);
-  if (serverlist[sourceserver].maxusernum==0) {
-    Error("nick",ERR_WARNING,"Stats request for bad server %s",cargv[1]);
-    return CMD_OK;
-  }
-  fromstring=serverlist[sourceserver].name->content;
-
-  switch(cargv[0][0]) {
-  case 'u':
-    irc_send(":%s 242 %s :Server Up %s",fromstring,replytarget,
-            longtoduration(time(NULL)-starttime, 0));
-    irc_send(":%s 250 %s :Highest connection count: 10 (9 clients)",fromstring,replytarget);
-    break;
-
-  case 'P':
-    irc_send(":%s 217 %s P none 0 :0x2000",fromstring,replytarget);
-    break;
-    
+  if(!userid) {
+    target->auth=NULL;
+    target->authname=malloc(strlen(cargv[1]) + 1);
+    strcpy(target->authname,cargv[1]);
+  } else {
+    target->auth=findorcreateauthname(userid, cargv[1]);
+    target->auth->usercount++;
+    target->authname=target->auth->name;
+    target->nextbyauthname = target->auth->nicks;
+    target->auth->nicks = target;
+    if (cargc>=5)
+      target->auth->flags=accountflags;
   }
 
-  irc_send(":%s 219 %s %c :End of /STATS report",fromstring,replytarget,cargv[0][0]);
+  triggerhook(HOOK_NICK_ACCOUNT, (void *)target);
 
   return CMD_OK;
 }
 
 int handleprivmsg(void *source, int cargc, char **cargv) {
   nick *sender;
-  char *message;
   void *args[3];
 
   if (cargc<2)
@@ -500,8 +423,6 @@ int handleprivmsg(void *source, int cargc, char **cargv) {
   if (!match2strings(cargv[0] + 1,myserver->content))
     return CMD_OK;
 
-  message=cargv[0];
-
   args[0]=sender;
   args[1]=cargv[0];
   args[2]=cargv[1];
@@ -511,3 +432,56 @@ int handleprivmsg(void *source, int cargc, char **cargv) {
   return CMD_OK;
 }
 
+int handleawaymsg(void *source, int cargc, char **cargv) {
+  nick *sender;
+    
+  /* Check source is a valid user */ 
+  if (!(sender=getnickbynumericstr(source))) {
+    return CMD_OK;
+  }
+
+  /* Done with the old away message either way */
+  freesstring(sender->away);
+  sender->away=NULL;
+  
+  /* If we have an arg and it isn't an empty string, this sets a new message */
+  if (cargc > 0 && *(cargv[0])) {
+    sender->away=getsstring(cargv[0], AWAYLEN);
+  }
+
+  return CMD_OK;
+}
+
+int handleaddcloak(void *source, int cargc, char **cargv) {
+  nick *sender, *target;
+
+  /* Check source is a valid user */
+  if (!(sender=getnickbynumericstr(source))) {
+    return CMD_OK;
+  }
+
+  if (cargc < 1)
+    return CMD_OK;
+
+  if (!(target=getnickbynumericstr(cargv[0]))) {
+    return CMD_OK;
+  }
+
+  addcloaktarget(sender, target);
+
+  return CMD_OK;
+}
+
+int handleclearcloak(void *source, int cargc, char **cargv) {
+  nick *sender;
+
+  /* Check source is a valid user */
+  if (!(sender=getnickbynumericstr(source))) {
+    return CMD_OK;
+  }
+
+  clearcloaktargets(sender);
+
+  return CMD_OK;
+}
+