]> jfr.im git - irc/quakenet/snircd-patchqueue.git/blame - cansendtochan.patch
done some work on cansendtochan.patch, added nserverflag.patch, and probably some...
[irc/quakenet/snircd-patchqueue.git] / cansendtochan.patch
CommitLineData
65b70298 1attempt to move checks for chanmodes c C N T u into
2the *_can_send_to_channel() functions in channel.c where ircu by default has its chanmode checks
3
4instead of having them in each of the places used (m_wallchops, m_wallvoices, ircd_relay.c, etc.)
5not tested completely
6
7client_can_send_to_channel()
8and
9member_can_send_to_channel()
65b70298 10
7efbed3b 11move our cCNT mode checks to new function can_send_to_channel() used
12from the two functions above
13now the checks for cCNT modes are in one place.
14check for +u remains in member_can_send_to_chan() - as quit from non-member does not show
15
16need to verify handling of remote users, services, servers etc.
17
18possible problem discovered (ircu):
65b70298 19in some places *_can_send_to_channel() is first called with reveal delayedjoin user ON
20but the code then proceeds to check target limits, which upon refusal means the delayedjoin
7efbed3b 21user is revealed (locally) without actually sending anything to the channel...
22...that seems wrong/weird
65b70298 23
7efbed3b 24diff -r 7113a0179d71 include/channel.h
25--- a/include/channel.h Wed Jan 21 16:44:50 2009 +0100
26+++ b/include/channel.h Wed Jan 21 17:13:44 2009 +0100
65b70298 27@@ -103,9 +103,9 @@
28 #define MODE_DELJOINS 0x1000 /**< New join messages are delayed */
29 #define MODE_REGISTERED 0x2000 /**< Channel marked as registered
30 * (for future semantic expansion) */
31-#define MODE_NOCOLOUR 0x4000 /**< No mIRC/ANSI colors/bold */
32-#define MODE_NOCTCP 0x8000 /**< No channel CTCPs */
33-#define MODE_NONOTICE 0x10000 /**< No channel notices */
34+#define MODE_NOCOLOUR 0x4000 /**< +c No mIRC/ANSI colors/bold */
35+#define MODE_NOCTCP 0x8000 /**< +C No channel CTCPs */
36+#define MODE_NONOTICE 0x10000 /**< +N No channel notices */
37 #define MODE_SAVE 0x20000 /**< save this mode-with-arg 'til
38 * later */
39 #define MODE_FREE 0x40000 /**< string needs to be passed to
40@@ -115,7 +115,7 @@
41 #define MODE_APASS 0x200000
42 #define MODE_WASDELJOINS 0x400000 /**< Not DELJOINS, but some joins
43 * pending */
44-#define MODE_NOQUITPARTS 0x800000
45+#define MODE_NOQUITPARTS 0x800000 /**< +u No user defined quit or part messages */
46
47 #define MODE_NOMULTITARGET 0x1000000 /**< +T No multiple targets */
48 #define MODE_MODERATENOREG 0x2000000 /**< +M Moderate unauthed users */
49@@ -396,8 +396,10 @@
50
51 extern const char* find_no_nickchange_channel(struct Client* cptr);
52 extern struct Membership* find_channel_member(struct Client* cptr, struct Channel* chptr);
53-extern int member_can_send_to_channel(struct Membership* member, int reveal);
54-extern int client_can_send_to_channel(struct Client *cptr, struct Channel *chptr, int reveal);
55+extern int member_can_send_to_channel(struct Membership* member, int reveal,
56+ unsigned int flags, const char *text, const int target);
57+extern int client_can_send_to_channel(struct Client *cptr, struct Channel *chptr,
58+ int reveal, unsigned int flags, const char *text, const int target);
59
60 extern void remove_user_from_channel(struct Client *sptr, struct Channel *chptr);
61 extern void remove_user_from_all_channels(struct Client* cptr);
7efbed3b 62diff -r 7113a0179d71 ircd/channel.c
63--- a/ircd/channel.c Wed Jan 21 16:44:50 2009 +0100
64+++ b/ircd/channel.c Wed Jan 21 17:13:44 2009 +0100
65@@ -681,10 +681,14 @@
65b70298 66 * @param member The membership of the user
67 * @param reveal If true, the user will be "revealed" on a delayed
68 * joined channel.
69+ * @param flags The bitmask of additional modes to check (besides +n +m +r +M +b)
70+ * @param text The message from the user, needed for modes +c and +C
71+ * @param target The number of targets the message is sent to, for +T
72 *
73 * @returns True if the client can speak on the channel.
74 */
75-int member_can_send_to_channel(struct Membership* member, int reveal)
76+int member_can_send_to_channel(struct Membership* member, int reveal,
77+ unsigned int flags, const char *text, const int target)
78 {
65b70298 79 assert(0 != member);
65b70298 80
7efbed3b 81@@ -692,15 +696,17 @@
65b70298 82 * temporary desynch, or maybe they are on an older server, but
83 * we do not want to send ERR_CANNOTSENDTOCHAN more than once.
84 */
85- if (!MyUser(member->user))
86- {
65b70298 87+ /* client on service server (+s) - let it through */
88+ if (IsService(cli_user(member->user)->server)) {
89 if (IsDelayedJoin(member) && reveal)
90 RevealDelayedJoin(member);
91 return 1;
92 }
7efbed3b 93-
94- /* +X user can always speak on the channel */
95+
96+ /* +X exclude +X clients from modes +mMR and bans */
97 if (IsXtraOp(member->user)) {
98+ if (!can_send_to_channel(member->user, member->channel, flags, text, target))
99+ return 0;
100 if (IsDelayedJoin(member) && reveal)
101 RevealDelayedJoin(member);
102 return 1;
103@@ -712,7 +718,7 @@
65b70298 104
7efbed3b 105 /* If you have voice or ops, you can speak. */
106 if (IsVoicedOrOpped(member))
65b70298 107- return 1;
7efbed3b 108+ return can_send_to_channel(member->user, member->channel, flags, text, target);
65b70298 109
7efbed3b 110 /*
111 * If it's moderated, and you aren't a privileged user, you can't
112@@ -727,6 +733,23 @@
65b70298 113
7efbed3b 114 /* If you're banned then you can't speak either. */
115 if (is_banned(member))
116+ return 0;
65b70298 117+
7efbed3b 118+ /* enough checked for remote users */
119+ if (!MyUser(member->user)) {
120+ if (IsDelayedJoin(member) && reveal)
121+ RevealDelayedJoin(member);
122+ return 1;
123+ }
65b70298 124+
7efbed3b 125+ /* +u check for user defined quit and part messages,
126+ * and they are not allowed
127+ */
128+ if ((flags & MODE_NOQUITPARTS) && (member->channel->mode.mode & MODE_NOQUITPARTS))
129+ return 0;
65b70298 130+
7efbed3b 131+ /* check various other modes (like cCNT) */
132+ if (!can_send_to_channel(member->user, member->channel, flags, text, target))
133 return 0;
65b70298 134
135 if (IsDelayedJoin(member) && reveal)
7efbed3b 136@@ -744,16 +767,22 @@
65b70298 137 * @param chptr The channel to check
138 * @param reveal If the user should be revealed (see
139 * member_can_send_to_channel())
140+ * @param flags The bitmask of additional modes to check (besides +n +m +r +M +b)
141+ * @param text The message needed to check for +c and +C
142+ * @param target The number of targets the message is sent to, for +T
143 *
144 * @returns true if the client is allowed to speak on the channel, false
145 * otherwise
146 *
147 * @see member_can_send_to_channel()
148 */
149-int client_can_send_to_channel(struct Client *cptr, struct Channel *chptr, int reveal)
150+int client_can_send_to_channel(struct Client *cptr, struct Channel *chptr, int reveal,
151+ unsigned int flags, const char *text, const int target)
152 {
153 struct Membership *member;
154- assert(0 != cptr);
65b70298 155+
156+ assert(0 != cptr);
157+
158 /*
159 * Servers can always speak on channels.
160 */
7efbed3b 161@@ -767,15 +796,90 @@
65b70298 162 * or +m (moderated).
65b70298 163 */
164 if (!member) {
165- if (IsXtraOp(cptr))
166+ /* client on service server (+s) - let it through */
167+ if (IsService(cli_user(cptr)->server))
168 return 1;
169- else if ((chptr->mode.mode & (MODE_NOPRIVMSGS|MODE_MODERATED)) ||
170- ((chptr->mode.mode & (MODE_REGONLY|MODE_MODERATENOREG)) && !IsAccount(cptr)))
7efbed3b 171+ /* client with umode +X exempt from modes +nmrM and bans */
65b70298 172+ if (!IsXtraOp(cptr)) {
7efbed3b 173+ if ((chptr->mode.mode & (MODE_NOPRIVMSGS|MODE_MODERATED)) ||
174+ ((chptr->mode.mode & (MODE_REGONLY|MODE_MODERATENOREG)) && !IsAccount(cptr)))
65b70298 175+ return 0;
176+ if (find_ban(cptr, chptr->banlist))
177+ return 0;
178+ }
7efbed3b 179+ /* check various other modes (like cCNT) */
180+ if (!can_send_to_channel(cptr, chptr, flags, text, target))
65b70298 181 return 0;
182- else
183- return !find_ban(cptr, chptr->banlist);
7efbed3b 184 }
185- return member_can_send_to_channel(member, reveal);
186+ return member_can_send_to_channel(member, reveal, flags, text, target);
187+}
65b70298 188+
7efbed3b 189+/** Check if a client can send to a channel.
190+ *
191+ * These checks are done for both clients on and off the channel.
192+ *
193+ * @param cptr The client to check
194+ * @param chptr The channel to check
195+ * @param flags The bitmask of modes to check
196+ * @param text The message needed to check for +c and +C
197+ * @param target The number of targets the message is sent to, for +T
198+ *
199+ * @returns true if the client is allowed to speak on the channel, false
200+ * otherwise
201+ *
202+ * @see client_can_send_to_channel()
203+ * @see member_can_send_to_channel()
204+ */
205+int can_send_to_channel(struct Client *cptr, struct Channel *chptr,
206+ unsigned int flags, const char *text, const int target)
207+{
208+ const char *ch;
209+ unsigned int modes;
210+ int controlcodes = 0;
211+
212+ assert(0 != cptr);
213+ assert(0 != chptr);
214+
215+ modes = chptr->mode.mode;
216+
217+ /* only check these modes on local users */
218+ if (!MyUser(cptr))
219+ return 1;
220+
221+ /* +T check for multi target message and they are not allowed */
222+ if ((flags & MODE_NOMULTITARGET) && (modes & MODE_NOMULTITARGET) &&
223+ target > 1)
224+ return 0;
225+
226+ /* +N check for channel wide notice and they are not allowed */
227+ if ((flags & MODE_NONOTICE) && (modes & MODE_NONOTICE))
228+ return 0;
65b70298 229+
7efbed3b 230+ /* these last two checks should always be last
231+ * as they loop over the entire message in search for
232+ * CTCP char and control codes
233+ */
234+ /* +C check for CTCP and CTCPs are not allowed */
235+ if ((flags & MODE_NOCTCP) && (modes & MODE_NOCTCP) && (text != NULL) &&
236+ ircd_strncmp(text,"\001ACTION ",8)) {
237+ for (ch=text;*ch;) {
238+ if (*ch++==1)
239+ return 0;
240+ if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31)
241+ controlcodes = 1;
65b70298 242+ }
7efbed3b 243+ }
65b70298 244+
7efbed3b 245+ /* +c check for control codes and they are not allowed */
246+ if ((flags & MODE_NOCOLOUR) && (modes & MODE_NOCOLOUR) && (text != NULL)) {
247+ if (controlcodes) /* already found control codes */
248+ return 0;
249+ for (ch=text;*ch;ch++) {
250+ if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31)
65b70298 251+ return 0;
65b70298 252+ }
7efbed3b 253+ }
254+ return 1;
65b70298 255 }
256
257 /** Returns the name of a channel that prevents the user from changing nick.
7efbed3b 258@@ -3625,13 +3729,11 @@
65b70298 259 /* Send notification to channel */
260 if (!(flags & (CHFL_ZOMBIE | CHFL_DELAYED)))
261 sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_PART, chan, NULL, 0,
262- ((flags & CHFL_BANNED) || ((chan->mode.mode & MODE_NOQUITPARTS)
263- && !IsChannelService(member->user)) || !jbuf->jb_comment) ?
264+ ((flags & CHFL_BANNED) || !jbuf->jb_comment) ?
265 "%H" : "%H :%s", chan, jbuf->jb_comment);
266 else if (MyUser(jbuf->jb_source))
267 sendcmdto_one(jbuf->jb_source, CMD_PART, jbuf->jb_source,
268- ((flags & CHFL_BANNED) || (chan->mode.mode & MODE_NOQUITPARTS)
269- || !jbuf->jb_comment) ?
270+ ((flags & CHFL_BANNED) || !jbuf->jb_comment) ?
271 ":%H" : "%H :%s", chan, jbuf->jb_comment);
272 /* XXX: Shouldn't we send a PART here anyway? */
273 /* to users on the channel? Why? From their POV, the user isn't on
7efbed3b 274diff -r 7113a0179d71 ircd/ircd_relay.c
275--- a/ircd/ircd_relay.c Wed Jan 21 16:44:50 2009 +0100
276+++ b/ircd/ircd_relay.c Wed Jan 21 17:13:44 2009 +0100
65b70298 277@@ -87,7 +87,6 @@
278 void relay_channel_message(struct Client* sptr, const char* name, const char* text, const int targetc)
279 {
280 struct Channel* chptr;
281- const char *ch;
282 assert(0 != sptr);
283 assert(0 != name);
284 assert(0 != text);
285@@ -99,35 +98,19 @@
286 /*
287 * This first: Almost never a server/service
288 */
289- if (!client_can_send_to_channel(sptr, chptr, 1)) {
290+ if (!client_can_send_to_channel(sptr, chptr, 1,
291+ (MODE_NOCOLOUR | MODE_NOCTCP | MODE_NOMULTITARGET), text, targetc)) {
292 send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
293 return;
294 }
295+ /* TODO: what is this again?
7efbed3b 296+ * client_can_send_to_channel already reveals delayed join user
65b70298 297+ * locally anyway, and now the message gets denied?
298+ * hmm...
299+ */
300 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
301 check_target_limit(sptr, chptr, chptr->chname, 0))
302 return;
303-
304- /* +T check */
305- if ((chptr->mode.mode & MODE_NOMULTITARGET) && (targetc > 1)) {
306- send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
307- return;
308- }
309-
310- /* +cC checks */
311- if (chptr->mode.mode & MODE_NOCOLOUR)
312- for (ch=text;*ch;ch++)
313- if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31) {
314- send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
315- return;
316- }
317-
318- if ((chptr->mode.mode & MODE_NOCTCP) && ircd_strncmp(text,"\001ACTION ",8))
319- for (ch=text;*ch;)
320- if (*ch++==1) {
321- send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
322- return;
323- }
324-
325
326 sendcmdto_channel_butone(sptr, CMD_PRIVATE, chptr, cli_from(sptr),
327 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
328@@ -143,7 +126,6 @@
329 void relay_channel_notice(struct Client* sptr, const char* name, const char* text, const int targetc)
330 {
331 struct Channel* chptr;
332- const char *ch;
333 assert(0 != sptr);
334 assert(0 != name);
335 assert(0 != text);
336@@ -153,30 +135,14 @@
337 /*
338 * This first: Almost never a server/service
339 */
340- if (!client_can_send_to_channel(sptr, chptr, 1))
341+ if (!client_can_send_to_channel(sptr, chptr, 1,
342+ (MODE_NONOTICE | MODE_NOCOLOUR | MODE_NOCTCP | MODE_NOMULTITARGET), text, targetc))
343 return;
344
345+ /* TODO: idem as in previous function */
346 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
347 check_target_limit(sptr, chptr, chptr->chname, 0))
348 return;
349-
350- if ((chptr->mode.mode & MODE_NONOTICE))
351- return;
352-
353- /* +T check */
354- if ((chptr->mode.mode & MODE_NOMULTITARGET) && (targetc > 1))
355- return;
356-
357- /* +cC checks */
358- if (chptr->mode.mode & MODE_NOCOLOUR)
359- for (ch=text;*ch;ch++)
360- if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31)
361- return;
362-
363- if (chptr->mode.mode & MODE_NOCTCP)
364- for (ch=text;*ch;)
365- if (*ch++==1)
366- return;
367
368 sendcmdto_channel_butone(sptr, CMD_NOTICE, chptr, cli_from(sptr),
369 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
370@@ -204,7 +170,7 @@
371 * This first: Almost never a server/service
372 * Servers may have channel services, need to check for it here
373 */
374- if (client_can_send_to_channel(sptr, chptr, 1) || IsChannelService(sptr)) {
375+ if (client_can_send_to_channel(sptr, chptr, 1, 0, NULL, 1)) {
376 sendcmdto_channel_butone(sptr, CMD_PRIVATE, chptr, cli_from(sptr),
377 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
378 }
379@@ -232,7 +198,8 @@
380 * This first: Almost never a server/service
381 * Servers may have channel services, need to check for it here
382 */
383- if (client_can_send_to_channel(sptr, chptr, 1) || IsChannelService(sptr)) {
384+ /* TODO: check how we get here */
385+ if (client_can_send_to_channel(sptr, chptr, 1, 0, NULL, 1)) {
386 sendcmdto_channel_butone(sptr, CMD_NOTICE, chptr, cli_from(sptr),
387 SKIP_DEAF | SKIP_BURST, "%H :%s", chptr, text);
388 }
7efbed3b 389diff -r 7113a0179d71 ircd/m_part.c
390--- a/ircd/m_part.c Wed Jan 21 16:44:50 2009 +0100
391+++ b/ircd/m_part.c Wed Jan 21 17:13:44 2009 +0100
65b70298 392@@ -140,7 +140,8 @@
393
394 assert(!IsZombie(member)); /* Local users should never zombie */
395
396- if (!member_can_send_to_channel(member, 0))
397+ /* check +u here or later somewhere in channel.c ? */
398+ if (!member_can_send_to_channel(member, 0, MODE_NOQUITPARTS, NULL, 1))
399 {
400 flags |= CHFL_BANNED;
401 /* Remote clients don't want to see a comment either. */
7efbed3b 402diff -r 7113a0179d71 ircd/m_quit.c
403--- a/ircd/m_quit.c Wed Jan 21 16:44:50 2009 +0100
404+++ b/ircd/m_quit.c Wed Jan 21 17:13:44 2009 +0100
65b70298 405@@ -109,8 +109,8 @@
406 struct Membership* chan;
407 /* (slug for +u) removed !IsDelayedJoin(chan) as splidge said to */
408 for (chan = cli_user(sptr)->channel; chan; chan = chan->next_channel) {
409- if (!IsZombie(chan) && (!member_can_send_to_channel(chan, 0)
410- || (chan->channel->mode.mode & MODE_NOQUITPARTS)))
411+ if (!IsZombie(chan) && (!member_can_send_to_channel(chan, 0,
412+ MODE_NOQUITPARTS, NULL, 1)))
413 return exit_client(cptr, sptr, sptr, "Signed off");
414 }
415 }
7efbed3b 416diff -r 7113a0179d71 ircd/m_topic.c
417--- a/ircd/m_topic.c Wed Jan 21 16:44:50 2009 +0100
418+++ b/ircd/m_topic.c Wed Jan 21 17:13:44 2009 +0100
65b70298 419@@ -144,7 +144,7 @@
420 }
421 else if ((chptr->mode.mode & MODE_TOPICLIMIT) && !is_chan_op(sptr, chptr))
422 send_reply(sptr, ERR_CHANOPRIVSNEEDED, chptr->chname);
423- else if (!client_can_send_to_channel(sptr, chptr, 1))
424+ else if (!client_can_send_to_channel(sptr, chptr, 1, 0, NULL, 1))
425 send_reply(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname);
426 else
427 do_settopic(sptr,cptr,chptr,topic,0);
7efbed3b 428diff -r 7113a0179d71 ircd/m_wallchops.c
429--- a/ircd/m_wallchops.c Wed Jan 21 16:44:50 2009 +0100
430+++ b/ircd/m_wallchops.c Wed Jan 21 17:13:44 2009 +0100
65b70298 431@@ -103,7 +103,6 @@
432 {
433 struct Channel *chptr;
434 struct Membership* member;
435- const char *ch;
436
437 assert(0 != cptr);
438 assert(cptr == sptr);
439@@ -117,23 +116,12 @@
440 return send_reply(sptr, ERR_NOTEXTTOSEND);
441
442 if (IsChannelName(parv[1]) && (chptr = FindChannel(parv[1]))) {
443- if (client_can_send_to_channel(sptr, chptr, 0) && !(chptr->mode.mode & MODE_NONOTICE)) {
444+ /* check also for modes +N +c and +C */
445+ if (client_can_send_to_channel(sptr, chptr, 0,
446+ (MODE_NONOTICE | MODE_NOCOLOUR | MODE_NOCTCP), parv[parc - 1], 1)) {
447 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
448 check_target_limit(sptr, chptr, chptr->chname, 0))
449 return 0;
450-
451- /* +cC checks */
452- if (chptr->mode.mode & MODE_NOCOLOUR)
453- for (ch=parv[parc - 1];*ch;ch++)
454- if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31) {
455- return 0;
456- }
457-
458- if ((chptr->mode.mode & MODE_NOCTCP) && ircd_strncmp(parv[parc - 1],"\001ACTION ",8))
459- for (ch=parv[parc - 1];*ch;)
460- if (*ch++==1) {
461- return 0;
462- }
463
464 /* Reveal delayedjoin user */
465 if ((member = find_member_link(chptr, cptr)) && IsDelayedJoin(member))
466@@ -165,7 +153,7 @@
467 return 0;
468
469 if (!IsLocalChannel(parv[1]) && (chptr = FindChannel(parv[1]))) {
470- if (client_can_send_to_channel(sptr, chptr, 1)) {
471+ if (client_can_send_to_channel(sptr, chptr, 1, 0, NULL, 1)) {
472 sendcmdto_channel_butone(sptr, CMD_WALLCHOPS, chptr, cptr,
473 SKIP_DEAF | SKIP_BURST | SKIP_NONOPS,
474 "%H :%s", chptr, parv[parc - 1]);
7efbed3b 475diff -r 7113a0179d71 ircd/m_wallvoices.c
476--- a/ircd/m_wallvoices.c Wed Jan 21 16:44:50 2009 +0100
477+++ b/ircd/m_wallvoices.c Wed Jan 21 17:13:44 2009 +0100
65b70298 478@@ -102,7 +102,6 @@
479 {
480 struct Channel *chptr;
481 struct Membership* member;
482- const char *ch;
483
484 assert(0 != cptr);
485 assert(cptr == sptr);
486@@ -116,23 +115,11 @@
487 return send_reply(sptr, ERR_NOTEXTTOSEND);
488
489 if (IsChannelName(parv[1]) && (chptr = FindChannel(parv[1]))) {
490- if (client_can_send_to_channel(sptr, chptr, 0) && !(chptr->mode.mode & MODE_NONOTICE)) {
491+ if (client_can_send_to_channel(sptr, chptr, 0,
492+ (MODE_NONOTICE | MODE_NOCOLOUR | MODE_NOCTCP), parv[parc - 1], 1)) {
493 if ((chptr->mode.mode & MODE_NOPRIVMSGS) &&
494 check_target_limit(sptr, chptr, chptr->chname, 0))
495 return 0;
496-
497- /* +cC checks */
498- if (chptr->mode.mode & MODE_NOCOLOUR)
499- for (ch=parv[parc - 1];*ch;ch++)
500- if (*ch==2 || *ch==3 || *ch==22 || *ch==27 || *ch==31) {
501- return 0;
502- }
503-
504- if ((chptr->mode.mode & MODE_NOCTCP) && ircd_strncmp(parv[parc - 1],"\001ACTION ",8))
505- for (ch=parv[parc - 1];*ch;)
506- if (*ch++==1) {
507- return 0;
508- }
509
510 /* Reveal delayedjoin user */
511 if ((member = find_member_link(chptr, cptr)) && IsDelayedJoin(member))
512@@ -164,7 +151,7 @@
513 return 0;
514
515 if (!IsLocalChannel(parv[1]) && (chptr = FindChannel(parv[1]))) {
516- if (client_can_send_to_channel(sptr, chptr, 1)) {
517+ if (client_can_send_to_channel(sptr, chptr, 1, 0, NULL, 1)) {
518 sendcmdto_channel_butone(sptr, CMD_WALLVOICES, chptr, cptr,
519 SKIP_DEAF | SKIP_BURST | SKIP_NONVOICES,
520 "%H :%s", chptr, parv[parc - 1]);