#include "../parser/parser.h"
#include <stdlib.h>
#include <string.h>
+#include <stdint.h>
/*
* handlenickmsg:
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);
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) {
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);
}
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();
np->realname->nicks=np;
np->timestamp=timestamp;
- base64toip(cargv[cargc-3], &ipaddress);
- /* todo: use a single node for /64 prefixes */
- np->ipnode = refnode(iptree, &ipaddress, irc_in_addr_is_ipv4(&ipaddress) ? PATRICIA_MAXBITS : 64);
+ 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->accountflags=0;
+ np->accountts=0;
+ np->cloak_count = 0;
+ np->cloak_extra = NULL;
+ np->message = NULL;
if(cargc>=9) {
+ int sethostarg = 6, opernamearg = 6, accountarg = 6;
+
setflags(&(np->umodes),UMODE_ALL,cargv[5],umodeflags,REJECT_NONE);
+
+ if(IsOper(np) && (serverlist[myhub].flags & SMODE_OPERNAME)) {
+ accountarg++;
+ sethostarg++;
+
+ np->opername=getsstring(cargv[opernamearg],ACCOUNTLEN);
+ }
+
if (IsAccount(np)) {
- if ((accountts=strchr(cargv[6],':'))) {
+ 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 {
- np->auth=findorcreateauthname(userid);
+ 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=strtoull(accountflags + 1,NULL,10);
}
- if(accountflags)
- np->accountflags=strtoul(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[6],ACCOUNTLEN);
- np->authname[ACCOUNTLEN]='\0';
}
- if (IsSetHost(np) && (fakehost=strchr(cargv[cargc-4],'@'))) {
+ if (IsSetHost(np) && (fakehost=strchr(cargv[sethostarg],'@'))) {
/* valid sethost */
*fakehost++='\0';
- np->shident=getsstring(cargv[cargc-4],USERLEN);
+ np->shident=getsstring(cargv[sethostarg],USERLEN);
np->sethost=getsstring(fakehost,HOSTLEN);
}
}
nick *np;
flag_t oldflags;
char *fakehost;
+ void *args[2];
if (cargc<2) {
Error("nick",ERR_WARNING,"Mode message with too few parameters");
return CMD_OK;
}
oldflags=np->umodes;
- if (strchr(cargv[1],'o')) {
- void *harg[2];
- harg[0]=np;
- harg[1]=cargv[1];
- triggerhook(HOOK_NICK_MODEOPER,harg);
- }
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)) {
+ np->opername = getsstring(cargv[2], ACCOUNTLEN);
+ } else {
+ freesstring(np->opername);
+ np->opername = NULL;
+ }
+ }
+ if((np->umodes ^ oldflags) & UMODE_OPER)
+ triggerhook(HOOK_NICK_MODEOPER,np);
+ }
if (strchr(cargv[1],'h')) { /* Have to allow +h twice.. */
/* +-h: just the freesstring() calls for the -h case */
freesstring(np->shident); /* freesstring(NULL) is OK */
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;
}
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)) {
+ void *arg[2];
+
+ if (!target->auth || strcmp(target->auth->name,cargv[1]) || (target->auth->userid != userid) || (target->accountts != accountts)) {
+ 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);
+
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->auth->usercount++;
- target->nextbyauthname = target->auth->nicks;
- target->auth->nicks = target;
- }
- if (cargc>=5)
- target->accountflags=strtoul(cargv[4],NULL,10);
- } else {
- target->auth=NULL;
- }
- } else {
- target->accountts=0;
+ target->accountts=accountts;
+
+ 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;
}
-
+
triggerhook(HOOK_NICK_ACCOUNT, (void *)target);
return CMD_OK;
}
-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!");
+int handleprivmsg(void *source, int cargc, char **cargv) {
+ nick *sender;
+ void *args[3];
+
+ if (cargc<2)
+ return CMD_OK;
+
+ if (cargv[0][0]!='$')
+ return CMD_OK;
+
+ sender=getnickbynumericstr((char *)source);
+
+ if (!match2strings(cargv[0] + 1,myserver->content))
+ return CMD_OK;
+
+ args[0]=sender;
+ args[1]=cargv[0];
+ args[2]=cargv[1];
+
+ triggerhook(HOOK_NICK_MASKPRIVMSG, (void *)args);
+
+ 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 (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);
+ /* 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;
}
- /* 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]);
+ if (cargc < 1)
+ return CMD_OK;
+
+ if (!(target=getnickbynumericstr(cargv[0]))) {
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;
-
+
+ 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;
}
- irc_send(":%s 219 %s %c :End of /STATS report",fromstring,replytarget,cargv[0][0]);
+ clearcloaktargets(sender);
return CMD_OK;
}
+