+2004-05-18 Michael Poole <mdpoole@troilus.org>
+
+ Announce invitations to other channel operators.
+
+ * include/ircd_features.h, ircd/ircd_features.c
+ (ANNOUNCE_INVITES): Add new boolean feature, default off.
+
+ * include/numeric.h, ircd/s_err.c (RPL_ISSUEDINVITE): Add new
+ reply.
+
+ * include/send.h, ircd/send.c (sendcmdto_channel_butserv_butone):
+ Add 'skip' parameter that is needed elsewhere.
+ (sendcmdto_channel_servers_butone): New function.
+
+ * ircd/channel.c, ircd/m_burst.c, ircd/m_kick.c, ircd/m_topic.c,
+ ircd/s_user.c: Add argument for 'skip' to calls to s_c_b_b.
+
+ * ircd/m_invite.c (m_invite, ms_invite): If ANNOUNCE_INVITES, send
+ the INVITE message to all interested servers, and send a numeric
+ to all local chanops.
+
2004-05-18 Michael Poole <mdpoole@troilus.org>
* ircd/res_adns.c (res_ourserver): Remove unused function.
FEAT_IRCD_RES_RETRIES,
FEAT_IRCD_RES_TIMEOUT,
FEAT_AUTH_TIMEOUT,
+ FEAT_ANNOUNCE_INVITES,
/* features that affect all operators */
FEAT_CRYPT_OPER_PASSWORD,
#define RPL_INVITING 341
/* RPL_SUMMONING 342 removed from RFC1459 */
+#define RPL_ISSUEDINVITE 345 /* Undernet extension */
#define RPL_INVITELIST 346 /* IRCnet, Undernet extension */
#define RPL_ENDOFINVITELIST 347 /* IRCnet, Undernet extension */
/* RPL_EXCEPTLIST 348 IRCnet extension */
const char *tok,
struct Channel *to,
struct Client *one,
+ unsigned int skip,
const char *pattern, ...);
+/* Send command to all servers interested in a channel */
+extern void sendcmdto_channel_servers_butone(struct Client *from,
+ const char *cmd,
+ const char *tok,
+ struct Channel *to,
+ struct Client *one,
+ unsigned int skip,
+ const char *pattern, ...);
+
/* Send command to all interested channel users */
extern void sendcmdto_channel_butone(struct Client *from, const char *cmd,
const char *tok, struct Channel *to,
addbuf_i ? "+" : "", addbuf, remstr, addstr);
if (mbuf->mb_dest & MODEBUF_DEST_CHANNEL)
- sendcmdto_channel_butserv_butone(app_source, CMD_MODE, mbuf->mb_channel, NULL,
+ sendcmdto_channel_butserv_butone(app_source, CMD_MODE, mbuf->mb_channel, NULL, 0,
"%H %s%s%s%s%s%s", mbuf->mb_channel,
rembuf_i ? "-" : "", rembuf,
addbuf_i ? "+" : "", addbuf, remstr, addstr);
/* Send notification to channel */
if (!(flags & (CHFL_ZOMBIE | CHFL_DELAYED)))
- sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_PART, chan, NULL,
+ sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_PART, chan, NULL, 0,
(flags & CHFL_BANNED || !jbuf->jb_comment) ?
":%H" : "%H :%s", chan, jbuf->jb_comment);
else if (MyUser(jbuf->jb_source))
if (!((chan->mode.mode & MODE_DELJOINS) && !(flags & CHFL_VOICED_OR_OPPED))) {
/* Send the notification to the channel */
- sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_JOIN, chan, NULL, "%H", chan);
+ sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_JOIN, chan, NULL, 0, "%H", chan);
/* send an op, too, if needed */
if (!MyUser(jbuf->jb_source) && jbuf->jb_type == JOINBUF_TYPE_CREATE)
- sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_MODE, chan, NULL, "%H +o %C",
+ sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_MODE, chan, NULL, 0, "%H +o %C",
chan, jbuf->jb_source);
} else if (MyUser(jbuf->jb_source))
sendcmdto_one(jbuf->jb_source, CMD_JOIN, jbuf->jb_source, ":%H", chan);
void RevealDelayedJoin(struct Membership *member) {
ClearDelayedJoin(member);
- sendcmdto_channel_butserv_butone(member->user, CMD_JOIN, member->channel, member->user, ":%H",
+ sendcmdto_channel_butserv_butone(member->user, CMD_JOIN, member->channel, member->user, 0, ":%H",
member->channel);
CheckDelayedJoins(member->channel);
}
if (!memb2) {
/* clear +d */
chan->mode.mode &= ~MODE_WASDELJOINS;
- sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan, NULL,
+ sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan, NULL, 0,
"%H -d", chan);
}
}
F_I(IRCD_RES_RETRIES, 0, 2, 0),
F_I(IRCD_RES_TIMEOUT, 0, 4, 0),
F_I(AUTH_TIMEOUT, 0, 9, 0),
+ F_B(ANNOUNCE_INVITES, 0, 0, 0),
/* features that affect all operators */
F_B(CRYPT_OPER_PASSWORD, FEAT_MYOPER | FEAT_READ, 1, 0),
if (!MyUser(member->user) || IsZombie(member))
continue;
sendcmdto_serv_butone(&me, CMD_KICK, NULL, "%H %C :Net Rider", chptr, member->user);
- sendcmdto_channel_butserv_butone(&me, CMD_KICK, chptr, NULL, "%H %C :Net Rider", chptr, member->user);
+ sendcmdto_channel_butserv_butone(&me, CMD_KICK, chptr, NULL, 0, "%H %C :Net Rider", chptr, member->user);
make_zombie(member, member->user, &me, &me, chptr);
}
}
*chptr->topic = '\0';
*chptr->topic_nick = '\0';
chptr->topic_time = 0;
- sendcmdto_channel_butserv_butone(&me, CMD_TOPIC, chptr, NULL,
+ sendcmdto_channel_butserv_butone(&me, CMD_TOPIC, chptr, NULL, 0,
"%H :%s", chptr, chptr->topic);
}
} else if (chptr->creationtime == timestamp) {
{
add_user_to_channel(chptr, acptr, current_mode, oplevel);
if (!(current_mode & CHFL_DELAYED))
- sendcmdto_channel_butserv_butone(acptr, CMD_JOIN, chptr, NULL, "%H", chptr);
+ sendcmdto_channel_butserv_butone(acptr, CMD_JOIN, chptr, NULL, 0, "%H", chptr);
}
else
{
#include "client.h"
#include "hash.h"
#include "ircd.h"
+#include "ircd_features.h"
#include "ircd_reply.h"
#include "ircd_string.h"
#include "list.h"
if (MyConnect(acptr))
add_invite(acptr, chptr);
- if (!IsLocalChannel(chptr->chname) || MyConnect(acptr))
- sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%H", cli_name(acptr), chptr);
+ if (!IsLocalChannel(chptr->chname) || MyConnect(acptr)) {
+ if (feature_bool(FEAT_ANNOUNCE_INVITES)) {
+ sendcmdto_channel_butserv_butone(&me, get_error_numeric(RPL_ISSUEDINVITE)->str,
+ NULL, chptr, sptr, SKIP_NONOPS,
+ "%C %C :%C has been invited by %C",
+ acptr, sptr, acptr, sptr);
+ sendcmdto_channel_servers_butone(sptr, NULL, TOK_INVITE, chptr, sptr, 0,
+ "%s :%H", cli_name(acptr), chptr);
+ if (MyConnect(acptr))
+ sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%H", cli_name(acptr), chptr);
+ }
+ else
+ sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%H", cli_name(acptr), chptr);
+ }
return 0;
}
send_reply(sptr, ERR_NOSUCHNICK, parv[1]);
return 0;
}
+ if (feature_bool(FEAT_ANNOUNCE_INVITES)) {
+ sendcmdto_channel_butserv_butone(&me, get_error_numeric(RPL_ISSUEDINVITE)->str,
+ NULL, chptr, sptr, SKIP_NONOPS,
+ "%C %C :%C has been invited by %C",
+ acptr, sptr, acptr, sptr);
+ sendcmdto_channel_servers_butone(sptr, NULL, TOK_INVITE, chptr, sptr, 0,
+ "%s :%H", cli_name(acptr), chptr);
+ if (MyConnect(acptr))
+ sendcmdto_one(sptr, CMD_INVITE, acptr, "%s :%H", cli_name(acptr), chptr);
+ return 0;
+ }
if (!MyUser(acptr)) {
/*
* just relay the message
sendcmdto_one(sptr, CMD_KICK, sptr, "%H %C :%s", chptr, who, comment);
CheckDelayedJoins(chptr);
} else
- sendcmdto_channel_butserv_butone(sptr, CMD_KICK, chptr, NULL, "%H %C :%s", chptr, who,
+ sendcmdto_channel_butserv_butone(sptr, CMD_KICK, chptr, NULL, 0, "%H %C :%s", chptr, who,
comment);
make_zombie(member, who, cptr, sptr, chptr);
if (member) { /* and tell the channel about it */
sendcmdto_channel_butserv_butone(IsServer(sptr) ? &me : sptr, CMD_KICK,
- chptr, NULL, "%H %C :%s", chptr, who,
+ chptr, NULL, 0, "%H %C :%s", chptr, who,
comment);
make_zombie(member, who, cptr, sptr, chptr);
sendcmdto_serv_butone(sptr, CMD_TOPIC, cptr, "%H %Tu %Tu :%s", chptr,
chptr->creationtime, chptr->topic_time, chptr->topic);
if (newtopic)
- sendcmdto_channel_butserv_butone(sptr, CMD_TOPIC, chptr, NULL,
+ sendcmdto_channel_butserv_butone(sptr, CMD_TOPIC, chptr, NULL, 0,
"%H :%s", chptr, chptr->topic);
/* if this is the same topic as before we send it to the person that
* set it (so they knew it went through ok), but don't bother sending
/* 344 */
{ 0 },
/* 345 */
- { 0 },
+ { RPL_ISSUEDINVITE, "%s %s %s :%s has been invited by %s", "345" },
/* 346 */
{ RPL_INVITELIST, ":%s", "346" },
/* 347 */
&& (chan->channel->mode.mode & MODE_DELJOINS))
SetDelayedJoin(chan);
else
- sendcmdto_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, cptr,
+ sendcmdto_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, cptr, 0,
"%H", chan->channel);
if (IsChanOp(chan) && HasVoice(chan))
- sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr,
+ sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr, 0,
"%H +ov %C %C", chan->channel, cptr,
cptr);
else if (IsChanOp(chan) || HasVoice(chan))
- sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr,
+ sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan->channel, cptr, 0,
"%H +%c %C", chan->channel, IsChanOp(chan) ? 'o' : 'v', cptr);
}
return 0;
* by <to>; <tok> is ignored by this function
*
* Update: don't send to 'one', if any. --Vampire
+ * Update: use 'skip' like sendcmdto_channel_butone. --Entrope
*/
void sendcmdto_channel_butserv_butone(struct Client *from, const char *cmd,
const char *tok, struct Channel *to,
- struct Client *one, const char *pattern,
- ...)
+ struct Client *one, unsigned int skip,
+ const char *pattern, ...)
{
struct VarData vd;
struct MsgBuf *mb;
/* send the buffer to each local channel member */
for (member = to->members; member; member = member->next_member) {
- if (MyConnect(member->user) && member->user != one && !IsZombie(member))
+ if (!MyConnect(member->user)
+ || member->user == one
+ || IsZombie(member)
+ || (skip & SKIP_DEAF && IsDeaf(member->user))
+ || (skip & SKIP_NONOPS && !IsChanOp(member))
+ || (skip & SKIP_NONVOICES && !IsChanOp(member) && !HasVoice(member)))
+ continue;
send_buffer(member->user, mb, 0);
}
msgq_clean(mb);
}
+/*
+ * Send a (prefixed) command to all servers with users on the channel
+ * specified by <to>; <cmd> and <skip> are ignored by this function.
+ *
+ * XXX sentalong_marker used XXX
+ */
+void sendcmdto_channel_servers_butone(struct Client *from, const char *cmd,
+ const char *tok, struct Channel *to,
+ struct Client *one, unsigned int skip,
+ const char *pattern, ...)
+{
+ struct VarData vd;
+ struct MsgBuf *serv_mb;
+ struct Membership *member;
+
+ /* build the buffer */
+ vd.vd_format = pattern;
+ va_start(vd.vd_args, pattern);
+ serv_mb = msgq_make(&me, "%:#C %s %v", from, tok, &vd);
+ va_end(vd.vd_args);
+
+ /* send the buffer to each server */
+ sentalong_marker++;
+ for (member = to->members; member; member = member->next_member) {
+ if (cli_from(member->user) == one
+ || MyConnect(member->user)
+ || IsZombie(member)
+ || cli_fd(cli_from(member->user)) < 0
+ || sentalong[cli_fd(cli_from(member->user))] == sentalong_marker)
+ continue;
+ sentalong[cli_fd(cli_from(member->user))] = sentalong_marker;
+ send_buffer(member->user, serv_mb, 0);
+ }
+ msgq_clean(serv_mb);
+}
+
+
/*
* Send a (prefixed) command to all users on this channel, including
* remote users; users to skip may be specified by setting appropriate