1 centralize mode checks for +c (no control codes) and +C (no CTCPs)
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 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
6 function loops over the text one time to check for control codes or CTCP chars, instead of twice as the old code did
8 diff -r 833a280b9406 include/channel.h
9 --- a/include/channel.h Sat Mar 20 15:42:02 2010 +0100
10 +++ b/include/channel.h Sat Mar 20 17:08:49 2010 +0100
12 extern struct Membership* find_channel_member(struct Client* cptr, struct Channel* chptr);
13 extern int member_can_send_to_channel(struct Membership* member, int reveal);
14 extern int client_can_send_to_channel(struct Client *cptr, struct Channel *chptr, int reveal);
15 +extern int client_can_send_controlcode_or_ctcp_to_channel(struct Client *cptr, struct Channel *chptr, const char *text, int action);
17 extern void remove_user_from_channel(struct Client *sptr, struct Channel *chptr);
18 extern void remove_user_from_all_channels(struct Client* cptr);
19 diff -r 833a280b9406 ircd/channel.c
20 --- a/ircd/channel.c Sat Mar 20 15:42:02 2010 +0100
21 +++ b/ircd/channel.c Sat Mar 20 17:08:49 2010 +0100
23 return member_can_send_to_channel(member, reveal);
26 +/** Check if a client can send control codes or CTCP to a channel
28 + * @param cptr The client to check
29 + * @param chptr The channel to check
30 + * @param text The text to check for control codes and/or CTCP chars
31 + * @param action When 1 allow CTCP ACTION (for PRIVMSG),
32 + * else dont allow (for NOTICE, WALLCHOPS, and WALLVOICES)
34 + * @returns true if the client is allowed to speak on the channel, false
38 +int client_can_send_controlcode_or_ctcp_to_channel(struct Client *cptr, struct Channel *chptr, const char *text, int action)
40 + int control = 0, ctcp = 0;
43 + /* dont check this for remote users or servers - fail safe */
44 + if (!MyUser(cptr) || IsServer(cptr))
48 + if (chptr->mode.mode & MODE_NOCOLOUR)
51 + /* mode +C set - do allow CTCP ACTION though but only when action is 1 */
52 + if ((chptr->mode.mode & MODE_NOCTCP) && (!action || ircd_strncmp(text,"\001ACTION ",8)))
55 + /* nothing to check */
56 + if (!control && !ctcp)
59 + /* search for control codes and/or CTCP chars */
60 + for (chr=text;*chr;chr++) {
61 + if ((ctcp && *chr==1) || ((control) && (*chr==2 || *chr==3 || *chr==22 || *chr==27 || *chr==31)))
68 /** Returns the name of a channel that prevents the user from changing nick.
69 * if a member and not (opped or voiced) and (banned or moderated), return
70 * the name of the first channel banned on.
71 diff -r 833a280b9406 ircd/ircd_relay.c
72 --- a/ircd/ircd_relay.c Sat Mar 20 15:42:02 2010 +0100
73 +++ b/ircd/ircd_relay.c Sat Mar 20 17:08:49 2010 +0100
75 void relay_channel_message(struct Client* sptr, const char* name, const char* text, const int targetc)
77 struct Channel* chptr;
86 - if (chptr->mode.mode & MODE_NOCOLOUR)
87 - for (ch=text;*ch;ch++)
88 - if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31) {
89 - send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
93 - if ((chptr->mode.mode & MODE_NOCTCP) && ircd_strncmp(text,"\001ACTION ",8))
96 - send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
99 + if (!client_can_send_controlcode_or_ctcp_to_channel(sptr, chptr, text, 1)) {
100 + send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
104 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
105 check_target_limit(sptr, chptr, chptr->chname, 0))
107 void relay_channel_notice(struct Client* sptr, const char* name, const char* text, const int targetc)
109 struct Channel* chptr;
118 - if (chptr->mode.mode & MODE_NOCOLOUR)
119 - for (ch=text;*ch;ch++)
120 - if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31)
123 - if (chptr->mode.mode & MODE_NOCTCP)
127 + if (!client_can_send_controlcode_or_ctcp_to_channel(sptr, chptr, text, 0))
130 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
131 check_target_limit(sptr, chptr, chptr->chname, 0))
132 diff -r 833a280b9406 ircd/m_wallchops.c
133 --- a/ircd/m_wallchops.c Sat Mar 20 15:42:02 2010 +0100
134 +++ b/ircd/m_wallchops.c Sat Mar 20 17:08:49 2010 +0100
137 struct Channel *chptr;
138 struct Membership* member;
142 assert(cptr == sptr);
144 return send_reply(sptr, ERR_NOTEXTTOSEND);
146 if (IsChannelName(parv[1]) && (chptr = FindChannel(parv[1]))) {
147 - if (client_can_send_to_channel(sptr, chptr, 0) && !(chptr->mode.mode & MODE_NONOTICE)) {
150 - if (chptr->mode.mode & MODE_NOCOLOUR)
151 - for (ch=parv[parc - 1];*ch;ch++)
152 - if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31) {
156 - if ((chptr->mode.mode & MODE_NOCTCP) && ircd_strncmp(parv[parc - 1],"\001ACTION ",8))
157 - for (ch=parv[parc - 1];*ch;)
161 + if (client_can_send_to_channel(sptr, chptr, 0) &&
162 + !(chptr->mode.mode & MODE_NONOTICE) && /* +N check */
163 + (client_can_send_controlcode_or_ctcp_to_channel(sptr, chptr, parv[parc - 1], 0))) { /* +cC checks */
165 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
166 check_target_limit(sptr, chptr, chptr->chname, 0))
167 diff -r 833a280b9406 ircd/m_wallvoices.c
168 --- a/ircd/m_wallvoices.c Sat Mar 20 15:42:02 2010 +0100
169 +++ b/ircd/m_wallvoices.c Sat Mar 20 17:08:49 2010 +0100
172 struct Channel *chptr;
173 struct Membership* member;
177 assert(cptr == sptr);
179 return send_reply(sptr, ERR_NOTEXTTOSEND);
181 if (IsChannelName(parv[1]) && (chptr = FindChannel(parv[1]))) {
182 - if (client_can_send_to_channel(sptr, chptr, 0) && !(chptr->mode.mode & MODE_NONOTICE)) {
185 - if (chptr->mode.mode & MODE_NOCOLOUR)
186 - for (ch=parv[parc - 1];*ch;ch++)
187 - if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31) {
191 - if ((chptr->mode.mode & MODE_NOCTCP) && ircd_strncmp(parv[parc - 1],"\001ACTION ",8))
192 - for (ch=parv[parc - 1];*ch;)
196 + if (client_can_send_to_channel(sptr, chptr, 0) &&
197 + !(chptr->mode.mode & MODE_NONOTICE) && /* +N check */
198 + (client_can_send_controlcode_or_ctcp_to_channel(sptr, chptr, parv[parc - 1], 0))) { /* +cC checks */
200 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
201 check_target_limit(sptr, chptr, chptr->chname, 0))