ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/m_svsjoin.c
Revision: 3326
Committed: Tue Apr 15 17:26:29 2014 UTC (11 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 9684 byte(s)
Log Message:
- m_svsjoin.c: propset

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 2014 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21
22 /*! \file m_svsjoin.c
23 * \brief Includes required functions for processing the SVSJOIN 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 "s_serv.h"
38 #include "conf.h"
39 #include "parse.h"
40 #include "modules.h"
41 #include "resv.h"
42
43
44 /* do_join_0()
45 *
46 * inputs - pointer to client doing join 0
47 * output - NONE
48 * side effects - Use has decided to join 0. This is legacy
49 * from the days when channels were numbers not names. *sigh*
50 * There is a bunch of evilness necessary here due to
51 * anti spambot code.
52 */
53 static void
54 do_join_0(struct Client *source_p)
55 {
56 dlink_node *ptr = NULL, *ptr_next = NULL;
57
58 DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->channel.head)
59 {
60 struct Channel *chptr = ((struct Membership *)ptr->data)->chptr;
61
62 sendto_server(source_p, NOCAPS, NOCAPS, ":%s PART %s",
63 source_p->id, chptr->chname);
64 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s PART %s",
65 source_p->name, source_p->username,
66 source_p->host, chptr->chname);
67
68 remove_user_from_channel(ptr->data);
69 }
70 }
71
72 /* last0() stolen from ircu */
73 static char *
74 last0(struct Client *target_p, char *chanlist)
75 {
76 char *p;
77 int join0 = 0;
78
79 for (p = chanlist; *p; ++p) /* find last "JOIN 0" */
80 {
81 if (*p == '0' && (*(p + 1) == ',' || *(p + 1) == '\0'))
82 {
83 if ((*p + 1) == ',')
84 ++p;
85
86 chanlist = p + 1;
87 join0 = 1;
88 }
89 else
90 {
91 while (*p != ',' && *p != '\0') /* skip past channel name */
92 ++p;
93
94 if (*p == '\0') /* hit the end */
95 break;
96 }
97 }
98
99 if (join0)
100 do_join_0(target_p);
101
102 return chanlist;
103 }
104
105 /*! \brief SVSJOIN command handler
106 *
107 * \param source_p Pointer to allocated Client struct from which the message
108 * originally comes from. This can be a local or remote client.
109 * \param parc Integer holding the number of supplied arguments.
110 * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
111 * pointers.
112 * \note Valid arguments for this command are:
113 * - parv[0] = command
114 * - parv[1] = nickname
115 * - parv[2] = channel
116 * - parv[3] = channel password (key)
117 */
118 static int
119 ms_svsjoin(struct Client *source_p, int parc, char *parv[])
120 {
121 char *p = NULL;
122 char *key_list = NULL;
123 char *chan_list = NULL;
124 char *chan = NULL;
125 struct Channel *chptr = NULL;
126 struct MaskItem *conf = NULL;
127 struct Client *target_p = NULL;
128 int i = 0;
129 unsigned int flags = 0;
130
131 if (!HasFlag(source_p, FLAGS_SERVICE))
132 return 0;
133
134 if (EmptyString(parv[2]))
135 return 0;
136
137 if ((target_p = find_person(source_p, parv[1])) == NULL)
138 return 0;
139
140 if (target_p->from == source_p->from)
141 {
142 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
143 "Received wrong-direction SVSJOIN "
144 "for %s (behind %s) from %s",
145 target_p->name, source_p->from->name,
146 get_client_name(source_p, HIDE_IP));
147 return 0;
148 }
149
150 if (!MyConnect(target_p))
151 {
152 if (parc == 3)
153 sendto_one(target_p, ":%s SVSJOIN %s %s", source_p->id,
154 target_p->id, parv[2]);
155 else
156 sendto_one(target_p, ":%s SVSJOIN %s %s %s", source_p->id,
157 target_p->id, parv[2], parv[3]);
158 return 0;
159 }
160
161 key_list = parv[3];
162 chan_list = last0(target_p, parv[2]);
163
164 for (chan = strtoken(&p, chan_list, ","); chan;
165 chan = strtoken(&p, NULL, ","))
166 {
167 const char *key = NULL;
168
169 /* If we have any more keys, take the first for this channel. */
170 if (!EmptyString(key_list) && (key_list = strchr(key = key_list, ',')))
171 *key_list++ = '\0';
172
173 /* Empty keys are the same as no keys. */
174 if (key && *key == '\0')
175 key = NULL;
176
177 if (!check_channel_name(chan, 1))
178 {
179 sendto_one_numeric(target_p, &me, ERR_BADCHANNAME, chan);
180 continue;
181 }
182
183 if (!IsExemptResv(target_p) &&
184 !(HasUMode(target_p, UMODE_OPER) && ConfigFileEntry.oper_pass_resv) &&
185 ((conf = match_find_resv(chan)) && !resv_find_exempt(target_p, conf)))
186 {
187 ++conf->count;
188 sendto_one_numeric(target_p, &me, ERR_CHANBANREASON,
189 chan, conf->reason ? conf->reason : "Reserved channel");
190 sendto_realops_flags(UMODE_SPY, L_ALL, SEND_NOTICE,
191 "Forbidding reserved channel %s from user %s",
192 chan, get_client_name(target_p, HIDE_IP));
193 continue;
194 }
195
196 if (dlink_list_length(&target_p->channel) >=
197 (HasUMode(target_p, UMODE_OPER) ?
198 ConfigChannel.max_chans_per_oper :
199 ConfigChannel.max_chans_per_user))
200 {
201 sendto_one_numeric(target_p, &me, ERR_TOOMANYCHANNELS, chan);
202 break;
203 }
204
205 if ((chptr = hash_find_channel(chan)) != NULL)
206 {
207 if (IsMember(target_p, chptr))
208 continue;
209
210 if (splitmode && !HasUMode(target_p, UMODE_OPER) &&
211 ConfigChannel.no_join_on_split)
212 {
213 sendto_one_numeric(target_p, &me, ERR_UNAVAILRESOURCE, chan);
214 continue;
215 }
216
217 /*
218 * can_join checks for +i key, bans.
219 */
220 if ((i = can_join(target_p, chptr, key)))
221 {
222 sendto_one_numeric(target_p, &me, i, chptr->chname);
223 continue;
224 }
225
226 /*
227 * This should never be the case unless there is some sort of
228 * persistant channels.
229 */
230 if (dlink_list_length(&chptr->members) == 0)
231 flags = CHFL_CHANOP;
232 else
233 flags = 0;
234 }
235 else
236 {
237 if (splitmode && !HasUMode(target_p, UMODE_OPER) &&
238 (ConfigChannel.no_create_on_split || ConfigChannel.no_join_on_split))
239 {
240 sendto_one_numeric(target_p, &me, ERR_UNAVAILRESOURCE, chan);
241 continue;
242 }
243
244 flags = CHFL_CHANOP;
245 chptr = make_channel(chan);
246 }
247
248 add_user_to_channel(chptr, target_p, flags, 1);
249
250 /*
251 * Set timestamp if appropriate, and propagate
252 */
253 if (flags & CHFL_CHANOP)
254 {
255 chptr->channelts = CurrentTime;
256 chptr->mode.mode |= MODE_TOPICLIMIT;
257 chptr->mode.mode |= MODE_NOPRIVMSGS;
258
259 sendto_server(target_p, NOCAPS, NOCAPS, ":%s SJOIN %lu %s +nt :@%s",
260 me.id, (unsigned long)chptr->channelts,
261 chptr->chname, target_p->id);
262 /*
263 * notify all other users on the new channel
264 */
265 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s JOIN :%s",
266 target_p->name, target_p->username,
267 target_p->host, chptr->chname);
268 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s MODE %s +nt",
269 me.name, chptr->chname);
270 if (target_p->away[0])
271 sendto_channel_local_butone(target_p, 0, CAP_AWAY_NOTIFY, chptr,
272 ":%s!%s@%s AWAY :%s",
273 target_p->name, target_p->username,
274 target_p->host, target_p->away);
275 }
276 else
277 {
278 sendto_server(target_p, NOCAPS, NOCAPS, ":%s JOIN %lu %s +",
279 target_p->id, (unsigned long)chptr->channelts,
280 chptr->chname);
281
282 sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s!%s@%s JOIN :%s",
283 target_p->name, target_p->username,
284 target_p->host, chptr->chname);
285
286 if (target_p->away[0])
287 sendto_channel_local_butone(target_p, 0, CAP_AWAY_NOTIFY, chptr,
288 ":%s!%s@%s AWAY :%s",
289 target_p->name, target_p->username,
290 target_p->host, target_p->away);
291 }
292
293 del_invite(chptr, target_p);
294
295 if (chptr->topic[0])
296 {
297 sendto_one_numeric(target_p, &me, RPL_TOPIC, chptr->chname, chptr->topic);
298 sendto_one_numeric(target_p, &me, RPL_TOPICWHOTIME, chptr->chname,
299 chptr->topic_info, chptr->topic_time);
300 }
301
302 channel_member_names(target_p, chptr, 1);
303 }
304
305 return 0;
306 }
307
308 static struct Message svsjoin_msgtab = {
309 "SVSJOIN", 0, 0, 3, MAXPARA, MFLG_SLOW, 0,
310 { m_unregistered, m_ignore, ms_svsjoin, m_ignore, m_ignore, m_ignore }
311 };
312
313 static void
314 module_init(void)
315 {
316 mod_add_cmd(&svsjoin_msgtab);
317 }
318
319 static void
320 module_exit(void)
321 {
322 mod_del_cmd(&svsjoin_msgtab);
323 }
324
325 struct module module_entry = {
326 .node = { NULL, NULL, NULL },
327 .name = NULL,
328 .version = "$Revision$",
329 .handle = NULL,
330 .modinit = module_init,
331 .modexit = module_exit,
332 .flags = MODULE_FLAG_CORE
333 };

Properties

Name Value
svn:keywords Id Revision