only ops should be able to set/remove MODE_AUDITORIUM (+u)
[ircu2.10.12-pk.git] / ircd / channel.c
index 01d25072c95275dc46bbafdbd9bdcc908244764f..3f563c326168645878d85aee5c29070dfae8deb4 100644 (file)
@@ -870,6 +870,8 @@ void channel_modes(struct Client *cptr, char *mbuf, char *pbuf, int buflen,
     *mbuf++ = 'M';
   if (chptr->mode.mode & MODE_QUARANTINE)
     *mbuf++ = 'Q';
+  if (chptr->mode.mode & MODE_AUDITORIUM)
+    *mbuf++ = 'u';
   if (chptr->mode.limit) {
     *mbuf++ = 'l';
     ircd_snprintf(0, pbuf, buflen, "%u", chptr->mode.limit);
@@ -1577,7 +1579,7 @@ static int
 modebuf_flush_int(struct ModeBuf *mbuf, int all)
 {
   /* we only need the flags that don't take args right now */
-  static int flags[] = {
+  static ulong64 flags[] = {
 /*  MODE_CHANOP,       'o', */
 /*  MODE_VOICE,                'v', */
     MODE_PRIVATE,      'p',
@@ -1603,14 +1605,15 @@ modebuf_flush_int(struct ModeBuf *mbuf, int all)
     MODE_NOAMSGS,   'M',
        MODE_NONOTICE,  'N',
        MODE_QUARANTINE,  'Q',
+       MODE_AUDITORIUM,  'u',
     0x0, 0x0
   };
-  static int local_flags[] = {
+  static ulong64 local_flags[] = {
     MODE_WASDELJOINS,   'd',
     0x0, 0x0
   };
   int i;
-  int *flag_p;
+  ulong64 *flag_p;
 
   struct Client *app_source; /* where the MODE appears to come from */
 
@@ -1633,8 +1636,8 @@ modebuf_flush_int(struct ModeBuf *mbuf, int all)
 
   char limitbuf[20],accessbuf[20]; /* convert limits to strings */
 
-  unsigned int limitdel = MODE_LIMIT;
-  unsigned int accessdel = MODE_ACCESS;
+  ulong64 limitdel = MODE_LIMIT;
+  ulong64 accessdel = MODE_ACCESS;
 
   assert(0 != mbuf);
 
@@ -2032,7 +2035,7 @@ modebuf_init(struct ModeBuf *mbuf, struct Client *source,
  * @param mode         MODE_ADD or MODE_DEL OR'd with MODE_PRIVATE etc.
  */
 void
-modebuf_mode(struct ModeBuf *mbuf, unsigned int mode)
+modebuf_mode(struct ModeBuf *mbuf, ulong64 mode)
 {
   assert(0 != mbuf);
   assert(0 != (mode & (MODE_ADD | MODE_DEL)));
@@ -2040,7 +2043,8 @@ modebuf_mode(struct ModeBuf *mbuf, unsigned int mode)
   mode &= (MODE_ADD | MODE_DEL | MODE_PRIVATE | MODE_SECRET | MODE_MODERATED |
           MODE_TOPICLIMIT | MODE_INVITEONLY | MODE_NOPRIVMSGS | MODE_REGONLY |
            MODE_DELJOINS | MODE_WASDELJOINS | MODE_REGISTERED | MODE_PERSIST |
-           MODE_NOCOLOUR | MODE_NOCTCP | MODE_NOAMSGS | MODE_NONOTICE | MODE_QUARANTINE);
+           MODE_NOCOLOUR | MODE_NOCTCP | MODE_NOAMSGS | MODE_NONOTICE | 
+                  MODE_QUARANTINE | MODE_AUDITORIUM);
 
   if (!(mode & ~(MODE_ADD | MODE_DEL))) /* don't add empty modes... */
     return;
@@ -2054,10 +2058,10 @@ modebuf_mode(struct ModeBuf *mbuf, unsigned int mode)
   }
 }
 
-/** Append a mode that takes an int argument to the modebuf
+/** Append a mode that takes an ulong64 argument to the modebuf
  *
  * 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
+ * ulong64 parameter; mode may *only* be the relevant mode flag ORed with one
  * of MODE_ADD or MODE_DEL
  *
  * @param mbuf         The mode buffer to append to.
@@ -2065,7 +2069,7 @@ modebuf_mode(struct ModeBuf *mbuf, unsigned int mode)
  * @param uint         The argument to the mode.
  */
 void
-modebuf_mode_uint(struct ModeBuf *mbuf, unsigned int mode, unsigned int uint)
+modebuf_mode_uint(struct ModeBuf *mbuf, ulong64 mode, unsigned int uint)
 {
   assert(0 != mbuf);
   assert(0 != (mode & (MODE_ADD | MODE_DEL)));
@@ -2098,7 +2102,7 @@ modebuf_mode_uint(struct ModeBuf *mbuf, unsigned int mode, unsigned int uint)
  * @param free         If the string should be free'd later.
  */
 void
-modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode, char *string,
+modebuf_mode_string(struct ModeBuf *mbuf, ulong64 mode, char *string,
                    int free)
 {
   assert(0 != mbuf);
@@ -2124,7 +2128,7 @@ modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode, char *string,
  * @param oplevel       The oplevel the user had or will have
  */
 void
-modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode,
+modebuf_mode_client(struct ModeBuf *mbuf, ulong64 mode,
                    struct Client *client, int oplevel)
 {
   assert(0 != mbuf);
@@ -2192,7 +2196,7 @@ modebuf_flush(struct ModeBuf *mbuf)
 void
 modebuf_extract(struct ModeBuf *mbuf, char *buf)
 {
-  static int flags[] = {
+  static ulong64 flags[] = {
 /*  MODE_CHANOP,       'o', */
 /*  MODE_VOICE,                'v', */
     MODE_PRIVATE,      'p',
@@ -2218,11 +2222,12 @@ modebuf_extract(struct ModeBuf *mbuf, char *buf)
        MODE_QUARANTINE,  'Q',
        MODE_ALTCHAN,    'F',
        MODE_ACCESS,    'a',
+       MODE_AUDITORIUM, 'u',
     0x0, 0x0
   };
-  unsigned int add;
+  ulong64 add;
   int i, bufpos = 0, len;
-  int *flag_p;
+  ulong64 *flag_p;
   char *key = 0, limitbuf[20], accessbuf[20];
   char *apass = 0, *upass = 0, *altchan = 0;
 
@@ -2334,17 +2339,17 @@ struct ParseState {
   struct Membership *member;
   int parc;
   char **parv;
-  unsigned int flags;
-  unsigned int dir;
-  unsigned int done;
-  unsigned int add;
-  unsigned int del;
+  ulong64 flags;
+  ulong64 dir;
+  ulong64 done;
+  ulong64 add;
+  ulong64 del;
   int args_used;
   int max_args;
   int numbans;
   struct Ban banlist[MAXPARA];
   struct {
-    unsigned int flag;
+    ulong64 flag;
     unsigned short oplevel;
     struct Client *client;
   } cli_change[MAXPARA];
@@ -2375,7 +2380,7 @@ send_notoper(struct ParseState *state)
  * @param flag_p       ?
  */
 static void
-mode_parse_limit(struct ParseState *state, int *flag_p)
+mode_parse_limit(struct ParseState *state, ulong64 *flag_p)
 {
   unsigned int t_limit;
 
@@ -2440,7 +2445,7 @@ mode_parse_limit(struct ParseState *state, int *flag_p)
 
 
 static void
-mode_parse_access(struct ParseState *state, int *flag_p)
+mode_parse_access(struct ParseState *state, ulong64 *flag_p)
 {
   unsigned int t_access;
 
@@ -2513,7 +2518,7 @@ mode_parse_access(struct ParseState *state, int *flag_p)
 
 
 static void
-mode_parse_altchan(struct ParseState *state, int *flag_p)
+mode_parse_altchan(struct ParseState *state, ulong64 *flag_p)
 {
   char *t_str;
 
@@ -2597,7 +2602,7 @@ mode_parse_altchan(struct ParseState *state, int *flag_p)
 }
 
 static void
-mode_parse_quarantine(struct ParseState *state, int *flag_p)
+mode_parse_quarantine(struct ParseState *state, ulong64 *flag_p)
 {
     
 }
@@ -2643,7 +2648,7 @@ is_clean_key(struct ParseState *state, char *s, char *command)
  * Helper function to convert keys
  */
 static void
-mode_parse_key(struct ParseState *state, int *flag_p)
+mode_parse_key(struct ParseState *state, ulong64 *flag_p)
 {
   char *t_str;
 
@@ -2730,7 +2735,7 @@ mode_parse_key(struct ParseState *state, int *flag_p)
  * Helper function to convert user passes
  */
 static void
-mode_parse_upass(struct ParseState *state, int *flag_p)
+mode_parse_upass(struct ParseState *state, ulong64 *flag_p)
 {
   char *t_str;
 
@@ -2849,7 +2854,7 @@ mode_parse_upass(struct ParseState *state, int *flag_p)
  * Helper function to convert admin passes
  */
 static void
-mode_parse_apass(struct ParseState *state, int *flag_p)
+mode_parse_apass(struct ParseState *state, ulong64 *flag_p)
 {
   struct Membership *memb;
   char *t_str;
@@ -3102,7 +3107,7 @@ int apply_ban(struct Ban **banlist, struct Ban *newban, int do_free)
 /* Removes MODE_WASDELJOINS in a channel.
  * Reveals all hidden users.
  */
-static void reveal_hidden_chan_users(struct ParseState *state, int *flag_p) {
+static void reveal_hidden_chan_users(struct ParseState *state, ulong64 *flag_p) {
     struct Membership *member;
 
     /* If the channel is not +d, do nothing. */
@@ -3116,11 +3121,33 @@ static void reveal_hidden_chan_users(struct ParseState *state, int *flag_p) {
     }
 }
 
+/* Handle MODE_AUDITORIUM changes 
+ * set Delayed for all hidden users on MODE_DEL
+ * part all nonoped users on MODE_ADD
+ */
+static void audit_chan_users(struct ParseState *state, ulong64 *flag_p) {
+       struct Membership *member;
+       if (state->dir == MODE_ADD) {
+               for(member = state->chptr->members; member; member = member->next_member) {
+                       if(!IsChanOp(member) && !HasVoice(member)) {
+                               sendcmdto_channel_butserv_butone(member->user, CMD_PART, member->channel, member->user, SKIP_OPS, "%H :%s", member->channel, "mode +u set.");
+                       }
+               }
+       } else {
+               for(member = state->chptr->members; member; member = member->next_member) {
+                       if(!IsChanOp(member) && !HasVoice(member)) {
+                               sendcmdto_channel_butserv_butone(member->user, CMD_JOIN, member->channel, member->user, SKIP_OPS, ":%H", member->channel);
+                       }
+               }
+       }
+}
+
+
 /*
  * Helper function to convert bans
  */
 static void
-mode_parse_ban(struct ParseState *state, int *flag_p)
+mode_parse_ban(struct ParseState *state, ulong64 *flag_p)
 {
   char *t_str, *s;
   struct Ban *ban, *newban;
@@ -3284,7 +3311,7 @@ mode_process_bans(struct ParseState *state)
  * Helper function to process client changes
  */
 static void
-mode_parse_client(struct ParseState *state, int *flag_p)
+mode_parse_client(struct ParseState *state, ulong64 *flag_p)
 {
   char *t_str;
   char *colon;
@@ -3488,6 +3515,10 @@ mode_process_clients(struct ParseState *state)
     modebuf_mode_client(state->mbuf, state->cli_change[i].flag,
                        state->cli_change[i].client,
                         state->cli_change[i].oplevel);
+       
+       if(MyUser(member->user) && (member->channel->mode.mode & MODE_AUDITORIUM) && (state->cli_change[i].flag & MODE_CHANOP)) {
+               do_names(member->user, member->channel, NAMES_ALL|NAMES_EON|((member->status & MODE_CHANOP) ? 0 : NAMES_OPS));
+       }
   } /* for (i = 0; state->cli_change[i].flags; i++) */
 }
 
@@ -3495,7 +3526,7 @@ mode_process_clients(struct ParseState *state)
  * Helper function to process the simple modes
  */
 static void
-mode_parse_mode(struct ParseState *state, int *flag_p)
+mode_parse_mode(struct ParseState *state, ulong64 *flag_p)
 {
   /* If they're not an oper, they can't change modes */
   if (state->flags & (MODE_PARSE_NOTOPER | MODE_PARSE_NOTMEMBER)) {
@@ -3509,6 +3540,9 @@ mode_parse_mode(struct ParseState *state, int *flag_p)
   /* Local users are not permitted to change registration status */
   if (flag_p[0] == MODE_REGISTERED && !(state->flags & MODE_PARSE_FORCE) && MyUser(state->sptr))
     return;
+       
+  if(flag_p[0] == MODE_AUDITORIUM)
+    audit_chan_users(state, flag_p);
 
   if (state->dir == MODE_ADD) {
     state->add |= flag_p[0];
@@ -3550,7 +3584,7 @@ mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr,
           struct Channel *chptr, int parc, char *parv[], unsigned int flags,
           struct Membership* member)
 {
-  static int chan_flags[] = {
+  static ulong64 chan_flags[] = {
     MODE_CHANOP,       'o',
     MODE_VOICE,                'v',
     MODE_PRIVATE,      'p',
@@ -3577,13 +3611,14 @@ mode_parse(struct ModeBuf *mbuf, struct Client *cptr, struct Client *sptr,
        MODE_QUARANTINE,      'Q',
        MODE_ALTCHAN,        'F',
     MODE_ACCESS,        'a',
+       MODE_AUDITORIUM,    'u',
     MODE_ADD,          '+',
     MODE_DEL,          '-',
     0x0, 0x0
   };
   int i;
-  int *flag_p;
-  unsigned int t_mode;
+  ulong64 *flag_p;
+  ulong64 t_mode;
   char *modestr;
   struct ParseState state;
 
@@ -3871,7 +3906,9 @@ joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, unsigned int flags)
     SetUserParting(member);
 
     /* Send notification to channel */
-    if (!(flags & (CHFL_ZOMBIE | CHFL_DELAYED)))
+       if((chan->mode.mode & MODE_AUDITORIUM) && !(flags & CHFL_VOICED_OR_OPPED)) {
+         //do noting here
+    } else if (!(flags & (CHFL_ZOMBIE | CHFL_DELAYED)))
       sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_PART, chan, NULL, 0,
                                (flags & CHFL_BANNED || !jbuf->jb_comment) ?
                                ":%H" : "%H :%s", chan, jbuf->jb_comment);
@@ -3909,8 +3946,14 @@ joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, unsigned int flags)
                            "%H %Tu %i", chan, chan->creationtime, 0);
          }
        }
-
-    if (!((chan->mode.mode & MODE_DELJOINS) && !(flags & CHFL_VOICED_OR_OPPED)) && !((flags & CHFL_INVISIBLE) && !(flags & CHFL_VOICED_OR_OPPED))) {
+       
+       if((chan->mode.mode & MODE_AUDITORIUM) && !(flags & CHFL_VOICED_OR_OPPED)) {
+               //we have to send this JOIN event to ops only...                  
+               sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_JOIN, chan, NULL, SKIP_NONOPS, "%H", chan);
+               if(MyUser(jbuf->jb_source))
+                 sendcmdto_one(jbuf->jb_source, CMD_JOIN, jbuf->jb_source, ":%H", chan);
+       }
+    else if (!((chan->mode.mode & MODE_DELJOINS) && !(flags & CHFL_VOICED_OR_OPPED)) && !((flags & CHFL_INVISIBLE) && !(flags & CHFL_VOICED_OR_OPPED))) {
       /* Send the notification to the channel */
       sendcmdto_channel_butserv_butone(jbuf->jb_source, CMD_JOIN, chan, NULL, 0, "%H", chan);
 
@@ -4023,6 +4066,16 @@ void CheckDelayedJoins(struct Channel *chan)
   }
 }
 
+void CheckEnableDelayedJoins(struct Channel *chan) {
+  if (!(chan->mode.mode & MODE_WASDELJOINS) && find_delayed_joins(chan)) {
+       chan->mode.mode |= MODE_WASDELJOINS;
+       sendcmdto_channel_butserv_butone(&me, CMD_MODE, chan, NULL, 0,
+                                     "%H +d", chan);
+    sendcmdto_channel_servers_butone(&me, CMD_MODE, chan, NULL, 0,
+                                     "%H +d", chan);
+  }
+}
+
 /* checks whether a channel is nonpersistent with no users and deletes it
  * returns 1 if deleted, otherwise 0
  */