]> jfr.im git - irc/rqf/shadowircd.git/blob - unsupported/m_force.c
146fa9c16105e65cb98bf17ace0168eba02f6d5a
[irc/rqf/shadowircd.git] / unsupported / m_force.c
1 /* contrib/m_force.c
2 * Copyright (C) 1996-2002 Hybrid Development Team
3 * Copyright (C) 2004 ircd-ratbox Development Team
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * 1.Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2.Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3.The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $Id: m_force.c 3297 2007-03-28 14:49:48Z jilles $
30 */
31
32 #include "stdinc.h"
33 #include "channel.h"
34 #include "class.h"
35 #include "client.h"
36 #include "common.h"
37 #include "match.h"
38 #include "ircd.h"
39 #include "hostmask.h"
40 #include "numeric.h"
41 #include "s_conf.h"
42 #include "s_newconf.h"
43 #include "logger.h"
44 #include "send.h"
45 #include "hash.h"
46 #include "s_serv.h"
47 #include "msg.h"
48 #include "parse.h"
49 #include "modules.h"
50
51 static int mo_forcejoin(struct Client *client_p, struct Client *source_p,
52 int parc, const char *parv[]);
53 static int mo_forcepart(struct Client *client_p, struct Client *source_p,
54 int parc, const char *parv[]);
55
56 struct Message forcejoin_msgtab = {
57 "FORCEJOIN", 0, 0, 0, MFLG_SLOW,
58 {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_forcejoin, 3}}
59 };
60
61 struct Message forcepart_msgtab = {
62 "FORCEPART", 0, 0, 0, MFLG_SLOW,
63 {mg_unreg, mg_not_oper, mg_ignore, mg_ignore, mg_ignore, {mo_forcepart, 3}}
64 };
65
66 mapi_clist_av1 force_clist[] = { &forcejoin_msgtab, &forcepart_msgtab, NULL };
67
68 DECLARE_MODULE_AV1(force, NULL, NULL, force_clist, NULL, NULL, "$Revision: 3297 $");
69
70 /*
71 * m_forcejoin
72 * parv[0] = sender prefix
73 * parv[1] = user to force
74 * parv[2] = channel to force them into
75 */
76 static int
77 mo_forcejoin(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
78 {
79 struct Client *target_p;
80 struct Channel *chptr;
81 int type;
82 char mode;
83 char sjmode;
84 char *newch;
85
86 if(!IsOperAdmin(source_p))
87 {
88 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin");
89 return 0;
90 }
91
92 if((hunt_server(client_p, source_p, ":%s FORCEJOIN %s %s", 1, parc, parv)) != HUNTED_ISME)
93 return 0;
94
95 /* if target_p is not existant, print message
96 * to source_p and bail - scuzzy
97 */
98 if((target_p = find_client(parv[1])) == NULL)
99 {
100 sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, parv[1]);
101 return 0;
102 }
103
104 if(!IsPerson(target_p))
105 return 0;
106
107 sendto_wallops_flags(UMODE_WALLOP, &me,
108 "FORCEJOIN called for %s %s by %s!%s@%s",
109 parv[1], parv[2], source_p->name, source_p->username, source_p->host);
110 ilog(L_MAIN, "FORCEJOIN called for %s %s by %s!%s@%s",
111 parv[1], parv[2], source_p->name, source_p->username, source_p->host);
112 sendto_server(NULL, NULL, NOCAPS, NOCAPS,
113 ":%s WALLOPS :FORCEJOIN called for %s %s by %s!%s@%s",
114 me.name, parv[1], parv[2],
115 source_p->name, source_p->username, source_p->host);
116
117 /* select our modes from parv[2] if they exist... (chanop) */
118 if(*parv[2] == '@')
119 {
120 type = CHFL_CHANOP;
121 mode = 'o';
122 sjmode = '@';
123 }
124 else if(*parv[2] == '+')
125 {
126 type = CHFL_VOICE;
127 mode = 'v';
128 sjmode = '+';
129 }
130 else
131 {
132 type = CHFL_PEON;
133 mode = sjmode = '\0';
134 }
135
136 if(mode != '\0')
137 parv[2]++;
138
139 if((chptr = find_channel(parv[2])) != NULL)
140 {
141 if(IsMember(target_p, chptr))
142 {
143 /* debugging is fun... */
144 sendto_one_notice(source_p, ":*** Notice -- %s is already in %s",
145 target_p->name, chptr->chname);
146 return 0;
147 }
148
149 add_user_to_channel(chptr, target_p, type);
150
151 sendto_server(target_p, chptr, NOCAPS, NOCAPS,
152 ":%s SJOIN %ld %s + :%c%s",
153 me.name, (long) chptr->channelts,
154 chptr->chname, type ? sjmode : ' ', target_p->name);
155
156 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
157 target_p->name, target_p->username,
158 target_p->host, chptr->chname);
159
160 if(type)
161 sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +%c %s",
162 me.name, chptr->chname, mode, target_p->name);
163
164 if(chptr->topic != NULL)
165 {
166 sendto_one(target_p, form_str(RPL_TOPIC), me.name,
167 target_p->name, chptr->chname, chptr->topic);
168 sendto_one(target_p, form_str(RPL_TOPICWHOTIME),
169 me.name, source_p->name, chptr->chname,
170 chptr->topic_info, chptr->topic_time);
171 }
172
173 channel_member_names(chptr, target_p, 1);
174 }
175 else
176 {
177 newch = LOCAL_COPY(parv[2]);
178 if(!check_channel_name(newch))
179 {
180 sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name,
181 source_p->name, (unsigned char *) newch);
182 return 0;
183 }
184
185 /* channel name must begin with & or # */
186 if(!IsChannelName(newch))
187 {
188 sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name,
189 source_p->name, (unsigned char *) newch);
190 return 0;
191 }
192
193 /* newch can't be longer than CHANNELLEN */
194 if(strlen(newch) > CHANNELLEN)
195 {
196 sendto_one_notice(source_p, ":Channel name is too long");
197 return 0;
198 }
199
200 chptr = get_or_create_channel(target_p, newch, NULL);
201 add_user_to_channel(chptr, target_p, CHFL_CHANOP);
202
203 /* send out a join, make target_p join chptr */
204 sendto_server(target_p, chptr, NOCAPS, NOCAPS,
205 ":%s SJOIN %ld %s +nt :@%s", me.name,
206 (long) chptr->channelts, chptr->chname, target_p->name);
207
208 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s JOIN :%s",
209 target_p->name, target_p->username,
210 target_p->host, chptr->chname);
211
212 chptr->mode.mode |= MODE_TOPICLIMIT;
213 chptr->mode.mode |= MODE_NOPRIVMSGS;
214
215 sendto_channel_local(ALL_MEMBERS, chptr, ":%s MODE %s +nt", me.name, chptr->chname);
216
217 target_p->localClient->last_join_time = rb_current_time();
218 channel_member_names(chptr, target_p, 1);
219
220 /* we do this to let the oper know that a channel was created, this will be
221 * seen from the server handling the command instead of the server that
222 * the oper is on.
223 */
224 sendto_one_notice(source_p, ":*** Notice -- Creating channel %s", chptr->chname);
225 }
226 return 0;
227 }
228
229
230 static int
231 mo_forcepart(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
232 {
233 struct Client *target_p;
234 struct Channel *chptr;
235 struct membership *msptr;
236
237 if(!IsOperAdmin(source_p))
238 {
239 sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "admin");
240 return 0;
241 }
242
243 if((hunt_server(client_p, source_p, ":%s FORCEPART %s %s", 1, parc, parv)) != HUNTED_ISME)
244 return 0;
245
246 /* if target_p == NULL then let the oper know */
247 if((target_p = find_client(parv[1])) == NULL)
248 {
249 sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, parv[1]);
250 return 0;
251 }
252
253 if(!IsClient(target_p))
254 return 0;
255
256 sendto_wallops_flags(UMODE_WALLOP, &me,
257 "FORCEPART called for %s %s by %s!%s@%s",
258 parv[1], parv[2], source_p->name, source_p->username, source_p->host);
259 ilog(L_MAIN, "FORCEPART called for %s %s by %s!%s@%s",
260 parv[1], parv[2], source_p->name, source_p->username, source_p->host);
261 sendto_server(NULL, NULL, NOCAPS, NOCAPS,
262 ":%s WALLOPS :FORCEPART called for %s %s by %s!%s@%s",
263 me.name, parv[1], parv[2],
264 source_p->name, source_p->username, source_p->host);
265
266 if((chptr = find_channel(parv[2])) == NULL)
267 {
268 sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL,
269 form_str(ERR_NOSUCHCHANNEL), parv[1]);
270 return 0;
271 }
272
273 if((msptr = find_channel_membership(chptr, target_p)) == NULL)
274 {
275 sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL,
276 form_str(ERR_USERNOTINCHANNEL),
277 parv[1], parv[2]);
278 return 0;
279 }
280
281 sendto_server(target_p, chptr, NOCAPS, NOCAPS,
282 ":%s PART %s :%s", target_p->name, chptr->chname, target_p->name);
283
284 sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s",
285 target_p->name, target_p->username,
286 target_p->host, chptr->chname, target_p->name);
287
288
289 remove_user_from_channel(msptr);
290
291 return 0;
292 }