Explorar el Código

* Bring over bantype patch from eggdrop submitted patch

This patch provides customizable host masking, compatible and extending
mIRC's mask types. Users will be able to make use of this trough a new
channel setting "ban-type".
-Rumen Stoyanov
Rumen Stoyanov (Ported by Bryan) hace 17 años
padre
commit
7b83e9d675
Se han modificado 3 ficheros con 135 adiciones y 89 borrados
  1. 17 0
      doc/help.txt
  2. 115 88
      src/misc.c
  3. 3 1
      src/misc.h

+ 17 - 0
doc/help.txt

@@ -380,6 +380,23 @@ See also: link
         $bban-time$b          Set here how long temporary bans will last (in
                           minutes). If you set this setting to 0, the bot will
                           never remove them. (This also requires +dynamicbans)
+        $bban-type$b
+                              This setting defines what type of bans should be
+                          placed. Available types are:
+                              0 *!user@host
+                              1 *!*user@host
+                              2 *!*@host
+                              3 *!*user@*.host
+                              4 *!*@*.host
+                              5 nick!user@host
+                              6 nick!*user@host
+                              7 nick!*@host
+                              8 nick!*user@*.host
+                              9 nick!*@*.host
+                          You can also specify types from 10 to 19 which correspond
+                          to types 0 to 9, with the exception that numbers in hostnames
+                          are replaced with the '?' wildcard, or 20 to 29, which works
+                          like 10 to 19 but using '*' for numbers, instead of '?'.
         $bexempt-time$b       Set here how long temporary exempts will last (in
                           minutes). If you set this setting to 0, the bot will
                           never remove them. The bot will check the exempts

+ 115 - 88
src/misc.c

@@ -197,102 +197,129 @@ char *newsplit(char **rest)
   return r;
 }
 
-/* Convert "abc!user@a.b.host" into "*!user@*.b.host"
- * or "abc!user@1.2.3.4" into "*!user@1.2.3.*"
- * or "abc!user@0:0:0:0:0:ffff:1.2.3.4" into "*!user@0:0:0:0:0:ffff:1.2.3.*"
- * or "abc!user@3ffe:604:2:b02e:6174:7265:6964:6573" into
- *    "*!user@3ffe:604:2:b02e:6174:7265:6964:*"
+/* maskhost(), modified to support custom mask types, as defined
+ * by mIRC.
+ * Does not require a proper hostmask in 's'. Accepts any strings,
+ * including empty ones and attempts to provide meaningful results.
+ *
+ * Strings containing no '@' character will be parsed as if the
+ * whole string is a host.
+ * Strings containing no '!' character will be interpreted as if
+ * there is no nick.
+ * '!' as a nick/user separator must precede any '@' characters.
+ * Otherwise it will be considered a part of the host.
+ * Supported types are listed in tcl-commands.doc in the maskhost
+ * command section. Type 3 resembles the older maskhost() most closely.
+ *
+ * Specific examples (with type=3):
+ *
+ * "nick!user@is.the.lamest.bg"  -> *!*user@*.the.lamest.bg (ccTLD)
+ * "nick!user@is.the.lamest.com" -> *!*user@*.lamest.com (gTLD)
+ * "lamest.example"              -> *!*@lamest.example
+ * "whatever@lamest.example"     -> *!*whatever@lamest.example
+ * "com.example@user!nick"       -> *!*com.example@user!nick
+ * "!"                           -> *!*@!
+ * "@"                           -> *!*@*
+ * ""                            -> *!*@*
+ * "abc!user@2001:db8:618:5c0:263:15:dead:babe"
+ * -> *!*user@2001:db8:618:5c0:263:15:dead:*
+ * "abc!user@0:0:0:0:0:ffff:1.2.3.4"
+ * -> *!*user@0:0:0:0:0:ffff:1.2.3.*
  */
