ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_join.c
Revision: 7355
Committed: Mon Feb 22 18:59:13 2016 UTC (10 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 12156 byte(s)
Log Message:
- Cleanup more conversion specifiers

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2820 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 7006 * Copyright (c) 1997-2016 ircd-hybrid development team
5 adx 30 *
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 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 adx 30 * USA
20     */
21    
22 michael 2820 /*! \file m_join.c
23     * \brief Includes required functions for processing the JOIN command.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28 michael 1011 #include "list.h"
29 adx 30 #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 michael 3347 #include "server.h"
38 michael 1309 #include "conf.h"
39 michael 7234 #include "conf_resv.h"
40 adx 30 #include "parse.h"
41     #include "modules.h"
42    
43    
44 michael 3660 static void set_final_mode(const struct Mode *, const struct Mode *);
45 adx 30 static void remove_our_modes(struct Channel *, struct Client *);
46 michael 3660 static void remove_a_mode(struct Channel *, struct Client *, int, const char);
47 adx 30
48     static char modebuf[MODEBUFLEN];
49     static char parabuf[MODEBUFLEN];
50     static char sendbuf[MODEBUFLEN];
51     static char *mbuf;
52    
53 michael 3342 /*! \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 adx 30 */
65 michael 2820 static int
66 michael 3156 m_join(struct Client *source_p, int parc, char *parv[])
67 adx 30 {
68 michael 632 if (EmptyString(parv[1]))
69 adx 30 {
70 michael 3109 sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "JOIN");
71 michael 2820 return 0;
72 adx 30 }
73    
74 michael 3937 channel_do_join(source_p, parv[1], parv[2]);
75 michael 2820 return 0;
76 adx 30 }
77    
78     /* ms_join()
79     *
80 michael 3096 * inputs - parv[0] = command
81 adx 30 * parv[1] = ts
82     * parv[2] = channel name
83 db 853 * parv[3] = modes (Deprecated)
84 adx 30 * output - none
85     * side effects - handles remote JOIN's sent by servers. In TSora
86 michael 2820 * remote clients are joined using SJOIN, hence a
87 adx 30 * 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 michael 2820 static int
92 michael 3156 ms_join(struct Client *source_p, int parc, char *parv[])
93 adx 30 {
94 michael 7330 uintmax_t newts = 0;
95     uintmax_t oldts = 0;
96 michael 632 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 adx 30
103 michael 3617 if (!IsClient(source_p))
104 michael 3637 return 0;
105 michael 3617
106 michael 3371 if (parc == 2 && !strcmp(parv[1], "0"))
107 adx 30 {
108 michael 3912 channel_do_join_0(source_p);
109 michael 2820 return 0;
110 adx 30 }
111    
112 michael 1474 if (parc < 4)
113 michael 2820 return 0;
114 adx 30
115 michael 6373 if (!channel_check_name(parv[2], 0))
116 michael 632 {
117 michael 1618 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
118 michael 3162 "*** Too long or invalid channel name from %s(via %s): %s",
119     source_p->name, source_p->from->name, parv[2]);
120 michael 2820 return 0;
121 michael 632 }
122 adx 30
123     mbuf = modebuf;
124     mode.mode = mode.limit = 0;
125     mode.key[0] = '\0';
126    
127 michael 632 if ((chptr = hash_find_channel(parv[2])) == NULL)
128     {
129     isnew = 1;
130 michael 6373 chptr = channel_make(parv[2]);
131 michael 632 }
132    
133 michael 7330 newts = strtoumax(parv[1], NULL, 10);
134 michael 4818 oldts = chptr->creationtime;
135 adx 30 oldmode = &chptr->mode;
136    
137 michael 4340 if (ConfigGeneral.ignore_bogus_ts)
138 adx 30 {
139     if (newts < 800000000)
140     {
141 michael 1618 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
142 michael 6782 "*** Bogus TS %ju on %s ignored from %s(via %s)",
143     newts, chptr->name,
144 michael 3169 source_p->name, source_p->from->name);
145 adx 30
146     newts = (oldts == 0) ? 0 : 800000000;
147     }
148     }
149     else
150     {
151     if (!newts && !isnew && oldts)
152     {
153 michael 6759 sendto_channel_local(NULL, chptr, 0, 0, 0,
154 michael 6782 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ju to 0",
155     me.name, chptr->name, chptr->name, oldts);
156 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
157 michael 6782 "Server %s changing TS on %s from %ju to 0",
158     source_p->name, chptr->name, oldts);
159 adx 30 }
160     }
161    
162     if (isnew)
163 michael 4818 chptr->creationtime = newts;
164 adx 30 else if (newts == 0 || oldts == 0)
165 michael 4818 chptr->creationtime = 0;
166 adx 30 else if (newts == oldts)
167     ;
168     else if (newts < oldts)
169     {
170 michael 894 keep_our_modes = 0;
171 michael 4818 chptr->creationtime = newts;
172 adx 30 }
173     else
174 michael 894 keep_new_modes = 0;
175 adx 30
176     if (!keep_new_modes)
177     mode = *oldmode;
178     else if (keep_our_modes)
179     {
180     mode.mode |= oldmode->mode;
181 michael 3660
182 adx 30 if (oldmode->limit > mode.limit)
183     mode.limit = oldmode->limit;
184     if (strcmp(mode.key, oldmode->key) < 0)
185 michael 3334 strlcpy(mode.key, oldmode->key, sizeof(mode.key));
186 adx 30 }
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 michael 873
196 michael 1203 if (chptr->topic[0])
197 michael 873 {
198 michael 3941 channel_set_topic(chptr, "", "", 0, 0);
199 michael 6759 sendto_channel_local(NULL, chptr, 0, 0, 0, ":%s TOPIC %s :",
200 michael 873 (IsHidden(source_p) ||
201     ConfigServerHide.hide_servers) ?
202 michael 4618 me.name : source_p->name, chptr->name);
203 michael 873 }
204    
205 michael 6759 sendto_channel_local(NULL, chptr, 0, 0, 0,
206 michael 6782 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ju to %ju",
207 michael 4618 me.name, chptr->name, chptr->name,
208 michael 6782 oldts, newts);
209 adx 30 }
210 michael 2820
211 michael 3660 if (*modebuf)
212 adx 30 {
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 michael 6759 sendto_channel_local(NULL, chptr, 0, 0, 0, ":%s MODE %s %s %s",
219 michael 4618 servername, chptr->name, modebuf, parabuf);
220 adx 30 }
221    
222     if (!IsMember(source_p, chptr))
223     {
224 michael 894 add_user_to_channel(chptr, source_p, 0, 1);
225 michael 3660
226 michael 6759 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 michael 6827 source_p->host, chptr->name, source_p->account, source_p->info);
229 michael 6759 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 michael 4792
233 michael 1734 if (source_p->away[0])
234 michael 6759 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 adx 30 }
239    
240 michael 6782 sendto_server(source_p, 0, 0, ":%s JOIN %ju %s +",
241     source_p->id, chptr->creationtime, chptr->name);
242 michael 2820 return 0;
243 adx 30 }
244    
245 michael 1175 /* set_final_mode
246 adx 30 *
247 michael 1175 * inputs - channel mode
248     * - old channel mode
249 adx 30 * output - NONE
250 michael 1175 * 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 adx 30 */
255     static void
256 michael 3660 set_final_mode(const struct Mode *mode, const struct Mode *oldmode)
257 adx 30 {
258     char *pbuf = parabuf;
259 michael 3660 int what = 0, len = 0;
260 adx 30
261 michael 3660 for (const struct mode_letter *tab = chan_modes; tab->letter; ++tab)
262 adx 30 {
263 michael 4884 if ((tab->mode & mode->mode) && !(tab->mode & oldmode->mode))
264 adx 30 {
265     if (what != 1)
266     {
267     *mbuf++ = '+';
268     what = 1;
269     }
270 michael 3660
271 michael 1175 *mbuf++ = tab->letter;
272 adx 30 }
273     }
274    
275 michael 3660 for (const struct mode_letter *tab = chan_modes; tab->letter; ++tab)
276 adx 30 {
277 michael 4884 if ((tab->mode & oldmode->mode) && !(tab->mode & mode->mode))
278 adx 30 {
279     if (what != -1)
280     {
281     *mbuf++ = '-';
282     what = -1;
283     }
284 michael 3660
285 michael 1175 *mbuf++ = tab->letter;
286 adx 30 }
287     }
288    
289 michael 3660 if (oldmode->limit && mode->limit == 0)
290 adx 30 {
291     if (what != -1)
292     {
293     *mbuf++ = '-';
294     what = -1;
295     }
296 michael 3660
297 adx 30 *mbuf++ = 'l';
298     }
299    
300 michael 4884 if (oldmode->key[0] && mode->key[0] == '\0')
301 adx 30 {
302     if (what != -1)
303     {
304     *mbuf++ = '-';
305     what = -1;
306     }
307 michael 3660
308 adx 30 *mbuf++ = 'k';
309 michael 1793 len = sprintf(pbuf, "%s ", oldmode->key);
310 adx 30 pbuf += len;
311     }
312    
313 michael 3660 if (mode->limit && oldmode->limit != mode->limit)
314 adx 30 {
315     if (what != 1)
316     {
317     *mbuf++ = '+';
318     what = 1;
319     }
320 michael 3660
321 adx 30 *mbuf++ = 'l';
322 michael 7355 len = sprintf(pbuf, "%u ", mode->limit);
323 adx 30 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 michael 3660
334 adx 30 *mbuf++ = 'k';
335 michael 1793 len = sprintf(pbuf, "%s ", mode->key);
336 adx 30 pbuf += len;
337     }
338 michael 3660
339 adx 30 *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 michael 3660 remove_a_mode(struct Channel *chptr, struct Client *source_p, int mask, const char flag)
366 adx 30 {
367 michael 4915 dlink_node *node = NULL;
368 adx 30 char lmodebuf[MODEBUFLEN];
369     const char *lpara[MAXMODEPARAMS];
370 michael 3660 int count = 0, lcount = 0;
371 adx 30
372     mbuf = lmodebuf;
373     *mbuf++ = '-';
374    
375 michael 3660 for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
376 adx 30 lpara[lcount] = "";
377 michael 3660
378 adx 30 sendbuf[0] = '\0';
379    
380 michael 4915 DLINK_FOREACH(node, chptr->members.head)
381 adx 30 {
382 michael 4915 struct Membership *member = node->data;
383 adx 30
384 michael 4815 if ((member->flags & mask) == 0)
385 adx 30 continue;
386    
387 michael 4815 member->flags &= ~mask;
388 adx 30
389 michael 4815 lpara[count++] = member->client_p->name;
390 adx 30
391     *mbuf++ = flag;
392    
393     if (count >= MAXMODEPARAMS)
394     {
395 michael 3660 for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
396 adx 30 {
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 michael 6759 sendto_channel_local(NULL, chptr, 0, 0, 0, ":%s MODE %s %s%s",
407 adx 30 (IsHidden(source_p) ||
408     ConfigServerHide.hide_servers) ?
409     me.name : source_p->name,
410 michael 4618 chptr->name, lmodebuf, sendbuf);
411 adx 30 mbuf = lmodebuf;
412     *mbuf++ = '-';
413     count = 0;
414     sendbuf[0] = '\0';
415     }
416     }
417    
418 michael 3342 if (count)
419 adx 30 {
420     *mbuf = '\0';
421 michael 3660
422     for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
423 adx 30 {
424     if (*lpara[lcount] == '\0')
425     break;
426    
427     strlcat(sendbuf, " ", sizeof(sendbuf));
428     strlcat(sendbuf, lpara[lcount], sizeof(sendbuf));
429     }
430 michael 3342
431 michael 6759 sendto_channel_local(NULL, chptr, 0, 0, 0, ":%s MODE %s %s%s",
432 adx 30 (IsHidden(source_p) || ConfigServerHide.hide_servers) ?
433 michael 4618 me.name : source_p->name, chptr->name, lmodebuf, sendbuf);
434 adx 30 }
435     }
436 michael 1230
437 michael 3331 static struct Message join_msgtab =
438     {
439 michael 5881 .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 michael 1230 };
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 michael 3331 struct module module_entry =
462     {
463 michael 1230 .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