* note: it is guaranteed that parv[0]..parv[parc-1] are all
* non-NULL pointers.
*/
-#if 0
-/*
- * No need to include handlers.h here the signatures must match
- * and we don't need to force a rebuild of all the handlers everytime
- * we add a new one to the list. --Bleep
- */
-#include "handlers.h"
-#endif /* 0 */
+#include "config.h"
+
#include "channel.h"
#include "client.h"
#include "hash.h"
#include "ircd.h"
+#include "ircd_features.h"
+#include "ircd_log.h"
#include "ircd_reply.h"
#include "ircd_string.h"
#include "list.h"
#include "send.h"
#include "struct.h"
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
/*
* m_invite - generic message handler
if (is_silenced(sptr, acptr))
return 0;
- clean_channelname(parv[2]);
-
- if (!IsChannelPrefix(*parv[2]))
- return 0;
-
- if (!(chptr = FindChannel(parv[2]))) {
- if (IsModelessChannel(parv[2]) || IsLocalChannel(parv[2])) {
- send_reply(sptr, ERR_NOTONCHANNEL, parv[2]);
- return 0;
- }
-
- /* Do not disallow to invite to non-existant #channels, otherwise they
- would simply first be created, causing only MORE bandwidth usage. */
-
- if (check_target_limit(sptr, acptr, cli_name(acptr), 0))
- return 0;
-
- send_reply(sptr, RPL_INVITING, cli_name(acptr), parv[2]);
-
- if (cli_user(acptr)->away)
- send_reply(sptr, RPL_AWAY, cli_name(acptr), cli_user(acptr)->away);
-
- sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%s", cli_name(acptr), parv[2]);
-
+ if (!IsChannelName(parv[2])
+ || !strIsIrcCh(parv[2])
+ || !(chptr = FindChannel(parv[2]))) {
+ send_reply(sptr, ERR_NOSUCHCHANNEL, parv[2]);
return 0;
}
if (cli_user(acptr)->away)
send_reply(sptr, RPL_AWAY, cli_name(acptr), cli_user(acptr)->away);
- if (MyConnect(acptr))
+ if (MyConnect(acptr)) {
add_invite(acptr, chptr);
+ sendcmdto_one(sptr, CMD_INVITE, acptr, "%s %H", cli_name(acptr), chptr);
+ } else if (!IsLocalChannel(chptr->chname)) {
+ sendcmdto_one(sptr, CMD_INVITE, acptr, "%s %H %Tu", cli_name(acptr), chptr,
+ chptr->creationtime);
+ }
- sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%H", cli_name(acptr), chptr);
+ if (!IsLocalChannel(chptr->chname) || MyConnect(acptr)) {
+ if (feature_bool(FEAT_ANNOUNCE_INVITES)) {
+ /* Announce to channel operators. */
+ sendcmdto_channel_butserv_butone(&his, get_error_numeric(RPL_ISSUEDINVITE)->str,
+ NULL, chptr, sptr, SKIP_NONOPS,
+ "%H %C %C :%C has been invited by %C",
+ chptr, acptr, sptr, acptr, sptr);
+ /* Announce to servers with channel operators. */
+ sendcmdto_channel_servers_butone(sptr, NULL, TOK_INVITE, chptr, acptr, SKIP_NONOPS,
+ "%s %H %Tu", cli_name(acptr),
+ chptr, chptr->creationtime);
+ }
+ }
return 0;
}
* parv[0] - sender prefix
* parv[1] - user to invite
* parv[2] - channel name
+ * parv[3] - (optional) channel timestamp
*
* - INVITE now is accepted only if who does it is chanop (this of course
* implies that channel must exist and he must be on it).
*
* - Invite with no parameters now lists the channels you are invited to.
* - Isomer 23 Oct 99
+ *
+ * - Invite with too-late timestamp, or with no timestamp from a bursting
+ * server, is silently discarded. - Entrope 19 Jan 05
*/
int ms_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
struct Client *acptr;
struct Channel *chptr;
+ time_t invite_ts;
if (IsServer(sptr)) {
/*
/*
* should have been handled upstream, ignore it.
*/
+ protocol_violation(sptr,"Too few arguments to invite");
return need_more_params(sptr,"INVITE");
}
- if ('#' != *parv[2]) {
+ if (!IsGlobalChannel(parv[2])) {
/*
* should not be sent
*/
send_reply(sptr, ERR_NOSUCHNICK, parv[1]);
return 0;
}
- if (!MyUser(acptr)) {
- /*
- * just relay the message
- */
- sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%s", cli_name(acptr), parv[2]);
- return 0;
- }
-
- if (is_silenced(sptr, acptr))
- return 0;
if (!(chptr = FindChannel(parv[2]))) {
/*
- * allow invites to non existant channels, bleah
+ * allow invites to non existent channels, bleah
* avoid JOIN, INVITE, PART abuse
*/
sendcmdto_one(sptr, CMD_INVITE, acptr, "%C :%s", acptr, parv[2]);
return 0;
}
- if (!find_channel_member(sptr, chptr)) {
- send_reply(sptr, ERR_NOTONCHANNEL, chptr->chname);
- return 0;
- }
- if (find_channel_member(acptr, chptr)) {
- send_reply(sptr, ERR_USERONCHANNEL, cli_name(acptr), chptr->chname);
+ if (parc > 3) {
+ invite_ts = atoi(parv[3]);
+ if (invite_ts > chptr->creationtime)
+ return 0;
+ } else if (IsBurstOrBurstAck(cptr))
return 0;
- }
- add_invite(acptr, chptr);
- sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%H", cli_name(acptr), chptr);
- return 0;
-}
-
-#if 0
-/*
- * m_invite
- *
- * parv[0] - sender prefix
- * parv[1] - user to invite
- * parv[2] - channel name
- *
- * - INVITE now is accepted only if who does it is chanop (this of course
- * implies that channel must exist and he must be on it).
- *
- * - On the other side it IS processed even if channel is NOT invite only
- * leaving room for other enhancements like inviting banned ppl. -- Nemesi
- *
- * - Invite with no parameters now lists the channels you are invited to.
- * - Isomer 23 Oct 99
- */
-int m_invite(struct Client* cptr, struct Client *sptr, int parc, char *parv[])
-{
- struct Client *acptr;
- struct Channel *chptr;
-
- if (parc < 2 ) {
- /*
- * list the channels you have an invite to.
- */
- struct SLink *lp;
- for (lp = sptr->user->invited; lp; lp = lp->next)
- sendto_one(cptr, rpl_str(RPL_INVITELIST), me.name, cptr->name, /* XXX DEAD */
- lp->value.chptr->chname);
- sendto_one(cptr, rpl_str(RPL_ENDOFINVITELIST), me.name, cptr->name); /* XXX DEAD */
+ if (!IsChannelService(sptr) && !find_channel_member(sptr, chptr)) {
+ send_reply(sptr, ERR_NOTONCHANNEL, chptr->chname);
return 0;
}
- if (parc < 3 || *parv[2] == '\0')
- return need_more_params(sptr, "INVITE");
-
- if (!(acptr = FindUser(parv[1])))
- {
- sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]); /* XXX DEAD */
+ if (find_channel_member(acptr, chptr)) {
+ send_reply(sptr, ERR_USERONCHANNEL, cli_name(acptr), chptr->chname);
return 0;
}
if (is_silenced(sptr, acptr))
return 0;
- if (MyUser(sptr))
- clean_channelname(parv[2]);
- else if (IsLocalChannel(parv[2]))
- return 0;
-
- if (*parv[2] == '0' || !IsChannelName(parv[2]))
- return 0;
-
- if (!(chptr = FindChannel(parv[2])))
- {
- if (IsModelessChannel(parv[2]) || IsLocalChannel(parv[2]))
- {
- sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0], parv[2]); /* XXX DEAD */
- return 0;
- }
-
- /* Do not disallow to invite to non-existant #channels, otherwise they
- would simply first be created, causing only MORE bandwidth usage. */
- if (MyConnect(sptr))
- {
- if (check_target_limit(sptr, acptr, acptr->name, 0))
- return 0;
-
- sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0], /* XXX DEAD */
- acptr->name, parv[2]);
-
- if (acptr->user->away)
- sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], /* XXX DEAD */
- acptr->name, acptr->user->away);
- }
-
- sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0], /* XXX DEAD */
- acptr->name, parv[2]);
-
- return 0;
- }
-
- if (!find_channel_member(sptr, chptr))
- {
- sendto_one(sptr, err_str(ERR_NOTONCHANNEL), me.name, parv[0], /* XXX DEAD */
- chptr->chname);
- return 0;
- }
-
- if (find_channel_member(acptr, chptr))
- {
- sendto_one(sptr, err_str(ERR_USERONCHANNEL), /* XXX DEAD */
- me.name, parv[0], acptr->name, chptr->chname);
- return 0;
- }
-
- if (MyConnect(sptr))
- {
- if (!is_chan_op(sptr, chptr))
- {
- sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), /* XXX DEAD */
- me.name, parv[0], chptr->chname);
- return 0;
- }
-
- /* If we get here, it was a VALID and meaningful INVITE */
-
- if (check_target_limit(sptr, acptr, acptr->name, 0))
- return 0;
-
- sendto_one(sptr, rpl_str(RPL_INVITING), me.name, parv[0], /* XXX DEAD */
- acptr->name, chptr->chname);
-
- if (acptr->user->away)
- sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], /* XXX DEAD */
- acptr->name, acptr->user->away);
- }
-
if (MyConnect(acptr)) {
add_invite(acptr, chptr);
- sendto_prefix_one(acptr, sptr, ":%s INVITE %s :%s", parv[0], /* XXX DEAD */
- acptr->name, chptr->chname);
+ sendcmdto_one(sptr, CMD_INVITE, acptr, "%s %H", cli_name(acptr), chptr);
+ } else {
+ sendcmdto_one(sptr, CMD_INVITE, acptr, "%s %H %Tu", cli_name(acptr), chptr,
+ chptr->creationtime);
+ }
+
+ if (feature_bool(FEAT_ANNOUNCE_INVITES)) {
+ /* Announce to channel operators. */
+ sendcmdto_channel_butserv_butone(&his, get_error_numeric(RPL_ISSUEDINVITE)->str,
+ NULL, chptr, sptr, SKIP_NONOPS,
+ "%H %C %C :%C has been invited by %C",
+ chptr, acptr, sptr, acptr, sptr);
+ /* Announce to servers with channel operators. */
+ sendcmdto_channel_servers_butone(sptr, NULL, TOK_INVITE, chptr, acptr, SKIP_NONOPS,
+ "%s %H %Tu", cli_name(acptr), chptr,
+ chptr->creationtime);
}
- else
- sendto_highprot_butone(acptr, 10, "%s%s " TOK_INVITE " %s :%s", /* XXX DEAD */
- NumNick(sptr), acptr->name, chptr->chname);
return 0;
}
-#endif /* 0 */
-