-void maskhost(const char *s, char *nw)
+void maskaddr(const char *s, char *nw, int type)
 {
-  register const char *p, *q, *e, *f;
-  int i;
+  int d = type % 5, num = 1;
+  register char *p, *u = 0, *h = 0, *ss;
+
+  /* Look for user and host.. */
+  ss = (char *)s;
+  u = strchr(s, '!');
+  if (u)
+    h = strchr(u, '@');
+  if (!h){
+    h = strchr(s, '@');
+    u = 0;
+  }
 
-  *nw++ = '*';
+  /* Print nick if required and available */
+  if (!u || (type % 10) < 5)
+    *nw++ = '*';
+  else {
+    strncpy(nw, s, u - s);
+    nw += u - s;
+  }
   *nw++ = '!';
-  p = (q = strchr(s, '!')) ? q + 1 : s;
-  /* Strip of any nick, if a username is found, use last 8 chars */
-  if ((q = strchr(p, '@'))) {
-    int fl = 0;
-
-    if ((q - p) > 9) {
-      nw[0] = '*';
-      p = q - 7;
-      i = 1;
-    } else
-      i = 0;
-    while (*p != '@') {
-      if (!fl && strchr("~+-^=", *p))
-       nw[i] = '?';
-      else
-        nw[i] = *p;
-      fl++;
-      p++;
-      i++;
+
+  /* Write user if required and available */
+  u = (u ? u + 1 : ss);
+  if (!h || (d == 2) || (d == 4))
+    *nw++ = '*';
+  else {
+    if (d) {
+      *nw++ = '*';
+      if (strchr("~+-^=", *u))
+        u++; /* trim leading crap */
     }
-    nw[i++] = '@';
-    q++;
-  } else {
-    nw[0] = '*';
-    nw[1] = '@';
-    i = 2;
-    q = s;
+    strncpy(nw, u, h - u);
+    nw += h - u;
   }
-  nw += i;
-  e = NULL;
-  /* Now q points to the hostname, i point to where to put the mask */
-  if ((!(p = strchr(q, '.')) || !(e = strchr(p + 1, '.'))) && !strchr(q, ':'))
-    /* TLD or 2 part host */
-    strcpy(nw, q);
-  else {
-    if (e == NULL) {		/* IPv6 address?		*/
-      const char *mask_str;
-
-      f = strrchr(q, ':');
-      if (strchr(f, '.')) {	/* IPv4 wrapped in an IPv6?	*/
-	f = strrchr(f, '.');
-	mask_str = ".*";
-      } else 			/* ... no, true IPv6.		*/
-	mask_str = ":*";
-      strncpy(nw, q, f - q);
-      /* No need to nw[f-q] = 0 here, as the strcpy below will
-       * terminate the string for us.
-       */
-      nw += (f - q);
-      strcpy(nw, mask_str);
-    } else {
-      for (f = e; *f; f++)
-        ;
-      f--;
-      if (*f >= '0' && *f <= '9') {	/* Numeric IP address */
-	while (*f != '.')
-	  f--;
-	strncpy(nw, q, f - q);
-	/* No need to nw[f-q] = 0 here, as the strcpy below will
-	 * terminate the string for us.
-	 */
-	nw += (f - q);
-	strcpy(nw, ".*");
-      } else {				/* Normal host >= 3 parts */
-	/*    a.b.c  -> *.b.c
-	 *    a.b.c.d ->  *.b.c.d if tld is a country (2 chars)
-	 *             OR   *.c.d if tld is com/edu/etc (3 chars)
-	 *    a.b.c.d.e -> *.c.d.e   etc
-	 */
-	const char *x = strchr(e + 1, '.');
-
-	if (!x)
-	  x = p;
-	else if (strchr(x + 1, '.'))
-	  x = e;
-	else if (strlen(x) == 3)
-	  x = p;
-	else
-	  x = e;
-	simple_sprintf(nw, "*%s", x);
+  *nw++ = '@';
+
+  /* The rest is for the host */
+  h = (h ? h + 1 : ss);
+  for (p = h; *p; p++) /* hostname? */
+    if ((*p > '9' || *p < '0') && *p != '.') {
+      num = 0;
+      break;
+    }
+  p = strrchr(h, ':'); /* IPv6? */
+  /* Mask out after the last colon/dot */
+  if (p && d > 2) {
+    if ((u = strrchr(p, '.')))
+      p = u;
+    strncpy(nw, h, ++p - h);
+    nw += p - h;
+    strcpy(nw, "*");
+  } else if (!p && !num && type >= 10) {
+      /* we have a hostname and type
+       requires us to replace numbers */
+    num = 0;
+    for (p = h; *p; p++) {
+      if (*p < '0' || *p > '9') {
+        *nw++ = *p;
+        num = 0;
+      } else {
+        if (type < 20)
+          *nw++ = '?';
+        else if (!num) {
+          *nw++ = '*';
+          num = 1; /* place only one '*'
+                      per numeric sequence */
+        }
       }
     }
-  }
+    *nw = 0;
+  } else if (d > 2 && (p = strrchr(h, '.'))) {
+    if (num) { /* IPv4 */
+      strncpy(nw, h, p - h);
+      nw += p - h;
+      strcpy(nw, ".*");
+      return;
+    }
+    for (u = h, d = 0; (u = strchr(++u, '.')); d++) ;
+    if (d < 2) { /* types < 2 don't mask the host */
+      strcpy(nw, h);
+      return;
+    }
+    u = strchr(h, '.');
+    if (d > 3 || (d == 3 && strlen(p) > 3))
+      u = strchr(++u, '.'); /* ccTLD or not? Look above. */
+    simple_sprintf(nw, "*%s", u);
+  } else if (!*h) {
+    /* take care if the mask is empty or contains only '@' */
+    strcpy(nw, "*");
+  } else
+    strcpy(nw, h);
 }
 
 

+ 3 - 1
src/misc.h

@@ -25,7 +25,9 @@ int bot_aggressive_to(struct userrec *);
 void readsocks(const char *);
 int updatebin(int, char *, int);
 size_t my_strcpy(char *, const char *);
-void maskhost(const char *, char *);
+void maskaddr(const char *, char *, int);
+#define maskhost(a,b) maskaddr((a),(b),3)
+#define maskban(a,b)  maskaddr((a),(b),3)
 char *stristr(char *, char *);
 void splitc(char *, char *, char);
 void splitcn(char *, char *, char, size_t);