]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/inspircd.cpp
Fixes
[user/henk/code/inspircd.git] / src / inspircd.cpp
index e4f4c51f3677c8478b2b043839dfabf284da28e3..79f2d58c450e7b915c5692174b13e4af81cefe88 100644 (file)
@@ -1601,11 +1601,8 @@ chanrec* add_channel(userrec *user, const char* cn, const char* key, bool overri
                                {
                                        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");
-                                               }
+                                               me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+                                               log(DEBUG,"Sent J token");
                                        }
                                }
                        }
@@ -1676,11 +1673,8 @@ chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool
                                        {
                                                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)");
-                                                       }
+                                                       me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+                                                       log(DEBUG,"Sent L token (with reason)");
                                                }
                                        }
                                }
@@ -1697,11 +1691,8 @@ chanrec* del_channel(userrec *user, const char* cname, const char* reason, bool
                                        {
                                                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)");
-                                                       }
+                                                       me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+                                                       log(DEBUG,"Sent L token (no reason)");
                                                }
                                        }
                                }
@@ -1773,7 +1764,8 @@ void kick_channel(userrec *src,userrec *user, chanrec *Ptr, char* reason)
        for (int i =0; i != MAXCHANS; i++)
        {
                /* zap it from the channel list of the user */
-               if (user->chans[i].channel == Ptr)
+               if (user->chans[i].channel)
+               if (!strcasecmp(user->chans[i].channel->name,Ptr->name))
                {
                        WriteChannel(Ptr,src,"KICK %s %s :%s",Ptr->name, user->nick, reason);
                        user->chans[i].uc_modes = 0;
@@ -1830,8 +1822,9 @@ int give_ops(userrec *user,char *dest,chanrec *chan,int status)
                log(DEFAULT,"*** BUG *** give_ops was given an invalid parameter");
                return 0;
        }
-       if (status != STATUS_OP)
+       if (status < STATUS_OP)
        {
+               log(DEBUG,"%s cant give ops to %s because they nave status %d and needs %d",user->nick,dest,status,STATUS_OP);
                WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name);
                return 0;
        }
@@ -1839,12 +1832,14 @@ int give_ops(userrec *user,char *dest,chanrec *chan,int status)
        {
                if (!isnick(dest))
                {
+                       log(DEFAULT,"the target nickname given to give_ops was invalid");
                        WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
                        return 0;
                }
                d = Find(dest);
                if (!d)
                {
+                       log(DEFAULT,"the target nickname given to give_ops couldnt be found");
                        WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
                        return 0;
                }
@@ -1852,17 +1847,21 @@ int give_ops(userrec *user,char *dest,chanrec *chan,int status)
                {
                        for (int i = 0; i != MAXCHANS; i++)
                        {
-                               if ((d->chans[i].channel == chan) && (chan != NULL))
+                               if ((d->chans[i].channel != NULL) && (chan != NULL))
+                               if (!strcasecmp(d->chans[i].channel->name,chan->name))
                                {
                                        if (d->chans[i].uc_modes & UCMODE_OP)
                                        {
                                                /* mode already set on user, dont allow multiple */
+                                               log(DEFAULT,"The target user given to give_ops was already opped on the channel");
                                                return 0;
                                        }
                                        d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_OP;
                                        log(DEBUG,"gave ops: %s %s",d->chans[i].channel->name,d->nick);
+                                       return 1;
                                }
                        }
+                       log(DEFAULT,"The target channel given to give_ops was not in the users mode list");
                }
        }
        return 1;
@@ -1900,7 +1899,8 @@ int give_hops(userrec *user,char *dest,chanrec *chan,int status)
                {
                        for (int i = 0; i != MAXCHANS; i++)
                        {
-                               if ((d->chans[i].channel == chan) && (chan != NULL))
+                               if ((d->chans[i].channel != NULL) && (chan != NULL))
+                               if (!strcasecmp(d->chans[i].channel->name,chan->name))
                                {
                                        if (d->chans[i].uc_modes & UCMODE_HOP)
                                        {
@@ -1909,6 +1909,7 @@ int give_hops(userrec *user,char *dest,chanrec *chan,int status)
                                        }
                                        d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_HOP;
                                        log(DEBUG,"gave h-ops: %s %s",d->chans[i].channel->name,d->nick);
+                                       return 1;
                                }
                        }
                }
