]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_cap.cpp
Change allocation of commands/modes
[user/henk/code/inspircd.git] / src / modules / m_cap.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd: (C) 2002-2009 InspIRCd Development Team
6  * See: http://wiki.inspircd.org/Credits
7  *
8  * This program is free but copyrighted software; see
9  *            the file COPYING for details.
10  *
11  * ---------------------------------------------------
12  */
13
14 #include "inspircd.h"
15 #include "m_cap.h"
16
17 /* $ModDesc: Provides the CAP negotiation mechanism seen in ratbox-derived ircds */
18
19 /*
20 CAP LS
21 :alfred.staticbox.net CAP * LS :multi-prefix sasl
22 CAP REQ :multi-prefix
23 :alfred.staticbox.net CAP * ACK :multi-prefix
24 CAP CLEAR
25 :alfred.staticbox.net CAP * ACK :-multi-prefix
26 CAP REQ :multi-prefix
27 :alfred.staticbox.net CAP * ACK :multi-prefix
28 CAP LIST
29 :alfred.staticbox.net CAP * LIST :multi-prefix
30 CAP END
31 */
32
33 /** Handle /CAP
34  */
35 class CommandCAP : public Command
36 {
37         Module* Creator;
38  public:
39         CommandCAP (InspIRCd* Instance, Module* mod) : Command(Instance,"CAP", 0, 1, true), Creator(mod)
40         {
41                 this->source = "m_cap.so";
42         }
43
44         CmdResult Handle (const std::vector<std::string> &parameters, User *user)
45         {
46                 irc::string subcommand = parameters[0].c_str();
47
48                 if (subcommand == "REQ")
49                 {
50                         CapData Data;
51
52                         Data.type = subcommand;
53                         Data.user = user;
54                         Data.creator = this->Creator;
55
56                         if (parameters.size() < 2)
57                                 return CMD_FAILURE;
58
59                         // tokenize the input into a nice list of requested caps
60                         std::string param = parameters[1];
61                         std::string cap_;
62                         irc::spacesepstream cap_stream(param);
63
64                         while (cap_stream.GetToken(cap_))
65                         {
66                                 Data.wanted.push_back(cap_);
67                         }
68
69                         user->Extend("CAP_REGHOLD");
70                         Event event((char*) &Data, (Module*)this->Creator, "cap_req");
71                         event.Send(this->ServerInstance);
72
73                         if (Data.ack.size() > 0)
74                         {
75                                 std::string AckResult = irc::stringjoiner(" ", Data.ack, 0, Data.ack.size() - 1).GetJoined();
76                                 user->WriteServ("CAP * ACK :%s", AckResult.c_str());
77                         }
78
79                         if (Data.wanted.size() > 0)
80                         {
81                                 std::string NakResult = irc::stringjoiner(" ", Data.wanted, 0, Data.wanted.size() - 1).GetJoined();
82                                 user->WriteServ("CAP * NAK :%s", NakResult.c_str());
83                         }
84                 }
85                 else if (subcommand == "END")
86                 {
87                         user->Shrink("CAP_REGHOLD");
88                 }
89                 else if ((subcommand == "LS") || (subcommand == "LIST"))
90                 {
91                         CapData Data;
92
93                         Data.type = subcommand;
94                         Data.user = user;
95                         Data.creator = this->Creator;
96
97                         user->Extend("CAP_REGHOLD");
98                         Event event((char*) &Data, (Module*)this->Creator, subcommand == "LS" ? "cap_ls" : "cap_list");
99                         event.Send(this->ServerInstance);
100
101                         std::string Result;
102                         if (Data.wanted.size() > 0)
103                                 Result = irc::stringjoiner(" ", Data.wanted, 0, Data.wanted.size() - 1).GetJoined();
104                         else
105                                 Result = "";
106
107                         user->WriteServ("CAP * %s :%s", subcommand.c_str(), Result.c_str());
108                 }
109                 else if (subcommand == "CLEAR")
110                 {
111                         CapData Data;
112
113                         Data.type = subcommand;
114                         Data.user = user;
115                         Data.creator = this->Creator;
116
117                         user->Extend("CAP_REGHOLD");
118                         Event event((char*) &Data, (Module*)this->Creator, "cap_clear");
119                         event.Send(this->ServerInstance);
120
121                         std::string Result = irc::stringjoiner(" ", Data.ack, 0, Data.ack.size() - 1).GetJoined();
122                         user->WriteServ("CAP * ACK :%s", Result.c_str());
123                 }
124                 else
125                 {
126                         user->WriteNumeric(ERR_INVALIDCAPSUBCOMMAND, "* %s :Invalid CAP subcommand", subcommand.c_str());
127                 }
128
129                 return CMD_FAILURE;
130         }
131 };
132
133 class ModuleCAP : public Module
134 {
135         CommandCAP newcommand;
136  public:
137         ModuleCAP(InspIRCd* Me)
138                 : Module(Me), newcommand(Me, this)
139         {
140                 ServerInstance->AddCommand(&newcommand);
141
142                 Implementation eventlist[] = { I_OnCheckReady };
143                 ServerInstance->Modules->Attach(eventlist, this, 1);
144         }
145
146         virtual bool OnCheckReady(User* user)
147         {
148                 /* Users in CAP state get held until CAP END */
149                 if (user->GetExt("CAP_REGHOLD"))
150                         return false;
151
152                 return true;
153         }
154
155         virtual ~ModuleCAP()
156         {
157         }
158
159         virtual Version GetVersion()
160         {
161                 return Version("$Id$", VF_VENDOR, API_VERSION);
162         }
163 };
164
165 MODULE_INIT(ModuleCAP)
166