]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/tools.c
This should fix the nickserv module complaining about not enough parameters when...
[irc/evilnet/x3.git] / src / tools.c
index 291150878947406b44e73445df478bab13da437a..a46ed50d000bc63954b84841a3321a905e066ea1 100644 (file)
@@ -1,7 +1,7 @@
 /* tools.c - miscellaneous utility functions
  * Copyright 2000-2004 srvx Development Team
  *
- * This file is part of srvx.
+ * This file is part of x3.
  *
  * srvx is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -245,68 +245,69 @@ int mmatch(const char *old_mask, const char *new_mask)
 int
 match_ircglob(const char *text, const char *glob)
 {
-    unsigned int star_p, q_cnt;
-    while (1) {
-       switch (*glob) {
-       case 0:
-           return !*text;
-        case '\\':
-            glob++;
-            /* intentionally not tolower(...) so people can force
-             * capitalization, or we can overload \ in the future */
-            if (*text++ != *glob++)
-                return 0;
-            break;
-       case '*':
-        case '?':
-            star_p = q_cnt = 0;
-            do {
-                if (*glob == '*')
-                    star_p = 1;
-                else if (*glob == '?')
-                    q_cnt++;
-                else
-                    break;
-                glob++;
-            } while (1);
-            while (q_cnt) {
-                if (!*text++)
-                    return 0;
-                q_cnt--;
-            }
-            if (star_p) {
-                /* if this is the last glob character, it will match any text */
-                if (!*glob)
-                    return 1;
-                /* Thanks to the loop above, we know that the next
-                 * character is a normal character.  So just look for
-                 * the right character.
-                 */
-                for (; *text; text++) {
-                    if ((tolower(*text) == tolower(*glob))
-                        && match_ircglob(text+1, glob+1)) {
-                        return 1;
-                    }
-                }
-                return 0;
-            }
-            /* if !star_p, fall through to normal character case,
-             * first checking to see if ?s carried us to the end */
-            if (!*glob && !*text)
+    const char *m = glob, *n = text;
+    const char *m_tmp = glob, *n_tmp = text;
+    int star_p;
+
+    for (;;) switch (*m) {
+    case '\0':
+        if (!*n)
+            return 1;
+    backtrack:
+        if (m_tmp == glob)
+            return 0;
+        m = m_tmp;
+        n = ++n_tmp;
+        break;
+    case '\\':
+        m++;
+        /* allow escaping to force capitalization */
+        if (*m++ != *n++)
+            return 0;
+        break;
+    case '*': case '?':
+        for (star_p = 0; ; m++) {
+            if (*m == '*')
+                star_p = 1;
+            else if (*m == '?') {
+                if (!*n++)
+                    goto backtrack;
+            } else break;
+        }
+        if (star_p) {
+            if (!*m)
                 return 1;
-       default:
-           if (!*text)
-                return 0;
-           while (*text && *glob && *glob != '*' && *glob != '?' && *glob != '\\') {
-               if (tolower(*text++) != tolower(*glob++))
+            else if (*m == '\\') {
+                m_tmp = ++m;
+                if (!*m)
                     return 0;
-           }
-       }
+                for (n_tmp = n; *n && *n != *m; n++) ;
+            } else {
+                m_tmp = m;
+                for (n_tmp = n; *n && tolower(*n) != tolower(*m); n++) ;
+            }
+        }
+        /* and fall through */
+    default:
+        if (!*n)
+            return *m == '\0';
+        if (tolower(*m) != tolower(*n))
+            goto backtrack;
+        m++;
+        n++;
+        break;
     }
 }
 
 extern const char *hidden_host_suffix;
 
