]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc-cap.c
"CAP REQ" starts capability negotiation and delays user registration
[ngircd-alex.git] / src / ngircd / irc-cap.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * Please read the file COPYING, README and AUTHORS for more information.
10  */
11
12 #include "portab.h"
13
14 /**
15  * @file
16  * Handler for IRC capability ("CAP") commands
17  */
18
19 #include "imp.h"
20 #include <assert.h>
21 #include <string.h>
22
23 #include "defines.h"
24 #include "conn.h"
25 #include "channel.h"
26 #include "client-cap.h"
27 #include "irc-write.h"
28 #include "log.h"
29 #include "login.h"
30 #include "messages.h"
31 #include "parse.h"
32
33 #include "exp.h"
34 #include "irc-cap.h"
35
36 bool Handle_CAP_LS PARAMS((CLIENT *Client, char *Arg));
37 bool Handle_CAP_LIST PARAMS((CLIENT *Client, char *Arg));
38 bool Handle_CAP_REQ PARAMS((CLIENT *Client, char *Arg));
39 bool Handle_CAP_ACK PARAMS((CLIENT *Client, char *Arg));
40 bool Handle_CAP_CLEAR PARAMS((CLIENT *Client));
41 bool Handle_CAP_END PARAMS((CLIENT *Client));
42
43 void Set_CAP_Negotiation PARAMS((CLIENT *Client));
44
45
46 /**
47  * Handler for the IRCv3 "CAP" command.
48  *
49  * @param Client The client from which this command has been received.
50  * @param Req Request structure with prefix and all parameters.
51  * @returns CONNECTED or DISCONNECTED.
52  */
53 GLOBAL bool
54 IRC_CAP(CLIENT *Client, REQUEST *Req)
55 {
56         assert(Client != NULL);
57         assert(Req != NULL);
58
59         /* Bad number of prameters? */
60         if (Req->argc < 1 || Req->argc > 2)
61                 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
62                                           Client_ID(Client), Req->command);
63
64         LogDebug("Got \"%s %s\" command from \"%s\" ...",
65                  Req->command, Req->argv[0], Client_ID(Client));
66
67         if (Req->argc == 1) {
68                 if (strcasecmp(Req->argv[0], "CLEAR") == 0)
69                         return Handle_CAP_CLEAR(Client);
70                 if (strcasecmp(Req->argv[0], "END") == 0)
71                         return Handle_CAP_END(Client);
72         }
73         if (Req->argc >= 1 && Req->argc <= 2) {
74                 if (strcasecmp(Req->argv[0], "LS") == 0)
75                         return Handle_CAP_LS(Client, Req->argv[1]);
76                 if (strcasecmp(Req->argv[0], "LIST") == 0)
77                         return Handle_CAP_LIST(Client, Req->argv[1]);
78         }
79         if (Req->argc == 2) {
80                 if (strcasecmp(Req->argv[0], "REQ") == 0)
81                         return Handle_CAP_REQ(Client, Req->argv[1]);
82                 if (strcasecmp(Req->argv[0], "ACK") == 0)
83                         return Handle_CAP_ACK(Client, Req->argv[1]);
84         }
85
86         return IRC_WriteStrClient(Client, ERR_INVALIDCAP_MSG,
87                                   Client_ID(Client), Req->argv[0]);
88 }
89
90 /**
91  * Handler for the "CAP LS" command.
92  *
93  * @param Client The client from which this command has been received.
94  * @param Arg Command argument or NULL.
95  * @returns CONNECTED or DISCONNECTED.
96  */
97 bool
98 Handle_CAP_LS(CLIENT *Client, UNUSED char *Arg)
99 {
100         assert(Client != NULL);
101
102         Set_CAP_Negotiation(Client);
103
104         return IRC_WriteStrClient(Client, "CAP %s LS :", Client_ID(Client));
105 }
106
107 /**
108  * Handler for the "CAP LIST" command.
109  *
110  * @param Client The client from which this command has been received.
111  * @param Arg Command argument or NULL.
112  * @returns CONNECTED or DISCONNECTED.
113  */
114 bool
115 Handle_CAP_LIST(CLIENT *Client, UNUSED char *Arg)
116 {
117         assert(Client != NULL);
118
119         return IRC_WriteStrClient(Client, "CAP %s LIST :", Client_ID(Client));
120 }
121
122 /**
123  * Handler for the "CAP REQ" command.
124  *
125  * @param Client The client from which this command has been received.
126  * @param Arg Command argument.
127  * @returns CONNECTED or DISCONNECTED.
128  */
129 bool
130 Handle_CAP_REQ(CLIENT *Client, char *Arg)
131 {
132         assert(Client != NULL);
133         assert(Arg != NULL);
134
135         Set_CAP_Negotiation(Client);
136
137         return IRC_WriteStrClient(Client, "CAP %s NAK :%s",
138                                   Client_ID(Client), Arg);
139 }
140
141 /**
142  * Handler for the "CAP ACK" command.
143  *
144  * @param Client The client from which this command has been received.
145  * @param Arg Command argument.
146  * @returns CONNECTED or DISCONNECTED.
147  */
148 bool
149 Handle_CAP_ACK(CLIENT *Client, char *Arg)
150 {
151         assert(Client != NULL);
152         assert(Arg != NULL);
153
154         return CONNECTED;
155 }
156
157 /**
158  * Handler for the "CAP CLEAR" command.
159  *
160  * @param Client The client from which this command has been received.
161  * @returns CONNECTED or DISCONNECTED.
162  */
163 bool
164 Handle_CAP_CLEAR(CLIENT *Client)
165 {
166         assert(Client != NULL);
167
168         return IRC_WriteStrClient(Client, "CAP %s ACK :", Client_ID(Client));
169 }
170
171 /**
172  * Handler for the "CAP END" command.
173  *
174  * @param Client The client from which this command has been received.
175  * @returns CONNECTED or DISCONNECTED.
176  */
177 bool
178 Handle_CAP_END(CLIENT *Client)
179 {
180         assert(Client != NULL);
181
182         if (Client_Type(Client) != CLIENT_USER) {
183                 /* User is still logging in ... */
184                 Client_CapDel(Client, CLIENT_CAP_PENDING);
185
186                 if (Client_Type(Client) == CLIENT_WAITCAPEND) {
187                         /* Only "CAP END" was missing: log in! */
188                         return Login_User(Client);
189                 }
190         }
191
192         return CONNECTED;
193 }
194
195 /**
196  * Set CAP negotiation status and mark client as "supports capabilities".
197  *
198  * @param Client The client to handle.
199  */
200 void
201 Set_CAP_Negotiation(CLIENT *Client)
202 {
203         assert(Client != NULL);
204
205         if (Client_Type(Client) != CLIENT_USER)
206                 Client_CapAdd(Client, CLIENT_CAP_PENDING);
207         Client_CapAdd(Client, CLIENT_CAP_SUPPORTED);
208 }
209
210 /* -eof- */