From: Kevin L. Mitchell Date: Mon, 27 Mar 2000 04:31:35 +0000 (+0000) Subject: Author: Kev X-Git-Url: http://git.pk910.de/?a=commitdiff_plain;h=45c4e3f969461693e6663c55c77f455e8a7613e5;p=ircu2.10.12-pk.git Author: Kev Log message: Create a ModeBuf abstraction to build strings of modes and "flush" them to the channel at the correct point. Eventually intended to work for servers too, but not currently implemented that way. This is intended to be the first step toward OPMODE and CLEARMODE--for informing clients what's happening. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@70 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- diff --git a/include/channel.h b/include/channel.h index 048712e..55d9c64 100644 --- a/include/channel.h +++ b/include/channel.h @@ -232,6 +232,33 @@ struct ListingArgs { struct Channel *chptr; }; +struct ModeBuf { + unsigned int mb_add; /* Modes to add */ + unsigned int mb_rem; /* Modes to remove */ + struct Client *mb_source; /* Source of MODE changes */ + struct Client *mb_connect; /* Connection of MODE changes */ + struct Channel *mb_channel; /* Channel they affect */ + unsigned int mb_dest; /* Destination of MODE changes */ + unsigned int mb_count; /* Number of modes w/args */ + struct { + unsigned int mbm_type; /* Type of argument */ + union { + unsigned int mbma_uint; /* A limit */ + char *mbma_string; /* A string */ + struct Client *mbma_client; /* A client */ + } mbm_arg; /* The mode argument */ + } mb_modeargs[MAXMODEPARAMS]; + /* A mode w/args */ +}; + +#define MODEBUF_DEST_CHANNEL 0x01 /* Mode is flushed to channel */ +/* #define MODEBUF_DEST_SERVER 0x02 / * Mode is flushed to server */ + +#define MB_TYPE(mb, i) ((mb)->mb_modeargs[(i)].mbm_type) +#define MB_UINT(mb, i) ((mb)->mb_modeargs[(i)].mbm_arg.mbma_uint) +#define MB_STRING(mb, i) ((mb)->mb_modeargs[(i)].mbm_arg.mbma_string) +#define MB_CLIENT(mb, i) ((mb)->mb_modeargs[(i)].mbm_arg.mbma_client) + extern struct Channel* GlobalChannelList; extern int LocalChanOperMode; @@ -288,5 +315,16 @@ extern void del_invite(struct Client *cptr, struct Channel *chptr); extern void list_next_channels(struct Client *cptr, int nr); extern void send_user_joins(struct Client *cptr, struct Client *user); +extern void modebuf_init(struct ModeBuf *mbuf, struct Client *source, + struct Client *connect, struct Channel *chan, + unsigned int dest); +extern void modebuf_mode(struct ModeBuf *mbuf, unsigned int mode); +extern void modebuf_mode_uint(struct ModeBuf *mbuf, unsigned int mode, + unsigned int uint); +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); #endif /* INCLUDED_channel_h */ diff --git a/ircd/channel.c b/ircd/channel.c index d0f0fd5..f33983d 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -2658,3 +2658,202 @@ void send_hack_notice(struct Client *cptr, struct Client *sptr, int parc, } } } + +void +modebuf_init(struct ModeBuf *mbuf, struct Client *source, + struct Client *connect, struct Channel *chan, unsigned int dest) +{ + int i; + + assert(0 != mbuf); + assert(0 != source); + assert(0 != chan); + assert(0 != dest); + + mbuf->mb_add = 0; + mbuf->mb_rem = 0; + mbuf->mb_source = source; + mbuf->mb_connect = connect; + mbuf->mb_channel = chan; + mbuf->mb_dest = dest; + mbuf->mb_count = 0; + + for (i = 0; i < MAXMODEPARAMS; i++) { + MB_TYPE(mbuf, i) = 0; + MB_UINT(mbuf, i) = 0; + } +} + +void +modebuf_mode(struct ModeBuf *mbuf, unsigned int mode) +{ + assert(0 != mbuf); + assert(0 != (mode & (MODE_ADD | MODE_DEL))); + + mode &= (MODE_ADD | MODE_DEL | MODE_PRIVATE | MODE_SECRET | MODE_MODERATED | + MODE_TOPICLIMIT | MODE_INVITEONLY | MODE_NOPRIVMSGS); + + if (mode & MODE_ADD) { + mbuf->mb_rem &= ~mode; + mbuf->mb_add |= mode; + } else { + mbuf->mb_add &= ~mode; + mbuf->mb_rem |= mode; + } +} + +void +modebuf_mode_uint(struct ModeBuf *mbuf, unsigned int mode, unsigned int uint) +{ + assert(0 != mbuf); + assert(0 != (mode & (MODE_ADD | MODE_DEL))); + + MB_TYPE(mbuf, mbuf->mb_count) = mode; + MB_UINT(mbuf, mbuf->mb_count) = uint; + + if (++mbuf->mb_count >= 6) + modebuf_flush(mbuf); +} + +void +modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode, char *string) +{ + assert(0 != mbuf); + assert(0 != (mode & (MODE_ADD | MODE_DEL))); + + MB_TYPE(mbuf, mbuf->mb_count) = mode; + MB_STRING(mbuf, mbuf->mb_count) = string; + + if (++mbuf->mb_count >= 6) + modebuf_flush(mbuf); +} + +void +modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode, + struct Client *client) +{ + assert(0 != mbuf); + assert(0 != (mode & (MODE_ADD | MODE_DEL))); + + MB_TYPE(mbuf, mbuf->mb_count) = mode; + MB_CLIENT(mbuf, mbuf->mb_count) = client; + + if (++mbuf->mb_count >= 6) + modebuf_flush(mbuf); +} + +static void +build_string(char *strptr, int *strptr_i, char *str) +{ + strptr[(*strptr_i)++] = ' '; + + while (strptr[(*strptr_i)++] = *str) + ; /* very simple strcat */ +} + +void +modebuf_flush(struct ModeBuf *mbuf) +{ + static int flags[] = { +/* MODE_CHANOP, 'o', */ +/* MODE_VOICE, 'v', */ + MODE_PRIVATE, 'p', + MODE_SECRET, 's', + MODE_MODERATED, 'm', + MODE_TOPICLIMIT, 't', + MODE_INVITEONLY, 'i', + MODE_NOPRIVMSGS, 'n', +/* MODE_KEY, 'k', */ +/* MODE_BAN, 'b', */ +/* MODE_LIMIT, 'l', */ + 0x0, 0x0 + }; + int i; + int *flag_p; + + char addbuf[20] = "+"; + int addbuf_i = 1; + char rembuf[20] = "-"; + int rembuf_i = 1; + char *bufptr; + int *bufptr_i; + + char addstr[MODEBUFLEN] = ""; + int addstr_i = 0; + char remstr[MODEBUFLEN] = ""; + int remstr_i = 0; + char *strptr; + int *strptr_i; + + char limitbuf[10]; + + assert(0 != mbuf); + + for (flag_p = flags; flag_p[0]; flag_p += 2) { + if (*flag_p & mbuf->mb_add) + addbuf[addbuf_i++] = flag_p[1]; + else if (*flag_p & mbuf->mb_rem) + rembuf[rembuf_i++] = flag_p[1]; + } + + if (addbuf_i == 1) + addbuf[0] = '\0'; + if (rembuf_i == 1) + rembuf[0] = '\0'; + + for (i = 0; i < mbuf->mb_count; i++) { + if (MB_TYPE(mbuf, i) & MODE_ADD) { + bufptr = addbuf; + bufptr_i = &addbuf_i; + } else { + bufptr = rembuf; + bufptr_i = &rembuf_i; + } + + if (MB_TYPE(mbuf, i) & MODE_CHANOP) + bufptr[(*bufptr_i)++] = 'o'; + else if (MB_TYPE(mbuf, i) & MODE_VOICE) + bufptr[(*bufptr_i)++] = 'v'; + else if (MB_TYPE(mbuf, i) & MODE_KEY) + bufptr[(*bufptr_i)++] = 'k'; + else if (MB_TYPE(mbuf, i) & MODE_BAN) + bufptr[(*bufptr_i)++] = 'b'; + else if (MB_TYPE(mbuf, i) & MODE_LIMIT) { + bufptr[(*bufptr_i)++] = 'l'; + + sprintf_irc(limitbuf, "%d", MB_UINT(mbuf, i)); + } + } + + if (mbuf->mb_dest & MODEBUF_DEST_CHANNEL) { + for (i = 0; i < mbuf->mb_count; i++) { + if (MB_TYPE(mbuf, i) & MODE_ADD) { + strptr = addstr; + strptr_i = &addstr_i; + } else { + strptr = remstr; + strptr_i = &remstr_i; + } + + if (MB_TYPE(mbuf, i) & (MODE_CHANOP | MODE_VOICE)) + build_string(strptr, strptr_i, MB_CLIENT(mbuf, i)->name); + else if (MB_TYPE(mbuf, i) & (MODE_KEY | MODE_BAN)) + build_string(strptr, strptr_i, MB_STRING(mbuf, i)); + else if (MB_TYPE(mbuf, i) & MODE_LIMIT) + build_string(strptr, strptr_i, limitbuf); + } + + sendto_channel_butserv(mbuf->mb_channel, mbuf->mb_source, + ":%s MODE %s %s%s%s%s", mbuf->mb_source->name, + mbuf->mb_channel->name, addbuf, rembuf, addstr, + remstr); + } + + mbuf->mb_count = 0; + + for (i = 0; i < MAXMODEPARAMS; i++) { + MB_TYPE(mbuf, i) = 0; + MB_UINT(mbuf, i) = 0; + } +} +