@@ -1948,7 +1949,8 @@ int give_voice(userrec *user,char *dest,chanrec *chan,int status)
                {
                        for (int i = 0; i != MAXCHANS; i++)
                        {
-                               if ((d->chans[i].channel == chan) && (chan != NULL))
+                               if ((d->chans[i].channel != NULL) && (chan != NULL))
+                               if (!strcasecmp(d->chans[i].channel->name,chan->name))
                                {
                                        if (d->chans[i].uc_modes & UCMODE_VOICE)
                                        {
@@ -1957,6 +1959,7 @@ int give_voice(userrec *user,char *dest,chanrec *chan,int status)
                                        }
                                        d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_VOICE;
                                        log(DEBUG,"gave voice: %s %s",d->chans[i].channel->name,d->nick);
+                                       return 1;
                                }
                        }
                }
@@ -1974,8 +1977,9 @@ int take_ops(userrec *user,char *dest,chanrec *chan,int status)
                log(DEFAULT,"*** BUG *** take_ops was given an invalid parameter");
                return 0;
        }
-       if (status != STATUS_OP)
+       if (status < STATUS_OP)
        {
+               log(DEBUG,"%s cant give ops to %s because they have status %d and needs %d",user->nick,dest,status,STATUS_OP);
                WriteServ(user->fd,"482 %s %s :You're not a channel operator",user->nick, chan->name);
                return 0;
        }
@@ -1984,11 +1988,13 @@ int take_ops(userrec *user,char *dest,chanrec *chan,int status)
                d = Find(dest);
                if (!isnick(dest))
                {
+                       log(DEBUG,"take_ops was given an invalid target nickname of %s",dest);
                        WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
                        return 0;
                }
                if (!d)
                {
+                       log(DEBUG,"take_ops couldnt resolve the target nickname: %s",dest);
                        WriteServ(user->fd,"401 %s %s :No suck nick/channel",user->nick, dest);
                        return 0;
                }
@@ -1996,7 +2002,8 @@ int take_ops(userrec *user,char *dest,chanrec *chan,int status)
                {
                        for (int i = 0; i != MAXCHANS; i++)
                        {
-                               if ((d->chans[i].channel == chan) && (chan != NULL))
+                               if ((d->chans[i].channel != NULL) && (chan != NULL))
+                               if (!strcasecmp(d->chans[i].channel->name,chan->name))
                                {
                                        if ((d->chans[i].uc_modes & UCMODE_OP) == 0)
                                        {
@@ -2005,8 +2012,10 @@ int take_ops(userrec *user,char *dest,chanrec *chan,int status)
                                        }
                                        d->chans[i].uc_modes ^= UCMODE_OP;
                                        log(DEBUG,"took ops: %s %s",d->chans[i].channel->name,d->nick);
+                                       return 1;
                                }
                        }
+                       log(DEBUG,"take_ops couldnt locate the target channel in the target users list");
                }
        }
        return 1;
@@ -2044,7 +2053,8 @@ int take_hops(userrec *user,char *dest,chanrec *chan,int status)
                {
                        for (int i = 0; i != MAXCHANS; i++)
                        {
-                               if ((d->chans[i].channel == chan) && (chan != NULL))
+                               if ((d->chans[i].channel != NULL) && (chan != NULL))
+                               if (!strcasecmp(d->chans[i].channel->name,chan->name))
                                {
                                        if ((d->chans[i].uc_modes & UCMODE_HOP) == 0)
                                        {
@@ -2053,6 +2063,7 @@ int take_hops(userrec *user,char *dest,chanrec *chan,int status)
                                        }
                                        d->chans[i].uc_modes ^= UCMODE_HOP;
                                        log(DEBUG,"took h-ops: %s %s",d->chans[i].channel->name,d->nick);
+                                       return 1;
                                }
                        }
                }
@@ -2092,7 +2103,8 @@ int take_voice(userrec *user,char *dest,chanrec *chan,int status)
                {
                        for (int i = 0; i != MAXCHANS; i++)
                        {
-                               if ((d->chans[i].channel == chan) && (chan != NULL))
+                               if ((d->chans[i].channel != NULL) && (chan != NULL))
+                               if (!strcasecmp(d->chans[i].channel->name,chan->name))
                                {
                                        if ((d->chans[i].uc_modes & UCMODE_VOICE) == 0)
                                        {
@@ -2101,6 +2113,7 @@ int take_voice(userrec *user,char *dest,chanrec *chan,int status)
                                        }
                                        d->chans[i].uc_modes ^= UCMODE_VOICE;
                                        log(DEBUG,"took voice: %s %s",d->chans[i].channel->name,d->nick);
+                                       return 1;
                                }
                        }
                }
