]> jfr.im git - irc/quakenet/newserv.git/blobdiff - newsearch/ns-gline.c
CHANSERV: fix issue where chanserv_relay doesn't wait for db to be loaded before...
[irc/quakenet/newserv.git] / newsearch / ns-gline.c
index 8735dc6bfb8bd0f557499da63ae3e05994e33a8c..f366fd33f022be2ec98fa7b491d261f7db2a63be 100644 (file)
@@ -7,11 +7,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdint.h>
 
 #include "../control/control.h"
 #include "../irc/irc.h" /* irc_send() */
 #include "../lib/irc_string.h" /* IPtostr(), longtoduration(), durationtolong() */
 #include "../lib/strlfunc.h"
+#include "../glines/glines.h"
 
 /* used for *_free functions that need to warn users of certain things
    i.e. hitting too many users in a (kill) or (gline) - declared in newsearch.c */
@@ -31,69 +33,83 @@ struct gline_localdata {
 struct searchNode *gline_parse(searchCtx *ctx, int argc, char **argv) {
   struct gline_localdata *localdata;
   struct searchNode *thenode;
-  int len;
-  char *p;
 
   if (!(localdata = (struct gline_localdata *) malloc(sizeof(struct gline_localdata)))) {
     parseError = "malloc: could not allocate memory for this search.";
     return NULL;
   }
   localdata->count = 0;
-  if (ctx->type == SEARCHTYPE_CHANNEL)
+  if (ctx->searchcmd == reg_chansearch)
     localdata->marker = nextchanmarker();
-  else
+  else if (ctx->searchcmd == reg_nicksearch)
     localdata->marker = nextnickmarker();
+  else if (ctx->searchcmd == reg_whowassearch)
+    localdata->marker = nextwhowasmarker();
+  else {
+    free(localdata);
+    parseError = "gline: invalid search type";
+    return NULL;
+  }
 
-  switch (argc) {
-  case 0:
+  /* default duration, default reason */
+  if(argc == 0) {
     localdata->duration = NSGLINE_DURATION;
     strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason));
-    break;
-
-  case 1:
-    if (strchr(argv[0], ' ') == NULL) { /* duration specified */
-      localdata->duration = durationtolong(argv[0]);
-      /* error checking on gline duration */
-      if (localdata->duration == 0)
-        localdata->duration = NSGLINE_DURATION;
-      strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason));
+  } else if(argc > 2) {
+    free(localdata);
+    parseError = "gline: invalid number of arguments";
+    return NULL;
+  } else {
+    char *argzerop, *reasonp, *durationp;
+    struct searchNode *durationsn, *reasonsn, *argzerosn;
+    
+    if (!(argzerosn=argtoconststr("gline", ctx, argv[0], &argzerop))) {
+      free(localdata);
+      return NULL;
     }
-    else { /* reason specified */
-      localdata->duration = NSGLINE_DURATION;
 
-      p = argv[0];
-      if(*p == '\"')
-        p++;
-      len = strlcpy(localdata->reason, p, sizeof(localdata->reason));
-      if(len >= sizeof(localdata->reason)) {
-        localdata->reason[sizeof(localdata->reason)-1] = '\0';
+    if(argc == 1) {
+      durationp = reasonp = NULL;
+      durationsn = reasonsn = NULL;
+      
+      /* if we have a space it's a reason */
+      if(strchr(argzerop, ' ')) {
+        reasonsn = argzerosn;
+        reasonp = argzerop;
       } else {
-        localdata->reason[len-1] = '\0';
+        durationsn = argzerosn;
+        durationp = argzerop;
       }
+    } else {
+      durationsn = argzerosn;
+      durationp = argzerop;
+      
+      if (!(reasonsn=argtoconststr("gline", ctx, argv[1], &reasonp))) {
+        durationsn->free(ctx, durationsn);
+        free(localdata);
+        return NULL;
+      }      
+    }
+    
+    if(!reasonp) {
+      strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason));
+    } else {
+      strlcpy(localdata->reason, reasonp, sizeof(localdata->reason));
+      reasonsn->free(ctx, reasonsn);
     }
-    break;
 
-  case 2:
-    localdata->duration = durationtolong(argv[0]);
-    /* error checking on gline duration */
-    if (localdata->duration == 0)
+    if(!durationp) {
       localdata->duration = NSGLINE_DURATION;
-
-    p = argv[1];
-    if(*p == '\"')
-      p++;
-    len = strlcpy(localdata->reason, p, sizeof(localdata->reason));
-    if(len >= sizeof(localdata->reason)) {
-      localdata->reason[sizeof(localdata->reason)-1] = '\0';
     } else {
-      localdata->reason[len-1] = '\0';
+      localdata->duration = durationtolong(durationp);
+      durationsn->free(ctx, durationsn);
+      
+      if (localdata->duration == 0) {
+        parseError = "gline duration invalid.";
+        free(localdata);
+        return NULL;
+      }
     }
-
-    break;
-  default:
-    free(localdata);
-    parseError = "gline: invalid number of arguments";
-    return NULL;
   }
 
   if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
@@ -115,30 +131,49 @@ void *gline_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
   struct gline_localdata *localdata;
   nick *np;
   chanindex *cip;
+  whowas *ww;
 
   localdata = thenode->localdata;
 
-  if (ctx->type == SEARCHTYPE_CHANNEL) {
+  if (ctx->searchcmd == reg_chansearch) {
     cip = (chanindex *)theinput;
     cip->marker = localdata->marker;
-    localdata->count += cip->channel->users->totalusers;
+    if (cip->channel != NULL)
+      localdata->count += cip->channel->users->totalusers;
   }
   else {
     np = (nick *)theinput;
-    np->marker = localdata->marker;
+    if (ctx->searchcmd == reg_nicksearch)
+      np->marker = localdata->marker;
+    else {
+      ww = (whowas *)np->next;
+      ww->marker = localdata->marker;
+    }
     localdata->count++;
   }
 
   return (void *)1;
 }
 
+static int glineuser(glinebuf *gbuf, nick *np, struct gline_localdata *localdata, time_t ti) {
+  char msgbuf[512];
+  if (!IsOper(np) && !IsService(np) && !IsXOper(np)) {
+    nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np);
+    glinebufaddbynick(gbuf, np, 0, "newsearch", msgbuf, getnettime() + localdata->duration, getnettime(), getnettime() + localdata->duration);
+    return 1;
+  }
+  
+  return 0;
+}
+
 void gline_free(searchCtx *ctx, struct searchNode *thenode) {
   struct gline_localdata *localdata;
   nick *np, *nnp;
   chanindex *cip, *ncip;
-  int i, j, safe=0;
-  char msgbuf[512];
+  whowas *ww;
+  int i, j, hits, safe=0;
   time_t ti = time(NULL);
+  glinebuf gbuf;
 
   localdata = thenode->localdata;
 
@@ -150,7 +185,9 @@ void gline_free(searchCtx *ctx, struct searchNode *thenode) {
     return;
   }
 
-  if (ctx->type == SEARCHTYPE_CHANNEL) {
+  glinebufinit(&gbuf, 0);
+
+  if (ctx->searchcmd == reg_chansearch) {
     for (i=0;i<CHANNELHASHSIZE;i++) {
       for (cip=chantable[i];cip;cip=ncip) {
         ncip = cip->next;
@@ -160,44 +197,45 @@ void gline_free(searchCtx *ctx, struct searchNode *thenode) {
               continue;
     
             if ((np=getnickbynumeric(cip->channel->users->content[j]))) {
-              if (!IsOper(np) && !IsService(np) && !IsXOper(np)) {
-                nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np);
-                if (np->host->clonecount <= NSMAX_GLINE_CLONES)
-                  irc_send("%s GL * +*@%s %u %d :%s", mynumeric->content, IPtostr(np->p_ipaddr), localdata->duration, ti, msgbuf);
-                else
-                  irc_send("%s GL * +%s@%s %u %d :%s", mynumeric->content, np->ident, IPtostr(np->p_ipaddr), localdata->duration, ti, msgbuf);
-              }
-              else
+              if(!glineuser(&gbuf, np, localdata, ti))
                 safe++;
             }
           }
         }
       }
     }
-  }
-  else {
+  } else if (ctx->searchcmd == reg_nicksearch) {
     for (i=0;i<NICKHASHSIZE;i++) {
       for (np=nicktable[i];np;np=nnp) {
         nnp = np->next;
         if (np->marker == localdata->marker) {
-          if (!IsOper(np) && !IsService(np) && !IsXOper(np)) {
-            nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np);
-            if (np->host->clonecount <= NSMAX_GLINE_CLONES)
-              irc_send("%s GL * +*@%s %u %d :%s", mynumeric->content, IPtostr(np->p_ipaddr), localdata->duration, ti, msgbuf);
-            else
-              irc_send("%s GL * +%s@%s %u %d :%s", mynumeric->content, np->ident, IPtostr(np->p_ipaddr), localdata->duration, ti, msgbuf);
-          }
-          else
-              safe++;
+          if(!glineuser(&gbuf, np, localdata, ti))
+            safe++;
         }
       }
     }
