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.
capab: CHW
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
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

View file

@ -16,7 +16,8 @@ NO PARAMETERS:
+c - No color. All color codes in messages are stripped.
+g - Free invite. Everyone may invite users. Significantly
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.
Only settable by opers.
+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_SAVE 0x40000 /* supports SAVE (nick collision FNC) */
#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 | \
CAP_IE | CAP_KLN | CAP_SERVICE |\
CAP_CLUSTER | CAP_ENCAP | \
CAP_ZIP | CAP_KNOCK | CAP_UNKLN | \
CAP_RSFNC | CAP_SAVE | CAP_EUID)
CAP_RSFNC | CAP_SAVE | CAP_EUID | CAP_EOPMOD)
#ifdef HAVE_LIBZ
#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,
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_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_CHANNEL 1
#define ENTITY_CHANOPS_ON_CHANNEL 2
#define ENTITY_CLIENT 3
#define ENTITY_CHANNEL_OPMOD 2
#define ENTITY_CHANOPS_ON_CHANNEL 3
#define ENTITY_CLIENT 4
static struct entity targets[512];
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 *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,
struct Client *client_p,
struct Client *source_p,
@ -204,6 +210,11 @@ m_message(int p_or_n,
(struct Channel *) targets[i].ptr, parv[2]);
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:
msg_channel_flags(p_or_n, command, client_p, source_p,
(struct Channel *) targets[i].ptr,
@ -382,6 +393,32 @@ build_target_list(int p_or_n, const char *command, struct Client *client_p,
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 */
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 &&
chptr->mode.mode & MODE_MODERATED &&
(!(chptr->mode.mode & MODE_NOPRIVMSGS) ||
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))
{
sendto_channel_flags(client_p, ONLY_CHANOPS, source_p, chptr,
"%s %s :%s", command, chptr->chname, text);
sendto_channel_opmod(client_p, source_p, chptr,
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

View file

@ -91,6 +91,7 @@ struct Capability captab[] = {
{ "RSFNC", CAP_RSFNC },
{ "SAVE", CAP_SAVE },
{ "EUID", CAP_EUID },
{ "EOPMOD", CAP_EOPMOD },
{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);
}
/* 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()
*