X-Git-Url: https://jfr.im/git/irc/rqf/shadowircd.git/blobdiff_plain/f0e0e5672df9bbc801c26f048e72e4be198ac2e0..2606c73c6f02ba5dbdedfd895f33dd3218a7f562:/src/chmode.c diff --git a/src/chmode.c b/src/chmode.c index c2fd63c..6ee15eb 100644 --- a/src/chmode.c +++ b/src/chmode.c @@ -22,7 +22,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * - * $Id: chmode.c 3580 2007-11-07 23:45:14Z jilles $ */ #include "stdinc.h" @@ -44,6 +43,7 @@ #include "chmode.h" #include "irc_dictionary.h" + /* bitmasks for error returns, so we send once per call */ #define SM_ERR_NOTS 0x00000001 /* No TS on channel */ #define SM_ERR_NOOPS 0x00000002 /* No chan ops */ @@ -57,6 +57,7 @@ #define SM_ERR_NOPRIVS 0x00000400 #define SM_ERR_RPL_Q 0x00000800 #define SM_ERR_RPL_F 0x00001000 +#define SM_ERR_MLOCK 0x00002000 #define MAXMODES_SIMPLE 46 /* a-zA-Z except bqeIov */ @@ -69,6 +70,7 @@ static int no_override_deop; char cflagsbuf[256]; char cflagsmyinfo[256]; +char cflagsparaminfo[256]; int chmode_flags[256]; @@ -120,14 +122,17 @@ construct_cflags_strings(void) break; default: - if(chmode_flags[i] != 0) + if(chmode_flags[i] != 0 && !(chmode_table[i].set_func == chm_orphaned)) { *ptr++ = (char) i; } } /* Should we leave orphaned check here? -- dwr */ - if(!(chmode_table[i].set_func == chm_nosuch) && !(chmode_table[i].set_func == chm_orphaned)) + if( !(chmode_table[i].set_func == chm_nosuch) && + !(chmode_table[i].set_func == chm_orphaned) && + !(chmode_table[i].set_func == chm_admin && !ConfigChannel.use_admin) && + !(chmode_table[i].set_func == chm_halfop && !ConfigChannel.use_halfop)) { *ptr2++ = (char) i; } @@ -137,6 +142,21 @@ construct_cflags_strings(void) *ptr2++ = '\0'; } +void +construct_cflag_param_string(void) +{ + + *cflagsparaminfo = '\0'; + rb_snprintf(cflagsparaminfo, sizeof cflagsparaminfo, "%sb%s%s%s%sklov%s%s", + ConfigChannel.use_admin ? "a" : "", + ConfigChannel.use_except ? "e" : "", + ConfigChannel.use_forward ? "f" : "", + ConfigChannel.use_halfop ? "h" : "", + strcasecmp(ConfigChannel.disabledmodes, "j") ? "" : "j", + strcasecmp(ConfigChannel.disabledmodes, "q") ? "" : "q", + ConfigChannel.use_invex ? "I" : ""); +} + /* * find_umode_slot * @@ -585,7 +605,10 @@ chm_orphaned(struct Client *source_p, struct Channel *chptr, const char **parv, int *errors, int dir, char c, long mode_type) { if(MyClient(source_p)) + { + sendto_one_numeric(source_p, 469, "Mode %c is disabled.", c); return; + } if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type)) { @@ -637,6 +660,7 @@ chm_hidden(struct Client *source_p, struct Channel *chptr, if(MyClient(source_p) && (++mode_limit_simple > MAXMODES_SIMPLE)) return; + /* setting + */ if((dir == MODE_ADD) && !(chptr->mode.mode & mode_type)) { @@ -650,6 +674,19 @@ chm_hidden(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].mems = ONLY_OPERS; mode_changes[mode_count].override = 0; mode_changes[mode_count++].arg = NULL; + + /* A little ugly */ + sendto_wallops_flags(UMODE_WALLOP, &me, + "+%c set on [%s] by %s!%s@%s", + c, chptr->chname, source_p->name, source_p->username, source_p->host); + ilog(L_MAIN, "+%c set on [%s] by %s", + c, chptr->chname, get_oper_name(source_p)); + + if(*chptr->chname != '&') + sendto_server(NULL, NULL, NOCAPS, NOCAPS, + ":%s WALLOPS :+%c set on [%s] by %s!%s@%s", + me.name, c, chptr->chname, source_p->name, source_p->username, + source_p->host); } else if((dir == MODE_DEL) && (chptr->mode.mode & mode_type)) { @@ -663,6 +700,19 @@ chm_hidden(struct Client *source_p, struct Channel *chptr, mode_changes[mode_count].id = NULL; mode_changes[mode_count].override = 0; mode_changes[mode_count++].arg = NULL; + + /* A little ugly */ + sendto_wallops_flags(UMODE_WALLOP, &me, + "+%c unset from [%s] by %s!%s@%s", + c, chptr->chname, source_p->name, source_p->username, source_p->host); + ilog(L_MAIN, "+%c unset from [%s] by %s", + c, chptr->chname, get_oper_name(source_p)); + + if(*chptr->chname != '&') + sendto_server(NULL, NULL, NOCAPS, NOCAPS, + ":%s WALLOPS :+%c unset from [%s] by %s!%s@%s", + me.name, c, chptr->chname, source_p->name, source_p->username, + source_p->host); } } @@ -1582,7 +1632,7 @@ chm_forward(struct Client *source_p, struct Channel *chptr, if(MyClient(source_p) && !(targptr->mode.mode & MODE_FREETARGET)) { if((msptr = find_channel_membership(targptr, source_p)) == NULL || - is_any_op(msptr)) + !is_any_op(msptr)) { if(IsOverride(source_p)) override = 1; @@ -2087,6 +2137,19 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, dir = MODE_QUERY; break; default: + /* If this mode char is locked, don't allow local users to change it. */ + if (MyClient(source_p) && chptr->mode_lock && strchr(chptr->mode_lock, c)) + { + if (!(errors & SM_ERR_MLOCK)) + sendto_one_numeric(source_p, + ERR_MLOCKRESTRICTED, + form_str(ERR_MLOCKRESTRICTED), + chptr->chname, + c, + chptr->mode_lock); + errors |= SM_ERR_MLOCK; + continue; + } chmode_table[(unsigned char) c].set_func(fakesource_p, chptr, alevel, parc, &parn, parv, &errors, dir, c, @@ -2234,3 +2297,24 @@ set_channel_mode(struct Client *client_p, struct Client *source_p, if(MyClient(source_p) || rb_dlink_list_length(&serv_list) > 1) send_cap_mode_changes(client_p, source_p, chptr, mode_changes, mode_count); } + +/* set_channel_mlock() + * + * inputs - client, source, channel, params + * output - + * side effects - channel mlock is changed / MLOCK is propagated + */ +void +set_channel_mlock(struct Client *client_p, struct Client *source_p, + struct Channel *chptr, const char *newmlock, int propagate) +{ + rb_free(chptr->mode_lock); + chptr->mode_lock = newmlock ? rb_strdup(newmlock) : NULL; + + if (propagate) + { + sendto_server(client_p, NULL, CAP_TS6 | CAP_MLOCK, NOCAPS, ":%s MLOCK %ld %s :%s", + source_p->id, (long) chptr->channelts, chptr->chname, + chptr->mode_lock ? chptr->mode_lock : ""); + } +}