Fix SF bug #2721107 (Gline lifetime changes from servers change the reason.)
[ircu2.10.12-pk.git] / ircd / m_gline.c
index cf0f002b57983b519abe741b330a45d46e7129d7..549ae140db667df9ebac742cc6efb0ec0ec25635 100644 (file)
@@ -1,4 +1,4 @@
-/*
+\/*
  * IRC - Internet Relay Chat, ircd/m_gline.c
  * Copyright (C) 1990 Jarkko Oikarinen and
  *                    University of Oulu, Computing Center
@@ -279,6 +279,7 @@ ms_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   case GLINE_LOCAL_DEACTIVATE: /* locally deactivating a G-line */
     if (!agline) /* no G-line to locally activate or deactivate? */
       return send_reply(sptr, ERR_NOSUCHGLINE, mask);
+    lastmod = agline->gl_lastmod;
     break; /* no additional parameters to manipulate */
 
   case GLINE_ACTIVATE: /* activating a G-line */
@@ -292,9 +293,6 @@ ms_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   case GLINE_MODIFY: /* modifying a G-line */
     /* convert expire and lastmod, look for lifetime and reason */
     if (parc > 4) { /* protect against fall-through from 4-param form */
-      if (parc < 5)
-       return need_more_params(sptr, "GLINE");
-
       expire = atoi(parv[3]); /* convert expiration and lastmod */
       expire = abs_expire(expire);
       lastmod = atoi(parv[4]);
@@ -310,7 +308,7 @@ ms_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
        if (!agline || /* gline creation, has to be the reason */
            /* trial-convert as lifetime, and if it doesn't fully convert,
             * it must be the reason */
-           ((lifetime = strtoul(parv[5], &tmp, 10)) && !*tmp)) {
+           (!(lifetime = strtoul(parv[5], &tmp, 10)) && !*tmp)) {
          lifetime = 0;
          reason = parv[5];
 
@@ -350,6 +348,18 @@ ms_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   assert(action != GLINE_LOCAL_DEACTIVATE);
   assert(action != GLINE_MODIFY);
 
+  if (!expire) { /* Cannot *add* a G-line we don't have, but try hard */
+    Debug((DEBUG_DEBUG, "Propagating G-line %s for G-line we don't have",
+          action == GLINE_ACTIVATE ? "activation" : "deactivation"));
+
+    /* propagate the G-line, even though we don't have it */
+    sendcmdto_serv_butone(sptr, CMD_GLINE, cptr, "* %c%s %Tu",
+                         action == GLINE_ACTIVATE ? '+' : '-',
+                         mask, lastmod);
+
+    return 0;
+  }
+
   return gline_add(cptr, sptr, mask, reason, expire, lastmod, lifetime,
                   flags | ((action == GLINE_ACTIVATE) ? GLINE_ACTIVE : 0));
 }
@@ -370,7 +380,7 @@ mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
   unsigned int flags = 0;
   enum GlineAction action = GLINE_MODIFY;
   time_t expire = 0;
-  char *mask = parv[1], *target = 0, *reason = 0;
+  char *mask = parv[1], *target = 0, *reason = 0, *end;
 
   if (parc < 2)
     return gline_list(sptr, 0);
@@ -413,12 +423,14 @@ mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
       return need_more_params(sptr, "GLINE");
 
     target = parv[2]; /* get the target... */
-    expire = atoi(parv[3]) + CurrentTime; /* and the expiration */
+    expire = strtol(parv[3], &end, 10) + CurrentTime; /* and the expiration */
+    if (*end != '\0')
+      return send_reply(sptr, SND_EXPLICIT | ERR_BADEXPIRE, "%s :Bad expire time", parv[3]);
 
     flags |= GLINE_EXPIRE; /* remember that we got an expire time */
 
     if (parc > 4) { /* also got a reason... */
-      reason = parv[4];
+      reason = parv[parc - 1];
       flags |= GLINE_REASON;
     }
 
@@ -433,8 +445,11 @@ mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
 
   case GLINE_LOCAL_ACTIVATE: /* locally activate a G-line */
   case GLINE_LOCAL_DEACTIVATE: /* locally deactivate a G-line */
-    if (parc > 2) /* if target is available, pick it */
+    if (parc > 2) /* if target is available, pick it */
       target = parv[2];
+      if (target[0] == '*' && target[1] == '\0')
+        return send_reply(sptr, ERR_NOSUCHSERVER, target);
+    }
     break;
 
   case GLINE_ACTIVATE: /* activating/adding a G-line */
@@ -444,8 +459,10 @@ mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
 
     if (parc > 3) {
       /* get expiration and target */
-      expire = atoi(parv[parc - 2]) + CurrentTime;
       reason = parv[parc - 1];
+      expire = strtol(parv[parc - 2], &end, 10) + CurrentTime;
+      if (*end != '\0')
+        return send_reply(sptr, SND_EXPLICIT | ERR_BADEXPIRE, "%s :Bad expire time", parv[parc - 2]);
 
       flags |= GLINE_EXPIRE | GLINE_REASON; /* remember that we got 'em */
 
@@ -490,8 +507,8 @@ mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
           action == GLINE_LOCAL_ACTIVATE ? '>' : '<'));
 
     sendcmdto_one(sptr, CMD_GLINE, acptr, "%C %s%c%s", acptr,
-                 flags & GLINE_OPERFORCE ? "!" : "",
-                 action == GLINE_LOCAL_ACTIVATE ? '>' : '<', mask);
+                  flags & GLINE_OPERFORCE ? "!" : "",
+                  action == GLINE_LOCAL_ACTIVATE ? '>' : '<', mask);
 
     return 0; /* all done */
   }
@@ -573,10 +590,12 @@ mo_gline(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
     }
   }
 
-  /* can't modify a G-line that doesn't exist... */
+  /* can't modify a G-line that doesn't exist...
+   * (and if we are creating a new one, we need a reason and expiration)
+   */
   if (!agline &&
       (action == GLINE_MODIFY || action == GLINE_LOCAL_ACTIVATE ||
-       action == GLINE_LOCAL_DEACTIVATE))
+       action == GLINE_LOCAL_DEACTIVATE || !reason || !expire))
     return send_reply(sptr, ERR_NOSUCHGLINE, mask);
 
   /* check for G-line permissions... */