]>
Commit | Line | Data |
---|---|---|
1 | centralize mode checks for +c (no control codes) and +C (no CTCPs) | |
2 | ||
3 | add client_can_send_controlcode_or_ctcp_to_channel() function in channel.c | |
4 | and use that (2x ircd_relay.c, m_wallchops.c, m_wallvoices.c), instead of duplicating code 4 times | |
5 | function uses a table to check for control codes, which is faster than what was used before | |
6 | also corrects that an error is returned in WALLVOICES and WALLCHOPS in case +c or +C blocks the message, which is also done for other modes there | |
7 | also corrects that CTCP ACTION is only allowed for PRIVMSG, and not for NOTICE WALLCHOPS and WALLVOICES | |
8 | ||
9 | diff -r 8567e020893c include/channel.h | |
10 | --- a/include/channel.h Thu Mar 25 13:10:37 2010 +0100 | |
11 | +++ b/include/channel.h Thu Mar 25 13:25:55 2010 +0100 | |
12 | @@ -398,6 +398,7 @@ | |
13 | extern struct Membership* find_channel_member(struct Client* cptr, struct Channel* chptr); | |
14 | extern int member_can_send_to_channel(struct Membership* member, int reveal); | |
15 | extern int client_can_send_to_channel(struct Client *cptr, struct Channel *chptr, int reveal); | |
16 | +extern int client_can_send_controlcode_or_ctcp_to_channel(struct Client *cptr, struct Channel *chptr, const char *text, int action); | |
17 | ||
18 | extern void remove_user_from_channel(struct Client *sptr, struct Channel *chptr); | |
19 | extern void remove_user_from_all_channels(struct Client* cptr); | |
20 | diff -r 8567e020893c ircd/channel.c | |
21 | --- a/ircd/channel.c Thu Mar 25 13:10:37 2010 +0100 | |
22 | +++ b/ircd/channel.c Thu Mar 25 13:25:55 2010 +0100 | |
23 | @@ -778,6 +778,68 @@ | |
24 | return member_can_send_to_channel(member, reveal); | |
25 | } | |
26 | ||
27 | +/** Table with control chars that should be blocked by chanmode +c | |
28 | + * | |
29 | + * codes: bold 2, colour 3, reverse 22, ansi escape 27, underline 31 | |
30 | + * | |
31 | + */ | |
32 | +static int control_codes[256] = { | |
33 | + 0, 0, 1, 1, 0, 0, 0, 0, | |
34 | + 0, 0, 0, 0, 0, 0, 0, 0, | |
35 | + 0, 0, 0, 0, 0, 0, 1, 0, | |
36 | + 0, 0, 0, 1, 0, 0, 0, 1, | |
37 | +}; | |
38 | + | |
39 | +/** Check if a client can send control codes or CTCP to a channel | |
40 | + * | |
41 | + * @param cptr The client to check | |
42 | + * @param chptr The channel to check | |
43 | + * @param text The text to check for control codes and/or CTCP chars | |
44 | + * @param action When 1 allow CTCP ACTION (for PRIVMSG), | |
45 | + * else dont allow (for NOTICE, WALLCHOPS, and WALLVOICES) | |
46 | + * | |
47 | + * @returns true if the client is allowed to speak on the channel, false | |
48 | + * otherwise | |
49 | + * | |
50 | + */ | |
51 | +int client_can_send_controlcode_or_ctcp_to_channel(struct Client *cptr, struct Channel *chptr, const char *text, int action) | |
52 | +{ | |
53 | + int control = 0, ctcp = 0; | |
54 | + const unsigned char *chr; | |
55 | + | |
56 | + assert(0 != cptr); | |
57 | + assert(0 != chptr); | |
58 | + | |
59 | + /* dont check this for remote users or servers - fail safe */ | |
60 | + if (!MyUser(cptr) || IsServer(cptr)) | |
61 | + return 1; | |
62 | + | |
63 | + /* mode +c set */ | |
64 | + if (chptr->mode.mode & MODE_NOCOLOUR) | |
65 | + control = 1; | |
66 | + | |
67 | + /* mode +C set */ | |
68 | + if (chptr->mode.mode & MODE_NOCTCP) { | |
69 | + ctcp = 1; | |
70 | + | |
71 | + /* when action is 1, do allow CTCP ACTION though */ | |
72 | + if (action && !ircd_strncmp(text,"\001ACTION ",8)) | |
73 | + ctcp = 0; | |
74 | + } | |
75 | + | |
76 | + /* nothing to check */ | |
77 | + if (!control && !ctcp) | |
78 | + return 1; | |
79 | + | |
80 | + /* search for control codes and/or CTCP chars */ | |
81 | + for (chr=text;*chr;chr++) { | |
82 | + if ((ctcp && *chr==1) || (control && control_codes[*chr])) | |
83 | + return 0; | |
84 | + } | |
85 | + | |
86 | + return 1; | |
87 | +} | |
88 | + | |
89 | /** Returns the name of a channel that prevents the user from changing nick. | |
90 | * if a member and not (opped or voiced) and (banned or moderated), return | |
91 | * the name of the first channel banned on. | |
92 | diff -r 8567e020893c ircd/ircd_relay.c | |
93 | --- a/ircd/ircd_relay.c Thu Mar 25 13:10:37 2010 +0100 | |
94 | +++ b/ircd/ircd_relay.c Thu Mar 25 13:25:55 2010 +0100 | |
95 | @@ -87,7 +87,6 @@ | |
96 | void relay_channel_message(struct Client* sptr, const char* name, const char* text, const int targetc) | |
97 | { | |
98 | struct Channel* chptr; | |
99 | - const char *ch; | |
100 | assert(0 != sptr); | |
101 | assert(0 != name); | |
102 | assert(0 != text); | |
103 | @@ -111,19 +110,10 @@ | |
104 | } | |
105 | ||
106 | /* +cC checks */ | |
107 | - if (chptr->mode.mode & MODE_NOCOLOUR) | |
108 | - for (ch=text;*ch;ch++) | |
109 | - if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31) { | |
110 | - send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname); | |
111 | - return; | |
112 | - } | |
113 | - | |
114 | - if ((chptr->mode.mode & MODE_NOCTCP) && ircd_strncmp(text,"\001ACTION ",8)) | |
115 | - for (ch=text;*ch;) | |
116 | - if (*ch++==1) { | |
117 | - send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname); | |
118 | - return; | |
119 | - } | |
120 | + if (!client_can_send_controlcode_or_ctcp_to_channel(sptr, chptr, text, 1)) { | |
121 | + send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname); | |
122 | + return; | |
123 | + } | |
124 | ||
125 | if ((chptr->mode.mode & MODE_NOPRIVMSGS) && | |
126 | check_target_limit(sptr, chptr, chptr->chname, 0)) | |
127 | @@ -144,7 +134,6 @@ | |
128 | void relay_channel_notice(struct Client* sptr, const char* name, const char* text, const int targetc) | |
129 | { | |
130 | struct Channel* chptr; | |
131 | - const char *ch; | |
132 | assert(0 != sptr); | |
133 | assert(0 != name); | |
134 | assert(0 != text); | |
135 | @@ -165,15 +154,8 @@ | |
136 | return; | |
137 | ||
138 | /* +cC checks */ | |
139 | - if (chptr->mode.mode & MODE_NOCOLOUR) | |
140 | - for (ch=text;*ch;ch++) | |
141 | - if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31) | |
142 | - return; | |
143 | - | |
144 | - if (chptr->mode.mode & MODE_NOCTCP) | |
145 | - for (ch=text;*ch;) | |
146 | - if (*ch++==1) | |
147 | - return; | |
148 | + if (!client_can_send_controlcode_or_ctcp_to_channel(sptr, chptr, text, 0)) | |
149 | + return; | |
150 | ||
151 | if ((chptr->mode.mode & MODE_NOPRIVMSGS) && | |
152 | check_target_limit(sptr, chptr, chptr->chname, 0)) | |
153 | diff -r 8567e020893c ircd/m_wallchops.c | |
154 | --- a/ircd/m_wallchops.c Thu Mar 25 13:10:37 2010 +0100 | |
155 | +++ b/ircd/m_wallchops.c Thu Mar 25 13:25:55 2010 +0100 | |
156 | @@ -103,7 +103,6 @@ | |
157 | { | |
158 | struct Channel *chptr; | |
159 | struct Membership* member; | |
160 | - const char *ch; | |
161 | ||
162 | assert(0 != cptr); | |
163 | assert(cptr == sptr); | |
164 | @@ -117,20 +116,9 @@ | |
165 | return send_reply(sptr, ERR_NOTEXTTOSEND); | |
166 | ||
167 | if (IsChannelName(parv[1]) && (chptr = FindChannel(parv[1]))) { | |
168 | - if (client_can_send_to_channel(sptr, chptr, 0) && !(chptr->mode.mode & MODE_NONOTICE)) { | |
169 | - | |
170 | - /* +cC checks */ | |
171 | - if (chptr->mode.mode & MODE_NOCOLOUR) | |
172 | - for (ch=parv[parc - 1];*ch;ch++) | |
173 | - if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31) { | |
174 | - return 0; | |
175 | - } | |
176 | - | |
177 | - if ((chptr->mode.mode & MODE_NOCTCP) && ircd_strncmp(parv[parc - 1],"\001ACTION ",8)) | |
178 | - for (ch=parv[parc - 1];*ch;) | |
179 | - if (*ch++==1) { | |
180 | - return 0; | |
181 | - } | |
182 | + if (client_can_send_to_channel(sptr, chptr, 0) && | |
183 | + !(chptr->mode.mode & MODE_NONOTICE) && /* +N check */ | |
184 | + (client_can_send_controlcode_or_ctcp_to_channel(sptr, chptr, parv[parc - 1], 0))) { /* +cC checks */ | |
185 | ||
186 | if ((chptr->mode.mode & MODE_NOPRIVMSGS) && | |
187 | check_target_limit(sptr, chptr, chptr->chname, 0)) | |
188 | diff -r 8567e020893c ircd/m_wallvoices.c | |
189 | --- a/ircd/m_wallvoices.c Thu Mar 25 13:10:37 2010 +0100 | |
190 | +++ b/ircd/m_wallvoices.c Thu Mar 25 13:25:55 2010 +0100 | |
191 | @@ -102,7 +102,6 @@ | |
192 | { | |
193 | struct Channel *chptr; | |
194 | struct Membership* member; | |
195 | - const char *ch; | |
196 | ||
197 | assert(0 != cptr); | |
198 | assert(cptr == sptr); | |
199 | @@ -116,20 +115,9 @@ | |
200 | return send_reply(sptr, ERR_NOTEXTTOSEND); | |
201 | ||
202 | if (IsChannelName(parv[1]) && (chptr = FindChannel(parv[1]))) { | |
203 | - if (client_can_send_to_channel(sptr, chptr, 0) && !(chptr->mode.mode & MODE_NONOTICE)) { | |
204 | - | |
205 | - /* +cC checks */ | |
206 | - if (chptr->mode.mode & MODE_NOCOLOUR) | |
207 | - for (ch=parv[parc - 1];*ch;ch++) | |
208 | - if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31) { | |
209 | - return 0; | |
210 | - } | |
211 | - | |
212 | - if ((chptr->mode.mode & MODE_NOCTCP) && ircd_strncmp(parv[parc - 1],"\001ACTION ",8)) | |
213 | - for (ch=parv[parc - 1];*ch;) | |
214 | - if (*ch++==1) { | |
215 | - return 0; | |
216 | - } | |
217 | + if (client_can_send_to_channel(sptr, chptr, 0) && | |
218 | + !(chptr->mode.mode & MODE_NONOTICE) && /* +N check */ | |
219 | + (client_can_send_controlcode_or_ctcp_to_channel(sptr, chptr, parv[parc - 1], 0))) { /* +cC checks */ | |
220 | ||
221 | if ((chptr->mode.mode & MODE_NOPRIVMSGS) && | |
222 | check_target_limit(sptr, chptr, chptr->chname, 0)) |