]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/channels.cpp
Removed a pointless check in ./configure --clean that made it only work with one...
[user/henk/code/inspircd.git] / src / channels.cpp
index 7a6f8546962e66d72f379f446d3f785ad23872fe..8a44479e068e122037a42f45c792302596f32cf3 100644 (file)
@@ -1,21 +1,16 @@
-/*   +------------------------------------+
- *   | Inspire Internet Relay Chat Daemon |
- *   +------------------------------------+
+/*       +------------------------------------+
+ *       | Inspire Internet Relay Chat Daemon |
+ *       +------------------------------------+
+ *
+ *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
  *
- *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
- *   E-mail:
- *       <brain@chatspike.net>
- *       <Craig@chatspike.net>
- * 
- * Written by Craig Edwards, Craig McLure, and others.
  * This program is free but copyrighted software; see
- *     the file COPYING for details.
+ *            the file COPYING for details.
  *
  * ---------------------------------------------------
  */
 
-using namespace std;
-
 #include <stdarg.h>
 #include "configreader.h"
 #include "inspircd.h"
@@ -28,7 +23,6 @@ chanrec::chanrec(InspIRCd* Instance) : ServerInstance(Instance)
 {
        *name = *topic = *setby = *key = 0;
        created = topicset = limit = 0;
-       internal_userlist.clear();
        memset(&modes,0,64);
        age = ServerInstance->Time(true);
 }
@@ -213,7 +207,7 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo
        {
                privs = "@";
 
-               if (IS_LOCAL(user))
+               if (IS_LOCAL(user) && override == false)
                {
                        MOD_RESULT = 0;
                        FOREACH_RESULT_I(Instance,I_OnUserPreJoin,OnUserPreJoin(user,NULL,cname,privs));
@@ -248,7 +242,7 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo
                 * remote users are allowed us to bypass channel modes
                 * and bans (used by servers)
                 */
-               if (IS_LOCAL(user)) /* was a check on fd > -1 */
+               if (IS_LOCAL(user) && override == false)
                {
                        MOD_RESULT = 0;
                        FOREACH_RESULT_I(Instance,I_OnUserPreJoin,OnUserPreJoin(user,Ptr,cname,privs));
@@ -274,11 +268,10 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo
                                if (Ptr->modes[CM_INVITEONLY])
                                {
                                        MOD_RESULT = 0;
-                                       irc::string xname(Ptr->name);
                                        FOREACH_RESULT_I(Instance,I_OnCheckInvite,OnCheckInvite(user, Ptr));
                                        if (!MOD_RESULT)
                                        {
-                                               if (user->IsInvited(xname))
+                                               if (user->IsInvited(Ptr->name))
                                                {
                                                        /* user was invited to channel */
                                                        /* there may be an optional channel NOTICE here */
@@ -289,7 +282,7 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo
                                                        return NULL;
                                                }
                                        }
-                                       user->RemoveInvite(xname);
+                                       user->RemoveInvite(Ptr->name);
                                }
                                if (Ptr->limit)
                                {
@@ -320,37 +313,27 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo
                }
        }
 
-       for (UserChanList::const_iterator index = user->chans.begin(); index != user->chans.end(); index++)
-       {
-               if ((*index)->channel == NULL)
-               {
-                       return chanrec::ForceChan(Instance, Ptr, *index, user, privs);
-               }
-       }
-
-       /*
-        * XXX: If the user is an oper here, we can just extend their user->chans vector by one
-        * and put the channel in here. Same for remote users which are not bound by
-        * the channel limits. Otherwise, nope, youre boned.
+       /* NOTE: If the user is an oper here, we can extend their user->chans by up to
+        * OPERMAXCHANS. For remote users which are not bound by the channel limits,
+        * we can extend infinitely. Otherwise, nope, youre restricted to MAXCHANS.
         */
-       if (!IS_LOCAL(user)) /* was a check on fd < 0 */
+       if (!IS_LOCAL(user) || override == true) /* was a check on fd < 0 */
        {
-               ucrec* a = new ucrec();
-               chanrec* c = chanrec::ForceChan(Instance, Ptr, a, user, privs);
-               user->chans.push_back(a);
-               return c;
+               return chanrec::ForceChan(Instance, Ptr, user, privs);
        }
        else if (*user->oper)
        {
                /* Oper allows extension up to the OPERMAXCHANS value */
                if (user->chans.size() < OPERMAXCHANS)
                {
-                       ucrec* a = new ucrec();
-                       chanrec* c = chanrec::ForceChan(Instance, Ptr, a, user, privs);
-                       user->chans.push_back(a);
-                       return c;
+                       return chanrec::ForceChan(Instance, Ptr, user, privs);
                }
        }
+       else if (user->chans.size() < MAXCHANS)
+       {
+               return chanrec::ForceChan(Instance, Ptr, user, privs);
+       }
+
 
        user->WriteServ("405 %s %s :You are on too many channels",user->nick, cname);
 
@@ -364,41 +347,22 @@ chanrec* chanrec::JoinUser(InspIRCd* Instance, userrec *user, const char* cn, bo
                        Ptr->DelUser(user);
                        DELETE(Ptr);
                        Instance->chanlist.erase(n);
-                       for (unsigned int index =0; index < user->chans.size(); index++)
-                       {
-                               if (user->chans[index]->channel == Ptr)
-                               {
-                                       user->chans[index]->channel = NULL;
-                                       user->chans[index]->uc_modes = 0;       
-                               }
-                       }
-               }
-       }
-       else
-       {
-               for (unsigned int index =0; index < user->chans.size(); index++)
-               {
-                       if (user->chans[index]->channel == Ptr)
-                       {
-                               user->chans[index]->channel = NULL;
-                               user->chans[index]->uc_modes = 0;
-                       }
                }
        }
+
        return NULL;
 }
 
