summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--doc/modes.txt1
-rw-r--r--include/channel.h2
-rw-r--r--include/channel_mode.h1
-rw-r--r--include/numeric.h1
-rw-r--r--modules/core/m_message.c17
-rw-r--r--modules/core/m_part.c4
-rw-r--r--modules/core/m_sjoin.c3
-rw-r--r--src/channel.c41
-rw-r--r--src/channel_mode.c3
-rw-r--r--src/numeric.c4
11 files changed, 63 insertions, 17 deletions
diff --git a/NEWS b/NEWS
index 9e88239..a922229 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,9 @@
o) PCRE support has been dropped
o) "STATS o" now shows how many times an oper{} block has been used.
Similar to STATS x|q"
+o) Implemented channel mode +c. Known from other ircds, this mode basically
+ prevents users from sending messages including control codes to a channel
+ that has this mode set
-- ircd-hybrid-8.1.0beta2 Release Notes
diff --git a/doc/modes.txt b/doc/modes.txt
index 6902948..59c56b0 100644
--- a/doc/modes.txt
+++ b/doc/modes.txt
@@ -40,6 +40,7 @@ User Modes:
Channel Modes:
+b - ban - Channel ban on nick!user@host
++c - noctrls - Prevent users from sending messages containing control codes to the channel
+e - exempt - Exemption from bans
+I - invex - Invite exceptions, nick!user@host does not need to be
explicitly INVITE'd into the channel before being able
diff --git a/include/channel.h b/include/channel.h
index 564533e..8780dbe 100644
--- a/include/channel.h
+++ b/include/channel.h
@@ -115,7 +115,7 @@ struct Ban
extern dlink_list global_channel_list;
extern int check_channel_name(const char *, const int);
-extern int can_send(struct Channel *, struct Client *, struct Membership *);
+extern int can_send(struct Channel *, struct Client *, struct Membership *, const char *);
extern int is_banned(const struct Channel *, const struct Client *);
extern int can_join(struct Client *, struct Channel *, const char *);
extern int has_member_flags(const struct Membership *, const unsigned int);
diff --git a/include/channel_mode.h b/include/channel_mode.h
index 2bd8ce6..ec705a5 100644
--- a/include/channel_mode.h
+++ b/include/channel_mode.h
@@ -59,6 +59,7 @@
#define MODE_OPERONLY 0x0080
#define MODE_REGISTERED 0x0100 /* Channel has been registered with ChanServ */
#define MODE_REGONLY 0x0200
+#define MODE_NOCTRL 0x0400
/* cache flags for silence on ban */
#define CHFL_BAN_CHECKED 0x0080
diff --git a/include/numeric.h b/include/numeric.h
index fb5da3a..923c91c 100644
--- a/include/numeric.h
+++ b/include/numeric.h
@@ -180,6 +180,7 @@ extern const char *form_str(unsigned int);
#define ERR_TOOMANYCHANNELS 405
#define ERR_WASNOSUCHNICK 406
#define ERR_TOOMANYTARGETS 407
+#define ERR_NOCTRLSONCHAN 408
#define ERR_NOORIGIN 409
#define ERR_INVALIDCAPCMD 410
diff --git a/modules/core/m_message.c b/modules/core/m_message.c
index 7fadaba..5aaf74b 100644
--- a/modules/core/m_message.c
+++ b/modules/core/m_message.c
@@ -409,7 +409,7 @@ static void
msg_channel(int p_or_n, const char *command, struct Client *client_p,
struct Client *source_p, struct Channel *chptr, char *text)
{
- int result;
+ int result = 0;
if (MyClient(source_p))
{
@@ -419,7 +419,7 @@ msg_channel(int p_or_n, const char *command, struct Client *client_p,
}
/* chanops and voiced can flood their own channel with impunity */
- if ((result = can_send(chptr, source_p, NULL)) < 0)
+ if ((result = can_send(chptr, source_p, NULL, text)) < 0)
{
if (result == CAN_SEND_OPV ||
!flood_attack_channel(p_or_n, source_p, chptr))
@@ -429,9 +429,16 @@ msg_channel(int p_or_n, const char *command, struct Client *client_p,
else
{
if (p_or_n != NOTICE)
- sendto_one(source_p, form_str(ERR_CANNOTSENDTOCHAN),
- ID_or_name(&me, client_p),
- ID_or_name(source_p, client_p), chptr->chname);
+ {
+ if (result == ERR_NOCTRLSONCHAN)
+ sendto_one(source_p, form_str(ERR_NOCTRLSONCHAN),
+ ID_or_name(&me, client_p),
+ ID_or_name(source_p, client_p), chptr->chname, text);
+ else
+ sendto_one(source_p, form_str(ERR_CANNOTSENDTOCHAN),
+ ID_or_name(&me, client_p),
+ ID_or_name(source_p, client_p), chptr->chname);
+ }
}
}
diff --git a/modules/core/m_part.c b/modules/core/m_part.c
index 3d1e83a..e999c6a 100644
--- a/modules/core/m_part.c
+++ b/modules/core/m_part.c
@@ -76,7 +76,7 @@ part_one_client(struct Client *client_p, struct Client *source_p,
* only allow /part reasons in -m chans
*/
if (reason[0] && (!MyConnect(source_p) ||
- ((can_send(chptr, source_p, ms) &&
+ ((can_send(chptr, source_p, ms, reason) &&
(source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time)
< CurrentTime))))
{
@@ -127,7 +127,7 @@ m_part(struct Client *client_p, struct Client *source_p,
return;
}
- if (parc > 2)
+ if (parc > 2 && !EmptyString(parv[2]))
strlcpy(reason, parv[2], sizeof(reason));
/* Finish the flood grace period... */
diff --git a/modules/core/m_sjoin.c b/modules/core/m_sjoin.c
index 65a5caa..8e10097 100644
--- a/modules/core/m_sjoin.c
+++ b/modules/core/m_sjoin.c
@@ -122,6 +122,9 @@ ms_sjoin(struct Client *client_p, struct Client *source_p,
{
switch (*s)
{
+ case 'c':
+ mode.mode |= MODE_NOCTRL;
+ break;
case 't':
mode.mode |= MODE_TOPICLIMIT;
break;
diff --git a/src/channel.c b/src/channel.c
index efc64d1..c3967d5 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -547,11 +547,7 @@ const char *
get_member_status(const struct Membership *ms, int combine)
{
static char buffer[4];
- char *p = NULL;
-
- if (ms == NULL)
- return "";
- p = buffer;
+ char *p = buffer;
if (ms->flags & CHFL_CHANOP)
{
@@ -697,6 +693,35 @@ find_channel_link(struct Client *client_p, struct Channel *chptr)
return NULL;
}
+/*
+ * Basically the same functionality as in bahamut
+ */
+static int
+msg_has_ctrls(const char *message)
+{
+ const unsigned char *p = (const unsigned char *)message;
+
+ for (; *p; ++p)
+ {
+ if (*p > 31 || *p == 1)
+ continue;
+
+ if (*p == 27)
+ {
+ if (*(p + 1) == '$' ||
+ *(p + 1) == '(')
+ {
+ ++p;
+ continue;
+ }
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
/*!
* \param chptr pointer to Channel struct
* \param source_p pointer to Client struct
@@ -706,7 +731,8 @@ find_channel_link(struct Client *client_p, struct Channel *chptr)
* ERR_CANNOTSENDTOCHAN or ERR_NEEDREGGEDNICK if they cannot send to channel\n
*/
int
-can_send(struct Channel *chptr, struct Client *source_p, struct Membership *ms)
+can_send(struct Channel *chptr, struct Client *source_p,
+ struct Membership *ms, const char *message)
{
struct MaskItem *conf = NULL;
@@ -750,6 +776,9 @@ can_send(struct Channel *chptr, struct Client *source_p, struct Membership *ms)
if ((chptr->mode.mode & MODE_REGONLY) && !HasUMode(source_p, UMODE_REGISTERED))
return ERR_NEEDREGGEDNICK;
+ if ((chptr->mode.mode & MODE_NOCTRL) && msg_has_ctrls(message))
+ return ERR_NOCTRLSONCHAN;
+
return CAN_SEND_NONOP;
}
diff --git a/src/channel_mode.c b/src/channel_mode.c
index 2a21b76..d1e83c5 100644
--- a/src/channel_mode.c
+++ b/src/channel_mode.c
@@ -321,6 +321,7 @@ del_id(struct Channel *chptr, char *banid, int type)
}
const struct mode_letter chan_modes[] = {
+ { MODE_NOCTRL, 'c' },
{ MODE_INVITEONLY, 'i' },
{ MODE_MODERATED, 'm' },
{ MODE_NOPRIVMSGS, 'n' },
@@ -1429,7 +1430,7 @@ static struct ChannelMode ModeTable[255] =
{chm_nosuch, NULL},
{chm_nosuch, NULL}, /* a */
{chm_ban, NULL}, /* b */
- {chm_nosuch, NULL}, /* c */
+ {chm_simple, (void *) MODE_NOCTRL}, /* c */
{chm_nosuch, NULL}, /* d */
{chm_except, NULL}, /* e */
{chm_nosuch, NULL}, /* f */
diff --git a/src/numeric.c b/src/numeric.c
index b7fee5b..b1ee134 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -31,7 +31,7 @@ static const char *replies[] = {
/* 001 RPL_WELCOME */ ":%s 001 %s :Welcome to the %s Internet Relay Chat Network %s!%s@%s",
/* 002 RPL_YOURHOST */ ":%s 002 %s :Your host is %s, running version %s",
/* 003 RPL_CREATED */ ":%s 003 %s :This server was created %s",
-/* 004 RPL_MYINFO */ ":%s 004 %s %s %s %s biklmnoprstveIORS bkloveI",
+/* 004 RPL_MYINFO */ ":%s 004 %s %s %s %s bciklmnoprstveIORS bkloveI",
/* 005 RPL_ISUPPORT */ ":%s 005 %s %s :are supported by this server",
/* 006 */ NULL,
/* 007 */ NULL,
@@ -435,7 +435,7 @@ static const char *replies[] = {
/* 405 ERR_TOOMANYCHANNELS */ ":%s 405 %s %s :You have joined too many channels",
/* 406 ERR_WASNOSUCHNICK */ ":%s 406 %s %s :There was no such nickname",
/* 407 ERR_TOOMANYTARGETS */ ":%s 407 %s %s :Too many recipients. Only %d processed",
-/* 408 */ NULL,
+/* 408 ERR_NOCTRLSONCHAN*/ ":%s 408 %s %s :You cannot use control codes on this channel. Not sent: %s",
/* 409 ERR_NOORIGIN */ ":%s 409 %s :No origin specified",
/* 410 ERR_INVALIDCAPCMD */ ":%s 410 %s %s :Invalid CAP subcommand",
/* 411 ERR_NORECIPIENT */ ":%s 411 %s :No recipient given (%s)",