@@ -2227,7 +2240,7 @@ void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int
                return;
        }
 
-       log(DEBUG,"process_modes: start");
+       log(DEBUG,"process_modes: start: parameters=%d",pcnt);
 
        strcpy(modelist,parameters[1]); /* mode list, e.g. +oo-o */
                                        /* parameters[2] onwards are parameters for
@@ -2278,13 +2291,17 @@ void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int
                                break;
 
                                case 'o':
+                                       log(DEBUG,"Ops");
                                        if ((param >= pcnt)) break;
+                                       log(DEBUG,"Enough parameters left");
                                        if (mdir == 1)
                                        {
+                                               log(DEBUG,"calling give_ops");
                                                r = give_ops(user,parameters[param++],chan,status);
                                        }
                                        else
                                        {
+                                               log(DEBUG,"calling take_ops");
                                                r = take_ops(user,parameters[param++],chan,status);
                                        }
                                        if (r)
@@ -2590,7 +2607,7 @@ void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int
                if (local)
                {
                        log(DEBUG,"Local mode change");
-                       WriteChannelLocal(chan, user, "MODE %s",outstr);
+                       WriteChannelLocal(chan, user, "MODE %s %s",chan->name,outstr);
                }
                else
                {
@@ -2601,18 +2618,15 @@ void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int
                                        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);
+                                       snprintf(buffer,MAXBUF,"M %s %s",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");
-                                                               }
+                                                               me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+                                                               log(DEBUG,"Sent M token");
                                                        }
                                                }
                                        }
@@ -2633,11 +2647,8 @@ void process_modes(char **parameters,userrec* user,chanrec *chan,int status, int
                                                {
                                                        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");
-                                                               }
+                                                               me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+                                                               log(DEBUG,"Sent m token");
                                                        }
                                                }
                                        }
@@ -2971,6 +2982,7 @@ void handle_mode(char **parameters, int pcnt, userrec *user)
                                        WriteServ(user->fd,"367 %s %s %s %s %d",user->nick, Ptr->name, i->data, i->set_by, i->set_time);
                                }
                                WriteServ(user->fd,"368 %s %s :End of channel ban list",user->nick, Ptr->name);
+                               return;
                        }
                }
 
@@ -3541,7 +3553,7 @@ void merge_mode2(char **parameters, int pcnt, userrec* user)
                        return;
                }
 
-               process_modes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,true,true);
+               process_modes(parameters,user,Ptr,cstatus(user,Ptr),pcnt,false,false,true);
        }
 }
 
@@ -3758,10 +3770,11 @@ void handle_kick(char **parameters, int pcnt, userrec *user)
                WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, parameters[0]);
                return;
        }
+
+       char reason[MAXBUF];
        
        if (pcnt > 2)
        {
-               char reason[MAXBUF];
                strncpy(reason,parameters[2],MAXBUF);
                if (strlen(reason)>MAXKICK)
                {
@@ -3772,8 +3785,23 @@ void handle_kick(char **parameters, int pcnt, userrec *user)
        }
        else
        {
-               kick_channel(user,u,Ptr,user->nick);
+               strcpy(reason,user->nick);
+               kick_channel(user,u,Ptr,reason);
        }
+       
+       // this must be propogated so that channel membership is kept in step network-wide
+       
+       char buffer[MAXBUF];
+       snprintf(buffer,MAXBUF,"k %s %s %s :%s",user->nick,u->nick,Ptr->name,reason);
+       for (int j = 0; j < 255; j++)
+       {
+               if (servers[j] != NULL)
+               {
+                       me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+                       log(DEBUG,"Sent k token");
+               }
+       }
+       
 }
 
 
@@ -3991,6 +4019,21 @@ void handle_invite(char **parameters, int pcnt, userrec *user)
        u->InviteTo(c->name);
        WriteFrom(u->fd,user,"INVITE %s :%s",u->nick,c->name);
        WriteServ(user->fd,"341 %s %s %s",user->nick,u->nick,c->name);
+       
+       // i token must go to ALL servers!!!
+       char buffer[MAXBUF];
+       snprintf(buffer,MAXBUF,"i %s %s %s",u->nick,user->nick,c->name);
+       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 i token");
+                       }
+               }
+       }
 }
 
 void handle_topic(char **parameters, int pcnt, userrec *user)
@@ -4045,6 +4088,21 @@ void handle_topic(char **parameters, int pcnt, userrec *user)
                                strcpy(Ptr->setby,user->nick);
                                Ptr->topicset = time(NULL);
                                WriteChannel(Ptr,user,"TOPIC %s :%s",Ptr->name, Ptr->topic);
+
+                               // t token must go to ALL servers!!!
+                               char buffer[MAXBUF];
+                               snprintf(buffer,MAXBUF,"t %s %s :%s",user->nick,Ptr->name,topic);
+                               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 t token");
+                                               }
+                                       }
+                               }
                        }
                        else
                        {
@@ -4611,6 +4669,20 @@ void handle_whois(char **parameters, int pcnt, userrec *user)
        }
 }
 
+void send_network_quit(const char* nick, const char* reason)
+{
+               char buffer[MAXBUF];
+               snprintf(buffer,MAXBUF,"Q %s :%s",nick,reason);
+               for (int j = 0; j < 255; j++)
+               {
+                       if (servers[j] != NULL)
+                       {
+                               me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+                               log(DEBUG,"Sent Q token");
+                       }
+               }
+}
+
 void handle_quit(char **parameters, int pcnt, userrec *user)
 {
        user_hash::iterator iter = clientlist.find(user->nick);
@@ -4642,12 +4714,9 @@ void handle_quit(char **parameters, int pcnt, userrec *user)
                        {
                                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");
-                                       }
-                                       }
+                                       me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+                                       log(DEBUG,"Sent Q token");
+                               }
                        }
                }
                else
@@ -4662,12 +4731,9 @@ void handle_quit(char **parameters, int pcnt, userrec *user)
                        {
                                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");
-                                       }
-                                       }
+                                       me[defaultRoute]->SendPacket(buffer,servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+                                       log(DEBUG,"Sent Q token");
+                               }
                        }
                }
                FOREACH_MOD OnUserQuit(user);
@@ -4837,23 +4903,45 @@ int usercount_unknown(void)
        return c;
 }
 
-int chancount(void)
+long chancount(void)
 {
        return chanlist.size();
 }
 
-int servercount(void)
+long count_servs(void)
 {
-       return 1;
+       int c = 0;
+       for (int j = 0; j < 255; j++)
+       {
+               if (servers[j] != NULL)
+                       c++;
+       }
+       return c;
 }
 
+long servercount(void)
+{
+       return count_servs()+1;
+}
+
+long local_count()
+{
+       int c = 0;
+       for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
+       {
+               if ((i->second->fd) && (isnick(i->second->nick)) && (!strcasecmp(i->second->server,ServerName))) c++;
+       }
+       return c;
+}
+
+
 void handle_lusers(char **parameters, int pcnt, userrec *user)
 {
        WriteServ(user->fd,"251 %s :There are %d users and %d invisible on %d servers",user->nick,usercnt()-usercount_invisible(),usercount_invisible(),servercount());
        WriteServ(user->fd,"252 %s %d :operator(s) online",user->nick,usercount_opers());
        WriteServ(user->fd,"253 %s %d :unknown connections",user->nick,usercount_unknown());
        WriteServ(user->fd,"254 %s %d :channels formed",user->nick,chancount());
-       WriteServ(user->fd,"254 %s :I have %d clients and 0 servers",user->nick,usercnt());
+       WriteServ(user->fd,"254 %s :I have %d clients and %d servers",user->nick,local_count(),count_servs());
 }
 
 void handle_admin(char **parameters, int pcnt, userrec *user)
@@ -5113,6 +5201,28 @@ void handle_modules(char **parameters, int pcnt, userrec *user)
        }
 }
 
+// calls a handler function for a command
+
+void call_handler(const char* commandname,char **parameters, int pcnt, userrec *user)
+{
+               for (int i = 0; i < cmdlist.size(); i++)
+               {
+                       if (!strcasecmp(cmdlist[i].command,commandname))
+                       {
+                               if (cmdlist[i].handler_function)
+                               {
+                                       if (pcnt>=cmdlist[i].min_params)
+                                       {
+                                               if (strchr(user->modes,cmdlist[i].flags_needed))
+                                               {
+                                                       cmdlist[i].handler_function(parameters,pcnt,user);
+                                               }
+                                       }
+                               }
+                       }
+               }
+}
+
 void handle_stats(char **parameters, int pcnt, userrec *user)
 {
        if (pcnt != 1)
@@ -5252,6 +5362,7 @@ void handle_connect(char **parameters, int pcnt, userrec *user)
                for (int j = 0; j < 255; j++) {
                        if (servers[j] == NULL) {
                                servers[j] = new serverrec;
+                               //servers[j]->initiator = true;
                                strcpy(servers[j]->internal_addr,Link_IPAddr);
                                servers[j]->internal_port = LinkPort;
                                strcpy(servers[j]->name,Link_ServerName);
@@ -5293,6 +5404,16 @@ char islast(serverrec* s)
        return c;
 }
 
+long map_count(serverrec* s)
+{
+       int c = 0;
+       for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
+       {
+               if ((i->second->fd) && (isnick(i->second->nick)) && (!strcasecmp(i->second->server,s->name))) c++;
+       }
+       return c;
+}
+
 void handle_links(char **parameters, int pcnt, userrec *user)
 {
        WriteServ(user->fd,"364 %s %s %s :0 %s",user->nick,ServerName,ServerName,ServerDesc);
@@ -5308,12 +5429,19 @@ void handle_links(char **parameters, int pcnt, userrec *user)
 
 void handle_map(char **parameters, int pcnt, userrec *user)
 {
-       WriteServ(user->fd,"006 %s :%s",user->nick,ServerName);
+       char line[MAXBUF];
+       snprintf(line,MAXBUF,"006 %s :%s",user->nick,ServerName);
+       while (strlen(line) < 50)
+               strcat(line," ");
+       WriteServ(user->fd,"%s%d (%.2f%%)",line,local_count(),(float)(((float)local_count()/(float)usercnt())*100));
        for (int j = 0; j < 255; j++)
        {
                if (servers[j] != NULL)
                {
-                       WriteServ(user->fd,"006 %s :%c-%s",user->nick,islast(servers[j]),servers[j]->name);
+                       snprintf(line,MAXBUF,"006 %s :%c-%s",user->nick,islast(servers[j]),servers[j]->name);
+                       while (strlen(line) < 50)
+                               strcat(line," ");
+                       WriteServ(user->fd,"%s%d (%.2f%%)",line,map_count(servers[j]),(float)(((float)map_count(servers[j])/(float)usercnt())*100));
                }
        }
        WriteServ(user->fd,"007 %s :End of /MAP",user->nick);
@@ -5968,6 +6096,37 @@ void handle_P(char token,char* params,serverrec* source,serverrec* reply, char*
        
 }
 
+void handle_i(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
+{
+       char* nick = strtok(params," ");
+       char* from = strtok(NULL," ");
+       char* channel = strtok(NULL," ");
+       userrec* u = Find(nick);
+       userrec* user = Find(from);
+       chanrec* c = FindChan(channel);
+       if ((c) && (u) && (user))
+       {
+               u->InviteTo(c->name);
+               WriteFrom(u->fd,user,"INVITE %s :%s",u->nick,c->name);
+       }
+}
+
+void handle_t(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
+{
+       char* setby = strtok(params," ");
+       char* channel = strtok(NULL," :");
+       char* topic = strtok(NULL,"\r\n");
+       topic++;
+       userrec* u = Find(setby);
+       chanrec* c = FindChan(channel);
+       if ((c) && (u))
+       {
+               WriteChannelLocal(c,u,"TOPIC %s :%s",c->name,topic);
+               strncpy(c->topic,topic,MAXTOPIC);
+               strncpy(c->setby,u->nick,NICKMAX);
+       }       
+}
+       
 
 void handle_T(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
 {
@@ -6003,7 +6162,7 @@ void handle_M(char token,char* params,serverrec* source,serverrec* reply, char*
                pars[index++] = parameter;
                parameter = strtok(NULL," ");
        }
-       merge_mode(pars,--index);
+       merge_mode(pars,index);
        if (FindChan(target))
        {
                WriteChannelLocal(FindChan(target), NULL, "MODE %s",original);
@@ -6029,11 +6188,6 @@ void handle_m(char token,char* params,serverrec* source,serverrec* reply, char*
                return;
        }
        
-       char* o = original;
-       while (o[0] != ' ')
-               o++;
-       o++;
-       
        int index = 0;
        
        char* src = strtok(params," ");
@@ -6050,7 +6204,7 @@ void handle_m(char token,char* params,serverrec* source,serverrec* reply, char*
                }
                
                log(DEBUG,"Calling merge_mode2");
-               merge_mode2(pars,--index,user);
+               merge_mode2(pars,index,user);
        }
 }
 
@@ -6126,6 +6280,23 @@ void handle_n(char token,char* params,serverrec* source,serverrec* reply, char*
        }
 }
 
+// k <SOURCE> <DEST> <CHANNEL> :<REASON>
+void handle_k(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
+{
+       char* src = strtok(params," ");
+       char* dest = strtok(NULL," ");
+       char* channel = strtok(NULL," :");
+       char* reason = strtok(NULL,"\r\n");
+       reason++;
+       userrec* s = Find(src);
+       userrec* d = Find(dest);
+       chanrec* c = FindChan(channel);
+       if ((s) && (d) && (c))
+       {
+               kick_channel(s,d,c,reason);
+       }
+}
+
 void handle_N(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
 {
        char* tm = strtok(params," ");
@@ -6225,7 +6396,7 @@ void handle_J(char token,char* params,serverrec* source,serverrec* reply, char*
                                                if (privilage == '+')
                                                {
                                                        user->chans[i].uc_modes = user->chans[i].uc_modes | UCMODE_VOICE;
-                                                       WriteChannelLocal(user->chans[i].channel, NULL, "MODE %s +o %s",channel,user->nick);
+                                                       WriteChannelLocal(user->chans[i].channel, NULL, "MODE %s +v %s",channel,user->nick);
                                                }
                                        }
                                }
@@ -6246,11 +6417,39 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve
                        nb_start = time(NULL);
                        WriteOpers("Server %s is starting netburst.",source->name);
                break;
+               // ?
+               // ping
+               case '?':
+                       reply->SendPacket("!",udp_host,udp_port,MyKey);
+               break;
+               // ?
+               // pong
+               case '!':
+               break;
+               // *
+               // no operation
+               case '*':
+               break;
                // N <TS> <NICK> <HOST> <DHOST> <IDENT> <MODES> <SERVER> :<GECOS>
                // introduce remote client
                case 'N':
                        handle_N(token,params,source,reply,udp_host,udp_port);
                break;
+               // t <NICK> <CHANNEL> :<TOPIC>
+               // change a channel topic
+               case 't':
+                       handle_t(token,params,source,reply,udp_host,udp_port);
+               break;
+               // i <NICK> <CHANNEL>
+               // invite a user to a channel
+               case 'i':
+                       handle_i(token,params,source,reply,udp_host,udp_port);
+               break;
+               // k <SOURCE> <DEST> <CHANNEL> :<REASON>
+               // kick a user from a channel
+               case 'k':
+                       handle_k(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
@@ -6363,6 +6562,7 @@ void handle_link_packet(long theirkey, char* udp_msg, char* udp_host, int udp_po
                                                                strcpy(servers[j]->description,serverdesc);
                                                                servers[j]->internal_port = udp_port;
                                                                // create a server record for this server
+                                                               WriteOpers("Server %s authenticated, exchanging server keys...",servername);
                                                                snprintf(response,10240,"O %d",MyKey);
                                                                serv->SendPacket(response,udp_host,udp_port,0);
                                                                return;
@@ -6397,7 +6597,7 @@ void handle_link_packet(long theirkey, char* udp_msg, char* udp_host, int udp_po
                                if (!strcasecmp(servers[i]->internal_addr,udp_host)) {
                                        servers[i]->key = atoi(params);
                                        log(DEBUG,"Key for this server is now %d",servers[i]->key);
-                                       DoSync(serv,udp_host,udp_port,MyKey);
+                                       servers[i]->sync_soon = true;
                                        return;
                                }
                        }
@@ -6695,7 +6895,7 @@ int InspIRCd(void)
        {
 
                fd_set sfd;
-               struct timeval tval;
+               timeval tval;
                FD_ZERO(&sfd);
 
                user_hash::iterator count2 = clientlist.begin();
@@ -6715,6 +6915,17 @@ int InspIRCd(void)
                        }
                        fd_reap.clear();
                        reap_counter=0;
+                       for (int j = 0; j < 255; j++)
+                       {
+                               if (servers[j])
+                               {
+                                       if (servers[j]->sync_soon)
+                                       {
+                                               servers[j]->sync_soon = false;
+                                               DoSync(servers[j],servers[j]->internal_addr,servers[j]->internal_port,MyKey);
+                                       }
+                               }
+                       }
                }