]> jfr.im git - irc/quakenet/newserv.git/blobdiff - chanserv/chanservuser.c
CHANSERV: more checks on lastchannelID / lastuserID
[irc/quakenet/newserv.git] / chanserv / chanservuser.c
index de27c8027eacc687db77fca7be26388a4dbd28e9..0428050082ac734a2cb7debc510c15c8ed498114 100644 (file)
@@ -40,7 +40,7 @@ void chanservreguser(void *arg) {
   csuser=getcopyconfigitem("chanserv","user","TheQBot",USERLEN);
   cshost=getcopyconfigitem("chanserv","host","some.host",HOSTLEN);
   csrealname=getcopyconfigitem("chanserv","realname","ChannelService",REALLEN);
-  csaccount=getcopyconfigitem("chanserv","account",csnick&&csnick->content&&csnick->content[0]?csnick->content:"Q",ACCOUNTLEN);
+  csaccount=getcopyconfigitem("chanserv","account",csnick&&csnick->content[0]?csnick->content:"Q",ACCOUNTLEN);
 
   Error("chanserv",ERR_INFO,"Connecting %s...",csnick->content);
 
@@ -111,6 +111,7 @@ void chanservuserhandler(nick *target, int message, void **params) {
       }
       cmd=findcommandintree(csctcpcommands, cargv[0]+1, 1);
       if (cmd) {
+       cmd->calls++;
        rejoinline(cargv[1],cargc-1);
        cmd->handler((void *)sender, cargc-1, &(cargv[1]));
       }      
@@ -173,12 +174,30 @@ void chanservuserhandler(nick *target, int message, void **params) {
        break;
       }
       
+      if ((cmd->level & QCMD_ACHIEVEMENTS) && !UIsDev(rup) &&
+          ((time(NULL) < ACHIEVEMENTS_START) || 
+           ((time(NULL) > ACHIEVEMENTS_END) && !UIsAchievements(rup)))) {
+        chanservstdmessage(sender, QM_UNKNOWNCMD, cargv[0]);
+        break;
+      } 
+    
+      if ((cmd->level & QCMD_TITLES) && !UIsDev(rup) &&
+          ((time(NULL) < ACHIEVEMENTS_START) ||
+           (time(NULL) > ACHIEVEMENTS_END))) {
+        chanservstdmessage(sender, QM_UNKNOWNCMD, cargv[0]);
+        break;
+      }
+      
+      cmd->calls++;
+      
       if (cmd->maxparams < (cargc-1)) {
        rejoinline(cargv[cmd->maxparams],cargc-(cmd->maxparams));
        cargc=(cmd->maxparams)+1;
       }
       
       cmd->handler((void *)sender, cargc-1, &(cargv[1]));
+      
+      triggerhook(HOOK_CHANSERV_CMD, sender);
     }
     break;
 
