/***********************************************************************
* IRC - Internet Relay Chat, server/s_send.c
*
* Copyright (C) 2000-2003 TR-IRCD Development
*
* Copyright (C) 1990 Jarkko Oikarinen and
* University of Oulu, Co Center
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* $Id: s_send.c,v 1.9 2003/07/18 22:31:54 tr-ircd Exp $
*/
#include "struct.h"
#include "channel.h"
#include "common.h"
#include "sys.h"
#include "h.h"
#include "numeric.h"
#include "language.h"
#ifdef STATIC_MODULES
#define TOKEN 1
#include "msg.h"
#undef TOKEN
#else
#include "msg.h"
#endif
#include "supported.h"
#include "s_conf.h"
#define IRC_SB_SIZE 1024
#define IRC_RB_SIZE 4096
static char sendbuf[IRC_SB_SIZE];
static char privbuf[IRC_SB_SIZE];
static char servbuf[IRC_RB_SIZE];
static char remotebuf[IRC_RB_SIZE];
extern struct Token tok1_msgtab[];
static inline void clear_buffer(char *b, int size)
{
memset(b, 0, size * sizeof(char));
}
void init_send(void)
{
}
/*
* * send message to single client
*/
void sendto_one(aClient *to, char *pattern, ...)
{
va_list vl;
int len; /* used for the length of the current message */
va_start(vl, pattern);
clear_buffer(sendbuf, IRC_SB_SIZE);
len = ircvsprintf(sendbuf, pattern, vl);
if (to->from)
to = to->from;
send_message(to, sendbuf, len);
va_end(vl);
}
void vsendto_one(aClient *to, char *pattern, va_list vl)
{
int len; /* used for the length of the current message */
clear_buffer(sendbuf, IRC_SB_SIZE);
len = ircvsprintf(sendbuf, pattern, vl);
if (to->from)
to = to->from;
send_message(to, sendbuf, len);
}
void send_me_notice(aClient *cptr, char *pattern, ...)
{
char nbuf[1024];
int len;
va_list vl;
va_start(vl, pattern);
len = ircsprintf(nbuf, "%c%s %s %s ",
(IsIDCapable(cptr->from) ? '!' : ':'),
((MyClient(cptr) && UsesAlias(cptr)) ? ServerInfo.aliasname :
(IsIDCapable(cptr->from) ? me.id.string : me.name)),
/* We can safely user ServerInfo.aliasname, because it always exists,
* when user is PFLAGS_ALIASED -TimeMr14C
* Please note that ServerInfo.aliasname is not rehashable */
IsToken1(cptr->from) ? TOK1_NOTICE : MSG_NOTICE, cptr->name);
strncat(nbuf, pattern, 1024 - len);
vsendto_one(cptr, nbuf, vl);
va_end(vl);
return;
}
void send_me_numeric(aClient *cptr, int numeric, ...)
{
char nbuf[1024];
char *pattern = NULL;
int len;
va_list vl;
pattern = get_numeric_format_in_lang(&numeric, get_language(cptr->lang));
va_start(vl, numeric);
len = ircsprintf(nbuf, "%c%s %N %s ",
(IsIDCapable(cptr->from) ? '!' : ':'),
((MyClient(cptr) && UsesAlias(cptr)) ? ServerInfo.aliasname :
(IsIDCapable(cptr->from) ? me.id.string : me.name)), numeric, cptr->name);
strncat(nbuf, pattern, 1024 - len);
vsendto_one(cptr, nbuf, vl);
va_end(vl);
return;
}
void send_me_debug(aClient *cptr, char *pattern, ...)
{
char nbuf[1024];
int len;
va_list vl;
va_start(vl, pattern);
len = ircsprintf(nbuf, "%c%s %N %s ",
(IsIDCapable(cptr->from) ? '!' : ':'),
((MyClient(cptr) && UsesAlias(cptr)) ? ServerInfo.aliasname :
(IsIDCapable(cptr->from) ? me.id.string : me.name)),
RPL_STATSDEBUG, cptr->name);
strncat(nbuf, pattern, 1024 - len);
vsendto_one(cptr, nbuf, vl);
va_end(vl);
return;
}
void send_me_desynch(aClient *cptr, aChannel *chptr, char *ev, int val)
{
char nbuf[1024];
int len;
len = ircsnprintf(nbuf, 1024, "%c%s %N %s :Desynch by %s in channel %H (0 != %d)",
(IsIDCapable(cptr->from) ? '!' : ':'),
((MyClient(cptr) && UsesAlias(cptr)) ? ServerInfo.aliasname :
(IsIDCapable(cptr->from) ? me.id.string : me.name)),
ERR_DESYNC, cptr->name, ev, chptr, val);
sendto_one(cptr, nbuf);
logevent_personal("Desynch from %C by %s in channel %H (0 != %d)", cptr, ev, chptr, val);
}
static inline void vsendto_users(long umode, char *pattern, va_list vl)
{
aClient *cptr;
dlink_node *ptr;
for (ptr = lclient_list.head; ptr; ptr = ptr->next) {
cptr = ptr->data;
if (!cptr || (umode && !((cptr->umode & umode) == umode)))
continue;
vsendto_one(cptr, pattern, vl);
}
}
void sendto_all(char *pattern, ...)
{
va_list vl;
va_start(vl, pattern);
vsendto_users(0, pattern, vl);
va_end(vl);
return;
}
void sendto_users(long umode, char *pattern, ...)
{
va_list vl;
va_start(vl, pattern);
vsendto_users(umode, pattern, vl);
va_end(vl);
return;
}
static inline void vsendto_operators(long umode, char *type, char *pattern, va_list vl)
{
aClient *cptr;
char nbuf[1024];
dlink_node *ptr;
for (ptr = locoper_list.head; ptr; ptr = ptr->next) {
cptr = ptr->data;
if (!cptr || (umode && !((cptr->umode & umode) == umode)))
continue;
ircsprintf(nbuf, ":%C %s %s :*** %s -- %s", &me, MSG_NOTICE, cptr->name, type, pattern);
vsendto_one(cptr, nbuf, vl);
}
}
void sendto_gnotice(char *pattern, ...)
{
va_list vl;
va_start(vl, pattern);
vsendto_operators(UMODE_n, "Routing", pattern, vl);
va_end(vl);
return;
}
void sendto_ops(char *pattern, ...)
{
va_list vl;
va_start(vl, pattern);
vsendto_operators(0, "Notice", pattern, vl);
va_end(vl);
return;
}
void sendto_operators(long umode, char *type, char *pattern, ...)
{
va_list vl;
va_start(vl, pattern);
vsendto_operators(umode, type, pattern, vl);
va_end(vl);
return;
}
static inline char *prepare_server_prefixes(aClient *from, aChannel *chptr,
aClient *to, char *token,
char *const buffer, int *msglen)
{
int prefixlen = 0;
int lastlen = *msglen;
char *dest = NULL;
char *command = NULL;
char *chan = NULL;
clear_buffer(servbuf, IRC_RB_SIZE);
if (IsToken1(to))
command = token;
else
command = tok1_msgtab[(u_char) *token].cmd;
if (from) {
if (IsIDCapable(to) && HasID(from)) {
dest = from->id.string;
servbuf[prefixlen++] = '!';
} else {
dest = from->name;
servbuf[prefixlen++] = ':';
}
while (*dest)
servbuf[prefixlen++] = *dest++;
servbuf[prefixlen++] = ' ';
}
while (*command)
servbuf[prefixlen++] = *command++;
servbuf[prefixlen++] = ' ';
if (chptr) {
chan = chptr->chname;
while (*chan)
servbuf[prefixlen++] = *chan++;
servbuf[prefixlen++] = ' ';
}
if (lastlen) {
memcpy(&servbuf[prefixlen], buffer, lastlen);
servbuf[prefixlen + lastlen] = '\0';
} else {
if (servbuf[prefixlen - 1] == ' ')
prefixlen--;
servbuf[prefixlen] = '\0';
}
*msglen = lastlen + prefixlen;
return servbuf;
}
static inline char *prepare_server_prefixes_mask(aClient *from, aClient *to, char *token,
char *const buffer, int *msglen)
{
int prefixlen = 0;
int lastlen = *msglen;
char *dest = NULL;
char *command = NULL;
clear_buffer(servbuf, IRC_RB_SIZE);
if (IsToken1(to))
command = token;
else
command = tok1_msgtab[(u_char) *token].cmd;
if (from) {
if (IsIDCapable(to) && HasID(from)) {
dest = from->id.string;
servbuf[prefixlen++] = '!';
} else {
dest = from->name;
servbuf[prefixlen++] = ':';
}
while (*dest)
servbuf[prefixlen++] = *dest++;
servbuf[prefixlen++] = ' ';
}
while (*command)
servbuf[prefixlen++] = *command++;
servbuf[prefixlen++] = ' ';
if (lastlen) {
memcpy(&servbuf[prefixlen], buffer, lastlen);
servbuf[prefixlen + lastlen] = '\0';
} else {
if (servbuf[prefixlen - 1] == ' ')
prefixlen--;
servbuf[prefixlen] = '\0';
}
*msglen = lastlen + prefixlen;
return servbuf;
}
static inline char *prepare_service_prefixes(aClient *from, aChannel *chptr,
aService * svc, char *token,
char *const buffer, int *msglen)
{
int prefixlen = 0;
int lastlen = *msglen;
char *dest = NULL;
char *command = tok1_msgtab[(u_char) *token].cmd;
char *chan = NULL;
clear_buffer(remotebuf, IRC_RB_SIZE);
if (from) {
dest = from->name;
remotebuf[prefixlen++] = ':';
while (*dest)
remotebuf[prefixlen++] = *dest++;
if ((svc->enable & SERVICE_SEE_PREFIX) && from->user) {
dest = from->user->username;
remotebuf[prefixlen++] = '!';
while (*dest)
remotebuf[prefixlen++] = *dest++;
remotebuf[prefixlen++] = '@';
dest = from->user->host;
while (*dest)
remotebuf[prefixlen++] = *dest++;
}
remotebuf[prefixlen++] = ' ';
}
while (*command)
remotebuf[prefixlen++] = *command++;
remotebuf[prefixlen++] = ' ';
if (chptr) {
chan = chptr->chname;
while (*chan)
remotebuf[prefixlen++] = *chan++;
remotebuf[prefixlen++] = ' ';
}
if (lastlen) {
memcpy(&remotebuf[prefixlen], buffer, lastlen);
remotebuf[prefixlen + lastlen] = '\0';
} else {
if (remotebuf[prefixlen - 1] == ' ')
prefixlen--;
remotebuf[prefixlen] = '\0';
}
*msglen = lastlen + prefixlen;
return remotebuf;
}
static inline char *prepare_prefixes_localremote(aClient *from,
aClient *to, char *token,
char *const buffer, int *msglen)
{
int prefixlen = 0;
int lastlen = *msglen;
int alocal = MyClient(to);
char *dest = NULL;
char *command = NULL;
clear_buffer(remotebuf, IRC_RB_SIZE);
if (!alocal && IsServer(to) && IsToken1(to))
command = token;
else
command = tok1_msgtab[(u_char) *token].cmd;
if (from) {
if (IsIDCapable(to) && HasID(from)) {
dest = from->id.string;
remotebuf[prefixlen++] = '!';
} else {
dest = from->name;
remotebuf[prefixlen++] = ':';
}
while (*dest)
remotebuf[prefixlen++] = *dest++;
if (alocal && from->user) {
dest = from->user->username;
remotebuf[prefixlen++] = '!';
while (*dest)
remotebuf[prefixlen++] = *dest++;
remotebuf[prefixlen++] = '@';
dest = IsFake(from) ? from->user->fakehost : from->user->host;
while (*dest)
remotebuf[prefixlen++] = *dest++;
}
remotebuf[prefixlen++] = ' ';
}
while (*command)
remotebuf[prefixlen++] = *command++;
remotebuf[prefixlen++] = ' ';
if (lastlen) {
memcpy(&remotebuf[prefixlen], buffer, lastlen);
remotebuf[prefixlen + lastlen] = '\0';
} else {
if (remotebuf[prefixlen - 1] == ' ')
prefixlen--;
remotebuf[prefixlen] = '\0';
}
*msglen = lastlen + prefixlen;
return remotebuf;
}
static inline char *prepare_channel_prefixes_localremote(aClient *from,
aChannel *chptr,
aClient *to,
int hidden, int cflags,
char *token, int flag,
char *const buffer, int *msglen)
{
int prefixlen = 0;
int lastlen = *msglen;
int alocal = 0;
int use_token = 0;
char *dest = NULL;
char *command = NULL;
char *chan = chptr->chname;
clear_buffer(privbuf, IRC_SB_SIZE);
if (!to) {
alocal = 1;
use_token = 0;
} else {
alocal = MyClient(to);
if (!alocal)
use_token = IsToken1(to->from);
}
if (!alocal && use_token)
command = token;
else
command = tok1_msgtab[(u_char) *token].cmd;
if (IsMe(from))
alocal = 0;
if (from && (!hidden || cflags)) {
if (to && IsIDCapable(to->from) && HasID(from)) {
dest = from->id.string;
privbuf[prefixlen++] = '!';
} else {
dest = from->name;
privbuf[prefixlen++] = ':';
}
while (*dest)
privbuf[prefixlen++] = *dest++;
if (alocal && from->user) {
dest = from->user->username;
privbuf[prefixlen++] = '!';
while (*dest)
privbuf[prefixlen++] = *dest++;
privbuf[prefixlen++] = '@';
dest = IsFake(from) ? from->user->fakehost : from->user->host;
while (*dest)
privbuf[prefixlen++] = *dest++;
}
privbuf[prefixlen++] = ' ';
} else if (from && (hidden && !cflags)) {
privbuf[prefixlen++] = ':';
dest = chptr->chname;
while (*dest)
privbuf[prefixlen++] = *dest++;
privbuf[prefixlen++] = ' ';
}
while (*command)
privbuf[prefixlen++] = *command++;
privbuf[prefixlen++] = ' ';
if (flag & CHFL_CHANOP)
privbuf[prefixlen++] = '@';
if (flag & CHFL_VOICE)
privbuf[prefixlen++] = '+';
if (flag & CHFL_HALFOP)
privbuf[prefixlen++] = '%';
while (*chan)
privbuf[prefixlen++] = *chan++;
privbuf[prefixlen++] = ' ';
if (lastlen) {
memcpy(&privbuf[prefixlen], buffer, lastlen);
privbuf[prefixlen + lastlen] = '\0';
} else {
if (privbuf[prefixlen - 1] == ' ')
prefixlen--;
privbuf[prefixlen] = '\0';
}
*msglen = lastlen + prefixlen;
return privbuf;
}
static inline char *prepare_channel_prefixes_local_short(aClient *from,
aChannel *chptr, char *token, int *msglen)
{
int prefixlen = 0;
char *dest = NULL;
char *command = NULL;
char *chan = chptr->chname;
clear_buffer(privbuf, IRC_SB_SIZE);
command = tok1_msgtab[(u_char) *token].cmd;
if (from) {
dest = from->name;
privbuf[prefixlen++] = ':';
while (*dest)
privbuf[prefixlen++] = *dest++;
if (from->user) {
dest = from->user->username;
privbuf[prefixlen++] = '!';
while (*dest)
privbuf[prefixlen++] = *dest++;
privbuf[prefixlen++] = '@';
dest = IsFake(from) ? from->user->fakehost : from->user->host;
while (*dest)
privbuf[prefixlen++] = *dest++;
}
privbuf[prefixlen++] = ' ';
}
while (*command)
privbuf[prefixlen++] = *command++;
privbuf[prefixlen++] = ' ';
if (*chan)
privbuf[prefixlen++] = ':';
/* The above issue is only required by JOIN, since the channel name is prepended
* with a semicolon.
* -TimeMr14C, 6/8/2002
*/
while (*chan)
privbuf[prefixlen++] = *chan++;
privbuf[prefixlen++] = ' ';
if (privbuf[prefixlen - 1] == ' ')
prefixlen--;
privbuf[prefixlen] = '\0';
*msglen = prefixlen;
return privbuf;
}
static void __new_vsendto_list_butone(dlink_list * listp,
aClient *one, aClient *from,
int incflags, int exflags,
aChannel *chptr, char *token, char *pattern, va_list vl)
{
int len;
int t;
char *txt;
dlink_node *ptr, *next_ptr;
aClient *cptr;
for (ptr = listp->head; ptr; ptr = next_ptr) {
next_ptr = ptr->next;
cptr = ptr->data;
if (!cptr || (cptr == one)
|| (incflags && !((cptr->capabilities & incflags) == incflags))
|| (exflags && (cptr->capabilities & exflags) == exflags))
continue;
clear_buffer(sendbuf, IRC_SB_SIZE);
t = len = ircvsprintf(sendbuf, pattern, vl);
txt = prepare_server_prefixes(from, chptr, cptr, token, sendbuf, &len);
send_message(cptr, txt, len);
}
}
/*
* sendto_flag_serv_butone
*
* Send a message to all connected servers except the client 'one'.
* Only if they include INCLUDE and exclude EXCLUDE
*/
void sendto_flag_serv_butone(aClient *one, int include, int exclude,
aClient *from, char *token, char *pattern, ...)
{
va_list vl;
va_start(vl, pattern);
__new_vsendto_list_butone(&serv_list, one, from, include, exclude, NULL, token, pattern, vl);
va_end(vl);
return;
}
void sendto_serv_butone(aClient *one, aClient *from, char *token, char *pattern, ...)
{
va_list vl;
va_start(vl, pattern);
__new_vsendto_list_butone(&serv_list, one, from, 0, 0, NULL, token, pattern, vl);
va_end(vl);
return;
}
void sendto_match_servs(aChannel *chptr, aClient *from, char *token, char *pattern, ...)
{
va_list vl;
if (chptr)
if (*chptr->chname == '&')
return;
va_start(vl, pattern);
__new_vsendto_list_butone(&serv_list, from->from, from, 0, 0, chptr, token, pattern, vl);
va_end(vl);
return;
}
void sendto_one_server(aClient *to, aClient *from, char *token, char *pattern, ...)
{
va_list vl;
int len;
char *txt;
va_start(vl, pattern);
clear_buffer(sendbuf, IRC_SB_SIZE);
len = ircvsprintf(sendbuf, pattern, vl);
if (to->from)
to = to->from;
txt = prepare_server_prefixes(from, NULL, to, token, sendbuf, &len);
send_message(to, txt, len);
va_end(vl);
}
void sendto_one_person(aClient *to, aClient *from, char *token, char *pattern, ...)
{
va_list vl;
int len; /* used for the length of the current message */
char *txt;
va_start(vl, pattern);
clear_buffer(sendbuf, IRC_SB_SIZE);
len = ircvsprintf(sendbuf, pattern, vl);
if (to->from)
to = to->from;
txt = prepare_prefixes_localremote(from, to, token, sendbuf, &len);
send_message(to, txt, len);
va_end(vl);
}
static int match_it(aClient *one, char *mask, int what)
{
if (what == MATCH_HOST)
return (match(mask, one->user->host) == 0);
else
return (match(mask, one->user->server) == 0);
}
void sendto_match_butone(aClient *one, char *mask, int what, aClient *from, char *pattern, ...)
{
aClient *cptr;
dlink_node *ptr, *next_ptr;
va_list vl;
int len, t;
char *txt;
va_start(vl, pattern);
for (ptr = lclient_list.head; ptr; ptr = next_ptr) {
next_ptr = ptr->next;
cptr = ptr->data;
if (!cptr)
continue;
if (cptr == one) /* must skip the origin !! */
continue;
if (!(IsPerson(cptr) && match_it(cptr, mask, what)))
continue;
clear_buffer(sendbuf, IRC_SB_SIZE);
len = ircvsprintf(sendbuf, pattern, vl);
t = len;
txt = prepare_prefixes_localremote(from, cptr, TOK1_NOTICE, sendbuf, &len);
send_message(cptr, txt, len);
}
for (ptr = serv_list.head; ptr; ptr = next_ptr) {
next_ptr = ptr->next;
cptr = ptr->data;
if (cptr == NULL)
continue;
if (cptr == one)
continue;
clear_buffer(sendbuf, IRC_SB_SIZE);
len = ircvsprintf(sendbuf, pattern, vl);
t = len;
txt = prepare_server_prefixes_mask(from, cptr, TOK1_NOTICE, sendbuf, &len);
send_message(cptr, txt, len);
}
va_end(vl);
return;
}
void sendto_service(int include, int exclude, aClient *from,
aChannel *chptr, char *token, char *pattern, ...)
{
aService *svc, *next_svc;
va_list vl;
int msglen = 0;
int t;
char *txt;
va_start(vl, pattern);
for (svc = firstservice; svc; svc = next_svc) {
next_svc = svc->next;
if ((svc->scptr == NULL) || (!MyConnect(svc->scptr)) ||
(include && !((svc->enable & include) == include)) ||
(exclude && (svc->enable & exclude) == exclude))
continue;
clear_buffer(sendbuf, IRC_SB_SIZE);
t = msglen = ircvsprintf(sendbuf, pattern, vl);
txt = prepare_service_prefixes(from, chptr, svc, token, sendbuf, &msglen);
send_message(svc->scptr, txt, msglen);
}
va_end(vl);
return;
}
static inline int check_fake_direction(aClient *from, aClient *to)
{
if (!MyClient(from) && IsPerson(to) && (to->from == from->from)) {
if (IsServer(from)) {
sendto_lev(SNOTICE_LEV, "Message to %s[%s] dropped from %s (Fake Direction)",
to->name, to->from->name, from->name);
return -1;
}
sendto_ops("Ghosted: %C from %C (%C)", to, from, to->from);
sendto_serv_butone(NULL, &me, TOK1_KILL, "%~C :Ghosted %s", to, to->from->name);
to->flags |= FLAGS_KILLED;
exit_client(to, &me, "Ghosted client");
return -1;
}
return 0;
}
void sendto_channel_butone(aClient *one, int incflags, int exflags, aClient *from,
aChannel *chptr, char *token, char *pattern, ...)
{
struct ChanMember *cm;
aClient *acptr;
int msglen = 0;
int t;
va_list vl;
char *txt;
dlink_node *ptr, *next_ptr;
int i;
unsigned long ssentalong[MAXCONNECTIONS];
memset(ssentalong, 0, MAXCONNECTIONS * sizeof(unsigned long));
va_start(vl, pattern);
for (ptr = chptr->members.head; ptr; ptr = next_ptr) {
next_ptr = ptr->next;
cm = ptr->data;
if (!cm)
continue;
acptr = cm->client_p;
if ((acptr->from == one) || IsAnon(acptr)
|| ((cm->flags & incflags) != incflags))
continue; /* skip the ONE and those who do not have these flags */
i = acptr->fd;
if (check_fake_direction(from, acptr))
continue;
clear_buffer(sendbuf, IRC_SB_SIZE);
t = msglen = ircvsprintf(sendbuf, pattern, vl);
if (MyClient(acptr)) {
txt = prepare_channel_prefixes_localremote(from, chptr, acptr, 0, 0,
token, incflags, sendbuf, &msglen);
send_message(acptr, txt, msglen);
ssentalong[i] = 1;
} else {
if (!acptr->from)
continue;
i = acptr->from->fd;
if (ssentalong[i] != 1) {
txt = prepare_channel_prefixes_localremote(from, chptr, acptr, 0, 0,
token, incflags, sendbuf, &msglen);
send_message(acptr->from, txt, msglen);
ssentalong[i] = 1;
}
}
}
va_end(vl);
return;
}
/*
* sendto_common_channels()
*
* Sends a message to all people (inclusing user) on local server who are
* in same channel with user.
*/
void sendto_common_channels(aClient *from, char *pattern, ...)
{
struct ChanMember *cm;
aChannel *chptr;
aClient *cptr;
va_list vl;
int msglen = 0;
int i;
dlink_node *chn, *next_chn;
dlink_node *usr, *next_usr;
unsigned long ssentalong[MAXCONNECTIONS];
memset(ssentalong, 0, MAXCONNECTIONS * sizeof(unsigned long));
if (from->fd > 0)
ssentalong[from->fd] = 1;
va_start(vl, pattern);
if (from->user) {
for (chn = from->user->channel.head; chn; chn = next_chn) {
next_chn = chn->next;
chptr = chn->data;
if (IsChanAnon(chptr))
continue;
for (usr = chptr->members.head; usr; usr = next_usr) {
next_usr = usr->next;
cm = usr->data;
if (!cm)
continue;
cptr = cm->client_p;
i = cptr->fd;
if (!MyConnect(cptr) || IsAnon(cptr) || (from == cptr) ||
ssentalong[i] == 1)
continue;
if (check_fake_direction(from, cptr))
continue;
clear_buffer(sendbuf, IRC_SB_SIZE);
msglen = ircvsprintf(sendbuf, pattern, vl);
send_message(cptr, sendbuf, msglen);
ssentalong[i] = 1;
}
}
}
if (MyConnect(from)) {
clear_buffer(sendbuf, IRC_SB_SIZE);
msglen = ircvsprintf(sendbuf, pattern, vl);
send_message(from, sendbuf, msglen);
}
va_end(vl);
return;
}
/*
* send_quit_to_common_channels()
*
* Sends a message to all people (inclusing user) on local server who are
* in same channel with user if the user can send to this channel.
*/
void send_quit_to_common_channels(aClient *from, char *reason)
{
struct ChanMember *cm;
dlink_node *channels, *next_chan;
dlink_node *users, *next_user;
aChannel *chptr;
aClient *cptr;
int msglen;
int i, j;
int sentalong[MAXCONNECTIONS];
for (j = 0; j < MAXCONNECTIONS; j++)
sentalong[j] = 0;
// memset(sentalong, 0, MAXCONNECTIONS * sizeof(int));
if (from->fd > 0)
sentalong[from->fd] = 1;
/* This loop is required, since buffers get replaced everytime when
* we enter this function within this function, because exit_client is
* called. After exit_client normally a client would be marked as closing,
* that flag signals us that we have to restart the whole function, since
* all of the used pointers are now dumb.
* -TimeMr14C 09.04.2003
*/
closeloop:
for (channels = from->user->channel.head; channels; channels = next_chan) {
next_chan = channels->next;
chptr = channels->data;
if (!can_send(from, chptr, reason) && !IsChanHidePartQuit(chptr)) {
for (users = chptr->members.head; users; users = next_user) {
next_user = users->next;
cm = users->data;
if (!cm)
continue;
cptr = cm->client_p;
i = cptr->fd;
if (!MyConnect(cptr) || IsAnon(cptr) || (cptr == from) ||
sentalong[i] == 1)
continue;
if (check_fake_direction(from, cptr))
continue;
clear_buffer(sendbuf, IRC_SB_SIZE);
msglen = ircsprintf(sendbuf, ":%C %s :%s", from, MSG_QUIT, reason);
send_message(cptr, sendbuf, msglen);
sentalong[i] = 1;
if (IsClosing(cptr))
goto closeloop;
}
} else if (!IsChanAnon(chptr)) {
for (users = chptr->members.head; users; users = next_user) {
next_user = users->next;
cm = users->data;
if (!cm)
continue;
cptr = cm->client_p;
i = cptr->fd;
if (!MyConnect(cptr) || IsAnon(cptr) || (cptr == from) ||
sentalong[i] == 1)
continue;
if (check_fake_direction(from, cptr))
continue;
clear_buffer(sendbuf, IRC_SB_SIZE);
msglen = ircsprintf(sendbuf, ":%C %s %H", from, MSG_PART, chptr);
send_message(cptr, sendbuf, msglen);
sentalong[i] = 1;
if (IsClosing(cptr))
goto closeloop;
}
}
remove_user_from_channel(from, chptr);
}
return;
}
/*
* sendto_channel_butserv
*
* Send a message to all members of a channel that are connected to this
* server.
*/
void sendto_channel_butserv(aChannel *chptr, aClient *from, char *token,
int flags, char *pattern, ...)
{
struct ChanMember *cm;
char *txt;
aClient *acptr;
va_list vl;
int msglen = 0;
int t = 0;
int noanon = 0;
dlink_node *ptr, *next_ptr;
va_start(vl, pattern);
clear_buffer(sendbuf, IRC_SB_SIZE);
msglen = ircvsprintf(sendbuf, pattern, vl);
txt = prepare_channel_prefixes_localremote(from, chptr, NULL, 0, 0, token, 0, sendbuf, &msglen);
t = msglen;
if (MyClient(from)) {
send_message(from, txt, msglen);
if (IsChanAnon(chptr) && IsLocalChan(chptr->chname))
return;
}
if (IsChanAnon(chptr) && IsGlobalChan(chptr->chname))
return;
noanon = (flags & CHFL_RESANON);
for (ptr = chptr->members.head; ptr; ptr = next_ptr) {
next_ptr = ptr->next;
cm = ptr->data;
msglen = t;
if (!cm)
continue;
acptr = cm->client_p;
if (!MyConnect(acptr) || (acptr == from) || IsAnon(acptr)) {
continue;
}
if (check_fake_direction(from, acptr))
continue;
clear_buffer(sendbuf, IRC_SB_SIZE);
msglen = ircvsprintf(sendbuf, pattern, vl);
txt = prepare_channel_prefixes_localremote(from, chptr, NULL,
(noanon ? 0 : IsChanHideOps(chptr)),
(noanon ? 0 : (flags & cm->flags)),
token, 0, sendbuf, &msglen);
send_message(acptr, txt, msglen);
}
va_end(vl);
return;
}
void sendto_channel_butserv_short(aChannel *chptr, aClient *from, char *token)
{
struct ChanMember *cm;
char *txt;
aClient *acptr;
int msglen = 0;
dlink_node *ptr, *next_ptr;
txt = prepare_channel_prefixes_local_short(from, chptr, token, &msglen);
if (MyClient(from)) {
send_message(from, txt, msglen);
if (IsChanAnon(chptr) && IsLocalChan(chptr->chname))
return;
}
if (IsChanAnon(chptr) && IsGlobalChan(chptr->chname))
return;
for (ptr = chptr->members.head; ptr; ptr = next_ptr) {
next_ptr = ptr->next;
cm = ptr->data;
if (!cm)
continue;
acptr = cm->client_p;
if (!MyConnect(acptr) || (acptr == from) || IsAnon(acptr))
continue;
if (check_fake_direction(from, acptr))
continue;
send_message(acptr, txt, msglen);
}
return;
}
int send_supported(aClient *cptr)
{
char featurebuf[1024];
ircsnprintf(featurebuf, sizeof(featurebuf), FEATURESET1, MAXBANS, TOPICLEN, TOPICLEN);
send_me_numeric(cptr, RPL_ISUPPORT, featurebuf);
ircsnprintf(featurebuf, sizeof(featurebuf), FEATURESET2, MAXWATCH, MAXMODEPARAMS,
MAXSILES, NICKLEN, "(uohv).@%+", GeneralOpts.chanmodelist,
ServerInfo.networkname, ChannelConf.max_channels_per_user);
send_me_numeric(cptr, RPL_ISUPPORT, featurebuf);
return 0;
}
/*
* kill_client
*
* inputs - client to send kill towards
* - pointer to client to kill
* - reason for kill
* output - NONE
* side effects - NONE
*/
void kill_client(struct Client *client_p, struct Client *diedie, char *pattern, ...)
{
va_list args;
char buf[BUFSIZE];
va_start(args, pattern);
ircvsprintf(buf, pattern, args);
va_end(args);
sendto_one_server(client_p, &me, TOK1_KILL, "%~C :%s", diedie, buf);
}
syntax highlighted by Code2HTML, v. 0.9.1