+  } else {
+    for (i = whowasoffset; i < whowasoffset + WW_MAXENTRIES; i++) {
+      ww = &whowasrecs[i % WW_MAXENTRIES];
+
+      if (ww->type == WHOWAS_UNUSED)
+        continue;
+
+      if (ww->marker == localdata->marker) {
+        if(!glineuser(&gbuf, &ww->nick, localdata, ti))
+          safe++;
+      }
+    }
   }
+
+  glinebufcounthits(&gbuf, &hits, NULL);
+  glinebufcommit(&gbuf, 1);
+
   if (safe)
     ctx->reply(senderNSExtern, "Warning: your pattern matched privileged users (%d in total) - these have not been touched.", safe);
   /* notify opers of the action */
   ctx->wall(NL_GLINES, "%s/%s glined %d %s via %s for %s [%d untouched].", senderNSExtern->nick, senderNSExtern->authname, (localdata->count - safe), 
-    (localdata->count - safe) != 1 ? "users" : "user", (ctx->type == SEARCHTYPE_CHANNEL) ? "chansearch" : "nicksearch", longtoduration(localdata->duration, 1), safe);
+    (localdata->count - safe) != 1 ? "users" : "user", (ctx->searchcmd == reg_chansearch) ? "chansearch" : "nicksearch", longtoduration(localdata->duration, 1), safe);
   free(localdata);
   free(thenode);
 }