ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/core/m_join.c
Revision: 8090
Committed: Wed Mar 29 12:49:28 2017 UTC (7 years ago) by michael
Content type: text/x-csrc
File size: 12176 byte(s)
Log Message:
- Get rid of chm_registered() and chm_simple_oper()

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2017 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 m_join.c
23 * \brief Includes required functions for processing the JOIN command.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #include "list.h"
29 #include "channel.h"
30 #include "channel_mode.h"
31 #include "client.h"
32 #include "hash.h"
33 #include "irc_string.h"
34 #include "ircd.h"
35 #include "numeric.h"
36 #include "send.h"
37 #include "server.h"
38 #include "conf.h"
39 #include "conf_resv.h"
40 #include "parse.h"
41 #include "modules.h"
42
43
44 static void set_final_mode(const struct Mode *, const struct Mode *);
45 static void remove_our_modes(struct Channel *, struct Client *);
46 static void remove_a_mode(struct Channel *, struct Client *, int, const char);
47
48 static char modebuf[MODEBUFLEN];
49 static char parabuf[MODEBUFLEN];
50 static char sendbuf[MODEBUFLEN];
51 static char *mbuf;
52
53 /*! \brief JOIN command handler
54 *
55 * \param source_p Pointer to allocated Client struct from which the message
56 * originally comes from. This can be a local or remote client.
57 * \param parc Integer holding the number of supplied arguments.
58 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
59 * pointers.
60 * \note Valid arguments for this command are:
61 * - parv[0] = command
62 * - parv[1] = channel
63 * - parv[2] = channel password (key)
64 */
65 static int
66 m_join(struct Client *source_p, int parc, char *parv[])
67 {
68 if (EmptyString(parv[1]))
69 {
70 sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "JOIN");
71 return 0;
72 }
73
74 channel_do_join(source_p, parv[1], parv[2]);
75 return 0;
76 }
77
78 /* ms_join()
79 *
80 * inputs - parv[0] = command
81 * parv[1] = ts
82 * parv[2] = channel name
83 * parv[3] = modes (Deprecated)
84 * output - none
85 * side effects - handles remote JOIN's sent by servers. In TSora
86 * remote clients are joined using SJOIN, hence a
87 * JOIN sent by a server on behalf of a client is an error.
88 * here, the initial code is in to take an extra parameter
89 * and use it for the TimeStamp on a new channel.
90 */
91 static int
92 ms_join(struct Client *source_p, int parc, char *parv[])
93 {
94 uintmax_t newts = 0;
95 uintmax_t oldts = 0;
96 int keep_our_modes = 1;
97 int keep_new_modes = 1;
98 int isnew = 0;
99 const char *servername = NULL;
100 struct Channel *chptr = NULL;
101 struct Mode mode, *oldmode;
102
103 if (!IsClient(source_p))
104 return 0;
105
106 if (parc == 2 && !strcmp(parv[1], "0"))
107 {
108 channel_do_join_0(source_p);
109 return 0;
110 }
111
112 if (parc < 4)
113 return 0;
114
115 if (!channel_check_name(parv[2], 0))
116 {
117 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
118 "*** Too long or invalid channel name from %s(via %s): %s",
119 source_p->name, source_p->from->name, parv[2]);
120 return 0;
121 }
122
123 mbuf = modebuf;
124 mode.mode = mode.limit = 0;
125 mode.key[0] = '\0';
126
127 if ((chptr = hash_find_channel(parv[2])) == NULL)
128 {
129 isnew = 1;
130 chptr = channel_make(parv[2]);
131 }
132
133 newts = strtoumax(parv[1], NULL, 10);
134 oldts = chptr->creationtime;
135 oldmode = &chptr->mode;
136
137 if (ConfigGeneral.ignore_bogus_ts)
138 {
139 if (newts < 800000000)
140 {
141 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
142 "*** Bogus TS %ju on %s ignored from %s(via %s)",
143 newts, chptr->name,
144 source_p->name, source_p->from->name);
145
146 newts = (oldts == 0) ? 0 : 800000000;
147 }
148 }
149 else
150 {
151 if (!newts && !isnew && oldts)
152 {
153 sendto_channel_local(NULL, chptr, 0, 0, 0,
154 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ju to 0",
155 me.name, chptr->name, chptr->name, oldts);
156 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
157 "Server %s changing TS on %s from %ju to 0",
158 source_p->name, chptr->name, oldts);
159 }
160 }
161
162 if (isnew)
163 chptr->creationtime = newts;
164 else if (newts == 0 || oldts == 0)
165 chptr->creationtime = 0;
166 else if (newts == oldts)
167 ;
168 else if (newts < oldts)
169 {
170 keep_our_modes = 0;
171 chptr->creationtime = newts;
172 }
173 else
174 keep_new_modes = 0;
175
176 if (!keep_new_modes)
177 mode = *oldmode;
178 else if (keep_our_modes)
179 {
180 mode.mode |= oldmode->mode;
181
182 if (oldmode->limit > mode.limit)
183 mode.limit = oldmode->limit;
184 if (strcmp(mode.key, oldmode->key) < 0)
185 strlcpy(mode.key, oldmode->key, sizeof(mode.key));
186 }
187
188 set_final_mode(&mode, oldmode);
189 chptr->mode = mode;
190
191 /* Lost the TS, other side wins, so remove modes on this side */
192 if (!keep_our_modes)
193 {
194 remove_our_modes(chptr, source_p);
195
196 if (chptr->topic[0])
197 {
198 channel_set_topic(chptr, "", "", 0, 0);
199 sendto_channel_local(NULL, chptr, 0, 0, 0, ":%s TOPIC %s :",
200 (IsHidden(source_p) ||
201 ConfigServerHide.hide_servers) ?
202 me.name : source_p->name, chptr->name);
203 }
204
205 sendto_channel_local(NULL, chptr, 0, 0, 0,
206 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ju to %ju",
207 me.name, chptr->name, chptr->name,
208 oldts, newts);
209 }
210
211 if (*modebuf)
212 {
213 servername = (ConfigServerHide.hide_servers || IsHidden(source_p)) ?
214 me.name : source_p->name;
215
216 /* This _SHOULD_ be to ALL_MEMBERS
217 * It contains only +imnpstlk, etc */
218 sendto_channel_local(NULL, chptr, 0, 0, 0, ":%s MODE %s %s %s",
219 servername, chptr->name, modebuf, parabuf);
220 }
221
222 if (!IsMember(source_p, chptr))
223 {
224 add_user_to_channel(chptr, source_p, 0, 1);
225
226 sendto_channel_local(NULL, chptr, 0, CAP_EXTENDED_JOIN, 0, ":%s!%s@%s JOIN %s %s :%s",
227 source_p->name, source_p->username,
228 source_p->host, chptr->name, source_p->account, source_p->info);
229 sendto_channel_local(NULL, chptr, 0, 0, CAP_EXTENDED_JOIN, ":%s!%s@%s JOIN :%s",
230 source_p->name, source_p->username,
231 source_p->host, chptr->name);
232
233 if (source_p->away[0])
234 sendto_channel_local(source_p, chptr, 0, CAP_AWAY_NOTIFY, 0,
235 ":%s!%s@%s AWAY :%s",
236 source_p->name, source_p->username,
237 source_p->host, source_p->away);
238 }
239
240 sendto_server(source_p, 0, 0, ":%s JOIN %ju %s +",
241 source_p->id, chptr->creationtime, chptr->name);
242 return 0;
243 }
244
245 /* set_final_mode
246 *
247 * inputs - channel mode
248 * - old channel mode
249 * output - NONE
250 * side effects - walk through all the channel modes turning off modes
251 * that were on in oldmode but aren't on in mode.
252 * Then walk through turning on modes that are on in mode
253 * but were not set in oldmode.
254 */
255 static void
256 set_final_mode(const struct Mode *mode, const struct Mode *oldmode)
257 {
258 char *pbuf = parabuf;
259 int what = 0, len = 0;
260
261 for (const struct chan_mode *tab = cmode_tab; tab->letter; ++tab)
262 {
263 if (tab->mode && (tab->mode & mode->mode) && !(tab->mode & oldmode->mode))
264 {
265 if (what != 1)
266 {
267 *mbuf++ = '+';
268 what = 1;
269 }
270
271 *mbuf++ = tab->letter;
272 }
273 }
274
275 for (const struct chan_mode *tab = cmode_tab; tab->letter; ++tab)
276 {
277 if (tab->mode && (tab->mode & oldmode->mode) && !(tab->mode & mode->mode))
278 {
279 if (what != -1)
280 {
281 *mbuf++ = '-';
282 what = -1;
283 }
284
285 *mbuf++ = tab->letter;
286 }
287 }
288
289 if (oldmode->limit && mode->limit == 0)
290 {
291 if (what != -1)
292 {
293 *mbuf++ = '-';
294 what = -1;
295 }
296
297 *mbuf++ = 'l';
298 }
299
300 if (oldmode->key[0] && mode->key[0] == '\0')
301 {
302 if (what != -1)
303 {
304 *mbuf++ = '-';
305 what = -1;
306 }
307
308 *mbuf++ = 'k';
309 len = sprintf(pbuf, "%s ", oldmode->key);
310 pbuf += len;
311 }
312
313 if (mode->limit && oldmode->limit != mode->limit)
314 {
315 if (what != 1)
316 {
317 *mbuf++ = '+';
318 what = 1;
319 }
320
321 *mbuf++ = 'l';
322 len = sprintf(pbuf, "%u ", mode->limit);
323 pbuf += len;
324 }
325
326 if (mode->key[0] && strcmp(oldmode->key, mode->key))
327 {
328 if (what != 1)
329 {
330 *mbuf++ = '+';
331 what = 1;
332 }
333
334 *mbuf++ = 'k';
335 len = sprintf(pbuf, "%s ", mode->key);
336 pbuf += len;
337 }
338
339 *mbuf = '\0';
340 }
341
342 /* remove_our_modes()
343 *
344 * inputs - pointer to channel to remove modes from
345 * - client pointer
346 * output - NONE
347 * side effects - Go through the local members, remove all their
348 * chanop modes etc., this side lost the TS.
349 */
350 static void
351 remove_our_modes(struct Channel *chptr, struct Client *source_p)
352 {
353 remove_a_mode(chptr, source_p, CHFL_CHANOP, 'o');
354 remove_a_mode(chptr, source_p, CHFL_HALFOP, 'h');
355 remove_a_mode(chptr, source_p, CHFL_VOICE, 'v');
356 }
357
358 /* remove_a_mode()
359 *
360 * inputs -
361 * output - NONE
362 * side effects - remove ONE mode from a channel
363 */
364 static void
365 remove_a_mode(struct Channel *chptr, struct Client *source_p, int mask, const char flag)
366 {
367 dlink_node *node = NULL;
368 char lmodebuf[MODEBUFLEN];
369 const char *lpara[MAXMODEPARAMS];
370 int count = 0, lcount = 0;
371
372 mbuf = lmodebuf;
373 *mbuf++ = '-';
374
375 for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
376 lpara[lcount] = "";
377
378 sendbuf[0] = '\0';
379
380 DLINK_FOREACH(node, chptr->members.head)
381 {
382 struct Membership *member = node->data;
383
384 if ((member->flags & mask) == 0)
385 continue;
386
387 member->flags &= ~mask;
388
389 lpara[count++] = member->client_p->name;
390
391 *mbuf++ = flag;
392
393 if (count >= MAXMODEPARAMS)
394 {
395 for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
396 {
397 if (*lpara[lcount] == '\0')
398 break;
399
400 strlcat(sendbuf, " ", sizeof(sendbuf));
401 strlcat(sendbuf, lpara[lcount], sizeof(sendbuf));
402 lpara[lcount] = "";
403 }
404
405 *mbuf = '\0';
406 sendto_channel_local(NULL, chptr, 0, 0, 0, ":%s MODE %s %s%s",
407 (IsHidden(source_p) ||
408 ConfigServerHide.hide_servers) ?
409 me.name : source_p->name,
410 chptr->name, lmodebuf, sendbuf);
411 mbuf = lmodebuf;
412 *mbuf++ = '-';
413 count = 0;
414 sendbuf[0] = '\0';
415 }
416 }
417
418 if (count)
419 {
420 *mbuf = '\0';
421
422 for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
423 {
424 if (*lpara[lcount] == '\0')
425 break;
426
427 strlcat(sendbuf, " ", sizeof(sendbuf));
428 strlcat(sendbuf, lpara[lcount], sizeof(sendbuf));
429 }
430
431 sendto_channel_local(NULL, chptr, 0, 0, 0, ":%s MODE %s %s%s",
432 (IsHidden(source_p) || ConfigServerHide.hide_servers) ?
433 me.name : source_p->name, chptr->name, lmodebuf, sendbuf);
434 }
435 }
436
437 static struct Message join_msgtab =
438 {
439 .cmd = "JOIN",
440 .args_min = 2,
441 .args_max = MAXPARA,
442 .handlers[UNREGISTERED_HANDLER] = m_unregistered,
443 .handlers[CLIENT_HANDLER] = m_join,
444 .handlers[SERVER_HANDLER] = ms_join,
445 .handlers[ENCAP_HANDLER] = m_ignore,
446 .handlers[OPER_HANDLER] = m_join
447 };
448
449 static void
450 module_init(void)
451 {
452 mod_add_cmd(&join_msgtab);
453 }
454
455 static void
456 module_exit(void)
457 {
458 mod_del_cmd(&join_msgtab);
459 }
460
461 struct module module_entry =
462 {
463 .version = "$Revision$",
464 .modinit = module_init,
465 .modexit = module_exit,
466 .flags = MODULE_FLAG_CORE
467 };

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision