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: 3940
Committed: Tue Jun 10 19:27:34 2014 UTC (9 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 11914 byte(s)
Log Message:
- Renamed set_channel_topic() to channel_set_topic()

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 2820 * Copyright (c) 1997-2014 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     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19     * 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 adx 30 #include "parse.h"
40     #include "modules.h"
41 michael 1825 #include "resv.h"
42 adx 30
43    
44 michael 3661 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 3661 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 3936 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 632 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 adx 30
103 michael 3618 if (!IsClient(source_p))
104 michael 3636 return 0;
105 michael 3618
106 michael 3371 if (parc == 2 && !strcmp(parv[1], "0"))
107 adx 30 {
108 michael 3913 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 632 if (!check_channel_name(parv[2], 0))
116     {
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     chptr = make_channel(parv[2]);
131     }
132    
133     newts = atol(parv[1]);
134 adx 30 oldts = chptr->channelts;
135     oldmode = &chptr->mode;
136    
137     if (ConfigFileEntry.ignore_bogus_ts)
138     {
139     if (newts < 800000000)
140     {
141 michael 1618 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
142 michael 3169 "*** Bogus TS %lu on %s ignored from %s(via %s)",
143 adx 30 (unsigned long)newts, chptr->chname,
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 894 sendto_channel_local(ALL_MEMBERS, 0, chptr,
154 michael 873 ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to 0",
155     me.name, chptr->chname, chptr->chname, (unsigned long)oldts);
156 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
157 adx 30 "Server %s changing TS on %s from %lu to 0",
158     source_p->name, chptr->chname, (unsigned long)oldts);
159     }
160     }
161    
162     if (isnew)
163     chptr->channelts = newts;
164     else if (newts == 0 || oldts == 0)
165     chptr->channelts = 0;
166     else if (newts == oldts)
167     ;
168     else if (newts < oldts)
169     {
170 michael 894 keep_our_modes = 0;
171 adx 30 chptr->channelts = newts;
172     }
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 3661
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 3940 channel_set_topic(chptr, "", "", 0, 0);
199 michael 896 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s TOPIC %s :",
200 michael 873 (IsHidden(source_p) ||
201     ConfigServerHide.hide_servers) ?
202     me.name : source_p->name, chptr->chname);
203     }
204    
205 michael 894 sendto_channel_local(ALL_MEMBERS, 0, chptr,
206 adx 30 ":%s NOTICE %s :*** Notice -- TS for %s changed from %lu to %lu",
207     me.name, chptr->chname, chptr->chname,
208     (unsigned long)oldts, (unsigned long)newts);
209     }
210 michael 2820
211 michael 3661 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 896 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s %s",
219 adx 30 servername, chptr->chname, modebuf, parabuf);
220     }
221    
222     if (!IsMember(source_p, chptr))
223     {
224 michael 894 add_user_to_channel(chptr, source_p, 0, 1);
225     sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s JOIN :%s",
226 adx 30 source_p->name, source_p->username,
227     source_p->host, chptr->chname);
228 michael 3661
229 michael 1734 if (source_p->away[0])
230     sendto_channel_local_butone(source_p, 0, CAP_AWAY_NOTIFY, chptr,
231     ":%s!%s@%s AWAY :%s",
232     source_p->name, source_p->username,
233     source_p->host, source_p->away);
234 adx 30 }
235    
236 michael 3169 sendto_server(source_p, NOCAPS, NOCAPS, ":%s JOIN %lu %s +",
237 michael 3186 source_p->id, (unsigned long)chptr->channelts, chptr->chname);
238 michael 2820 return 0;
239 adx 30 }
240    
241 michael 1175 /* set_final_mode
242 adx 30 *
243 michael 1175 * inputs - channel mode
244     * - old channel mode
245 adx 30 * output - NONE
246 michael 1175 * side effects - walk through all the channel modes turning off modes
247     * that were on in oldmode but aren't on in mode.
248     * Then walk through turning on modes that are on in mode
249     * but were not set in oldmode.
250 adx 30 */
251     static void
252 michael 3661 set_final_mode(const struct Mode *mode, const struct Mode *oldmode)
253 adx 30 {
254     char *pbuf = parabuf;
255 michael 3661 int what = 0, len = 0;
256 adx 30
257 michael 3661 for (const struct mode_letter *tab = chan_modes; tab->letter; ++tab)
258 adx 30 {
259 michael 1175 if ((tab->mode & mode->mode) &&
260     !(tab->mode & oldmode->mode))
261 adx 30 {
262     if (what != 1)
263     {
264     *mbuf++ = '+';
265     what = 1;
266     }
267 michael 3661
268 michael 1175 *mbuf++ = tab->letter;
269 adx 30 }
270     }
271    
272 michael 3661 for (const struct mode_letter *tab = chan_modes; tab->letter; ++tab)
273 adx 30 {
274 michael 1175 if ((tab->mode & oldmode->mode) &&
275     !(tab->mode & mode->mode))
276 adx 30 {
277     if (what != -1)
278     {
279     *mbuf++ = '-';
280     what = -1;
281     }
282 michael 3661
283 michael 1175 *mbuf++ = tab->letter;
284 adx 30 }
285     }
286    
287 michael 3661 if (oldmode->limit && mode->limit == 0)
288 adx 30 {
289     if (what != -1)
290     {
291     *mbuf++ = '-';
292     what = -1;
293     }
294 michael 3661
295 adx 30 *mbuf++ = 'l';
296     }
297    
298     if (oldmode->key[0] && !mode->key[0])
299     {
300     if (what != -1)
301     {
302     *mbuf++ = '-';
303     what = -1;
304     }
305 michael 3661
306 adx 30 *mbuf++ = 'k';
307 michael 1793 len = sprintf(pbuf, "%s ", oldmode->key);
308 adx 30 pbuf += len;
309     }
310    
311 michael 3661 if (mode->limit && oldmode->limit != mode->limit)
312 adx 30 {
313     if (what != 1)
314     {
315     *mbuf++ = '+';
316     what = 1;
317     }
318 michael 3661
319 adx 30 *mbuf++ = 'l';
320 michael 1793 len = sprintf(pbuf, "%d ", mode->limit);
321 adx 30 pbuf += len;
322     }
323    
324     if (mode->key[0] && strcmp(oldmode->key, mode->key))
325     {
326     if (what != 1)
327     {
328     *mbuf++ = '+';
329     what = 1;
330     }
331 michael 3661
332 adx 30 *mbuf++ = 'k';
333 michael 1793 len = sprintf(pbuf, "%s ", mode->key);
334 adx 30 pbuf += len;
335     }
336 michael 3661
337 adx 30 *mbuf = '\0';
338     }
339    
340     /* remove_our_modes()
341     *
342     * inputs - pointer to channel to remove modes from
343     * - client pointer
344     * output - NONE
345     * side effects - Go through the local members, remove all their
346     * chanop modes etc., this side lost the TS.
347     */
348     static void
349     remove_our_modes(struct Channel *chptr, struct Client *source_p)
350     {
351     remove_a_mode(chptr, source_p, CHFL_CHANOP, 'o');
352     remove_a_mode(chptr, source_p, CHFL_HALFOP, 'h');
353     remove_a_mode(chptr, source_p, CHFL_VOICE, 'v');
354     }
355    
356     /* remove_a_mode()
357     *
358     * inputs -
359     * output - NONE
360     * side effects - remove ONE mode from a channel
361     */
362     static void
363 michael 3661 remove_a_mode(struct Channel *chptr, struct Client *source_p, int mask, const char flag)
364 adx 30 {
365 michael 3661 dlink_node *ptr = NULL;
366 adx 30 char lmodebuf[MODEBUFLEN];
367     const char *lpara[MAXMODEPARAMS];
368 michael 3661 int count = 0, lcount = 0;
369 adx 30
370     mbuf = lmodebuf;
371     *mbuf++ = '-';
372    
373 michael 3661 for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
374 adx 30 lpara[lcount] = "";
375 michael 3661
376 adx 30 sendbuf[0] = '\0';
377    
378     DLINK_FOREACH(ptr, chptr->members.head)
379     {
380 michael 3661 struct Membership *ms = ptr->data;
381 adx 30
382     if ((ms->flags & mask) == 0)
383     continue;
384    
385     ms->flags &= ~mask;
386    
387     lpara[count++] = ms->client_p->name;
388    
389     *mbuf++ = flag;
390    
391     if (count >= MAXMODEPARAMS)
392     {
393 michael 3661 for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
394 adx 30 {
395     if (*lpara[lcount] == '\0')
396     break;
397    
398     strlcat(sendbuf, " ", sizeof(sendbuf));
399     strlcat(sendbuf, lpara[lcount], sizeof(sendbuf));
400     lpara[lcount] = "";
401     }
402    
403     *mbuf = '\0';
404 michael 3661 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
405 adx 30 (IsHidden(source_p) ||
406     ConfigServerHide.hide_servers) ?
407     me.name : source_p->name,
408     chptr->chname, lmodebuf, sendbuf);
409     mbuf = lmodebuf;
410     *mbuf++ = '-';
411     count = 0;
412     sendbuf[0] = '\0';
413     }
414     }
415    
416 michael 3342 if (count)
417 adx 30 {
418     *mbuf = '\0';
419 michael 3661
420     for (lcount = 0; lcount < MAXMODEPARAMS; ++lcount)
421 adx 30 {
422     if (*lpara[lcount] == '\0')
423     break;
424    
425     strlcat(sendbuf, " ", sizeof(sendbuf));
426     strlcat(sendbuf, lpara[lcount], sizeof(sendbuf));
427     }
428 michael 3342
429 michael 3661 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s %s%s",
430 adx 30 (IsHidden(source_p) || ConfigServerHide.hide_servers) ?
431 michael 3661 me.name : source_p->name, chptr->chname, lmodebuf, sendbuf);
432 adx 30 }
433     }
434 michael 1230
435 michael 3331 static struct Message join_msgtab =
436     {
437 michael 1230 "JOIN", 0, 0, 2, MAXPARA, MFLG_SLOW, 0,
438     { m_unregistered, m_join, ms_join, m_ignore, m_join, m_ignore }
439     };
440    
441     static void
442     module_init(void)
443     {
444     mod_add_cmd(&join_msgtab);
445     }
446    
447     static void
448     module_exit(void)
449     {
450     mod_del_cmd(&join_msgtab);
451     }
452    
453 michael 3331 struct module module_entry =
454     {
455 michael 1230 .node = { NULL, NULL, NULL },
456     .name = NULL,
457     .version = "$Revision$",
458     .handle = NULL,
459     .modinit = module_init,
460     .modexit = module_exit,
461     .flags = MODULE_FLAG_CORE
462     };

Properties

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