X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/212380e3f42f585dc1ea927402252eb943f91f7b..b2c208be091670e3c5259eba77187bae6ac6eece:/modules/core/m_part.c diff --git a/modules/core/m_part.c b/modules/core/m_part.c index d31da2f5..54413e5f 100644 --- a/modules/core/m_part.c +++ b/modules/core/m_part.c @@ -25,12 +25,11 @@ */ #include "stdinc.h" -#include "tools.h" #include "channel.h" #include "client.h" #include "common.h" #include "hash.h" -#include "irc_string.h" +#include "match.h" #include "ircd.h" #include "numeric.h" #include "send.h" @@ -40,6 +39,8 @@ #include "modules.h" #include "s_conf.h" #include "packet.h" +#include "inline/stringops.h" +#include "hook.h" static int m_part(struct Client *, struct Client *, int, const char **); @@ -54,11 +55,12 @@ DECLARE_MODULE_AV1(part, NULL, NULL, part_clist, NULL, NULL, "$Revision: 98 $"); static void part_one_client(struct Client *client_p, struct Client *source_p, char *name, char *reason); +static int can_send_part(struct Client *source_p, struct Channel *chptr, struct membership *msptr); +static int do_message_hook(struct Client *source_p, struct Channel *chptr, char **reason); /* ** m_part -** parv[0] = sender prefix ** parv[1] = channel ** parv[2] = reason */ @@ -72,20 +74,18 @@ m_part(struct Client *client_p, struct Client *source_p, int parc, const char *p reason[0] = '\0'; if(parc > 2) - strlcpy(reason, parv[2], sizeof(reason)); + rb_strlcpy(reason, parv[2], sizeof(reason)); - name = strtoken(&p, s, ","); + name = rb_strtok_r(s, ",", &p); /* Finish the flood grace period... */ if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); - strip_colour(reason); - while(name) { part_one_client(client_p, source_p, name, reason); - name = strtoken(&p, NULL, ","); + name = rb_strtok_r(NULL, ",", &p); } return 0; } @@ -125,15 +125,15 @@ part_one_client(struct Client *client_p, struct Client *source_p, char *name, ch * Remove user from the old channel (if any) * only allow /part reasons in -m chans */ - if(reason[0] && (is_chanop(msptr) || !MyConnect(source_p) || - ((can_send(chptr, source_p, msptr) > 0 && - (source_p->localClient->firsttime + - ConfigFileEntry.anti_spam_exit_message_time) < CurrentTime)))) + if(!EmptyString(reason) && + (!MyConnect(source_p) || + (can_send_part(source_p, chptr, msptr) && do_message_hook(source_p, chptr, &reason)) + ) + ) { + sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s PART %s :%s", use_id(source_p), chptr->chname, reason); - sendto_server(client_p, chptr, NOCAPS, CAP_TS6, - ":%s PART %s :%s", source_p->name, chptr->chname, reason); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s", source_p->name, source_p->username, source_p->host, chptr->chname, reason); @@ -142,11 +142,65 @@ part_one_client(struct Client *client_p, struct Client *source_p, char *name, ch { sendto_server(client_p, chptr, CAP_TS6, NOCAPS, ":%s PART %s", use_id(source_p), chptr->chname); - sendto_server(client_p, chptr, NOCAPS, CAP_TS6, - ":%s PART %s", source_p->name, chptr->chname); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s", source_p->name, source_p->username, source_p->host, chptr->chname); } remove_user_from_channel(msptr); } + +/* + * can_send_part - whether a part message can be sent. + * + * inputs: + * - client parting + * - channel being parted + * - membership pointer + * outputs: + * - 1 if message allowed + * - 0 if message denied + * side effects: + * - none. + */ +static int +can_send_part(struct Client *source_p, struct Channel *chptr, struct membership *msptr) +{ + if (!can_send(chptr, source_p, msptr)) + return 0; + /* Allow chanops to bypass anti_spam_exit_message_time for part messages. */ + if (is_chanop(msptr)) + return 1; + return (source_p->localClient->firsttime + ConfigFileEntry.anti_spam_exit_message_time) < rb_current_time(); +} + +/* + * do_message_hook - execute the message hook on a part message reason. + * + * inputs: + * - client parting + * - channel being parted + * - pointer to reason + * outputs: + * - 1 if message is allowed + * - 0 if message is denied or message is now empty + * side effects: + * - reason may be modified. + */ +static int +do_message_hook(struct Client *source_p, struct Channel *chptr, char **reason) +{ + hook_data_privmsg_channel hdata; + + hdata.msgtype = MESSAGE_TYPE_PART; + hdata.source_p = source_p; + hdata.chptr = chptr; + hdata.text = *reason; + hdata.approved = 0; + + call_hook(h_privmsg_channel, &hdata); + + /* The reason may have been changed by a hook... */ + *reason = hdata.text; + + return (hdata.approved == 0 && !EmptyString(*reason)); +}