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