]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/channels.cpp
Update m_exemptchanops to allow users to specify the status required for the exemption
[user/henk/code/inspircd.git] / src / channels.cpp
index d7f8f372e47b1645742027286aa4b5bee4d2bcf4..0b9eb1cc478d1681ecfcb1a8fd59b6915f046844 100644 (file)
@@ -2,7 +2,7 @@
  *       | Inspire Internet Relay Chat Daemon |
  *       +------------------------------------+
  *
- *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
+ *  InspIRCd: (C) 2002-2010 InspIRCd Development Team
  * See: http://wiki.inspircd.org/Credits
  *
  * This program is free but copyrighted software; see
@@ -36,7 +36,12 @@ void Channel::SetMode(char mode,bool mode_on)
        modes[mode-65] = mode_on;
 }
 
-void Channel::SetModeParam(char mode, std::string parameter)
+void Channel::SetMode(ModeHandler* mh, bool on)
+{
+       modes[mh->GetModeChar() - 65] = on;
+}
+
+void Channel::SetModeParam(char mode, const std::string& parameter)
 {
        CustomModeList::iterator n = custom_mode_params.find(mode);
        // always erase, even if changing, so that the map gets the new value
@@ -53,6 +58,11 @@ void Channel::SetModeParam(char mode, std::string parameter)
        }
 }
 
+void Channel::SetModeParam(ModeHandler* mode, const std::string& parameter)
+{
+       SetModeParam(mode->GetModeChar(), parameter);
+}
+
 std::string Channel::GetModeParameter(char mode)
 {
        CustomModeList::iterator n = custom_mode_params.find(mode);
@@ -61,31 +71,36 @@ std::string Channel::GetModeParameter(char mode)
        return "";
 }
 
