]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_spanningtree/capab.cpp
Split servers if they try to send infinite garbage without a newline
[user/henk/code/inspircd.git] / src / modules / m_spanningtree / capab.cpp
index 7ebee4bda6eba72adea98de74118ecc924ecb391..f76c78f8045a461e88b529ace079f9ada30a25a8 100644 (file)
@@ -19,8 +19,6 @@
 #include "utils.h"
 #include "main.h"
 
-/* $ModDep: m_spanningtree/utils.h m_spanningtree/treeserver.h m_spanningtree/treesocket.h */
-
 std::string TreeSocket::MyModules(int filter)
 {
        std::vector<std::string> modlist = ServerInstance->Modules->GetAllModuleNames(filter);
@@ -33,10 +31,10 @@ std::string TreeSocket::MyModules(int filter)
        for (unsigned int i = 0; i < modlist.size(); i++)
        {
                if (i)
-                       capabilities.push_back(',');
+                       capabilities.push_back(proto_version > 1201 ? ' ' : ',');
                capabilities.append(modlist[i]);
                Module* m = ServerInstance->Modules->Find(modlist[i]);
-               if (m && proto_version >= 1202)
+               if (m && proto_version > 1201)
                {
                        Version v = m->GetVersion();
                        if (!v.link_data.empty())
@@ -58,7 +56,7 @@ static std::string BuildModeList(ModeType type)
                if (mh)
                {
                        if (!line.empty())
-                               line.push_back(',');
+                               line.push_back(' ');
                        line.append(mh->name);
                        line.push_back('=');
                        if (mh->GetPrefix())
@@ -81,51 +79,47 @@ void TreeSocket::SendCapabilities(int phase)
        if (phase < 2)
                return;
 
-       irc::commasepstream modulelist(MyModules(VF_COMMON));
-       irc::commasepstream optmodulelist(MyModules(VF_OPTCOMMON));
+       char sep = proto_version > 1201 ? ' ' : ',';
+       irc::sepstream modulelist(MyModules(VF_COMMON), sep);
+       irc::sepstream optmodulelist(MyModules(VF_OPTCOMMON), sep);
        /* Send module names, split at 509 length */
        std::string item;
-       std::string line = "CAPAB MODULES ";
+       std::string line = "CAPAB MODULES :";
        while (modulelist.GetToken(item))
        {
                if (line.length() + item.length() + 1 > 509)
                {
                        this->WriteLine(line);
-                       line = "CAPAB MODULES ";
+                       line = "CAPAB MODULES :";
                }
 
-               if (line != "CAPAB MODULES ")
-                       line.append(",");
+               if (line != "CAPAB MODULES :")
+                       line.push_back(sep);
 
                line.append(item);
        }
-       if (line != "CAPAB MODULES ")
+       if (line != "CAPAB MODULES :")
                this->WriteLine(line);
 
-       line = "CAPAB MODSUPPORT ";
+       line = "CAPAB MODSUPPORT :";
        while (optmodulelist.GetToken(item))
        {
                if (line.length() + item.length() + 1 > 509)
                {
                        this->WriteLine(line);
-                       line = "CAPAB MODSUPPORT ";
+                       line = "CAPAB MODSUPPORT :";
                }
 
-               if (line != "CAPAB MODSUPPORT ")
-                       line.append(",");
+               if (line != "CAPAB MODSUPPORT :")
+                       line.push_back(sep);
 
                line.append(item);
        }
-       if (line != "CAPAB MODSUPPORT ")
+       if (line != "CAPAB MODSUPPORT :")
                this->WriteLine(line);
 
-       line = "CAPAB CHANMODES " + BuildModeList(MODETYPE_CHANNEL);
-       if (line != "CAPAB CHANMODES ")
-               this->WriteLine(line);
-
-       line = "CAPAB USERMODES " + BuildModeList(MODETYPE_USER);
-       if (line != "CAPAB USERMODES ")
-               this->WriteLine(line);
+       WriteLine("CAPAB CHANMODES :" + BuildModeList(MODETYPE_CHANNEL));
+       WriteLine("CAPAB USERMODES :" + BuildModeList(MODETYPE_USER));
 
        int ip6 = 0;
 #ifdef IPV6
@@ -160,35 +154,31 @@ void TreeSocket::SendCapabilities(int phase)
        this->WriteLine("CAPAB END");
 }
 
-/* Check a comma seperated list for an item */
-bool TreeSocket::HasItem(const std::string &list, const std::string &item)
-{
-       irc::commasepstream seplist(list);
-       std::string item2;
-
-       while (seplist.GetToken(item2))
-       {
-               if (item2 == item)
-                       return true;
-       }
-       return false;
-}
-
 /* Isolate and return the elements that are different between two comma seperated lists */
-std::string TreeSocket::ListDifference(const std::string &one, const std::string &two)
+void TreeSocket::ListDifference(const std::string &one, const std::string &two, char sep,
+               std::string& mleft, std::string& mright)
 {
-       irc::commasepstream list_one(one);
+       std::set<std::string> values;
+       irc::sepstream sepleft(one, sep);
+       irc::sepstream sepright(two, sep);
        std::string item;
-       std::string result;
-       while (list_one.GetToken(item))
+       while (sepleft.GetToken(item))
        {
-               if (!HasItem(two, item))
+               values.insert(item);
+       }
+       while (sepright.GetToken(item))
+       {
+               if (!values.erase(item))
                {
-                       result.append(" ");
-                       result.append(item);
+                       mleft.push_back(sep);
+                       mleft.append(item);
                }
        }
-       return result;
+       for(std::set<std::string>::iterator i = values.begin(); i != values.end(); ++i)
+       {
+               mright.push_back(sep);
+               mright.append(*i);
+       }
 }
 
 bool TreeSocket::Capab(const parameterlist &params)
@@ -213,47 +203,42 @@ bool TreeSocket::Capab(const parameterlist &params)
                /* Compare ModuleList and check CapKeys */
                if ((this->capab->ModuleList != this->MyModules(VF_COMMON)) && (this->capab->ModuleList.length()))
                {
-                       std::string diffIneed = ListDifference(this->capab->ModuleList, this->MyModules(VF_COMMON));
-                       std::string diffUneed = ListDifference(this->MyModules(VF_COMMON), this->capab->ModuleList);
-                       if (diffIneed.length() == 0 && diffUneed.length() == 0)
-                       {
-                               reason = "Module list in CAPAB is not alphabetically ordered, cannot compare lists.";
-                       }
-                       else
+                       std::string diffIneed, diffUneed;
+                       ListDifference(this->capab->ModuleList, this->MyModules(VF_COMMON), proto_version > 1201 ? ' ' : ',', diffIneed, diffUneed);
+                       if (diffIneed.length() || diffUneed.length())
                        {
                                reason = "Modules incorrectly matched on these servers.";
                                if (diffIneed.length())
                                        reason += " Not loaded here:" + diffIneed;
                                if (diffUneed.length())
                                        reason += " Not loaded there:" + diffUneed;
+                               this->SendError("CAPAB negotiation failed: "+reason);
+                               return false;
                        }
-                       this->SendError("CAPAB negotiation failed: "+reason);
-                       return false;
                }
                if (this->capab->OptModuleList != this->MyModules(VF_OPTCOMMON) && this->capab->OptModuleList.length())
                {
-                       std::string diffIneed = ListDifference(this->capab->OptModuleList, this->MyModules(VF_OPTCOMMON));
-                       std::string diffUneed = ListDifference(this->MyModules(VF_OPTCOMMON), this->capab->OptModuleList);
-                       if (diffIneed.length() == 0 && diffUneed.length() == 0)
-                       {
-                               reason = "Optional Module list in CAPAB is not alphabetically ordered, cannot compare lists.";
-                       }
-                       else if (Utils->AllowOptCommon)
+                       std::string diffIneed, diffUneed;
+                       ListDifference(this->capab->ModuleList, this->MyModules(VF_OPTCOMMON), ' ', diffIneed, diffUneed);
+                       if (diffIneed.length() || diffUneed.length())
                        {
-                               ServerInstance->SNO->WriteToSnoMask('l',
-                                       "Optional module lists do not match, some commands may not work globally.%s%s%s%s",
-                                       diffIneed.length() ? " Not loaded here:" : "", diffIneed.c_str(),
-                                       diffUneed.length() ? " Not loaded there:" : "", diffUneed.c_str());
-                       }
-                       else
-                       {
-                               reason = "Optional modules incorrectly matched on these servers, and options::allowmismatch not set.";
-                               if (diffIneed.length())
-                                       reason += " Not loaded here:" + diffIneed;
-                               if (diffUneed.length())
-                                       reason += " Not loaded there:" + diffUneed;
-                               this->SendError("CAPAB negotiation failed: "+reason);
-                               return false;
+                               if (Utils->AllowOptCommon)
+                               {
+                                       ServerInstance->SNO->WriteToSnoMask('l',
+                                               "Optional module lists do not match, some commands may not work globally.%s%s%s%s",
+                                               diffIneed.length() ? " Not loaded here:" : "", diffIneed.c_str(),
+                                               diffUneed.length() ? " Not loaded there:" : "", diffUneed.c_str());
+                               }
+                               else
+                               {
+                                       reason = "Optional modules incorrectly matched on these servers, and options::allowmismatch not set.";
+                                       if (diffIneed.length())
+                                               reason += " Not loaded here:" + diffIneed;
+                                       if (diffUneed.length())
+                                               reason += " Not loaded there:" + diffUneed;
+                                       this->SendError("CAPAB negotiation failed: "+reason);
+                                       return false;
+                               }
                        }
                }
 
@@ -279,13 +264,16 @@ bool TreeSocket::Capab(const parameterlist &params)
                {
                        if (capab->ChanModes != BuildModeList(MODETYPE_CHANNEL))
                        {
-                               std::string diffIneed = ListDifference(capab->ChanModes, BuildModeList(MODETYPE_CHANNEL));
-                               std::string diffUneed = ListDifference(BuildModeList(MODETYPE_CHANNEL), capab->ChanModes);
-                               reason = "Channel modes not matched on these servers.";
-                               if (diffIneed.length())
-                                       reason += " Not loaded here:" + diffIneed;
-                               if (diffUneed.length())
-                                       reason += " Not loaded there:" + diffUneed;
+                               std::string diffIneed, diffUneed;
+                               ListDifference(capab->ChanModes, BuildModeList(MODETYPE_CHANNEL), ' ', diffIneed, diffUneed);
+                               if (diffIneed.length() || diffUneed.length())
+                               {
+                                       reason = "Channel modes not matched on these servers.";
+                                       if (diffIneed.length())
+                                               reason += " Not loaded here:" + diffIneed;
+                                       if (diffUneed.length())
+                                               reason += " Not loaded there:" + diffUneed;
+                               }
                        }
                }
                else if (this->capab->CapKeys.find("CHANMODES") != this->capab->CapKeys.end())
@@ -298,13 +286,16 @@ bool TreeSocket::Capab(const parameterlist &params)
                {
                        if (capab->UserModes != BuildModeList(MODETYPE_USER))
                        {
-                               std::string diffIneed = ListDifference(capab->UserModes, BuildModeList(MODETYPE_USER));
-                               std::string diffUneed = ListDifference(BuildModeList(MODETYPE_USER), capab->UserModes);
-                               reason = "User modes not matched on these servers.";
-                               if (diffIneed.length())
-                                       reason += " Not loaded here:" + diffIneed;
-                               if (diffUneed.length())
-                                       reason += " Not loaded there:" + diffUneed;
+                               std::string diffIneed, diffUneed;
+                               ListDifference(capab->UserModes, BuildModeList(MODETYPE_USER), ' ', diffIneed, diffUneed);
+                               if (diffIneed.length() || diffUneed.length())
+                               {
+                                       reason = "User modes not matched on these servers.";
+                                       if (diffIneed.length())
+                                               reason += " Not loaded here:" + diffIneed;
+                                       if (diffUneed.length())
+                                               reason += " Not loaded there:" + diffUneed;
+                               }
                        }
                }
                else if (this->capab->CapKeys.find("USERMODES") != this->capab->CapKeys.end())
@@ -344,26 +335,26 @@ bool TreeSocket::Capab(const parameterlist &params)
        }
        else if ((params[0] == "MODULES") && (params.size() == 2))
        {
-               if (!this->capab->ModuleList.length())
+               if (!capab->ModuleList.length())
                {
-                       this->capab->ModuleList.append(params[1]);
+                       capab->ModuleList = params[1];
                }
                else
                {
-                       this->capab->ModuleList.append(",");
-                       this->capab->ModuleList.append(params[1]);
+                       capab->ModuleList.push_back(proto_version > 1201 ? ' ' : ',');
+                       capab->ModuleList.append(params[1]);
                }
        }
        else if ((params[0] == "MODSUPPORT") && (params.size() == 2))
        {
-               if (!this->capab->OptModuleList.length())
+               if (!capab->OptModuleList.length())
                {
-                       this->capab->OptModuleList.append(params[1]);
+                       capab->OptModuleList = params[1];
                }
                else
                {
-                       this->capab->OptModuleList.append(",");
-                       this->capab->OptModuleList.append(params[1]);
+                       capab->OptModuleList.push_back(' ');
+                       capab->OptModuleList.append(params[1]);
                }
        }
        else if ((params[0] == "CHANMODES") && (params.size() == 2))
@@ -378,11 +369,10 @@ bool TreeSocket::Capab(const parameterlist &params)
        {
                irc::tokenstream capabs(params[1]);
                std::string item;
-               bool more = true;
-               while ((more = capabs.GetToken(item)))
+               while (capabs.GetToken(item))
                {
                        /* Process each key/value pair */
-                       std::string::size_type equals = item.rfind('=');
+                       std::string::size_type equals = item.find('=');
                        if (equals != std::string::npos)
                        {
                                std::string var = item.substr(0, equals);