extern vector<ircd_module*> factory;
std::vector<int> fd_reap;
-int client_exit = 0;
-
extern int MODCOUNT;
bool nofork = false;
}
}
+// returns TRUE of any users on channel C occupy server 'servername'.
+
+bool ChanAnyOnThisServer(chanrec *c,char* servername)
+{
+ log(DEBUG,"ChanAnyOnThisServer");
+ for (user_hash::iterator i = clientlist.begin(); i != clientlist.end(); i++)
+ {
+ if (has_channel(i->second,c))
+ {
+ if (!strcasecmp(i->second->server,servername))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// returns true if user 'u' shares any common channels with any users on server 'servername'
+
+bool CommonOnThisServer(userrec* u,char* servername)
+{
+ log(DEBUG,"ChanAnyOnThisServer");
+ for (user_hash::iterator i = clientlist.begin(); i != clientlist.end(); i++)
+ {
+ if ((common_channels(u,i->second)) && (u != i->second))
+ {
+ if (!strcasecmp(i->second->server,servername))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+
+
bool hasumode(userrec* user, char mode)
{
if (user)
Ptr = FindChan(cname);
if (Ptr)
{
- FOREACH_RESULT(OnUserPreJoin(user,Ptr,cname));
- if (MOD_RESULT) {
- return NULL;
- }
-
log(DEBUG,"add_channel: joining to: %s",Ptr->name);
// the override flag allows us to bypass channel modes
// and bans (used by servers)
if (!override)
{
+ FOREACH_RESULT(OnUserPreJoin(user,Ptr,cname));
+ if (MOD_RESULT) {
+ return NULL;
+ }
if (strcmp(Ptr->key,""))
{
}
}
- }
+ log(DEBUG,"add_channel: bans checked");
+
- log(DEBUG,"add_channel: bans checked");
+ if ((Ptr) && (user))
+ {
+ user->RemoveInvite(Ptr->name);
+ }
+
+ log(DEBUG,"add_channel: invites removed");
- if ((Ptr) && (user))
+ }
+ else
{
- user->RemoveInvite(Ptr->name);
+ log(DEBUG,"Overridden checks");
}
- log(DEBUG,"add_channel: invites removed");
}
created = 1;
}
user->chans[i].channel = Ptr;
WriteChannel(Ptr,user,"JOIN :%s",Ptr->name);
+
+ if (!override) // we're not overriding... so this isnt part of a netburst, broadcast it.
+ {
+ // use the stamdard J token with no privilages.
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"J %s :%s",user->nick,Ptr->name);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (ChanAnyOnThisServer(Ptr,servers[j]->name))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent J token");
+ }
+ }
+ }
+ }
log(DEBUG,"Sent JOIN to client");
/* remove a channel from a users record, and remove the record from memory
* if the channel has become empty */
-chanrec* del_channel(userrec *user, const char* cname, const char* reason)
+chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool local)
{
if ((!user) || (!cname))
{
if (reason)
{
WriteChannel(Ptr,user,"PART %s :%s",Ptr->name, reason);
+
+ if (!local)
+ {
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"L %s %s :%s",user->nick,Ptr->name,reason);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (ChanAnyOnThisServer(Ptr,servers[j]->name))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent L token (with reason)");
+ }
+ }
+ }
+ }
+
+
}
else
{
+ if (!local)
+ {
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"L %s %s :",user->nick,Ptr->name);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (ChanAnyOnThisServer(Ptr,servers[j]->name))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent L token (no reason)");
+ }
+ }
+ }
+ }
+
WriteChannel(Ptr,user,"PART :%s",Ptr->name);
}
user->chans[i].uc_modes = 0;
if (servermode)
{
if (!silent)
+ {
WriteChannelWithServ(ServerName,chan,user,"MODE %s %s",chan->name,outstr);
+ // M token for a usermode must go to all servers
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"M %s %s",ServerName,chan->name, outstr);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (strcmp(servers[j]->name,ServerName))
+ {
+ if (ChanAnyOnThisServer(chan,servers[j]->name))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent M token");
+ }
+ }
+ }
+ }
+ }
+
}
else
{
if (!silent)
+ {
WriteChannel(chan,user,"MODE %s %s",chan->name,outstr);
+ // M token for a usermode must go to all servers
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"m %s %s %s",user->nick,chan->name, outstr);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (strcmp(servers[j]->name,ServerName))
+ {
+ if (ChanAnyOnThisServer(chan,servers[j]->name))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent m token");
+ }
+ }
+ }
+ }
+ }
}
}
}
WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
+ // M token for a usermode must go to all servers
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"m %s %s %s",user->nick, dest->nick, b);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (strcmp(servers[j]->name,ServerName))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent m token");
+ }
+ }
+ }
+
if (strlen(dmodes)>MAXMODES)
{
dmodes[MAXMODES-1] = '\0';
WriteTo(user, dest, "MODE %s :%s", dest->nick, b);
+ // M token for a usermode must go to all servers
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"m %s %s %s",user->nick, dest->nick, b);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (strcmp(servers[j]->name,ServerName))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent m token");
+ }
+ }
+ }
+
if (strlen(dmodes)>MAXMODES)
{
dmodes[MAXMODES-1] = '\0';
}
+void merge_mode2(char **parameters, int pcnt, userrec* user)
+{
+ chanrec* Ptr;
+ userrec* dest;
+ int can_change,i;
+ int direction = 1;
+ char outpars[MAXBUF];
+
+ dest = Find(parameters[0]);
+
+ // fix: ChroNiCk found this - we cant use this as debug if its null!
+ if (dest)
+ {
+ log(DEBUG,"merge_mode on %s",dest->nick);
+ }
+
+ if ((dest) && (pcnt > 1))
+ {
+ log(DEBUG,"params > 1");
+
+ char dmodes[MAXBUF];
+ strncpy(dmodes,dest->modes,MAXBUF);
+
+ strcpy(outpars,"+");
+ direction = 1;
+
+ if ((parameters[1][0] != '+') && (parameters[1][0] != '-'))
+ return;
+
+ for (int i = 0; i < strlen(parameters[1]); i++)
+ {
+ if (parameters[1][i] == '+')
+ {
+ if (direction != 1)
+ {
+ if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
+ {
+ outpars[strlen(outpars)-1] = '+';
+ }
+ else
+ {
+ strcat(outpars,"+");
+ }
+ }
+ direction = 1;
+ }
+ else
+ if (parameters[1][i] == '-')
+ {
+ if (direction != 0)
+ {
+ if ((outpars[strlen(outpars)-1] == '+') || (outpars[strlen(outpars)-1] == '-'))
+ {
+ outpars[strlen(outpars)-1] = '-';
+ }
+ else
+ {
+ strcat(outpars,"-");
+ }
+ }
+ direction = 0;
+ }
+ else
+ {
+ log(DEBUG,"begin mode processing entry");
+ can_change = 1;
+ if (can_change)
+ {
+ if (direction == 1)
+ {
+ log(DEBUG,"umode %c being added",parameters[1][i]);
+ if ((!strchr(dmodes,parameters[1][i])) && (allowed_umode(parameters[1][i],user->modes,true)))
+ {
+ char umode = parameters[1][i];
+ log(DEBUG,"umode %c is an allowed umode",umode);
+ if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
+ {
+ dmodes[strlen(dmodes)+1]='\0';
+ dmodes[strlen(dmodes)] = parameters[1][i];
+ outpars[strlen(outpars)+1]='\0';
+ outpars[strlen(outpars)] = parameters[1][i];
+ }
+ }
+ }
+ else
+ {
+ // can only remove a mode they already have
+ log(DEBUG,"umode %c being removed",parameters[1][i]);
+ if ((allowed_umode(parameters[1][i],user->modes,false)) && (strchr(dmodes,parameters[1][i])))
+ {
+ char umode = parameters[1][i];
+ log(DEBUG,"umode %c is an allowed umode",umode);
+ if ((process_module_umode(umode, NULL, dest, direction)) || (umode == 'i') || (umode == 's') || (umode == 'w') || (umode == 'o'))
+ {
+ int q = 0;
+ char temp[MAXBUF];
+ char moo[MAXBUF];
+
+ outpars[strlen(outpars)+1]='\0';
+ outpars[strlen(outpars)] = parameters[1][i];
+
+ strcpy(temp,"");
+ for (q = 0; q < strlen(dmodes); q++)
+ {
+ if (dmodes[q] != parameters[1][i])
+ {
+ moo[0] = dmodes[q];
+ moo[1] = '\0';
+ strcat(temp,moo);
+ }
+ }
+ strcpy(dmodes,temp);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (strlen(outpars))
+ {
+ char b[MAXBUF];
+ strcpy(b,"");
+ int z = 0;
+ int i = 0;
+ while (i < strlen (outpars))
+ {
+ b[z++] = outpars[i++];
+ b[z] = '\0';
+ if (i<strlen(outpars)-1)
+ {
+ if (((outpars[i] == '-') || (outpars[i] == '+')) && ((outpars[i+1] == '-') || (outpars[i+1] == '+')))
+ {
+ // someones playing silly buggers and trying
+ // to put a +- or -+ into the line...
+ i++;
+ }
+ }
+ if (i == strlen(outpars)-1)
+ {
+ if ((outpars[i] == '-') || (outpars[i] == '+'))
+ {
+ i++;
+ }
+ }
+ }
+
+ z = strlen(b)-1;
+ if ((b[z] == '-') || (b[z] == '+'))
+ b[z] == '\0';
+
+ if ((!strcmp(b,"+")) || (!strcmp(b,"-")))
+ return;
+
+ if (strlen(dmodes)>MAXMODES)
+ {
+ dmodes[MAXMODES-1] = '\0';
+ }
+ log(DEBUG,"Stripped mode line");
+ log(DEBUG,"Line dest is now %s",dmodes);
+ strncpy(dest->modes,dmodes,MAXMODES);
+
+ }
+
+ return;
+ }
+
+ Ptr = FindChan(parameters[0]);
+ if (Ptr)
+ {
+ process_modes(parameters,user,Ptr,STATUS_OP,pcnt,false,true);
+ }
+}
+
+
+
/* This function pokes and hacks at a parameter list like the following:
*
* PART #winbot, #darkgalaxy :m00!
{
if (loop_call(handle_part,parameters,pcnt,user,0,pcnt-2,0))
return;
- del_channel(user,parameters[0],parameters[1]);
+ del_channel(user,parameters[0],parameters[1],false);
}
else
{
if (loop_call(handle_part,parameters,pcnt,user,0,pcnt-1,0))
return;
- del_channel(user,parameters[0],NULL);
+ del_channel(user,parameters[0],NULL,false);
}
}
if (user->registered == 7) {
FOREACH_MOD OnUserQuit(user);
WriteCommonExcept(user,"QUIT :%s",reason);
+
+ // Q token must go to ALL servers!!!
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"Q %s :%s",user->nick,reason);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (strcmp(servers[j]->name,ServerName))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent Q token");
+ }
+ }
+ }
}
/* push the socket on a stack of sockets due to be closed at the next opportunity
if (user->registered == 7) {
purge_empty_chans();
}
-
- client_exit = 1;
}
}
}
-// returns TRUE of any users on channel C occupy server 'servername'.
-
-bool ChanAnyOnThisServer(chanrec *c,char* servername)
-{
- log(DEBUG,"ChanAnyOnThisServer");
- for (user_hash::iterator i = clientlist.begin(); i != clientlist.end(); i++)
- {
- if (has_channel(i->second,c))
- {
- if (!strcasecmp(i->second->server,servername))
- {
- return true;
- }
- }
- }
- return false;
-}
-
void handle_privmsg(char **parameters, int pcnt, userrec *user)
{
userrec *dest;
return;
}
- WriteChannel(chan, user, "NOTICE %s :%s", chan->name, parameters[1]);
+ ChanExceptSender(chan, user, "NOTICE %s :%s", chan->name, parameters[1]);
+
+ // if any users of this channel are on remote servers, broadcast the packet
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"V %s %s :%s",user->nick,chan->name,parameters[1]);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (ChanAnyOnThisServer(chan,servers[j]->name))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ }
+ }
+ }
}
else
{
return;
}
- WriteTo(user, dest, "NOTICE %s :%s", dest->nick, parameters[1]);
+ if (!strcmp(dest->server,user->server))
+ {
+ // direct write, same server
+ WriteTo(user, dest, "NOTICE %s :%s", dest->nick, parameters[1]);
+ }
+ else
+ {
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (!strcasecmp(servers[j]->name,dest->server))
+ {
+ // direct write, same server
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"V %s %s :%s",user->nick,dest->nick,parameters[1]);
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ }
+ }
+ }
+ }
}
else
{
Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,parameters[0]);
WriteOpers("*** Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,parameters[0]);
WriteCommonExcept(user,"QUIT :%s%s",PrefixQuit,parameters[0]);
+
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"Q %s :%s%s",user->nick,PrefixQuit,parameters[0]);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (CommonOnThisServer(user,servers[j]->name))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent Q token");
+ }
+ }
+ }
}
else
{
Write(user->fd,"ERROR :Closing link (%s@%s) [QUIT]",user->ident,user->host);
WriteOpers("*** Client exiting: %s!%s@%s [Client exited]",user->nick,user->ident,user->host);
WriteCommonExcept(user,"QUIT :Client exited");
+
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"Q %s :Client exited",user->nick);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (CommonOnThisServer(user,servers[j]->name))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent Q token");
+ }
+ }
+ }
}
FOREACH_MOD OnUserQuit(user);
AddWhoWas(user);
if (user->registered == 7) {
purge_empty_chans();
}
-
- client_exit = 1;
}
void handle_who(char **parameters, int pcnt, userrec *user)
ShowMOTD(user);
FOREACH_MOD OnUserConnect(user);
WriteOpers("*** Client connecting on port %d: %s!%s@%s",user->port,user->nick,user->ident,user->host);
+
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"N %d %s %s %s %s +%s %s :%s",user->age,user->nick,user->host,user->dhost,user->ident,user->modes,ServerName,user->fullname);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (strcmp(servers[j]->name,ServerName))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent N token");
+ }
+ }
+ }
+
}
void handle_version(char **parameters, int pcnt, userrec *user)
if (user->registered == 7)
{
WriteCommon(user,"NICK %s",parameters[0]);
+
+ // Q token must go to ALL servers!!!
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"n %s %s",user->nick,parameters[0]);
+ for (int j = 0; j < 255; j++)
+ {
+ if (servers[j] != NULL)
+ {
+ if (strcmp(servers[j]->name,ServerName))
+ {
+ me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+ log(DEBUG,"Sent n token");
+ }
+ }
+ }
+
}
/* change the nick of the user in the users_hash */
{
char data[MAXBUF];
// send start of sync marker: Y <timestamp>
+ // at this point the ircd receiving it starts broadcasting this netburst to all ircds
+ // except the ones its receiving it from.
snprintf(data,MAXBUF,"Y %d",time(NULL));
serv->SendPacket(data,udp_host,udp_port,MyKey);
// send users and channels
for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
{
- snprintf(data,MAXBUF,"N %d %s %s %s %s %s %s :%s",u->second->age,u->second->nick,u->second->host,u->second->dhost,u->second->ident,u->second->modes,u->second->server,u->second->fullname);
+ snprintf(data,MAXBUF,"N %d %s %s %s %s +%s %s :%s",u->second->age,u->second->nick,u->second->host,u->second->dhost,u->second->ident,u->second->modes,u->second->server,u->second->fullname);
serv->SendPacket(data,udp_host,udp_port,MyKey);
if (strcmp(chlist(u->second),""))
{
// send end of sync marker: E <timestamp>
snprintf(data,MAXBUF,"F %d",time(NULL));
serv->SendPacket(data,udp_host,udp_port,MyKey);
+ // ircd sends its serverlist after the end of sync here
}
+
+void handle_V(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
+{
+ char* src = strtok(params," ");
+ char* dest = strtok(NULL," :");
+ char* text = strtok(NULL,"\r\n");
+ text++;
+
+ userrec* user = Find(src);
+ if (user)
+ {
+ userrec* dst = Find(dest);
+
+ if (dst)
+ {
+ WriteTo(user, dst, "NOTICE %s :%s", dst->nick, text);
+ }
+ else
+ {
+ chanrec* d = FindChan(dest);
+ if (d)
+ {
+ ChanExceptSender(d, user, "NOTICE %s :%s", d->name, text);
+ }
+ }
+ }
+
+}
+
+
void handle_P(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
{
- char* src = strtok(NULL," ");
+ char* src = strtok(params," ");
char* dest = strtok(NULL," :");
char* text = strtok(NULL,"\r\n");
text++;
}
}
+// m is modes set by users only (not servers) valid targets are channels or users.
+
+void handle_m(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
+{
+ // m blah #chatspike +b *!test@*4
+ char* pars[128];
+ char original[MAXBUF];
+ strncpy(original,params,MAXBUF);
+ int index = 0;
+
+ char* src = strtok(params," ");
+ userrec* user = Find(src);
+
+ if (user)
+ {
+ log(DEBUG,"Found user: %s",user->nick);
+ char* parameter = strtok(NULL," ");
+ while (parameter)
+ {
+ pars[index++] = parameter;
+ parameter = strtok(NULL," ");
+ }
+
+ log(DEBUG,"Calling merge_mode2");
+ merge_mode2(pars,--index,user);
+ if (FindChan(pars[0]))
+ {
+ log(DEBUG,"Target is channel");
+ WriteChannelLocal(FindChan(pars[0]), user, "MODE %s",original);
+ }
+ if (Find(pars[0]))
+ {
+ log(DEBUG,"Target is nick");
+ WriteTo(user,Find(pars[0]),"MODE %s",original);
+ }
+ }
+}
+
+
+void handle_L(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
+{
+ char* nick = strtok(params," ");
+ char* channel = strtok(NULL," :");
+ char* reason = strtok(NULL,"\r\n");
+ userrec* user = Find(nick);
+ reason++;
+ if (user)
+ {
+ if (strcmp(reason,""))
+ {
+ del_channel(user,channel,reason,true);
+ }
+ else
+ {
+ del_channel(user,channel,NULL,true);
+ }
+ }
+}
+
+void handle_Q(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
+{
+ char* nick = strtok(params," :");
+ char* reason = strtok(NULL,"\r\n");
+ reason++;
+
+ userrec* user = Find(nick);
+
+ if (user)
+ {
+ if (strlen(reason)>MAXQUIT)
+ {
+ reason[MAXQUIT-1] = '\0';
+ }
+
+
+ WriteCommonExcept(user,"QUIT :%s",reason);
+
+ user_hash::iterator iter = clientlist.find(user->nick);
+
+ if (iter != clientlist.end())
+ {
+ log(DEBUG,"deleting user hash value %d",iter->second);
+ if ((iter->second) && (user->registered == 7)) {
+ delete iter->second;
+ }
+ clientlist.erase(iter);
+ }
+
+ purge_empty_chans();
+ }
+}
+
+void handle_n(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
+{
+ char* oldnick = strtok(params," ");
+ char* newnick = strtok(NULL," ");
+
+ userrec* user = Find(oldnick);
+
+ if (user)
+ {
+ WriteCommon(user,"NICK %s",newnick);
+ user = ReHashNick(user->nick, newnick);
+ if (!user) return;
+ if (!user->nick) return;
+ strncpy(user->nick, newnick,NICKMAX);
+ log(DEBUG,"new nick set: %s",user->nick);
+ }
+}
+
void handle_N(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
{
char* tm = strtok(params," ");
char* server = strtok(NULL," :");
char* gecos = strtok(NULL,"\r\n");
gecos++;
+ modes++;
time_t TS = atoi(tm);
user_hash::iterator iter = clientlist.find(nick);
if (iter != clientlist.end())
clientlist[nick]->port = 0; // so is this...
clientlist[nick]->registered = 7; // this however we need to set for them to receive messages and appear online
clientlist[nick]->idle_lastmsg = time(NULL); // this is unrealiable and wont actually be used locally
+ for (int i = 0; i < MAXCHANS; i++)
+ {
+ clientlist[nick]->chans[i].channel = NULL;
+ clientlist[nick]->chans[i].uc_modes = 0;
+ }
}
void handle_F(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
case 'N':
handle_N(token,params,source,reply,udp_host,udp_port);
break;
+ // n <NICK> <NEWNICK>
+ // change nickname of client -- a server should only be able to
+ // change the nicknames of clients that reside on it unless
+ // they are ulined.
+ case 'n':
+ handle_n(token,params,source,reply,udp_host,udp_port);
+ break;
// J <NICK> <CHANLIST>
// Join user to channel list, merge channel permissions
case 'J':
case 'T':
handle_T(token,params,source,reply,udp_host,udp_port);
break;
- // M <TS> <TARGET> <MODES> [MODE-PARAMETERS]
- // Set modes on an object
+ // M <TARGET> <MODES> [MODE-PARAMETERS]
+ // Server setting modes on an object
case 'M':
handle_M(token,params,source,reply,udp_host,udp_port);
break;
+ // m <SOURCE> <TARGET> <MODES> [MODE-PARAMETERS]
+ // User setting modes on an object
+ case 'm':
+ handle_m(token,params,source,reply,udp_host,udp_port);
+ break;
// P <SOURCE> <TARGET> :<TEXT>
// Send a private/channel message
case 'P':
handle_P(token,params,source,reply,udp_host,udp_port);
break;
+ // V <SOURCE> <TARGET> :<TEXT>
+ // Send a private/channel notice
+ case 'V':
+ handle_V(token,params,source,reply,udp_host,udp_port);
+ break;
+ // L <SOURCE> <CHANNEL> :<REASON>
+ // User parting a channel
+ case 'L':
+ handle_L(token,params,source,reply,udp_host,udp_port);
+ break;
+ // Q <SOURCE> :<REASON>
+ // user quitting
+ case 'Q':
+ handle_Q(token,params,source,reply,udp_host,udp_port);
+ break;
// F <TS>
// end netburst
case 'F':