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:
Jilles Tjoelker 2009-03-29 15:48:07 +02:00
parent 1ba5ea0f06
commit c4d2d01419
7 changed files with 193 additions and 9 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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}
}; };

View file

@ -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()
* *