+std::string Channel::GetModeParameter(ModeHandler* mode)
+{
+       CustomModeList::iterator n = custom_mode_params.find(mode->GetModeChar());
+       if (n != custom_mode_params.end())
+               return n->second;
+       return "";
+}
+
 int Channel::SetTopic(User *u, std::string &ntopic, bool forceset)
 {
-       if (u)
+       if (!u)
+               u = ServerInstance->FakeClient;
+       if (IS_LOCAL(u) && !forceset)
        {
-               if(!forceset)
-               {
-                       ModResult res;
-                       /* 0: check status, 1: don't, -1: disallow change silently */
-
-                       FIRST_MOD_RESULT(OnPreTopicChange, res, (u,this,ntopic));
+               ModResult res;
+               FIRST_MOD_RESULT(OnPreTopicChange, res, (u,this,ntopic));
 
-                       if (res == MOD_RES_DENY)
+               if (res == MOD_RES_DENY)
+                       return CMD_FAILURE;
+               if (res != MOD_RES_ALLOW)
+               {
+                       if (!this->HasUser(u))
+                       {
+                               u->WriteNumeric(442, "%s %s :You're not on that channel!",u->nick.c_str(), this->name.c_str());
                                return CMD_FAILURE;
-                       if (res != MOD_RES_ALLOW)
+                       }
+                       if ((this->IsModeSet('t')) && (this->GetPrefixValue(u) < HALFOP_VALUE))
                        {
-                               if (!this->HasUser(u))
-                               {
-                                       u->WriteNumeric(442, "%s %s :You're not on that channel!",u->nick.c_str(), this->name.c_str());
-                                       return CMD_FAILURE;
-                               }
-                               if ((this->IsModeSet('t')) && (this->GetPrefixValue(u) < HALFOP_VALUE))
-                               {
-                                       u->WriteNumeric(482, "%s %s :You must be at least a half-operator to change the topic on this channel", u->nick.c_str(), this->name.c_str());
-                                       return CMD_FAILURE;
-                               }
+                               u->WriteNumeric(482, "%s %s :You do not have access to change the topic on this channel", u->nick.c_str(), this->name.c_str());
+                               return CMD_FAILURE;
                        }
                }
        }
@@ -104,11 +119,7 @@ int Channel::SetTopic(User *u, std::string &ntopic, bool forceset)
 
        this->topicset = ServerInstance->Time();
 
-       // XXX: this check for 'u' is probably pre-fake-user, and it fucking sucks anyway. we need to change this.
-       if (u)
-       {
-               FOREACH_MOD(I_OnPostTopicChange,OnPostTopicChange(u, this, this->topic));
-       }
+       FOREACH_MOD(I_OnPostTopicChange,OnPostTopicChange(u, this, this->topic));
 
        return CMD_SUCCESS;
 }
@@ -218,24 +229,23 @@ Channel* Channel::JoinUser(User *user, const char* cn, bool override, const char
         */
        if (IS_LOCAL(user) && !override)
        {
-               // Checking MyClass exists because we *may* get here with NULL, not 100% sure.
-               if (user->MyClass && user->MyClass->maxchans)
+               if (user->HasPrivPermission("channels/high-join-limit"))
                {
-                       if (user->HasPrivPermission("channels/high-join-limit"))
+                       if (user->chans.size() >= ServerInstance->Config->OperMaxChans)
                        {
-                               if (user->chans.size() >= ServerInstance->Config->OperMaxChans)
-                               {
-                                       user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
-                                       return NULL;
-                               }
+                               user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
+                               return NULL;
                        }
-                       else
+               }
+               else
+               {
+                       unsigned int maxchans = user->GetClass()->maxchans;
+                       if (!maxchans)
+                               maxchans = ServerInstance->Config->MaxChans;
+                       if (user->chans.size() >= maxchans)
                        {
-                               if (user->chans.size() >= user->MyClass->maxchans)
-                               {
-                                       user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
-                                       return NULL;
-                               }
+                               user->WriteNumeric(ERR_TOOMANYCHANNELS, "%s %s :You are on too many channels",user->nick.c_str(), cn);
+                               return NULL;
                        }
                }
        }
@@ -291,7 +301,7 @@ Channel* Channel::JoinUser(User *user, const char* cn, bool override, const char
                        else if (MOD_RESULT == MOD_RES_PASSTHRU)
                        {
                                std::string ckey = Ptr->GetModeParameter('k');
-                               bool invited = user->IsInvited(Ptr->name.c_str());
+                               bool invited = IS_LOCAL(user)->IsInvited(Ptr->name.c_str());
                                bool can_bypass = ServerInstance->Config->InvBypassModes && invited;
 
                                if (!ckey.empty())
@@ -338,7 +348,7 @@ Channel* Channel::JoinUser(User *user, const char* cn, bool override, const char
                                 */
                                if (invited)
                                {
-                                       user->RemoveInvite(Ptr->name.c_str());
+                                       IS_LOCAL(user)->RemoveInvite(Ptr->name.c_str());
                                }
                        }
                }
@@ -378,7 +388,9 @@ Channel* Channel::ForceChan(Channel* Ptr, User* user, const std::string &privs,
        Ptr->WriteAllExcept(user, false, 0, except_list, "JOIN :%s", Ptr->name.c_str());
 
        /* Theyre not the first ones in here, make sure everyone else sees the modes we gave the user */
-       std::string ms = ServerInstance->Modes->ModeString(user, Ptr);
+       std::string ms = memb->modes;
+       for(unsigned int i=0; i < memb->modes.length(); i++)
+               ms.append(" ").append(user->nick);
        if ((Ptr->GetUserCounter() > 1) && (ms.length()))
                Ptr->WriteAllExceptSender(user, true, 0, "MODE %s +%s", Ptr->name.c_str(), ms.c_str());
 
@@ -484,16 +496,6 @@ void Channel::PartUser(User *user, std::string &reason)
        this->DelUser(user);
 }
 
-void Channel::ServerKickUser(User* user, const char* reason, const std::string& servername)
-{
-       if (servername.empty() || !ServerInstance->Config->HideWhoisServer.empty())
-               ServerInstance->FakeClient->server = ServerInstance->Config->ServerName;
-       else
-               ServerInstance->FakeClient->server = servername;
-
-       KickUser(ServerInstance->FakeClient, user, reason);
-}
-
 void Channel::KickUser(User *src, User *user, const char* reason)
 {
        if (!src || !user || !reason)
@@ -655,19 +657,19 @@ void Channel::WriteAllExcept(User* user, bool serversource, char status, CUList
 
 void Channel::RawWriteAllExcept(User* user, bool serversource, char status, CUList &except_list, const std::string &out)
 {
-       char statmode = 0;
+       unsigned int minrank = 0;
        if (status)
        {
                ModeHandler* mh = ServerInstance->Modes->FindPrefix(status);
                if (mh)
-                       statmode = mh->GetModeChar();
+                       minrank = mh->GetPrefixRank();
        }
        for (UserMembIter i = userlist.begin(); i != userlist.end(); i++)
        {
-               if ((IS_LOCAL(i->first)) && (except_list.find(i->first) == except_list.end()))
+               if (IS_LOCAL(i->first) && (except_list.find(i->first) == except_list.end()))
                {
-                       /* User doesnt have the status we're after */
-                       if (statmode && !i->second->hasMode(statmode))
+                       /* User doesn't have the status we're after */
+                       if (minrank && i->second->getRank() < minrank)
                                continue;
 
                        i->first->Write(out);
@@ -715,30 +717,13 @@ char* Channel::ChanModes(bool showkey)
                {
                        *offset++ = n + 65;
                        extparam.clear();
-                       switch (n)
+                       if (n == 'k' - 65 && !showkey)
                        {
-                               case CM_KEY:
-                                       // Unfortunately this must be special-cased, as we definitely don't want to always display key.
-                                       if (showkey)
-                                       {
-                                               extparam = this->GetModeParameter('k');
-                                       }
-                                       else
-                                       {
-                                               extparam = "<key>";
-                                       }
-                                       break;
-                               case CM_NOEXTERNAL:
-                               case CM_TOPICLOCK:
-                               case CM_INVITEONLY:
-                               case CM_MODERATED:
-                               case CM_SECRET:
-                               case CM_PRIVATE:
-                                       /* We know these have no parameters */
-                               break;
-                               default:
-                                       extparam = this->GetModeParameter(n + 65);
-                               break;
+                               extparam = "<key>";
+                       }
+                       else
+                       {
+                               extparam = this->GetModeParameter(n + 65);
                        }
                        if (!extparam.empty())
                        {
@@ -937,14 +922,14 @@ unsigned int Channel::GetPrefixValue(User* user)
        return m->second->getRank();
 }
 
-void Channel::SetPrefix(User* user, char prefix, bool adding)
+bool Channel::SetPrefix(User* user, char prefix, bool adding)
 {
        ModeHandler* delta_mh = ServerInstance->Modes->FindMode(prefix, MODETYPE_CHANNEL);
        if (!delta_mh)
-               return;
+               return false;
        UserMembIter m = userlist.find(user);
        if (m == userlist.end())
-               return;
+               return false;
        for(unsigned int i=0; i < m->second->modes.length(); i++)
        {
                char mchar = m->second->modes[i];
@@ -955,11 +940,12 @@ void Channel::SetPrefix(User* user, char prefix, bool adding)
                                m->second->modes.substr(0,i) +
                                (adding ? std::string(1, prefix) : "") +
                                m->second->modes.substr(mchar == prefix ? i+1 : i);
-                       return;
+                       return adding != (mchar == prefix);
                }
        }
        if (adding)
                m->second->modes += std::string(1, prefix);
+       return adding;
 }
 
 void Channel::RemoveAllPrefixes(User* user)