X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/0cce7774d5d1f0c0abddedb0e7d35278d0f70cb7..4d12e65469c877f8028d5ac40a39457ec96b2f40:/modules/m_invite.c diff --git a/modules/m_invite.c b/modules/m_invite.c index b8782d03..af65e1b5 100644 --- a/modules/m_invite.c +++ b/modules/m_invite.c @@ -20,12 +20,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA - * - * $Id: m_invite.c 3438 2007-05-06 14:46:45Z jilles $ */ #include "stdinc.h" -#include "common.h" #include "channel.h" #include "client.h" #include "hash.h" @@ -40,29 +37,43 @@ #include "modules.h" #include "packet.h" #include "tgchange.h" +#include "s_newconf.h" + +static const char invite_desc[] = "Provides /invite"; -static int m_invite(struct Client *, struct Client *, int, const char **); +static void m_invite(struct MsgBuf *, struct Client *, struct Client *, int, const char **); struct Message invite_msgtab = { - "INVITE", 0, 0, 0, MFLG_SLOW, + "INVITE", 0, 0, 0, 0, {mg_unreg, {m_invite, 3}, {m_invite, 3}, mg_ignore, mg_ignore, {m_invite, 3}} }; + +static int can_invite_hook; +static int invite_hook; + mapi_clist_av1 invite_clist[] = { &invite_msgtab, NULL }; -DECLARE_MODULE_AV1(invite, NULL, NULL, invite_clist, NULL, NULL, "$Revision: 3438 $"); +mapi_hlist_av1 invite_hlist[] = { + { "can_invite", &can_invite_hook }, + { "invite", &invite_hook }, + { NULL, NULL } +}; + +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 -m_invite(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) +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); @@ -74,14 +85,14 @@ m_invite(struct Client *client_p, struct Client *source_p, int parc, const char if(target_p == NULL) { if(!MyClient(source_p) && IsDigit(parv[1][0])) - sendto_one_numeric(source_p, ERR_NOSUCHNICK, - "* :Target left IRC. Failed to invite to %s", + sendto_one_numeric(source_p, ERR_NOSUCHNICK, + "* :Target left IRC. Failed to invite to %s", parv[2]); else - sendto_one_numeric(source_p, ERR_NOSUCHNICK, - form_str(ERR_NOSUCHNICK), + sendto_one_numeric(source_p, ERR_NOSUCHNICK, + form_str(ERR_NOSUCHNICK), parv[1]); - return 0; + return; } if(check_channel_name(parv[2]) == 0) @@ -89,25 +100,17 @@ m_invite(struct Client *client_p, struct Client *source_p, int parc, const char sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]); - return 0; - } - - if(!IsChannelName(parv[2])) - { - if(MyClient(source_p)) - sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, - form_str(ERR_NOSUCHCHANNEL), parv[2]); - return 0; + return; } /* Do not send local channel invites to users if they are not on the - * same server as the person sending the INVITE message. + * same server as the person sending the INVITE message. */ if(parv[2][0] == '&' && !MyConnect(target_p)) { 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)) || @@ -117,14 +120,14 @@ m_invite(struct Client *client_p, struct Client *source_p, int parc, const char 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); @@ -132,7 +135,7 @@ m_invite(struct Client *client_p, struct Client *source_p, int parc, const char { sendto_one_numeric(source_p, ERR_NOTONCHANNEL, form_str(ERR_NOTONCHANNEL), parv[2]); - return 0; + return; } if(IsMember(target_p, chptr)) @@ -140,17 +143,28 @@ m_invite(struct Client *client_p, struct Client *source_p, int parc, const char 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 @@ -163,15 +177,15 @@ m_invite(struct Client *client_p, struct Client *source_p, int parc, const char 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), + sendto_one(source_p, form_str(RPL_INVITING), me.name, source_p->name, target_p->name, parv[2]); if(target_p->user->away) @@ -183,62 +197,46 @@ m_invite(struct Client *client_p, struct Client *source_p, int parc, const char { /* 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); } - else if(target_p->from != client_p) + else if (target_p->from != client_p) { sendto_one_prefix(target_p, source_p, "INVITE", "%s %lu", chptr->chname, (unsigned long) chptr->channelts); } - - return 0; } /* 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; @@ -247,11 +245,11 @@ 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 */ - if((int)rb_dlink_list_length(&who->user->invited) >= + if((int)rb_dlink_list_length(&who->user->invited) >= ConfigChannel.max_chans_per_user) { ptr = who->user->invited.tail; @@ -263,6 +261,6 @@ add_invite(struct Channel *chptr, struct Client *who) /* add channel to user invite list */ rb_dlinkAddAlloc(chptr, &who->user->invited); -} - + return true; +}