/[svn]/ircd-hybrid/branches/8.2.x/modules/core/m_join.c
ViewVC logotype

Contents of /ircd-hybrid/branches/8.2.x/modules/core/m_join.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10026 - (show annotations)
Fri Jan 14 15:11:00 2022 UTC (16 months, 2 weeks ago) by michael
File MIME type: text/x-chdr
File size: 8868 byte(s)
- channel.c:channel_demote_members(): rewrite to remove all member flags in a single run. Also members having multiple flags set are now stuffed into the same MODE message (as long as pargs <= MAXMODEPARAMS)

1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 1997-2022 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
42
43 /* set_final_mode
44 *
45 * inputs - channel mode
46 * - old channel mode
47 * output - NONE
48 * side effects - walk through all the channel modes turning off modes
49 * that were on in oldmode but aren't on in mode.
50 * Then walk through turning on modes that are on in mode
51 * but were not set in oldmode.
52 */
53 static void
54 set_final_mode(const struct Mode *mode, const struct Mode *oldmode, char *mbuf, char *pbuf)
55 {
56 int what = MODE_QUERY;
57
58 for (const struct chan_mode *tab = cmode_tab; tab->letter; ++tab)
59 {
60 if (tab->mode && (tab->mode & mode->mode) && !(tab->mode & oldmode->mode))
61 {
62 if (what != MODE_ADD)
63 {
64 *mbuf++ = '+';
65 what = MODE_ADD;
66 }
67
68 *mbuf++ = tab->letter;
69 }
70 }
71
72 for (const struct chan_mode *tab = cmode_tab; tab->letter; ++tab)
73 {
74 if (tab->mode && (tab->mode & oldmode->mode) && !(tab->mode & mode->mode))
75 {
76 if (what != MODE_DEL)
77 {
78 *mbuf++ = '-';
79 what = MODE_DEL;
80 }
81
82 *mbuf++ = tab->letter;
83 }
84 }
85
86 if (oldmode->limit && mode->limit == 0)
87 {
88 if (what != MODE_DEL)
89 {
90 *mbuf++ = '-';
91 what = MODE_DEL;
92 }
93
94 *mbuf++ = 'l';
95 }
96
97 if (oldmode->key[0] && mode->key[0] == '\0')
98 {
99 if (what != MODE_DEL)
100 {
101 *mbuf++ = '-';
102 what = MODE_DEL;
103 }
104
105 *mbuf++ = 'k';
106 pbuf += sprintf(pbuf, "%s ", oldmode->key);
107 }
108
109 if (mode->limit && oldmode->limit != mode->limit)
110 {
111 if (what != MODE_ADD)
112 {
113 *mbuf++ = '+';
114 what = MODE_ADD;
115 }
116
117 *mbuf++ = 'l';
118 pbuf += sprintf(pbuf, "%u ", mode->limit);
119 }
120
121 if (mode->key[0] && strcmp(oldmode->key, mode->key))
122 {
123 if (what != MODE_ADD)
124 {
125 *mbuf++ = '+';
126 what = MODE_ADD;
127 }
128
129 *mbuf++ = 'k';
130 pbuf += sprintf(pbuf, "%s ", mode->key);
131 }
132
133 *mbuf = '\0';
134 }
135
136 /*! \brief JOIN command handler
137 *
138 * \param source_p Pointer to allocated Client struct from which the message
139 * originally comes from. This can be a local or remote client.
140 * \param parc Integer holding the number of supplied arguments.
141 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
142 * pointers.
143 * \note Valid arguments for this command are:
144 * - parv[0] = command
145 * - parv[1] = channel
146 * - parv[2] = channel password (key)
147 */
148 static void
149 m_join(struct Client *source_p, int parc, char *parv[])
150 {
151 channel_do_join(source_p, parv[1], parv[2]);
152 }
153
154 /* ms_join()
155 *
156 * inputs - parv[0] = command
157 * parv[1] = ts
158 * parv[2] = channel name
159 * parv[3] = modes (Deprecated)
160 * output - none
161 * side effects - handles remote JOIN's sent by servers. In TSora
162 * remote clients are joined using SJOIN, hence a
163 * JOIN sent by a server on behalf of a client is an error.
164 * here, the initial code is in to take an extra parameter
165 * and use it for the TimeStamp on a new channel.
166 */
167 static void
168 ms_join(struct Client *source_p, int parc, char *parv[])
169 {
170 bool keep_our_modes = true;
171 bool keep_new_modes = true;
172 bool isnew = false;
173 struct Mode mode = { .mode = 0, .limit = 0, .key[0] = '\0' };
174 char modebuf[MODEBUFLEN];
175 char parabuf[MODEBUFLEN];
176
177 if (!IsClient(source_p))
178 return;
179
180 if (channel_check_name(parv[2], false) == false)
181 {
182 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
183 "*** Too long or invalid channel name from %s(via %s): %s",
184 source_p->name, source_p->from->name, parv[2]);
185 return;
186 }
187
188 struct Channel *channel = hash_find_channel(parv[2]);
189 if (channel == NULL)
190 {
191 isnew = true;
192 channel = channel_make(parv[2]);
193 }
194
195 uintmax_t newts = strtoumax(parv[1], NULL, 10);
196 uintmax_t oldts = channel->creation_time;
197
198 if (newts == 0 && isnew == false && oldts)
199 {
200 sendto_channel_local(NULL, channel, 0, 0, 0,
201 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ju to 0",
202 me.name, channel->name, channel->name, oldts);
203 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
204 "Server %s changing TS on %s from %ju to 0",
205 source_p->servptr->name, channel->name, oldts);
206 }
207
208 if (isnew == true)
209 channel->creation_time = newts;
210 else if (newts == 0 || oldts == 0)
211 channel->creation_time = 0;
212 else if (newts == oldts)
213 ;
214 else if (newts < oldts)
215 {
216 keep_our_modes = false;
217 channel->creation_time = newts;
218 }
219 else
220 keep_new_modes = false;
221
222 struct Mode *oldmode = &channel->mode;
223
224 if (keep_new_modes == false)
225 mode = *oldmode;
226 else if (keep_our_modes == true)
227 {
228 mode.mode |= oldmode->mode;
229
230 if (oldmode->limit > mode.limit)
231 mode.limit = oldmode->limit;
232 if (strcmp(mode.key, oldmode->key) < 0)
233 strlcpy(mode.key, oldmode->key, sizeof(mode.key));
234 }
235
236 set_final_mode(&mode, oldmode, modebuf, parabuf);
237 channel->mode = mode;
238
239 const struct Client *origin = source_p->servptr;
240 if (IsHidden(source_p->servptr) || ConfigServerHide.hide_servers)
241 origin = &me;
242
243 /* Lost the TS, other side wins, so remove modes on this side */
244 if (keep_our_modes == false)
245 {
246 /* Update channel name to be the correct case */
247 strlcpy(channel->name, parv[2], sizeof(channel->name));
248
249 channel_demote_members(channel, origin);
250
251 if (channel->topic[0])
252 {
253 channel_set_topic(channel, "", "", 0, false);
254 sendto_channel_local(NULL, channel, 0, 0, 0, ":%s TOPIC %s :",
255 origin->name, channel->name);
256 }
257
258 sendto_channel_local(NULL, channel, 0, 0, 0,
259 ":%s NOTICE %s :*** Notice -- TS for %s changed from %ju to %ju",
260 me.name, channel->name, channel->name, oldts, newts);
261 }
262
263 if (*modebuf)
264 sendto_channel_local(NULL, channel, 0, 0, 0, ":%s MODE %s %s %s",
265 origin->name, channel->name, modebuf, parabuf);
266
267 if (member_find_link(source_p, channel) == NULL)
268 {
269 add_user_to_channel(channel, source_p, 0, true);
270
271 sendto_channel_local(NULL, channel, 0, CAP_EXTENDED_JOIN, 0, ":%s!%s@%s JOIN %s %s :%s",
272 source_p->name, source_p->username,
273 source_p->host, channel->name, source_p->account, source_p->info);
274 sendto_channel_local(NULL, channel, 0, 0, CAP_EXTENDED_JOIN, ":%s!%s@%s JOIN :%s",
275 source_p->name, source_p->username,
276 source_p->host, channel->name);
277
278 if (source_p->away[0])
279 sendto_channel_local(source_p, channel, 0, CAP_AWAY_NOTIFY, 0,
280 ":%s!%s@%s AWAY :%s",
281 source_p->name, source_p->username,
282 source_p->host, source_p->away);
283 }
284
285 sendto_server(source_p, 0, 0, ":%s JOIN %ju %s +",
286 source_p->id, channel->creation_time, channel->name);
287 }
288
289 static struct Message join_msgtab =
290 {
291 .cmd = "JOIN",
292 .handlers[UNREGISTERED_HANDLER] = { .handler = m_unregistered },
293 .handlers[CLIENT_HANDLER] = { .handler = m_join, .args_min = 2 },
294 .handlers[SERVER_HANDLER] = { .handler = ms_join, .args_min = 4 },
295 .handlers[ENCAP_HANDLER] = { .handler = m_ignore },
296 .handlers[OPER_HANDLER] = { .handler = m_join, .args_min = 2 }
297 };
298
299 static void
300 module_init(void)
301 {
302 mod_add_cmd(&join_msgtab);
303 }
304
305 static void
306 module_exit(void)
307 {
308 mod_del_cmd(&join_msgtab);
309 }
310
311 struct module module_entry =
312 {
313 .version = "$Revision$",
314 .modinit = module_init,
315 .modexit = module_exit,
316 .is_core = true
317 };

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.30