Author: Kev <klmitch@mit.edu>
authorKevin L. Mitchell <klmitch@mit.edu>
Fri, 31 Mar 2000 18:19:09 +0000 (18:19 +0000)
committerKevin L. Mitchell <klmitch@mit.edu>
Fri, 31 Mar 2000 18:19:09 +0000 (18:19 +0000)
Log message:

* ircd/m_clearmode.c (do_clearmode): updated uses of
modebuf_mode_string() for the new usage

* ircd/channel.c: added flag MODE_FREE and an int argument to
modebuf_mode_string() to indicate that the string must be free'd;
updated calls to modebuf_mode_string() for the new usage; called
collapse(pretty_mask()) on the ban string and use allocated memory
for it; added ban list length accounting; fixed a number of small
bugs in ban processing

* include/channel.h: added flag MODE_FREE and an int argument to
modebuf_mode_string() to indicate that the string must be free'd

git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@111 c9e4aea6-c8fd-4c43-8297-357d70d61c8c

ChangeLog
include/channel.h
ircd/channel.c
ircd/m_clearmode.c

index e3bc9fad865d4ea705cb05d52c02c89c571b5aae..ae1022999c1dd9401d10e01433988768ad1cb3e2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2000-03-31  Kevin L. Mitchell  <klmitch@mit.edu>
 
+       * ircd/m_clearmode.c (do_clearmode): updated uses of
+       modebuf_mode_string() for the new usage
+
+       * ircd/channel.c: added flag MODE_FREE and an int argument to
+       modebuf_mode_string() to indicate that the string must be free'd;
+       updated calls to modebuf_mode_string() for the new usage; called
+       collapse(pretty_mask()) on the ban string and use allocated memory
+       for it; added ban list length accounting; fixed a number of small
+       bugs in ban processing
+
+       * include/channel.h: added flag MODE_FREE and an int argument to
+       modebuf_mode_string() to indicate that the string must be free'd
+
        * ircd/m_clearmode.c (do_clearmode): made sure clearmode removed
        keys and limits that are set
 
 #
 # ChangeLog for ircu2.10.11
 #
-# $Id: ChangeLog,v 1.47 2000-03-31 15:35:18 kev Exp $
+# $Id: ChangeLog,v 1.48 2000-03-31 18:19:09 kev Exp $
 #
 # Insert new changes at beginning of the change list.
 #
index 1abc9dd491538e0cd61697eb576dc33dcc09cc87..3c748e027ab3657fbc80a446fc60868b810e36f1 100644 (file)
@@ -89,6 +89,7 @@ struct Client;
                                  * temporary TS; can be removed when all 2.10 */
 #define MODE_LISTED     0x10000
 #define MODE_SAVE      0x20000 /* save this mode-with-arg 'til later */
+#define MODE_FREE      0x40000 /* string needs to be passed to MyFree() */
 /*
  * mode flags which take another parameter (With PARAmeterS)
  */
@@ -330,7 +331,7 @@ 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);
+                               char *string, int free);
 extern void modebuf_mode_client(struct ModeBuf *mbuf, unsigned int mode,
                                struct Client *client);
 extern int modebuf_flush(struct ModeBuf *mbuf);
index b89fc0c2270605364cf81ae66930395718178f7d..25b310c6f328f989407c4cda4df0286135e2e4db 100644 (file)
@@ -2987,7 +2987,8 @@ modebuf_flush_int(struct ModeBuf *mbuf, int all)
 
       if (mbuf->mb_count++ == i) /* don't overwrite our hard work */
        continue;
-    }
+    } else if (MB_TYPE(mbuf, i) & MODE_FREE)
+      MyFree(MB_STRING(mbuf, i)); /* free string if needed */
 
     MB_TYPE(mbuf, i) = 0;
     MB_UINT(mbuf, i) = 0;
@@ -3078,12 +3079,13 @@ modebuf_mode_uint(struct ModeBuf *mbuf, unsigned int mode, unsigned int uint)
  * MODE_ADD or MODE_DEL
  */
 void
-modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode, char *string)
+modebuf_mode_string(struct ModeBuf *mbuf, unsigned int mode, char *string,
+                   int free)
 {
   assert(0 != mbuf);
   assert(0 != (mode & (MODE_ADD | MODE_DEL)));
 
-  MB_TYPE(mbuf, mbuf->mb_count) = mode;
+  MB_TYPE(mbuf, mbuf->mb_count) = mode | (free ? MODE_FREE : 0);
   MB_STRING(mbuf, mbuf->mb_count) = string;
 
   /* when we've reached the maximal count, flush the buffer */
@@ -3303,11 +3305,11 @@ mode_parse_key(struct ParseState *state, int *flag_p)
   if (state->flags & MODE_PARSE_BOUNCE) {
     if (*state->chptr->mode.key) /* reset old key */
       modebuf_mode_string(state->mbuf, MODE_DEL | flag_p[0],
-                         state->chptr->mode.key);
+                         state->chptr->mode.key, 0);
     else /* remove new bogus key */
-      modebuf_mode_string(state->mbuf, MODE_ADD | flag_p[0], t_str);
+      modebuf_mode_string(state->mbuf, MODE_ADD | flag_p[0], t_str, 0);
   } else /* send new key */