+/* Prevent *@* *@** *@*a* type masks, while allowing anything else. This is the best way iv found to detect 
+ * a global matching mask; if it matches this string, it'll match almost anything :) */
+int is_overmask(char *mask)
+{
+    return(match_ircglob("abcdefghijklmnopqrstuv!frcmbghilnrtoasde@apdic.yfa.dsfsdaffsdasfdasfd.abcdefghijklmnopqrstuvwxyz.asdfasfdfsdsfdasfda.ydfbe", mask));
+}
+
 int user_matches_glob(struct userNode *user, const char *orig_glob, int include_nick)
 {
     /* A new glob function, the old one had many false positives.
@@ -418,24 +419,24 @@ user_matches_glob_broken(struct userNode *user, const char *orig_glob, int inclu
     if (!match_ircglob(user->ident, glob) && (IsSetHost(user) && !match_ircglob(setident, glob)))
        return 0;
     glob = marker + 1;
-    /* Now check the host part */
-    if (isdigit(*glob) && !glob[strspn(glob, "0123456789./*?")]) {
-        /* Looks like an IP-based mask */
-        return match_ircglob(inet_ntoa(user->ip), glob);
-    } else {
-        /* The host part of the mask isn't IP-based */
-        if (IsSetHost(user) && match_ircglob(sethostname, glob))
+    /* If it might be an IP glob, test that. */
+    if (!glob[strspn(glob, "0123456789./*?")]
+        && match_ircglob(inet_ntoa(user->ip), glob))
+        return 1;
+    /* Check for a fakehost match. */
+    if (IsFakeHost(user) && match_ircglob(user->fakehost, glob))
+        return 1;
+    if (IsSetHost(user) && match_ircglob(sethostname, glob))
+        return 1;
+    /* Check for an account match. */
+    if (hidden_host_suffix && user->handle_info) {
+        char hidden_host[HOSTLEN+1];
+        snprintf(hidden_host, sizeof(hidden_host), "%s.%s", user->handle_info->handle, hidden_host_suffix);
+        if (match_ircglob(hidden_host, glob))
             return 1;
-        if (IsFakeHost(user) && match_ircglob(user->fakehost, glob))
-            return 1;
-        if (hidden_host_suffix && user->handle_info) {
-            char hidden_host[HOSTLEN+1];
-            snprintf(hidden_host, sizeof(hidden_host), "%s.%s", user->handle_info->handle, hidden_host_suffix);
-            if (match_ircglob(hidden_host, glob))
-                return 1;
-        }
-        return match_ircglob(user->hostname, glob);
     }
+    /* None of the above; could only be a hostname match. */
+    return match_ircglob(user->hostname, glob);
 }
 
 int
@@ -464,7 +465,22 @@ is_gline(const char *text)
         return 0;
     if (!*text)
         return 0;
-    while (*text && (isalnum((char)*text) || strchr(".-?*", *text)))
+    while (*text && (isalnum((char)*text) || strchr(".-?*:", *text)))
+        text++;
+    return !*text;
+}
+
+int
+is_shun(const char *text)
+{
+    if (*text == '@')
+        return 0;
+    text += strcspn(text, "@!% \t\r\n");
+    if (*text++ != '@')
+        return 0;
+    if (!*text)
+        return 0;
+    while (*text && (isalnum((char)*text) || strchr(".-?*:", *text)))
         text++;
     return !*text;
 }
@@ -493,7 +509,7 @@ split_ircmask(char *text, char **nick, char **ident, char **host)
         *ident = start;
     
     start = ++text;
-    while (*text && (isalnum((char)*text) || strchr(".-?*", *text)))
+    while (*text && (isalnum((char)*text) || strchr(".-?*:", *text)))
         text++;
     if (host)
         *host = start;
@@ -588,7 +604,7 @@ TypeLength(char type)
 {
     switch (type) {
     case 'y': return 365*24*60*60;
-    case 'M': return 31*24*60*60;
+    case 'M': return 30*24*60*60;
     case 'w': return 7*24*60*60;
     case 'd': return 24*60*60;
     case 'h': return 60*60;
@@ -598,6 +614,10 @@ TypeLength(char type)
     }
 }
 
+/* This function is not entirely accurate as it does not take into account leap units
+ * or varying months. TODO: use proper dateadd functions to calculate real seconds
+ * from now for the units (eg 1M should be give us seconds till todays date next month)
+ */
 unsigned long
 ParseInterval(const char *interval)
 {
@@ -767,13 +787,13 @@ intervalString(char *output, time_t interval, struct handle_info *hi)
 
         if (words++ == 1) {
             msg = language_find_message(lang, "MSG_AND");
-            pos += sprintf(output + pos, " %s ", msg);
+            pos += sprintf(output + pos, "%s ", msg);
         }
         if (count == 1)
             msg = language_find_message(lang, unit[type].msg_single);
         else
             msg = language_find_message(lang, unit[type].msg_plural);
-        pos += sprintf(output + pos, "%d %s", count, msg);
+        pos += sprintf(output + pos, "%d%s", count, msg);
     }
 
     output[pos] = 0;
@@ -935,7 +955,7 @@ tools_cleanup(void)
  * multiple dilimiters, which can really
  * offset tokens and cause huge corruption
  * so this function will use strsep but
- * act like strtok in that sence.
+ * act like strtok in that sense.
  */
 char *mysep(char **sepstr, char *delim)
 {
@@ -962,3 +982,49 @@ char *time2str(time_t thetime)
     return(buf);
 }
 
+char* x3_strtok(char **save, char *str, char *fs)
+{
+  char *pos = *save;            /* keep last position across calls */
+  char *tmp;
+
+  if (str)
+    pos = str;                  /* new string scan */
+
+  while (pos && *pos && strchr(fs, *pos) != NULL)
+    pos++;                      /* skip leading separators */
+
+  if (!pos || !*pos)
+    return (pos = *save = NULL);        /* string contains only sep's */
+
+  tmp = pos;                    /* now, keep position of the token */
+
+  while (*pos && strchr(fs, *pos) == NULL)
+    pos++;                      /* skip content of the token */
+
+  if (*pos)
+    *pos++ = '\0';              /* remove first sep after the token */
+  else
+    pos = NULL;                 /* end of string */
+
+  *save = pos;
+  return (tmp);
+}
+
+int valid_email(const char *email)
+{
+    unsigned int i;
+    for (i=0;i<strlen(email);i++)
+    {
+        if(!isalnum(email[i]) &&
+               email[i] != '.' &&
+               email[i] != '@' &&
+               email[i] != '-' &&
+               email[i] != '+' &&
+               email[i] != '_' )
+            return false;
+    }
+    if(strchr(email, '@') == NULL)
+        return false;
+    return true;
+}
+