-chanrec* chanrec::ForceChan(InspIRCd* Instance, chanrec* Ptr,ucrec *a,userrec* user, const std::string &privs)
+chanrec* chanrec::ForceChan(InspIRCd* Instance, chanrec* Ptr, userrec* user, const std::string &privs)
 {
        userrec* dummyuser = new userrec(Instance);
        std::string nick = user->nick;
 
-       a->uc_modes = 0;
        dummyuser->SetFd(FD_MAGIC_NUMBER);
-
-       a->channel = Ptr;
        Ptr->AddUser(user);
-       user->ModChannelCount(1);
+
+       /* Just in case they have no permissions */
+       user->chans[Ptr] = 0;
 
        for (std::string::const_iterator x = privs.begin(); x != privs.end(); x++)
        {
@@ -409,6 +373,27 @@ chanrec* chanrec::ForceChan(InspIRCd* Instance, chanrec* Ptr,ucrec *a,userrec* u
                        Ptr->SetPrefix(user, status, mh->GetPrefixRank(), true);
                        /* Make sure that the mode handler knows this mode was now set */
                        mh->OnModeChange(dummyuser, dummyuser, Ptr, nick, true);
+
+                       switch (mh->GetPrefix())
+                       {
+                               /* These logic ops are SAFE IN THIS CASE
+                                * because if the entry doesnt exist,
+                                * addressing operator[] creates it.
+                                * If they do exist, it points to it.
+                                * At all other times where we dont want
+                                * to create an item if it doesnt exist, we
+                                * must stick to ::find().
+                                */
+                               case '@':
+                                       user->chans[Ptr] |= STATUS_OP;
+                               break;
+                               case '%':
+                                       user->chans[Ptr] |= STATUS_HOP;
+                               break;
+                               case '+':
+                                       user->chans[Ptr] |= STATUS_VOICE;
+                               break;
+                       }
                }
        }
 
@@ -468,19 +453,13 @@ long chanrec::PartUser(userrec *user, const char* reason)
        if (!user)
                return this->GetUserCounter();
 
-       for (unsigned int i =0; i < user->chans.size(); i++)
+       UCListIter i = user->chans.find(this);
+       if (i != user->chans.end())
        {
-               /* zap it from the channel list of the user */
-               if (user->chans[i]->channel == this)
-               {
-                       FOREACH_MOD(I_OnUserPart,OnUserPart(user, this, reason ? reason : ""));
-                       this->WriteChannel(user, "PART %s%s%s", this->name, reason ? " :" : "", reason ? reason : "");
-                       user->chans[i]->uc_modes = 0;
-                       user->chans[i]->channel = NULL;
-                       user->ModChannelCount(-1);
-                       this->RemoveAllPrefixes(user);
-                       break;
-               }
+               FOREACH_MOD(I_OnUserPart,OnUserPart(user, this, reason ? reason : ""));
+               this->WriteChannel(user, "PART %s%s%s", this->name, reason ? " :" : "", reason ? reason : "");
+               user->chans.erase(i);
+               this->RemoveAllPrefixes(user);
        }
 
        if (!this->DelUser(user)) /* if there are no users left on the channel... */
@@ -518,16 +497,12 @@ long chanrec::ServerKickUser(userrec* user, const char* reason, bool triggereven
                FOREACH_MOD(I_OnUserKick,OnUserKick(NULL,user,this,reason));
        }
 
-       for (unsigned int i =0; i < user->chans.size(); i++)
+       UCListIter i = user->chans.find(this);
+       if (i != user->chans.end())
        {
-               if (user->chans[i]->channel == this)
-               {
-                       this->WriteChannelWithServ(ServerInstance->Config->ServerName, "KICK %s %s :%s", this->name, user->nick, reason);
-                       user->chans[i]->uc_modes = 0;
-                       user->chans[i]->channel = NULL;
-                       this->RemoveAllPrefixes(user);
-                       break;
-               }
+               this->WriteChannelWithServ(ServerInstance->Config->ServerName, "KICK %s %s :%s", this->name, user->nick, reason);
+               user->chans.erase(i);
+               this->RemoveAllPrefixes(user);
        }
 
        if (!this->DelUser(user))
@@ -592,18 +567,14 @@ long chanrec::KickUser(userrec *src, userrec *user, const char* reason)
        }
 
        FOREACH_MOD(I_OnUserKick,OnUserKick(src,user,this,reason));
