]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/modules/m_cap.h
Fix CAP REQ to be atomic like the standard dictates.
[user/henk/code/inspircd.git] / src / modules / m_cap.h
index 5c91abc32f42b63ba4c7e58270bdde436d61c1f8..23cf8cf69a748ef9a373340c1f3e5745b5340e2f 100644 (file)
@@ -1,68 +1,95 @@
-/*       +------------------------------------+
- *       | Inspire Internet Relay Chat Daemon |
- *       +------------------------------------+
+/*
+ * InspIRCd -- Internet Relay Chat Daemon
  *
- *  InspIRCd: (C) 2002-2008 InspIRCd Development Team
- * See: http://www.inspircd.org/wiki/index.php/Credits
+ *   Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org>
+ *   Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc>
  *
- * This program is free but copyrighted software; see
- *         the file COPYING for details.
+ * This file is part of InspIRCd.  InspIRCd is free software: you can
+ * redistribute it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation, version 2.
  *
- * ---------------------------------------------------
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __CAP_H__
-#define __CAP_H__
 
-#include <map>
-#include <string>
+#ifndef M_CAP_H
+#define M_CAP_H
+
+class GenericCap;
 
-class CapData
+class CapEvent : public Event
 {
  public:
-       irc::string type;
+       enum CapEventType
+       {
+               CAPEVENT_REQ,
+               CAPEVENT_LS,
+               CAPEVENT_LIST,
+               CAPEVENT_CLEAR
+       };
+
+       CapEventType type;
        std::vector<std::string> wanted;
        std::vector<std::string> ack;
+       std::vector<std::pair<GenericCap*, int> > changed; // HACK: clean this up before 2.2
        User* user;
-       Module* creator;
+       CapEvent(Module* sender, User* u, CapEventType capevtype) : Event(sender, "cap_request"), type(capevtype), user(u) {}
 };
 
-void GenericCapHandler(Event* ev, const std::string &extname, const std::string &cap)
+class GenericCap
 {
-       if (ev->GetEventID() == "cap_req")
-       {
-               CapData *data = (CapData *) ev->GetData();
-
-               std::vector<std::string>::iterator it;
-               if ((it = std::find(data->wanted.begin(), data->wanted.end(), cap)) != data->wanted.end())
-               {
-                       // we can handle this, so ACK it, and remove it from the wanted list
-                       data->ack.push_back(*it);
-                       data->wanted.erase(it);
-                       data->user->Extend(extname);
-               }
-       }
-
-       if (ev->GetEventID() == "cap_ls")
+ public:
+       LocalIntExt ext;
+       const std::string cap;
+       GenericCap(Module* parent, const std::string &Cap) : ext("cap_" + Cap, parent), cap(Cap)
        {
-               CapData *data = (CapData *) ev->GetData();
-               data->wanted.push_back(cap);
+               ServerInstance->Modules->AddService(ext);
        }
 
-       if (ev->GetEventID() == "cap_list")
+       void HandleEvent(Event& ev)
        {
-               CapData *data = (CapData *) ev->GetData();
+               if (ev.id != "cap_request")
+                       return;
 
-               if (data->user->GetExt(extname))
+               CapEvent *data = static_cast<CapEvent*>(&ev);
+               if (data->type == CapEvent::CAPEVENT_REQ)
+               {
+                       for (std::vector<std::string>::iterator it = data->wanted.begin(); it != data->wanted.end(); ++it)
+                       {
+                               if (it->empty())
+                                       continue;
+                               bool enablecap = ((*it)[0] != '-');
+                               if (((enablecap) && (*it == cap)) || (*it == "-" + cap))
+                               {
+                                       // we can handle this, so ACK it, and remove it from the wanted list
+                                       data->ack.push_back(*it);
+                                       data->wanted.erase(it);
+                                       data->changed.push_back(std::make_pair(this, ext.set(data->user, enablecap ? 1 : 0)));
+                                       break;
+                               }
+                       }
+               }
+               else if (data->type == CapEvent::CAPEVENT_LS)
+               {
                        data->wanted.push_back(cap);
+               }
+               else if (data->type == CapEvent::CAPEVENT_LIST)
+               {
+                       if (ext.get(data->user))
+                               data->wanted.push_back(cap);
+               }
+               else if (data->type == CapEvent::CAPEVENT_CLEAR)
+               {
+                       data->ack.push_back("-" + cap);
+                       ext.set(data->user, 0);
+               }
        }
-
-       if (ev->GetEventID() == "cap_clear")
-       {
-               CapData *data = (CapData *) ev->GetData();
-               data->ack.push_back("-" + cap);
-               data->user->Shrink(extname);
-       }
-}
+};
 
 #endif