From 82f8e812f5f3df9a23b58dff2024f83237280b9d Mon Sep 17 00:00:00 2001 From: "B.Greenham" Date: Sun, 28 Feb 2010 02:35:48 -0500 Subject: [PATCH] Add full support for +a (owner) and +h (halfop) chmodes. --- include/channel.h | 4 + include/chmode.h | 6 + modules/core/m_join.c | 293 +++++++++++++++++++++++++++++++++++++++++- src/channel.c | 6 +- src/chmode.c | 226 ++++++++++++++++++++++++++++++-- src/send.c | 2 +- 6 files changed, 517 insertions(+), 20 deletions(-) diff --git a/include/channel.h b/include/channel.h index bad7739..a6fa1a1 100644 --- a/include/channel.h +++ b/include/channel.h @@ -147,10 +147,14 @@ typedef int (*ExtbanFunc)(const char *data, struct Client *client_p, #define CHFL_BANNED 0x0008 /* cached as banned */ #define CHFL_QUIETED 0x0010 /* cached as being +q victim */ #define ONLY_SERVERS 0x0020 +#define CHFL_HALFOP 0x0040 +#define CHFL_OWNER 0x0080 #define ALL_MEMBERS CHFL_PEON #define ONLY_CHANOPS CHFL_CHANOP #define ONLY_CHANOPSVOICED (CHFL_CHANOP|CHFL_VOICE) +#define is_chmode_h(x) ((x) && (x)->flags & CHFL_HALFOP) /* does not check if halfop is enabled, should typically not be used */ +#define is_chmode_a(x) ((x) && (x)->flags & CHFL_OWNER) /* does not check if owner is enabled, should typically not be used */ #define is_chanop(x) ((x) && (x)->flags & CHFL_CHANOP) #define is_voiced(x) ((x) && (x)->flags & CHFL_VOICE) #define can_send_banned(x) ((x) && (x)->flags & (CHFL_BANNED|CHFL_QUIETED)) diff --git a/include/chmode.h b/include/chmode.h index a9c04a6..9538194 100644 --- a/include/chmode.h +++ b/include/chmode.h @@ -66,9 +66,15 @@ extern void chm_limit(struct Client *source_p, struct Channel *chptr, extern void chm_regonly(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, const char **parv, int *errors, int dir, char c, long mode_type); +extern void chm_owner(struct Client *source_p, struct Channel *chptr, + int alevel, int parc, int *parn, + const char **parv, int *errors, int dir, char c, long mode_type); extern void chm_op(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, const char **parv, int *errors, int dir, char c, long mode_type); +extern void chm_halfop(struct Client *source_p, struct Channel *chptr, + int alevel, int parc, int *parn, + const char **parv, int *errors, int dir, char c, long mode_type); extern void chm_voice(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, const char **parv, int *errors, int dir, char c, long mode_type); diff --git a/modules/core/m_join.c b/modules/core/m_join.c index e6e4db2..79ab428 100644 --- a/modules/core/m_join.c +++ b/modules/core/m_join.c @@ -490,11 +490,21 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char for (i = 0; i < 2; i++) { - if(*s == '@') + if(*s == '!') + { + fl |= CHFL_OWNER; + s++; + } + else if(*s == '@') { fl |= CHFL_CHANOP; s++; } + else if(*s == '%') + { + fl |= CHFL_HALFOP; + s++; + } else if(*s == '+') { fl |= CHFL_VOICE; @@ -520,12 +530,24 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char if(keep_new_modes) { + if(fl & CHFL_OWNER) + { + *ptr_uid++ = '!'; + len_nick++; + len_uid++; + } if(fl & CHFL_CHANOP) { *ptr_uid++ = '@'; len_nick++; len_uid++; } + if(fl & CHFL_HALFOP) + { + *ptr_uid++ = '%'; + len_nick++; + len_uid++; + } if(fl & CHFL_VOICE) { *ptr_uid++ = '+'; @@ -551,12 +573,108 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char joins++; } + /* If anyone can think of a way to do this that doesn't make babies cry + * I would love to hear it - Taros */ + + if(fl & CHFL_OWNER) + { + *mbuf++ = 'a'; + para[pargs++] = target_p->name; + + if(fl & CHFL_CHANOP) + { + /* its possible the +a has filled up MAXMODEPARAMS, if so, start + * a new buffer + */ + if(pargs >= MAXMODEPARAMS) + { + *mbuf = '\0'; + sendto_channel_local(ALL_MEMBERS, chptr, + ":%s MODE %s %s %s %s %s %s", + fakesource_p->name, chptr->chname, + modebuf, + para[0], para[1], para[2], para[3]); + mbuf = modebuf; + *mbuf++ = '+'; + para[0] = para[1] = para[2] = para[3] = NULL; + pargs = 0; + } + + *mbuf++ = 'o'; + para[pargs++] = target_p->name; + } + if(fl & CHFL_HALFOP) + { + /* its possible the +a has filled up MAXMODEPARAMS, if so, start + * a new buffer + */ + if(pargs >= MAXMODEPARAMS) + { + *mbuf = '\0'; + sendto_channel_local(ALL_MEMBERS, chptr, + ":%s MODE %s %s %s %s %s %s", + fakesource_p->name, chptr->chname, + modebuf, + para[0], para[1], para[2], para[3]); + mbuf = modebuf; + *mbuf++ = '+'; + para[0] = para[1] = para[2] = para[3] = NULL; + pargs = 0; + } + + *mbuf++ = 'h'; + para[pargs++] = target_p->name; + } + if(fl & CHFL_VOICE) + { + /* its possible the +a has filled up MAXMODEPARAMS, if so, start + * a new buffer + */ + if(pargs >= MAXMODEPARAMS) + { + *mbuf = '\0'; + sendto_channel_local(ALL_MEMBERS, chptr, + ":%s MODE %s %s %s %s %s %s", + fakesource_p->name, chptr->chname, + modebuf, + para[0], para[1], para[2], para[3]); + mbuf = modebuf; + *mbuf++ = '+'; + para[0] = para[1] = para[2] = para[3] = NULL; + pargs = 0; + } + + *mbuf++ = 'v'; + para[pargs++] = target_p->name; + } + } if(fl & CHFL_CHANOP) { *mbuf++ = 'o'; para[pargs++] = target_p->name; - /* a +ov user.. bleh */ + if(fl & CHFL_HALFOP) + { + /* its possible the +o has filled up MAXMODEPARAMS, if so, start + * a new buffer + */ + if(pargs >= MAXMODEPARAMS) + { + *mbuf = '\0'; + sendto_channel_local(ALL_MEMBERS, chptr, + ":%s MODE %s %s %s %s %s %s", + fakesource_p->name, chptr->chname, + modebuf, + para[0], para[1], para[2], para[3]); + mbuf = modebuf; + *mbuf++ = '+'; + para[0] = para[1] = para[2] = para[3] = NULL; + pargs = 0; + } + + *mbuf++ = 'h'; + para[pargs++] = target_p->name; + } if(fl & CHFL_VOICE) { /* its possible the +o has filled up MAXMODEPARAMS, if so, start @@ -580,6 +698,34 @@ ms_sjoin(struct Client *client_p, struct Client *source_p, int parc, const char para[pargs++] = target_p->name; } } + if(fl & CHFL_HALFOP) + { + *mbuf++ = 'h'; + para[pargs++] = target_p->name; + + if(fl & CHFL_VOICE) + { + /* its possible the +h has filled up MAXMODEPARAMS, if so, start + * a new buffer + */ + if(pargs >= MAXMODEPARAMS) + { + *mbuf = '\0'; + sendto_channel_local(ALL_MEMBERS, chptr, + ":%s MODE %s %s %s %s %s %s", + fakesource_p->name, chptr->chname, + modebuf, + para[0], para[1], para[2], para[3]); + mbuf = modebuf; + *mbuf++ = '+'; + para[0] = para[1] = para[2] = para[3] = NULL; + pargs = 0; + } + + *mbuf++ = 'v'; + para[pargs++] = target_p->name; + } + } else if(fl & CHFL_VOICE) { *mbuf++ = 'v'; @@ -798,13 +944,152 @@ remove_our_modes(struct Channel *chptr, struct Client *source_p) { msptr = ptr->data; - if(is_chanop(msptr)) + /* If anyone can think of a way to do this that doesn't make babies cry + * I would love to hear it - Taros */ + + if(is_owner(msptr)) + { + msptr->flags &= ~CHFL_OWNER; + lpara[count++] = msptr->client_p->name; + *mbuf++ = 'a'; + + /* Make sure it fits if +h, +o, or +v are involved */ + if(is_chanop(msptr)) + { + if(count >= MAXMODEPARAMS) + { + *mbuf = '\0'; + sendto_channel_local(ALL_MEMBERS, chptr, + ":%s MODE %s %s %s %s %s %s", + source_p->name, chptr->chname, + lmodebuf, lpara[0], lpara[1], + lpara[2], lpara[3]); + + /* preserve the initial '-' */ + mbuf = lmodebuf; + *mbuf++ = '-'; + count = 0; + + for(i = 0; i < MAXMODEPARAMS; i++) + lpara[i] = NULL; + } + + msptr->flags &= ~CHFL_CHANOP; + lpara[count++] = msptr->client_p->name; + *mbuf++ = 'o'; + } + if(is_halfop(msptr)) + { + if(count >= MAXMODEPARAMS) + { + *mbuf = '\0'; + sendto_channel_local(ALL_MEMBERS, chptr, + ":%s MODE %s %s %s %s %s %s", + source_p->name, chptr->chname, + lmodebuf, lpara[0], lpara[1], + lpara[2], lpara[3]); + + /* preserve the initial '-' */ + mbuf = lmodebuf; + *mbuf++ = '-'; + count = 0; + + for(i = 0; i < MAXMODEPARAMS; i++) + lpara[i] = NULL; + } + + msptr->flags &= ~CHFL_HALFOP; + lpara[count++] = msptr->client_p->name; + *mbuf++ = 'h'; + } + if(is_voiced(msptr)) + { + if(count >= MAXMODEPARAMS) + { + *mbuf = '\0'; + sendto_channel_local(ALL_MEMBERS, chptr, + ":%s MODE %s %s %s %s %s %s", + source_p->name, chptr->chname, + lmodebuf, lpara[0], lpara[1], + lpara[2], lpara[3]); + + /* preserve the initial '-' */ + mbuf = lmodebuf; + *mbuf++ = '-'; + count = 0; + + for(i = 0; i < MAXMODEPARAMS; i++) + lpara[i] = NULL; + } + + msptr->flags &= ~CHFL_VOICE; + lpara[count++] = msptr->client_p->name; + *mbuf++ = 'v'; + } + } + else if(is_chanop(msptr)) { msptr->flags &= ~CHFL_CHANOP; lpara[count++] = msptr->client_p->name; *mbuf++ = 'o'; - /* +ov, might not fit so check. */ + /* Make sure it fits if +h or +v are involved */ + if(is_halfop(msptr)) + { + if(count >= MAXMODEPARAMS) + { + *mbuf = '\0'; + sendto_channel_local(ALL_MEMBERS, chptr, + ":%s MODE %s %s %s %s %s %s", + source_p->name, chptr->chname, + lmodebuf, lpara[0], lpara[1], + lpara[2], lpara[3]); + + /* preserve the initial '-' */ + mbuf = lmodebuf; + *mbuf++ = '-'; + count = 0; + + for(i = 0; i < MAXMODEPARAMS; i++) + lpara[i] = NULL; + } + + msptr->flags &= ~CHFL_HALFOP; + lpara[count++] = msptr->client_p->name; + *mbuf++ = 'h'; + } + if(is_voiced(msptr)) + { + if(count >= MAXMODEPARAMS) + { + *mbuf = '\0'; + sendto_channel_local(ALL_MEMBERS, chptr, + ":%s MODE %s %s %s %s %s %s", + source_p->name, chptr->chname, + lmodebuf, lpara[0], lpara[1], + lpara[2], lpara[3]); + + /* preserve the initial '-' */ + mbuf = lmodebuf; + *mbuf++ = '-'; + count = 0; + + for(i = 0; i < MAXMODEPARAMS; i++) + lpara[i] = NULL; + } + + msptr->flags &= ~CHFL_VOICE; + lpara[count++] = msptr->client_p->name; + *mbuf++ = 'v'; + } + } + else if(is_halfop(msptr)) + { + msptr->flags &= ~CHFL_HALFOP; + lpara[count++] = msptr->client_p->name; + *mbuf++ = 'h'; + + /* +hv, might not fit so check. */ if(is_voiced(msptr)) { if(count >= MAXMODEPARAMS) diff --git a/src/channel.c b/src/channel.c index 8e3f570..d45e87f 100644 --- a/src/channel.c +++ b/src/channel.c @@ -219,9 +219,10 @@ find_channel_status(struct membership *msptr, int combine) int is_halfop(struct membership *msptr) { - /* will do something other than return 0 when owner is implemented */ if(!ConfigChannel.use_halfop) return 0; + if(is_chmode_h(msptr)) + return 1; else return 0; } @@ -237,9 +238,10 @@ is_halfop(struct membership *msptr) int is_owner(struct membership *msptr) { - /* will do something other than return 0 when owner is implemented */ if(!ConfigChannel.use_owner) return 0; + if(is_chmode_a(msptr)) + return 1; else return 0; } diff --git a/src/chmode.c b/src/chmode.c index 7121e26..7f78db9 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -89,7 +89,9 @@ construct_noparam_modes(void) !(chmode_table[i].set_func == chm_throttle) && !(chmode_table[i].set_func == chm_key) && !(chmode_table[i].set_func == chm_limit) && + !(chmode_table[i].set_func == chm_owner) && !(chmode_table[i].set_func == chm_op) && + !(chmode_table[i].set_func == chm_halfop) && !(chmode_table[i].set_func == chm_voice)) { chmode_flags[i] = chmode_table[i].mode_type; @@ -175,8 +177,12 @@ find_cflag_slot(void) static int get_channel_access(struct Client *source_p, struct membership *msptr) { - if(!MyClient(source_p) || is_chanop(msptr)) + if(!MyClient(source_p) || is_owner(msptr)) + return CHFL_OWNER; + else if(is_chanop(msptr)) return CHFL_CHANOP; + else if(is_halfop(msptr)) + return CHFL_HALFOP; return CHFL_PEON; } @@ -492,7 +498,7 @@ chm_simple(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, const char **parv, int *errors, int dir, char c, long mode_type) { - if(alevel != CHFL_CHANOP) + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { if(!(*errors & SM_ERR_NOOPS)) sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), @@ -706,7 +712,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr, *errors |= errorval; /* non-ops cant see +eI lists.. */ - if(alevel != CHFL_CHANOP && mode_type != CHFL_BAN && + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP && mode_type != CHFL_BAN && mode_type != CHFL_QUIET) { if(!(*errors & SM_ERR_NOOPS)) @@ -730,7 +736,7 @@ chm_ban(struct Client *source_p, struct Channel *chptr, return; } - if(alevel != CHFL_CHANOP) + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { if(!(*errors & SM_ERR_NOOPS)) sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), @@ -809,6 +815,103 @@ chm_ban(struct Client *source_p, struct Channel *chptr, } } +void +chm_owner(struct Client *source_p, struct Channel *chptr, + int alevel, int parc, int *parn, + const char **parv, int *errors, int dir, char c, long mode_type) +{ + struct membership *mstptr; + const char *ownernick; + struct Client *targ_p; + + if(!ConfigChannel.use_owner) + { + if(*errors & SM_ERR_UNKNOWN) + return; + *errors |= SM_ERR_UNKNOWN; + sendto_one(source_p, form_str(ERR_UNKNOWNMODE), me.name, source_p->name, c); + return; + } + + if(alevel != CHFL_OWNER) + { + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } + + if((dir == MODE_QUERY) || (parc <= *parn)) + return; + + ownernick = parv[(*parn)]; + (*parn)++; + + /* empty nick */ + if(EmptyString(ownernick)) + { + sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), "*"); + return; + } + + if((targ_p = find_chasing(source_p, ownernick, NULL)) == NULL) + { + return; + } + + mstptr = find_channel_membership(chptr, targ_p); + + if(mstptr == NULL) + { + if(!(*errors & SM_ERR_NOTONCHANNEL) && MyClient(source_p)) + sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL, + form_str(ERR_USERNOTINCHANNEL), ownernick, chptr->chname); + *errors |= SM_ERR_NOTONCHANNEL; + return; + } + + if(MyClient(source_p) && (++mode_limit > MAXMODEPARAMS)) + return; + + if(dir == MODE_ADD) + { + if(targ_p == source_p) + return; + + mode_changes[mode_count].letter = c; + mode_changes[mode_count].dir = MODE_ADD; + mode_changes[mode_count].caps = 0; + mode_changes[mode_count].nocaps = 0; + mode_changes[mode_count].mems = ALL_MEMBERS; + mode_changes[mode_count].id = targ_p->id; + mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count++].client = targ_p; + + mstptr->flags |= CHFL_OWNER; + } + else + { + if(MyClient(source_p) && IsService(targ_p)) + { + sendto_one(source_p, form_str(ERR_ISCHANSERVICE), + me.name, source_p->name, targ_p->name, chptr->chname); + return; + } + + mode_changes[mode_count].letter = c; + mode_changes[mode_count].dir = MODE_DEL; + mode_changes[mode_count].caps = 0; + mode_changes[mode_count].nocaps = 0; + mode_changes[mode_count].mems = ALL_MEMBERS; + mode_changes[mode_count].id = targ_p->id; + mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count++].client = targ_p; + + mstptr->flags &= ~CHFL_OWNER; + } +} + void chm_op(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, @@ -818,7 +921,7 @@ chm_op(struct Client *source_p, struct Channel *chptr, const char *opnick; struct Client *targ_p; - if(alevel != CHFL_CHANOP) + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER) { if(!(*errors & SM_ERR_NOOPS)) sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), @@ -897,6 +1000,103 @@ chm_op(struct Client *source_p, struct Channel *chptr, } } +void +chm_halfop(struct Client *source_p, struct Channel *chptr, + int alevel, int parc, int *parn, + const char **parv, int *errors, int dir, char c, long mode_type) +{ + struct membership *mstptr; + const char *halfopnick; + struct Client *targ_p; + + if(!ConfigChannel.use_halfop) + { + if(*errors & SM_ERR_UNKNOWN) + return; + *errors |= SM_ERR_UNKNOWN; + sendto_one(source_p, form_str(ERR_UNKNOWNMODE), me.name, source_p->name, c); + return; + } + + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) + { + if(!(*errors & SM_ERR_NOOPS)) + sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), + me.name, source_p->name, chptr->chname); + *errors |= SM_ERR_NOOPS; + return; + } + + if((dir == MODE_QUERY) || (parc <= *parn)) + return; + + halfopnick = parv[(*parn)]; + (*parn)++; + + /* empty nick */ + if(EmptyString(halfopnick)) + { + sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), "*"); + return; + } + + if((targ_p = find_chasing(source_p, halfopnick, NULL)) == NULL) + { + return; + } + + mstptr = find_channel_membership(chptr, targ_p); + + if(mstptr == NULL) + { + if(!(*errors & SM_ERR_NOTONCHANNEL) && MyClient(source_p)) + sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL, + form_str(ERR_USERNOTINCHANNEL), halfopnick, chptr->chname); + *errors |= SM_ERR_NOTONCHANNEL; + return; + } + + if(MyClient(source_p) && (++mode_limit > MAXMODEPARAMS)) + return; + + if(dir == MODE_ADD) + { + if(targ_p == source_p) + return; + + mode_changes[mode_count].letter = c; + mode_changes[mode_count].dir = MODE_ADD; + mode_changes[mode_count].caps = 0; + mode_changes[mode_count].nocaps = 0; + mode_changes[mode_count].mems = ALL_MEMBERS; + mode_changes[mode_count].id = targ_p->id; + mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count++].client = targ_p; + + mstptr->flags |= CHFL_HALFOP; + } + else + { + if(MyClient(source_p) && IsService(targ_p)) + { + sendto_one(source_p, form_str(ERR_ISCHANSERVICE), + me.name, source_p->name, targ_p->name, chptr->chname); + return; + } + + mode_changes[mode_count].letter = c; + mode_changes[mode_count].dir = MODE_DEL; + mode_changes[mode_count].caps = 0; + mode_changes[mode_count].nocaps = 0; + mode_changes[mode_count].mems = ALL_MEMBERS; + mode_changes[mode_count].id = targ_p->id; + mode_changes[mode_count].arg = targ_p->name; + mode_changes[mode_count++].client = targ_p; + + mstptr->flags &= ~CHFL_HALFOP; + } +} + void chm_voice(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, @@ -906,7 +1106,7 @@ chm_voice(struct Client *source_p, struct Channel *chptr, const char *opnick; struct Client *targ_p; - if(alevel != CHFL_CHANOP) + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { if(!(*errors & SM_ERR_NOOPS)) sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), @@ -984,7 +1184,7 @@ chm_limit(struct Client *source_p, struct Channel *chptr, static char limitstr[30]; int limit; - if(alevel != CHFL_CHANOP) + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { if(!(*errors & SM_ERR_NOOPS)) sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), @@ -1043,7 +1243,7 @@ chm_throttle(struct Client *source_p, struct Channel *chptr, { int joins = 0, timeslice = 0; - if(alevel != CHFL_CHANOP) + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { if(!(*errors & SM_ERR_NOOPS)) sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), @@ -1126,7 +1326,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr, } #ifndef FORWARD_OPERONLY - if(alevel != CHFL_CHANOP) + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { if(!(*errors & SM_ERR_NOOPS)) sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), @@ -1218,7 +1418,7 @@ chm_key(struct Client *source_p, struct Channel *chptr, { char *key; - if(alevel != CHFL_CHANOP) + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { if(!(*errors & SM_ERR_NOOPS)) sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), @@ -1295,7 +1495,7 @@ chm_regonly(struct Client *source_p, struct Channel *chptr, int alevel, int parc, int *parn, const char **parv, int *errors, int dir, char c, long mode_type) { - if(alevel != CHFL_CHANOP) + if(alevel != CHFL_CHANOP && alevel != CHFL_OWNER && alevel != CHFL_HALFOP) { if(!(*errors & SM_ERR_NOOPS)) sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), @@ -1429,14 +1629,14 @@ struct ChannelMode chmode_table[256] = {chm_nosuch, 0 }, {chm_nosuch, 0 }, {chm_nosuch, 0 }, - {chm_nosuch, 0 }, /* a */ + {chm_owner, 0 }, /* a */ {chm_ban, CHFL_BAN }, /* b */ {chm_simple, MODE_NOCOLOR }, /* c */ {chm_nosuch, 0 }, /* d */ {chm_ban, CHFL_EXCEPTION }, /* e */ {chm_forward, 0 }, /* f */ {chm_simple, MODE_FREEINVITE }, /* g */ - {chm_nosuch, 0 }, /* h */ + {chm_halfop, 0 }, /* h */ {chm_simple, MODE_INVITEONLY }, /* i */ {chm_throttle, 0 }, /* j */ {chm_key, 0 }, /* k */ diff --git a/src/send.c b/src/send.c index 4aebff9..e5d71f2 100644 --- a/src/send.c +++ b/src/send.c @@ -584,7 +584,7 @@ sendto_channel_opmod(struct Client *one, struct Client *source_p, if(IsIOError(target_p->from) || target_p->from == one) continue; - if((msptr->flags & CHFL_CHANOP) == 0) + if(!is_any_op(msptr)) continue; if(IsDeaf(target_p))