Apply +z to messages blocked by +b and +q as well.
This adds a new server capab EOPMOD which will be used for an extended topic command also.
This commit is contained in:
parent
1ba5ea0f06
commit
c4d2d01419
7 changed files with 193 additions and 9 deletions
|
@ -544,6 +544,9 @@ The target can be:
|
||||||
with that status or higher only.
|
with that status or higher only.
|
||||||
capab: CHW
|
capab: CHW
|
||||||
propagation: all servers with -D users with appropriate status
|
propagation: all servers with -D users with appropriate status
|
||||||
|
- '=' followed by a channel name, to send to chanops only, for cmode +z.
|
||||||
|
capab: CHW and EOPMOD
|
||||||
|
propagation: all servers with -D chanops
|
||||||
- a user@server message, to send to users on a specific server. The exact
|
- a user@server message, to send to users on a specific server. The exact
|
||||||
meaning of the part before the '@' is not prescribed, except that "opers"
|
meaning of the part before the '@' is not prescribed, except that "opers"
|
||||||
allows IRC operators to send to all IRC operators on the server in an
|
allows IRC operators to send to all IRC operators on the server in an
|
||||||
|
|
|
@ -16,7 +16,8 @@ NO PARAMETERS:
|
||||||
+c - No color. All color codes in messages are stripped.
|
+c - No color. All color codes in messages are stripped.
|
||||||
+g - Free invite. Everyone may invite users. Significantly
|
+g - Free invite. Everyone may invite users. Significantly
|
||||||
weakens +i control.
|
weakens +i control.
|
||||||
+z - Op moderated. Messages blocked by +m are instead sent to ops.
|
+z - Op moderated. Messages blocked by +m, +b and +q are instead
|
||||||
|
sent to ops.
|
||||||
+L - Large ban list. Increase maximum number of +beIq entries.
|
+L - Large ban list. Increase maximum number of +beIq entries.
|
||||||
Only settable by opers.
|
Only settable by opers.
|
||||||
+P - Permanent. Channel does not disappear when empty. Only
|
+P - Permanent. Channel does not disappear when empty. Only
|
||||||
|
|
|
@ -70,12 +70,13 @@ struct Capability
|
||||||
#define CAP_RSFNC 0x20000 /* rserv FNC */
|
#define CAP_RSFNC 0x20000 /* rserv FNC */
|
||||||
#define CAP_SAVE 0x40000 /* supports SAVE (nick collision FNC) */
|
#define CAP_SAVE 0x40000 /* supports SAVE (nick collision FNC) */
|
||||||
#define CAP_EUID 0x80000 /* supports EUID (ext UID + nonencap CHGHOST) */
|
#define CAP_EUID 0x80000 /* supports EUID (ext UID + nonencap CHGHOST) */
|
||||||
|
#define CAP_EOPMOD 0x100000 /* supports EOPMOD (ext +z + ext topic) */
|
||||||
|
|
||||||
#define CAP_MASK (CAP_QS | CAP_EX | CAP_CHW | \
|
#define CAP_MASK (CAP_QS | CAP_EX | CAP_CHW | \
|
||||||
CAP_IE | CAP_KLN | CAP_SERVICE |\
|
CAP_IE | CAP_KLN | CAP_SERVICE |\
|
||||||
CAP_CLUSTER | CAP_ENCAP | \
|
CAP_CLUSTER | CAP_ENCAP | \
|
||||||
CAP_ZIP | CAP_KNOCK | CAP_UNKLN | \
|
CAP_ZIP | CAP_KNOCK | CAP_UNKLN | \
|
||||||
CAP_RSFNC | CAP_SAVE | CAP_EUID)
|
CAP_RSFNC | CAP_SAVE | CAP_EUID | CAP_EOPMOD)
|
||||||
|
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
#define CAP_ZIP_SUPPORTED CAP_ZIP
|
#define CAP_ZIP_SUPPORTED CAP_ZIP
|
||||||
|
|
|
@ -57,6 +57,9 @@ extern void sendto_server(struct Client *one, struct Channel *chptr,
|
||||||
|
|
||||||
extern void sendto_channel_flags(struct Client *one, int type, struct Client *source_p,
|
extern void sendto_channel_flags(struct Client *one, int type, struct Client *source_p,
|
||||||
struct Channel *chptr, const char *, ...) AFP(5, 6);
|
struct Channel *chptr, const char *, ...) AFP(5, 6);
|
||||||
|
extern void sendto_channel_opmod(struct Client *one, struct Client *source_p,
|
||||||
|
struct Channel *chptr, const char *command,
|
||||||
|
const char *text);
|
||||||
|
|
||||||
extern void sendto_channel_local(int type, struct Channel *, const char *, ...) AFP(3, 4);
|
extern void sendto_channel_local(int type, struct Channel *, const char *, ...) AFP(3, 4);
|
||||||
extern void sendto_channel_local_butone(struct Client *, int type, struct Channel *, const char *, ...) AFP(4, 5);
|
extern void sendto_channel_local_butone(struct Client *, int type, struct Channel *, const char *, ...) AFP(4, 5);
|
||||||
|
|
|
@ -97,8 +97,9 @@ static int flood_attack_channel(int p_or_n, struct Client *source_p,
|
||||||
|
|
||||||
#define ENTITY_NONE 0
|
#define ENTITY_NONE 0
|
||||||
#define ENTITY_CHANNEL 1
|
#define ENTITY_CHANNEL 1
|
||||||
#define ENTITY_CHANOPS_ON_CHANNEL 2
|
#define ENTITY_CHANNEL_OPMOD 2
|
||||||
#define ENTITY_CLIENT 3
|
#define ENTITY_CHANOPS_ON_CHANNEL 3
|
||||||
|
#define ENTITY_CLIENT 4
|
||||||
|
|
||||||
static struct entity targets[512];
|
static struct entity targets[512];
|
||||||
static int ntargets = 0;
|
static int ntargets = 0;
|
||||||
|
@ -109,6 +110,11 @@ static void msg_channel(int p_or_n, const char *command,
|
||||||
struct Client *client_p,
|
struct Client *client_p,
|
||||||
struct Client *source_p, struct Channel *chptr, const char *text);
|
struct Client *source_p, struct Channel *chptr, const char *text);
|
||||||
|
|
||||||
|
static void msg_channel_opmod(int p_or_n, const char *command,
|
||||||
|
struct Client *client_p,
|
||||||
|
struct Client *source_p, struct Channel *chptr,
|
||||||
|
const char *text);
|
||||||
|
|
||||||
static void msg_channel_flags(int p_or_n, const char *command,
|
static void msg_channel_flags(int p_or_n, const char *command,
|
||||||
struct Client *client_p,
|
struct Client *client_p,
|
||||||
struct Client *source_p,
|
struct Client *source_p,
|
||||||
|
@ -204,6 +210,11 @@ m_message(int p_or_n,
|
||||||
(struct Channel *) targets[i].ptr, parv[2]);
|
(struct Channel *) targets[i].ptr, parv[2]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ENTITY_CHANNEL_OPMOD:
|
||||||
|
msg_channel_opmod(p_or_n, command, client_p, source_p,
|
||||||
|
(struct Channel *) targets[i].ptr, parv[2]);
|
||||||
|
break;
|
||||||
|
|
||||||
case ENTITY_CHANOPS_ON_CHANNEL:
|
case ENTITY_CHANOPS_ON_CHANNEL:
|
||||||
msg_channel_flags(p_or_n, command, client_p, source_p,
|
msg_channel_flags(p_or_n, command, client_p, source_p,
|
||||||
(struct Channel *) targets[i].ptr,
|
(struct Channel *) targets[i].ptr,
|
||||||
|
@ -382,6 +393,32 @@ build_target_list(int p_or_n, const char *command, struct Client *client_p,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(IsServer(client_p) && *nick == '=' && nick[1] == '#')
|
||||||
|
{
|
||||||
|
nick++;
|
||||||
|
if((chptr = find_channel(nick)) != NULL)
|
||||||
|
{
|
||||||
|
if(!duplicate_ptr(chptr))
|
||||||
|
{
|
||||||
|
if(ntargets >= ConfigFileEntry.max_targets)
|
||||||
|
{
|
||||||
|
sendto_one(source_p, form_str(ERR_TOOMANYTARGETS),
|
||||||
|
me.name, source_p->name, nick);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
targets[ntargets].ptr = (void *) chptr;
|
||||||
|
targets[ntargets++].type = ENTITY_CHANNEL_OPMOD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* non existant channel */
|
||||||
|
else if(p_or_n != NOTICE)
|
||||||
|
sendto_one_numeric(source_p, ERR_NOSUCHNICK,
|
||||||
|
form_str(ERR_NOSUCHNICK), nick);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* no matching anything found - error if not NOTICE */
|
/* no matching anything found - error if not NOTICE */
|
||||||
if(p_or_n != NOTICE)
|
if(p_or_n != NOTICE)
|
||||||
{
|
{
|
||||||
|
@ -476,16 +513,65 @@ msg_channel(int p_or_n, const char *command,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(chptr->mode.mode & MODE_OPMODERATE &&
|
else if(chptr->mode.mode & MODE_OPMODERATE &&
|
||||||
chptr->mode.mode & MODE_MODERATED &&
|
|
||||||
(!(chptr->mode.mode & MODE_NOPRIVMSGS) ||
|
(!(chptr->mode.mode & MODE_NOPRIVMSGS) ||
|
||||||
IsMember(source_p, chptr)))
|
IsMember(source_p, chptr)))
|
||||||
{
|
{
|
||||||
/* only do +z for +m channels for now, as bans/quiets
|
|
||||||
* aren't tested for remote clients -- jilles */
|
|
||||||
if(!flood_attack_channel(p_or_n, source_p, chptr, chptr->chname))
|
if(!flood_attack_channel(p_or_n, source_p, chptr, chptr->chname))
|
||||||
{
|
{
|
||||||
sendto_channel_flags(client_p, ONLY_CHANOPS, source_p, chptr,
|
sendto_channel_opmod(client_p, source_p, chptr,
|
||||||
"%s %s :%s", command, chptr->chname, text);
|
command, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(p_or_n != NOTICE)
|
||||||
|
sendto_one_numeric(source_p, ERR_CANNOTSENDTOCHAN,
|
||||||
|
form_str(ERR_CANNOTSENDTOCHAN), chptr->chname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* msg_channel_opmod
|
||||||
|
*
|
||||||
|
* inputs - flag privmsg or notice
|
||||||
|
* - pointer to command "PRIVMSG" or "NOTICE"
|
||||||
|
* - pointer to client_p
|
||||||
|
* - pointer to source_p
|
||||||
|
* - pointer to channel
|
||||||
|
* output - NONE
|
||||||
|
* side effects - message given channel ops
|
||||||
|
*
|
||||||
|
* XXX - We need to rework this a bit, it's a tad ugly. --nenolod
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
msg_channel_opmod(int p_or_n, const char *command,
|
||||||
|
struct Client *client_p, struct Client *source_p,
|
||||||
|
struct Channel *chptr, const char *text)
|
||||||
|
{
|
||||||
|
char text2[BUFSIZE];
|
||||||
|
|
||||||
|
if(chptr->mode.mode & MODE_NOCOLOR)
|
||||||
|
{
|
||||||
|
rb_strlcpy(text2, text, BUFSIZE);
|
||||||
|
strip_colour(text2);
|
||||||
|
text = text2;
|
||||||
|
if (EmptyString(text))
|
||||||
|
{
|
||||||
|
/* could be empty after colour stripping and
|
||||||
|
* that would cause problems later */
|
||||||
|
if(p_or_n != NOTICE)
|
||||||
|
sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), me.name, source_p->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chptr->mode.mode & MODE_OPMODERATE &&
|
||||||
|
(!(chptr->mode.mode & MODE_NOPRIVMSGS) ||
|
||||||
|
IsMember(source_p, chptr)))
|
||||||
|
{
|
||||||
|
if(!flood_attack_channel(p_or_n, source_p, chptr, chptr->chname))
|
||||||
|
{
|
||||||
|
sendto_channel_opmod(client_p, source_p, chptr,
|
||||||
|
command, text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -91,6 +91,7 @@ struct Capability captab[] = {
|
||||||
{ "RSFNC", CAP_RSFNC },
|
{ "RSFNC", CAP_RSFNC },
|
||||||
{ "SAVE", CAP_SAVE },
|
{ "SAVE", CAP_SAVE },
|
||||||
{ "EUID", CAP_EUID },
|
{ "EUID", CAP_EUID },
|
||||||
|
{ "EOPMOD", CAP_EOPMOD },
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
89
src/send.c
89
src/send.c
|
@ -531,6 +531,95 @@ sendto_channel_flags(struct Client *one, int type, struct Client *source_p,
|
||||||
rb_linebuf_donebuf(&rb_linebuf_id);
|
rb_linebuf_donebuf(&rb_linebuf_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sendto_channel_flags()
|
||||||
|
*
|
||||||
|
* inputs - server not to send to, flags needed, source, channel, va_args
|
||||||
|
* outputs - message is sent to channel members
|
||||||
|
* side effects -
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
sendto_channel_opmod(struct Client *one, struct Client *source_p,
|
||||||
|
struct Channel *chptr, const char *command,
|
||||||
|
const char *text)
|
||||||
|
{
|
||||||
|
static char buf[BUFSIZE];
|
||||||
|
va_list args;
|
||||||
|
buf_head_t rb_linebuf_local;
|
||||||
|
buf_head_t rb_linebuf_old;
|
||||||
|
buf_head_t rb_linebuf_new;
|
||||||
|
struct Client *target_p;
|
||||||
|
struct membership *msptr;
|
||||||
|
rb_dlink_node *ptr;
|
||||||
|
rb_dlink_node *next_ptr;
|
||||||
|
|
||||||
|
rb_linebuf_newbuf(&rb_linebuf_local);
|
||||||
|
rb_linebuf_newbuf(&rb_linebuf_old);
|
||||||
|
rb_linebuf_newbuf(&rb_linebuf_new);
|
||||||
|
|
||||||
|
current_serial++;
|
||||||
|
|
||||||
|
if(IsServer(source_p))
|
||||||
|
rb_linebuf_putmsg(&rb_linebuf_local, NULL, NULL,
|
||||||
|
":%s %s %s :%s",
|
||||||
|
source_p->name, command, chptr->chname, text);
|
||||||
|
else
|
||||||
|
rb_linebuf_putmsg(&rb_linebuf_local, NULL, NULL,
|
||||||
|
":%s!%s@%s %s %s :%s",
|
||||||
|
source_p->name, source_p->username,
|
||||||
|
source_p->host, command, chptr->chname, text);
|
||||||
|
|
||||||
|
if (chptr->mode.mode & MODE_MODERATED)
|
||||||
|
rb_linebuf_putmsg(&rb_linebuf_old, NULL, NULL,
|
||||||
|
":%s %s %s :%s",
|
||||||
|
use_id(source_p), command, chptr->chname, text);
|
||||||
|
else
|
||||||
|
rb_linebuf_putmsg(&rb_linebuf_old, NULL, NULL,
|
||||||
|
":%s NOTICE @%s :<%s:%s> %s",
|
||||||
|
use_id(source_p->servptr), chptr->chname,
|
||||||
|
source_p->name, chptr->chname, text);
|
||||||
|
rb_linebuf_putmsg(&rb_linebuf_new, NULL, NULL,
|
||||||
|
":%s %s =%s :%s",
|
||||||
|
use_id(source_p), command, chptr->chname, text);
|
||||||
|
|
||||||
|
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, chptr->members.head)
|
||||||
|
{
|
||||||
|
msptr = ptr->data;
|
||||||
|
target_p = msptr->client_p;
|
||||||
|
|
||||||
|
if(IsIOError(target_p->from) || target_p->from == one)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if((msptr->flags & CHFL_CHANOP) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(IsDeaf(target_p))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!MyClient(target_p))
|
||||||
|
{
|
||||||
|
/* if we've got a specific type, target must support
|
||||||
|
* CHW.. --fl
|
||||||
|
*/
|
||||||
|
if(NotCapable(target_p->from, CAP_CHW))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(target_p->from->serial != current_serial)
|
||||||
|
{
|
||||||
|
if (IsCapable(target_p->from, CAP_EOPMOD))
|
||||||
|
send_linebuf_remote(target_p, source_p, &rb_linebuf_new);
|
||||||
|
else
|
||||||
|
send_linebuf_remote(target_p, source_p, &rb_linebuf_old);
|
||||||
|
target_p->from->serial = current_serial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
_send_linebuf(target_p, &rb_linebuf_local);
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_linebuf_donebuf(&rb_linebuf_local);
|
||||||
|
rb_linebuf_donebuf(&rb_linebuf_old);
|
||||||
|
rb_linebuf_donebuf(&rb_linebuf_new);
|
||||||
|
}
|
||||||
|
|
||||||
/* sendto_channel_local()
|
/* sendto_channel_local()
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue