From 05202dd2a417d4e648febaca4dbb193d60169362 Mon Sep 17 00:00:00 2001 From: Bram Matthys Date: Sat, 22 Jun 2019 16:03:06 +0200 Subject: [PATCH] Move can_send() function from core to m_message. --- include/h.h | 2 +- include/modules.h | 1 + src/channel.c | 94 ----------------------------------------- src/modules.c | 4 +- src/modules/m_message.c | 94 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 96 deletions(-) diff --git a/include/h.h b/include/h.h index aceb74462..996b16fb5 100644 --- a/include/h.h +++ b/include/h.h @@ -181,7 +181,6 @@ extern int add_silence(aClient *, char *, int); extern int del_silence(aClient *, char *); extern void send_user_joins(aClient *, aClient *); extern void clean_channelname(char *); -extern int can_send(aClient *cptr, aChannel *chptr, char **msgtext, char **errmsg, int notice); extern long get_access(aClient *, aChannel *); extern int is_chan_op(aClient *, aChannel *); extern int has_voice(aClient *, aChannel *); @@ -678,6 +677,7 @@ extern MODVAR char *(*charsys_get_current_languages)(void); extern MODVAR void (*broadcast_sinfo)(aClient *acptr, aClient *to, aClient *except); extern MODVAR void (*parse_message_tags)(aClient *cptr, char **str, MessageTag **mtag_list); extern MODVAR char *(*mtags_to_string)(MessageTag *m, aClient *acptr); +extern MODVAR int (*can_send)(aClient *cptr, aChannel *chptr, char **msgtext, char **errmsg, int notice); /* /Efuncs */ extern MODVAR aMotdFile opermotd, svsmotd, motd, botmotd, smotd, rules; diff --git a/include/modules.h b/include/modules.h index c9af3052b..cf83afda6 100644 --- a/include/modules.h +++ b/include/modules.h @@ -1204,6 +1204,7 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum #define EFUNC_MTAGS_TO_STRING 62 #define EFUNC_TKL_CHARTOTYPE 63 #define EFUNC_TKL_TYPE_STRING 64 +#define EFUNC_CAN_SEND 65 /* Module flags */ #define MODFLAG_NONE 0x0000 diff --git a/src/channel.c b/src/channel.c index 6a061d8c8..8240ba930 100644 --- a/src/channel.c +++ b/src/channel.c @@ -736,100 +736,6 @@ int is_chanprot(aClient *cptr, aChannel *chptr) return 0; } -// FIXME: move to m_message and efunc !! - -/** Can user send a message to this channel? - * @param cptr The client - * @param chptr The channel - * @param msgtext The message to send (MAY be changed, even if user is allowed to send) - * @param errmsg The error message (will be filled in) - * @param notice If it's a NOTICE then this is set to 1. Set to 0 for PRIVMSG. - * @returns Returns 1 if the user is allowed to send, otherwise 0. - * (note that this behavior was reversed in UnrealIRCd versions <5.x. - */ -int can_send(aClient *cptr, aChannel *chptr, char **msgtext, char **errmsg, int notice) -{ - Membership *lp; - int member, i = 0; - Hook *h; - - if (!MyClient(cptr)) - return 1; - - *errmsg = NULL; - - member = IsMember(cptr, chptr); - - if (chptr->mode.mode & MODE_NOPRIVMSGS && !member) - { - /* Channel does not accept external messages (+n). - * Reject, unless HOOKTYPE_CAN_BYPASS_NO_EXTERNAL_MSGS tells otherwise. - */ - for (h = Hooks[HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION]; h; h = h->next) - { - i = (*(h->func.intfunc))(cptr, chptr, BYPASS_CHANMSG_EXTERNAL); - if (i != HOOK_CONTINUE) - break; - } - if (i != HOOK_ALLOW) - { - *errmsg = "No external channel messages"; - return 0; - } - } - - lp = find_membership_link(cptr->user->channel, chptr); - if (chptr->mode.mode & MODE_MODERATED && - !op_can_override("channel:override:message:moderated",cptr,chptr,NULL) && - (!lp /* FIXME: UGLY */ - || !(lp->flags & (CHFL_CHANOP | CHFL_VOICE | CHFL_CHANOWNER | CHFL_HALFOP | CHFL_CHANPROT)))) - { - /* Channel is moderated (+m). - * Reject, unless HOOKTYPE_CAN_BYPASS_MODERATED tells otherwise. - */ - for (h = Hooks[HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION]; h; h = h->next) - { - i = (*(h->func.intfunc))(cptr, chptr, BYPASS_CHANMSG_MODERATED); - if (i != HOOK_CONTINUE) - break; - } - if (i != HOOK_ALLOW) - { - *errmsg = "You need voice (+v)"; - return 0; - } - } - - /* Modules can plug in as well */ - for (h = Hooks[HOOKTYPE_CAN_SEND]; h; h = h->next) - { - i = (*(h->func.intfunc))(cptr, chptr, lp, &msgtext, &errmsg, notice); - if (i != HOOK_CONTINUE) - break; - } - if (i != HOOK_CONTINUE) - return 0; - - /* Now we are going to check bans */ - - /* ..but first: exempt ircops */ - if (op_can_override("channel:override:message:ban",cptr,chptr,NULL)) - return 0; - - if ((!lp - || !(lp->flags & (CHFL_CHANOP | CHFL_VOICE | CHFL_CHANOWNER | - CHFL_HALFOP | CHFL_CHANPROT))) && MyClient(cptr) - && is_banned(cptr, chptr, BANCHK_MSG, msgtext, errmsg)) - { - /* Modules can set 'errmsg', otherwise we default to this: */ - if (!*errmsg) - *errmsg = "You are banned"; - return 0; - } - - return 1; -} - /** Returns 1 if channel has this channel mode set and 0 if not */ int has_channel_mode(aChannel *chptr, char mode) { diff --git a/src/modules.c b/src/modules.c index cfea98fb7..cfc45e8f0 100644 --- a/src/modules.c +++ b/src/modules.c @@ -143,6 +143,7 @@ void (*parse_message_tags)(aClient *cptr, char **str, MessageTag **mtag_list); extern void parse_message_tags_default_handler(aClient *cptr, char **str, MessageTag **mtag_list); char *(*mtags_to_string)(MessageTag *m, aClient *acptr); extern char *mtags_to_string_default_handler(MessageTag *m, aClient *acptr); +int (*can_send)(aClient *cptr, aChannel *chptr, char **msgtext, char **errmsg, int notice); static const EfunctionsList efunction_table[MAXEFUNCTIONS] = { /* 00 */ {NULL, NULL, NULL}, @@ -210,7 +211,8 @@ static const EfunctionsList efunction_table[MAXEFUNCTIONS] = { /* 62 */ {"mtags_to_string", (void *)&mtags_to_string, &mtags_to_string_default_handler}, /* 63 */ {"tkl_chartotype", (void *)&tkl_chartotype, NULL}, /* 64 */ {"tkl_type_string", (void *)&tkl_type_string, NULL}, -/* 65 */ {NULL, NULL, NULL}, +/* 65 */ {"can_send", (void *)&can_send, NULL}, +/* 66 */ {NULL, NULL, NULL}, }; #ifdef UNDERSCORE diff --git a/src/modules/m_message.c b/src/modules/m_message.c index c632fc073..02aaa4695 100644 --- a/src/modules/m_message.c +++ b/src/modules/m_message.c @@ -29,6 +29,7 @@ int ban_version(aClient *sptr, char *text); CMD_FUNC(m_private); CMD_FUNC(m_notice); int m_message(aClient *cptr, aClient *sptr, MessageTag *recv_mtags, int parc, char *parv[], int notice); +int _can_send(aClient *cptr, aChannel *chptr, char **msgtext, char **errmsg, int notice); /* Place includes here */ #define MSG_PRIVATE "PRIVMSG" /* PRIV */ @@ -49,6 +50,7 @@ MOD_TEST(m_message) EfunctionAddPChar(modinfo->handle, EFUNC_STRIPCOLORS, _StripColors); EfunctionAddPChar(modinfo->handle, EFUNC_STRIPCONTROLCODES, _StripControlCodes); EfunctionAdd(modinfo->handle, EFUNC_IS_SILENCED, _is_silenced); + EfunctionAdd(modinfo->handle, EFUNC_CAN_SEND, _can_send); return MOD_SUCCESS; } @@ -880,3 +882,95 @@ int ban_version(aClient *sptr, char *text) return 0; } + +/** Can user send a message to this channel? + * @param cptr The client + * @param chptr The channel + * @param msgtext The message to send (MAY be changed, even if user is allowed to send) + * @param errmsg The error message (will be filled in) + * @param notice If it's a NOTICE then this is set to 1. Set to 0 for PRIVMSG. + * @returns Returns 1 if the user is allowed to send, otherwise 0. + * (note that this behavior was reversed in UnrealIRCd versions <5.x. + */ +int _can_send(aClient *cptr, aChannel *chptr, char **msgtext, char **errmsg, int notice) +{ + Membership *lp; + int member, i = 0; + Hook *h; + + if (!MyClient(cptr)) + return 1; + + *errmsg = NULL; + + member = IsMember(cptr, chptr); + + if (chptr->mode.mode & MODE_NOPRIVMSGS && !member) + { + /* Channel does not accept external messages (+n). + * Reject, unless HOOKTYPE_CAN_BYPASS_NO_EXTERNAL_MSGS tells otherwise. + */ + for (h = Hooks[HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION]; h; h = h->next) + { + i = (*(h->func.intfunc))(cptr, chptr, BYPASS_CHANMSG_EXTERNAL); + if (i != HOOK_CONTINUE) + break; + } + if (i != HOOK_ALLOW) + { + *errmsg = "No external channel messages"; + return 0; + } + } + + lp = find_membership_link(cptr->user->channel, chptr); + if (chptr->mode.mode & MODE_MODERATED && + !op_can_override("channel:override:message:moderated",cptr,chptr,NULL) && + (!lp /* FIXME: UGLY */ + || !(lp->flags & (CHFL_CHANOP | CHFL_VOICE | CHFL_CHANOWNER | CHFL_HALFOP | CHFL_CHANPROT)))) + { + /* Channel is moderated (+m). + * Reject, unless HOOKTYPE_CAN_BYPASS_MODERATED tells otherwise. + */ + for (h = Hooks[HOOKTYPE_CAN_BYPASS_CHANNEL_MESSAGE_RESTRICTION]; h; h = h->next) + { + i = (*(h->func.intfunc))(cptr, chptr, BYPASS_CHANMSG_MODERATED); + if (i != HOOK_CONTINUE) + break; + } + if (i != HOOK_ALLOW) + { + *errmsg = "You need voice (+v)"; + return 0; + } + } + + /* Modules can plug in as well */ + for (h = Hooks[HOOKTYPE_CAN_SEND]; h; h = h->next) + { + i = (*(h->func.intfunc))(cptr, chptr, lp, &msgtext, &errmsg, notice); + if (i != HOOK_CONTINUE) + break; + } + if (i != HOOK_CONTINUE) + return 0; + + /* Now we are going to check bans */ + + /* ..but first: exempt ircops */ + if (op_can_override("channel:override:message:ban",cptr,chptr,NULL)) + return 0; + + if ((!lp + || !(lp->flags & (CHFL_CHANOP | CHFL_VOICE | CHFL_CHANOWNER | + CHFL_HALFOP | CHFL_CHANPROT))) && MyClient(cptr) + && is_banned(cptr, chptr, BANCHK_MSG, msgtext, errmsg)) + { + /* Modules can set 'errmsg', otherwise we default to this: */ + if (!*errmsg) + *errmsg = "You are banned"; + return 0; + } + + return 1; +}