From 8664eacf2eb8467ed422ab7054bd9f87560dafd0 Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Tue, 28 Mar 2000 02:40:30 +0000 Subject: [PATCH] Author: Kev Log message: Various misc. bug fixes, feature additions for modebuf_* for anticipated future use; /clearmode should now be fully functional. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@88 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 21 +++- include/channel.h | 11 ++- ircd/channel.c | 238 ++++++++++++++++++++++++++++++++++----------- ircd/m_clearmode.c | 2 +- 4 files changed, 210 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index 804098b..448e988 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,24 @@ 2000-03-27 Kevin L. Mitchell + * ircd/m_clearmode.c (do_clearmode): only mark the modes the + channel actually has in effect for deletion + + * ircd/channel.c: added explanatory comments to all added + functions; made flushing take place at the correct place even if + the MODEBUF_DEST_DEOP flag is set; rewrote build_string() helper + to bash some stupid bugs; made modebuf_flush() return if ModeBuf + is empty, fixed the apparent source, removed some bogus string + termination code, properly terminate the mode strings, add support + for HACK2 and HACK3, made limit strings not be sent if the limit + is being removed, changed where '+' and '-' come from in sent + strings, added support for DEOP flag, set up bouncing code for + HACK2 + + * ircd/Makefile.in: ran make depend + + * include/channel.h: added new defines for future functionality, + made modebuf_flush() return int so I can use tail recursion + * ircd/m_clearmode.c: add msg.h to includes; other misc cleanups to make it all compile @@ -89,7 +108,7 @@ # # ChangeLog for ircu2.10.11 # -# $Id: ChangeLog,v 1.33 2000-03-28 00:52:14 bleep Exp $ +# $Id: ChangeLog,v 1.34 2000-03-28 02:40:30 kev Exp $ # # Insert new changes at beginning of the change list. # diff --git a/include/channel.h b/include/channel.h index a75b576..5f7fa24 100644 --- a/include/channel.h +++ b/include/channel.h @@ -253,9 +253,12 @@ struct ModeBuf { #define MODEBUF_DEST_CHANNEL 0x01 /* Mode is flushed to channel */ #define MODEBUF_DEST_SERVER 0x02 /* Mode is flushed to server */ -#define MODEBUF_DEST_OPMODE 0x40 /* Send server mode as OPMODE */ -#define MODEBUF_DEST_HACK4 0x80 /* Send a HACK(4) notice and, on - server sends, use a TS of 0 */ + +#define MODEBUF_DEST_OPMODE 0x08 /* Send server mode as OPMODE */ +#define MODEBUF_DEST_DEOP 0x10 /* Deop the offender */ +#define MODEBUF_DEST_HACK2 0x20 /* Send a HACK(2) notice, reverse */ +#define MODEBUF_DEST_HACK3 0x40 /* Send a HACK(3) notice, TS == 0 */ +#define MODEBUF_DEST_HACK4 0x80 /* Send a HACK(4) notice, TS == 0 */ #define MB_TYPE(mb, i) ((mb)->mb_modeargs[(i)].mbm_type) #define MB_UINT(mb, i) ((mb)->mb_modeargs[(i)].mbm_arg.mbma_uint) @@ -328,6 +331,6 @@ extern void modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode, char *string); extern void modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode, struct Client *client); -extern void modebuf_flush(struct ModeBuf *mbuf); +extern int modebuf_flush(struct ModeBuf *mbuf); #endif /* INCLUDED_channel_h */ diff --git a/ircd/channel.c b/ircd/channel.c index 06ceff7..cdad174 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -2659,6 +2659,10 @@ void send_hack_notice(struct Client *cptr, struct Client *sptr, int parc, } } +/* + * This routine just initializes a ModeBuf structure with the information + * needed and the options given. + */ void modebuf_init(struct ModeBuf *mbuf, struct Client *source, struct Client *connect, struct Channel *chan, unsigned int dest) @@ -2678,12 +2682,17 @@ modebuf_init(struct ModeBuf *mbuf, struct Client *source, mbuf->mb_dest = dest; mbuf->mb_count = 0; + /* clear each mode-with-parameter slot */ for (i = 0; i < MAXMODEPARAMS; i++) { MB_TYPE(mbuf, i) = 0; MB_UINT(mbuf, i) = 0; } } +/* + * This routine simply adds modes to be added or deleted; do a binary OR + * with either MODE_ADD or MODE_DEL + */ void modebuf_mode(struct ModeBuf *mbuf, unsigned int mode) { @@ -2702,6 +2711,11 @@ modebuf_mode(struct ModeBuf *mbuf, unsigned int mode) } } +/* + * This routine adds a mode to be added or deleted that takes a unsigned + * int parameter; mode may *only* be the relevant mode flag ORed with one + * of MODE_ADD or MODE_DEL + */ void modebuf_mode_uint(struct ModeBuf *mbuf, unsigned int mode, unsigned int uint) { @@ -2711,10 +2725,17 @@ modebuf_mode_uint(struct ModeBuf *mbuf, unsigned int mode, unsigned int uint) MB_TYPE(mbuf, mbuf->mb_count) = mode; MB_UINT(mbuf, mbuf->mb_count) = uint; - if (++mbuf->mb_count >= 6) + /* when we've reached the maximal count, flush the buffer */ + if (++mbuf->mb_count >= + (MAXMODEPARAMS - (mbuf->mb_dest & MODEBUF_DEST_DEOP ? 1 : 0))) modebuf_flush(mbuf); } +/* + * This routine adds a mode to be added or deleted that takes a string + * parameter; mode may *only* be the relevant mode flag ORed with one of + * MODE_ADD or MODE_DEL + */ void modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode, char *string) { @@ -2724,10 +2745,17 @@ modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode, char *string) MB_TYPE(mbuf, mbuf->mb_count) = mode; MB_STRING(mbuf, mbuf->mb_count) = string; - if (++mbuf->mb_count >= 6) + /* when we've reached the maximal count, flush the buffer */ + if (++mbuf->mb_count >= + (MAXMODEPARAMS - (mbuf->mb_dest & MODEBUF_DEST_DEOP ? 1 : 0))) modebuf_flush(mbuf); } +/* + * This routine adds a mode to be added or deleted that takes a client + * parameter; mode may *only* be the relevant mode flag ORed with one of + * MODE_ADD or MODE_DEL + */ void modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode, struct Client *client) @@ -2738,26 +2766,40 @@ modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode, MB_TYPE(mbuf, mbuf->mb_count) = mode; MB_CLIENT(mbuf, mbuf->mb_count) = client; - if (++mbuf->mb_count >= 6) + /* when we've reached the maximal count, flush the buffer */ + if (++mbuf->mb_count >= + (MAXMODEPARAMS - (mbuf->mb_dest & MODEBUF_DEST_DEOP ? 1 : 0))) modebuf_flush(mbuf); } +/* + * This helper function builds an argument string in strptr, consisting + * of the original string, a space, and str1 and str2 concatenated (if, + * of course, str2 is not NULL) + */ static void build_string(char *strptr, int *strptr_i, char *str1, char *str2) { strptr[(*strptr_i)++] = ' '; - while ((strptr[(*strptr_i)++] = *(str1++))) - ; /* very simple strcat */ + while (*str1) + strptr[(*strptr_i)++] = *(str1++); if (str2) - while ((strptr[(*strptr_i)++] = *(str2++))) - ; /* for the two-argument form--used for numeric nicks */ + while (*str2) + strptr[(*strptr_i)++] = *(str2++); + + strptr[(*strptr_i)] = '\0'; } -void +/* + * This is the workhorse of our ModeBuf suite; this actually generates the + * output MODE commands, HACK notices, or whatever. It's pretty complicated. + */ +int modebuf_flush(struct ModeBuf *mbuf) { + /* we only need the flags that don't take args right now */ static int flags[] = { /* MODE_CHANOP, 'o', */ /* MODE_VOICE, 'v', */ @@ -2775,31 +2817,39 @@ modebuf_flush(struct ModeBuf *mbuf) int i; int *flag_p; - struct Client *app_source; + struct Client *app_source; /* where the MODE appears to come from */ - char addbuf[20] = "+"; - int addbuf_i = 1; - char rembuf[20] = "-"; - int rembuf_i = 1; - char *bufptr; + char addbuf[20]; /* accumulates +psmtin, etc. */ + int addbuf_i = 0; + char rembuf[20]; /* accumulates -psmtin, etc. */ + int rembuf_i = 0; + char *bufptr; /* we make use of indirection to simplify the code */ int *bufptr_i; - char addstr[MODEBUFLEN]; + char addstr[MODEBUFLEN]; /* accumulates MODE parameters to add */ int addstr_i; - char remstr[MODEBUFLEN]; + char remstr[MODEBUFLEN]; /* accumulates MODE parameters to remove */ int remstr_i; - char *strptr; + char *strptr; /* more indirection to simplify the code */ int *strptr_i; - char limitbuf[10]; + char limitbuf[10]; /* convert limits to strings */ + + unsigned int limitdel = MODE_LIMIT; assert(0 != mbuf); + /* If the ModeBuf is empty, we have nothing to do */ + if (mbuf->mb_add == 0 && mbuf->mb_rem == 0 && mbuf->mb_count == 0) + return 0; + + /* Ok, if we were given the OPMODE flag, hide the source if its a user */ if (mbuf->mb_dest & MODEBUF_DEST_OPMODE && !IsServer(mbuf->mb_source)) - app_source = mbuf->mb_source->from; + app_source = mbuf->mb_source->user->server; else app_source = mbuf->mb_source; + /* Calculate the simple flags */ for (flag_p = flags; flag_p[0]; flag_p += 2) { if (*flag_p & mbuf->mb_add) addbuf[addbuf_i++] = flag_p[1]; @@ -2807,21 +2857,9 @@ modebuf_flush(struct ModeBuf *mbuf) rembuf[rembuf_i++] = flag_p[1]; } - if (addbuf_i == 1 && rembuf_i == 1) - return; - - if (addbuf_i == 1) - addbuf[0] = '\0'; - else - addbuf[addbuf_i] = '\0'; - - if (rembuf_i == 1) - rembuf[0] = '\0'; - else - rembuf[rembuf_i] = '\0'; - + /* Now go through the modes with arguments... */ for (i = 0; i < mbuf->mb_count; i++) { - if (MB_TYPE(mbuf, i) & MODE_ADD) { + if (MB_TYPE(mbuf, i) & MODE_ADD) { /* adding or removing? */ bufptr = addbuf; bufptr_i = &addbuf_i; } else { @@ -2840,18 +2878,26 @@ modebuf_flush(struct ModeBuf *mbuf) else if (MB_TYPE(mbuf, i) & MODE_LIMIT) { bufptr[(*bufptr_i)++] = 'l'; + /* if it's a limit, we also format the number */ sprintf_irc(limitbuf, "%d", MB_UINT(mbuf, i)); } } - if (mbuf->mb_dest & (MODEBUF_DEST_CHANNEL | MODEBUF_DEST_HACK4)) { + /* terminate the mode strings */ + addbuf[addbuf_i] = '\0'; + rembuf[rembuf_i] = '\0'; + + /* If we're building a user visible MODE or HACK... */ + if (mbuf->mb_dest & (MODEBUF_DEST_CHANNEL | MODEBUF_DEST_HACK2 | + MODEBUF_DEST_HACK3 | MODEBUF_DEST_HACK4)) { + /* Set up the parameter strings */ addstr[0] = '\0'; addstr_i = 0; remstr[0] = '\0'; remstr_i = 0; for (i = 0; i < mbuf->mb_count; i++) { - if (MB_TYPE(mbuf, i) & MODE_ADD) { + if (MB_TYPE(mbuf, i) & MODE_ADD) { /* adding or removing? */ strptr = addstr; strptr_i = &addstr_i; } else { @@ -2859,34 +2905,67 @@ modebuf_flush(struct ModeBuf *mbuf) strptr_i = &remstr_i; } + /* deal with clients... */ if (MB_TYPE(mbuf, i) & (MODE_CHANOP | MODE_VOICE)) build_string(strptr, strptr_i, MB_CLIENT(mbuf, i)->name, 0); + + /* deal with strings... */ else if (MB_TYPE(mbuf, i) & (MODE_KEY | MODE_BAN)) build_string(strptr, strptr_i, MB_STRING(mbuf, i), 0); - else if (MB_TYPE(mbuf, i) & MODE_LIMIT) + + /* + * deal with limit; note we cannot include the limit parameter if we're + * removing it + */ + else if ((MB_TYPE(mbuf, i) & (MODE_ADD | MODE_LIMIT)) == + (MODE_ADD | MODE_LIMIT)) build_string(strptr, strptr_i, limitbuf, 0); } + /* send the messages off to their destination */ if (mbuf->mb_dest & MODEBUF_DEST_CHANNEL) sendto_channel_butserv(mbuf->mb_channel, app_source, - ":%s MODE %s %s%s%s%s", app_source->name, - mbuf->mb_channel->chname, addbuf, rembuf, addstr, + ":%s MODE %s %s%s%s%s%s%s", app_source->name, + mbuf->mb_channel->chname, addbuf_i ? "+" : "", + addbuf, rembuf_i ? "-" : "", rembuf, addstr, remstr); - if (mbuf->mb_dest & MODEBUF_DEST_HACK4) - sendto_op_mask(SNO_HACK4, "HACK(4): %s MODE %s %s%s%s%s [" TIME_T_FMT + + if (mbuf->mb_dest & MODEBUF_DEST_HACK2) + sendto_op_mask(SNO_HACK2, "HACK(2): %s MODE %s %s%s%s%s%s%s [" TIME_T_FMT "]", app_source->name, mbuf->mb_channel->chname, - addbuf, rembuf, addstr, remstr, + addbuf_i ? "+" : "", addbuf, rembuf_i ? "-" : "", rembuf, + addstr, remstr, mbuf->mb_channel->creationtime); + + if (mbuf->mb_dest & MODEBUF_DEST_HACK3) + sendto_op_mask(SNO_HACK3, "BOUNCE or HACK(3): %s MODE %s %s%s%s%s%s%s [" + TIME_T_FMT "]", app_source->name, + mbuf->mb_channel->chname, addbuf_i ? "+" : "", addbuf, + rembuf_i ? "-" : "", rembuf, addstr, remstr, mbuf->mb_channel->creationtime); + + if (mbuf->mb_dest & MODEBUF_DEST_HACK4) + sendto_op_mask(SNO_HACK4, "HACK(4): %s MODE %s %s%s%s%s%s%s [" TIME_T_FMT + "]", app_source->name, mbuf->mb_channel->chname, + addbuf_i ? "+" : "", addbuf, rembuf_i ? "-" : "", rembuf, + addstr, remstr, mbuf->mb_channel->creationtime); } + /* Now are we supposed to propagate to other servers? */ if (mbuf->mb_dest & MODEBUF_DEST_SERVER) { + /* set up parameter string */ addstr[0] = '\0'; addstr_i = 0; remstr[0] = '\0'; remstr_i = 0; + /* + * limit is supressed if we're removing it; we have to figure out which + * direction is the direction for it to be removed, though... + */ + limitdel |= (mbuf->mb_dest & MODEBUF_DEST_HACK2) ? MODE_DEL : MODE_ADD; + for (i = 0; i < mbuf->mb_count; i++) { - if (MB_TYPE(mbuf, i) & MODE_ADD) { + if (MB_TYPE(mbuf, i) & MODE_ADD) { /* adding or removing? */ strptr = addstr; strptr_i = &addstr_i; } else { @@ -2894,46 +2973,93 @@ modebuf_flush(struct ModeBuf *mbuf) strptr_i = &remstr_i; } + /* deal with modes that take clients */ if (MB_TYPE(mbuf, i) & (MODE_CHANOP | MODE_VOICE)) build_string(strptr, strptr_i, NumNick(MB_CLIENT(mbuf, i))); + + /* deal with modes that take strings */ else if (MB_TYPE(mbuf, i) & (MODE_KEY | MODE_BAN)) build_string(strptr, strptr_i, MB_STRING(mbuf, i), 0); - else if (MB_TYPE(mbuf, i) & MODE_LIMIT) + + /* + * deal with the limit. Logic here is complicated; if HACK2 is set, + * we're bouncing the mode, so sense is reversed, and we have to + * include the original limit if it looks like it's being removed + */ + else if ((MB_TYPE(mbuf, i) & limitdel) == limitdel) build_string(strptr, strptr_i, limitbuf, 0); } + /* we were told to deop the source */ + if (mbuf->mb_dest & MODEBUF_DEST_DEOP) { + addbuf[addbuf_i++] = 'o'; /* remember, sense is reversed */ + addbuf[addbuf_i] = '\0'; /* terminate the string... */ + build_string(addstr, &addstr_i, NumNick(mbuf->mb_source)); /* add user */ + + /* mark that we've done this, so we don't do it again */ + mbuf->mb_dest &= ~MODEBUF_DEST_DEOP; + } + if (mbuf->mb_dest & MODEBUF_DEST_OPMODE) { + /* If OPMODE was set, we're propagating the mode as an OPMODE message */ if (IsServer(mbuf->mb_source)) - sendto_serv_butone(mbuf->mb_connect, "%s " TOK_OPMODE " %s %s%s%s%s", - NumServ(mbuf->mb_source), mbuf->mb_channel->chname, - addbuf, rembuf, addstr, remstr); + sendto_serv_butone(mbuf->mb_connect, "%s " TOK_OPMODE + " %s %s%s%s%s%s%s", NumServ(mbuf->mb_source), + mbuf->mb_channel->chname, addbuf_i ? "+" : "", + addbuf, rembuf_i ? "-" : "", rembuf, addstr, + remstr); else - sendto_serv_butone(mbuf->mb_connect, "%s%s " TOK_OPMODE " %s %s%s%s%s", - NumNick(mbuf->mb_source), mbuf->mb_channel->chname, - addbuf, rembuf, addstr, remstr); + sendto_serv_butone(mbuf->mb_connect, "%s%s " TOK_OPMODE + " %s %s%s%s%s%s%s", NumNick(mbuf->mb_source), + mbuf->mb_channel->chname, addbuf_i ? "+" : "", + addbuf, rembuf_i ? "-" : "", rembuf, addstr, + remstr); + } else if (mbuf->mb_dest & MODEBUF_DEST_HACK2) { + /* + * If HACK2 was set, we're bouncing; we send the MODE back to the + * connection we got it from with the senses reversed and a TS of 0; + * origin is us + */ + sendto_one(mbuf->mb_connect, "%s " TOK_MODE " %s %s%s%s%s%s%s " + TIME_T_FMT, NumServ(&me), mbuf->mb_channel->chname, + rembuf_i ? "+" : "", rembuf, addbuf_i ? "-" : "", addbuf, + remstr, addstr, 0); } else { + /* + * We're propagating a normal MODE command to the rest of the network; + * we send the actual channel TS unless this is a HACK3 or a HACK4 + */ if (IsServer(mbuf->mb_source)) - sendto_serv_butone(mbuf->mb_connect, "%s " TOK_MODE " %s %s%s%s%s " + sendto_serv_butone(mbuf->mb_connect, "%s " TOK_MODE " %s %s%s%s%s%s%s " TIME_T_FMT, NumServ(mbuf->mb_source), - mbuf->mb_channel->chname, addbuf, rembuf, addstr, - remstr, (mbuf->mb_dest & MODEBUF_DEST_HACK4) ? 0 : + mbuf->mb_channel->chname, addbuf_i ? "+" : "", + addbuf, rembuf_i ? "-" : "", rembuf, addstr, + remstr, (mbuf->mb_dest & (MODEBUF_DEST_HACK3 | + MODEBUF_DEST_HACK4)) ? 0 : mbuf->mb_channel->creationtime); else - sendto_serv_butone(mbuf->mb_connect, "%s%s " TOK_MODE " %s %s%s%s%s " - TIME_T_FMT, NumNick(mbuf->mb_source), - mbuf->mb_channel->chname, addbuf, rembuf, addstr, - remstr, (mbuf->mb_dest & MODEBUF_DEST_HACK4) ? 0 : + sendto_serv_butone(mbuf->mb_connect, "%s%s " TOK_MODE + " %s %s%s%s%s%s%s " TIME_T_FMT, + NumNick(mbuf->mb_source), mbuf->mb_channel->chname, + addbuf_i ? "+" : "", addbuf, rembuf_i ? "-" : "", + rembuf, addstr, remstr, + (mbuf->mb_dest & (MODEBUF_DEST_HACK3 | + MODEBUF_DEST_HACK4)) ? 0 : mbuf->mb_channel->creationtime); } } + /* We've drained the ModeBuf... */ mbuf->mb_add = 0; mbuf->mb_rem = 0; mbuf->mb_count = 0; + /* reinitialize the mode-with-arg slots */ for (i = 0; i < MAXMODEPARAMS; i++) { MB_TYPE(mbuf, i) = 0; MB_UINT(mbuf, i) = 0; } + + return 0; } diff --git a/ircd/m_clearmode.c b/ircd/m_clearmode.c index 53cbc12..2004494 100644 --- a/ircd/m_clearmode.c +++ b/ircd/m_clearmode.c @@ -156,7 +156,7 @@ do_clearmode(struct Client *cptr, struct Client *sptr, struct Channel *chptr, MODEBUF_DEST_OPMODE | /* Treat it like an OPMODE */ MODEBUF_DEST_HACK4)); /* Generate a HACK(4) notice */ - modebuf_mode(&mbuf, MODE_DEL | del_mode); /* Mark modes for deletion */ + modebuf_mode(&mbuf, MODE_DEL | (del_mode & chptr->mode.mode)); chptr->mode.mode &= ~del_mode; /* and of course actually delete them */ /* If we're removing invite, remove all the invites */ -- 2.20.1