1 |
/* |
2 |
* ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd) |
3 |
* |
4 |
* Copyright (c) 1997-2019 ircd-hybrid development team |
5 |
* |
6 |
* This program is free software; you can redistribute it and/or modify |
7 |
* it under the terms of the GNU General Public License as published by |
8 |
* the Free Software Foundation; either version 2 of the License, or |
9 |
* (at your option) any later version. |
10 |
* |
11 |
* This program is distributed in the hope that it will be useful, |
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
* GNU General Public License for more details. |
15 |
* |
16 |
* You should have received a copy of the GNU General Public License |
17 |
* along with this program; if not, write to the Free Software |
18 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 |
19 |
* USA |
20 |
*/ |
21 |
|
22 |
/*! \file isupport.c |
23 |
* \brief Contains functions pertaining to RPL_ISUPPORT. |
24 |
* \version $Id$ |
25 |
*/ |
26 |
|
27 |
#include "stdinc.h" |
28 |
#include "list.h" |
29 |
#include "ircd.h" |
30 |
#include "conf.h" |
31 |
#include "send.h" |
32 |
#include "numeric.h" |
33 |
#include "client.h" |
34 |
#include "irc_string.h" |
35 |
#include "memory.h" |
36 |
#include "isupport.h" |
37 |
#include "channel_mode.h" |
38 |
#include "parse.h" |
39 |
|
40 |
|
41 |
/* Used for building up the isupport string, |
42 |
* used with init_isupport, add_isupport, delete_isupport |
43 |
*/ |
44 |
struct Isupport |
45 |
{ |
46 |
dlink_node node; |
47 |
char *name; |
48 |
char *options; |
49 |
int number; |
50 |
}; |
51 |
|
52 |
static dlink_list isupport_list; |
53 |
static dlink_list isupport_list_lines; |
54 |
|
55 |
/* |
56 |
* isupport_init() |
57 |
* |
58 |
* input - NONE |
59 |
* output - NONE |
60 |
* side effects - Must be called before isupport is enabled |
61 |
*/ |
62 |
void |
63 |
isupport_init(void) |
64 |
{ |
65 |
isupport_add("CALLERID", NULL, -1); |
66 |
isupport_add("CASEMAPPING", "ascii", -1); |
67 |
isupport_add("DEAF", "D", -1); |
68 |
isupport_add("KICKLEN", NULL, KICKLEN); |
69 |
isupport_add("MODES", NULL, MAXMODEPARAMS); |
70 |
isupport_add("PREFIX", "(ohv)" CMEMBER_STATUS_FLAGS, -1); |
71 |
isupport_add("STATUSMSG", CMEMBER_STATUS_FLAGS, -1); |
72 |
isupport_add("EXCEPTS", NULL, -1); |
73 |
isupport_add("INVEX", NULL, -1); |
74 |
} |
75 |
|
76 |
/* |
77 |
* isupport_add() |
78 |
* |
79 |
* input - name of supported function |
80 |
* - options if any |
81 |
* - number if any |
82 |
* output - NONE |
83 |
* side effects - Each supported item must call this when activated |
84 |
*/ |
85 |
void |
86 |
isupport_add(const char *name, const char *options, int n) |
87 |
{ |
88 |
dlink_node *node = NULL; |
89 |
struct Isupport *support = NULL; |
90 |
|
91 |
DLINK_FOREACH(node, isupport_list.head) |
92 |
{ |
93 |
support = node->data; |
94 |
if (irccmp(support->name, name) == 0) |
95 |
{ |
96 |
xfree(support->name); |
97 |
xfree(support->options); |
98 |
break; |
99 |
} |
100 |
} |
101 |
|
102 |
if (node == NULL) |
103 |
{ |
104 |
support = xcalloc(sizeof(*support)); |
105 |
dlinkAddTail(support, &support->node, &isupport_list); |
106 |
} |
107 |
|
108 |
support->name = xstrdup(name); |
109 |
if (options) |
110 |
support->options = xstrdup(options); |
111 |
support->number = n; |
112 |
|
113 |
isupport_rebuild(); |
114 |
} |
115 |
|
116 |
/* |
117 |
* isupport_delete() |
118 |
* |
119 |
* input - name of supported function |
120 |
* output - NONE |
121 |
* side effects - Each supported item must call this when deactivated |
122 |
*/ |
123 |
void |
124 |
isupport_delete(const char *name) |
125 |
{ |
126 |
dlink_node *node = NULL; |
127 |
|
128 |
DLINK_FOREACH(node, isupport_list.head) |
129 |
{ |
130 |
struct Isupport *support = node->data; |
131 |
|
132 |
if (irccmp(support->name, name) == 0) |
133 |
{ |
134 |
dlinkDelete(node, &isupport_list); |
135 |
xfree(support->name); |
136 |
xfree(support->options); |
137 |
xfree(support); |
138 |
break; |
139 |
} |
140 |
} |
141 |
|
142 |
isupport_rebuild(); |
143 |
} |
144 |
|
145 |
/* |
146 |
* issuport_rebuild() |
147 |
* |
148 |
* input - NONE |
149 |
* output - NONE |
150 |
* side effects - Destroy the isupport MessageFile lines, and rebuild. |
151 |
*/ |
152 |
void |
153 |
isupport_rebuild(void) |
154 |
{ |
155 |
char isupportbuffer[IRCD_BUFSIZE]; |
156 |
char *p = isupportbuffer; |
157 |
dlink_node *node = NULL, *node_next = NULL; |
158 |
int n = 0; |
159 |
int tokens = 0; |
160 |
size_t len = 0; |
161 |
size_t reserve = strlen(me.name) + HOSTLEN + strlen(numeric_form(RPL_ISUPPORT)); |
162 |
|
163 |
DLINK_FOREACH_SAFE(node, node_next, isupport_list_lines.head) |
164 |
{ |
165 |
dlinkDelete(node, &isupport_list_lines); |
166 |
xfree(node->data); |
167 |
free_dlink_node(node); |
168 |
} |
169 |
|
170 |
DLINK_FOREACH(node, isupport_list.head) |
171 |
{ |
172 |
struct Isupport *support = node->data; |
173 |
|
174 |
p += (n = sprintf(p, "%s", support->name)); |
175 |
len += n; |
176 |
|
177 |
if (support->options) |
178 |
{ |
179 |
p += (n = sprintf(p, "=%s", support->options)); |
180 |
len += n; |
181 |
} |
182 |
|
183 |
if (support->number > 0) |
184 |
{ |
185 |
p += (n = sprintf(p, "=%d", support->number)); |
186 |
len += n; |
187 |
} |
188 |
|
189 |
*p++ = ' '; |
190 |
len++; |
191 |
*p = '\0'; |
192 |
|
193 |
if (++tokens == (MAXPARA-2) || len >= (sizeof(isupportbuffer)-reserve)) |
194 |
{ /* arbritrary for now */ |
195 |
if (*--p == ' ') |
196 |
*p = '\0'; |
197 |
|
198 |
dlinkAddTail(xstrdup(isupportbuffer), make_dlink_node(), &isupport_list_lines); |
199 |
p = isupportbuffer; |
200 |
len = 0; |
201 |
n = 0; |
202 |
tokens = 0; |
203 |
} |
204 |
} |
205 |
|
206 |
if (len) |
207 |
{ |
208 |
if (*--p == ' ') |
209 |
*p = '\0'; |
210 |
dlinkAddTail(xstrdup(isupportbuffer), make_dlink_node(), &isupport_list_lines); |
211 |
} |
212 |
} |
213 |
|
214 |
/* isupport_show() |
215 |
* |
216 |
* inputs - pointer to client |
217 |
* output - NONE |
218 |
* side effects - display to client what we support (for them) |
219 |
*/ |
220 |
void |
221 |
isupport_show(struct Client *source_p) |
222 |
{ |
223 |
const dlink_node *node = NULL; |
224 |
|
225 |
DLINK_FOREACH(node, isupport_list_lines.head) |
226 |
sendto_one_numeric(source_p, &me, RPL_ISUPPORT, node->data); |
227 |
} |