diff --git a/include/channel.h b/include/channel.h index e395431c3..17427c87b 100644 --- a/include/channel.h +++ b/include/channel.h @@ -26,13 +26,6 @@ #define MODEBUFLEN 200 -#define CANNOT_SEND_MODERATED 1 -#define CANNOT_SEND_NOPRIVMSGS 2 -#define CANNOT_SEND_BAN 4 -#define CANNOT_SEND_MODREG 6 -#define CANNOT_SEND_SWEAR 7 /* This isn't actually used here */ -#define CANNOT_SEND_NONOTICE 8 - #define NullChn ((aChannel *)0) #define ChannelExists(n) (find_channel(n, NullChn) != NullChn) diff --git a/include/modules.h b/include/modules.h index 64ac71420..c9af3052b 100644 --- a/include/modules.h +++ b/include/modules.h @@ -975,7 +975,7 @@ int hooktype_handshake(aClient *sptr); int hooktype_away(aClient *sptr, char *reason); int hooktype_invite(aClient *from, aClient *to, aChannel *chptr); int hooktype_can_join(aClient *sptr, aChannel *chptr, char *key, char *parv[]); -int hooktype_can_send(aClient *sptr, aChannel *chptr, char *text, Membership *member, int notice); +int hooktype_can_send(aClient *sptr, aChannel *chptr, Membership *member, char **text, char **errmsg, int notice); int hooktype_can_kick(aClient *sptr, aClient *victim, aChannel *chptr, char *comment, long sptr_flags, long victim_flags, char **error); int hooktype_free_client(aClient *acptr); int hooktype_free_user(anUser *user, aClient *acptr); diff --git a/src/channel.c b/src/channel.c index c43ee77e1..6a061d8c8 100644 --- a/src/channel.c +++ b/src/channel.c @@ -149,12 +149,14 @@ static int list_length(Link *lp) Member *find_member_link(Member *lp, aClient *ptr) { if (ptr) + { while (lp) { if (lp->cptr == ptr) return (lp); lp = lp->next; - } + } + } return NULL; } @@ -179,7 +181,7 @@ Member *make_member(void) if (freemember == NULL) { - for (i = 1; i <= (4072/sizeof(Member)); ++i) + for (i = 1; i <= (4072/sizeof(Member)); ++i) { lp = MyMallocEx(sizeof(Member)); lp->cptr = NULL; @@ -239,7 +241,7 @@ Membership *make_membership(int local) { if (freemembershipL == NULL) { - for (i = 1; i <= (4072/sizeof(MembershipL)); i++) + for (i = 1; i <= (4072/sizeof(MembershipL)); i++) { lp2 = MyMallocEx(sizeof(MembershipL)); lp2->next = (Membership *) freemembershipL; @@ -343,7 +345,7 @@ int add_listmode_ex(Ban **list, aClient *cptr, aChannel *chptr, char *banid, cha if (MyClient(cptr)) (void)collapse(banid); - + len = strlen(banid); if (!*list && ((len > MAXBANLENGTH) || (MAXBANS < 1))) { @@ -693,9 +695,10 @@ int is_chanowner(aClient *cptr, aChannel *chptr) return 0; } -int is_chanownprotop(aClient *cptr, aChannel *chptr) { +int is_chanownprotop(aClient *cptr, aChannel *chptr) +{ Membership *lp; - + if (IsServer(cptr)) return 1; if (chptr) @@ -705,9 +708,10 @@ int is_chanownprotop(aClient *cptr, aChannel *chptr) { return 0; } -int is_skochanop(aClient *cptr, aChannel *chptr) { +int is_skochanop(aClient *cptr, aChannel *chptr) +{ Membership *lp; - + if (IsServer(cptr)) return 1; if (chptr) @@ -732,26 +736,34 @@ 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; - /* - * #0000053 by |savage|, speedup - */ - + if (!MyClient(cptr)) - { - return 0; - } + return 1; + + *errmsg = NULL; member = IsMember(cptr, chptr); if (chptr->mode.mode & MODE_NOPRIVMSGS && !member) { - /* Channel mode +n. Reject, unless HOOKTYPE_CAN_BYPASS_NO_EXTERNAL_MSGS - * tells otherwise. + /* 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) { @@ -760,17 +772,20 @@ int can_send(aClient *cptr, aChannel *chptr, char **msgtext, char **errmsg, int break; } if (i != HOOK_ALLOW) - return CANNOT_SEND_NOPRIVMSGS; + { + *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 - || !(lp->flags & (CHFL_CHANOP | CHFL_VOICE | CHFL_CHANOWNER | - CHFL_HALFOP | CHFL_CHANPROT)))) - { - /* Channel mode +m. Reject, unless HOOKTYPE_CAN_BYPASS_MODERATED - * tells otherwise. + 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) { @@ -779,21 +794,25 @@ int can_send(aClient *cptr, aChannel *chptr, char **msgtext, char **errmsg, int break; } if (i != HOOK_ALLOW) - return CANNOT_SEND_MODERATED; - } - + { + *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,msgtext,lp,notice); + i = (*(h->func.intfunc))(cptr, chptr, lp, &msgtext, &errmsg, notice); if (i != HOOK_CONTINUE) break; } - if (i != HOOK_CONTINUE) - return i; + return 0; - /* Makes opers able to talk thru bans -Stskeeps suggested by The_Cat */ + /* Now we are going to check bans */ + + /* ..but first: exempt ircops */ if (op_can_override("channel:override:message:ban",cptr,chptr,NULL)) return 0; @@ -801,9 +820,14 @@ int can_send(aClient *cptr, aChannel *chptr, char **msgtext, char **errmsg, int || !(lp->flags & (CHFL_CHANOP | CHFL_VOICE | CHFL_CHANOWNER | CHFL_HALFOP | CHFL_CHANPROT))) && MyClient(cptr) && is_banned(cptr, chptr, BANCHK_MSG, msgtext, errmsg)) - return (CANNOT_SEND_BAN); + { + /* Modules can set 'errmsg', otherwise we default to this: */ + if (!*errmsg) + *errmsg = "You are banned"; + return 0; + } - return 0; + return 1; } /** Returns 1 if channel has this channel mode set and 0 if not */ @@ -834,7 +858,7 @@ int has_channel_mode(aChannel *chptr, char mode) /* Special handling for +k (needed??) */ if (chptr->mode.key[0] && (mode == 'k')) return 1; - + return 0; /* Not found */ } diff --git a/src/modules/chanmodes/nonotice.c b/src/modules/chanmodes/nonotice.c index 77976b15c..954a0a4f8 100644 --- a/src/modules/chanmodes/nonotice.c +++ b/src/modules/chanmodes/nonotice.c @@ -32,7 +32,7 @@ Cmode_t EXTCMODE_NONOTICE; #define IsNoNotice(chptr) (chptr->mode.extmode & EXTCMODE_NONOTICE) -int nonotice_check_can_send(aClient *cptr, aChannel *chptr, char *msgtext, Membership *lp, int notice); +int nonotice_check_can_send(aClient *cptr, aChannel *chptr, Membership *lp, char **msg, char **errmsg, int notice); MOD_TEST(nonotice) { @@ -65,7 +65,7 @@ MOD_UNLOAD(nonotice) return MOD_SUCCESS; } -int nonotice_check_can_send(aClient *cptr, aChannel *chptr, char *msgtext, Membership *lp, int notice) +int nonotice_check_can_send(aClient *cptr, aChannel *chptr, Membership *lp, char **msg, char **errmsg, int notice) { Hook *h; int i; @@ -81,7 +81,8 @@ int nonotice_check_can_send(aClient *cptr, aChannel *chptr, char *msgtext, Membe } if (i == HOOK_ALLOW) return HOOK_CONTINUE; /* bypass restriction */ - return CANNOT_SEND_NONOTICE; /* block notice */ + *errmsg = "NOTICEs are not permitted in this channel"; + return HOOK_DENY; /* block notice */ } return HOOK_CONTINUE; diff --git a/src/modules/chanmodes/regonlyspeak.c b/src/modules/chanmodes/regonlyspeak.c index 1416d9a8e..5674f0661 100644 --- a/src/modules/chanmodes/regonlyspeak.c +++ b/src/modules/chanmodes/regonlyspeak.c @@ -34,8 +34,8 @@ static char errMsg[2048]; #define IsRegOnlySpeak(chptr) (chptr->mode.extmode & EXTCMODE_REGONLYSPEAK) -int regonlyspeak_can_send (aClient* cptr, aChannel *chptr, char* message, Membership* lp, int notice); -char * regonlyspeak_part_message (aClient* sptr, aChannel *chptr, char* comment); +int regonlyspeak_can_send(aClient *cptr, aChannel *chptr, Membership *lp, char **msg, char **errmsg, int notice); +char *regonlyspeak_part_message (aClient* sptr, aChannel *chptr, char* comment); MOD_TEST(regonlyspeak) { @@ -81,7 +81,7 @@ char *regonlyspeak_part_message (aClient *sptr, aChannel *chptr, char *comment) return comment; } -int regonlyspeak_can_send (aClient *cptr, aChannel *chptr, char *message, Membership *lp, int notice) +int regonlyspeak_can_send(aClient *cptr, aChannel *chptr, Membership *lp, char **msg, char **errmsg, int notice) { Hook *h; int i; @@ -100,7 +100,8 @@ int regonlyspeak_can_send (aClient *cptr, aChannel *chptr, char *message, Member if (i == HOOK_ALLOW) return HOOK_CONTINUE; /* bypass +M restriction */ - return CANNOT_SEND_MODREG; /* BLOCK message */ + *errmsg = "You must have a registered nick (+r) to talk on this channel"; + return HOOK_DENY; /* BLOCK message */ } return HOOK_CONTINUE; diff --git a/src/modules/m_message.c b/src/modules/m_message.c index 68236b279..c632fc073 100644 --- a/src/modules/m_message.c +++ b/src/modules/m_message.c @@ -178,25 +178,6 @@ int m_message(aClient *cptr, aClient *sptr, MessageTag *recv_mtags, int parc, ch MessageTag *mtags; int sendflags; - /* - * Reasons why someone can't send to a channel - * Note: a few have been moved to modules now, but don't just blindly delete them!! as we use the array index ;p - */ - static char *err_cantsend[] = { - "You need voice (+v)", - "No external channel messages", - "Color is not permitted in this channel <>", - "You are banned", - "CTCPs are not permitted in this channel <>", - "You must have a registered nick (+r) to talk on this channel", - "Swearing is not permitted in this channel", - "NOTICEs are not permitted in this channel", - NULL - }; - - if (IsHandshake(sptr)) - return 0; - if (parc < 2 || *parv[1] == '\0') { sendnumeric(sptr, ERR_NORECIPIENT, cmd); @@ -344,14 +325,13 @@ int m_message(aClient *cptr, aClient *sptr, MessageTag *recv_mtags, int parc, ch errmsg = NULL; if (MyClient(sptr) && !IsULine(sptr)) { - int cansend = can_send(sptr, chptr, &text, &errmsg, notice); - if (cansend != 0) + if (!can_send(sptr, chptr, &text, &errmsg, notice)) { - if (!notice || (cansend == 8)) + if (!notice) { /* Send error message */ - // TODO: move all the cansend shit to *errmsg ? if possible? - sendnumeric(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname, errmsg ? errmsg : err_cantsend[cansend - 1], p2); + // TODO: move all the cansend shit to *errmsg ? if possible? + sendnumeric(sptr, ERR_CANNOTSENDTOCHAN, chptr->chname, errmsg, p2); } continue; /* skip */ }