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: 6374
Committed: Fri Aug 21 10:01:21 2015 UTC (8 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 12345 byte(s)
Log Message:
- Rename several functions in channel.c to comply with naming convention

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2015 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 "parse.h"
40 #include "modules.h"
41 #include "resv.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 time_t newts = 0;
95 time_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 = atol(parv[1]);
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 %lu on %s ignored from %s(via %s)",
143 (unsigned long)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(0, chptr,
154 ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to 0",
155 me.name, chptr->name, chptr->name, (unsigned long)oldts);
156 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
157 "Server %s changing TS on %s from %lu to 0",
158 source_p->name, chptr->name, (unsigned long)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(0, chptr, ":%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(0, chptr,
206 ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to %lu",
207 me.name, chptr->name, chptr->name,
208 (unsigned long)oldts, (unsigned long)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(0, chptr, ":%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_butone(NULL, CAP_EXTENDED_JOIN, 0, chptr, ":%s!%s@%s JOIN %s %s :%s",
227 source_p->name, source_p->username,
228 source_p->host, chptr->name,
229 (!IsDigit(source_p->account[0]) && source_p->account[0] != '*') ? source_p->account : "*",
230 source_p->info);
231 sendto_channel_local_butone(NULL, 0, CAP_EXTENDED_JOIN, chptr, ":%s!%s@%s JOIN :%s",
232 source_p->name, source_p->username,
233 source_p->host, chptr->name);
234
235 if (source_p->away[0])
236 sendto_channel_local_butone(source_p, CAP_AWAY_NOTIFY, 0, chptr,
237 ":%s!%s@%s AWAY :%s",
238 source_p->name, source_p->username,
239 source_p->host, source_p->away);
240 }
241
242 sendto_server(source_p, 0, 0, ":%s JOIN %lu %s +",
243 source_p->id, (unsigned long)chptr->creationtime, chptr->name);
244 return 0;
245 }
246
247 /* set_final_mode
248 *
249 * inputs - channel mode
250 * - old channel mode
251 * output - NONE
252 * side effects - walk through all the channel modes turning off modes
253 * that were on in oldmode but aren't on in mode.
254 * Then walk through turning on modes that are on in mode
255 * but were not set in oldmode.
256 */
257 static void
258 set_final_mode(const struct Mode *mode, const struct Mode *oldmode)
259 {
260 char *pbuf = parabuf;
261 int what = 0, len = 0;
262
263 for (const struct mode_letter *tab = chan_modes; tab->letter; ++tab)
264 {
265 if ((tab->mode & mode->mode) && !(tab->mode & oldmode->mode))
266 {
267 if (what != 1)
268 {
269 *mbuf++ = '+';
270 what = 1;
271 }
272
273 *mbuf++ = tab->letter;
274 }
275 }
276
277 for (const struct mode_letter *tab = chan_modes; tab->letter; ++tab)
278 {
279 if ((tab->mode & oldmode->mode) && !(tab->mode & mode->mode))
280 {
281 if (what != -1)
282 {
283 *mbuf++ = '-';
284 what = -1;
285 }
286
287 *mbuf++ = tab->letter;
288 }
289 }
290
291 if (oldmode->limit && mode->limit == 0)
292 {
293 if (what != -1)
294 {
295 *mbuf++ = '-';
296 what = -1;
297 }
298
299 *mbuf++ = 'l';
300 }
301
302 if (oldmode->key[0] && mode->key[0] == '\0')
303 {
304 if (what != -1)
305 {
306 *mbuf++ = '-';
307 what = -1;
308 }
309
310 *mbuf++ = 'k';
311 len = sprintf(pbuf, "%s ", oldmode->key);
312 pbuf += len;
313 }
314
315 if (mode->limit && oldmode->limit != mode->limit)
316 {
317 if (what != 1)
318 {
319 *mbuf++ = '+';
320 what = 1;
321 }
322
323 *mbuf++ = 'l';
324 len = sprintf(pbuf, "%d ", mode->limit);
325 pbuf += len;
326 }
327
328 if (mode->key[0] && strcmp(oldmode->key, mode->key))
329 {
330 if (what != 1)
331 {
332 *mbuf++ = '+';
333 what = 1;
334 }
335
336 *mbuf++ = 'k';
337 len = sprintf(pbuf, "%s ", mode->key);
338 pbuf += len;
339 }
340
341 *mbuf = '\0';
342 }
343
344 /* remove_our_modes()
345 *
346 * inputs - pointer to channel to remove modes from
347 * - client pointer
348 * output - NONE
349 * side effects - Go through the local members, remove all their
350 * chanop modes etc., this side lost the TS.
351 */
352 static void
353 remove_our_modes(struct Channel *chptr, struct Client *source_p)
354 {
355 remove_a_mode(chptr, source_p, CHFL_CHANOP, 'o');
356 remove_a_mode(chptr, source_p, CHFL_HALFOP, 'h');
357 remove_a_mode(chptr, source_p, CHFL_VOICE, 'v');
358 }
359
360 /* remove_a_mode()
361 *
362 * inputs -
363 * output - NONE
364 * side effects - remove ONE mode from a channel
365 */
366 static void
367 remove_a_mode(struct Channel *chptr, struct Client *source_p, int mask, const char flag)
368 {
369 dlink_node *node = NULL;
370 char lmodebuf[MODEBUFLEN];
371 const char *lpara[MAXMODEPARAMS];
372 int count = 0, lcount = 0;
373
374 mbuf = lmodebuf;
375 *mbuf++ = '-';
376
377 for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
378 lpara[lcount] = "";
379
380 sendbuf[0] = '\0';
381
382 DLINK_FOREACH(node, chptr->members.head)
383 {
384 struct Membership *member = node->data;
385
386 if ((member->flags & mask) == 0)
387 continue;
388
389 member->flags &= ~mask;
390
391 lpara[count++] = member->client_p->name;
392
393 *mbuf++ = flag;
394
395 if (count >= MAXMODEPARAMS)
396 {
397 for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
398 {
399 if (*lpara[lcount] == '\0')
400 break;
401
402 strlcat(sendbuf, " ", sizeof(sendbuf));
403 strlcat(sendbuf, lpara[lcount], sizeof(sendbuf));
404 lpara[lcount] = "";
405 }
406
407 *mbuf = '\0';
408 sendto_channel_local(0, chptr, ":%s MODE %s %s%s",
409 (IsHidden(source_p) ||
410 ConfigServerHide.hide_servers) ?
411 me.name : source_p->name,
412 chptr->name, lmodebuf, sendbuf);
413 mbuf = lmodebuf;
414 *mbuf++ = '-';
415 count = 0;
416 sendbuf[0] = '\0';
417 }
418 }
419
420 if (count)
421 {
422 *mbuf = '\0';
423
424 for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
425 {
426 if (*lpara[lcount] == '\0')
427 break;
428
429 strlcat(sendbuf, " ", sizeof(sendbuf));
430 strlcat(sendbuf, lpara[lcount], sizeof(sendbuf));
431 }
432
433 sendto_channel_local(0, chptr, ":%s MODE %s %s%s",
434 (IsHidden(source_p) || ConfigServerHide.hide_servers) ?
435 me.name : source_p->name, chptr->name, lmodebuf, sendbuf);
436 }
437 }
438
439 static struct Message join_msgtab =
440 {
441 .cmd = "JOIN",
442 .args_min = 2,
443 .args_max = MAXPARA,
444 .handlers[UNREGISTERED_HANDLER] = m_unregistered,
445 .handlers[CLIENT_HANDLER] = m_join,
446 .handlers[SERVER_HANDLER] = ms_join,
447 .handlers[ENCAP_HANDLER] = m_ignore,
448 .handlers[OPER_HANDLER] = m_join
449 };
450
451 static void
452 module_init(void)
453 {
454 mod_add_cmd(&join_msgtab);
455 }
456
457 static void
458 module_exit(void)
459 {
460 mod_del_cmd(&join_msgtab);
461 }
462
463 struct module module_entry =
464 {
465 .version = "$Revision$",
466 .modinit = module_init,
467 .modexit = module_exit,
468 .flags = MODULE_FLAG_CORE
469 };

Properties

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