ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/contrib/m_force.c
Revision: 356
Committed: Mon Jan 2 22:05:15 2006 UTC (18 years, 3 months ago) by adx
Content type: text/x-csrc
File size: 11190 byte(s)
Log Message:
+ MFC support for halfop->op rewriting.

File Contents

# Content
1 /* contrib/m_force.c
2 * Copyright (C) 2002, 2003, 2004, 2005 Hybrid Development Team
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * 1.Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2.Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3.The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $Id$
29 */
30
31 #include "stdinc.h"
32 #include "handlers.h"
33 #include "client.h"
34 #include "common.h" /* FALSE bleah */
35 #include "ircd.h"
36 #include "irc_string.h"
37 #include "numeric.h"
38 #include "fdlist.h"
39 #include "hash.h"
40 #include "s_bsd.h"
41 #include "s_conf.h"
42 #include "s_serv.h"
43 #include "send.h"
44 #include "msg.h"
45 #include "parse.h"
46 #include "modules.h"
47 #include "channel.h"
48 #include "channel_mode.h"
49
50 static void mo_forcejoin(struct Client *, struct Client *, int parc, char *[]);
51 static void mo_forcepart(struct Client *, struct Client *, int parc, char *[]);
52
53 struct Message forcejoin_msgtab = {
54 "FORCEJOIN", 0, 0, 3, 0, MFLG_SLOW, 0,
55 { m_ignore, m_not_oper, mo_forcejoin, mo_forcejoin, mo_forcejoin, m_ignore }
56 };
57
58 struct Message forcepart_msgtab = {
59 "FORCEPART", 0, 0, 3, 0, MFLG_SLOW, 0,
60 { m_ignore, m_not_oper, mo_forcepart, mo_forcepart, mo_forcepart, m_ignore }
61 };
62
63 #ifndef STATIC_MODULES
64 void
65 _modinit(void)
66 {
67 mod_add_cmd(&forcejoin_msgtab);
68 mod_add_cmd(&forcepart_msgtab);
69 }
70
71 void
72 _moddeinit(void)
73 {
74 mod_del_cmd(&forcejoin_msgtab);
75 mod_del_cmd(&forcepart_msgtab);
76 }
77
78 const char *_version = "$Revision$";
79 #endif
80
81 /* m_forcejoin()
82 * parv[0] = sender prefix
83 * parv[1] = user to force
84 * parv[2] = channel to force them into
85 */
86 static void
87 mo_forcejoin(struct Client *client_p, struct Client *source_p,
88 int parc, char *parv[])
89 {
90 struct Client *target_p = NULL;
91 struct Channel *chptr = NULL;
92 unsigned int type = 0;
93 char mode = '\0';
94 char sjmode = '\0';
95 char *newch = NULL;
96 dlink_node *ptr;
97
98 if (!IsAdmin(source_p))
99 {
100 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
101 me.name, source_p->name);
102 return;
103 }
104
105 if ((target_p = find_client(parv[1])) == NULL)
106 {
107 sendto_one(source_p, form_str(ERR_NOSUCHNICK),
108 me.name, source_p->name, parv[1]);
109 return;
110 }
111
112 if (!MyConnect(target_p))
113 {
114 if (target_p->from != client_p)
115 {
116 if (IsCapable(target_p->from, CAP_ENCAP))
117 sendto_one(target_p, ":%s ENCAP %s FORCEJOIN %s %s",
118 source_p->name, target_p->from->name,
119 target_p->name, parv[2]);
120 else
121 sendto_one(target_p, ":%s FORCEJOIN %s %s",
122 source_p->name, target_p->name, parv[2]);
123 }
124
125 return;
126 }
127
128 /* select our modes from parv[2] if they exist... (chanop)*/
129 switch (*parv[2])
130 {
131 case '@':
132 type = CHFL_CHANOP;
133 mode = 'o';
134 sjmode = '@';
135 parv[2]++;
136 break;
137 #ifdef HALFOPS
138 case '%':
139 type = CHFL_HALFOP;
140 mode = 'h';
141 sjmode = '%';
142 parv[2]++;
143 break;
144 #endif
145 case '+':
146 type = CHFL_VOICE;
147 mode = 'v';
148 sjmode = '+';
149 parv[2]++;
150 break;
151 default:
152 type = 0;
153 mode = sjmode = '\0'; /* make sure sjmode is 0. sjoin depends on it */
154 break;
155 }
156
157 if ((chptr = hash_find_channel(parv[2])) != NULL)
158 {
159 if (IsMember(target_p, chptr))
160 {
161 sendto_one(source_p, ":%s NOTICE %s :*** Notice -- %s is already in %s",
162 me.name, source_p->name, target_p->name, chptr->chname);
163 return;
164 }
165
166 add_user_to_channel(chptr, target_p, type, NO);
167
168 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s JOIN :%s",
169 target_p->name, target_p->username,
170 target_p->host, chptr->chname);
171
172 if (sjmode)
173 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s MODE %s +%c %s",
174 me.name, chptr->chname, mode, target_p->name);
175
176 if (chptr->chname[0] == '#')
177 {
178 if (sjmode)
179 DLINK_FOREACH (ptr, serv_list.head)
180 {
181 struct Client *serv_p = ptr->data;
182 if (serv_p == target_p->from || IsDead(serv_p))
183 continue;
184
185 sendto_one(serv_p, ":%s SJOIN %lu %s + :%c%s",
186 ID_or_name(&me, serv_p), (unsigned long)chptr->channelts,
187 chptr->chname, (sjmode == '%' &&
188 !IsCapable(serv_p, CAP_HOPS)) ? '@' : sjmode,
189 ID_or_name(target_p, serv_p));
190 }
191 else
192 {
193 sendto_server(target_p, target_p, chptr, CAP_TS6, NOCAPS, LL_ICLIENT,
194 ":%s SJOIN %lu %s + :%s",
195 me.id, (unsigned long)chptr->channelts,
196 chptr->chname, target_p->id);
197 sendto_server(target_p, target_p, chptr, NOCAPS, CAP_TS6, LL_ICLIENT,
198 ":%s SJOIN %lu %s + :%s",
199 me.name, (unsigned long)chptr->channelts,
200 chptr->chname, target_p->name);
201 }
202 }
203
204 if (chptr->topic != NULL)
205 {
206 sendto_one(target_p, form_str(RPL_TOPIC),
207 me.name, target_p->name,
208 chptr->chname, chptr->topic);
209 sendto_one(target_p, form_str(RPL_TOPICWHOTIME),
210 me.name, source_p->name, chptr->chname,
211 chptr->topic_info, chptr->topic_time);
212 }
213
214 target_p->localClient->last_join_time = CurrentTime;
215 channel_member_names(target_p, chptr, 1);
216 }
217 else
218 {
219 newch = parv[2];
220
221 if (check_channel_name(newch) == 0)
222 {
223 sendto_one(source_p, form_str(ERR_BADCHANNAME),
224 me.name, source_p->name, newch);
225 return;
226 }
227
228 /* channel name must begin with & or # */
229 if (!IsChanPrefix(*newch))
230 {
231 sendto_one(source_p, form_str(ERR_BADCHANNAME),
232 me.name, source_p->name, newch);
233 return;
234 }
235
236 /* it would be interesting here to allow an oper
237 * to force target_p into a channel that doesn't exist
238 * even more so, into a local channel when we disable
239 * local channels... but...
240 * I don't want to break anything - scuzzy
241 */
242 if (ConfigChannel.disable_local_channels && (*newch == '&'))
243 {
244 sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
245 me.name, source_p->name, newch);
246 return;
247 }
248
249 /* newch can't be longer than CHANNELLEN */
250 if (strlen(newch) > CHANNELLEN)
251 {
252 sendto_one(source_p, form_str(ERR_BADCHANNAME),
253 me.name, source_p->name, newch);
254 return;
255 }
256
257 chptr = get_or_create_channel(target_p, newch, NULL);
258 add_user_to_channel(chptr, target_p, CHFL_CHANOP, NO);
259
260 /* send out a join, make target_p join chptr */
261 if (chptr->chname[0] == '#')
262 {
263 sendto_server(target_p, target_p, chptr, CAP_TS6, NOCAPS, LL_ICLIENT,
264 ":%s SJOIN %lu %s +nt :@%s",
265 me.id, (unsigned long)chptr->channelts,
266 chptr->chname, ID(target_p));
267 sendto_server(target_p, target_p, chptr, NOCAPS, CAP_TS6, LL_ICLIENT,
268 ":%s SJOIN %lu %s +nt :@%s",
269 me.name, (unsigned long)chptr->channelts,
270 chptr->chname, target_p->name);
271 }
272
273 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s JOIN :%s",
274 target_p->name, target_p->username,
275 target_p->host, chptr->chname);
276
277 chptr->mode.mode |= MODE_TOPICLIMIT | MODE_NOPRIVMSGS;
278
279 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s MODE %s +nt",
280 me.name, chptr->chname);
281
282 target_p->localClient->last_join_time = CurrentTime;
283 channel_member_names(target_p, chptr, 1);
284
285 /* we do this to let the oper know that a channel was created, this will be
286 * seen from the server handling the command instead of the server that
287 * the oper is on.
288 */
289 sendto_one(source_p, ":%s NOTICE %s :*** Notice -- Creating channel %s",
290 me.name, source_p->name, chptr->chname);
291 }
292 }
293
294 static void
295 mo_forcepart(struct Client *client_p, struct Client *source_p,
296 int parc, char *parv[])
297 {
298 struct Client *target_p = NULL;
299 struct Channel *chptr = NULL;
300 struct Membership *member = NULL;
301
302 if (!IsAdmin(source_p))
303 {
304 sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
305 me.name, source_p->name);
306 return;
307 }
308
309 /* if target_p == NULL then let the oper know */
310 if ((target_p = find_client(parv[1])) == NULL)
311 {
312 sendto_one(source_p, form_str(ERR_NOSUCHNICK),
313 me.name, source_p->name, parv[1]);
314 return;
315 }
316
317 if (!MyConnect(target_p))
318 {
319 if (target_p->from != client_p)
320 {
321 if (IsCapable(target_p->from, CAP_ENCAP))
322 sendto_one(target_p, ":%s ENCAP %s FORCEPART %s %s",
323 source_p->name, target_p->from->name,
324 target_p->name, parv[2]);
325 else
326 sendto_one(target_p, ":%s FORCEPART %s %s",
327 source_p->name, target_p->name, parv[2]);
328 }
329
330 return;
331 }
332
333 if ((chptr = hash_find_channel(parv[2])) == NULL)
334 {
335 sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
336 me.name, source_p->name, parv[2]);
337 return;
338 }
339
340 if ((member = find_channel_link(target_p, chptr)) == NULL)
341 {
342 sendto_one(source_p, form_str(ERR_USERNOTINCHANNEL),
343 me.name, source_p->name, chptr->chname, target_p->name);
344 return;
345 }
346
347 if (chptr->chname[0] == '#')
348 {
349 sendto_server(target_p, target_p, chptr, CAP_TS6, NOCAPS, LL_ICLIENT,
350 ":%s PART %s :%s", ID(target_p),
351 chptr->chname, target_p->name);
352 sendto_server(target_p, target_p, chptr, NOCAPS, CAP_TS6, LL_ICLIENT,
353 ":%s PART %s :%s", target_p->name,
354 chptr->chname, target_p->name);
355 }
356
357 sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s!%s@%s PART %s :%s",
358 target_p->name, target_p->username,
359 target_p->host, chptr->chname,
360 target_p->name);
361 remove_user_from_channel(member);
362 }

Properties

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