@@ -519,7 +538,7 @@ void chanservkillstdmessage(nick *target, int messageid, ... ) {
   va_start(va, messageid);
   q9vsnprintf(buf, 511, message, messageargs, va);
   va_end(va);
-  killuser(chanservnick, target, buf);
+  killuser(chanservnick, target, "%s", buf);
 }
 
 int checkpassword(reguser *rup, const char *pass) {
@@ -765,7 +784,15 @@ void cs_doallautomodes(nick *np) {
       if ((lp=getnumerichandlefromchanhash(rcup->chan->index->channel->users, np->numeric))) {
         /* User is on channel.. */
 
-        if (CUKnown(rcup) && rcup->chan->index->channel->users->totalusers >= 3) {
+        /* Update last use time.  Do early in case of ban. */
+        rcup->usetime=getnettime();
+        
+        if (CUIsBanned(rcup)) {
+          cs_banuser(NULL, rcup->chan->index, np, NULL);
+          continue;
+        }
+
+        if (CUHasOpPriv(rcup) && cs_ischannelactive(rcup->chan->index->channel, NULL)) {
           /* This meets the channel use criteria, update. */
           rcup->chan->lastactive=time(NULL);
           
@@ -776,9 +803,6 @@ void cs_doallautomodes(nick *np) {
           }
         }
 
-        /* Update last use time */
-        rcup->usetime=getnettime();
-
        localsetmodeinit(&changes, rcup->chan->index->channel, chanservnick);
        if (*lp & CUMODE_OP) {
          if (!IsService(np) && (CUIsDeny(rcup) || (CIsBitch(rcup->chan) && !CUHasOpPriv(rcup))))
@@ -803,11 +827,16 @@ void cs_doallautomodes(nick *np) {
       } else {
        /* Channel exists but user is not joined: invite if they are +j-b */
        if (CUIsAutoInvite(rcup) && CUKnown(rcup) && !CUIsBanned(rcup)) {
-         localinvite(chanservnick, rcup->chan->index->channel, np);
+         localinvite(chanservnick, rcup->chan->index, np);
        }
       }
-    }
-  }
+    } /* if (rcup->chan->index->channel) */ else {
+      /* Channel doesn't currently exist - send invite anyway for +j */
+      if (CUIsAutoInvite(rcup) && CUKnown(rcup) && !CUIsBanned(rcup)) {
+        localinvite(chanservnick, rcup->chan->index, np);
+      }
+    } 
+  } /* for */
 }
 
 void cs_checknickbans(nick *np) {
@@ -825,7 +854,7 @@ void cs_checknickbans(nick *np) {
 
   for (j=0;j<i;j++) {
     if ((rcp=ca[j]->index->exts[chanservext]) && !CIsSuspended(rcp) && 
-       CIsEnforce(rcp) && nickbanned_visible(np, ca[j]))
+       CIsEnforce(rcp) && nickbanned(np, ca[j], 1))
       localkickuser(chanservnick, ca[j], np, "Banned.");
   }
 
@@ -866,8 +895,8 @@ void cs_checkbans(channel *cp) {
 
     for (rbp=rcp->bans;rbp;rbp=rbp->next) {
       if (((!rbp->expiry) || (rbp->expiry <= now)) &&
-         nickmatchban_visible(np, rbp->cbp)) {
-       if (!nickbanned_visible(np, cp)) {
+         nickmatchban(np, rbp->cbp, 1)) {
+       if (!nickbanned(np, cp, 1)) {
          localdosetmode_ban(&changes, bantostring(rbp->cbp), MCB_ADD);
        }
        localkickuser(chanservnick,cp,np,rbp->reason?rbp->reason->content:"Banned.");
@@ -880,7 +909,7 @@ void cs_checkbans(channel *cp) {
 
     if (CIsEnforce(rcp)) {
       for (cbp=cp->bans;cbp;cbp=cbp->next) {
-       if ((cbp->timeset>=rcp->lastbancheck) && nickmatchban_visible(np, cbp))
+       if ((cbp->timeset>=rcp->lastbancheck) && nickmatchban(np, cbp, 1))
          localkickuser(chanservnick,cp,np,"Banned.");
       }
       rcp->lastbancheck=time(NULL);
@@ -1102,7 +1131,16 @@ int cs_removechannelifempty(nick *sender, regchan *rcp) {
         return 0;
     }
   }
-  
+
+  /*
+   * don't cleanup the last channel to prevent channel id reuse.
+   * the channel will be orphaned but will be cleaned up by cleanup eventually
+   */
+  if(rcp->ID == lastchannelID) {
+    cs_log(sender,"DELCHAN FAILED %s (last id)",rcp->index->name->content);
+    return 0;
+  }
+
   cs_log(sender,"DELCHAN %s (Empty)",rcp->index->name->content);
   cs_removechannel(rcp, "Last user removed - channel deleted.");
   
@@ -1163,9 +1201,9 @@ int cs_bancheck(nick *np, channel *cp) {
       freesstring(rbp->reason);
       freechanban(rbp->cbp);
       freeregban(rbp);
-    } else if (nickmatchban_visible(np,(*rbh)->cbp)) {
+    } else if (nickmatchban(np,(*rbh)->cbp,1)) {
       /* This user matches this ban.. */
-      if (!nickbanned_visible(np,cp)) {
+      if (!nickbanned(np,cp,1)) {
        /* Only bother putting the ban on the channel if they're not banned already */
        /* (might be covered by this ban or a different one.. doesn't really matter */
        localsetmodeinit(&changes, cp, chanservnick);
@@ -1199,7 +1237,7 @@ void cs_setregban(chanindex *cip, regban *rbp) {
     if (cip->channel->users->content[i]!=nouser &&
        (np=getnickbynumeric(cip->channel->users->content[i])) &&
        !IsService(np) && !IsOper(np) && !IsXOper(np) &&
-       nickmatchban_visible(np, rbp->cbp))
+       nickmatchban(np, rbp->cbp, 1))
       localkickuser(chanservnick, cip->channel, np, rbp->reason ? rbp->reason->content : "Banned.");
   }
 
@@ -1213,7 +1251,7 @@ void cs_banuser(modechanges *changes, chanindex *cip, nick *np, const char *reas
   if (!cip->channel)
     return;
 
-  if (nickbanned_visible(np, cip->channel)) {
+  if (nickbanned(np, cip->channel, 1)) {
     localkickuser(chanservnick, cip->channel, np, reason?reason:"Banned.");
     return;
   }
@@ -1339,7 +1377,7 @@ reguser *findreguser(nick *sender, const char *str) {
  *
  * Return 0 if it works, 1 if it don't.
  */
-int cs_unbanfn(nick *sender, chanindex *cip, UnbanFN fn, void *arg, int removepermbans, int abortonfailure) {
+int cs_unbanfn(nick *sender, chanindex *cip, int (*fn)(void *arg, struct chanban *ban), void *arg, int removepermbans, int abortonfailure) {
   regban **rbh, *rbp;
   chanban **cbh, *cbp;
   regchan *rcp;
@@ -1415,3 +1453,98 @@ int checkreason(nick *np, char *reason) {
 
   return 1;
 }
+
+regchan *cs_addchan(chanindex *cip, nick *sender, reguser *addedby, reguser *founder, flag_t flags, flag_t forcemodes, flag_t denymodes, short type) {
+  regchan *rcp;
+  regchanuser *rcup;
+  void *args[3];
+  int i;
+
+  if (cip->exts[chanservext])
+    return NULL;
+
+  /* Initialise the channel */
+  rcp=getregchan();
+
+  /* ID, index */
+  rcp->ID=++lastchannelID;
+  rcp->index=cip;
+  cip->exts[chanservext]=rcp;
+
+  rcp->chantype=type;
+  rcp->flags=flags;
+  rcp->status=0;
+  rcp->bans=NULL;
+  rcp->lastcountersync=0;
+
+  rcp->limit=0;
+  rcp->forcemodes=forcemodes;
+  rcp->denymodes=denymodes;
+
+  if (CIsAutoLimit(rcp)) {
+    rcp->forcemodes |= CHANMODE_LIMIT;
+  }
+
+  rcp->autolimit=5;
+  rcp->banstyle=0;
+
+  rcp->created=rcp->lastactive=rcp->statsreset=rcp->ostatsreset=time(NULL);
+  rcp->banduration=0;
+  rcp->autoupdate=0;
+  rcp->lastbancheck=0;
+
+  /* Added by */
+  rcp->addedby=addedby->ID;
+
+  /* Founder */
+  rcp->founder=founder->ID;
+
+  /* Suspend by */
+  rcp->suspendby=0;
+  rcp->suspendtime=0;
+
+  rcp->totaljoins=rcp->tripjoins=rcp->otripjoins=rcp->maxusers=rcp->tripusers=rcp->otripusers=0;
+  rcp->welcome=rcp->topic=rcp->key=rcp->suspendreason=rcp->comment=NULL;
+
+  /* Users */
+  memset(rcp->regusers,0,REGCHANUSERHASHSIZE*sizeof(reguser *));
+
+  rcp->checksched=NULL;
+  rcp->ltimestamp=0;
+  for (i=0;i<CHANOPHISTORY;i++) {
+    rcp->chanopnicks[i][0]='\0';
+    rcp->chanopaccts[i]=0;
+  }
+  rcp->chanoppos=0;
+
+  /* Add new channel to db.. */
+  csdb_createchannel(rcp);
+
+  /* Add the founder as +ano */
+  rcup=getregchanuser();
+  rcup->chan=rcp;
+  rcup->user=founder;
+  rcup->flags=(QCUFLAG_OWNER | QCUFLAG_OP | QCUFLAG_AUTOOP);
+  rcup->usetime=0;
+  rcup->info=NULL;
+  rcup->changetime=time(NULL);
+
+  addregusertochannel(rcup);
+  csdb_createchanuser(rcup);
+  csdb_chanlevhistory_insert(rcp, sender, rcup->user, 0, rcup->flags);
+
+  args[0]=sender;
+  args[1]=rcup;
+  args[2]=(void *)0;
+
+  triggerhook(HOOK_CHANSERV_CHANLEVMOD, args);
+
+  /* If the channel exists, get the ball rolling */
+  if (cip->channel) {
+    chanservjoinchan(cip->channel);
+    rcp->status |= QCSTAT_MODECHECK | QCSTAT_OPCHECK | QCSTAT_BANCHECK;
+    cs_timerfunc(cip);
+  }
+
+  return rcp;
+}