diff -Nurp ircu2.10.12.10/doc/example.conf ircu2.10.12.10-opermodes/doc/example.conf --- ircu2.10.12.10/doc/example.conf 2007-02-25 16:40:22.000000000 +0100 +++ ircu2.10.12.10-opermodes/doc/example.conf 2007-03-13 02:38:32.000000000 +0100 @@ -115,6 +115,9 @@ Admin { # maxlinks = number; # sendq = size; # usermode = "+i"; +# hide_channels = yes|no; +# hide_idletime = yes|no; +# umode_chserv = yes|no; # }; # # maxlinks should be set at either 0 or 1. @@ -126,6 +129,12 @@ Admin { # Note that times can be specified as a number, or by giving something # like: 1 minutes 20 seconds, or 1*60+20. # +# hide_channels and hide_idletime allow users to set umode +n/+I to hide +# their channels or their idle time from non-opers +# +# umode_chserv allows users in this class to set usermode +k. +# USE THIS WITH CARE, +k users cannot be deopped, kicked or killed! +# # Recommended server classes: # All your server uplinks you are not a hub for. Class { Files ircu2.10.12.10/include/.client.h.swp and ircu2.10.12.10-opermodes/include/.client.h.swp differ diff -Nurp ircu2.10.12.10/include/client.h ircu2.10.12.10-opermodes/include/client.h --- ircu2.10.12.10/include/client.h 2006-02-16 04:49:54.000000000 +0100 +++ ircu2.10.12.10-opermodes/include/client.h 2007-03-13 02:43:38.000000000 +0100 @@ -126,6 +126,9 @@ enum Priv PRIV_FORCE_OPMODE, /**< can hack modes on quarantined channels */ PRIV_FORCE_LOCAL_OPMODE, /**< can hack modes on quarantined local channels */ PRIV_APASS_OPMODE, /**< can hack modes +A/-A/+U/-U */ + PRIV_UMODE_NOCHAN, /**< may set umode +n (hide channels) */ + PRIV_UMODE_NOIDLE, /**< may set umode +I (hide idle time) */ + PRIV_UMODE_CHSERV, /**< may set umode +k (channel service) */ PRIV_LAST_PRIV /**< number of privileges */ }; @@ -166,6 +169,8 @@ enum Flag FLAG_DEBUG, /**< send global debug/anti-hack info */ FLAG_ACCOUNT, /**< account name has been set */ FLAG_HIDDENHOST, /**< user's host is hidden */ + FLAG_NOCHAN, /**< hide user's channels for non-opers */ + FLAG_NOIDLE, /**< hide idle time for non-opers */ FLAG_LAST_FLAG, /**< number of flags */ FLAG_LOCAL_UMODES = FLAG_LOCOP, /**< First local mode flag */ FLAG_GLOBAL_UMODES = FLAG_OPER /**< First global mode flag */ @@ -586,6 +591,10 @@ struct Client { #define IsPrivileged(x) (IsAnOper(x) || IsServer(x)) /** Return non-zero if the client's host is hidden. */ #define HasHiddenHost(x) (IsHiddenHost(x) && IsAccount(x)) +/** Return non-zero if the client's channels are hidden. */ +#define IsNoChan(x) HasFlag(x, FLAG_NOCHAN) +/** Return non-zero if the client's idle time is hidden. */ +#define IsNoIdle(x) HasFlag(x, FLAG_NOIDLE) /** Mark a client as having an in-progress net.burst. */ #define SetBurst(x) SetFlag(x, FLAG_BURST) @@ -625,6 +634,10 @@ struct Client { #define SetAccount(x) SetFlag(x, FLAG_ACCOUNT) /** Mark a client as having mode +x (hidden host). */ #define SetHiddenHost(x) SetFlag(x, FLAG_HIDDENHOST) +/** Mark a client as having mode +n (channels hidden). */ +#define SetNoChan(x) SetFlag(x, FLAG_NOCHAN) +/** Mark a client as having mode +I (idle time hidden). */ +#define SetNoIdle(x) SetFlag(x, FLAG_NOIDLE) /** Mark a client as having a pending PING. */ #define SetPingSent(x) SetFlag(x, FLAG_PINGSENT) @@ -658,6 +671,10 @@ struct Client { #define ClearServNotice(x) ClrFlag(x, FLAG_SERVNOTICE) /** Remove mode +x (hidden host) from the client. */ #define ClearHiddenHost(x) ClrFlag(x, FLAG_HIDDENHOST) +/** Remove mode +n (channels hidden) from the client. */ +#define ClearNoChan(x) ClrFlag(x, FLAG_NOCHAN) +/** Remove mode +I (idle time hidden) from the client. */ +#define ClearNoIdle(x) ClrFlag(x, FLAG_NOIDLE) /** Clear the client's pending PING flag. */ #define ClearPingSent(x) ClrFlag(x, FLAG_PINGSENT) diff -Nurp ircu2.10.12.10/ircd/client.c ircu2.10.12.10-opermodes/ircd/client.c --- ircu2.10.12.10/ircd/client.c 2005-10-13 01:50:04.000000000 +0200 +++ ircu2.10.12.10-opermodes/ircd/client.c 2007-03-13 02:40:38.000000000 +0100 @@ -158,6 +158,7 @@ client_set_privs(struct Client *client, FlagClr(&privs_global, PRIV_BADCHAN); FlagClr(&privs_global, PRIV_LOCAL_BADCHAN); FlagClr(&privs_global, PRIV_APASS_OPMODE); + FlagClr(&privs_global, PRIV_UMODE_CHSERV); memset(&privs_local, 0, sizeof(privs_local)); FlagSet(&privs_local, PRIV_CHAN_LIMIT); @@ -172,6 +173,8 @@ client_set_privs(struct Client *client, FlagSet(&privs_local, PRIV_WHOX); FlagSet(&privs_local, PRIV_DISPLAY); FlagSet(&privs_local, PRIV_FORCE_LOCAL_OPMODE); + FlagSet(&privs_local, PRIV_UMODE_NOCHAN); + FlagSet(&privs_local, PRIV_UMODE_NOIDLE); privs_defaults_set = 1; } @@ -236,6 +239,7 @@ static struct { P(BADCHAN), P(LOCAL_BADCHAN), P(SEE_CHAN), P(PROPAGATE), P(DISPLAY), P(SEE_OPERS), P(WIDE_GLINE), P(LIST_CHAN), P(FORCE_OPMODE), P(FORCE_LOCAL_OPMODE), P(APASS_OPMODE), + P(UMODE_NOCHAN), P(UMODE_NOIDLE), P(UMODE_CHSERV), #undef P { 0, 0 } }; diff -Nurp ircu2.10.12.10/ircd/ircd_lexer.l ircu2.10.12.10-opermodes/ircd/ircd_lexer.l --- ircu2.10.12.10/ircd/ircd_lexer.l 2007-02-25 16:41:48.000000000 +0100 +++ ircu2.10.12.10-opermodes/ircd/ircd_lexer.l 2007-03-13 02:39:22.000000000 +0100 @@ -151,6 +151,9 @@ static struct lexer_token { { "walk_lchan", TPRIV_WALK_LCHAN }, { "wide_gline", TPRIV_WIDE_GLINE }, { "whox", TPRIV_WHOX }, + { "hide_channels", TPRIV_UMODE_NOCHAN }, + { "hide_idletime", TPRIV_UMODE_NOIDLE }, + { "umode_chserv", TPRIV_UMODE_CHSERV }, { NULL, 0 } }; static int ntokens; diff -Nurp ircu2.10.12.10/ircd/ircd_parser.y ircu2.10.12.10-opermodes/ircd/ircd_parser.y --- ircu2.10.12.10/ircd/ircd_parser.y 2007-02-25 16:41:48.000000000 +0100 +++ ircu2.10.12.10-opermodes/ircd/ircd_parser.y 2007-03-13 02:39:08.000000000 +0100 @@ -165,6 +165,7 @@ static void parse_error(char *pattern,.. %token TOK_IPV4 TOK_IPV6 %token DNS /* and now a lot of privileges... */ +%token TPRIV_UMODE_NOCHAN TPRIV_UMODE_NOIDLE TPRIV_UMODE_CHSERV %token TPRIV_CHAN_LIMIT TPRIV_MODE_LCHAN TPRIV_DEOP_LCHAN TPRIV_WALK_LCHAN %token TPRIV_LOCAL_KILL TPRIV_REHASH TPRIV_RESTART TPRIV_DIE %token TPRIV_GLINE TPRIV_LOCAL_GLINE TPRIV_LOCAL_JUPE TPRIV_LOCAL_BADCHAN @@ -638,6 +639,9 @@ privtype: TPRIV_CHAN_LIMIT { $$ = PRIV_C TPRIV_MODE_LCHAN { $$ = PRIV_MODE_LCHAN; } | TPRIV_DEOP_LCHAN { $$ = PRIV_DEOP_LCHAN; } | TPRIV_WALK_LCHAN { $$ = PRIV_WALK_LCHAN; } | + TPRIV_UMODE_NOCHAN { $$ = PRIV_UMODE_NOCHAN; } | + TPRIV_UMODE_NOIDLE { $$ = PRIV_UMODE_NOIDLE; } | + TPRIV_UMODE_CHSERV { $$ = PRIV_UMODE_CHSERV; } | KILL { $$ = PRIV_KILL; } | TPRIV_LOCAL_KILL { $$ = PRIV_LOCAL_KILL; } | TPRIV_REHASH { $$ = PRIV_REHASH; } | diff -Nurp ircu2.10.12.10/ircd/m_whois.c ircu2.10.12.10-opermodes/ircd/m_whois.c --- ircu2.10.12.10/ircd/m_whois.c 2006-06-09 04:16:17.000000000 +0200 +++ ircu2.10.12.10-opermodes/ircd/m_whois.c 2007-03-13 02:27:42.000000000 +0100 @@ -144,7 +144,7 @@ static void do_whois(struct Client* sptr cli_info(acptr)); /* Display the channels this user is on. */ - if (!IsChannelService(acptr)) + if (!IsChannelService(acptr) && (!IsNoChan(acptr) || IsAnOper(sptr) || acptr == sptr)) { struct Membership* chan; mlen = strlen(cli_name(&me)) + strlen(cli_name(sptr)) + 12 + strlen(name); @@ -219,10 +219,12 @@ static void do_whois(struct Client* sptr * probably a good place to add them :) */ - if (MyConnect(acptr) && (!feature_bool(FEAT_HIS_WHOIS_IDLETIME) || - (sptr == acptr || IsAnOper(sptr) || parc >= 3))) + if (MyConnect(acptr) && (!IsNoIdle(acptr) || sptr == acptr || IsAnOper(sptr)) && + (!feature_bool(FEAT_HIS_WHOIS_IDLETIME) || (sptr == acptr || IsAnOper(sptr) || parc >= 3))) + { send_reply(sptr, RPL_WHOISIDLE, name, CurrentTime - user->last, cli_firsttime(acptr)); + } } } diff -Nurp ircu2.10.12.10/ircd/s_user.c ircu2.10.12.10-opermodes/ircd/s_user.c --- ircu2.10.12.10/ircd/s_user.c 2007-01-13 19:43:41.000000000 +0100 +++ ircu2.10.12.10-opermodes/ircd/s_user.c 2007-03-13 02:39:58.000000000 +0100 @@ -410,6 +410,14 @@ int register_user(struct Client *cptr, s if (!feature_bool(FEAT_HIS_DEBUG_OPER_ONLY)) SetDebug(sptr); break; + case 'n': + if (HasPriv(sptr, PRIV_UMODE_NOCHAN)) + SetNoChan(sptr); + break; + case 'I': + if (HasPriv(sptr, PRIV_UMODE_NOIDLE)) + SetNoIdle(sptr); + break; } } } @@ -511,7 +519,9 @@ static const struct UserMode { { FLAG_CHSERV, 'k' }, { FLAG_DEBUG, 'g' }, { FLAG_ACCOUNT, 'r' }, - { FLAG_HIDDENHOST, 'x' } + { FLAG_HIDDENHOST, 'x' }, + { FLAG_NOCHAN, 'n' }, + { FLAG_NOIDLE, 'I' } }; /** Length of #userModeList. */ @@ -1131,6 +1141,18 @@ int set_user_mode(struct Client *cptr, s case 'x': if (what == MODE_ADD) do_host_hiding = 1; break; + case 'n': + if (what == MODE_ADD) + SetNoChan(sptr); + else + ClearNoChan(sptr); + break; + case 'I': + if (what == MODE_ADD) + SetNoIdle(sptr); + else + ClearNoIdle(sptr); + break; default: send_reply(sptr, ERR_UMODEUNKNOWNFLAG, *m); @@ -1152,7 +1174,7 @@ int set_user_mode(struct Client *cptr, s * new umode; servers can set it, local users cannot; * prevents users from /kick'ing or /mode -o'ing */ - if (!FlagHas(&setflags, FLAG_CHSERV)) + if (!FlagHas(&setflags, FLAG_CHSERV) && IsChannelService(sptr) && !HasPriv(sptr, PRIV_UMODE_CHSERV)) ClearChannelService(sptr); /* * only send wallops to opers @@ -1170,6 +1192,10 @@ int set_user_mode(struct Client *cptr, s !IsAnOper(sptr) && !FlagHas(&setflags, FLAG_DEBUG)) ClearDebug(sptr); } + if (!FlagHas(&setflags, FLAG_NOCHAN) && IsNoChan(sptr) && !HasPriv(sptr, PRIV_UMODE_NOCHAN)) + ClearNoChan(sptr); + if (!FlagHas(&setflags, FLAG_NOIDLE) && IsNoIdle(sptr) && !HasPriv(sptr, PRIV_UMODE_NOIDLE)) + ClearNoIdle(sptr); if (MyConnect(sptr)) { if ((FlagHas(&setflags, FLAG_OPER) || FlagHas(&setflags, FLAG_LOCOP)) && diff -Nurp ircu2.10.12.10/ircd/whocmds.c ircu2.10.12.10-opermodes/ircd/whocmds.c --- ircu2.10.12.10/ircd/whocmds.c 2007-03-04 15:55:31.000000000 +0100 +++ ircu2.10.12.10-opermodes/ircd/whocmds.c 2007-03-13 02:26:40.000000000 +0100 @@ -90,7 +90,7 @@ void do_who(struct Client* sptr, struct chan = find_channel_member(acptr, repchan); } else if ((!fields || (fields & (WHO_FIELD_CHA | WHO_FIELD_FLA))) - && !IsChannelService(acptr)) + && !IsChannelService(acptr) && (!IsNoChan(acptr) || IsOper(sptr) || sptr == acptr)) { for (chan = cli_user(acptr)->channel; chan; chan = chan->next_channel) if (PubChannel(chan->channel) &&