]> jfr.im git - irc/quakenet/newserv.git/blobdiff - glines/glines_formats.c
Merge branch 'master' into chanserv-live
[irc/quakenet/newserv.git] / glines / glines_formats.c
index fdcd2f09e43b57588d9f505022a2e5d7bc048dcc..6a1649fc7dcc962cdd80f29df842926b764cb6a7 100644 (file)
@@ -9,15 +9,55 @@
 #include "../control/control.h"
 #include "glines.h"
 
+/** Find canonical user and host for a string.
+ * If \a userhost starts with '$', assign \a userhost to *user_p and NULL to *host_p.
+ * Otherwise, if \a userhost contains '@', assign the earlier part of it to *user_p and the rest to *host_p.
+ * Otherwise, assign \a def_user to *user_p and \a userhost to *host_p.
+ *
+ * @param[in] userhost Input string from user.
+ * @param[out] nick_p Gets pointer to nick part of hostmask.
+ * @param[out] user_p Gets pointer to user (or channel/realname) part of hostmask.
+ * @param[out] host_p Gets point to host part of hostmask (may be assigned NULL).
+ * @param[in] def_user Default value for user part.
+ */
+static void
+canon_userhost(char *userhost, char **nick_p, char **user_p, char **host_p, char *def_user) {
+  char *tmp, *s;
+
+  if (*userhost == '$') {
+    *user_p = userhost;
+    *host_p = NULL;
+    *nick_p = NULL;
+    return;
+  }
+
+  if ((tmp = strchr(userhost, '!'))) {
+    *nick_p = userhost;
+    *(tmp++) = '\0';
+  } else {
+    *nick_p = def_user;
+    tmp = userhost;
+  }
+
+  if (!(s = strchr(tmp, '@'))) {
+    *user_p = def_user;
+    *host_p = tmp;
+  } else {
+    *user_p = tmp;
+    *(s++) = '\0';
+    *host_p = s;
+  }
+}
+
 gline *makegline(const char *mask) {
   /* populate gl-> user,host,node,nick and set appropriate flags */
   gline *gl;
-  char nick[512], user[512], host[512];
-  const char *pnick = NULL, *puser = NULL, *phost = NULL;
+  char dupmask[512];
+  char *nick, *user, *host;
   const char *pos;
   int count;
 
-  /* Make sure there are no spaces in the mask, glstore_* depends on this */
+  /* Make sure there are no spaces in the mask */
   if (strchr(mask, ' ') != NULL)
     return NULL;
 
@@ -27,7 +67,7 @@ gline *makegline(const char *mask) {
     Error("gline", ERR_ERROR, "Failed to allocate new gline");
     return NULL;
   }
-
+  
   if (mask[0] == '#' || mask[0] == '&') {
     gl->flags |= GLINE_BADCHAN;
     gl->user = getsstring(mask, CHANNELLEN);
@@ -41,65 +81,42 @@ gline *makegline(const char *mask) {
     }
 
     gl->flags |= GLINE_REALNAME;
-    gl->user = getsstring(mask + 2, REALLEN);
-    return gl;
-  }
 
-  if (sscanf(mask, "%[^!]!%[^@]@%s", nick, user, host) == 3) {
-    pnick = nick;
-    puser = user;
-    phost = host;
-  } else if (sscanf(mask, "%[^@]@%s", user, host) == 2) {
-    puser = user;
-    phost = host;
-  } else {
-    phost = mask;
-  }
+    if (strcmp(mask + 2, "*") != 0)
+      gl->user = getsstring(mask + 2, REALLEN);
 
-  /* validate length of the mask components */
-  if ((pnick && (pnick[0] == '\0' || strlen(pnick) > NICKLEN)) ||
-      (puser && (puser[0] == '\0' || strlen(puser) > USERLEN)) ||
-      (phost && (phost[0] == '\0' || strlen(phost) > HOSTLEN))) {
-    freegline(gl);
-    return NULL;
+    return gl;
   }
 
-  /* ! and @ are not allowed in the mask components */
-  if ((pnick && (strchr(pnick, '!') || strchr(pnick, '@'))) ||
-      (puser && (strchr(puser, '!') || strchr(puser, '@'))) ||
-      (phost && (strchr(phost, '!') || strchr(phost, '@')))) {
-    freegline(gl);
-    return NULL;
-  }
+  strncpy(dupmask, mask, sizeof(dupmask));
+  canon_userhost(dupmask, &nick, &user, &host, "*");
 
-  if (phost && ipmask_parse(phost, &gl->ip, &gl->bits))
+  if (ipmask_parse(host, &gl->ip, &gl->bits))
     gl->flags |= GLINE_IPMASK;
   else
     gl->flags |= GLINE_HOSTMASK;
 
-  /* Don't allow invalid IPv6 bans as those match * on snircd 1.3.4 */
-  if (phost) {
-    count = 0;
+  /* Don't allow invalid IPv6 bans as those might match * on snircd 1.3.4 */
+  count = 0;
 
-    for (pos = phost; *pos; pos++)
-      if (*pos == ':')
-        count++;
+  for (pos = host; *pos; pos++)
+    if (*pos == ':')
+      count++;
 
-    if (count >= 8) {
-      controlwall(NO_OPER, NL_GLINES, "Warning: Parsed invalid IPv6 G-Line: %s", mask);
-      freegline(gl);
-      return NULL;
-    }
+  if (count >= 8) {
+    controlwall(NO_OPER, NL_GLINES_AUTO, "Warning: Parsed invalid IPv6 G-Line: %s", mask);
+    freegline(gl);
+    return NULL;
   }
 
-  if (pnick && strcmp(pnick, "*") != 0)
-    gl->nick = getsstring(pnick, NICKLEN);
+  if (strcmp(nick, "*") != 0)
+    gl->nick = getsstring(nick, 512);
 
-  if (puser && strcmp(puser, "*") != 0)
-    gl->user = getsstring(puser, USERLEN);
+  if (strcmp(user, "*") != 0)
+    gl->user = getsstring(user, 512);
 
-  if (phost && strcmp(phost, "*") != 0)
-    gl->host = getsstring(phost, HOSTLEN);
+  if (strcmp(host, "*") != 0)
+    gl->host = getsstring(host, 512);
 
   return gl;
 }
@@ -108,11 +125,7 @@ char *glinetostring(gline *gl) {
   static char mask[512]; /* check */
 
   if (gl->flags & GLINE_REALNAME) {
-   if (gl->user)
-     snprintf(mask, sizeof(mask), "$R%s", gl->user->content);
-   else
-     strncpy(mask, "$R*", sizeof(mask));
-
+   snprintf(mask, sizeof(mask), "$R%s", (gl->user) ? gl->user->content : "*");
    return mask;
   }