-                       
-       for (UserChanList::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
+
+       UCListIter i = user->chans.find(this);
+       if (i != user->chans.end())
        {
                /* zap it from the channel list of the user */
-               if ((*i)->channel == this)
-               {
-                       this->WriteChannel(src, "KICK %s %s :%s", this->name, user->nick, reason);
-                       (*i)->uc_modes = 0;
-                       (*i)->channel = NULL;
-                       this->RemoveAllPrefixes(user);
-                       break;
-               }
+               this->WriteChannel(src, "KICK %s %s :%s", this->name, user->nick, reason);
+               user->chans.erase(i);
+               this->RemoveAllPrefixes(user);
        }
 
        if (!this->DelUser(user))
@@ -960,43 +931,37 @@ unsigned int chanrec::GetPrefixValue(userrec* user)
        return 0;
 }
 
-
 int chanrec::GetStatusFlags(userrec *user)
 {
-       for (std::vector<ucrec*>::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
+       UCListIter i = user->chans.find(this);
+       if (i != user->chans.end())
        {
-               if ((*i)->channel == this)
-               {
-                       return (*i)->uc_modes;
-               }
+               return i->second;
        }
        return 0;
 }
 
-
 int chanrec::GetStatus(userrec *user)
 {
        if (ServerInstance->ULine(user->server))
                return STATUS_OP;
 
-       for (std::vector<ucrec*>::const_iterator i = user->chans.begin(); i != user->chans.end(); i++)
+       UCListIter i = user->chans.find(this);
+       if (i != user->chans.end())
        {
-               if ((*i)->channel == this)
+               if ((i->second & UCMODE_OP) > 0)
                {
-                       if (((*i)->uc_modes & UCMODE_OP) > 0)
-                       {
-                               return STATUS_OP;
-                       }
-                       if (((*i)->uc_modes & UCMODE_HOP) > 0)
-                       {
-                               return STATUS_HOP;
-                       }
-                       if (((*i)->uc_modes & UCMODE_VOICE) > 0)
-                       {
-                               return STATUS_VOICE;
-                       }
-                       return STATUS_NORMAL;
+                       return STATUS_OP;
+               }
+               if ((i->second & UCMODE_HOP) > 0)
+               {
+                       return STATUS_HOP;
+               }
+               if ((i->second & UCMODE_VOICE) > 0)
+               {
+                       return STATUS_VOICE;
                }
+               return STATUS_NORMAL;
        }
        return STATUS_NORMAL;
 }