]> jfr.im git - irc/quakenet/newserv.git/blobdiff - chanserv/chanservnetevents.c
CHANSERV: lastactive is now only updated for +o and above joins (changes how often...
[irc/quakenet/newserv.git] / chanserv / chanservnetevents.c
index b375103ee8bd217759fae86f30781101c39941ff..7989f90664f690bc7e9aea5b973bc90163936931 100644 (file)
@@ -32,20 +32,12 @@ void cs_handlesethost(int hooknum, void *arg) {
 
 void cs_handlelostnick(int hooknum, void *arg) {
   nick *np=(nick *)arg;
-  nicklist **nlh;
-  nicklist *nlp;
   reguser *rup;
   
   if ((rup=getreguserfromnick(np))) {
-    for (nlh=&(rup->nicks);*nlh;nlh=&((*nlh)->next)) {
-      if ((*nlh)->np==np) {
-        nlp=*nlh;
-        *nlh=nlp->next;
-        freenicklist(nlp);
-        break;
-      }
-    }
-    if ((rup->status & QUSTAT_DEAD) && !rup->nicks) {
+    /* Clean up if this is the last user.  auth->usercount is decremented
+     * AFTER the hook is sent... */
+    if ((rup->status & QUSTAT_DEAD) && (np->auth->usercount==1)) {
       freereguser(rup);
     }  
   }
@@ -69,38 +61,8 @@ void cs_handlenewchannel(int hooknum, void *arg) {
   if ((rcp=(regchan *)cp->index->exts[chanservext])==NULL || CIsSuspended(rcp))
     return;
 
-  /*
-   * If we're supposed to be joined, join ourselves..
-   */
-
-  if (CIsJoined(rcp) && (chanservnick!=NULL)) {
-    chanservjoinchan(cp);
-  }
-
-  /* This code interacts badly with bursts.. need to fix */
-  
-#if 0
-  /* We need to watch out for people sneaking into +k/i channels..
-   * This code relies on the fact that that user will already be in 
-   * the channel at this point in time.. */
-  if (rcp->forcemodes & (CHANMODE_KEY | CHANMODE_INVITEONLY)) {
-    /* OK, this channel is keyed.. let's find out if the user is allowed to be here */
-    for (i=0;i<cp->users->hashsize;i++) {
-      if (cp->users->content[i]!=nouser && (np=getnickbynumeric(cp->users->content[i]))) {
-       if (IsService(np))
-         /* service (might even be us..) */
-         continue;
-
-       if ((rup=getreguserfromnick(np)) && (rcup=findreguseronchannel(rcp, rup)) &&
-           CUKnown(rcup) && !CUIsBanned(rcup))
-         /* legit user */
-         continue;
-
-       localkickuser(chanservnick, cp, np, "Private channel.");
-      }
-    }
-  }
-#endif
+  /* chanservjoinchan() will deal with joining the channel and/or setting the timestamp */   
+  chanservjoinchan(cp);
 
   /* Make sure the right modes are set/cleared */
   cs_checkchanmodes(cp);
@@ -161,8 +123,9 @@ void cs_handlejoin(int hooknum, void *arg) {
   reguser *rup;
   regchanuser *rcup=NULL;
   chanindex *cip;
-  int iscreate;
+  int iscreate, isopped;
   int dowelcome=0;
+  unsigned long *lp;
 
   short modes=0;
  
@@ -184,53 +147,72 @@ void cs_handlejoin(int hooknum, void *arg) {
   if (rup && (rup->status & QUSTAT_DEAD))
     rup=NULL;
   
-  if (rup && (rcup=findreguseronchannel(rcp,rup)) && CUKnown(rcup) && cp->users->totalusers >= 3)
+  if (rup && (rcup=findreguseronchannel(rcp,rup)) && CUHasOpPriv(rcup) && cp->users->totalusers >= 3)
     rcp->lastactive=time(NULL);
+
+  /* Update last use time */
+  if (rcup)
+    rcup->usetime=getnettime();
   
   if (rcp->lastcountersync < (time(NULL) - COUNTERSYNCINTERVAL)) {
     csdb_updatechannelcounters(rcp);
     rcp->lastcountersync=time(NULL);
   }
 
+  /* OK, this may be a CREATE but it's possible we have already bursted onto
+   * the channel and deopped them.  So let's just check that out now.
+   *
+   * There's a distinction between "is it a create?" and "are they opped
+   * already?", since we need to send the generic "This is a Q9 channel"
+   * message on create even if we already deopped them. */
   if (hooknum==HOOK_CHANNEL_CREATE) {
     iscreate=1;
+    if ((lp=getnumerichandlefromchanhash(cp->users, np->numeric)) && (*lp & CUMODE_OP))
+      isopped=1;
+    else
+      isopped=0;
   } else {
-    iscreate=0;
+    isopped=iscreate=0;
   }  
 
-  /* Check for "Q ban" */
-  if (!IsService(np) && cs_bancheck(np,cp)) {
-    /* They got kicked.. */
-    return;
-  }
+  /* Various things that can ban the user on join.  Don't apply these to anyone
+   * with one of +k, +X, +o */
+  if (!IsService(np) && !IsOper(np) && !IsXOper(np)) {
+    /* Check for "Q ban" */
+    if (cs_bancheck(np,cp)) {
+      /* They got kicked.. */
+      return;
+    }
 
-  /* Check for other ban lurking on channel which we are enforcing */
-  if (!IsService(np) && CIsEnforce(rcp) && nickbanned(np,cp)) {
-    localkickuser(chanservnick,cp,np,"Banned.");
-    return;
-  }
+    /* Check for other ban lurking on channel which we are enforcing */
+    if (CIsEnforce(rcp) && nickbanned(np,cp,1)) {
+      localkickuser(chanservnick,cp,np,"Banned.");
+      return;
+    }
 
-  /* Check for +b chanlev flag */
-  if (!IsService(np) && rcup && CUIsBanned(rcup)) {
-    cs_banuser(NULL, cip, np, NULL);
-    cs_timerfunc(cip);
-    return;
-  } 
-
-  /* Check for +k chan flag */
-  if (!IsService(np) && CIsKnownOnly(rcp) && !(rcup && CUKnown(rcup))) {
-    if (IsInviteOnly(cp) || (IsRegOnly(cp) && !IsAccount(np))) {
-      localkickuser(chanservnick,cp,np,"Authorised users only.");
-    } else {      
-      cs_banuser(NULL, cip, np, "Authorised users only.");
+    /* Check for +b chanlev flag */
+    if (rcup && CUIsBanned(rcup)) {
+      cs_banuser(NULL, cip, np, NULL);
       cs_timerfunc(cip);
+      return;
+    } 
+
+    /* Check for +k chan flag */
+    if (CIsKnownOnly(rcp) && !(rcup && CUKnown(rcup))) {
+      /* Don't ban if they are already "visibly" banned for some reason. */
+      if (IsInviteOnly(cp) || (IsRegOnly(cp) && !IsAccount(np))) {
+        localkickuser(chanservnick,cp,np,"Authorised users only.");
+      } else {      
+        cs_banuser(NULL, cip, np, "Authorised users only.");
+        cs_timerfunc(cip);
+      }
+      return;
     }
-    return;
   }
-
+  
   if (!rup || !rcup) {
     /* They're not a registered user, so deop if it is a create */
-    if (iscreate && !IsService(np)) {
+    if (isopped && !IsService(np)) {
       modes |= MC_DEOP;
     }
     if (CIsVoiceAll(rcp)) {
@@ -243,8 +225,6 @@ void cs_handlejoin(int hooknum, void *arg) {
       dowelcome=2;  /* Send a generic warning */
     }
   } else {
-    /* Update last use time */
-    rcup->usetime=getnettime();
 
     /* DB update removed for efficiency..
      * csdb_updatelastjoin(rcup); */
@@ -253,12 +233,13 @@ void cs_handlejoin(int hooknum, void *arg) {
     if (CUIsOp(rcup) && (CIsAutoOp(rcp) || CUIsAutoOp(rcup) || CUIsProtect(rcup) || CIsProtect(rcp)) && 
        !CUIsDeny(rcup)) {
       /* Auto op */
-      if (!iscreate) {
+      if (!isopped) {
         modes |= MC_OP;
+        cs_logchanop(rcp, np->nick, rup);
       }
     } else {
-      /* Not auto op */
-      if (iscreate && !CUIsOp(rcup) && !IsService(np)) {
+      /* Not auto op; deop them if they are opped and are not allowed them */
+      if (isopped && !CUHasOpPriv(rcup) && !IsService(np)) {
         modes |= MC_DEOP;
       }
 
@@ -293,11 +274,15 @@ void cs_handlejoin(int hooknum, void *arg) {
           break;
   }        
 
-  if (rup && rcup && CIsInfo(rcp) && UIsInfo(rcup->user) && !CUIsHideInfo(rcup) && chanservnick) {
-    if (rcup->info) {
+  /* Display infoline if... (deep breath) user is registered, known on channel,
+   * user,channel,chanlev all +i and user,channel,chanlev all -s AND Q online */
+  if (rup && rcup && 
+      CIsInfo(rcp) && UIsInfo(rcup->user) && CUIsInfo(rcup) && 
+      !CIsNoInfo(rcp) && !UIsNoInfo(rcup->user) && !CUIsNoInfo(rcup) && chanservnick) {
+    if (rcup->info && *(rcup->info->content)) {
       /* Chan-specific info */
       sendmessagetochannel(chanservnick, cp, "[%s] %s",np->nick, rcup->info->content);
-    } else if (rup->info) {
+    } else if (rup->info && *(rup->info->content)) {
       /* Default info */
       sendmessagetochannel(chanservnick, cp, "[%s] %s",np->nick, rup->info->content);
     }
@@ -311,7 +296,7 @@ void cs_handlejoin(int hooknum, void *arg) {
 void cs_handlemodechange(int hooknum, void *arg) {
   void **arglist=(void **)arg;
   channel *cp=(channel *)arglist[0];
-  int changeflags=(int)arglist[2];
+  long changeflags=(long)arglist[2];
   regchan *rcp;
 
   if ((rcp=cp->index->exts[chanservext])==NULL || CIsSuspended(rcp))
@@ -424,7 +409,7 @@ void cs_handlenewban(int hooknum, void *arg) {
          Error("chanserv",ERR_WARNING,"Found user on channel %s who doesn't exist!",cp->index->name->content);
          continue;
        }
-       if (!IsService(np) && nickmatchban(np,cbp)) {
+       if (!IsService(np) && nickmatchban(np,cbp,1)) {
          localkickuser(chanservnick,cp,np,"Banned.");
        }
       }
@@ -445,10 +430,8 @@ void cs_handletopicchange(int hooknum, void *arg) {
     return;
  
   if (CIsForceTopic(rcp)) {
-    if (rcp->topic) {
-      /* Forced topic: change it back */
-      localsettopic(chanservnick, cp, rcp->topic->content);
-    }
+    /* Forced topic: change it back even if blank */
+    localsettopic(chanservnick, cp, (rcp->topic)?rcp->topic->content:"");
   } else if (CIsTopicSave(rcp)) {
     if (rcp->topic) {
       freesstring(rcp->topic);