]> jfr.im git - irc/quakenet/newserv.git/blobdiff - chanfix/chanfix.c
TRUSTS: require sqlite
[irc/quakenet/newserv.git] / chanfix / chanfix.c
index 79cace4566c6b034bf2b0b725239ec2cc78b22ed..fd6db4e54b5fb9f0c5a2dfeb6f48f2a1b20dae0a 100644 (file)
 #include "../nick/nick.h"
 #include "../lib/irc_string.h"
 #include "../control/control.h"
+#include "../lib/version.h"
+
+MODULE_VERSION("")
 
 /* control's nick */
 extern nick *mynick;
 
 int cfext;
 int cfnext;
-int cffailedinit;
+
+static int cffailedinit;
 
 /* user accessible commands */
 int cfcmd_debug(void *source, int cargc, char **cargv);
@@ -44,7 +48,6 @@ void cfsched_dosave(void *arg);
 void cfhook_autofix(int hook, void *arg);
 void cfhook_statsreport(int hook, void *arg);
 void cfhook_auth(int hook, void *arg);
-void cfhook_lostnick(int hook, void *arg);
 
 /* helper functions */
 regop *cf_createregop(nick *np, chanindex *cip);
@@ -64,93 +67,89 @@ void _init() {
   if (cfext < 0 || cfnext < 0) {
     Error("chanfix", ERR_ERROR, "Couldn't register channel and/or nick extension");
     cffailedinit = 1;
-  } else {
-    schedulerecurring(time(NULL), 0, CFSAMPLEINTERVAL, &cfsched_dosample, NULL);
-    schedulerecurring(time(NULL), 0, CFEXPIREINTERVAL, &cfsched_doexpire, NULL);
-    schedulerecurring(time(NULL), 0, CFAUTOSAVEINTERVAL, &cfsched_dosave, NULL);
+    return;
+  }
+
+  schedulerecurring(time(NULL), 0, CFSAMPLEINTERVAL, &cfsched_dosample, NULL);
+  schedulerecurring(time(NULL), 0, CFEXPIREINTERVAL, &cfsched_doexpire, NULL);
+  schedulerecurring(time(NULL), 0, CFAUTOSAVEINTERVAL, &cfsched_dosave, NULL);
 
-    registercontrolhelpcmd("cfdebug", NO_DEVELOPER, 1, &cfcmd_debug, "Display Debug Information on chanfix data for channel");
-    registercontrolhelpcmd("cfhistogram", NO_DEVELOPER, 1, &cfcmd_debughistogram, "Display Debug Histogram of chanfix data for channel");
+  registercontrolhelpcmd("cfdebug", NO_DEVELOPER, 1, &cfcmd_debug, "Display Debug Information on chanfix data for channel");
+  registercontrolhelpcmd("cfhistogram", NO_DEVELOPER, 1, &cfcmd_debughistogram, "Display Debug Histogram of chanfix data for channel");
 #if CFDEBUG
-    registercontrolhelpcmd("cfsample", NO_DEVELOPER, &cfcmd_debugsample, "DEBUG Command - must not be loaded on live instances");
-    registercontrolhelpcmd("cfexpire", NO_DEVELOPER, 1, &cfcmd_debugexpire, "DEBUG Command - must not be loaded on live instances");
+  registercontrolhelpcmd("cfsample", NO_DEVELOPER, 1, &cfcmd_debugsample, "DEBUG Command - must not be loaded on live instances");
+  registercontrolhelpcmd("cfexpire", NO_DEVELOPER, 1, &cfcmd_debugexpire, "DEBUG Command - must not be loaded on live instances");
 #endif
-    registercontrolhelpcmd("chanopstat", NO_OPER, 1, &cfcmd_chanopstat, "Shows chanop statistics for a given channel");
-    registercontrolhelpcmd("chanoplist", NO_OPER, 1, &cfcmd_chanoplist, "Shows lists of known chanops, including scores");
+  registercontrolhelpcmd("chanopstat", NO_OPER, 1, &cfcmd_chanopstat, "Shows chanop statistics for a given channel");
+  registercontrolhelpcmd("chanoplist", NO_OPER, 1, &cfcmd_chanoplist, "Shows lists of known chanops, including scores");
 
-    registercontrolhelpcmd("chanfix", NO_OPER, 1, &cfcmd_chanfix, "Perform a chanfix on a channel to op known users only");
-    registercontrolhelpcmd("showregs", NO_OPER, 1, &cfcmd_showregs, "Show regular ops known on a channel (including services)");
+  registercontrolhelpcmd("chanfix", NO_OPER, 1, &cfcmd_chanfix, "Perform a chanfix on a channel to op known users only");
+  registercontrolhelpcmd("showregs", NO_OPER, 1, &cfcmd_showregs, "Show regular ops known on a channel (including services)");
 #if CFDEBUG
-    /* should we disable this in the 'final' build? */
-    /* registercontrolcmd("requestop", 0, 2, &cfcmd_requestop); */
+  /* should we disable this in the 'final' build? */
+  /* registercontrolcmd("requestop", 0, 2, &cfcmd_requestop); */
 #endif
-    registercontrolhelpcmd("cfsave", NO_DEVELOPER, 0, &cfcmd_save, "Force save of chanfix data");
-    registercontrolhelpcmd("cfload", NO_DEVELOPER, 0, &cfcmd_load, "Force load of chanfix data");
+  registercontrolhelpcmd("cfsave", NO_DEVELOPER, 0, &cfcmd_save, "Force save of chanfix data");
+  registercontrolhelpcmd("cfload", NO_DEVELOPER, 0, &cfcmd_load, "Force load of chanfix data");
 
 #if CFAUTOFIX
-    registerhook(HOOK_CHANNEL_DEOPPED, &cfhook_autofix);
-    registerhook(HOOK_CHANNEL_PART, &cfhook_autofix);
-    registerhook(HOOK_CHANNEL_KICK, &cfhook_autofix);
-    registerhook(HOOK_CHANNEL_JOIN, &cfhook_autofix);
+  registerhook(HOOK_CHANNEL_DEOPPED, &cfhook_autofix);
+  registerhook(HOOK_CHANNEL_PART, &cfhook_autofix);
+  registerhook(HOOK_CHANNEL_KICK, &cfhook_autofix);
+  registerhook(HOOK_CHANNEL_JOIN, &cfhook_autofix);
 #endif
 
-    registerhook(HOOK_CORE_STATSREQUEST, &cfhook_statsreport);
-    registerhook(HOOK_NICK_ACCOUNT, &cfhook_auth);
-    registerhook(HOOK_NICK_LOSTNICK, &cfhook_lostnick);
+  registerhook(HOOK_CORE_STATSREQUEST, &cfhook_statsreport);
+  registerhook(HOOK_NICK_ACCOUNT, &cfhook_auth);
 
-    cf_loadchanfix();
+  cf_loadchanfix();
 
-    cffailedinit = 0;
-  }
+  cffailedinit = 0;
 }
 
 void _fini() {
-  int i;
-  nick *nip;
-
-  if (cffailedinit == 0) {
-    deleteschedule(NULL, &cfsched_dosample, NULL);
-    deleteschedule(NULL, &cfsched_doexpire, NULL);
-    deleteschedule(NULL, &cfsched_dosave, NULL);
-
-    cf_storechanfix();
+  if (cffailedinit)
+    return;
 
-    cf_free();
+  deleteschedule(NULL, &cfsched_dosample, NULL);
+  deleteschedule(NULL, &cfsched_doexpire, NULL);
+  deleteschedule(NULL, &cfsched_dosave, NULL);
 
-    for (i=0; i<NICKHASHSIZE; i++)
-      for (nip=nicktable[i]; nip; nip=nip->next)
-        free(nip->exts[cfnext]);
+  cf_storechanfix();
 
-    releasechanext(cfext);
-    releasenickext(cfnext);
+  cf_free();
 
-    deregistercontrolcmd("cfdebug", &cfcmd_debug);
-    deregistercontrolcmd("cfhistogram", &cfcmd_debughistogram);
+  deregistercontrolcmd("cfdebug", &cfcmd_debug);
+  deregistercontrolcmd("cfhistogram", &cfcmd_debughistogram);
 #if CFDEBUG
-    deregistercontrolcmd("cfsample", &cfcmd_debugsample);
-    deregistercontrolcmd("cfexpire", &cfcmd_debugexpire);
+  deregistercontrolcmd("cfsample", &cfcmd_debugsample);
+  deregistercontrolcmd("cfexpire", &cfcmd_debugexpire);
 #endif
-    deregistercontrolcmd("chanopstat", &cfcmd_chanopstat);
-    deregistercontrolcmd("chanoplist", &cfcmd_chanoplist);
-    deregistercontrolcmd("chanfix", &cfcmd_chanfix);
-    deregistercontrolcmd("showregs", &cfcmd_showregs);
+  deregistercontrolcmd("chanopstat", &cfcmd_chanopstat);
+  deregistercontrolcmd("chanoplist", &cfcmd_chanoplist);
+  deregistercontrolcmd("chanfix", &cfcmd_chanfix);
+  deregistercontrolcmd("showregs", &cfcmd_showregs);
 #if CFDEBUG
-//    deregistercontrolcmd("requestop", &cfcmd_requestop);
+//  deregistercontrolcmd("requestop", &cfcmd_requestop);
 #endif
-    deregistercontrolcmd("cfsave", &cfcmd_save);
-    deregistercontrolcmd("cfload", &cfcmd_load);
+  deregistercontrolcmd("cfsave", &cfcmd_save);
+  deregistercontrolcmd("cfload", &cfcmd_load);
 
 #if CFAUTOFIX
-    deregisterhook(HOOK_CHANNEL_DEOPPED, &cfhook_autofix);
-    deregisterhook(HOOK_CHANNEL_PART, &cfhook_autofix);
-    deregisterhook(HOOK_CHANNEL_KICK, &cfhook_autofix);
-    deregisterhook(HOOK_CHANNEL_JOIN, &cfhook_autofix);
+  deregisterhook(HOOK_CHANNEL_DEOPPED, &cfhook_autofix);
+  deregisterhook(HOOK_CHANNEL_PART, &cfhook_autofix);
+  deregisterhook(HOOK_CHANNEL_KICK, &cfhook_autofix);
+  deregisterhook(HOOK_CHANNEL_JOIN, &cfhook_autofix);
 #endif
 
-    deregisterhook(HOOK_CORE_STATSREQUEST, &cfhook_statsreport);
-    deregisterhook(HOOK_NICK_ACCOUNT, &cfhook_auth);
-    deregisterhook(HOOK_NICK_LOSTNICK, &cfhook_lostnick);
-  }
+  deregisterhook(HOOK_CORE_STATSREQUEST, &cfhook_statsreport);
+  deregisterhook(HOOK_NICK_ACCOUNT, &cfhook_auth);
+
+  if (cfext >= 0)
+    releasechanext(cfext);
+
+  if (cfnext >= 0)
+    releasenickext(cfnext);
 }
 
 int cfcmd_debug(void *source, int cargc, char **cargv) {
@@ -160,11 +159,8 @@ int cfcmd_debug(void *source, int cargc, char **cargv) {
   regop *ro;
   int i;
 
-  if (cargc < 1) {
-    controlreply(np, "Syntax: cfdebug <#channel>");
-
-    return CMD_ERROR;
-  }
+  if (cargc < 1)
+    return CMD_USAGE;
 
   cip = findchanindex(cargv[0]);
 
@@ -172,8 +168,9 @@ int cfcmd_debug(void *source, int cargc, char **cargv) {
     controlreply(np, "No such channel.");
 
     return CMD_ERROR;
-  } else
-    controlreply(np, "Found channel %s. Retrieving chanfix information...", cargv[0]);
+  }
+
+  controlreply(np, "Found channel %s. Retrieving chanfix information...", cargv[0]);
 
   cf = cip->exts[cfext];
 
@@ -181,13 +178,14 @@ int cfcmd_debug(void *source, int cargc, char **cargv) {
     controlreply(np, "No chanfix information for %s", cargv[0]);
 
     return CMD_ERROR;
-  } else
-    controlreply(np, "Found chanfix information. Dumping...");
+  }
+
+  controlreply(np, "Found chanfix information. Dumping...");
 
   for (i=0;i<cf->regops.cursi;i++) {
     ro = ((regop**)cf->regops.content)[i];
 
-    controlreply(np, "%d. type: %s hash: 0x%x lastopped: %d uh: %s score: %d",
+    controlreply(np, "%d. type: %s hash: 0x%lx lastopped: %lu uh: %s score: %d",
                  i + 1, ro->type == CFACCOUNT ? "CFACCOUNT" : "CFHOST", ro->hash,
                  ro->lastopped, ro->uh ? ro->uh->content : "(unknown)", ro->score);
   }
@@ -202,7 +200,6 @@ int cfcmd_debughistogram(void *source, int cargc, char **cargv) {
   int i,a,score;
   chanindex* cip;
   chanfix *cf;
-  char buf[400];
   int histogram[10001]; /* 625 (lines) * 16 (columns/line) + 1 (for histogram[0]) */
 
   for (i = 0; i < 10001; i++)
@@ -224,16 +221,11 @@ int cfcmd_debughistogram(void *source, int cargc, char **cargv) {
   controlreply(np, "--- Histogram of chanfix scores");
 
   for (i = 1; i < 10001; i += 16) {
-    buf[0] = '\0';
-
-    for (a = 0; a < 16; a++) {
-      if (a != 0)
-        strcat(buf, " ");
-
-      sprintf(buf+strlen(buf),"%d", histogram[i+a]);
-    }
-
-    controlreply(np, "%6d: %s", i, buf);
+    controlreply(np, "%6d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", 
+      i, histogram[i], histogram[i+1], histogram[i+2], histogram[i+3], histogram[i+4],
+      histogram[i+5], histogram[i+6], histogram[i+7], histogram[i+8], histogram[i+9],
+      histogram[i+10], histogram[i+11], histogram[i+12], histogram[i+13], histogram[i+14],
+      histogram[i+15]);
   }
 
   controlreply(np, "--- End of histogram");
@@ -291,9 +283,8 @@ int cf_getsortedregops(chanfix *cf, int max, regop **list) {
 
   qsort(cf->regops.content, cf->regops.cursi, sizeof(regop*), cmpregop);
 
-  for (i = 0; i < min(max, cf->regops.cursi); i++) {
+  for (i = 0; i < min(max, cf->regops.cursi); i++)
     list[i] = ((regop**)cf->regops.content)[i];
-  }
 
   return i;
 }
@@ -307,13 +298,9 @@ int cfcmd_chanopstat(void *source, int cargc, char **cargv) {
   regop *rolist[10];
   int i, a, count;
   int *scores;
-  char buf[400];
-
-  if (cargc < 1) {
-    controlreply(np, "Syntax: chanopstat <#channel>");
 
-    return CMD_ERROR;
-  }
+  if (cargc < 1)
+    return CMD_USAGE;
 
   cp = findchannel(cargv[0]);
 
@@ -333,17 +320,10 @@ int cfcmd_chanopstat(void *source, int cargc, char **cargv) {
 
   /* known ops */
   count = cf_getsortedregops(cf, 10, rolist);
+  controlreply(np, "Scores of \"best ops\" on %s are:", cargv[0]);
 
-  buf[0] = '\0';
-
-  for (i=0;i<count;i++) {
-    if (i != 0)
-      strcat(buf, " ");
-
-    sprintf(buf+strlen(buf),"%d", rolist[i]->score);
-  }
-
-  controlreply(np, "Scores of \"best ops\" on %s are: %s", cargv[0], buf);
+  for (i=0;i<count;i++)
+    controlreply(np, "  %d", rolist[i]->score);
 
   /* current ops */
   scores = (int*)malloc(sizeof(int) * cp->users->hashsize);
@@ -362,23 +342,16 @@ int cfcmd_chanopstat(void *source, int cargc, char **cargv) {
   }
 
   qsort(scores, i, sizeof(int), &cmpint);
-
-  buf[0] = '\0';
+  controlreply(np, "Scores of current ops on %s are:", cargv[0]);
 
   for (a=0;a<min(i,20);a++) {
     if (scores[a] == 0)
       break;
 
-    if (a != 0)
-      strcat(buf, " ");
-
-    sprintf(buf+strlen(buf),"%d", scores[a]);
+    controlreply(np, "  %d", scores[a]);
   }
 
   free(scores);
-
-  controlreply(np, "Scores of current ops on %s are: %s", cargv[0], buf);
-
   controlreply(np, "Done.");
 
   return CMD_OK;
@@ -390,17 +363,14 @@ int cfcmd_chanoplist(void *source, int cargc, char **cargv) {
   chanindex *cip;
   chanfix *cf;
   regop *rolist[50];
-  int i,a,count;
+  int i,count;
   time_t ct;
-  const char* cdate;
-  char* date;
+  struct tm *tm;
+  char date[50];
   unsigned long *hand;
 
-  if (cargc < 1) {
-    controlreply(np, "Syntax: chanoplist <#channel>");
-
-    return CMD_ERROR;
-  }
+  if (cargc < 1)
+    return CMD_USAGE;
 
   cip = findchanindex(cargv[0]);
 
@@ -436,25 +406,11 @@ int cfcmd_chanoplist(void *source, int cargc, char **cargv) {
                      np2->host->name->content, np2->realname->name->content);
     } else {
       ct = rolist[i]->lastopped;
-
-      cdate = ctime(&ct);
-
-      date = (char*)malloc(strlen(cdate) + 1);
-      strcpy(date, cdate);
-
-      for (a=0;a<strlen(date);a++) {
-        if (date[a] == '\n') {
-          date[a] = '\0';
-          break;
-        }
-      }
-
+      tm = gmtime(&ct);
+      strftime(date,sizeof(date),"%d-%m-%Y %H:%M:%S",tm);
       controlreply(np, "%3d %5d %-7s %1s%-16s %s Last seen: %s", i + 1, rolist[i]->score,
-                   (rolist[i]->type == CFACCOUNT) ? "account" : "host",
-                   "", "!NONE!",
+                   (rolist[i]->type == CFACCOUNT) ? "account" : "host", "", "!NONE!",
                    rolist[i]->uh ? rolist[i]->uh->content : "!UNKNOWN!", date);
-
-      free(date);
     }
   }
 
@@ -468,11 +424,8 @@ int cfcmd_chanfix(void *source, int cargc, char **cargv) {
   channel *cp;
   int ret;
 
-  if (cargc < 1) {
-    controlreply(np, "Syntax: chanfix <#channel>");
-
-    return CMD_ERROR;
-  }
+  if (cargc < 1)
+    return CMD_USAGE;
 
   cp = findchannel(cargv[0]);
 
@@ -482,7 +435,7 @@ int cfcmd_chanfix(void *source, int cargc, char **cargv) {
     return CMD_ERROR;
   }
 
-  if (sp_countsplitservers() > 0) {
+  if (sp_countsplitservers(SERVERTYPEFLAG_USER_STATE) > 0) {
     controlreply(np, "Chanfix cannot be used during a netsplit.");
 
     return CMD_ERROR;
@@ -513,14 +466,11 @@ int cfcmd_showregs(void *source, int cargc, char **cargv) {
   nick *np2;
   chanfix *cf;
   channel *cp;
-  int a, i, count, ops;
+  int i, count, ops;
   regop *rolist[50];
 
-  if (cargc < 1) {
-    controlreply(np, "Syntax: showregs <#channel>");
-
-    return CMD_ERROR;
-  }
+  if (cargc < 1)
+    return CMD_USAGE;
 
   cp = findchannel(cargv[0]);
 
@@ -540,9 +490,9 @@ int cfcmd_showregs(void *source, int cargc, char **cargv) {
 
   count = 0;
 
-  for(a=0;a<cp->users->hashsize;a++) {
-    if(cp->users->content[a] != nouser) {
-      np2 = getnickbynumeric(cp->users->content[a]);
+  for(i=0;i<cp->users->hashsize;i++) {
+    if(cp->users->content[i] != nouser) {
+      np2 = getnickbynumeric(cp->users->content[i]);
 
       if (IsService(np2)) {
         controlreply(np, "%s (service)", np2->nick);
@@ -581,11 +531,8 @@ int cfcmd_requestop(void *source, int cargc, char **cargv) {
   unsigned long *hand;
   modechanges changes;
 
-  if (cargc < 1) {
-    controlreply(np, "Syntax: requestop <#channel> [nick]");
-
-    return CMD_ERROR;
-  }
+  if (cargc < 1)
+    return CMD_USAGE;
 
   cp = findchannel(cargv[0]);
 
@@ -622,7 +569,7 @@ int cfcmd_requestop(void *source, int cargc, char **cargv) {
     }
   }
 
-  if (sp_countsplitservers() > 0) {
+  if (sp_countsplitservers(SERVERTYPEFLAG_USER_STATE) > 0) {
     controlreply(np, "One or more servers are currently split. Wait until the"
                  " netsplit is over and try again.");
 
@@ -711,28 +658,25 @@ int cf_hasauthedcloneonchan(nick *np, channel *cp) {
 }
 
 void cfsched_dosample(void *arg) {
-  int i,a,now,cfscore,cfnewro,cfuhost,diff;
+  int i,a,now,cfscore,cfnewro,diff;
   channel *cp;
   chanindex *cip;
   nick *np;
-  chanfix *cf;
   regop *ro, *roh;
   struct timeval start;
   struct timeval end;
-  char buf[USERLEN+1+HOSTLEN+1];
 
   now = getnettime();
 
-  cfuhost = cfscore = cfnewro = 0;
+  cfscore = cfnewro = 0;
 
-  if (sp_countsplitservers() > CFMAXSPLITSERVERS)
+  if (sp_countsplitservers(SERVERTYPEFLAG_USER_STATE) > CFMAXSPLITSERVERS)
     return;
 
   gettimeofday(&start, NULL);
 
   for (i=0; i<CHANNELHASHSIZE; i++) {
     for (cip=chantable[i]; cip; cip=cip->next) {
-      cf = (chanfix*)cip->exts[cfext];
       cp = cip->channel;
 
       if (!cp || cp->users->totalusers < CFMINUSERS)
@@ -742,6 +686,9 @@ void cfsched_dosample(void *arg) {
         if ((cp->users->content[a] != nouser) && (cp->users->content[a] & CUMODE_OP)) {
           np = getnickbynumeric(cp->users->content[a]);
 
+          if (!np)
+            continue;
+
 #if !CFDEBUG
           if (IsService(np))
             continue;
@@ -757,37 +704,23 @@ void cfsched_dosample(void *arg) {
 
           /* lastopped == now if the user has clones, we obviously
            * don't want to give them points in this case */
-          if (ro && ro->lastopped != now) {
-            if (ro->type != CFHOST || !cf_hasauthedcloneonchan(np, cp)) {
-              ro->score++;
-              cfscore++;
-            }
-
-            /* merge any matching CFHOST records */
-            if (roh && roh->type == CFHOST && ro->type == CFACCOUNT) {
-              /* hmm */
-              ro->score += roh->score;
-
-              cf_deleteregop(cip, roh);
-            }
-
-            /* store the user's account/host if we have to */
-            if (ro->uh == NULL && ro->score >= CFMINSCOREUH) {
-              if (ro->type == CFACCOUNT)
-                ro->uh = getsstring(np->authname, ACCOUNTLEN);
-              else {
-                strcpy(buf, np->ident);
-                strcat(buf, "@");
-                strcat(buf, np->host->name->content);
-
-                roh->uh = getsstring(buf, USERLEN+1+HOSTLEN);
-              }
-
-              cfuhost++;
-            }
-
-            ro->lastopped = now;
+          if (!ro || ro->lastopped == now)
+            continue;
+
+          if (ro->type != CFHOST || !cf_hasauthedcloneonchan(np, cp)) {
+            ro->score++;
+            cfscore++;
           }
+
+          /* merge any matching CFHOST records */
+          if (roh && roh->type == CFHOST && ro->type == CFACCOUNT) {
+            /* hmm */
+            ro->score += roh->score;
+
+            cf_deleteregop(cip, roh);
+          }
+
+          ro->lastopped = now;
         }
       }
     }
@@ -802,8 +735,8 @@ void cfsched_dosample(void *arg) {
            (start.tv_sec * 1000 + start.tv_usec / 1000);
 
     sendmessagetochannel(mynick, cp, "sampled chanfix scores, assigned %d new"
-                         " points, %d new regops, %d user@hosts added, deltaT: %dms", cfscore,
-                         cfnewro, cfuhost, diff);
+                         " points, %d new regops, deltaT: %dms", cfscore,
+                         cfnewro, diff);
   }
 }
 
@@ -812,14 +745,14 @@ void cfsched_doexpire(void *arg) {
   chanindex *cip;
   chanindex *ncip;
   chanfix *cf;
-  int i,a,cfscore,cfregop,cffreeuh,diff;
+  int i,a,cfscore,cfregop,diff;
   regop **rolist;
   regop *ro;
   struct timeval start;
   struct timeval end;
   time_t currenttime;
 
-  cffreeuh = cfscore = cfregop = 0;
+  cfscore = cfregop = 0;
 
   gettimeofday(&start, NULL);
   currenttime=getnettime();
@@ -834,19 +767,12 @@ void cfsched_doexpire(void *arg) {
         for (a=0;a<cf->regops.cursi;a++) {
           ro = rolist[a];
 
-          if ((currenttime - ro->lastopped > 2 * CFSAMPLEINTERVAL) && ro->score) {
+          if (((currenttime - ro->lastopped) > (2 * CFSAMPLEINTERVAL)) && ro->score) {
             ro->score--;
             cfscore++;
           }
 
-          if (ro->score < CFMINSCOREUH && ro->uh) {
-            freesstring(ro->uh);
-            ro->uh = NULL;
-
-            cffreeuh++;
-          }
-
-          if (ro->score == 0 || ro->lastopped < currenttime - CFREMEMBEROPS) {
+          if (ro->score == 0 || ro->lastopped < (currenttime - CFREMEMBEROPS)) {
             cf_deleteregop(cip, ro);
             cfregop++;
           }
@@ -876,8 +802,8 @@ void cfsched_doexpire(void *arg) {
            (start.tv_sec * 1000 + start.tv_usec / 1000);
 
     sendmessagetochannel(mynick, cp, "expired chanfix scores, purged %d points,"
-                         " scrapped %6d regops, %d user@hosts freed, deltaT: %dms", cfscore,
-                         cfregop, cffreeuh, diff);
+                         " scrapped %6d regops, deltaT: %dms", cfscore,
+                         cfregop, diff);
   }
 
 }
@@ -896,7 +822,7 @@ void cfhook_autofix(int hook, void *arg) {
       hook == HOOK_CHANNEL_KICK || hook == HOOK_CHANNEL_JOIN) {
     cp = args[0];
 
-    if (sp_countsplitservers() > 0)
+    if (sp_countsplitservers(SERVERTYPEFLAG_USER_STATE) > 0)
       return;
 
     for(a=0;a<cp->users->hashsize;a++) {
@@ -922,7 +848,6 @@ void cfhook_statsreport(int hook, void *arg) {
   char buf[300];
   int i,a,rc,mc,memory;
   chanindex *cip;
-  nick *nip;
   chanfix *cf;
 
   if ((long)arg > 2) {
@@ -947,15 +872,8 @@ void cfhook_statsreport(int hook, void *arg) {
       }
     }
 
-    for (i=0; i<NICKHASHSIZE; i++) {
-      for (nip=nicktable[i]; nip; nip=nip->next) {
-        if (nip->exts[cfnext])
-          memory += sizeof(int);
-      }
-    }
-
-    sprintf(buf, "Chanfix : %6d registered ops, %9d monitored channels. %9d"
-            " kbytes of memory used", rc, mc, memory / 1024);
+    snprintf(buf, sizeof(buf), "Chanfix : %6d registered ops, %9d monitored channels. %9d"
+            " kbytes of memory used", rc, mc, (memory / 1024));
     triggerhook(HOOK_CORE_STATSREPLY, buf);
   }
 }
@@ -964,20 +882,12 @@ void cfhook_auth(int hook, void *arg) {
   nick *np = (nick*)arg;
 
   /* Invalidate the user's hash */
-  free(np->exts[cfnext]);
-
   np->exts[cfnext] = NULL;
   
   /* Calculate the new hash */
   cf_gethash(np, CFACCOUNT);
 }
 
-void cfhook_lostnick(int hook, void *arg) {
-  nick *np = (nick*)arg;
-
-  free(np->exts[cfnext]);
-}
-
 /* Returns the hash of a specific user (np), type can be either CFACCOUNT,
    CFHOST or both (binary or'd values). cf_gethash will also cache the user's
    hash in a nick extension */
@@ -985,30 +895,25 @@ unsigned long cf_gethash(nick *np, int type) {
   char buf[USERLEN+1+HOSTLEN+1];
   unsigned long hash;
 
-  if (IsAccount(np) && type & CFACCOUNT) {
+  if (IsAccount(np) && (type & CFACCOUNT)) {
     if (np->exts[cfnext] == NULL) {
-      np->exts[cfnext] = (int*)malloc(sizeof(int));
-      *(int*)np->exts[cfnext] = crc32(np->authname);
+      np->exts[cfnext] = (void *)irc_crc32(np->authname);
     }
 
-    return *(int*)np->exts[cfnext];
+    return (unsigned long)np->exts[cfnext];
   } else if (type == CFACCOUNT)
     return 0; /* this should not happen */
 
   if (type & CFHOST) {
     if (!IsAccount(np) && np->exts[cfnext])
-      return *(int*)np->exts[cfnext];
+      return (unsigned long)np->exts[cfnext];
     else {
-      strcpy(buf, np->ident);
-      strcat(buf, "@");
-      strcat(buf, np->host->name->content);
-      hash = crc32(buf);
+      snprintf(buf, sizeof(buf), "%s@%s", np->ident, np->host->name->content);
+      hash = irc_crc32(buf);
 
       /* if the user is not authed, update the hash */
       if (!IsAccount(np)) {
-        np->exts[cfnext] = (int*)malloc(sizeof(int));
-
-        *(int*)np->exts[cfnext] = hash;
+        np->exts[cfnext] = (void *)hash;
       }
 
       return hash;
@@ -1099,7 +1004,7 @@ regop *cf_findregop(nick *np, chanindex *cip, int type) {
   if (cf == NULL)
     return NULL;
 
-  if (IsAccount(np) && type & CFACCOUNT)
+  if (IsAccount(np) && (type & CFACCOUNT))
     ty = CFACCOUNT;
   else
     ty = CFHOST;
@@ -1112,7 +1017,7 @@ regop *cf_findregop(nick *np, chanindex *cip, int type) {
   }
 
   /* try using the uhost if we didn't find a user with the right account */
-  if (ty == CFACCOUNT && type & CFHOST)
+  if (ty == CFACCOUNT && (type & CFHOST))
     return cf_findregop(np, cip, CFHOST);
   else
     return NULL;
@@ -1124,6 +1029,7 @@ regop *cf_createregop(nick *np, chanindex *cip) {
   chanfix *cf = cip->exts[cfext];
   int slot, type;
   regop **rolist;
+  char buf[USERLEN+1+HOSTLEN+1];
 
   if (cf == NULL) {
     cf = (chanfix*)malloc(sizeof(chanfix));
@@ -1140,14 +1046,18 @@ regop *cf_createregop(nick *np, chanindex *cip) {
 
   rolist[slot] = (regop*)malloc(sizeof(regop));
 
-  if (IsAccount(np))
+  if (IsAccount(np)) {
     type = CFACCOUNT;
-  else
+    rolist[slot]->uh = getsstring(np->authname, ACCOUNTLEN);
+  } else {
     type = CFHOST;
 
+    snprintf(buf, sizeof(buf), "%s@%s", np->ident, np->host->name->content);
+    rolist[slot]->uh = getsstring(buf, USERLEN+1+HOSTLEN);
+  }
+
   rolist[slot]->type = type;
   rolist[slot]->hash = cf_gethash(np, type);
-  rolist[slot]->uh = NULL;
   rolist[slot]->lastopped = 0;
   rolist[slot]->score = 0;
 
@@ -1222,7 +1132,7 @@ int cf_fixchannel(channel *cp) {
 
   /* and op some of them */
   for (i=0;i<ops;i++) {
-    if (count >= CFMAXOPS || rolist[i]->score < rolist[0]->score / 2)
+    if (count >= CFMAXOPS || rolist[i]->score < (rolist[0]->score / 2))
       break;
 
     if (rolist[i]->score < CFMINSCORE && i != 0 )
@@ -1257,16 +1167,16 @@ int cf_storechanfix(void) {
   char dstfile[300];
   int a, i, count = 0;
 
-  snprintf(dstfile, 300, "%s.%d", CFSTORAGE, CFSAVEFILES);
+  snprintf(dstfile, sizeof(dstfile), "%s.%d", CFSTORAGE, CFSAVEFILES);
   unlink(dstfile);
 
   for (i = CFSAVEFILES; i > 0; i--) {
-    snprintf(srcfile, 300, "%s.%i", CFSTORAGE, i - 1);
-    snprintf(dstfile, 300, "%s.%i", CFSTORAGE, i);
+    snprintf(srcfile, sizeof(srcfile), "%s.%i", CFSTORAGE, i - 1);
+    snprintf(dstfile, sizeof(dstfile), "%s.%i", CFSTORAGE, i);
     rename(srcfile, dstfile);
   }
 
-  snprintf(srcfile, 300, "%s.0", CFSTORAGE);
+  snprintf(srcfile, sizeof(srcfile), "%s.0", CFSTORAGE);
   cfdata = fopen(srcfile, "w");
 
   if (cfdata == NULL)
@@ -1279,14 +1189,11 @@ int cf_storechanfix(void) {
           ro = ((regop**)cf->regops.content)[a];
 
           if (ro->uh)
-            fprintf(cfdata, "%s %lu %lu %lu %lu %s\n", cip->name->content,
-                    (unsigned long)ro->type, (unsigned long)ro->hash,
-                    (unsigned long)ro->lastopped, (unsigned long)ro->score,
-                    ro->uh->content);
+            fprintf(cfdata, "%s %d %lu %lu %d %s\n", cip->name->content,
+                    ro->type, ro->hash, ro->lastopped, ro->score, ro->uh->content);
           else
-            fprintf(cfdata, "%s %lu %lu %lu %lu\n", cip->name->content,
-                    (unsigned long)ro->type, (unsigned long)ro->hash,
-                    (unsigned long)ro->lastopped, (unsigned long)ro->score);
+            fprintf(cfdata, "%s %d %lu %lu %d\n", cip->name->content,
+                    ro->type, ro->hash, ro->lastopped, ro->score);
           count++;
         }
       }
@@ -1305,11 +1212,13 @@ int cf_parseline(char *line) {
   int count;
   int slot;
   char chan[CHANNELLEN+1];
+  int type, score;
+  unsigned long hash;
+  time_t lastopped;
   char host[USERLEN+1+HOSTLEN+1];
-  unsigned long type,hash,lastopped,score;
   regop **rolist;
 
-  count = sscanf(line, "%s %lu %lu %lu %lu %s", chan, &type, &hash, &lastopped, &score, host);
+  count = sscanf(line, "%s %d %lu %lu %d %s", chan, &type, &hash, &lastopped, &score, host);
 
   if (count < 5)
     return 0; /* invalid chanfix record */
@@ -1337,11 +1246,7 @@ int cf_parseline(char *line) {
   rolist[slot]->hash = hash;
   rolist[slot]->lastopped = lastopped;
   rolist[slot]->score = score;
-
-  if (count >= 6 && strchr(host, '@') != NULL)
-    rolist[slot]->uh = getsstring(host, USERLEN+1+HOSTLEN);
-  else
-    rolist[slot]->uh = NULL;
+  rolist[slot]->uh = getsstring(host, USERLEN+1+HOSTLEN);
 
   return 1;
 }
@@ -1354,7 +1259,7 @@ int cf_loadchanfix(void) {
 
   cf_free();
 
-  snprintf(srcfile, 300, "%s.0", CFSTORAGE);
+  snprintf(srcfile, sizeof(srcfile), "%s.0", CFSTORAGE);
   cfdata = fopen(srcfile, "r");
 
   if (cfdata == NULL)