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