1 /*
2 * IRC - Internet Relay Chat, src/modules/m_invite.c
3 * (C) 2004 The UnrealIRCd Team
4 *
5 * See file AUTHORS in IRC package for additional names of
6 * the programmers.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 1, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22 #include "config.h"
23 #include "struct.h"
24 #include "common.h"
25 #include "sys.h"
26 #include "numeric.h"
27 #include "msg.h"
28 #include "proto.h"
29 #include "channel.h"
30 #include <time.h>
31 #include <sys/stat.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #ifdef _WIN32
36 #include <io.h>
37 #endif
38 #include <fcntl.h>
39 #include "h.h"
40 #ifdef STRIPBADWORDS
41 #include "badwords.h"
42 #endif
43 #ifdef _WIN32
44 #include "version.h"
45 #endif
46
47 DLLFUNC int m_invite(aClient *cptr, aClient *sptr, int parc, char *parv[]);
48
49 #define MSG_INVITE "INVITE"
50 #define TOK_INVITE "*"
51
52 ModuleHeader MOD_HEADER(m_invite)
53 = {
54 "m_invite",
55 "$Id$",
56 "command /invite",
57 "3.2-b8-1",
58 NULL
59 };
60
MOD_INIT(m_invite)61 DLLFUNC int MOD_INIT(m_invite)(ModuleInfo *modinfo)
62 {
63 add_Command(MSG_INVITE, TOK_INVITE, m_invite, MAXPARA);
64 MARK_AS_OFFICIAL_MODULE(modinfo);
65 return MOD_SUCCESS;
66 }
67
MOD_LOAD(m_invite)68 DLLFUNC int MOD_LOAD(m_invite)(int module_load)
69 {
70 return MOD_SUCCESS;
71 }
72
MOD_UNLOAD(m_invite)73 DLLFUNC int MOD_UNLOAD(m_invite)(int module_unload)
74 {
75 if (del_Command(MSG_INVITE, TOK_INVITE, m_invite) < 0)
76 {
77 sendto_realops("Failed to delete commands when unloading %s",
78 MOD_HEADER(m_invite).name);
79 }
80 return MOD_SUCCESS;
81 }
82
83 /* Send the user his/her list of active invites */
send_invite_list(aClient * sptr)84 int send_invite_list(aClient *sptr)
85 {
86 Link *inv;
87
88 for (inv = sptr->user->invited; inv; inv = inv->next)
89 {
90 sendto_one(sptr, rpl_str(RPL_INVITELIST), me.name, sptr->name,
91 inv->value.chptr->chname);
92 }
93 sendto_one(sptr, rpl_str(RPL_ENDOFINVITELIST), me.name, sptr->name);
94 return 0;
95 }
96
97 /*
98 ** m_invite
99 ** parv[0] - sender prefix
100 ** parv[1] - user to invite
101 ** parv[2] - channel number
102 */
CMD_FUNC(m_invite)103 DLLFUNC CMD_FUNC(m_invite)
104 {
105 aClient *acptr;
106 aChannel *chptr;
107 short over = 0;
108
109 if (parc == 1)
110 return send_invite_list(sptr);
111 else if (parc < 3 || *parv[1] == '\0')
112 {
113 sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
114 me.name, parv[0], "INVITE");
115 return -1;
116 }
117
118 if (!(acptr = find_person(parv[1], (aClient *)NULL)))
119 {
120 sendto_one(sptr, err_str(ERR_NOSUCHNICK),
121 me.name, parv[0], parv[1]);
122 return -1;
123 }
124
125 if (MyConnect(sptr))
126 clean_channelname(parv[2]);
127
128 if (check_channelmask(sptr, cptr, parv[2]))
129 return -1;
130
131 if (!(chptr = find_channel(parv[2], NullChn)))
132 {
133 sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL),
134 me.name, parv[0], parv[2]);
135 return -1;
136 }
137
138 if (chptr->mode.mode & MODE_NOINVITE && !IsULine(sptr))
139 {
140 #ifndef NO_OPEROVERRIDE
141 if ((MyClient(sptr) ? (IsOper(sptr) && OPCanOverride(sptr)) :
142 IsOper(sptr)) && sptr == acptr)
143 over = 1;
144 else {
145 #endif
146 sendto_one(sptr, err_str(ERR_NOINVITE),
147 me.name, parv[0], parv[2]);
148 return -1;
149 #ifndef NO_OPEROVERRIDE
150 }
151 #endif
152 }
153
154 if (!IsMember(sptr, chptr) && !IsULine(sptr))
155 {
156 #ifndef NO_OPEROVERRIDE
157 if ((MyClient(sptr) ? (IsOper(sptr) && OPCanOverride(sptr)) :
158 IsOper(sptr)) && sptr == acptr)
159 over = 1;
160 else {
161 #endif
162 sendto_one(sptr, err_str(ERR_NOTONCHANNEL),
163 me.name, parv[0], parv[2]);
164 return -1;
165 #ifndef NO_OPEROVERRIDE
166 }
167 #endif
168 }
169
170 if (IsMember(acptr, chptr))
171 {
172 sendto_one(sptr, err_str(ERR_USERONCHANNEL),
173 me.name, parv[0], parv[1], parv[2]);
174 return 0;
175 }
176
177 if (chptr->mode.mode & MODE_INVITEONLY)
178 {
179 if (!is_chan_op(sptr, chptr) && !IsULine(sptr))
180 {
181 #ifndef NO_OPEROVERRIDE
182 if ((MyClient(sptr) ? (IsOper(sptr) && OPCanOverride(sptr)) :
183 IsOper(sptr)) && sptr == acptr)
184 over = 1;
185 else {
186 #endif
187 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
188 me.name, parv[0], chptr->chname);
189 return -1;
190 #ifndef NO_OPEROVERRIDE
191 }
192 #endif
193 }
194 else if (!IsMember(sptr, chptr) && !IsULine(sptr))
195 {
196 #ifndef NO_OPEROVERRIDE
197 if ((MyClient(sptr) ? (IsOper(sptr) && OPCanOverride(sptr)) :
198 IsOper(sptr)) && sptr == acptr)
199 over = 1;
200 else {
201 #endif
202 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
203 me.name, parv[0],
204 ((chptr) ? (chptr->chname) : parv[2]));
205 return -1;
206 #ifndef NO_OPEROVERRIDE
207 }
208 #endif
209 }
210 }
211
212 if (MyClient(sptr) && SPAMFILTER_VIRUSCHANDENY && SPAMFILTER_VIRUSCHAN &&
213 !strcasecmp(chptr->chname, SPAMFILTER_VIRUSCHAN) &&
214 !is_chan_op(sptr, chptr) && !IsAnOper(sptr) && !IsULine(sptr))
215 {
216 sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED),
217 me.name, parv[0], chptr->chname);
218 return -1;
219 }
220
221 if (MyConnect(sptr))
222 {
223 if (check_for_target_limit(sptr, acptr, acptr->name))
224 return 0;
225 if (!over)
226 {
227 sendto_one(sptr, rpl_str(RPL_INVITING), me.name,
228 parv[0], acptr->name,
229 ((chptr) ? (chptr->chname) : parv[2]));
230 if (acptr->user->away)
231 sendto_one(sptr, rpl_str(RPL_AWAY), me.name,
232 parv[0], acptr->name, acptr->user->away);
233 }
234 }
235 /* Note: is_banned() here will cause some extra CPU load,
236 * and we're really only relying on the existence
237 * of the limit because we could momentarily have
238 * less people on channel.
239 */
240
241
242 if (over && MyConnect(acptr)) {
243 if ((chptr->mode.mode & MODE_ONLYSECURE) && !IsSecure(acptr))
244 {
245 sendto_snomask_global(SNO_EYES,
246 "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +z).",
247 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
248
249 /* Logging implementation added by XeRXeS */
250 ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) invited him/herself into %s (Overriding Secure Mode)",
251 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
252 }
253 else if (is_banned(sptr, chptr, BANCHK_JOIN))
254 {
255 sendto_snomask_global(SNO_EYES,
256 "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +b).",
257 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
258
259 /* Logging implementation added by XeRXeS */
260 ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) invited him/herself into %s (Overriding Ban).",
261 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
262
263 }
264 else if (chptr->mode.mode & MODE_INVITEONLY)
265 {
266 sendto_snomask_global(SNO_EYES,
267 "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +i).",
268 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
269
270 /* Logging implementation added by XeRXeS */
271 ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) invited him/herself into %s (Overriding Invite Only)",
272 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
273
274 }
275 else if (chptr->mode.limit)
276 {
277 sendto_snomask_global(SNO_EYES,
278 "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +l).",
279 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
280
281 /* Logging implementation added by XeRXeS */
282 ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) invited him/herself into %s (Overriding Limit)",
283 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
284
285 }
286 else if (chptr->mode.mode & MODE_RGSTRONLY)
287 {
288 sendto_snomask_global(SNO_EYES,
289 "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +R).",
290 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
291
292 /* Logging implementation added by XeRXeS */
293 ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) invited him/herself into %s (Overriding Reg Nicks Only)",
294 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
295
296 }
297 else if (*chptr->mode.key)
298 {
299 sendto_snomask_global(SNO_EYES,
300 "*** OperOverride -- %s (%s@%s) invited him/herself into %s (overriding +k).",
301 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
302
303 /* Logging implementation added by XeRXeS */
304 ircd_log(LOG_OVERRIDE,"OVERRIDE: %s (%s@%s) invited him/herself into %s (Overriding Key)",
305 sptr->name, sptr->user->username, sptr->user->realhost, chptr->chname);
306
307 }
308 #ifdef OPEROVERRIDE_VERIFY
309 else if (chptr->mode.mode & MODE_SECRET || chptr->mode.mode & MODE_PRIVATE)
310 over = -1;
311 #endif
312 else
313 return 0;
314 }
315 if (MyConnect(acptr)) {
316 if (chptr && sptr->user
317 && (is_chan_op(sptr, chptr)
318 || IsULine(sptr)
319 #ifndef NO_OPEROVERRIDE
320 || IsOper(sptr)
321 #endif
322 )) {
323 if (over == 1)
324 sendto_channelprefix_butone(NULL, &me, chptr, PREFIX_OP|PREFIX_ADMIN|PREFIX_OWNER,
325 ":%s NOTICE @%s :OperOverride -- %s invited him/herself into the channel.",
326 me.name, chptr->chname, sptr->name);
327 else if (over == 0)
328 sendto_channelprefix_butone(NULL, &me, chptr, PREFIX_OP|PREFIX_ADMIN|PREFIX_OWNER,
329 ":%s NOTICE @%s :%s invited %s into the channel.",
330 me.name, chptr->chname, sptr->name, acptr->name);
331
332 add_invite(acptr, chptr);
333 }
334 }
335 if (!is_silenced(sptr, acptr))
336 sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0],
337 acptr->name, ((chptr) ? (chptr->chname) : parv[2]));
338
339 return 0;
340 }
341