-    modebuf_mode_string(state->mbuf, state->dir | flag_p[0], t_str);
+    modebuf_mode_string(state->mbuf, state->dir | flag_p[0], t_str, 0);
 
   if (state->flags & MODE_PARSE_SET) {
     if (state->dir == MODE_ADD) /* set the new key */
@@ -3358,12 +3360,14 @@ mode_parse_ban(struct ParseState *state, int *flag_p)
     return;
   }
 
+  t_str = collapse(pretty_mask(t_str));
+
   /* remember the ban for the moment... */
   if (state->dir == MODE_ADD) {
     newban = state->banlist + (state->numbans++);
     newban->next = 0;
 
-    newban->value.ban.banstr = t_str;
+    DupString(newban->value.ban.banstr, t_str);
     newban->value.ban.who = state->sptr->name;
     newban->value.ban.when = CurrentTime;
 
@@ -3373,6 +3377,12 @@ mode_parse_ban(struct ParseState *state, int *flag_p)
       newban->flags |= CHFL_BAN_IPMASK;
   }
 
+  if (!state->chptr->banlist) {
+    state->chptr->banlist = newban; /* add our ban with its flags */
+    state->done |= DONE_BANCLEAN;
+    return;
+  }
+
   /* Go through all bans */
   for (ban = state->chptr->banlist; ban; ban = ban->next) {
     /* first, clean the ban flags up a bit */
@@ -3407,12 +3417,17 @@ mode_parse_ban(struct ParseState *state, int *flag_p)
       if (!ircd_strcmp(ban->value.ban.banstr, t_str)) {
        if (state->done & DONE_BANCLEAN) /* If we're cleaning, finish */
          break;
-      } else if (!mmatch(ban->value.ban.banstr, t_str))
-       newban->flags |= CHFL_BAN_OVERLAPPED; /* our ban overlaps */
-      else if (!mmatch(t_str, ban->value.ban.banstr))
+       continue;
+      } else if (!mmatch(ban->value.ban.banstr, t_str)) {
+       if (!(ban->flags & MODE_DEL))
+         newban->flags |= CHFL_BAN_OVERLAPPED; /* our ban overlaps */
+      } else if (!mmatch(t_str, ban->value.ban.banstr))
        ban->flags |= MODE_DEL; /* mark ban for deletion: overlapping */
-      else if (!ban->next)
+
+      if (!ban->next) {
        ban->next = newban; /* add our ban with its flags */
+       break; /* get out of loop */
+      }
     }
   }
   state->done |= DONE_BANCLEAN;
