]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/modules/m_cap.cpp
Add Module* creator to Command and ModeHandler
[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  public:
38         CommandCAP (InspIRCd* Instance, Module* mod) : Command(Instance, mod, "CAP", 0, 1, true)
39         {
40         }
41
42         CmdResult Handle (const std::vector<std::string> &parameters, User *user)
43         {
44                 irc::string subcommand = parameters[0].c_str();
45
46                 if (subcommand == "REQ")
47                 {
48                         CapData Data;
49
50                         Data.type = subcommand;
51                         Data.user = user;
52                         Data.creator = this->creator;
53
54                         if (parameters.size() < 2)
55                                 return CMD_FAILURE;
56
57                         // tokenize the input into a nice list of requested caps
58                         std::string param = parameters[1];
59                         std::string cap_;
60                         irc::spacesepstream cap_stream(param);
61
62                         while (cap_stream.GetToken(cap_))
63                         {
64                                 Data.wanted.push_back(cap_);
65                         }
66
67                         user->Extend("CAP_REGHOLD");
68                         Event event((char*) &Data, this->creator, "cap_req");
69                         event.Send(this->ServerInstance);
70
71                         if (Data.ack.size() > 0)
72                         {
73                                 std::string AckResult = irc::stringjoiner(" ", Data.ack, 0, Data.ack.size() - 1).GetJoined();
74                                 user->WriteServ("CAP * ACK :%s", AckResult.c_str());
75                         }
76
77                         if (Data.wanted.size() > 0)
78                         {
79                                 std::string NakResult = irc::stringjoiner(" ", Data.wanted, 0, Data.wanted.size() - 1).GetJoined();
80                                 user->WriteServ("CAP * NAK :%s", NakResult.c_str());
81                         }
82                 }
83                 else if (subcommand == "END")
84                 {
85                         user->Shrink("CAP_REGHOLD");
86                 }
87                 else if ((subcommand == "LS") || (subcommand == "LIST"))
88                 {
89                         CapData Data;
90
91                         Data.type = subcommand;
92                         Data.user = user;
93                         Data.creator = this->creator;
94
95                         user->Extend("CAP_REGHOLD");
96                         Event event((char*) &Data, this->creator, subcommand == "LS" ? "cap_ls" : "cap_list");
97                         event.Send(this->ServerInstance);
98
99                         std::string Result;
100                         if (Data.wanted.size() > 0)
101                                 Result = irc::stringjoiner(" ", Data.wanted, 0, Data.wanted.size() - 1).GetJoined();
102                         else
103                                 Result = "";
104
105                         user->WriteServ("CAP * %s :%s", subcommand.c_str(), Result.c_str());
106                 }
107                 else if (subcommand == "CLEAR")
108                 {
109                         CapData Data;
110
111                         Data.type = subcommand;
112                         Data.user = user;
113                         Data.creator = this->creator;
114
115                         user->Extend("CAP_REGHOLD");
116                         Event event((char*) &Data, this->creator, "cap_clear");
117                         event.Send(this->ServerInstance);
118
119                         std::string Result = irc::stringjoiner(" ", Data.ack, 0, Data.ack.size() - 1).GetJoined();
120                         user->WriteServ("CAP * ACK :%s", Result.c_str());
121                 }
122                 else
123                 {
124                         user->WriteNumeric(ERR_INVALIDCAPSUBCOMMAND, "* %s :Invalid CAP subcommand", subcommand.c_str());
125                 }
126
127                 return CMD_FAILURE;
128         }
129 };
130
131 class ModuleCAP : public Module
132 {
133         CommandCAP newcommand;
134  public:
135         ModuleCAP(InspIRCd* Me)
136                 : Module(Me), newcommand(Me, this)
137         {
138                 ServerInstance->AddCommand(&newcommand);
139
140                 Implementation eventlist[] = { I_OnCheckReady };
141                 ServerInstance->Modules->Attach(eventlist, this, 1);
142         }
143
144         virtual bool OnCheckReady(User* user)
145         {
146                 /* Users in CAP state get held until CAP END */
147                 if (user->GetExt("CAP_REGHOLD"))
148                         return false;
149
150                 return true;
151         }
152
153         virtual ~ModuleCAP()
154         {
155         }
156
157         virtual Version GetVersion()
158         {
159                 return Version("$Id$", VF_VENDOR, API_VERSION);
160         }
161 };
162
163 MODULE_INIT(ModuleCAP)
164