X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/cbeab4bc340b7b3f4fbf424ff327758defb9598a..4d12e65469c877f8028d5ac40a39457ec96b2f40:/modules/m_invite.c diff --git a/modules/m_invite.c b/modules/m_invite.c index 3b7f4825..af65e1b5 100644 --- a/modules/m_invite.c +++ b/modules/m_invite.c @@ -23,7 +23,6 @@ */ #include "stdinc.h" -#include "common.h" #include "channel.h" #include "client.h" #include "hash.h" @@ -38,44 +37,43 @@ #include "modules.h" #include "packet.h" #include "tgchange.h" +#include "s_newconf.h" -static int m_invite(struct MsgBuf *, struct Client *, struct Client *, int, const char **); -static unsigned int CAP_INVITE_NOTIFY = 0; +static const char invite_desc[] = "Provides /invite"; + +static void m_invite(struct MsgBuf *, struct Client *, struct Client *, int, const char **); struct Message invite_msgtab = { "INVITE", 0, 0, 0, 0, {mg_unreg, {m_invite, 3}, {m_invite, 3}, mg_ignore, mg_ignore, {m_invite, 3}} }; -mapi_clist_av1 invite_clist[] = { &invite_msgtab, NULL }; -static int -invite_modinit(void) -{ - CAP_INVITE_NOTIFY = capability_put(cli_capindex, "invite-notify", NULL); - return 0; -} +static int can_invite_hook; +static int invite_hook; -static void -invite_moddeinit(void) -{ - capability_orphan(cli_capindex, "invite-notify"); -} +mapi_clist_av1 invite_clist[] = { &invite_msgtab, NULL }; +mapi_hlist_av1 invite_hlist[] = { + { "can_invite", &can_invite_hook }, + { "invite", &invite_hook }, + { NULL, NULL } +}; -DECLARE_MODULE_AV1(invite, invite_modinit, invite_moddeinit, invite_clist, NULL, NULL, "$Revision: 3438 $"); +DECLARE_MODULE_AV2(invite, NULL, NULL, invite_clist, invite_hlist, NULL, NULL, NULL, invite_desc); -static void add_invite(struct Channel *, struct Client *); +static bool add_invite(struct Channel *, struct Client *); /* m_invite() * parv[1] - user to invite * parv[2] - channel name */ -static int +static void m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Client *target_p; struct Channel *chptr; struct membership *msptr; int store_invite = 0; + hook_data_channel_approval hdata = { 0 }; if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); @@ -94,7 +92,7 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), parv[1]); - return 0; + return; } if(check_channel_name(parv[2]) == 0) @@ -102,7 +100,7 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]); - return 0; + return; } /* Do not send local channel invites to users if they are not on the @@ -112,7 +110,7 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source { sendto_one(source_p, form_str(ERR_USERNOTONSERV), me.name, source_p->name, target_p->name); - return 0; + return; } if(((MyConnect(source_p) && !IsExemptResv(source_p)) || @@ -122,14 +120,14 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]); - return 0; + return; } if((chptr = find_channel(parv[2])) == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[2]); - return 0; + return; } msptr = find_channel_membership(chptr, source_p); @@ -137,7 +135,7 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), parv[2]); - return 0; + return; } if(IsMember(target_p, chptr)) @@ -145,17 +143,28 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source sendto_one_numeric(source_p, ERR_USERONCHANNEL, form_str(ERR_USERONCHANNEL), target_p->name, parv[2]); - return 0; + return; } - /* unconditionally require ops, unless the channel is +g */ - /* treat remote clients as chanops */ - if(MyClient(source_p) && !is_chanop(msptr) && - !(chptr->mode.mode & MODE_FREEINVITE)) + if (MyClient(source_p)) { - sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), - me.name, source_p->name, parv[2]); - return 0; + hdata.chptr = chptr; + hdata.msptr = msptr; + hdata.client = source_p; + hdata.target = target_p; + hdata.approved = !(is_chanop(msptr) || (chptr->mode.mode & MODE_FREEINVITE)); + + call_hook(can_invite_hook, &hdata); + if (hdata.approved) + { + if (hdata.error) + sendto_one_numeric(source_p, hdata.approved, "%s", hdata.error); + else + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, parv[2]); + + return; + } } /* store invites when they could affect the ability to join @@ -168,13 +177,13 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source if(MyConnect(source_p)) { - if (ConfigFileEntry.target_change && !IsOper(source_p) && + if (ConfigFileEntry.target_change && !IsOperGeneral(source_p) && !find_allowing_channel(source_p, target_p) && !add_target(source_p, target_p)) { sendto_one(source_p, form_str(ERR_TARGCHANGE), me.name, source_p->name, target_p->name); - return 0; + return; } sendto_one(source_p, form_str(RPL_INVITING), me.name, source_p->name, @@ -188,70 +197,46 @@ m_invite(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source { /* this should never be less than */ if(atol(parv[3]) > chptr->channelts) - return 0; + return; } if(MyConnect(target_p)) { - if(!IsOper(source_p) && (IsSetCallerId(target_p) || - (IsSetRegOnlyMsg(target_p) && !source_p->user->suser[0])) && - !accept_message(source_p, target_p)) + hdata.chptr = chptr; + hdata.msptr = msptr; + hdata.client = source_p; + hdata.target = target_p; + hdata.approved = 0; + + call_hook(invite_hook, &hdata); + + if (hdata.approved) { - if (IsSetRegOnlyMsg(target_p) && !source_p->user->suser[0]) - { - sendto_one_numeric(source_p, ERR_NONONREG, - form_str(ERR_NONONREG), - target_p->name); - return 0; - } - else - { - /* instead of sending RPL_UMODEGMSG, - * just let the invite through - */ - if((target_p->localClient->last_caller_id_time + - ConfigFileEntry.caller_id_wait) >= rb_current_time()) - { - sendto_one_numeric(source_p, ERR_TARGUMODEG, - form_str(ERR_TARGUMODEG), - target_p->name); - return 0; - } - target_p->localClient->last_caller_id_time = rb_current_time(); - } + if (hdata.error) + sendto_one_numeric(source_p, hdata.approved, "%s", hdata.error); + return; } + add_reply_target(target_p, source_p); - sendto_one(target_p, ":%s!%s@%s INVITE %s :%s", - source_p->name, source_p->username, source_p->host, - target_p->name, chptr->chname); + sendto_anywhere(target_p, source_p, "INVITE", ":%s", chptr->chname); if(store_invite) - { add_invite(chptr, target_p); - - sendto_channel_local_with_capability(CHFL_CHANOP, 0, CAP_INVITE_NOTIFY, chptr, - ":%s NOTICE %s :%s is inviting %s to %s.", - me.name, chptr->chname, source_p->name, target_p->name, chptr->chname); - sendto_channel_local_with_capability(CHFL_CHANOP, CAP_INVITE_NOTIFY, 0, chptr, - ":%s!%s@%s INVITE %s %s", source_p->name, source_p->username, - source_p->host, target_p->name, chptr->chname); - } } - - sendto_server(source_p, chptr, CAP_TS6, 0, ":%s INVITE %s %s %lu", - use_id(source_p), use_id(target_p), - chptr->chname, (unsigned long) chptr->channelts); - - return 0; + else if (target_p->from != client_p) + { + sendto_one_prefix(target_p, source_p, "INVITE", "%s %lu", + chptr->chname, (unsigned long) chptr->channelts); + } } /* add_invite() * * input - channel to add invite to, client to add - * output - + * output - true if it is a new invite, else false * side effects - client is added to invite list. */ -static void +static bool add_invite(struct Channel *chptr, struct Client *who) { rb_dlink_node *ptr; @@ -260,7 +245,7 @@ add_invite(struct Channel *chptr, struct Client *who) RB_DLINK_FOREACH(ptr, who->user->invited.head) { if(ptr->data == chptr) - return; + return false; } /* ok, if their invite list is too long, remove the tail */ @@ -276,4 +261,6 @@ add_invite(struct Channel *chptr, struct Client *who) /* add channel to user invite list */ rb_dlinkAddAlloc(chptr, &who->user->invited); + + return true; }