@@ -3425,14 +3440,33 @@ static void
 mode_process_bans(struct ParseState *state)
 {
   struct SLink *ban, *newban, *prevban, *nextban;
+  int count = 0;
+  int len = 0;
+  int banlen;
   int changed = 0;
 
   for (prevban = 0, ban = state->chptr->banlist; ban; ban = nextban) {
+    count++;
+    banlen = strlen(ban->value.ban.banstr);
+    len += banlen;
     nextban = ban->next;
 
-    if (ban->flags & MODE_DEL) { /* Deleted a ban? */
+    if ((ban->flags & (MODE_DEL | MODE_ADD)) == (MODE_DEL | MODE_ADD)) {
+      if (prevban)
+       prevban->next = 0; /* Break the list; ban isn't a real ban */
+      else
+       state->chptr->banlist = 0;
+
+      count--;
+      len -= banlen;
+
+      MyFree(ban->value.ban.banstr);
+
+      continue;
+    } else if (ban->flags & MODE_DEL) { /* Deleted a ban? */
       modebuf_mode_string(state->mbuf, MODE_DEL | MODE_BAN,
-                         ban->value.ban.banstr);
+                         ban->value.ban.banstr,
+                         state->flags & MODE_PARSE_SET);
 
       if (state->flags & MODE_PARSE_SET) { /* Ok, make it take effect */
        if (prevban) /* clip it out of the list... */
@@ -3440,7 +3474,9 @@ mode_process_bans(struct ParseState *state)
        else
          state->chptr->banlist = ban->next;
 
-       MyFree(ban->value.ban.banstr); /* free it */
+       count--;
+       len -= banlen;
+
        MyFree(ban->value.ban.who);
        free_link(ban);
 
@@ -3449,34 +3485,50 @@ mode_process_bans(struct ParseState *state)
       } else
        ban->flags &= (CHFL_BAN | CHFL_BAN_IPMASK); /* unset other flags */
     } else if (ban->flags & MODE_ADD) { /* adding a ban? */
-      prevban->next = 0; /* Break the list; ban isn't a real ban */
+      if (prevban)
+       prevban->next = 0; /* Break the list; ban isn't a real ban */
+      else
+       state->chptr->banlist = 0;
 
       /* If we're supposed to ignore it, do so. */
       if (ban->flags & CHFL_BAN_OVERLAPPED &&
          !(state->flags & MODE_PARSE_BOUNCE)) {
-       prevban = ban;
-       continue;
-      }
+       count--;
+       len -= banlen;
 
-      /* add the ban to the buffer */
-      modebuf_mode_string(state->mbuf, MODE_ADD | MODE_BAN,
-                         ban->value.ban.banstr);
-
-      if (state->flags & MODE_PARSE_SET) { /* create a new ban */
-       newban = make_link();
-       DupString(newban->value.ban.banstr, ban->value.ban.banstr);
-       DupString(newban->value.ban.who, ban->value.ban.who);
-       newban->value.ban.when = ban->value.ban.when;
-       newban->flags = ban->flags & (CHFL_BAN | CHFL_BAN_IPMASK);
-
-       newban->next = state->chptr->banlist; /* and link it in */
-       state->chptr->banlist = newban;
-
-       changed++;
+       MyFree(ban->value.ban.banstr);
+      } else {
+       if (state->flags & MODE_PARSE_SET && MyUser(state->sptr) &&
+           (len > MAXBANLENGTH || count >= MAXBANS)) {
+         send_error_to_client(state->sptr, ERR_BANLISTFULL,
+                              state->chptr->chname, ban->value.ban.banstr);
+         count--;
+         len -= banlen;
+
+         MyFree(ban->value.ban.banstr);
+       } else {
+         /* add the ban to the buffer */
+         modebuf_mode_string(state->mbuf, MODE_ADD | MODE_BAN,
+                             ban->value.ban.banstr,
+                             !(state->flags & MODE_PARSE_SET));
+
+         if (state->flags & MODE_PARSE_SET) { /* create a new ban */
+           newban = make_link();
+           newban->value.ban.banstr = ban->value.ban.banstr;
+           DupString(newban->value.ban.who, ban->value.ban.who);
+           newban->value.ban.when = ban->value.ban.when;
+           newban->flags = ban->flags & (CHFL_BAN | CHFL_BAN_IPMASK);
+
+           newban->next = state->chptr->banlist; /* and link it in */
+           state->chptr->banlist = newban;
+
+           changed++;
+         }
+       }
       }
     }
 
-    prevban = ban; /* keep track of where we've been */
+    prevban = ban;
   } /* for (prevban = 0, ban = state->chptr->banlist; ban; ban = nextban) { */
 
   if (changed) /* if we changed the ban list, we must invalidate the bans */
index 248ab5184d4d28e420cac4c087f6211237e5ded0..c99d46ec0591a69f4f81f26bdb4b84255b50e16d 100644 (file)
@@ -168,7 +168,7 @@ do_clearmode(struct Client *cptr, struct Client *sptr, struct Channel *chptr,
    * the key until after modebuf_* are done with it
    */
   if (del_mode & MODE_KEY && *chptr->mode.key)
-    modebuf_mode_string(&mbuf, MODE_DEL | MODE_KEY, chptr->mode.key);
+    modebuf_mode_string(&mbuf, MODE_DEL | MODE_KEY, chptr->mode.key, 0);
 
   /* If we're removing the limit, note that and clear the limit */
   if (del_mode & MODE_LIMIT && chptr->mode.limit) {
@@ -180,9 +180,19 @@ do_clearmode(struct Client *cptr, struct Client *sptr, struct Channel *chptr,
    * Go through and mark the bans for deletion; note that we can't
    * free them until after modebuf_* are done with them
    */
-  if (del_mode & MODE_BAN)
-    for (link = chptr->banlist; link; link = link->next)
-      modebuf_mode_string(&mbuf, MODE_DEL | MODE_BAN, link->value.ban.banstr);
+  if (del_mode & MODE_BAN) {
+    for (link = chptr->banlist; link; link = next) {
+      next = link->next;
+
+      modebuf_mode_string(&mbuf, MODE_DEL | MODE_BAN, /* delete ban */
+                         link->value.ban.banstr, 1);
+
+      MyFree(link->value.ban.who); /* free up who string */
+      free_link(link); /* and of course the link itself */
+    }
+
+    chptr->banlist = 0;
+  }
 
   /* Deal with users on the channel */
   if (del_mode & (MODE_BAN | MODE_CHANOP | MODE_VOICE))
@@ -213,19 +223,6 @@ do_clearmode(struct Client *cptr, struct Client *sptr, struct Channel *chptr,
   if (del_mode & MODE_KEY)
     chptr->mode.key[0] = '\0';
 
-  /* and free the bans */
-  if (del_mode & MODE_BAN) {
-    for (link = chptr->banlist; link; link = next) {
-      next = link->next;
-
-      MyFree(link->value.ban.banstr);
-      MyFree(link->value.ban.who);
-      free_link(link);
-    }
-
-    chptr->banlist = 0;
-  }
-
   /* Don't propagate CLEARMODE if it's a local channel */
   if (IsLocalChannel(chptr->chname))
     return 0;