1 /*
2  *   IRC - Internet Relay Chat, src/modules/m_knock.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_knock(aClient *cptr, aClient *sptr, int parc, char *parv[]);
48 
49 #define MSG_KNOCK 	"KNOCK"
50 #define TOK_KNOCK 	"AI"
51 
52 ModuleHeader MOD_HEADER(m_knock)
53   = {
54 	"m_knock",
55 	"$Id$",
56 	"command /knock",
57 	"3.2-b8-1",
58 	NULL
59     };
60 
MOD_INIT(m_knock)61 DLLFUNC int MOD_INIT(m_knock)(ModuleInfo *modinfo)
62 {
63 	CommandAdd(modinfo->handle, MSG_KNOCK, TOK_KNOCK, m_knock, 2, M_USER|M_ANNOUNCE);
64 	MARK_AS_OFFICIAL_MODULE(modinfo);
65 	return MOD_SUCCESS;
66 }
67 
MOD_LOAD(m_knock)68 DLLFUNC int MOD_LOAD(m_knock)(int module_load)
69 {
70 	return MOD_SUCCESS;
71 }
72 
MOD_UNLOAD(m_knock)73 DLLFUNC int MOD_UNLOAD(m_knock)(int module_unload)
74 {
75 	return MOD_SUCCESS;
76 }
77 
78 /*
79 ** m_knock
80 **	parv[0] - sender prefix
81 **	parv[1] - channel
82 **	parv[2] - reason
83 **
84 ** Coded by Stskeeps
85 ** Additional bugfixes/ideas by codemastr
86 ** (C) codemastr & Stskeeps
87 **
88 */
CMD_FUNC(m_knock)89 CMD_FUNC(m_knock)
90 {
91 	aChannel *chptr;
92 	char buf[1024], chbuf[CHANNELLEN + 8];
93 
94 	if (IsServer(sptr))
95 		return 0;
96 
97 	if (parc < 2 || *parv[1] == '\0')
98 	{
99 		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
100 		    me.name, parv[0], "KNOCK");
101 		return -1;
102 	}
103 
104 	if (MyConnect(sptr))
105 		clean_channelname(parv[1]);
106 
107 	if (check_channelmask(sptr, cptr, parv[1]))
108 		return 0;
109 	/* bugfix for /knock PRv Please? */
110 	if (*parv[1] != '#')
111 	{
112 		sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
113 		    me.name,
114 		    sptr->name,
115 		    parv[1], "Remember to use a # prefix in channel name");
116 
117 		return 0;
118 	}
119 	if (!(chptr = find_channel(parv[1], NullChn)))
120 	{
121 		sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
122 		    me.name, sptr->name, parv[1], "Channel does not exist!");
123 		return 0;
124 	}
125 
126 	/* IsMember bugfix by codemastr */
127 	if (IsMember(sptr, chptr) == 1)
128 	{
129 		sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
130 		    me.name,
131 		    sptr->name, chptr->chname, "You're already there!");
132 		return 0;
133 	}
134 	if (chptr->mode.mode & MODE_NOKNOCK)
135 	{
136 		sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
137 		    me.name,
138 		    sptr->name, chptr->chname, "No knocks are allowed! (+K)");
139 		return 0;
140 	}
141 
142 	if (!(chptr->mode.mode & MODE_INVITEONLY))
143 	{
144 		sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
145 		    me.name,
146 		    sptr->name, chptr->chname, "Channel is not invite only!");
147 		return 0;
148 	}
149 
150 	if (is_banned(sptr, chptr, BANCHK_JOIN))
151 	{
152 		sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
153 		    me.name, sptr->name, chptr->chname, "You're banned!");
154 		return 0;
155 	}
156 
157 	if ((chptr->mode.mode & MODE_NOINVITE) && !is_chan_op(sptr, chptr))
158 	{
159 		sendto_one(sptr, err_str(ERR_CANNOTKNOCK),
160 		    me.name,
161 		    sptr->name,
162 		    chptr->chname, "The channel does not allow invites (+V)");
163 
164 		return 0;
165 	}
166 
167 	ircsprintf(chbuf, "@%s", chptr->chname);
168 	ircsprintf(buf, "[Knock] by %s!%s@%s (%s)",
169 		sptr->name, sptr->user->username, GetHost(sptr),
170 		parv[2] ? parv[2] : "no reason specified");
171 	sendto_channelprefix_butone_tok(NULL, &me, chptr, PREFIX_OP|PREFIX_ADMIN|PREFIX_OWNER,
172 		MSG_NOTICE, TOK_NOTICE, chbuf, buf, 0);
173 
174 	sendto_one(sptr, ":%s %s %s :Knocked on %s", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE",
175 	    sptr->name, chptr->chname);
176 
177 #ifdef NEWCHFLOODPROT
178 	if (chptr->mode.floodprot && !IsULine(sptr) &&
179 	    do_chanflood(chptr->mode.floodprot, FLD_KNOCK) && MyClient(sptr))
180 		do_chanflood_action(chptr, FLD_KNOCK, "knock");
181 #endif
182 	return 0;
183 }
184