]> jfr.im git - irc/quakenet/newserv.git/commitdiff
More chanserv refactoring
authorsplidge <redacted>
Sat, 2 Jun 2007 13:38:06 +0000 (14:38 +0100)
committersplidge <redacted>
Sat, 2 Jun 2007 13:38:06 +0000 (14:38 +0100)
The previously monolithic "chancmds.c", "usercmds.c", and "authcmds.c" files
have been split up into multiple files in new directories "chancmds",
"usercmds" and "authcmds".

Each command source file now has a comment header which contains tags
indicating the name of the command, the level required to use it, the
maximum argument count, a short description and the name of the command
function to be called.  A perl script has been added which reads these tags
and automatically generates a file called "commandlist.c" which sets up
appropriate _init() and _fini() functions for the module.  The perl script
also generates the Makefile, so if you add a command it will be added to the
Makefile automatically.  The perl script will emit warnings if tags are
incomplete and not include that file.

A perl script called "refactor.pl" has been added which assists in the
splitting up process.  This was used to generate the new individual files in
each directory.  You may find it useful if you have locally added your own
commands to one of the old monolithic files and want it to automatically
generate new individual files for you.  Note it's not perfect, in particular
it won't notice if you have defined helper functions as well as your main
command function, so don't overwrite the checked-in version of files with
ones generated by refactor.pl unless you have made changes to the relevant
command and have checked it first.

If you want to register command aliases, create a dummy .c file with
appropriate tags (see authcmds/auth.c for an example).

71 files changed:
chanserv/Makefile
chanserv/authcmds.c [deleted file]
chanserv/authcmds/Makefile [new file with mode: 0644]
chanserv/authcmds/auth.c [new file with mode: 0644]
chanserv/authcmds/commandlist.c [new file with mode: 0644]
chanserv/authcmds/email.c [new file with mode: 0644]
chanserv/authcmds/hello.c [new file with mode: 0644]
chanserv/authcmds/login.c [new file with mode: 0644]
chanserv/authcmds/newpass.c [new file with mode: 0644]
chanserv/authcmds/requestmasterpassword.c [new file with mode: 0644]
chanserv/authcmds/requestpassword.c [new file with mode: 0644]
chanserv/authcmds/setemail.c [new file with mode: 0644]
chanserv/authcmds/setmasterpassword.c [new file with mode: 0644]
chanserv/authcmds/setpassword.c [new file with mode: 0644]
chanserv/authlib.c
chanserv/chancmds.c [deleted file]
chanserv/chancmds/Makefile [new file with mode: 0644]
chanserv/chancmds/addchan.c [new file with mode: 0644]
chanserv/chancmds/adduser.c [new file with mode: 0644]
chanserv/chancmds/autolimit.c [new file with mode: 0644]
chanserv/chancmds/banclear.c [new file with mode: 0644]
chanserv/chancmds/bandel.c [new file with mode: 0644]
chanserv/chancmds/banlist.c [new file with mode: 0644]
chanserv/chancmds/bantimer.c [new file with mode: 0644]
chanserv/chancmds/chanflags.c [new file with mode: 0644]
chanserv/chancmds/chanlev.c [new file with mode: 0644]
chanserv/chancmds/chanmode.c [new file with mode: 0644]
chanserv/chancmds/channelcomment.c [new file with mode: 0644]
chanserv/chancmds/chanstat.c [new file with mode: 0644]
chanserv/chancmds/chantype.c [new file with mode: 0644]
chanserv/chancmds/clearchan.c [new file with mode: 0644]
chanserv/chancmds/commandlist.c [new file with mode: 0644]
chanserv/chancmds/delchan.c [new file with mode: 0644]
chanserv/chancmds/deopall.c [new file with mode: 0644]
chanserv/chancmds/devoiceall.c [new file with mode: 0644]
chanserv/chancmds/invite.c [new file with mode: 0644]
chanserv/chancmds/op.c [new file with mode: 0644]
chanserv/chancmds/permban.c [new file with mode: 0644]
chanserv/chancmds/recover.c [new file with mode: 0644]
chanserv/chancmds/rejoin.c [new file with mode: 0644]
chanserv/chancmds/removeuser.c [new file with mode: 0644]
chanserv/chancmds/renchan.c [new file with mode: 0644]
chanserv/chancmds/settopic.c [new file with mode: 0644]
chanserv/chancmds/suspendchan.c [new file with mode: 0644]
chanserv/chancmds/suspendchanlist.c [new file with mode: 0644]
chanserv/chancmds/tempban.c [new file with mode: 0644]
chanserv/chancmds/unbanall.c [new file with mode: 0644]
chanserv/chancmds/unbanmask.c [new file with mode: 0644]
chanserv/chancmds/unbanme.c [new file with mode: 0644]
chanserv/chancmds/unsuspendchan.c [new file with mode: 0644]
chanserv/chancmds/voice.c [new file with mode: 0644]
chanserv/chancmds/welcome.c [new file with mode: 0644]
chanserv/chanserv.h
chanserv/mkcommandlist.pl [new file with mode: 0755]
chanserv/refactor.pl [new file with mode: 0755]
chanserv/usercmds.c [deleted file]
chanserv/usercmds/Makefile [new file with mode: 0644]
chanserv/usercmds/commandlist.c [new file with mode: 0644]
chanserv/usercmds/deluser.c [new file with mode: 0644]
chanserv/usercmds/info.c [new file with mode: 0644]
chanserv/usercmds/language.c [new file with mode: 0644]
chanserv/usercmds/listflags.c [new file with mode: 0644]
chanserv/usercmds/spewdb.c [new file with mode: 0644]
chanserv/usercmds/spewemail.c [new file with mode: 0644]
chanserv/usercmds/spewpass.c [new file with mode: 0644]
chanserv/usercmds/suspenduser.c [new file with mode: 0644]
chanserv/usercmds/suspenduserlist.c [new file with mode: 0644]
chanserv/usercmds/unsuspenduser.c [new file with mode: 0644]
chanserv/usercmds/usercomment.c [new file with mode: 0644]
chanserv/usercmds/userflags.c [new file with mode: 0644]
chanserv/usercmds/whois.c [new file with mode: 0644]

index b4deed2a71f2031fd22bdfef532ffef2a7c994a4..5661700bf70a1071e11660d4626803c2082f20d5 100644 (file)
@@ -1,9 +1,8 @@
 
-CSDIRS=database
+CSDIRS=database chancmds usercmds authcmds
 
 .PHONY: all dirs clean
-all: chanserv.so chanserv_chancmds.so chanserv_usercmds.so chanserv_protect.so chanserv_auth.so chanserv_grep.so \
-       chanserv_chansearch.so dirs
+all: chanserv.so chanserv_protect.so chanserv_grep.so chanserv_chansearch.so dirs
 
 dirs:
        for i in $(CSDIRS) ; do $(MAKE) -C $$i all ; done
@@ -16,18 +15,9 @@ chanserv.so: chanserv.o chanservuser.o chanservnetevents.o chanservprivs.o chans
                chanservdump.o chanservschedule.o
        ld -shared -Bdynamic ${LIBPGSQL} -o $@ $^
 
-chanserv_chancmds.so: chancmds.o
-       ld -shared -Bdynamic -o $@ $^
-
-chanserv_usercmds.so: usercmds.o
-       ld -shared -Bdynamic -o $@ $^
-
 chanserv_protect.so: chanserv_protect.o
        ld -shared -Bdynamic -o $@ $^
 
-chanserv_auth.so: authcmds.o authlib.o
-       ld -shared -Bdynamic -o $@ $^
-
 chanserv_grep.so: chanservgrep.o
        ld -shared -Bdynamic ${LIBPCRE} -o $@ $^
 
diff --git a/chanserv/authcmds.c b/chanserv/authcmds.c
deleted file mode 100644 (file)
index e85a181..0000000
+++ /dev/null
@@ -1,454 +0,0 @@
-#include "chanserv.h"
-#include "authlib.h"
-#include "../lib/irc_string.h"
-
-#include <stdio.h>
-#include <string.h>
-
-int csa_dohello(void *source, int cargc, char **cargv);
-int csa_doauth(void *source, int cargc, char **cargv);
-int csa_doreqpw(void *source, int cargc, char **cargv);
-int csa_doreqmasterpw(void *source, int cargc, char **cargv);
-int csa_donewpw(void *source, int cargc, char **cargv);
-int csa_doemail(void *source, int cargc, char **cargv);
-int csa_dosetpw(void *source, int cargc, char **cargv);
-int csa_dosetmail(void *source, int cargc, char **cargv);
-int csa_dosetmasterpw(void *source, int cargc, char **cargv);
-
-void _init() {
-  csa_initregex();
-  chanservaddcommand("hello",   QCMD_NOTAUTHED, 2, csa_dohello, "Creates a new user account.");
-  chanservaddcommand("auth",    QCMD_ALIAS | QCMD_SECURE | QCMD_NOTAUTHED, 2, csa_doauth,  "Authenticates you on the bot.");
-  chanservaddcommand("login",   QCMD_SECURE | QCMD_NOTAUTHED, 2, csa_doauth,  "Authenticates you on the bot.");
-  chanservaddcommand("newpass", QCMD_AUTHED, 3, csa_donewpw, "Change your password.");
-  chanservaddcommand("email",   QCMD_AUTHED, 3, csa_doemail, "Change your email address.");
-  chanservaddcommand("requestpassword", QCMD_NOTAUTHED, 2, csa_doreqpw, "Requests the current password by email.");
-  chanservaddcommand("requestmasterpassword", QCMD_AUTHED, 1, csa_doreqmasterpw, "Requests a new master password by email.");
-  chanservaddcommand("setpassword",       QCMD_OPER, 2, csa_dosetpw, "Set a new password.");
-  chanservaddcommand("setemail",          QCMD_OPER, 2, csa_dosetmail, "Set the email address.");
-  chanservaddcommand("setmasterpassword", QCMD_OPER, 2, csa_dosetmasterpw, "Set the master password.");
-//  chanservaddcommand("getpassword",       QCMD_DEV, 2, csa_dogetpw, "Get the password.");
-//  chanservaddcommand("getmasterpassword", QCMD_DEV, 2, csa_dogetmasterpw, "Get the master password.");
-}
-
-void _fini() {
-  csa_freeregex();
-  chanservremovecommand("hello", csa_dohello);
-  chanservremovecommand("auth",  csa_doauth);
-  chanservremovecommand("login",  csa_doauth);
-  chanservremovecommand("requestpassword", csa_doreqpw);
-  chanservremovecommand("requestmasterpassword",  csa_doreqmasterpw);
-  chanservremovecommand("newpass",  csa_donewpw);
-  chanservremovecommand("email",  csa_doemail);
-  chanservremovecommand("setpassword", csa_dosetpw);
-  chanservremovecommand("setemail", csa_dosetmail);
-  chanservremovecommand("setmasterpassword", csa_dosetmasterpw);
-}
-
-/* 
- * check if account is "throttled"
- */
-int csa_checkthrottled(nick *sender, reguser *rup, char *s)
-{
-  time_t now;
-  long d;
-  float t;
-
-  now=time(NULL);
-  d=MAX_RESEND_TIME+rup->lastemailchange-now;
-
-  if (d>MAX_RESEND_TIME)
-    d=MAX_RESEND_TIME;
-
-  if (d>0L) {
-    t = ((float) d) / ((float) 3600);
-    chanservstdmessage(sender, QM_MAILTHROTTLED, t);
-    cs_log(sender,"%s FAIL username %s, new request throttled for %.1f hours",s,rup->username,t);
-    return 1;
-  }
-  return 0;
-}
-
-/*
- * /msg Q HELLO <email address> <email address>
- */
-int csa_dohello(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup;
-  char userhost[USERLEN+HOSTLEN+2];
-
-  if (getreguserfromnick(sender))
-    return CMD_ERROR;
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "hello");
-    return CMD_ERROR;
-  }
-
-  if (findreguserbynick(sender->nick)) {
-    chanservstdmessage(sender, QM_AUTHNAMEINUSE, sender->nick);
-    return CMD_ERROR;
-  }
-
-  if (strcmp(cargv[0],cargv[1])) {
-    chanservstdmessage(sender, QM_EMAILDONTMATCH);
-    cs_log(sender,"HELLO FAIL username %s email don't match (%s vs %s)",sender->nick,cargv[0],cargv[1]);
-    return CMD_ERROR;
-  }
-
-  if (csa_checkeboy(sender, cargv[0]))
-    return CMD_ERROR;
-
-  rup=getreguser();
-  rup->status=0;
-  rup->ID=++lastuserID;
-  strncpy(rup->username,sender->nick,NICKLEN); rup->username[NICKLEN]='\0';
-  rup->created=time(NULL);
-  rup->lastauth=time(NULL);
-  rup->lastemailchange=time(NULL);
-  rup->flags=QUFLAG_NOTICE;
-  rup->languageid=0;
-  rup->suspendby=0;
-  rup->suspendexp=0;
-  rup->password[0]='\0';
-  rup->masterpass[0]='\0';
-  rup->email=getsstring(cargv[0],EMAILLEN);
-  rup->info=NULL;
-  sprintf(userhost,"%s@%s",sender->ident,sender->host->name->content);
-  rup->lastuserhost=getsstring(userhost,USERLEN+HOSTLEN+1);
-  rup->suspendreason=NULL;
-  rup->comment=NULL;
-  rup->knownon=NULL;
-  rup->checkshd=NULL;
-  rup->stealcount=0;
-  rup->fakeuser=NULL;
-  rup->nicks=NULL;
-  addregusertohash(rup);
-  csa_createrandompw(rup->password, PASSLEN);
-  csa_createrandompw(rup->masterpass, PASSLEN);
-  chanservstdmessage(sender, QM_NEWACCOUNT, rup->username,rup->email->content);
-  cs_log(sender,"HELLO OK created auth %s (%s)",rup->username,rup->email->content); 
-  csdb_createuser(rup);
-  csdb_createmail(rup, QMAIL_NEWACCOUNT);
-  return CMD_OK;
-}
-
-/*
- * /msg Q AUTH <account> <password>
- */
-int csa_doauth(void *source, int cargc, char **cargv) {
-  reguser *rup;
-  activeuser* aup;
-  nick *sender=source;
-  nicklist *nl = NULL;
-  char userhost[USERLEN+HOSTLEN+2];
-  int ucount=0;
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "auth");
-    return CMD_ERROR;
-  }
-  
-  if (!(aup = getactiveuserfromnick(sender)))
-    return CMD_ERROR;
-  
-  aup->authattempts++;
-  if (aup->authattempts > MAXAUTHATTEMPT) {
-    if ((aup->authattempts % 100) == 0)
-      chanservwallmessage("Warning: User %s!%s@%s attempted to auth %d times. Last attempt: AUTH %s %s", 
-        nl->np->nick, nl->np->ident, nl->np->host->name->content, cargv[0], cargv[1]);
-    chanservstdmessage(sender, QM_AUTHFAIL);
-    cs_log(sender,"AUTH FAIL too many auth attempts (last attempt: AUTH %s %s)",cargv[0], cargv[1]); 
-    return CMD_ERROR;
-  }
-
-  if (!(rup=findreguserbynick(cargv[0]))) {
-    chanservstdmessage(sender, QM_AUTHFAIL);
-    cs_log(sender,"AUTH FAIL bad username %s",cargv[0]); 
-    return CMD_ERROR;
-  }
-
-  if (!checkpassword(rup, cargv[1])) {
-    chanservstdmessage(sender, QM_AUTHFAIL);
-    cs_log(sender,"AUTH FAIL username %s bad password %s",rup->username,cargv[1]);
-    return CMD_ERROR;
-  }
-
-  rup->lastauth=time(NULL);
-  sprintf(userhost,"%s@%s",sender->ident,sender->host->name->content);
-  if (rup->lastuserhost)
-    freesstring(rup->lastuserhost);
-  rup->lastuserhost=getsstring(userhost,USERLEN+HOSTLEN+1);
-  
-  if (UHasSuspension(rup) && rup->suspendexp && (time(0) >= rup->suspendexp)) {
-    /* suspension has expired, remove it */
-    rup->flags&=(~(QUFLAG_SUSPENDED|QUFLAG_GLINE|QUFLAG_DELAYEDGLINE));
-    rup->suspendby=0;
-    rup->suspendexp=0;
-    freesstring(rup->suspendreason);
-    rup->suspendreason=0;
-  }
-  
-  if (UIsNeedAuth(rup))
-    rup->flags&=~(QUFLAG_NEEDAUTH);
-  csdb_updateuser(rup);
-  
-  if (UIsDelayedGline(rup)) {
-    /* delayed-gline - schedule the user's squelching */
-    deleteschedule(NULL, &chanservdgline, (void*)rup); /* icky, but necessary unless we stick more stuff in reguser structure */
-    scheduleoneshot(time(NULL)+rand()%900, &chanservdgline, (void*)rup);
-  }
-  else if (UIsGline(rup)) {
-    /* instant-gline - lets be lazy and set a schedule expiring now :) */
-    deleteschedule(NULL, &chanservdgline, (void*)rup); /* icky, but necessary unless we stick more stuff in reguser structure */
-    scheduleoneshot(time(NULL), &chanservdgline, (void*)rup);
-  }
-  else if (UIsSuspended(rup)) {
-    /* plain suspend */
-    chanservstdmessage(sender, QM_AUTHSUSPENDED);
-    chanservstdmessage(sender, QM_REASON, rup->suspendreason->content);
-    if (rup->suspendexp) {
-      struct tm* tmp;
-      char buf[200];
-      
-      tmp=gmtime(&(rup->suspendexp));
-      strftime(buf, 15, "%d/%m/%y %H:%M", tmp);
-      chanservstdmessage(sender, QM_EXPIRES, buf);
-    }
-    return CMD_ERROR;
-  }
-  
-  if (!UHasHelperPriv(rup) && !UIsNoAuthLimit(rup)) {
-    for (nl=rup->nicks; nl; nl=nl->next)
-      ucount++;
-    
-    if (ucount >= MAXAUTHCOUNT) {
-      chanservstdmessage(sender, QM_TOOMANYAUTHS);
-      return CMD_ERROR;
-    }
-  }
-  
-  chanservstdmessage(sender, QM_AUTHOK, rup->username);
-  cs_log(sender,"AUTH OK username %s", rup->username);
-  localusersetaccount(sender, rup->username);
-
-  return CMD_OK;
-}
-
-/*
- * /msg Q REQUESTPASSWORD <account> <email>
- */
-int csa_doreqpw(void *source, int cargc, char **cargv) {
-  reguser *rup;
-  nick *sender=source;
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "requestpassword");
-    return CMD_ERROR;
-  }
-
-  if (!(rup=findreguser(sender, cargv[0])))
-    return CMD_ERROR;
-
-  if (ircd_strcmp(cargv[1],rup->email->content)) {
-    chanservstdmessage(sender, QM_BADEMAIL, rup->username);
-    cs_log(sender,"REQUESTPASSWORD FAIL wrong email, username %s email %s",rup->username,cargv[1]);
-    return CMD_ERROR;
-  }
-
-  if (csa_checkthrottled(sender, rup, "REQUESTPASSWORD"))
-    return CMD_ERROR;
-
-  rup->lastemailchange=time(NULL);
-  csdb_updateuser(rup);
-  csdb_createmail(rup, QMAIL_REQPW);
-  chanservstdmessage(sender, QM_MAILQUEUED, rup->username);
-  cs_log(sender,"REQUESTPASSWORD OK username %s email %s", rup->username,rup->email->content);
-
-  return CMD_OK;
-}
-
-/*
- * /msg Q NEWPASS <master password> <new password> <new password>
- */
-int csa_donewpw(void *source, int cargc, char **cargv) {
-  reguser *rup;
-  nick *sender=source;
-
-  if (cargc<3) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "newpass");
-    return CMD_ERROR;
-  }
-
-  if (!(rup=getreguserfromnick(sender)))
-    return CMD_ERROR;
-
-  if (!checkmasterpassword(rup, cargv[0])) {
-    chanservstdmessage(sender, QM_AUTHFAIL);
-    cs_log(sender,"NEWPASS FAIL username %s bad masterpassword %s",rup->username,cargv[0]);
-    return CMD_ERROR;
-  }
-
-  if (strcmp(cargv[1],cargv[2])) {
-    chanservstdmessage(sender, QM_PWDONTMATCH); /* Sorry, passwords do not match */
-    cs_log(sender,"NEWPASS FAIL username %s new passwords don't match (%s vs %s)",rup->username,cargv[1],cargv[2]);
-    return CMD_ERROR;
-  }
-
-  if (strlen(cargv[1]) < 6) {
-    chanservstdmessage(sender, QM_PWTOSHORT); /* new password to short */
-    cs_log(sender,"NEWPASS FAIL username %s password to short %s (%d characters)",rup->username,cargv[1],strlen(cargv[1]));
-    return CMD_ERROR;
-  }
-
-  setpassword(rup, cargv[1]);
-  rup->lastauth=time(NULL);
-  chanservstdmessage(sender, QM_PWCHANGED);
-  cs_log(sender,"NEWPASS OK username %s", rup->username);
-  csdb_updateuser(rup);
-  csdb_createmail(rup, QMAIL_NEWPW);
-
-  return CMD_OK;
-}
-
-/*
- * /msg Q REQUESTMASTERPASSWORD
- */
-int csa_doreqmasterpw(void *source, int cargc, char **cargv) {
-  reguser *rup;
-  nick *sender=source;
-
-  if (!(rup=getreguserfromnick(sender)))
-    return CMD_ERROR;
-
-  if (csa_checkthrottled(sender, rup, "REQUESTMASTERPASSWORD"))
-    return CMD_ERROR;
-
-  csa_createrandompw(rup->masterpass, PASSLEN);
-  chanservstdmessage(sender, QM_MASTERPWCHANGED);
-  cs_log(sender,"REQUESTMASTERPASSWORD OK username %s",rup->username);
-  csdb_updateuser(rup);
-  csdb_createmail(rup, QMAIL_NEWMASTERPW);
-
-  return CMD_OK;
-}
-
-/*
- * /msg Q EMAIL <master password> <email address> <email address>
- */
-int csa_doemail(void *source, int cargc, char **cargv) {
-  reguser *rup;
-  nick *sender=source;
-
-  if (cargc<3) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "email");
-    return CMD_ERROR;
-  }
-
-  if (!(rup=getreguserfromnick(sender)))
-    return CMD_ERROR;
-
-  if (!checkmasterpassword(rup, cargv[0])) {
-    chanservstdmessage(sender, QM_AUTHFAIL);
-    cs_log(sender,"EMAIL FAIL username %s bad masterpass %s",rup->username,cargv[0]);
-    return CMD_ERROR;
-  }
-
-  if (strcmp(cargv[1],cargv[2])) {
-    chanservstdmessage(sender, QM_EMAILDONTMATCH);
-    cs_log(sender,"EMAIL FAIL username %s email don't match (%s vs %s)",rup->username,cargv[1],cargv[2]);
-    return CMD_ERROR;
-  }
-
-  if (csa_checkeboy(sender, cargv[1]))
-    return CMD_ERROR;
-
-//  rup2->ID = rup->ID;
-//  rup2->email=getsstring(rup->email->content,EMAILLEN); /* save previous email addy */
-
-  csdb_createmail(rup, QMAIL_NEWEMAIL);
-  freesstring(rup->email);
-  rup->email=getsstring(cargv[1],EMAILLEN);
-  rup->lastemailchange=time(NULL);
-  chanservstdmessage(sender, QM_EMAILCHANGED, cargv[1]);
-  cs_log(sender,"EMAIL OK username %s",rup->username);
-  csdb_updateuser(rup);
-
-  return CMD_OK;
-}
-
-/*
- * /msg Q SETPASSWORD <account> <new password>
- */
-int csa_dosetpw(void *source, int cargc, char **cargv) {
-  reguser *rup;
-  nick *sender=source;
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "setpassword");
-    return CMD_ERROR;
-  }
-
-  if (!(rup=findreguser(sender, cargv[0])))
-    return CMD_ERROR;
-
-  strncpy(rup->password,cargv[1],PASSLEN);
-  rup->password[PASSLEN]='\0';
-  chanservstdmessage(sender, QM_PWCHANGED);
-  cs_log(sender,"SETPASSWORD OK username %s",rup->username);
-  csdb_updateuser(rup);
-
-  return CMD_OK;
-}
-
-/*
- * /msg Q SETEMAIL <account> <email address>
- */
-int csa_dosetmail(void *source, int cargc, char **cargv) {
-  reguser *rup;
-  nick *sender=source;
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "setemail");
-    return CMD_ERROR;
-  }
-
-  if (!(rup=findreguser(sender, cargv[0])))
-    return CMD_ERROR;
-
-  if (csa_checkeboy(sender, cargv[1]))
-    return CMD_ERROR;
-
-  freesstring(rup->email);
-  rup->email=getsstring(cargv[1],EMAILLEN);
-  rup->lastemailchange=time(NULL);
-  chanservstdmessage(sender, QM_EMAILCHANGED, cargv[1]);
-  cs_log(sender,"SETEMAIL OK username %s <%s>",rup->username,rup->email->content);
-  csdb_updateuser(rup);
-
-  return CMD_OK;
-}
-
-/*
- * /msg Q SETMASTERPASSWORD <account>
- */
-int csa_dosetmasterpw(void *source, int cargc, char **cargv) {
-  reguser *rup;
-  nick *sender=source;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "setmasterpassword");
-    return CMD_ERROR;
-  }
-
-  if (!(rup=findreguser(sender, cargv[0])))
-    return CMD_ERROR;
-
-  csa_createrandompw(rup->masterpass, PASSLEN);
-  chanservstdmessage(sender, QM_MASTERPWCHANGED);
-  cs_log(sender,"SETMASTERPASSWORD OK username %s",rup->username);
-  csdb_updateuser(rup);
-
-  return CMD_OK;
-}
diff --git a/chanserv/authcmds/Makefile b/chanserv/authcmds/Makefile
new file mode 100644 (file)
index 0000000..0dbad60
--- /dev/null
@@ -0,0 +1,10 @@
+# Automatically generated Makefile, do not edit.
+
+.PHONY: all Makefile
+all: Makefile chanserv_authcmds.so
+
+Makefile:
+       ../mkcommandlist.pl chanserv_authcmds.so
+
+chanserv_authcmds.so: auth.o email.o hello.o login.o newpass.o requestmasterpassword.o requestpassword.o setemail.o setmasterpassword.o setpassword.o commandlist.o 
+        ld -shared -Bdynamic -o $@ $^ 
diff --git a/chanserv/authcmds/auth.c b/chanserv/authcmds/auth.c
new file mode 100644 (file)
index 0000000..4fff1b5
--- /dev/null
@@ -0,0 +1,12 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: auth
+ * CMDLEVEL: QCMD_ALIAS | QCMD_SECURE | QCMD_NOTAUTHED
+ * CMDARGS: 2
+ * CMDDESC: Authenticates you on the bot.
+ * CMDFUNC: csa_doauth
+ * CMDPROTO: int csa_doauth(void *source, int cargc, char **cargv);
+ */
+
+/* Actual function is in login.c */
diff --git a/chanserv/authcmds/commandlist.c b/chanserv/authcmds/commandlist.c
new file mode 100644 (file)
index 0000000..2e53ba1
--- /dev/null
@@ -0,0 +1,41 @@
+/* Automatically generated by mkcommandlist.pl, do not edit. */
+
+#include "../chanserv.h"
+
+/* Prototypes */
+int csa_doauth(void *source, int cargc, char **cargv);
+int csa_doemail(void *source, int cargc, char **cargv);
+int csa_dohello(void *source, int cargc, char **cargv);
+int csa_doauth(void *source, int cargc, char **cargv);
+int csa_donewpw(void *source, int cargc, char **cargv);
+int csa_doreqmasterpw(void *source, int cargc, char **cargv);
+int csa_doreqpw(void *source, int cargc, char **cargv);
+int csa_dosetmail(void *source, int cargc, char **cargv);
+int csa_dosetmasterpw(void *source, int cargc, char **cargv);
+int csa_dosetpw(void *source, int cargc, char **cargv);
+
+void _init() {
+  chanservaddcommand("auth", QCMD_ALIAS | QCMD_SECURE | QCMD_NOTAUTHED, 2, csa_doauth, "Authenticates you on the bot.");
+  chanservaddcommand("email", QCMD_AUTHED, 3, csa_doemail, "Change your email address.");
+  chanservaddcommand("hello", QCMD_NOTAUTHED, 2, csa_dohello, "Creates a new user account.");
+  chanservaddcommand("login", QCMD_SECURE | QCMD_NOTAUTHED, 2, csa_doauth, "Authenticates you on the bot.");
+  chanservaddcommand("newpass", QCMD_AUTHED, 3, csa_donewpw, "Change your password.");
+  chanservaddcommand("requestmasterpassword", QCMD_AUTHED, 1, csa_doreqmasterpw, "Requests a new master password by email.");
+  chanservaddcommand("requestpassword", QCMD_NOTAUTHED, 2, csa_doreqpw, "Requests the current password by email.");
+  chanservaddcommand("setemail", QCMD_OPER, 2, csa_dosetmail, "Set the email address.");
+  chanservaddcommand("setmasterpassword", QCMD_OPER, 2, csa_dosetmasterpw, "Set the master password.");
+  chanservaddcommand("setpassword", QCMD_OPER, 2, csa_dosetpw, "Set a new password.");
+}
+
+void _fini() {
+  chanservremovecommand("auth", csa_doauth);
+  chanservremovecommand("email", csa_doemail);
+  chanservremovecommand("hello", csa_dohello);
+  chanservremovecommand("login", csa_doauth);
+  chanservremovecommand("newpass", csa_donewpw);
+  chanservremovecommand("requestmasterpassword", csa_doreqmasterpw);
+  chanservremovecommand("requestpassword", csa_doreqpw);
+  chanservremovecommand("setemail", csa_dosetmail);
+  chanservremovecommand("setmasterpassword", csa_dosetmasterpw);
+  chanservremovecommand("setpassword", csa_dosetpw);
+}
diff --git a/chanserv/authcmds/email.c b/chanserv/authcmds/email.c
new file mode 100644 (file)
index 0000000..402a22f
--- /dev/null
@@ -0,0 +1,57 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: email
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 3
+ * CMDDESC: Change your email address.
+ * CMDFUNC: csa_doemail
+ * CMDPROTO: int csa_doemail(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../authlib.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csa_doemail(void *source, int cargc, char **cargv) {
+  reguser *rup;
+  nick *sender=source;
+
+  if (cargc<3) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "email");
+    return CMD_ERROR;
+  }
+
+  if (!(rup=getreguserfromnick(sender)))
+    return CMD_ERROR;
+
+  if (!checkmasterpassword(rup, cargv[0])) {
+    chanservstdmessage(sender, QM_AUTHFAIL);
+    cs_log(sender,"EMAIL FAIL username %s bad masterpass %s",rup->username,cargv[0]);
+    return CMD_ERROR;
+  }
+
+  if (strcmp(cargv[1],cargv[2])) {
+    chanservstdmessage(sender, QM_EMAILDONTMATCH);
+    cs_log(sender,"EMAIL FAIL username %s email don't match (%s vs %s)",rup->username,cargv[1],cargv[2]);
+    return CMD_ERROR;
+  }
+
+  if (csa_checkeboy(sender, cargv[1]))
+    return CMD_ERROR;
+
+//  rup2->ID = rup->ID;
+//  rup2->email=getsstring(rup->email->content,EMAILLEN); /* save previous email addy */
+
+  csdb_createmail(rup, QMAIL_NEWEMAIL);
+  freesstring(rup->email);
+  rup->email=getsstring(cargv[1],EMAILLEN);
+  rup->lastemailchange=time(NULL);
+  chanservstdmessage(sender, QM_EMAILCHANGED, cargv[1]);
+  cs_log(sender,"EMAIL OK username %s",rup->username);
+  csdb_updateuser(rup);
+
+  return CMD_OK;
+}
diff --git a/chanserv/authcmds/hello.c b/chanserv/authcmds/hello.c
new file mode 100644 (file)
index 0000000..3ae7299
--- /dev/null
@@ -0,0 +1,78 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: hello
+ * CMDLEVEL: QCMD_NOTAUTHED
+ * CMDARGS: 2
+ * CMDDESC: Creates a new user account.
+ * CMDFUNC: csa_dohello
+ * CMDPROTO: int csa_dohello(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../authlib.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csa_dohello(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup;
+  char userhost[USERLEN+HOSTLEN+2];
+
+  if (getreguserfromnick(sender))
+    return CMD_ERROR;
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "hello");
+    return CMD_ERROR;
+  }
+
+  if (findreguserbynick(sender->nick)) {
+    chanservstdmessage(sender, QM_AUTHNAMEINUSE, sender->nick);
+    return CMD_ERROR;
+  }
+
+  if (strcmp(cargv[0],cargv[1])) {
+    chanservstdmessage(sender, QM_EMAILDONTMATCH);
+    cs_log(sender,"HELLO FAIL username %s email don't match (%s vs %s)",sender->nick,cargv[0],cargv[1]);
+    return CMD_ERROR;
+  }
+
+  if (csa_checkeboy(sender, cargv[0]))
+    return CMD_ERROR;
+
+  rup=getreguser();
+  rup->status=0;
+  rup->ID=++lastuserID;
+  strncpy(rup->username,sender->nick,NICKLEN); rup->username[NICKLEN]='\0';
+  rup->created=time(NULL);
+  rup->lastauth=time(NULL);
+  rup->lastemailchange=time(NULL);
+  rup->flags=QUFLAG_NOTICE;
+  rup->languageid=0;
+  rup->suspendby=0;
+  rup->suspendexp=0;
+  rup->password[0]='\0';
+  rup->masterpass[0]='\0';
+  rup->email=getsstring(cargv[0],EMAILLEN);
+  rup->info=NULL;
+  sprintf(userhost,"%s@%s",sender->ident,sender->host->name->content);
+  rup->lastuserhost=getsstring(userhost,USERLEN+HOSTLEN+1);
+  rup->suspendreason=NULL;
+  rup->comment=NULL;
+  rup->knownon=NULL;
+  rup->checkshd=NULL;
+  rup->stealcount=0;
+  rup->fakeuser=NULL;
+  rup->nicks=NULL;
+  addregusertohash(rup);
+  csa_createrandompw(rup->password, PASSLEN);
+  csa_createrandompw(rup->masterpass, PASSLEN);
+  chanservstdmessage(sender, QM_NEWACCOUNT, rup->username,rup->email->content);
+  cs_log(sender,"HELLO OK created auth %s (%s)",rup->username,rup->email->content); 
+  csdb_createuser(rup);
+  csdb_createmail(rup, QMAIL_NEWACCOUNT);
+  return CMD_OK;
+}
diff --git a/chanserv/authcmds/login.c b/chanserv/authcmds/login.c
new file mode 100644 (file)
index 0000000..dd837ee
--- /dev/null
@@ -0,0 +1,115 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: login
+ * CMDLEVEL: QCMD_SECURE | QCMD_NOTAUTHED
+ * CMDARGS: 2
+ * CMDDESC: Authenticates you on the bot.
+ * CMDFUNC: csa_doauth
+ * CMDPROTO: int csa_doauth(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../authlib.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csa_doauth(void *source, int cargc, char **cargv) {
+  reguser *rup;
+  activeuser* aup;
+  nick *sender=source;
+  nicklist *nl = NULL;
+  char userhost[USERLEN+HOSTLEN+2];
+  int ucount=0;
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "auth");
+    return CMD_ERROR;
+  }
+  
+  if (!(aup = getactiveuserfromnick(sender)))
+    return CMD_ERROR;
+  
+  aup->authattempts++;
+  if (aup->authattempts > MAXAUTHATTEMPT) {
+    if ((aup->authattempts % 100) == 0)
+      chanservwallmessage("Warning: User %s!%s@%s attempted to auth %d times. Last attempt: AUTH %s %s", 
+        nl->np->nick, nl->np->ident, nl->np->host->name->content, cargv[0], cargv[1]);
+    chanservstdmessage(sender, QM_AUTHFAIL);
+    cs_log(sender,"AUTH FAIL too many auth attempts (last attempt: AUTH %s %s)",cargv[0], cargv[1]); 
+    return CMD_ERROR;
+  }
+
+  if (!(rup=findreguserbynick(cargv[0]))) {
+    chanservstdmessage(sender, QM_AUTHFAIL);
+    cs_log(sender,"AUTH FAIL bad username %s",cargv[0]); 
+    return CMD_ERROR;
+  }
+
+  if (!checkpassword(rup, cargv[1])) {
+    chanservstdmessage(sender, QM_AUTHFAIL);
+    cs_log(sender,"AUTH FAIL username %s bad password %s",rup->username,cargv[1]);
+    return CMD_ERROR;
+  }
+
+  rup->lastauth=time(NULL);
+  sprintf(userhost,"%s@%s",sender->ident,sender->host->name->content);
+  if (rup->lastuserhost)
+    freesstring(rup->lastuserhost);
+  rup->lastuserhost=getsstring(userhost,USERLEN+HOSTLEN+1);
+  
+  if (UHasSuspension(rup) && rup->suspendexp && (time(0) >= rup->suspendexp)) {
+    /* suspension has expired, remove it */
+    rup->flags&=(~(QUFLAG_SUSPENDED|QUFLAG_GLINE|QUFLAG_DELAYEDGLINE));
+    rup->suspendby=0;
+    rup->suspendexp=0;
+    freesstring(rup->suspendreason);
+    rup->suspendreason=0;
+  }
+  
+  if (UIsNeedAuth(rup))
+    rup->flags&=~(QUFLAG_NEEDAUTH);
+  csdb_updateuser(rup);
+  
+  if (UIsDelayedGline(rup)) {
+    /* delayed-gline - schedule the user's squelching */
+    deleteschedule(NULL, &chanservdgline, (void*)rup); /* icky, but necessary unless we stick more stuff in reguser structure */
+    scheduleoneshot(time(NULL)+rand()%900, &chanservdgline, (void*)rup);
+  }
+  else if (UIsGline(rup)) {
+    /* instant-gline - lets be lazy and set a schedule expiring now :) */
+    deleteschedule(NULL, &chanservdgline, (void*)rup); /* icky, but necessary unless we stick more stuff in reguser structure */
+    scheduleoneshot(time(NULL), &chanservdgline, (void*)rup);
+  }
+  else if (UIsSuspended(rup)) {
+    /* plain suspend */
+    chanservstdmessage(sender, QM_AUTHSUSPENDED);
+    chanservstdmessage(sender, QM_REASON, rup->suspendreason->content);
+    if (rup->suspendexp) {
+      struct tm* tmp;
+      char buf[200];
+      
+      tmp=gmtime(&(rup->suspendexp));
+      strftime(buf, 15, "%d/%m/%y %H:%M", tmp);
+      chanservstdmessage(sender, QM_EXPIRES, buf);
+    }
+    return CMD_ERROR;
+  }
+  
+  if (!UHasHelperPriv(rup) && !UIsNoAuthLimit(rup)) {
+    for (nl=rup->nicks; nl; nl=nl->next)
+      ucount++;
+    
+    if (ucount >= MAXAUTHCOUNT) {
+      chanservstdmessage(sender, QM_TOOMANYAUTHS);
+      return CMD_ERROR;
+    }
+  }
+  
+  chanservstdmessage(sender, QM_AUTHOK, rup->username);
+  cs_log(sender,"AUTH OK username %s", rup->username);
+  localusersetaccount(sender, rup->username);
+
+  return CMD_OK;
+}
diff --git a/chanserv/authcmds/newpass.c b/chanserv/authcmds/newpass.c
new file mode 100644 (file)
index 0000000..40fa51a
--- /dev/null
@@ -0,0 +1,56 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: newpass
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 3
+ * CMDDESC: Change your password.
+ * CMDFUNC: csa_donewpw
+ * CMDPROTO: int csa_donewpw(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../authlib.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csa_donewpw(void *source, int cargc, char **cargv) {
+  reguser *rup;
+  nick *sender=source;
+
+  if (cargc<3) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "newpass");
+    return CMD_ERROR;
+  }
+
+  if (!(rup=getreguserfromnick(sender)))
+    return CMD_ERROR;
+
+  if (!checkmasterpassword(rup, cargv[0])) {
+    chanservstdmessage(sender, QM_AUTHFAIL);
+    cs_log(sender,"NEWPASS FAIL username %s bad masterpassword %s",rup->username,cargv[0]);
+    return CMD_ERROR;
+  }
+
+  if (strcmp(cargv[1],cargv[2])) {
+    chanservstdmessage(sender, QM_PWDONTMATCH); /* Sorry, passwords do not match */
+    cs_log(sender,"NEWPASS FAIL username %s new passwords don't match (%s vs %s)",rup->username,cargv[1],cargv[2]);
+    return CMD_ERROR;
+  }
+
+  if (strlen(cargv[1]) < 6) {
+    chanservstdmessage(sender, QM_PWTOSHORT); /* new password to short */
+    cs_log(sender,"NEWPASS FAIL username %s password to short %s (%d characters)",rup->username,cargv[1],strlen(cargv[1]));
+    return CMD_ERROR;
+  }
+
+  setpassword(rup, cargv[1]);
+  rup->lastauth=time(NULL);
+  chanservstdmessage(sender, QM_PWCHANGED);
+  cs_log(sender,"NEWPASS OK username %s", rup->username);
+  csdb_updateuser(rup);
+  csdb_createmail(rup, QMAIL_NEWPW);
+
+  return CMD_OK;
+}
diff --git a/chanserv/authcmds/requestmasterpassword.c b/chanserv/authcmds/requestmasterpassword.c
new file mode 100644 (file)
index 0000000..c5bb4e3
--- /dev/null
@@ -0,0 +1,35 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: requestmasterpassword
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Requests a new master password by email.
+ * CMDFUNC: csa_doreqmasterpw
+ * CMDPROTO: int csa_doreqmasterpw(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../authlib.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csa_doreqmasterpw(void *source, int cargc, char **cargv) {
+  reguser *rup;
+  nick *sender=source;
+
+  if (!(rup=getreguserfromnick(sender)))
+    return CMD_ERROR;
+
+  if (csa_checkthrottled(sender, rup, "REQUESTMASTERPASSWORD"))
+    return CMD_ERROR;
+
+  csa_createrandompw(rup->masterpass, PASSLEN);
+  chanservstdmessage(sender, QM_MASTERPWCHANGED);
+  cs_log(sender,"REQUESTMASTERPASSWORD OK username %s",rup->username);
+  csdb_updateuser(rup);
+  csdb_createmail(rup, QMAIL_NEWMASTERPW);
+
+  return CMD_OK;
+}
diff --git a/chanserv/authcmds/requestpassword.c b/chanserv/authcmds/requestpassword.c
new file mode 100644 (file)
index 0000000..fe0f0fc
--- /dev/null
@@ -0,0 +1,46 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: requestpassword
+ * CMDLEVEL: QCMD_NOTAUTHED
+ * CMDARGS: 2
+ * CMDDESC: Requests the current password by email.
+ * CMDFUNC: csa_doreqpw
+ * CMDPROTO: int csa_doreqpw(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../authlib.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csa_doreqpw(void *source, int cargc, char **cargv) {
+  reguser *rup;
+  nick *sender=source;
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "requestpassword");
+    return CMD_ERROR;
+  }
+
+  if (!(rup=findreguser(sender, cargv[0])))
+    return CMD_ERROR;
+
+  if (ircd_strcmp(cargv[1],rup->email->content)) {
+    chanservstdmessage(sender, QM_BADEMAIL, rup->username);
+    cs_log(sender,"REQUESTPASSWORD FAIL wrong email, username %s email %s",rup->username,cargv[1]);
+    return CMD_ERROR;
+  }
+
+  if (csa_checkthrottled(sender, rup, "REQUESTPASSWORD"))
+    return CMD_ERROR;
+
+  rup->lastemailchange=time(NULL);
+  csdb_updateuser(rup);
+  csdb_createmail(rup, QMAIL_REQPW);
+  chanservstdmessage(sender, QM_MAILQUEUED, rup->username);
+  cs_log(sender,"REQUESTPASSWORD OK username %s email %s", rup->username,rup->email->content);
+
+  return CMD_OK;
+}
diff --git a/chanserv/authcmds/setemail.c b/chanserv/authcmds/setemail.c
new file mode 100644 (file)
index 0000000..4255f99
--- /dev/null
@@ -0,0 +1,41 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: setemail
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 2
+ * CMDDESC: Set the email address.
+ * CMDFUNC: csa_dosetmail
+ * CMDPROTO: int csa_dosetmail(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../authlib.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csa_dosetmail(void *source, int cargc, char **cargv) {
+  reguser *rup;
+  nick *sender=source;
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "setemail");
+    return CMD_ERROR;
+  }
+
+  if (!(rup=findreguser(sender, cargv[0])))
+    return CMD_ERROR;
+
+  if (csa_checkeboy(sender, cargv[1]))
+    return CMD_ERROR;
+
+  freesstring(rup->email);
+  rup->email=getsstring(cargv[1],EMAILLEN);
+  rup->lastemailchange=time(NULL);
+  chanservstdmessage(sender, QM_EMAILCHANGED, cargv[1]);
+  cs_log(sender,"SETEMAIL OK username %s <%s>",rup->username,rup->email->content);
+  csdb_updateuser(rup);
+
+  return CMD_OK;
+}
diff --git a/chanserv/authcmds/setmasterpassword.c b/chanserv/authcmds/setmasterpassword.c
new file mode 100644 (file)
index 0000000..41af500
--- /dev/null
@@ -0,0 +1,36 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: setmasterpassword
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 2
+ * CMDDESC: Set the master password.
+ * CMDFUNC: csa_dosetmasterpw
+ * CMDPROTO: int csa_dosetmasterpw(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../authlib.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csa_dosetmasterpw(void *source, int cargc, char **cargv) {
+  reguser *rup;
+  nick *sender=source;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "setmasterpassword");
+    return CMD_ERROR;
+  }
+
+  if (!(rup=findreguser(sender, cargv[0])))
+    return CMD_ERROR;
+
+  csa_createrandompw(rup->masterpass, PASSLEN);
+  chanservstdmessage(sender, QM_MASTERPWCHANGED);
+  cs_log(sender,"SETMASTERPASSWORD OK username %s",rup->username);
+  csdb_updateuser(rup);
+
+  return CMD_OK;
+}
diff --git a/chanserv/authcmds/setpassword.c b/chanserv/authcmds/setpassword.c
new file mode 100644 (file)
index 0000000..c6384bd
--- /dev/null
@@ -0,0 +1,37 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: setpassword
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 2
+ * CMDDESC: Set a new password.
+ * CMDFUNC: csa_dosetpw
+ * CMDPROTO: int csa_dosetpw(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../authlib.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csa_dosetpw(void *source, int cargc, char **cargv) {
+  reguser *rup;
+  nick *sender=source;
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "setpassword");
+    return CMD_ERROR;
+  }
+
+  if (!(rup=findreguser(sender, cargv[0])))
+    return CMD_ERROR;
+
+  strncpy(rup->password,cargv[1],PASSLEN);
+  rup->password[PASSLEN]='\0';
+  chanservstdmessage(sender, QM_PWCHANGED);
+  cs_log(sender,"SETPASSWORD OK username %s",rup->username);
+  csdb_updateuser(rup);
+
+  return CMD_OK;
+}
index 3d7101bcf58a3c13628364bd198aaf81e6d7c580..f257fef1543a94e7c98aa78919c564df9af29b6b 100644 (file)
@@ -90,3 +90,27 @@ void csa_createrandompw(char *pw, int n)
   }
   pw[n] = '\0';
 }
+
+/*
+ * check if account is "throttled"
+ */
+int csa_checkthrottled(nick *sender, reguser *rup, char *s)
+{
+  time_t now;
+  long d;
+  float t;
+
+  now=time(NULL);
+  d=MAX_RESEND_TIME+rup->lastemailchange-now;
+
+  if (d>MAX_RESEND_TIME)
+    d=MAX_RESEND_TIME;
+
+  if (d>0L) {
+    t = ((float) d) / ((float) 3600);
+    chanservstdmessage(sender, QM_MAILTHROTTLED, t);
+    cs_log(sender,"%s FAIL username %s, new request throttled for %.1f hours",s,rup->username,t);
+    return 1;
+  }
+  return 0;
+}
diff --git a/chanserv/chancmds.c b/chanserv/chancmds.c
deleted file mode 100644 (file)
index d9f8b9d..0000000
+++ /dev/null
@@ -1,2170 +0,0 @@
-/*
- * chancmds.c:
- *  Provides basic channel commands:
- *   CHANLEV
- *   WHOIS
- *   CHANFLAGS
- * etc.
- */
-#include "chanserv.h"
-#include "../nick/nick.h"
-#include "../lib/flags.h"
-#include "../lib/irc_string.h"
-#include "../channel/channel.h"
-#include "../parser/parser.h"
-#include "../irc/irc.h"
-#include "../localuser/localuserchannel.h"
-
-#include <string.h>
-#include <stdio.h>
-
-int csc_dochanlev(void *source, int cargc, char **cargv);
-int csc_dochanflags(void *source, int cargc, char **cargv);
-int csc_dochanmode(void *source, int cargc, char **cargv);
-int csc_doautolimit(void *source, int cargc, char **cargv);
-int csc_dobantimer(void *source, int cargc, char **cargv);
-int csc_doaddchan(void *source, int cargc, char **cargv);
-int csc_dosuspendchan(void *source, int cargc, char **cargv);
-int csc_dosuspendchanlist(void *source, int cargc, char **cargv);
-int csc_dounsuspendchan(void *source, int cargc, char **cargv);
-int csc_dodelchan(void *source, int cargc, char **cargv);
-int csc_dorenchan(void *source, int cargc, char **cargv);
-int csc_dowelcome(void *source, int cargc, char **cargv);
-int csc_doinvite(void *source, int cargc, char **cargv);
-int csc_doop(void *source, int cargc, char **cargv);
-int csc_dovoice(void *source, int cargc, char **cargv);
-int csc_dodeopall(void *source, int cargc, char **cargv);
-int csc_dounbanall(void *source, int cargc, char **cargv);
-int csc_doclearchan(void *source, int cargc, char **cargv);
-int csc_dorecover(void *source, int cargc, char **cargv);
-int csc_dounbanme(void *source, int cargc, char **cargv);
-int csc_dodevoiceall(void *source, int cargc, char **cargv);
-int csc_dosettopic(void *source, int cargc, char **cargv);
-int csc_dopermban(void *source, int cargc, char **cargv);
-int csc_dotempban(void *source, int cargc, char **cargv);
-int csc_dobanlist(void *source, int cargc, char **cargv);
-int csc_dounbanmask(void *source, int cargc, char **cargv);
-int csc_dobandel(void *source, int cargc, char **cargv);
-int csc_dochannelcomment(void *source, int cargc, char **cargv);
-int csc_dorejoin(void *source, int cargc, char **cargv);
-int csc_doadduser(void *source, int cargc, char **cargv);
-int csc_doremoveuser(void *source, int cargc, char **cargv);
-int csc_dobanclear(void *source, int cargc, char **cargv);
-int csc_dochantype(void *source, int cargc, char **cargv);
-int csc_dochanstat(void *source, int cargc, char **cargv);
-
-char *getchanmode(regchan *rcp);
-
-void _init() {
-  chanservaddcommand("chanflags", QCMD_AUTHED, 2, csc_dochanflags, "Shows or changes the flags on a channel.");
-  chanservaddcommand("chanmode",  QCMD_AUTHED, 4, csc_dochanmode,  "Shows which modes are forced or denied on a channel.");
-  chanservaddcommand("chanlev",   QCMD_AUTHED, 3, csc_dochanlev,   "Shows or modifies user access on a channel.");
-  chanservaddcommand("autolimit", QCMD_AUTHED, 2, csc_doautolimit, "Shows or changes the autolimit threshold on a channel.");
-  chanservaddcommand("bantimer",  QCMD_AUTHED, 2, csc_dobantimer,  "Shows or changes the time after which bans are removed.");
-  chanservaddcommand("addchan",   QCMD_OPER,   4, csc_doaddchan,   "Adds a new channel to the bot.");
-  chanservaddcommand("suspendchan",   QCMD_OPER,   2, csc_dosuspendchan,   "Suspends a channel from the bot.");
-  chanservaddcommand("suspendchanlist", QCMD_HELPER, 1, csc_dosuspendchanlist,   "Lists suspended channels.");
-  chanservaddcommand("unsuspendchan", QCMD_OPER,   1, csc_dounsuspendchan, "Unsuspends a channel from the bot.");
-  chanservaddcommand("delchan",   QCMD_OPER,   2, csc_dodelchan,   "Removes a channel from the bot.");
-  chanservaddcommand("renchan",   QCMD_OPER,   2, csc_dorenchan,   "Renames a channel on the bot.");
-  chanservaddcommand("welcome",   QCMD_AUTHED, 2, csc_dowelcome,   "Shows or changes the welcome message on a channel.");
-  chanservaddcommand("invite",    QCMD_AUTHED, 1, csc_doinvite,    "Invites you to a channel.");
-  chanservaddcommand("op",        QCMD_AUTHED, 20,csc_doop,        "Ops you or other users on channel(s).");
-  chanservaddcommand("voice",     QCMD_AUTHED, 20,csc_dovoice,     "Voices you or other users on channel(s).");
-  chanservaddcommand("deopall",   QCMD_AUTHED, 1, csc_dodeopall,   "Deops all users on channel.");
-  chanservaddcommand("devoiceall",QCMD_AUTHED, 1, csc_dodevoiceall,"Devoices all users on a channel.");
-  chanservaddcommand("unbanall",  QCMD_AUTHED, 1, csc_dounbanall,  "Removes all bans from a channel.");
-  chanservaddcommand("unbanme",   QCMD_AUTHED, 1, csc_dounbanme,   "Removes any bans affecting you from a channel.");
-  chanservaddcommand("clearchan", QCMD_AUTHED, 1, csc_doclearchan, "Removes all modes from a channel.");
-  chanservaddcommand("recover",   QCMD_AUTHED, 1, csc_dorecover,   "Recovers a channel (same as deopall, unbanall, clearchan).");
-  chanservaddcommand("settopic",  QCMD_AUTHED, 2, csc_dosettopic,  "Changes the topic on a channel.");
-  chanservaddcommand("permban",   QCMD_AUTHED, 3, csc_dopermban,   "Permanently bans a hostmask on a channel.");
-  chanservaddcommand("tempban",   QCMD_AUTHED, 4, csc_dotempban,   "Bans a hostmask on a channel for a specified time period.");
-  chanservaddcommand("banlist",   QCMD_AUTHED, 1, csc_dobanlist,   "Displays all persistent bans on a channel.");
-  chanservaddcommand("unbanmask", QCMD_AUTHED, 2, csc_dounbanmask, "Removes bans matching a particular mask from a channel.");
-  chanservaddcommand("bandel",    QCMD_AUTHED, 2, csc_dobandel,    "Removes a single ban from a channel.");
-  chanservaddcommand("banclear",  QCMD_AUTHED, 1, csc_dobanclear,  "Removes all bans from a channel including persistent bans.");
-  chanservaddcommand("channelcomment",QCMD_OPER,2,csc_dochannelcomment,"Shows or changes the staff comment for a channel.");
-  chanservaddcommand("rejoin",    QCMD_OPER,   1, csc_dorejoin,    "Makes the bot rejoin a channel.");
-  chanservaddcommand("adduser",   QCMD_AUTHED, 20,csc_doadduser,   "Adds one or more users to a channel as +aot.");
-  chanservaddcommand("removeuser",QCMD_AUTHED, 20,csc_doremoveuser,"Removes one or more users from a channel.");
-  chanservaddcommand("chantype",  QCMD_OPER,    2,csc_dochantype,  "Shows or changes a channel's type.");
-  chanservaddcommand("chanstat",  QCMD_AUTHED,  1,csc_dochanstat,  "Displays channel activity statistics.");
-}
-
-void _fini() {
-  chanservremovecommand("chanflags", csc_dochanflags);
-  chanservremovecommand("chanmode",  csc_dochanmode);
-  chanservremovecommand("chanlev",   csc_dochanlev);
-  chanservremovecommand("autolimit", csc_doautolimit);
-  chanservremovecommand("bantimer",  csc_dobantimer);
-  chanservremovecommand("addchan",   csc_doaddchan);
-  chanservremovecommand("suspendchan",csc_dosuspendchan);
-  chanservremovecommand("suspendchanlist",csc_dosuspendchanlist);
-  chanservremovecommand("unsuspendchan",csc_dounsuspendchan);
-  chanservremovecommand("delchan",   csc_dodelchan);
-  chanservremovecommand("renchan",   csc_dorenchan);
-  chanservremovecommand("welcome",   csc_dowelcome);
-  chanservremovecommand("invite",    csc_doinvite);
-  chanservremovecommand("op",        csc_doop);
-  chanservremovecommand("voice",     csc_dovoice);
-  chanservremovecommand("deopall",   csc_dodeopall);
-  chanservremovecommand("devoiceall",csc_dodevoiceall);
-  chanservremovecommand("unbanall",  csc_dounbanall);
-  chanservremovecommand("unbanme",   csc_dounbanme);
-  chanservremovecommand("clearchan", csc_doclearchan);
-  chanservremovecommand("recover",   csc_dorecover);
-  chanservremovecommand("settopic",  csc_dosettopic);
-  chanservremovecommand("permban",   csc_dopermban);
-  chanservremovecommand("tempban",   csc_dotempban);
-  chanservremovecommand("banlist",   csc_dobanlist);
-  chanservremovecommand("unbanmask", csc_dounbanmask);
-  chanservremovecommand("bandel",    csc_dobandel);
-  chanservremovecommand("banclear",    csc_dobanclear);
-  chanservremovecommand("channelcomment",csc_dochannelcomment);
-  chanservremovecommand("rejoin",    csc_dorejoin);
-  chanservremovecommand("adduser",   csc_doadduser);
-  chanservremovecommand("removeuser",csc_doremoveuser);
-  chanservremovecommand("chantype",  csc_dochantype);
-  chanservremovecommand("chanstat",  csc_dochanstat);
-}
-
-int csc_dochanflags(void *source, int cargc, char **cargv) {
-  regchan *rcp;
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  chanindex *cip;
-  flag_t oldflags,changemask;
-  char flagbuf[20];
-
-  if (cargc<1) {
-    chanservstdmessage(sender,QM_NOTENOUGHPARAMS,"chanflags");
-    return CMD_ERROR;
-  }
-  
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, 
-                          "chanflags", QPRIV_VIEWCHANFLAGS, 0))) 
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cargc>1) {
-    if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, "chanflags", 
-                       QPRIV_CHANGECHANFLAGS, 0))
-      return CMD_ERROR;
-
-    oldflags=rcp->flags;
-    changemask=QCFLAG_USERCONTROL;
-    if (UIsDev(rup)) {
-      changemask=QCFLAG_ALL;
-    }
-    setflags(&rcp->flags, changemask, cargv[1], rcflags, REJECT_NONE);
-
-    /* We might need to do things in response to the flag changes.. */
-    if (cip->channel) {
-      if ((oldflags ^ rcp->flags) & (QCFLAG_JOINED | QCFLAG_SUSPENDED)) {
-        chanservjoinchan(cip->channel);
-       rcp->status |= (QCSTAT_OPCHECK | QCSTAT_MODECHECK | QCSTAT_BANCHECK);
-       rcp->lastbancheck=0;
-       cs_timerfunc(cip);
-      } else {
-        if (CIsEnforce(rcp)) {
-         rcp->lastbancheck=0;
-          cs_checkbans(cip->channel);  
-       }
-    
-        if (CIsProtect(rcp) || CIsBitch(rcp) || CIsAutoOp(rcp) || CIsAutoVoice(rcp) || CIsKnownOnly(rcp)) {
-         rcp->status |= QCSTAT_OPCHECK;
-         cs_timerfunc(cip);
-       }
-      }
-    }
-    
-    if (CIsAutoLimit(rcp) && !(oldflags & QCFLAG_AUTOLIMIT)) {
-      rcp->forcemodes |= CHANMODE_LIMIT;
-      rcp->denymodes &= ~CHANMODE_LIMIT;
-      rcp->limit=0;
-      cs_timerfunc(cip);
-    }
-
-    if (!CIsAutoLimit(rcp) && (oldflags & QCFLAG_AUTOLIMIT)) {
-      rcp->forcemodes &= ~CHANMODE_LIMIT;
-      if (cip->channel) 
-        cs_checkchanmodes(cip->channel);
-    }
-
-    strcpy(flagbuf,printflags(oldflags, rcflags));
-    cs_log(sender,"CHANFLAGS %s %s (%s -> %s)",cip->name->content,cargv[1],flagbuf,printflags(rcp->flags,rcflags));
-    chanservstdmessage(sender, QM_DONE);
-    csdb_updatechannel(rcp);
-  }
-  
-  chanservstdmessage(sender,QM_CURCHANFLAGS,cip->name->content,printflags(rcp->flags, rcflags));
-  return CMD_OK;
-}
-
-int csc_dochanmode(void *source, int cargc, char **cargv) {
-  regchan *rcp;
-  nick *sender=source;
-  chanindex *cip;
-  flag_t forceflags,denyflags;
-  char buf1[60];
-  int carg=2,limdone=0;
-  sstring *newkey=NULL;
-  unsigned int newlim=0;
-
-  if (cargc<1) {
-    chanservstdmessage(sender,QM_NOTENOUGHPARAMS,"chanmode");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, 
-                          NULL, "chanmode", QPRIV_VIEWCHANMODES, 0)))
-    return CMD_ERROR;
-  
-  rcp=cip->exts[chanservext];
-
-  if (cargc>1) {
-    if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV,
-                       cip, "chanmode", QPRIV_CHANGECHANMODES, 0))
-      return CMD_ERROR;
-
-    /* Save the current modes.. */
-    strcpy(buf1,getchanmode(rcp));
-
-    /* Pick out the + flags: start from 0 */
-    forceflags=0;
-    setflags(&forceflags, CHANMODE_ALL, cargv[1], cmodeflags, REJECT_NONE);    
-
-    /* Pick out the - flags: start from everything and invert afterwards.. */
-    denyflags=CHANMODE_ALL;
-    setflags(&denyflags, CHANMODE_ALL, cargv[1], cmodeflags, REJECT_NONE);
-    denyflags = (~denyflags) & CHANMODE_ALL;
-
-    forceflags &= ~denyflags; /* Can't force and deny the same mode (shouldn't be possible anyway) */
-    if (forceflags & CHANMODE_SECRET) {
-      forceflags &= ~CHANMODE_PRIVATE;
-      denyflags |= CHANMODE_PRIVATE;
-    }
-    if (forceflags & CHANMODE_PRIVATE) {
-      forceflags &= ~CHANMODE_SECRET;
-      denyflags |= CHANMODE_SECRET;
-    }
-
-    if ((forceflags & CHANMODE_LIMIT) && 
-       (!(forceflags & CHANMODE_KEY) || strrchr(cargv[1],'l') < strrchr(cargv[1],'k'))) {
-      if (cargc<=carg) {
-       chanservstdmessage(sender,QM_NOTENOUGHPARAMS,"chanmode");
-       return CMD_ERROR;
-      }
-      newlim=strtol(cargv[carg++],NULL,10);
-      limdone=1;
-    }
-
-    if (forceflags & CHANMODE_KEY) {
-      if (cargc<=carg) {
-       chanservstdmessage(sender,QM_NOTENOUGHPARAMS,"chanmode");
-       return CMD_ERROR;
-      }
-      newkey=getsstring(cargv[carg++], KEYLEN);
-    }
-
-    if ((forceflags & CHANMODE_LIMIT) && !limdone) {
-      if (cargc<=carg) {
-       chanservstdmessage(sender,QM_NOTENOUGHPARAMS,"chanmode");
-       return CMD_ERROR;
-      }
-      newlim=strtol(cargv[carg++],NULL,10);
-      limdone=1;
-    }
-
-    if (CIsAutoLimit(rcp)) {
-      forceflags |= CHANMODE_LIMIT;
-      denyflags &= ~CHANMODE_LIMIT;
-      newlim=rcp->limit;
-    }
-
-    /* It parsed OK, so update the structure.. */
-    rcp->forcemodes=forceflags;
-    rcp->denymodes=denyflags;      
-    if (rcp->key)
-      freesstring(rcp->key);
-    rcp->key=newkey;
-    rcp->limit=newlim;
-    
-    chanservstdmessage(sender, QM_DONE);
-    cs_log(sender,"CHANMODE %s %s (%s -> %s)",cip->name->content,cargv[1],buf1,getchanmode(rcp));
-    csdb_updatechannel(rcp);
-    cs_checkchanmodes(cip->channel);    
-  }
-  
-  chanservstdmessage(sender,QM_CURFORCEMODES,cip->name->content,getchanmode(rcp));
-
-  return CMD_OK;
-}
-
-char *getchanmode(regchan *rcp) {
-  static char buf1[50];
-  char buf2[30];
-
-  if (rcp->forcemodes) {
-    strcpy(buf1,printflags(rcp->forcemodes, cmodeflags));
-  } else {
-    buf1[0]='\0';
-  }
-
-  strcpy(buf2,printflagdiff(CHANMODE_ALL, ~(rcp->denymodes), cmodeflags));
-  strcat(buf1, buf2);
-
-  if (rcp->forcemodes & CHANMODE_LIMIT) {
-    sprintf(buf2, " %d",rcp->limit);
-    strcat(buf1, buf2);
-  }
-
-  if (rcp->forcemodes & CHANMODE_KEY) {
-    sprintf(buf2, " %s",rcp->key->content);
-    strcat(buf1, buf2);
-  }
-
-  if (*buf1=='\0') {
-    strcpy(buf1,"(none)");
-  }
-
-  return buf1;
-}
-
-int compareflags(const void *u1, const void *u2) {
-  const regchanuser *r1=*(void **)u1, *r2=*(void **)u2;
-  flag_t f1,f2;
-  
-  for (f1=QCUFLAG_OWNER;f1;f1>>=1)
-    if (r1->flags & f1)
-      break;
-
-  for (f2=QCUFLAG_OWNER;f2;f2>>=1)
-    if (r2->flags & f2) 
-      break;
-  
-  if (f1==f2) {
-    return ircd_strcmp(r1->user->username, r2->user->username);
-  } else {
-    return f2-f1;
-  }
-}
-
-int csc_dochanlev(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regchan *rcp;
-  regchanuser *rcup, *rcuplist;
-  regchanuser **rusers;
-  reguser *rup=getreguserfromnick(sender), *target;
-  char time1[15],time2[15];
-  char flagbuf[30];
-  struct tm *tmp;
-  flag_t flagmask, changemask, flags, oldflags;
-  int showtimes=0;
-  int donehead=0;
-  int i,j;
-  int newuser=0;
-  int usercount;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "chanlev");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_KNOWN,
-                          NULL, "chanlev", QPRIV_VIEWFULLCHANLEV, 0)))
-    return CMD_ERROR;
-  
-  rcp=cip->exts[chanservext];
-  rcup=findreguseronchannel(rcp, rup);
-
-  /* Set flagmask for +v/+o users (can't see bans etc.) */
-  flagmask = (QCUFLAG_OWNER | QCUFLAG_MASTER | QCUFLAG_OP | QCUFLAG_VOICE | QCUFLAG_AUTOVOICE | 
-             QCUFLAG_AUTOOP | QCUFLAG_TOPIC | QCUFLAG_SPAMCON | QCUFLAG_PROTECT | QCUFLAG_KNOWN);
-  
-  /* If user has +m or above, or helper access, show everything */
-  if (cs_privcheck(QPRIV_VIEWFULLCHANLEV, sender) || CUHasMasterPriv(rcup)) {
-    flagmask = QCUFLAG_ALL;
-    showtimes=1;
-  }
-  
-  if (cargc==1) {
-    /* One arg: list chanlev */
-    if (cs_privcheck(QPRIV_VIEWFULLCHANLEV, sender)) {
-      reguser *founder=NULL, *addedby=NULL;
-      addedby=findreguserbyID(rcp->addedby);
-      chanservstdmessage(sender, QM_ADDEDBY, addedby ? addedby->username : "(unknown)");
-      founder=findreguserbyID(rcp->founder);
-      chanservstdmessage(sender, QM_FOUNDER, founder ? founder->username : "(unknown)");
-      if (rcp->chantype) {
-        chanservstdmessage(sender, QM_CHANTYPE, chantypes[rcp->chantype]->content);
-      }
-    }
-
-    /* Count users */
-    for (i=0,usercount=0;i<REGCHANUSERHASHSIZE;i++)
-      for (rcuplist=rcp->regusers[i];rcuplist;rcuplist=rcuplist->nextbychan)
-       usercount++;
-    
-    /* Allocate array */
-    rusers=(regchanuser **)malloc(usercount * sizeof(regchanuser *));
-
-    /* Fill array */
-    for (j=i=0;i<REGCHANUSERHASHSIZE;i++) {
-      for (rcuplist=rcp->regusers[i];rcuplist;rcuplist=rcuplist->nextbychan) {
-       if (!(flags=rcuplist->flags & flagmask))
-         continue;
-       
-       rusers[j++]=rcuplist;
-      }
-    }
-
-    /* Sort */
-    qsort(rusers, j, sizeof(regchanuser *), compareflags);
-
-    /* List */
-    for (i=0;i<j;i++) {
-      rcuplist=rusers[i];
-
-      if (!(flags=rcuplist->flags & flagmask)) 
-       continue;
-      
-      if (!donehead) {
-       chanservstdmessage(sender, QM_CHANLEVHEADER, cip->name->content);
-       if (showtimes) 
-         chanservstdmessage(sender, QM_CHANLEVCOLFULL);
-       else
-         chanservstdmessage(sender, QM_CHANLEVCOLSHORT);
-       donehead=1;
-      }
-      
-      if (showtimes) {
-       if (!rcuplist->usetime) {
-         strcpy(time1,"Never");
-       } else {
-         tmp=localtime(&(rcuplist->usetime));
-         strftime(time1,15,"%d/%m/%y %H:%M",tmp);
-       }
-       if (!rcuplist->changetime) {
-         strcpy(time2, "Unknown");
-       } else {
-         tmp=localtime(&(rcuplist->changetime));
-         strftime(time2,15,"%d/%m/%y %H:%M",tmp);
-       }
-       chanservsendmessage(sender, " %-15s %-13s %-14s  %-14s  %s", rcuplist->user->username, 
-                           printflags(flags, rcuflags), time1, time2, rcuplist->info?rcuplist->info->content:"");
-      } else 
-       chanservsendmessage(sender, " %-15s %s", rcuplist->user->username, printflags(flags, rcuflags));
-    }
-    
-    if (donehead) {
-      chanservstdmessage(sender, QM_ENDOFLIST);
-    } else {
-      chanservstdmessage(sender, QM_NOUSERSONCHANLEV, cip->name->content);
-    }
-
-    free(rusers);
-  } else {
-    /* 2 or more args.. relates to one specific user */
-    if (!(target=findreguser(sender, cargv[1])))
-      return CMD_ERROR; /* If there was an error, findreguser will have sent a message saying why.. */
-    
-    rcuplist=findreguseronchannel(rcp, target);
-    
-    if (cargc>2) {
-      /* To change chanlev you have to either.. */
-      if (!( cs_privcheck(QPRIV_CHANGECHANLEV, sender) ||             /* Have override privilege */
-            (rcup && rcuplist && (rcup==rcuplist) && CUKnown(rcup)) || /* Be manipulting yourself (oo er..) */
-            (rcup && CUHasMasterPriv(rcup) &&                        /* Have +m or +n on the channel */
-             !(rcuplist && CUIsOwner(rcuplist) && !CUIsOwner(rcup))) /* masters can't screw with owners */
-            )) {
-       chanservstdmessage(sender, QM_NOACCESSONCHAN, cip->name->content, "chanlev");
-       return CMD_ERROR;
-      }
-      
-      if (!rcuplist) {
-       rcuplist=getregchanuser();
-       rcuplist->user=target;
-       rcuplist->chan=rcp;
-       rcuplist->flags=0;
-       rcuplist->changetime=time(NULL);
-       rcuplist->usetime=0;
-       rcuplist->info=NULL;
-       newuser=1;
-      }
-      
-      if (cs_privcheck(QPRIV_CHANGECHANLEV, sender)) {
-       /* Opers are allowed to change everything */
-       changemask = QCUFLAG_ALL;
-      } else {
-       changemask=0;
-       
-       /* Everyone can change their own flags (except +dqb), and turn +iwj on/off */
-       if (rcup==rcuplist) {
-         changemask = (rcup->flags | QCUFLAG_HIDEWELCOME | QCUFLAG_HIDEINFO | QCUFLAG_AUTOINVITE) & 
-                     ~(QCUFLAG_BANNED | QCUFLAG_DENY | QCUFLAG_QUIET);
-         flagmask |= (QCUFLAG_HIDEWELCOME | QCUFLAG_HIDEINFO | QCUFLAG_AUTOINVITE);
-       }
-       
-       /* Masters are allowed to manipulate +ovagtbqdpk */
-       if (CUHasMasterPriv(rcup))
-         changemask |= ( QCUFLAG_KNOWN | QCUFLAG_OP | QCUFLAG_VOICE | QCUFLAG_AUTOOP | QCUFLAG_AUTOVOICE | 
-                         QCUFLAG_TOPIC | QCUFLAG_BANNED | QCUFLAG_QUIET | QCUFLAG_DENY | QCUFLAG_PROTECT);
-       
-       /* Owners are allowed to manipulate +ms as well */
-       if (CUIsOwner(rcup))
-         changemask |= ( QCUFLAG_MASTER | QCUFLAG_SPAMCON );
-      }
-
-      oldflags=rcuplist->flags;
-      if (setflags(&(rcuplist->flags), changemask, cargv[2], rcuflags, REJECT_UNKNOWN | REJECT_DISALLOWED)) {
-       chanservstdmessage(sender, QM_INVALIDCHANLEVCHANGE);
-       return CMD_ERROR;
-      }
-
-      /* Now fix up some "impossible" combinations.. */
-      /* +m can't be any of +qdb */
-      if (CUHasMasterPriv(rcuplist))
-       rcuplist->flags &= ~(QCUFLAG_BANNED | QCUFLAG_QUIET | QCUFLAG_DENY);
-      
-      /* +d can't be +o */
-      if (CUIsDeny(rcuplist))
-       rcuplist->flags &= ~QCUFLAG_OP;
-
-      /* +q can't be +v */
-      if (CUIsQuiet(rcuplist))
-       rcuplist->flags &= ~QCUFLAG_VOICE;
-
-      /* -o or +p can't be +a */
-      if (!CUIsOp(rcuplist) || CUIsProtect(rcuplist))
-       rcuplist->flags &= ~QCUFLAG_AUTOOP;
-      
-      /* +a or -v or +p can't be +g */
-      if (!CUIsVoice(rcuplist) || CUIsAutoOp(rcuplist) || CUIsProtect(rcuplist))
-       rcuplist->flags &= ~QCUFLAG_AUTOVOICE;
-
-      /* and -ov can't be +p */
-      if (!CUIsOp(rcuplist) && !CUIsVoice(rcuplist)) 
-       rcuplist->flags &= ~QCUFLAG_PROTECT;
-
-      /* Check if anything "significant" has changed */
-      if ((oldflags ^ rcuplist->flags) & (QCUFLAG_OWNER | QCUFLAG_MASTER | QCUFLAG_OP))
-       rcuplist->changetime=time(NULL);
-
-      strcpy(flagbuf,printflags(oldflags,rcuflags));
-      cs_log(sender,"CHANLEV %s #%s %s (%s -> %s)",cip->name->content,rcuplist->user->username,cargv[2],
-            flagbuf,printflags(rcuplist->flags,rcuflags));
-
-      /* Now see what we do next */
-      if (rcuplist->flags) {
-       /* User still valid: update or create */
-       if (newuser) {
-         addregusertochannel(rcuplist);
-         csdb_createchanuser(rcuplist);
-       } else {
-         csdb_updatechanuser(rcuplist);
-       }
-      } else {
-       /* User has no flags: delete */
-       if (!newuser) {
-         csdb_deletechanuser(rcuplist);
-         delreguserfromchannel(rcp, target);
-       }
-       freeregchanuser(rcuplist);
-       rcuplist=NULL;
-        for (i=0;i<REGCHANUSERHASHSIZE;i++)
-          if (rcp->regusers[i])
-            break;
-        if (i==REGCHANUSERHASHSIZE) {
-         cs_log(sender,"DELCHAN %s (Cleared chanlev)",cip->name->content);
-          cs_removechannel(rcp);       
-       }
-      }
-
-      /* Say we've done it */
-      chanservstdmessage(sender, QM_DONE);
-      rcp->status |= QCSTAT_OPCHECK;
-      cs_timerfunc(cip);
-    }
-    
-    if (rcuplist && (rcuplist->flags & flagmask)) {
-      chanservstdmessage(sender, QM_CHANUSERFLAGS, cargv[1], cip->name->content, 
-                        printflags(rcuplist->flags & flagmask, rcuflags));
-    } else {
-      chanservstdmessage(sender, QM_CHANUSERUNKNOWN, cargv[1], cip->name->content);
-    }
-  }
-  
-  return CMD_OK;
-}
-
-int csc_doautolimit(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regchan *rcp;
-  int oldlimit;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "autolimit");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV,
-                          NULL, "autolimit", QPRIV_VIEWAUTOLIMIT, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cargc>1) {
-    if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, 
-                       cip, "autolimit", QPRIV_CHANGEAUTOLIMIT, 0))
-      return CMD_ERROR;
-
-    oldlimit=rcp->autolimit;
-    rcp->autolimit=strtol(cargv[1],NULL,10);
-
-    if (rcp->autolimit<1)
-      rcp->autolimit=1;
-    
-    csdb_updatechannel(rcp);
-    
-    cs_log(sender,"AUTOLIMIT %s %s (%d -> %d)",cip->name->content,cargv[1],oldlimit,rcp->autolimit);
-    chanservstdmessage(sender, QM_DONE);
-    rcp->limit=0;
-    cs_timerfunc(cip);
-  }
-
-  chanservstdmessage(sender, QM_CHANAUTOLIMIT, cargv[0], rcp->autolimit);
-  return CMD_OK;
-}
-
-int csc_dobantimer(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regchan *rcp;
-  int oldtimer;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "bantimer");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "bantimer",
-                          QPRIV_VIEWBANTIMER, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cargc>1) {
-    if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, "bantimer",
-                       QPRIV_CHANGEBANTIMER, 0))
-      return CMD_ERROR;
-
-    oldtimer=rcp->banduration;
-    rcp->banduration=durationtolong(cargv[1]);
-
-    if (rcp->banduration<0)
-      rcp->banduration=0;
-    
-    /* Arbitrary limit */
-    if (rcp->banduration > 31622400)
-      rcp->banduration = 31622400;
-      
-    csdb_updatechannel(rcp);
-    
-    cs_log(sender,"BANTIMER %s %s (%u -> %u)",cip->name->content,cargv[1],oldtimer,rcp->banduration);
-    chanservstdmessage(sender, QM_DONE);
-    cs_timerfunc(cip);
-  }
-
-  if (rcp->banduration)
-    chanservstdmessage(sender, QM_CHANBANAUTOREMOVE, cargv[0], longtoduration(rcp->banduration, 1));
-  else
-    chanservstdmessage(sender, QM_NOCHANBANAUTOREMOVE, cargv[0]);
-
-  return CMD_OK;
-}
-
-int csc_dowelcome(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regchan *rcp;
-  sstring *oldwelcome;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "welcome");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "welcome",
-                          QPRIV_VIEWWELCOME, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cargc>1) {
-    if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, "welcome",
-                       QPRIV_CHANGEWELCOME, 0))
-      return CMD_ERROR;
-
-    oldwelcome=rcp->welcome;
-    
-    rcp->welcome=getsstring(cargv[1], 500);
-    csdb_updatechannel(rcp);
-
-    cs_log(sender,"WELCOME %s %s (was %s)",cip->name->content,rcp->welcome->content,oldwelcome?oldwelcome->content:"unset");
-    freesstring(oldwelcome);
-    chanservstdmessage(sender, QM_DONE);
-  }
-
-  chanservstdmessage(sender, QM_WELCOMEMESSAGEIS, rcp->index->name->content, 
-                    rcp->welcome?rcp->welcome->content:"(none)");
-
-  return CMD_OK;
-}
-
-int csc_doaddchan(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  chanindex *cip;
-  regchan *rcp;
-  regchanuser *rcup;
-  reguser *founder;
-  flag_t flags;
-  short type=0;
-  
-  if (!rup)
-    return CMD_ERROR;
-    
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "addchan");
-    return CMD_ERROR;
-  }
-  
-  if (*cargv[0] != '#') {
-    chanservstdmessage(sender, QM_INVALIDCHANNAME, cargv[0]);
-    return CMD_ERROR;
-  } 
-  
-  if (cargc>1) {
-    if (!(founder=findreguser(sender, cargv[1])))
-      return CMD_ERROR;
-  } else {
-    founder=rup;
-  }      
-  
-  if (cargc>2) {
-    flags=0;
-    setflags(&flags, QCFLAG_ALL, cargv[2], rcflags, REJECT_NONE);    
-  } else {
-    flags = (QCFLAG_JOINED | QCFLAG_BITCH | QCFLAG_PROTECT | QCFLAG_ENFORCE);
-  }
-  
-  /* Pick up the chantype */
-  if (cargc>3) {
-    for (type=CHANTYPES-1;type;type--) {
-      if (!ircd_strcmp(chantypes[type]->content, cargv[3]))
-       break;
-    }
-    if (!type) {
-      chanservstdmessage(sender, QM_UNKNOWNCHANTYPE, cargv[3]);
-      return CMD_ERROR;
-    }
-  }
-  
-  if (!(cip=findorcreatechanindex(cargv[0]))) {
-    chanservstdmessage(sender, QM_INVALIDCHANNAME, cargv[0]);
-    return CMD_ERROR;
-  }
-  
-  if (cip->exts[chanservext]) {
-    chanservstdmessage(sender, QM_ALREADYREGISTERED, cip->name->content);
-    return CMD_ERROR;
-  }
-  
-  /* 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=CHANMODE_NOEXTMSG | CHANMODE_TOPICLIMIT;
-  rcp->denymodes=0;
-
-  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=1800;
-  rcp->autoupdate=0;
-  rcp->lastbancheck=0;
-  
-  /* Added by */
-  rcp->addedby=rup->ID;
-  
-  /* Founder */
-  rcp->founder=founder->ID;
-  /* Suspend by */
-  rcp->suspendby=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;
-
-  /* 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);
-
-  /* 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);
-  }
-
-  cs_log(sender, "ADDCHAN %s #%s %s %s",cip->name->content,founder->username,printflags(rcp->flags,rcflags), chantypes[type]->content);
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}
-
-int csc_dosuspendchan(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  chanindex *cip;
-  regchan *rcp;
-
-  if (!rup)
-    return CMD_ERROR;
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspendchan");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
-    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
-    return CMD_ERROR;
-  }
-
-  if (CIsSuspended(rcp)) {
-    chanservstdmessage(sender, QM_CHANNELALREADYSUSPENDED, cip->name->content);
-    return CMD_ERROR;
-  }
-
-  CSetSuspended(rcp);
-  rcp->suspendreason = getsstring(cargv[1], 250);
-  rcp->suspendby = rup->ID;
-  cs_log(sender,"SUSPENDCHAN %s (%s)",cip->name->content,rcp->suspendreason->content);
-  chanservjoinchan(cip->channel);
-
-  csdb_updatechannel(rcp);
-  chanservstdmessage(sender, QM_DONE);
-
-  return CMD_OK;
-}
-
-int csc_dosuspendchanlist(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  chanindex *cip;
-  regchan *rcp;
-  int i;
-  char *bywhom;
-  unsigned int count=0;
-  
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc < 1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspendchanlist");
-    return CMD_ERROR;
-  }
-  
-  chanservstdmessage(sender, QM_SUSPENDCHANLISTHEADER);
-  for (i=0; i<CHANNELHASHSIZE; i++) {
-    for (cip=chantable[i]; cip; cip=cip->next) {
-      if (!(rcp=(regchan*)cip->exts[chanservext]))
-        continue;
-      
-      if (!CIsSuspended(rcp))
-        continue;
-      
-      if ((rcp->suspendby != rup->ID) && match(cargv[0], cip->name->content))
-        continue;
-      
-      if (rcp->suspendby == rup->ID)
-        bywhom=rup->username;
-      else {
-        reguser *trup=findreguserbyID(rcp->suspendby);
-        if (trup)
-          bywhom=trup->username;
-        else
-          bywhom="unknown";
-      }
-      count++;
-      chanservsendmessage(sender, "%-30s %-15s %s", cip->name->content, bywhom, rcp->suspendreason->content);
-      if (count >= 2000) {
-        chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "channels");
-        return CMD_ERROR;
-      }
-    }
-  }
-  chanservstdmessage(sender, QM_RESULTCOUNT, count, "channel", (count==1)?"":"s");
-  
-  return CMD_OK;
-}
-
-int csc_dounsuspendchan(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  chanindex *cip;
-  regchan *rcp;
-
-  if (!rup)
-    return CMD_ERROR;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unsuspendchan");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
-    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
-    return CMD_ERROR;
-  }
-
-  if(!CIsSuspended(rcp)) {
-    chanservstdmessage(sender, QM_CHANNELNOTSUSPENDED, cip->name->content);
-    cs_log(sender,"UNSUSPENDCHAN %s is not suspended",cip->name->content);
-    return CMD_ERROR;
-  }
-
-  CClearSuspended(rcp);
-  cs_log(sender,"UNSUSPENDCHAN %s (%s)",cip->name->content,rcp->suspendreason->content);
-  freesstring(rcp->suspendreason);
-  rcp->suspendreason = NULL;
-  rcp->suspendby = 0;
-
-  chanservjoinchan(cip->channel);
-
-  csdb_updatechannel(rcp);
-  chanservstdmessage(sender, QM_DONE);
-
-  return CMD_OK;
-}
-
-int csc_dodelchan(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  chanindex *cip;
-  regchan *rcp;
-
-  if (!rup)
-    return CMD_ERROR;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "delchan");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
-    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
-    return CMD_ERROR;
-  }
-
-  cs_log(sender,"DELCHAN %s (%s)",cip->name->content,cargc>1?cargv[1]:"");
-  cs_removechannel(rcp);
-  chanservstdmessage(sender, QM_DONE);
-
-  return CMD_OK;
-}
-
-int csc_doinvite(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "invite");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_KNOWN | CA_OFFCHAN, 
-                          NULL, "invite", 0, 0)))
-    return CMD_ERROR;
-
-  if (cip->channel) {
-    localinvite(chanservnick, cip->channel, sender);
-  }
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}
-
-int csc_dosettopic(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regchan *rcp;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "settopic");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_TOPICPRIV, 
-                          NULL, "settopic", 0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cargc>1) {
-    if (rcp->topic)
-      freesstring(rcp->topic);
-    rcp->topic=getsstring(cargv[1],TOPICLEN);
-  } 
-  
-  if (rcp->topic && cip->channel) {
-    localsettopic(chanservnick, cip->channel, rcp->topic->content);
-  }
-
-  chanservstdmessage(sender, QM_DONE);
-  csdb_updatechannel(rcp);
-  return CMD_OK;
-}
-
-int csc_doop(void *source, int cargc, char **cargv) {
-  nick *sender=source, *np;
-  reguser *rup=getreguserfromnick(sender);
-  chanindex *cip;
-  regchan *rcp=NULL;
-  regchanuser *rcup;
-  channel **ca;
-  unsigned long *lp;
-  int i;
-  modechanges changes;
-
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc==0) {
-    /* No args: "op me on every channel you can */
-    ca=sender->channels->content;
-    for (i=0;i<sender->channels->cursi;i++) {
-      if ((rcp=ca[i]->index->exts[chanservext]) && !CIsSuspended(rcp)) {
-       /* It's a Q channel */
-       if (!(*(getnumerichandlefromchanhash(ca[i]->users, sender->numeric)) & 
-             CUMODE_OP)) {
-         /* They're not opped */
-         if ((rcup=findreguseronchannel(rcp, rup)) && CUHasOpPriv(rcup) && 
-             !CUIsDeny(rcup)) {
-           /* And they have op priv on the chan: op them */
-           localsetmodeinit(&changes, ca[i], chanservnick);
-           localdosetmode_nick(&changes, sender, MC_OP);
-           localsetmodeflush(&changes,1);
-         }
-       }
-      }
-    }
-    
-    chanservstdmessage(sender, QM_DONE);
-    return CMD_OK;
-  }
-
-  /* If there is at least one arg, the first is a channel */
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "op", 0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cargc==1) {
-    /* Only one arg: "op me" */
-    if (!cs_checkaccess(sender, NULL, CA_OPPRIV | CA_DEOPPED, cip, "op", 0, 0))
-      return CMD_ERROR;
-    
-    localsetmodeinit(&changes, cip->channel, chanservnick);
-    localdosetmode_nick(&changes, sender, MC_OP);
-    localsetmodeflush(&changes,1);
-
-    chanservstdmessage(sender, QM_DONE);
-    return CMD_OK;
-  }
-
-  /* Set up the modes */
-  localsetmodeinit(&changes, cip->channel, chanservnick);
-
-  for(i=1;i<cargc;i++) {
-    if (!(np=getnickbynick(cargv[i]))) {
-      chanservstdmessage(sender, QM_UNKNOWNUSER, cargv[i]);
-      continue;
-    }
-
-    if (!(lp=getnumerichandlefromchanhash(cip->channel->users, np->numeric))) {
-      chanservstdmessage(sender, QM_USERNOTONCHAN, np->nick, cip->name->content);
-      continue;
-    }
-
-    if (*lp & CUMODE_OP) {
-      chanservstdmessage(sender, QM_USEROPPEDONCHAN, np->nick, cip->name->content);
-      continue;
-    }
-
-    rup=getreguserfromnick(np);
-    if (rup)
-      rcup=findreguseronchannel(rcp,rup);
-    else
-      rcup=NULL;
-
-    /* Bitch mode: check that this user is allowed to be opped.. */
-    if ((CIsBitch(rcp) && (!rcup || !CUHasOpPriv(rcup))) || (rcup && CUIsDeny(rcup))) {
-      chanservstdmessage(sender, QM_CANTOP, np->nick, cip->name->content);
-      continue;
-    }
-
-    localdosetmode_nick(&changes, np, MC_OP);
-  }
-
-  localsetmodeflush(&changes, 1);
-  chanservstdmessage(sender, QM_DONE);
-
-  return CMD_OK;
-}
-
-int csc_dovoice(void *source, int cargc, char **cargv) {
-  nick *sender=source, *np;
-  reguser *rup=getreguserfromnick(sender);
-  chanindex *cip;
-  regchan *rcp=NULL;
-  regchanuser *rcup;
-  channel **ca;
-  unsigned long *lp;
-  int i;
-  modechanges changes;
-
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc==0) {
-    /* No args: "voice me on every channel you can */
-    ca=sender->channels->content;
-    for (i=0;i<sender->channels->cursi;i++) {
-      if ((rcp=ca[i]->index->exts[chanservext]) && !CIsSuspended(rcp)) {
-       /* It's a Q channel */
-       if (!(*(getnumerichandlefromchanhash(ca[i]->users, sender->numeric)) & 
-             (CUMODE_OP|CUMODE_VOICE))) {
-         /* They're not opped or voiced */
-         rcup=findreguseronchannel(rcp, rup);
-         if ((!rcup || !CUIsQuiet(rcup)) && 
-             ((rcup && CUHasVoicePriv(rcup)) ||
-             (CIsVoiceAll(rcp)))) {
-           /* And they have voice priv on the chan (or it's autovoice): 
-            * voice them */
-           localsetmodeinit(&changes, ca[i], chanservnick);
-           localdosetmode_nick(&changes, sender, MC_VOICE);
-           localsetmodeflush(&changes,1);
-         }
-       }
-      }
-    }
-    
-    chanservstdmessage(sender, QM_DONE);
-    return CMD_OK;
-  }
-
-  /* If there is at least one arg, the first is a channel */
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_VOICEPRIV, NULL, "voice", 0, 0)))
-    return CMD_ERROR;
-
-  if (cargc==1) {
-    /* Only one arg: "voice me" */
-    if (!cs_checkaccess(sender, NULL, CA_VOICEPRIV | CA_DEVOICED, cip,
-                       "voice", 0, 0))
-      return CMD_ERROR;
-
-    localsetmodeinit(&changes, cip->channel, chanservnick);
-    localdosetmode_nick(&changes, sender, MC_VOICE);
-    localsetmodeflush(&changes,1);
-
-    chanservstdmessage(sender, QM_DONE);
-    return CMD_OK;
-  }
-
-  if (!(cip=cs_checkaccess(sender, NULL, CA_OPPRIV, cip, "voice", 0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  /* Set up the modes */
-  localsetmodeinit(&changes, cip->channel, chanservnick);
-
-  for(i=1;i<cargc;i++) {
-    if (!(np=getnickbynick(cargv[i]))) {
-      chanservstdmessage(sender, QM_UNKNOWNUSER, cargv[i]);
-      continue;
-    }
-
-    if (!(lp=getnumerichandlefromchanhash(cip->channel->users, np->numeric))) {
-      chanservstdmessage(sender, QM_USERNOTONCHAN, np->nick, cip->name->content);
-      continue;
-    }
-
-    if (*lp & CUMODE_VOICE) {
-      chanservstdmessage(sender, QM_USERVOICEDONCHAN, np->nick, cip->name->content);
-      continue;
-    }
-   
-    if ((rup=getreguserfromnick(np)) && (rcup=findreguseronchannel(rcp, rup)) && CUIsQuiet(rcup)) {
-      chanservstdmessage(sender, QM_CANTVOICE, np->nick, cip->name->content);
-      continue;
-    }
-
-    localdosetmode_nick(&changes, np, MC_VOICE);
-  }
-
-  localsetmodeflush(&changes, 1);
-  chanservstdmessage(sender, QM_DONE);
-
-  return CMD_OK;
-}
-
-int csc_dodeopall(void *source, int cargc, char **cargv) {
-  nick *sender=source,*np;
-  reguser *rup;
-  regchanuser *rcup;
-  regchan *rcp;
-  chanindex *cip;
-  unsigned long *lp;
-  int i;
-  modechanges changes;
-  
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "deopall");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "deopall",0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cip->channel) {
-    localsetmodeinit(&changes, cip->channel, chanservnick);
-
-    for (i=0,lp=cip->channel->users->content;
-        i<cip->channel->users->hashsize;i++,lp++) {
-      if (*lp!=nouser && (*lp & CUMODE_OP)) {
-       if (!(np=getnickbynumeric(*lp)) || 
-           (!IsService(np) && (!(rup=getreguserfromnick(np)) || 
-           !(rcup=findreguseronchannel(rcp, rup)) || !(CUHasOpPriv(rcup)) ||
-           !(CUIsProtect(rcup) || CIsProtect(rcp))))) {
-         localdosetmode_nick(&changes, np, MC_DEOP);
-       }
-      }
-    }
-
-    localsetmodeflush(&changes, 1);
-  }
-
-  cs_log(sender,"DEOPALL %s",cip->name->content);
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}     
-      
-int csc_dodevoiceall(void *source, int cargc, char **cargv) {
-  nick *sender=source,*np;
-  reguser *rup;
-  regchanuser *rcup;
-  regchan *rcp;
-  chanindex *cip;
-  unsigned long *lp;
-  int i;
-  modechanges changes;
-  
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "devoiceall");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "devoiceall",0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cip->channel) {
-    localsetmodeinit(&changes, cip->channel, chanservnick);
-
-    for (i=0,lp=cip->channel->users->content;
-        i<cip->channel->users->hashsize;i++,lp++) {
-      if (*lp!=nouser && (*lp & CUMODE_VOICE)) {
-       if (!(np=getnickbynumeric(*lp)) || 
-           (!IsService(np) && (!(rup=getreguserfromnick(np)) || 
-           !(rcup=findreguseronchannel(rcp, rup)) || !(CUHasVoicePriv(rcup)) ||
-           !(CUIsProtect(rcup) || CIsProtect(rcp))))) {
-         localdosetmode_nick(&changes, np, MC_DEVOICE);
-       }
-      }
-    }
-
-    localsetmodeflush(&changes, 1);
-  }
-
-  cs_log(sender,"DEVOICEALL %s",cip->name->content);
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}     
-      
-int csc_dounbanall(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  regchan *rcp;
-  chanindex *cip;
-  modechanges changes;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unbanall");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "unbanall",0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cip->channel) {
-    localsetmodeinit(&changes, cip->channel, chanservnick);
-
-    while (cip->channel->bans) {
-      localdosetmode_ban(&changes, bantostring(cip->channel->bans), MCB_DEL);
-    }
-
-    localsetmodeflush(&changes, 1);
-  }
-
-  cs_log(sender,"UNBANALL %s",cip->name->content);
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}     
-      
-int csc_dounbanme(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  regchan *rcp;
-  chanindex *cip;
-  modechanges changes;
-  chanban **cbh;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unbanme");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "unbanme", 0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cip->channel) {
-    localsetmodeinit(&changes, cip->channel, chanservnick);
-
-    for (cbh=&(cip->channel->bans);*cbh;) {
-      if (nickmatchban(sender, *cbh))
-       localdosetmode_ban(&changes, bantostring(*cbh), MCB_DEL);
-      else
-       cbh=&((*cbh)->next);
-    }
-
-    localsetmodeflush(&changes, 1);
-  }
-
-  cs_log(sender,"UNBANME %s",cip->name->content);
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}     
-      
-int csc_doclearchan(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  regchan *rcp;
-  chanindex *cip;
-  modechanges changes;
-  
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "clearchan");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "clearchan",0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cip->channel) {
-    localsetmodeinit(&changes, cip->channel, chanservnick);
-    localdosetmode_key(&changes, NULL, MCB_DEL);
-    localdosetmode_simple(&changes, 0, cip->channel->flags);
-    cs_docheckchanmodes(cip->channel, &changes);
-    localsetmodeflush(&changes, 1);
-  }
-
-  cs_log(sender,"CLEARCHAN %s",cip->name->content);
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}     
-      
-int csc_dorecover(void *source, int cargc, char **cargv) {
-  nick *sender=source,*np;
-  reguser *rup;
-  regchanuser *rcup;
-  regchan *rcp;
-  chanindex *cip;
-  unsigned long *lp;
-  int i;
-  modechanges changes;
-  
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "recover");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "recover",0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cip->channel) {
-    localsetmodeinit(&changes, cip->channel, chanservnick);
-
-    /* clearchan */
-    localdosetmode_key(&changes, NULL, MCB_DEL);
-    localdosetmode_simple(&changes, 0, cip->channel->flags);
-    cs_docheckchanmodes(cip->channel, &changes);
-
-    /* unbanall */
-    while (cip->channel->bans) {
-      localdosetmode_ban(&changes, bantostring(cip->channel->bans), MCB_DEL);
-    }
-
-    /* deopall */
-    for (i=0,lp=cip->channel->users->content;
-        i<cip->channel->users->hashsize;i++,lp++) {
-      if (*lp!=nouser && (*lp & CUMODE_OP)) {
-       if (!(np=getnickbynumeric(*lp)) || 
-           (!IsService(np) && (!(rup=getreguserfromnick(np)) || 
-           !(rcup=findreguseronchannel(rcp, rup)) || !(CUHasOpPriv(rcup)) ||
-           !(CUIsProtect(rcup) || CIsProtect(rcp))))) {
-         localdosetmode_nick(&changes, np, MC_DEOP);
-       }
-      }
-    }
-
-    localsetmodeflush(&changes, 1);
-  }
-
-  cs_log(sender,"RECOVER %s",cip->name->content);
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}     
-
-int csc_dopermban(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regban *rbp;
-  regchan *rcp;
-  reguser *rup=getreguserfromnick(sender);
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "permban");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "permban",0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  rbp=getregban();
-  rbp->ID=++lastbanID;
-  rbp->cbp=makeban(cargv[1]);
-  rbp->setby=rup->ID;
-  rbp->expiry=0;
-  if (cargc>2)
-    rbp->reason=getsstring(cargv[2],200);
-  else
-    rbp->reason=NULL;
-  rbp->next=rcp->bans;
-  rcp->bans=rbp;
-
-  cs_setregban(cip, rbp);
-  csdb_createban(rcp, rbp);
-  
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}
-  
-int csc_dotempban(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regban *rbp;
-  regchan *rcp;
-  reguser *rup=getreguserfromnick(sender);
-  unsigned int duration;
-
-  if (cargc<3) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "tempban");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "tempban",0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  duration=durationtolong(cargv[2]);
-  
-  rbp=getregban();
-  rbp->ID=++lastbanID;
-  rbp->cbp=makeban(cargv[1]);
-  rbp->setby=rup->ID;
-  rbp->expiry=time(NULL)+duration;
-  if (cargc>3)
-    rbp->reason=getsstring(cargv[3],200);
-  else
-    rbp->reason=NULL;
-  rbp->next=rcp->bans;
-  rcp->bans=rbp;
-
-  cs_setregban(cip, rbp);
-  csdb_createban(rcp, rbp);
-  
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}
-
-int csc_dobanlist(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regchan *rcp;
-  regban *rbp;
-  reguser *rup;
-  chanban *cbp;
-  int i=0;
-  int exp;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "banlist");
-    return CMD_ERROR;
-  }
-  
-  if(!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "banlist", 0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-  
-  if (rcp->bans || cip->channel->bans) {
-    chanservstdmessage(sender, QM_REGBANHEADER, cip->name->content);
-    for(rbp=rcp->bans;rbp;rbp=rbp->next) {
-      rup=findreguserbyID(rbp->setby);
-      chanservsendmessage(sender," #%-2d %-29s %-18s %-15s  %s",++i,bantostring(rbp->cbp),
-                         rbp->expiry?longtoduration(rbp->expiry-time(NULL),0):"Permanent",
-                         rup?rup->username:"<unknown>",
-                         rbp->reason?rbp->reason->content:"");
-    }
-    for (cbp=cip->channel->bans;cbp;cbp=cbp->next) {
-      for (rbp=rcp->bans;rbp;rbp=rbp->next) {
-       if (banequal(rbp->cbp, cbp))
-         break;
-      }
-      if (!rbp) {
-       if (rcp->banduration) {
-         exp=(cbp->timeset + rcp->banduration) - time(NULL);
-       } else {
-         exp=0;
-       } 
-       chanservsendmessage(sender, " #%-2d %-29s %-18s %-15s",++i,bantostring(cbp),
-                           exp ? longtoduration(exp,0) : "Permanent",
-                           "(channel ban)");
-      }
-    }
-    chanservstdmessage(sender, QM_ENDOFLIST);
-  } else {
-    chanservstdmessage(sender, QM_NOBANS, cip->name->content);
-  }
-      
-  return CMD_OK;
-}
-
-int csc_dobandel(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regban **rbh, *rbp;
-  chanban *cbp;
-  regchan *rcp;
-  chanban *theban=NULL;
-  modechanges changes;
-  int i,banid=0;
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unban");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "unban", 0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  /* OK, let's see what they want to remove.. */
-  if (*cargv[1]=='#') {
-    /* Remove by ID number */
-    if (!(banid=strtoul(cargv[1]+1, NULL, 10))) {
-      chanservstdmessage(sender, QM_UNKNOWNBAN, cargv[1], cip->name->content);
-      return CMD_ERROR;
-    }
-  } else {
-    /* Remove by ban string */
-    theban=makeban(cargv[1]);
-  }
-   
-  i=0;
-  for (rbh=&(rcp->bans);*rbh;rbh=&((*rbh)->next)) {
-    i++;
-    if ((banid  && i==banid) ||
-       (theban && banequal(theban, (*rbh)->cbp))) {
-      /* got it - they will need master access to remove this */
-      rbp=*rbh;
-      
-      if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, "unban", 0, 0))
-       return CMD_ERROR;
-      
-      chanservstdmessage(sender, QM_REMOVEDPERMBAN, bantostring(rbp->cbp), cip->name->content);
-      if (cip->channel) {
-       localsetmodeinit(&changes, cip->channel, chanservnick);    
-       localdosetmode_ban(&changes, bantostring(rbp->cbp), MCB_DEL);
-       localsetmodeflush(&changes, 1);
-      }
-      
-      /* Remove from database */
-      csdb_deleteban(rbp);
-      /* Remove from list */
-      (*rbh)=rbp->next;
-      /* Free ban/string and actual regban */
-      freesstring(rbp->reason);
-      freechanban(rbp->cbp);
-      freeregban(rbp);
-
-      if (theban)
-       freechanban(theban);
-
-      return CMD_OK;
-    }
-  }
-  
-  /* If we've run out of registered bans, let's try channel bans */
-  if (cip->channel && cip->channel->bans) {
-    for (cbp=cip->channel->bans;cbp;cbp=cbp->next) {
-      for (rbp=rcp->bans;rbp;rbp=rbp->next) {
-       if (banequal(rbp->cbp,cbp))
-         break;
-      }
-      
-      if (rbp)
-       continue;
-      
-      i++;
-      if ((banid  && (i==banid)) ||
-         (theban && banequal(theban, cbp))) {
-       /* got it - this is just a channel ban */
-       chanservstdmessage(sender, QM_REMOVEDCHANBAN, bantostring(cbp), cip->name->content);
-       localsetmodeinit(&changes, cip->channel, chanservnick);
-       localdosetmode_ban(&changes, cargv[1], MCB_DEL);
-       localsetmodeflush(&changes, 1);
-
-       if (theban)
-         freechanban(theban);
-       
-       return CMD_OK;
-      }
-    }
-  }
-       
-  chanservstdmessage(sender, QM_UNKNOWNBAN, cargv[1], cip->name->content);
-
-  return CMD_OK;
-} 
-  
-int csc_dobanclear(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regban **rbh, *rbp;
-  chanban **cbh, *cbp;
-  regchan *rcp;
-  modechanges changes;
-  char *banstr;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "banclear");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "banclear", 0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  if (cip->channel)
-    localsetmodeinit(&changes, cip->channel, chanservnick);
-    
-  for (rbh=&(rcp->bans); *rbh; ) {
-    rbp=*rbh;
-    banstr=bantostring(rbp->cbp);
-    chanservstdmessage(sender, QM_REMOVEDPERMBAN, banstr, cip->name->content);
-    if (cip->channel)
-      localdosetmode_ban(&changes, banstr, MCB_DEL);
-    /* Remove from database */
-    csdb_deleteban(rbp);
-    /* Remove from list */
-    (*rbh)=rbp->next;
-    /* Free ban/string and update setby refcount, and free actual regban */
-    freesstring(rbp->reason);
-    freechanban(rbp->cbp);
-    freeregban(rbp);
-  }
-
-  if (cip->channel) {
-    for (cbh=&(cip->channel->bans); *cbh; ) {
-      cbp=*cbh;
-      banstr=bantostring(cbp);
-      chanservstdmessage(sender, QM_REMOVEDCHANBAN, banstr, cip->name->content);
-      localdosetmode_ban(&changes, banstr, MCB_DEL);
-    }
-    localsetmodeflush(&changes,1);
-  }
-    
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}
-      
-int csc_dounbanmask(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regban **rbh, *rbp;
-  chanban **cbh, *cbp;
-  regchan *rcp;
-  chanban *theban;
-  modechanges changes;
-  char *banstr;
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unbanmask");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "unbanmask", 0, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-  theban=makeban(cargv[1]);
-
-  if (cip->channel)
-    localsetmodeinit(&changes, cip->channel, chanservnick);
-    
-  for (rbh=&(rcp->bans); *rbh; ) {
-    rbp=*rbh;
-    if (banoverlap(theban, rbp->cbp)) {
-      banstr=bantostring(rbp->cbp);
-      /* Check perms and remove */
-      if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, NULL, 0, 1)) {
-       chanservstdmessage(sender, QM_NOTREMOVEDPERMBAN, banstr, cip->name->content);
-       rbh=&(rbp->next);
-      } else {
-       chanservstdmessage(sender, QM_REMOVEDPERMBAN, banstr, cip->name->content);
-       if (cip->channel)
-         localdosetmode_ban(&changes, banstr, MCB_DEL);
-       /* Remove from database */
-       csdb_deleteban(rbp);
-       /* Remove from list */
-       (*rbh)=rbp->next;
-       /* Free ban/string and update setby refcount, and free actual regban */
-       freesstring(rbp->reason);
-       freechanban(rbp->cbp);
-       freeregban(rbp);
-      }
-    } else {
-      rbh=&(rbp->next);
-    }
-  }
-
-  if (cip->channel) {
-    for (cbh=&(cip->channel->bans); *cbh; ) {
-      cbp=*cbh;
-      if (banoverlap(theban, cbp)) {
-       /* Remove */
-       banstr=bantostring(cbp);
-       chanservstdmessage(sender, QM_REMOVEDCHANBAN, banstr, cip->name->content);
-       localdosetmode_ban(&changes, banstr, MCB_DEL);
-      } else {
-       cbh=&(cbp->next);
-      }
-    }
-    localsetmodeflush(&changes,1);
-  }
-  
-  
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}
-      
-int csc_dorenchan(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  chanindex *cip1,*cip2;
-  regchan *rcp;
-
-  if (!rup)
-    return CMD_ERROR;
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "renchan");
-    return CMD_ERROR;
-  }
-
-  if (!(cip1=findchanindex(cargv[0])) || !(rcp=cip1->exts[chanservext])) {
-    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
-    return CMD_ERROR;
-  }
-
-  if (*cargv[1] != '#') {
-    chanservstdmessage(sender, QM_INVALIDCHANNAME, cargv[0]);
-    return CMD_ERROR;
-  } 
-
-  if (!(cip2=findorcreatechanindex(cargv[1])) || cip2->exts[chanservext]) {
-    chanservstdmessage(sender, QM_ALREADYREGISTERED, cip2->name->content);
-    return CMD_ERROR;
-  }
-
-  cs_log(sender,"RENCHAN %s -> %s",cip1->name->content,cip2->name->content);
-
-  /* Remove from the channel.  Don't bother if the channel doesn't exist. */
-  if (!CIsSuspended(rcp) && cip1->channel) {
-    CSetSuspended(rcp);    
-    chanservjoinchan(cip1->channel);
-    CClearSuspended(rcp);
-  }
-  
-  cip1->exts[chanservext]=NULL;
-  releasechanindex(cip1);
-
-  cip2->exts[chanservext]=rcp;
-  rcp->index=cip2;
-  if (cip2->channel) {
-    chanservjoinchan(cip2->channel);
-  }
-
-  csdb_updatechannel(rcp);
-  chanservstdmessage(sender, QM_DONE);
-
-  return CMD_OK;
-}
-
-int csc_dochannelcomment(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  regchan *rcp;
-  chanindex *cip;
-  char buf[300];
-  int bufpos;
-
-  if (!rup)
-    return CMD_ERROR;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "channelcomment");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
-    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
-    return CMD_ERROR;
-  }
-
-  if (cargc>1) {
-    if (!ircd_strcmp(cargv[1],"none")) {
-      freesstring(rcp->comment);
-      rcp->comment=NULL;
-    } else {
-      if (*cargv[1]=='+') {
-       if (rcp->comment) {
-         strcpy(buf,rcp->comment->content);
-         bufpos=rcp->comment->length;
-         buf[bufpos++]=' ';
-       } else {
-         bufpos=0;
-       }
-       strncpy(buf+bufpos, cargv[1]+1, 250-bufpos);
-      } else {
-       strncpy(buf, cargv[1], 250);
-      }
-    
-      freesstring(rcp->comment);
-      rcp->comment=getsstring(buf,250);
-    }
-    csdb_updatechannel(rcp);
-  }
-  
-  if (rcp->comment) 
-    chanservstdmessage(sender, QM_COMMENT, cip->name->content, rcp->comment->content);
-  else
-    chanservstdmessage(sender, QM_NOCOMMENT, cip->name->content);
-
-  return CMD_OK;
-}
-
-int csc_dorejoin(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regchan *rcp;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "rejoin");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
-    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
-    return CMD_ERROR;
-  }
-
-  if (CIsJoined(rcp) && !CIsSuspended(rcp)) {
-    CSetSuspended(rcp);
-    chanservjoinchan(cip->channel);
-    CClearSuspended(rcp);
-    chanservjoinchan(cip->channel);
-  }
-
-  chanservstdmessage(sender, QM_DONE);
-
-  return CMD_OK;
-}
-
-int csc_dochantype(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regchan *rcp;
-  int type;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "chantype");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
-    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
-    return CMD_ERROR;
-  }
-
-  if (cargc>1) {
-    /* Set type */
-    for (type=CHANTYPES-1;type;type--) {
-      if (!ircd_strcmp(chantypes[type]->content, cargv[1]))
-       break;
-    }
-    if (!type) {
-      chanservstdmessage(sender, QM_UNKNOWNCHANTYPE, cargv[1]);
-      return CMD_ERROR;
-    }
-    rcp->chantype=type;
-
-    csdb_updatechannel(rcp);
-    chanservstdmessage(sender, QM_DONE);
-  }
-
-  chanservstdmessage(sender, QM_CHANTYPEIS, cip->name->content, chantypes[rcp->chantype]->content);
-
-  return CMD_OK;
-}
-
-int csc_doadduser(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regchanuser *rcup;
-  regchan *rcp;
-  reguser *rup;
-  int i;
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "adduser");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "adduser", QPRIV_CHANGECHANLEV, 0)))
-    return CMD_ERROR;
-
-  rcp=cip->exts[chanservext];
-
-  for (i=1;i<cargc;i++) {
-    if (!(rup=findreguser(sender, cargv[i])))
-      continue;
-
-    if ((rcup=findreguseronchannel(rcp, rup))) {
-      chanservstdmessage(sender, QM_ALREADYKNOWNONCHAN, cargv[i], cip->name->content);
-      continue;
-    }
-
-    rcup=getregchanuser();
-    rcup->chan=rcp;
-    rcup->user=rup;
-    rcup->flags = QCUFLAG_OP | QCUFLAG_AUTOOP | QCUFLAG_TOPIC;
-    rcup->changetime=time(NULL);
-    rcup->usetime=0;
-    rcup->info=NULL;
-   
-    cs_log(sender,"CHANLEV %s #%s +aot (+ -> +aot)",cip->name->content,rup->username);
-    addregusertochannel(rcup);
-    csdb_createchanuser(rcup);
-  }
-
-  rcp->status |= QCSTAT_OPCHECK;
-  cs_timerfunc(cip);
-
-  chanservstdmessage(sender, QM_DONE);
-
-  return CMD_OK;
-}
-
-int csc_doremoveuser(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regchanuser *rcup;
-  regchan *rcp;
-  reguser *rup;
-  int isowner=0;
-  int i;
-
-  if (cargc<2) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "removeuser");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "adduser", QPRIV_CHANGECHANLEV, 0)))
-    return CMD_ERROR;
-
-  if (cs_checkaccess(sender, NULL, CA_OWNERPRIV, cip, "adduser", QPRIV_CHANGECHANLEV, 1))
-    isowner=1;
-
-  rcp=cip->exts[chanservext];
-
-  for (i=1;i<cargc;i++) {
-    if (!(rup=findreguser(sender, cargv[i])))
-      continue;
-
-    if (!(rcup=findreguseronchannel(rcp, rup))) {
-      chanservstdmessage(sender, QM_CHANUSERUNKNOWN, cargv[i], cip->name->content);
-      continue;
-    }
-
-    if (CUIsOwner(rcup)) {
-      chanservstdmessage(sender, QM_CANNOTREMOVEOWNER, cargv[i], cip->name->content);
-      continue;
-    }
-
-    if (CUIsMaster(rcup) && !isowner && (rup != getreguserfromnick(sender))) {
-      chanservstdmessage(sender, QM_CANNOTREMOVEMASTER, cargv[i], cip->name->content);
-      continue;
-    }
-    
-    cs_log(sender,"CHANLEV %s #%s -%s (%s -> +)",cip->name->content,rup->username,
-          printflags_noprefix(rcup->flags, rcuflags), printflags(rcup->flags, rcuflags));
-
-    csdb_deletechanuser(rcup);
-    delreguserfromchannel(rcp, rup);
-  }
-
-  rcp->status |= QCSTAT_OPCHECK;
-  cs_timerfunc(cip);
-
-  chanservstdmessage(sender, QM_DONE);
-
-  return CMD_OK;
-}
-
-int csc_dochanstat(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  chanindex *cip;
-  regchan *rcp;
-  char timebuf[30];
-  
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "chanstat");
-    return CMD_ERROR;
-  }
-
-  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV,
-                          NULL, "chanstat", QPRIV_VIEWFULLCHANLEV, 0)))
-    return CMD_ERROR;
-  
-  rcp=cip->exts[chanservext];
-
-  chanservstdmessage(sender, QM_STATSHEADER, cip->name->content);
-
-  strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(rcp->created)));
-  chanservstdmessage(sender, QM_STATSADDED, timebuf);
-
-  /* Show opers founder/addedby/type info */
-  if (cs_privcheck(QPRIV_VIEWFULLCHANLEV, sender)) {
-    reguser *founder=NULL, *addedby=NULL;
-
-    strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(rcp->lastactive)));
-    chanservstdmessage(sender, QM_STATSLASTACTIVE, timebuf);
-
-
-    addedby=findreguserbyID(rcp->addedby);
-    chanservstdmessage(sender, QM_ADDEDBY, addedby ? addedby->username : "(unknown)");
-    founder=findreguserbyID(rcp->founder);
-    chanservstdmessage(sender, QM_FOUNDER, founder ? founder->username : "(unknown)");      
-    chanservstdmessage(sender, QM_CHANTYPE, chantypes[rcp->chantype]->content);
-  }
-
-  strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(rcp->created)));
-
-  chanservstdmessage(sender, QM_STATSJOINS, timebuf, rcp->maxusers, rcp->totaljoins, 
-                    (float)rcp->totaljoins/ ((time(NULL)-rcp->created)/(3600*24)));
-
-  strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(rcp->statsreset)));
-
-  chanservstdmessage(sender, QM_STATSJOINS, timebuf, rcp->tripusers, rcp->tripjoins, 
-                    (float)rcp->tripjoins / ((time(NULL)-rcp->statsreset)/(3600*24)));
-
-  return CMD_OK;
-}
diff --git a/chanserv/chancmds/Makefile b/chanserv/chancmds/Makefile
new file mode 100644 (file)
index 0000000..60bb66c
--- /dev/null
@@ -0,0 +1,10 @@
+# Automatically generated Makefile, do not edit.
+
+.PHONY: all Makefile
+all: Makefile chanserv_chancmds.so
+
+Makefile:
+       ../mkcommandlist.pl chanserv_chancmds.so
+
+chanserv_chancmds.so: addchan.o adduser.o autolimit.o banclear.o bandel.o banlist.o bantimer.o chanflags.o chanlev.o chanmode.o channelcomment.o chanstat.o chantype.o clearchan.o delchan.o deopall.o devoiceall.o invite.o op.o permban.o recover.o rejoin.o removeuser.o renchan.o settopic.o suspendchan.o suspendchanlist.o tempban.o unbanall.o unbanmask.o unbanme.o unsuspendchan.o voice.o welcome.o commandlist.o 
+        ld -shared -Bdynamic -o $@ $^ 
diff --git a/chanserv/chancmds/addchan.c b/chanserv/chancmds/addchan.c
new file mode 100644 (file)
index 0000000..607e7fc
--- /dev/null
@@ -0,0 +1,155 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: addchan
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 4
+ * CMDDESC: Adds a new channel to the bot.
+ * CMDFUNC: csc_doaddchan
+ * CMDPROTO: int csc_doaddchan(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_doaddchan(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  chanindex *cip;
+  regchan *rcp;
+  regchanuser *rcup;
+  reguser *founder;
+  flag_t flags;
+  short type=0;
+  
+  if (!rup)
+    return CMD_ERROR;
+    
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "addchan");
+    return CMD_ERROR;
+  }
+  
+  if (*cargv[0] != '#') {
+    chanservstdmessage(sender, QM_INVALIDCHANNAME, cargv[0]);
+    return CMD_ERROR;
+  } 
+  
+  if (cargc>1) {
+    if (!(founder=findreguser(sender, cargv[1])))
+      return CMD_ERROR;
+  } else {
+    founder=rup;
+  }      
+  
+  if (cargc>2) {
+    flags=0;
+    setflags(&flags, QCFLAG_ALL, cargv[2], rcflags, REJECT_NONE);    
+  } else {
+    flags = (QCFLAG_JOINED | QCFLAG_BITCH | QCFLAG_PROTECT | QCFLAG_ENFORCE);
+  }
+  
+  /* Pick up the chantype */
+  if (cargc>3) {
+    for (type=CHANTYPES-1;type;type--) {
+      if (!ircd_strcmp(chantypes[type]->content, cargv[3]))
+       break;
+    }
+    if (!type) {
+      chanservstdmessage(sender, QM_UNKNOWNCHANTYPE, cargv[3]);
+      return CMD_ERROR;
+    }
+  }
+  
+  if (!(cip=findorcreatechanindex(cargv[0]))) {
+    chanservstdmessage(sender, QM_INVALIDCHANNAME, cargv[0]);
+    return CMD_ERROR;
+  }
+  
+  if (cip->exts[chanservext]) {
+    chanservstdmessage(sender, QM_ALREADYREGISTERED, cip->name->content);
+    return CMD_ERROR;
+  }
+  
+  /* 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=CHANMODE_NOEXTMSG | CHANMODE_TOPICLIMIT;
+  rcp->denymodes=0;
+
+  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=1800;
+  rcp->autoupdate=0;
+  rcp->lastbancheck=0;
+  
+  /* Added by */
+  rcp->addedby=rup->ID;
+  
+  /* Founder */
+  rcp->founder=founder->ID;
+  /* Suspend by */
+  rcp->suspendby=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;
+
+  /* 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);
+
+  /* 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);
+  }
+
+  cs_log(sender, "ADDCHAN %s #%s %s %s",cip->name->content,founder->username,printflags(rcp->flags,rcflags), chantypes[type]->content);
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/adduser.c b/chanserv/chancmds/adduser.c
new file mode 100644 (file)
index 0000000..d778e61
--- /dev/null
@@ -0,0 +1,69 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: adduser
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 20
+ * CMDDESC: Adds one or more users to a channel as +aot.
+ * CMDFUNC: csc_doadduser
+ * CMDPROTO: int csc_doadduser(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_doadduser(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regchanuser *rcup;
+  regchan *rcp;
+  reguser *rup;
+  int i;
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "adduser");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "adduser", QPRIV_CHANGECHANLEV, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  for (i=1;i<cargc;i++) {
+    if (!(rup=findreguser(sender, cargv[i])))
+      continue;
+
+    if ((rcup=findreguseronchannel(rcp, rup))) {
+      chanservstdmessage(sender, QM_ALREADYKNOWNONCHAN, cargv[i], cip->name->content);
+      continue;
+    }
+
+    rcup=getregchanuser();
+    rcup->chan=rcp;
+    rcup->user=rup;
+    rcup->flags = QCUFLAG_OP | QCUFLAG_AUTOOP | QCUFLAG_TOPIC;
+    rcup->changetime=time(NULL);
+    rcup->usetime=0;
+    rcup->info=NULL;
+   
+    cs_log(sender,"CHANLEV %s #%s +aot (+ -> +aot)",cip->name->content,rup->username);
+    addregusertochannel(rcup);
+    csdb_createchanuser(rcup);
+  }
+
+  rcp->status |= QCSTAT_OPCHECK;
+  cs_timerfunc(cip);
+
+  chanservstdmessage(sender, QM_DONE);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/autolimit.c b/chanserv/chancmds/autolimit.c
new file mode 100644 (file)
index 0000000..6427017
--- /dev/null
@@ -0,0 +1,61 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: autolimit
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 2
+ * CMDDESC: Shows or changes the autolimit threshold on a channel.
+ * CMDFUNC: csc_doautolimit
+ * CMDPROTO: int csc_doautolimit(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_doautolimit(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regchan *rcp;
+  int oldlimit;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "autolimit");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV,
+                          NULL, "autolimit", QPRIV_VIEWAUTOLIMIT, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cargc>1) {
+    if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, 
+                       cip, "autolimit", QPRIV_CHANGEAUTOLIMIT, 0))
+      return CMD_ERROR;
+
+    oldlimit=rcp->autolimit;
+    rcp->autolimit=strtol(cargv[1],NULL,10);
+
+    if (rcp->autolimit<1)
+      rcp->autolimit=1;
+    
+    csdb_updatechannel(rcp);
+    
+    cs_log(sender,"AUTOLIMIT %s %s (%d -> %d)",cip->name->content,cargv[1],oldlimit,rcp->autolimit);
+    chanservstdmessage(sender, QM_DONE);
+    rcp->limit=0;
+    cs_timerfunc(cip);
+  }
+
+  chanservstdmessage(sender, QM_CHANAUTOLIMIT, cargv[0], rcp->autolimit);
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/banclear.c b/chanserv/chancmds/banclear.c
new file mode 100644 (file)
index 0000000..9024e48
--- /dev/null
@@ -0,0 +1,73 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: banclear
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Removes all bans from a channel including persistent bans.
+ * CMDFUNC: csc_dobanclear
+ * CMDPROTO: int csc_dobanclear(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dobanclear(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regban **rbh, *rbp;
+  chanban **cbh, *cbp;
+  regchan *rcp;
+  modechanges changes;
+  char *banstr;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "banclear");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "banclear", 0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cip->channel)
+    localsetmodeinit(&changes, cip->channel, chanservnick);
+    
+  for (rbh=&(rcp->bans); *rbh; ) {
+    rbp=*rbh;
+    banstr=bantostring(rbp->cbp);
+    chanservstdmessage(sender, QM_REMOVEDPERMBAN, banstr, cip->name->content);
+    if (cip->channel)
+      localdosetmode_ban(&changes, banstr, MCB_DEL);
+    /* Remove from database */
+    csdb_deleteban(rbp);
+    /* Remove from list */
+    (*rbh)=rbp->next;
+    /* Free ban/string and update setby refcount, and free actual regban */
+    freesstring(rbp->reason);
+    freechanban(rbp->cbp);
+    freeregban(rbp);
+  }
+
+  if (cip->channel) {
+    for (cbh=&(cip->channel->bans); *cbh; ) {
+      cbp=*cbh;
+      banstr=bantostring(cbp);
+      chanservstdmessage(sender, QM_REMOVEDCHANBAN, banstr, cip->name->content);
+      localdosetmode_ban(&changes, banstr, MCB_DEL);
+    }
+    localsetmodeflush(&changes,1);
+  }
+    
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/bandel.c b/chanserv/chancmds/bandel.c
new file mode 100644 (file)
index 0000000..7c2a30e
--- /dev/null
@@ -0,0 +1,120 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: bandel
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 2
+ * CMDDESC: Removes a single ban from a channel.
+ * CMDFUNC: csc_dobandel
+ * CMDPROTO: int csc_dobandel(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dobandel(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regban **rbh, *rbp;
+  chanban *cbp;
+  regchan *rcp;
+  chanban *theban=NULL;
+  modechanges changes;
+  int i,banid=0;
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unban");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "unban", 0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  /* OK, let's see what they want to remove.. */
+  if (*cargv[1]=='#') {
+    /* Remove by ID number */
+    if (!(banid=strtoul(cargv[1]+1, NULL, 10))) {
+      chanservstdmessage(sender, QM_UNKNOWNBAN, cargv[1], cip->name->content);
+      return CMD_ERROR;
+    }
+  } else {
+    /* Remove by ban string */
+    theban=makeban(cargv[1]);
+  }
+   
+  i=0;
+  for (rbh=&(rcp->bans);*rbh;rbh=&((*rbh)->next)) {
+    i++;
+    if ((banid  && i==banid) ||
+       (theban && banequal(theban, (*rbh)->cbp))) {
+      /* got it - they will need master access to remove this */
+      rbp=*rbh;
+      
+      if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, "unban", 0, 0))
+       return CMD_ERROR;
+      
+      chanservstdmessage(sender, QM_REMOVEDPERMBAN, bantostring(rbp->cbp), cip->name->content);
+      if (cip->channel) {
+       localsetmodeinit(&changes, cip->channel, chanservnick);    
+       localdosetmode_ban(&changes, bantostring(rbp->cbp), MCB_DEL);
+       localsetmodeflush(&changes, 1);
+      }
+      
+      /* Remove from database */
+      csdb_deleteban(rbp);
+      /* Remove from list */
+      (*rbh)=rbp->next;
+      /* Free ban/string and actual regban */
+      freesstring(rbp->reason);
+      freechanban(rbp->cbp);
+      freeregban(rbp);
+
+      if (theban)
+       freechanban(theban);
+
+      return CMD_OK;
+    }
+  }
+  
+  /* If we've run out of registered bans, let's try channel bans */
+  if (cip->channel && cip->channel->bans) {
+    for (cbp=cip->channel->bans;cbp;cbp=cbp->next) {
+      for (rbp=rcp->bans;rbp;rbp=rbp->next) {
+       if (banequal(rbp->cbp,cbp))
+         break;
+      }
+      
+      if (rbp)
+       continue;
+      
+      i++;
+      if ((banid  && (i==banid)) ||
+         (theban && banequal(theban, cbp))) {
+       /* got it - this is just a channel ban */
+       chanservstdmessage(sender, QM_REMOVEDCHANBAN, bantostring(cbp), cip->name->content);
+       localsetmodeinit(&changes, cip->channel, chanservnick);
+       localdosetmode_ban(&changes, cargv[1], MCB_DEL);
+       localsetmodeflush(&changes, 1);
+
+       if (theban)
+         freechanban(theban);
+       
+       return CMD_OK;
+      }
+    }
+  }
+       
+  chanservstdmessage(sender, QM_UNKNOWNBAN, cargv[1], cip->name->content);
+
+  return CMD_OK;
+} 
diff --git a/chanserv/chancmds/banlist.c b/chanserv/chancmds/banlist.c
new file mode 100644 (file)
index 0000000..e442e1d
--- /dev/null
@@ -0,0 +1,74 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: banlist
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Displays all persistent bans on a channel.
+ * CMDFUNC: csc_dobanlist
+ * CMDPROTO: int csc_dobanlist(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dobanlist(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regchan *rcp;
+  regban *rbp;
+  reguser *rup;
+  chanban *cbp;
+  int i=0;
+  int exp;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "banlist");
+    return CMD_ERROR;
+  }
+  
+  if(!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "banlist", 0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+  
+  if (rcp->bans || cip->channel->bans) {
+    chanservstdmessage(sender, QM_REGBANHEADER, cip->name->content);
+    for(rbp=rcp->bans;rbp;rbp=rbp->next) {
+      rup=findreguserbyID(rbp->setby);
+      chanservsendmessage(sender," #%-2d %-29s %-18s %-15s  %s",++i,bantostring(rbp->cbp),
+                         rbp->expiry?longtoduration(rbp->expiry-time(NULL),0):"Permanent",
+                         rup?rup->username:"<unknown>",
+                         rbp->reason?rbp->reason->content:"");
+    }
+    for (cbp=cip->channel->bans;cbp;cbp=cbp->next) {
+      for (rbp=rcp->bans;rbp;rbp=rbp->next) {
+       if (banequal(rbp->cbp, cbp))
+         break;
+      }
+      if (!rbp) {
+       if (rcp->banduration) {
+         exp=(cbp->timeset + rcp->banduration) - time(NULL);
+       } else {
+         exp=0;
+       } 
+       chanservsendmessage(sender, " #%-2d %-29s %-18s %-15s",++i,bantostring(cbp),
+                           exp ? longtoduration(exp,0) : "Permanent",
+                           "(channel ban)");
+      }
+    }
+    chanservstdmessage(sender, QM_ENDOFLIST);
+  } else {
+    chanservstdmessage(sender, QM_NOBANS, cip->name->content);
+  }
+      
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/bantimer.c b/chanserv/chancmds/bantimer.c
new file mode 100644 (file)
index 0000000..204d9d5
--- /dev/null
@@ -0,0 +1,68 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: bantimer
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 2
+ * CMDDESC: Shows or changes the time after which bans are removed.
+ * CMDFUNC: csc_dobantimer
+ * CMDPROTO: int csc_dobantimer(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dobantimer(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regchan *rcp;
+  int oldtimer;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "bantimer");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "bantimer",
+                          QPRIV_VIEWBANTIMER, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cargc>1) {
+    if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, "bantimer",
+                       QPRIV_CHANGEBANTIMER, 0))
+      return CMD_ERROR;
+
+    oldtimer=rcp->banduration;
+    rcp->banduration=durationtolong(cargv[1]);
+
+    if (rcp->banduration<0)
+      rcp->banduration=0;
+    
+    /* Arbitrary limit */
+    if (rcp->banduration > 31622400)
+      rcp->banduration = 31622400;
+      
+    csdb_updatechannel(rcp);
+    
+    cs_log(sender,"BANTIMER %s %s (%u -> %u)",cip->name->content,cargv[1],oldtimer,rcp->banduration);
+    chanservstdmessage(sender, QM_DONE);
+    cs_timerfunc(cip);
+  }
+
+  if (rcp->banduration)
+    chanservstdmessage(sender, QM_CHANBANAUTOREMOVE, cargv[0], longtoduration(rcp->banduration, 1));
+  else
+    chanservstdmessage(sender, QM_NOCHANBANAUTOREMOVE, cargv[0]);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/chanflags.c b/chanserv/chancmds/chanflags.c
new file mode 100644 (file)
index 0000000..6f8276a
--- /dev/null
@@ -0,0 +1,95 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: chanflags
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 2
+ * CMDDESC: Shows or changes the flags on a channel.
+ * CMDFUNC: csc_dochanflags
+ * CMDPROTO: int csc_dochanflags(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dochanflags(void *source, int cargc, char **cargv) {
+  regchan *rcp;
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  chanindex *cip;
+  flag_t oldflags,changemask;
+  char flagbuf[20];
+
+  if (cargc<1) {
+    chanservstdmessage(sender,QM_NOTENOUGHPARAMS,"chanflags");
+    return CMD_ERROR;
+  }
+  
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, 
+                          "chanflags", QPRIV_VIEWCHANFLAGS, 0))) 
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cargc>1) {
+    if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, "chanflags", 
+                       QPRIV_CHANGECHANFLAGS, 0))
+      return CMD_ERROR;
+
+    oldflags=rcp->flags;
+    changemask=QCFLAG_USERCONTROL;
+    if (UIsDev(rup)) {
+      changemask=QCFLAG_ALL;
+    }
+    setflags(&rcp->flags, changemask, cargv[1], rcflags, REJECT_NONE);
+
+    /* We might need to do things in response to the flag changes.. */
+    if (cip->channel) {
+      if ((oldflags ^ rcp->flags) & (QCFLAG_JOINED | QCFLAG_SUSPENDED)) {
+        chanservjoinchan(cip->channel);
+       rcp->status |= (QCSTAT_OPCHECK | QCSTAT_MODECHECK | QCSTAT_BANCHECK);
+       rcp->lastbancheck=0;
+       cs_timerfunc(cip);
+      } else {
+        if (CIsEnforce(rcp)) {
+         rcp->lastbancheck=0;
+          cs_checkbans(cip->channel);  
+       }
+    
+        if (CIsProtect(rcp) || CIsBitch(rcp) || CIsAutoOp(rcp) || CIsAutoVoice(rcp) || CIsKnownOnly(rcp)) {
+         rcp->status |= QCSTAT_OPCHECK;
+         cs_timerfunc(cip);
+       }
+      }
+    }
+    
+    if (CIsAutoLimit(rcp) && !(oldflags & QCFLAG_AUTOLIMIT)) {
+      rcp->forcemodes |= CHANMODE_LIMIT;
+      rcp->denymodes &= ~CHANMODE_LIMIT;
+      rcp->limit=0;
+      cs_timerfunc(cip);
+    }
+
+    if (!CIsAutoLimit(rcp) && (oldflags & QCFLAG_AUTOLIMIT)) {
+      rcp->forcemodes &= ~CHANMODE_LIMIT;
+      if (cip->channel) 
+        cs_checkchanmodes(cip->channel);
+    }
+
+    strcpy(flagbuf,printflags(oldflags, rcflags));
+    cs_log(sender,"CHANFLAGS %s %s (%s -> %s)",cip->name->content,cargv[1],flagbuf,printflags(rcp->flags,rcflags));
+    chanservstdmessage(sender, QM_DONE);
+    csdb_updatechannel(rcp);
+  }
+  
+  chanservstdmessage(sender,QM_CURCHANFLAGS,cip->name->content,printflags(rcp->flags, rcflags));
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/chanlev.c b/chanserv/chancmds/chanlev.c
new file mode 100644 (file)
index 0000000..d969870
--- /dev/null
@@ -0,0 +1,289 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: chanlev
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 3
+ * CMDDESC: Shows or modifies user access on a channel.
+ * CMDFUNC: csc_dochanlev
+ * CMDPROTO: int csc_dochanlev(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int compareflags(const void *u1, const void *u2) {
+  const regchanuser *r1=*(void **)u1, *r2=*(void **)u2;
+  flag_t f1,f2;
+
+  for (f1=QCUFLAG_OWNER;f1;f1>>=1)
+    if (r1->flags & f1)
+      break;
+
+  for (f2=QCUFLAG_OWNER;f2;f2>>=1)
+    if (r2->flags & f2)
+      break;
+
+  if (f1==f2) {
+    return ircd_strcmp(r1->user->username, r2->user->username);
+  } else {
+    return f2-f1;
+  }
+}
+
+int csc_dochanlev(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regchan *rcp;
+  regchanuser *rcup, *rcuplist;
+  regchanuser **rusers;
+  reguser *rup=getreguserfromnick(sender), *target;
+  char time1[15],time2[15];
+  char flagbuf[30];
+  struct tm *tmp;
+  flag_t flagmask, changemask, flags, oldflags;
+  int showtimes=0;
+  int donehead=0;
+  int i,j;
+  int newuser=0;
+  int usercount;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "chanlev");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_KNOWN,
+                          NULL, "chanlev", QPRIV_VIEWFULLCHANLEV, 0)))
+    return CMD_ERROR;
+  
+  rcp=cip->exts[chanservext];
+  rcup=findreguseronchannel(rcp, rup);
+
+  /* Set flagmask for +v/+o users (can't see bans etc.) */
+  flagmask = (QCUFLAG_OWNER | QCUFLAG_MASTER | QCUFLAG_OP | QCUFLAG_VOICE | QCUFLAG_AUTOVOICE | 
+             QCUFLAG_AUTOOP | QCUFLAG_TOPIC | QCUFLAG_SPAMCON | QCUFLAG_PROTECT | QCUFLAG_KNOWN);
+  
+  /* If user has +m or above, or helper access, show everything */
+  if (cs_privcheck(QPRIV_VIEWFULLCHANLEV, sender) || CUHasMasterPriv(rcup)) {
+    flagmask = QCUFLAG_ALL;
+    showtimes=1;
+  }
+  
+  if (cargc==1) {
+    /* One arg: list chanlev */
+    if (cs_privcheck(QPRIV_VIEWFULLCHANLEV, sender)) {
+      reguser *founder=NULL, *addedby=NULL;
+      addedby=findreguserbyID(rcp->addedby);
+      chanservstdmessage(sender, QM_ADDEDBY, addedby ? addedby->username : "(unknown)");
+      founder=findreguserbyID(rcp->founder);
+      chanservstdmessage(sender, QM_FOUNDER, founder ? founder->username : "(unknown)");
+      if (rcp->chantype) {
+        chanservstdmessage(sender, QM_CHANTYPE, chantypes[rcp->chantype]->content);
+      }
+    }
+
+    /* Count users */
+    for (i=0,usercount=0;i<REGCHANUSERHASHSIZE;i++)
+      for (rcuplist=rcp->regusers[i];rcuplist;rcuplist=rcuplist->nextbychan)
+       usercount++;
+    
+    /* Allocate array */
+    rusers=(regchanuser **)malloc(usercount * sizeof(regchanuser *));
+
+    /* Fill array */
+    for (j=i=0;i<REGCHANUSERHASHSIZE;i++) {
+      for (rcuplist=rcp->regusers[i];rcuplist;rcuplist=rcuplist->nextbychan) {
+       if (!(flags=rcuplist->flags & flagmask))
+         continue;
+       
+       rusers[j++]=rcuplist;
+      }
+    }
+
+    /* Sort */
+    qsort(rusers, j, sizeof(regchanuser *), compareflags);
+
+    /* List */
+    for (i=0;i<j;i++) {
+      rcuplist=rusers[i];
+
+      if (!(flags=rcuplist->flags & flagmask)) 
+       continue;
+      
+      if (!donehead) {
+       chanservstdmessage(sender, QM_CHANLEVHEADER, cip->name->content);
+       if (showtimes) 
+         chanservstdmessage(sender, QM_CHANLEVCOLFULL);
+       else
+         chanservstdmessage(sender, QM_CHANLEVCOLSHORT);
+       donehead=1;
+      }
+      
+      if (showtimes) {
+       if (!rcuplist->usetime) {
+         strcpy(time1,"Never");
+       } else {
+         tmp=localtime(&(rcuplist->usetime));
+         strftime(time1,15,"%d/%m/%y %H:%M",tmp);
+       }
+       if (!rcuplist->changetime) {
+         strcpy(time2, "Unknown");
+       } else {
+         tmp=localtime(&(rcuplist->changetime));
+         strftime(time2,15,"%d/%m/%y %H:%M",tmp);
+       }
+       chanservsendmessage(sender, " %-15s %-13s %-14s  %-14s  %s", rcuplist->user->username, 
+                           printflags(flags, rcuflags), time1, time2, rcuplist->info?rcuplist->info->content:"");
+      } else 
+       chanservsendmessage(sender, " %-15s %s", rcuplist->user->username, printflags(flags, rcuflags));
+    }
+    
+    if (donehead) {
+      chanservstdmessage(sender, QM_ENDOFLIST);
+    } else {
+      chanservstdmessage(sender, QM_NOUSERSONCHANLEV, cip->name->content);
+    }
+
+    free(rusers);
+  } else {
+    /* 2 or more args.. relates to one specific user */
+    if (!(target=findreguser(sender, cargv[1])))
+      return CMD_ERROR; /* If there was an error, findreguser will have sent a message saying why.. */
+    
+    rcuplist=findreguseronchannel(rcp, target);
+    
+    if (cargc>2) {
+      /* To change chanlev you have to either.. */
+      if (!( cs_privcheck(QPRIV_CHANGECHANLEV, sender) ||             /* Have override privilege */
+            (rcup && rcuplist && (rcup==rcuplist) && CUKnown(rcup)) || /* Be manipulting yourself (oo er..) */
+            (rcup && CUHasMasterPriv(rcup) &&                        /* Have +m or +n on the channel */
+             !(rcuplist && CUIsOwner(rcuplist) && !CUIsOwner(rcup))) /* masters can't screw with owners */
+            )) {
+       chanservstdmessage(sender, QM_NOACCESSONCHAN, cip->name->content, "chanlev");
+       return CMD_ERROR;
+      }
+      
+      if (!rcuplist) {
+       rcuplist=getregchanuser();
+       rcuplist->user=target;
+       rcuplist->chan=rcp;
+       rcuplist->flags=0;
+       rcuplist->changetime=time(NULL);
+       rcuplist->usetime=0;
+       rcuplist->info=NULL;
+       newuser=1;
+      }
+      
+      if (cs_privcheck(QPRIV_CHANGECHANLEV, sender)) {
+       /* Opers are allowed to change everything */
+       changemask = QCUFLAG_ALL;
+      } else {
+       changemask=0;
+       
+       /* Everyone can change their own flags (except +dqb), and turn +iwj on/off */
+       if (rcup==rcuplist) {
+         changemask = (rcup->flags | QCUFLAG_HIDEWELCOME | QCUFLAG_HIDEINFO | QCUFLAG_AUTOINVITE) & 
+                     ~(QCUFLAG_BANNED | QCUFLAG_DENY | QCUFLAG_QUIET);
+         flagmask |= (QCUFLAG_HIDEWELCOME | QCUFLAG_HIDEINFO | QCUFLAG_AUTOINVITE);
+       }
+       
+       /* Masters are allowed to manipulate +ovagtbqdpk */
+       if (CUHasMasterPriv(rcup))
+         changemask |= ( QCUFLAG_KNOWN | QCUFLAG_OP | QCUFLAG_VOICE | QCUFLAG_AUTOOP | QCUFLAG_AUTOVOICE | 
+                         QCUFLAG_TOPIC | QCUFLAG_BANNED | QCUFLAG_QUIET | QCUFLAG_DENY | QCUFLAG_PROTECT);
+       
+       /* Owners are allowed to manipulate +ms as well */
+       if (CUIsOwner(rcup))
+         changemask |= ( QCUFLAG_MASTER | QCUFLAG_SPAMCON );
+      }
+
+      oldflags=rcuplist->flags;
+      if (setflags(&(rcuplist->flags), changemask, cargv[2], rcuflags, REJECT_UNKNOWN | REJECT_DISALLOWED)) {
+       chanservstdmessage(sender, QM_INVALIDCHANLEVCHANGE);
+       return CMD_ERROR;
+      }
+
+      /* Now fix up some "impossible" combinations.. */
+      /* +m can't be any of +qdb */
+      if (CUHasMasterPriv(rcuplist))
+       rcuplist->flags &= ~(QCUFLAG_BANNED | QCUFLAG_QUIET | QCUFLAG_DENY);
+      
+      /* +d can't be +o */
+      if (CUIsDeny(rcuplist))
+       rcuplist->flags &= ~QCUFLAG_OP;
+
+      /* +q can't be +v */
+      if (CUIsQuiet(rcuplist))
+       rcuplist->flags &= ~QCUFLAG_VOICE;
+
+      /* -o or +p can't be +a */
+      if (!CUIsOp(rcuplist) || CUIsProtect(rcuplist))
+       rcuplist->flags &= ~QCUFLAG_AUTOOP;
+      
+      /* +a or -v or +p can't be +g */
+      if (!CUIsVoice(rcuplist) || CUIsAutoOp(rcuplist) || CUIsProtect(rcuplist))
+       rcuplist->flags &= ~QCUFLAG_AUTOVOICE;
+
+      /* and -ov can't be +p */
+      if (!CUIsOp(rcuplist) && !CUIsVoice(rcuplist)) 
+       rcuplist->flags &= ~QCUFLAG_PROTECT;
+
+      /* Check if anything "significant" has changed */
+      if ((oldflags ^ rcuplist->flags) & (QCUFLAG_OWNER | QCUFLAG_MASTER | QCUFLAG_OP))
+       rcuplist->changetime=time(NULL);
+
+      strcpy(flagbuf,printflags(oldflags,rcuflags));
+      cs_log(sender,"CHANLEV %s #%s %s (%s -> %s)",cip->name->content,rcuplist->user->username,cargv[2],
+            flagbuf,printflags(rcuplist->flags,rcuflags));
+
+      /* Now see what we do next */
+      if (rcuplist->flags) {
+       /* User still valid: update or create */
+       if (newuser) {
+         addregusertochannel(rcuplist);
+         csdb_createchanuser(rcuplist);
+       } else {
+         csdb_updatechanuser(rcuplist);
+       }
+      } else {
+       /* User has no flags: delete */
+       if (!newuser) {
+         csdb_deletechanuser(rcuplist);
+         delreguserfromchannel(rcp, target);
+       }
+       freeregchanuser(rcuplist);
+       rcuplist=NULL;
+        for (i=0;i<REGCHANUSERHASHSIZE;i++)
+          if (rcp->regusers[i])
+            break;
+        if (i==REGCHANUSERHASHSIZE) {
+         cs_log(sender,"DELCHAN %s (Cleared chanlev)",cip->name->content);
+          cs_removechannel(rcp);       
+       }
+      }
+
+      /* Say we've done it */
+      chanservstdmessage(sender, QM_DONE);
+      rcp->status |= QCSTAT_OPCHECK;
+      cs_timerfunc(cip);
+    }
+    
+    if (rcuplist && (rcuplist->flags & flagmask)) {
+      chanservstdmessage(sender, QM_CHANUSERFLAGS, cargv[1], cip->name->content, 
+                        printflags(rcuplist->flags & flagmask, rcuflags));
+    } else {
+      chanservstdmessage(sender, QM_CHANUSERUNKNOWN, cargv[1], cip->name->content);
+    }
+  }
+  
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/chanmode.c b/chanserv/chancmds/chanmode.c
new file mode 100644 (file)
index 0000000..ff69e66
--- /dev/null
@@ -0,0 +1,151 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: chanmode
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 4
+ * CMDDESC: Shows which modes are forced or denied on a channel.
+ * CMDFUNC: csc_dochanmode
+ * CMDPROTO: int csc_dochanmode(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+char *getchanmode(regchan *rcp) {
+  static char buf1[50];
+  char buf2[30];
+
+  if (rcp->forcemodes) {
+    strcpy(buf1,printflags(rcp->forcemodes, cmodeflags));
+  } else {
+    buf1[0]='\0';
+  }
+
+  strcpy(buf2,printflagdiff(CHANMODE_ALL, ~(rcp->denymodes), cmodeflags));
+  strcat(buf1, buf2);
+
+  if (rcp->forcemodes & CHANMODE_LIMIT) {
+    sprintf(buf2, " %d",rcp->limit);
+    strcat(buf1, buf2);
+  }
+
+  if (rcp->forcemodes & CHANMODE_KEY) {
+    sprintf(buf2, " %s",rcp->key->content);
+    strcat(buf1, buf2);
+  }
+
+  if (*buf1=='\0') {
+    strcpy(buf1,"(none)");
+  }
+
+  return buf1;
+}
+
+int csc_dochanmode(void *source, int cargc, char **cargv) {
+  regchan *rcp;
+  nick *sender=source;
+  chanindex *cip;
+  flag_t forceflags,denyflags;
+  char buf1[60];
+  int carg=2,limdone=0;
+  sstring *newkey=NULL;
+  unsigned int newlim=0;
+
+  if (cargc<1) {
+    chanservstdmessage(sender,QM_NOTENOUGHPARAMS,"chanmode");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, 
+                          NULL, "chanmode", QPRIV_VIEWCHANMODES, 0)))
+    return CMD_ERROR;
+  
+  rcp=cip->exts[chanservext];
+
+  if (cargc>1) {
+    if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV,
+                       cip, "chanmode", QPRIV_CHANGECHANMODES, 0))
+      return CMD_ERROR;
+
+    /* Save the current modes.. */
+    strcpy(buf1,getchanmode(rcp));
+
+    /* Pick out the + flags: start from 0 */
+    forceflags=0;
+    setflags(&forceflags, CHANMODE_ALL, cargv[1], cmodeflags, REJECT_NONE);    
+
+    /* Pick out the - flags: start from everything and invert afterwards.. */
+    denyflags=CHANMODE_ALL;
+    setflags(&denyflags, CHANMODE_ALL, cargv[1], cmodeflags, REJECT_NONE);
+    denyflags = (~denyflags) & CHANMODE_ALL;
+
+    forceflags &= ~denyflags; /* Can't force and deny the same mode (shouldn't be possible anyway) */
+    if (forceflags & CHANMODE_SECRET) {
+      forceflags &= ~CHANMODE_PRIVATE;
+      denyflags |= CHANMODE_PRIVATE;
+    }
+    if (forceflags & CHANMODE_PRIVATE) {
+      forceflags &= ~CHANMODE_SECRET;
+      denyflags |= CHANMODE_SECRET;
+    }
+
+    if ((forceflags & CHANMODE_LIMIT) && 
+       (!(forceflags & CHANMODE_KEY) || strrchr(cargv[1],'l') < strrchr(cargv[1],'k'))) {
+      if (cargc<=carg) {
+       chanservstdmessage(sender,QM_NOTENOUGHPARAMS,"chanmode");
+       return CMD_ERROR;
+      }
+      newlim=strtol(cargv[carg++],NULL,10);
+      limdone=1;
+    }
+
+    if (forceflags & CHANMODE_KEY) {
+      if (cargc<=carg) {
+       chanservstdmessage(sender,QM_NOTENOUGHPARAMS,"chanmode");
+       return CMD_ERROR;
+      }
+      newkey=getsstring(cargv[carg++], KEYLEN);
+    }
+
+    if ((forceflags & CHANMODE_LIMIT) && !limdone) {
+      if (cargc<=carg) {
+       chanservstdmessage(sender,QM_NOTENOUGHPARAMS,"chanmode");
+       return CMD_ERROR;
+      }
+      newlim=strtol(cargv[carg++],NULL,10);
+      limdone=1;
+    }
+
+    if (CIsAutoLimit(rcp)) {
+      forceflags |= CHANMODE_LIMIT;
+      denyflags &= ~CHANMODE_LIMIT;
+      newlim=rcp->limit;
+    }
+
+    /* It parsed OK, so update the structure.. */
+    rcp->forcemodes=forceflags;
+    rcp->denymodes=denyflags;      
+    if (rcp->key)
+      freesstring(rcp->key);
+    rcp->key=newkey;
+    rcp->limit=newlim;
+    
+    chanservstdmessage(sender, QM_DONE);
+    cs_log(sender,"CHANMODE %s %s (%s -> %s)",cip->name->content,cargv[1],buf1,getchanmode(rcp));
+    csdb_updatechannel(rcp);
+    cs_checkchanmodes(cip->channel);    
+  }
+  
+  chanservstdmessage(sender,QM_CURFORCEMODES,cip->name->content,getchanmode(rcp));
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/channelcomment.c b/chanserv/chancmds/channelcomment.c
new file mode 100644 (file)
index 0000000..1b5023d
--- /dev/null
@@ -0,0 +1,74 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: channelcomment
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 2
+ * CMDDESC: Shows or changes the staff comment for a channel.
+ * CMDFUNC: csc_dochannelcomment
+ * CMDPROTO: int csc_dochannelcomment(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dochannelcomment(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  regchan *rcp;
+  chanindex *cip;
+  char buf[300];
+  int bufpos;
+
+  if (!rup)
+    return CMD_ERROR;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "channelcomment");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
+    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
+    return CMD_ERROR;
+  }
+
+  if (cargc>1) {
+    if (!ircd_strcmp(cargv[1],"none")) {
+      freesstring(rcp->comment);
+      rcp->comment=NULL;
+    } else {
+      if (*cargv[1]=='+') {
+       if (rcp->comment) {
+         strcpy(buf,rcp->comment->content);
+         bufpos=rcp->comment->length;
+         buf[bufpos++]=' ';
+       } else {
+         bufpos=0;
+       }
+       strncpy(buf+bufpos, cargv[1]+1, 250-bufpos);
+      } else {
+       strncpy(buf, cargv[1], 250);
+      }
+    
+      freesstring(rcp->comment);
+      rcp->comment=getsstring(buf,250);
+    }
+    csdb_updatechannel(rcp);
+  }
+  
+  if (rcp->comment) 
+    chanservstdmessage(sender, QM_COMMENT, cip->name->content, rcp->comment->content);
+  else
+    chanservstdmessage(sender, QM_NOCOMMENT, cip->name->content);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/chanstat.c b/chanserv/chancmds/chanstat.c
new file mode 100644 (file)
index 0000000..128f78b
--- /dev/null
@@ -0,0 +1,71 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: chanstat
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Displays channel activity statistics.
+ * CMDFUNC: csc_dochanstat
+ * CMDPROTO: int csc_dochanstat(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dochanstat(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regchan *rcp;
+  char timebuf[30];
+  
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "chanstat");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV,
+                          NULL, "chanstat", QPRIV_VIEWFULLCHANLEV, 0)))
+    return CMD_ERROR;
+  
+  rcp=cip->exts[chanservext];
+
+  chanservstdmessage(sender, QM_STATSHEADER, cip->name->content);
+
+  strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(rcp->created)));
+  chanservstdmessage(sender, QM_STATSADDED, timebuf);
+
+  /* Show opers founder/addedby/type info */
+  if (cs_privcheck(QPRIV_VIEWFULLCHANLEV, sender)) {
+    reguser *founder=NULL, *addedby=NULL;
+
+    strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(rcp->lastactive)));
+    chanservstdmessage(sender, QM_STATSLASTACTIVE, timebuf);
+
+
+    addedby=findreguserbyID(rcp->addedby);
+    chanservstdmessage(sender, QM_ADDEDBY, addedby ? addedby->username : "(unknown)");
+    founder=findreguserbyID(rcp->founder);
+    chanservstdmessage(sender, QM_FOUNDER, founder ? founder->username : "(unknown)");      
+    chanservstdmessage(sender, QM_CHANTYPE, chantypes[rcp->chantype]->content);
+  }
+
+  strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(rcp->created)));
+
+  chanservstdmessage(sender, QM_STATSJOINS, timebuf, rcp->maxusers, rcp->totaljoins, 
+                    (float)rcp->totaljoins/ ((time(NULL)-rcp->created)/(3600*24)));
+
+  strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(rcp->statsreset)));
+
+  chanservstdmessage(sender, QM_STATSJOINS, timebuf, rcp->tripusers, rcp->tripjoins, 
+                    (float)rcp->tripjoins / ((time(NULL)-rcp->statsreset)/(3600*24)));
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/chantype.c b/chanserv/chancmds/chantype.c
new file mode 100644 (file)
index 0000000..bcb3f42
--- /dev/null
@@ -0,0 +1,58 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: chantype
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 2
+ * CMDDESC: Shows or changes a channel's type.
+ * CMDFUNC: csc_dochantype
+ * CMDPROTO: int csc_dochantype(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dochantype(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regchan *rcp;
+  int type;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "chantype");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
+    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
+    return CMD_ERROR;
+  }
+
+  if (cargc>1) {
+    /* Set type */
+    for (type=CHANTYPES-1;type;type--) {
+      if (!ircd_strcmp(chantypes[type]->content, cargv[1]))
+       break;
+    }
+    if (!type) {
+      chanservstdmessage(sender, QM_UNKNOWNCHANTYPE, cargv[1]);
+      return CMD_ERROR;
+    }
+    rcp->chantype=type;
+
+    csdb_updatechannel(rcp);
+    chanservstdmessage(sender, QM_DONE);
+  }
+
+  chanservstdmessage(sender, QM_CHANTYPEIS, cip->name->content, chantypes[rcp->chantype]->content);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/clearchan.c b/chanserv/chancmds/clearchan.c
new file mode 100644 (file)
index 0000000..d3f9edd
--- /dev/null
@@ -0,0 +1,50 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: clearchan
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Removes all modes from a channel.
+ * CMDFUNC: csc_doclearchan
+ * CMDPROTO: int csc_doclearchan(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_doclearchan(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  regchan *rcp;
+  chanindex *cip;
+  modechanges changes;
+  
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "clearchan");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "clearchan",0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cip->channel) {
+    localsetmodeinit(&changes, cip->channel, chanservnick);
+    localdosetmode_key(&changes, NULL, MCB_DEL);
+    localdosetmode_simple(&changes, 0, cip->channel->flags);
+    cs_docheckchanmodes(cip->channel, &changes);
+    localsetmodeflush(&changes, 1);
+  }
+
+  cs_log(sender,"CLEARCHAN %s",cip->name->content);
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}     
diff --git a/chanserv/chancmds/commandlist.c b/chanserv/chancmds/commandlist.c
new file mode 100644 (file)
index 0000000..834e3cc
--- /dev/null
@@ -0,0 +1,113 @@
+/* Automatically generated by mkcommandlist.pl, do not edit. */
+
+#include "../chanserv.h"
+
+/* Prototypes */
+int csc_doaddchan(void *source, int cargc, char **cargv);
+int csc_doadduser(void *source, int cargc, char **cargv);
+int csc_doautolimit(void *source, int cargc, char **cargv);
+int csc_dobanclear(void *source, int cargc, char **cargv);
+int csc_dobandel(void *source, int cargc, char **cargv);
+int csc_dobanlist(void *source, int cargc, char **cargv);
+int csc_dobantimer(void *source, int cargc, char **cargv);
+int csc_dochanflags(void *source, int cargc, char **cargv);
+int csc_dochanlev(void *source, int cargc, char **cargv);
+int csc_dochanmode(void *source, int cargc, char **cargv);
+int csc_dochannelcomment(void *source, int cargc, char **cargv);
+int csc_dochanstat(void *source, int cargc, char **cargv);
+int csc_dochantype(void *source, int cargc, char **cargv);
+int csc_doclearchan(void *source, int cargc, char **cargv);
+int csc_dodelchan(void *source, int cargc, char **cargv);
+int csc_dodeopall(void *source, int cargc, char **cargv);
+int csc_dodevoiceall(void *source, int cargc, char **cargv);
+int csc_doinvite(void *source, int cargc, char **cargv);
+int csc_doop(void *source, int cargc, char **cargv);
+int csc_dopermban(void *source, int cargc, char **cargv);
+int csc_dorecover(void *source, int cargc, char **cargv);
+int csc_dorejoin(void *source, int cargc, char **cargv);
+int csc_doremoveuser(void *source, int cargc, char **cargv);
+int csc_dorenchan(void *source, int cargc, char **cargv);
+int csc_dosettopic(void *source, int cargc, char **cargv);
+int csc_dosuspendchan(void *source, int cargc, char **cargv);
+int csc_dosuspendchanlist(void *source, int cargc, char **cargv);
+int csc_dotempban(void *source, int cargc, char **cargv);
+int csc_dounbanall(void *source, int cargc, char **cargv);
+int csc_dounbanmask(void *source, int cargc, char **cargv);
+int csc_dounbanme(void *source, int cargc, char **cargv);
+int csc_dounsuspendchan(void *source, int cargc, char **cargv);
+int csc_dovoice(void *source, int cargc, char **cargv);
+int csc_dowelcome(void *source, int cargc, char **cargv);
+
+void _init() {
+  chanservaddcommand("addchan", QCMD_OPER, 4, csc_doaddchan, "Adds a new channel to the bot.");
+  chanservaddcommand("adduser", QCMD_AUTHED, 20, csc_doadduser, "Adds one or more users to a channel as +aot.");
+  chanservaddcommand("autolimit", QCMD_AUTHED, 2, csc_doautolimit, "Shows or changes the autolimit threshold on a channel.");
+  chanservaddcommand("banclear", QCMD_AUTHED, 1, csc_dobanclear, "Removes all bans from a channel including persistent bans.");
+  chanservaddcommand("bandel", QCMD_AUTHED, 2, csc_dobandel, "Removes a single ban from a channel.");
+  chanservaddcommand("banlist", QCMD_AUTHED, 1, csc_dobanlist, "Displays all persistent bans on a channel.");
+  chanservaddcommand("bantimer", QCMD_AUTHED, 2, csc_dobantimer, "Shows or changes the time after which bans are removed.");
+  chanservaddcommand("chanflags", QCMD_AUTHED, 2, csc_dochanflags, "Shows or changes the flags on a channel.");
+  chanservaddcommand("chanlev", QCMD_AUTHED, 3, csc_dochanlev, "Shows or modifies user access on a channel.");
+  chanservaddcommand("chanmode", QCMD_AUTHED, 4, csc_dochanmode, "Shows which modes are forced or denied on a channel.");
+  chanservaddcommand("channelcomment", QCMD_OPER, 2, csc_dochannelcomment, "Shows or changes the staff comment for a channel.");
+  chanservaddcommand("chanstat", QCMD_AUTHED, 1, csc_dochanstat, "Displays channel activity statistics.");
+  chanservaddcommand("chantype", QCMD_OPER, 2, csc_dochantype, "Shows or changes a channel's type.");
+  chanservaddcommand("clearchan", QCMD_AUTHED, 1, csc_doclearchan, "Removes all modes from a channel.");
+  chanservaddcommand("delchan", QCMD_OPER, 2, csc_dodelchan, "Removes a channel from the bot.");
+  chanservaddcommand("deopall", QCMD_AUTHED, 1, csc_dodeopall, "Deops all users on channel.");
+  chanservaddcommand("devoiceall", QCMD_AUTHED, 1, csc_dodevoiceall, "Devoices all users on a channel.");
+  chanservaddcommand("invite", QCMD_AUTHED, 1, csc_doinvite, "Invites you to a channel.");
+  chanservaddcommand("op", QCMD_AUTHED, 20, csc_doop, "Ops you or other users on channel(s).");
+  chanservaddcommand("permban", QCMD_AUTHED, 3, csc_dopermban, "Permanently bans a hostmask on a channel.");
+  chanservaddcommand("recover", QCMD_AUTHED, 1, csc_dorecover, "Recovers a channel (same as deopall, unbanall, clearchan).");
+  chanservaddcommand("rejoin", QCMD_OPER, 1, csc_dorejoin, "Makes the bot rejoin a channel.");
+  chanservaddcommand("removeuser", QCMD_AUTHED, 20, csc_doremoveuser, "Removes one or more users from a channel.");
+  chanservaddcommand("renchan", QCMD_OPER, 2, csc_dorenchan, "Renames a channel on the bot.");
+  chanservaddcommand("settopic", QCMD_AUTHED, 2, csc_dosettopic, "Changes the topic on a channel.");
+  chanservaddcommand("suspendchan", QCMD_OPER, 2, csc_dosuspendchan, "Suspends a channel from the bot.");
+  chanservaddcommand("suspendchanlist", QCMD_HELPER, 1, csc_dosuspendchanlist, "Lists suspended channels.");
+  chanservaddcommand("tempban", QCMD_AUTHED, 4, csc_dotempban, "Bans a hostmask on a channel for a specified time period.");
+  chanservaddcommand("unbanall", QCMD_AUTHED, 1, csc_dounbanall, "Removes all bans from a channel.");
+  chanservaddcommand("unbanmask", QCMD_AUTHED, 2, csc_dounbanmask, "Removes bans matching a particular mask from a channel.");
+  chanservaddcommand("unbanme", QCMD_AUTHED, 1, csc_dounbanme, "Removes any bans affecting you from a channel.");
+  chanservaddcommand("unsuspendchan", QCMD_OPER, 1, csc_dounsuspendchan, "Unsuspends a channel from the bot.");
+  chanservaddcommand("voice", QCMD_AUTHED, 20, csc_dovoice, "Voices you or other users on channel(s).");
+  chanservaddcommand("welcome", QCMD_AUTHED, 2, csc_dowelcome, "Shows or changes the welcome message on a channel.");
+}
+
+void _fini() {
+  chanservremovecommand("addchan", csc_doaddchan);
+  chanservremovecommand("adduser", csc_doadduser);
+  chanservremovecommand("autolimit", csc_doautolimit);
+  chanservremovecommand("banclear", csc_dobanclear);
+  chanservremovecommand("bandel", csc_dobandel);
+  chanservremovecommand("banlist", csc_dobanlist);
+  chanservremovecommand("bantimer", csc_dobantimer);
+  chanservremovecommand("chanflags", csc_dochanflags);
+  chanservremovecommand("chanlev", csc_dochanlev);
+  chanservremovecommand("chanmode", csc_dochanmode);
+  chanservremovecommand("channelcomment", csc_dochannelcomment);
+  chanservremovecommand("chanstat", csc_dochanstat);
+  chanservremovecommand("chantype", csc_dochantype);
+  chanservremovecommand("clearchan", csc_doclearchan);
+  chanservremovecommand("delchan", csc_dodelchan);
+  chanservremovecommand("deopall", csc_dodeopall);
+  chanservremovecommand("devoiceall", csc_dodevoiceall);
+  chanservremovecommand("invite", csc_doinvite);
+  chanservremovecommand("op", csc_doop);
+  chanservremovecommand("permban", csc_dopermban);
+  chanservremovecommand("recover", csc_dorecover);
+  chanservremovecommand("rejoin", csc_dorejoin);
+  chanservremovecommand("removeuser", csc_doremoveuser);
+  chanservremovecommand("renchan", csc_dorenchan);
+  chanservremovecommand("settopic", csc_dosettopic);
+  chanservremovecommand("suspendchan", csc_dosuspendchan);
+  chanservremovecommand("suspendchanlist", csc_dosuspendchanlist);
+  chanservremovecommand("tempban", csc_dotempban);
+  chanservremovecommand("unbanall", csc_dounbanall);
+  chanservremovecommand("unbanmask", csc_dounbanmask);
+  chanservremovecommand("unbanme", csc_dounbanme);
+  chanservremovecommand("unsuspendchan", csc_dounsuspendchan);
+  chanservremovecommand("voice", csc_dovoice);
+  chanservremovecommand("welcome", csc_dowelcome);
+}
diff --git a/chanserv/chancmds/delchan.c b/chanserv/chancmds/delchan.c
new file mode 100644 (file)
index 0000000..d516bfd
--- /dev/null
@@ -0,0 +1,47 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: delchan
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 2
+ * CMDDESC: Removes a channel from the bot.
+ * CMDFUNC: csc_dodelchan
+ * CMDPROTO: int csc_dodelchan(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dodelchan(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  chanindex *cip;
+  regchan *rcp;
+
+  if (!rup)
+    return CMD_ERROR;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "delchan");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
+    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
+    return CMD_ERROR;
+  }
+
+  cs_log(sender,"DELCHAN %s (%s)",cip->name->content,cargc>1?cargv[1]:"");
+  cs_removechannel(rcp);
+  chanservstdmessage(sender, QM_DONE);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/deopall.c b/chanserv/chancmds/deopall.c
new file mode 100644 (file)
index 0000000..5469d19
--- /dev/null
@@ -0,0 +1,64 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: deopall
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Deops all users on channel.
+ * CMDFUNC: csc_dodeopall
+ * CMDPROTO: int csc_dodeopall(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dodeopall(void *source, int cargc, char **cargv) {
+  nick *sender=source,*np;
+  reguser *rup;
+  regchanuser *rcup;
+  regchan *rcp;
+  chanindex *cip;
+  unsigned long *lp;
+  int i;
+  modechanges changes;
+  
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "deopall");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "deopall",0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cip->channel) {
+    localsetmodeinit(&changes, cip->channel, chanservnick);
+
+    for (i=0,lp=cip->channel->users->content;
+        i<cip->channel->users->hashsize;i++,lp++) {
+      if (*lp!=nouser && (*lp & CUMODE_OP)) {
+       if (!(np=getnickbynumeric(*lp)) || 
+           (!IsService(np) && (!(rup=getreguserfromnick(np)) || 
+           !(rcup=findreguseronchannel(rcp, rup)) || !(CUHasOpPriv(rcup)) ||
+           !(CUIsProtect(rcup) || CIsProtect(rcp))))) {
+         localdosetmode_nick(&changes, np, MC_DEOP);
+       }
+      }
+    }
+
+    localsetmodeflush(&changes, 1);
+  }
+
+  cs_log(sender,"DEOPALL %s",cip->name->content);
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}     
diff --git a/chanserv/chancmds/devoiceall.c b/chanserv/chancmds/devoiceall.c
new file mode 100644 (file)
index 0000000..a84dc6d
--- /dev/null
@@ -0,0 +1,64 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: devoiceall
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Devoices all users on a channel.
+ * CMDFUNC: csc_dodevoiceall
+ * CMDPROTO: int csc_dodevoiceall(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dodevoiceall(void *source, int cargc, char **cargv) {
+  nick *sender=source,*np;
+  reguser *rup;
+  regchanuser *rcup;
+  regchan *rcp;
+  chanindex *cip;
+  unsigned long *lp;
+  int i;
+  modechanges changes;
+  
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "devoiceall");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "devoiceall",0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cip->channel) {
+    localsetmodeinit(&changes, cip->channel, chanservnick);
+
+    for (i=0,lp=cip->channel->users->content;
+        i<cip->channel->users->hashsize;i++,lp++) {
+      if (*lp!=nouser && (*lp & CUMODE_VOICE)) {
+       if (!(np=getnickbynumeric(*lp)) || 
+           (!IsService(np) && (!(rup=getreguserfromnick(np)) || 
+           !(rcup=findreguseronchannel(rcp, rup)) || !(CUHasVoicePriv(rcup)) ||
+           !(CUIsProtect(rcup) || CIsProtect(rcp))))) {
+         localdosetmode_nick(&changes, np, MC_DEVOICE);
+       }
+      }
+    }
+
+    localsetmodeflush(&changes, 1);
+  }
+
+  cs_log(sender,"DEVOICEALL %s",cip->name->content);
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}     
diff --git a/chanserv/chancmds/invite.c b/chanserv/chancmds/invite.c
new file mode 100644 (file)
index 0000000..7eba00a
--- /dev/null
@@ -0,0 +1,42 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: invite
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Invites you to a channel.
+ * CMDFUNC: csc_doinvite
+ * CMDPROTO: int csc_doinvite(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_doinvite(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "invite");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_KNOWN | CA_OFFCHAN, 
+                          NULL, "invite", 0, 0)))
+    return CMD_ERROR;
+
+  if (cip->channel) {
+    localinvite(chanservnick, cip->channel, sender);
+  }
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/op.c b/chanserv/chancmds/op.c
new file mode 100644 (file)
index 0000000..9971a07
--- /dev/null
@@ -0,0 +1,119 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: op
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 20
+ * CMDDESC: Ops you or other users on channel(s).
+ * CMDFUNC: csc_doop
+ * CMDPROTO: int csc_doop(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_doop(void *source, int cargc, char **cargv) {
+  nick *sender=source, *np;
+  reguser *rup=getreguserfromnick(sender);
+  chanindex *cip;
+  regchan *rcp=NULL;
+  regchanuser *rcup;
+  channel **ca;
+  unsigned long *lp;
+  int i;
+  modechanges changes;
+
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc==0) {
+    /* No args: "op me on every channel you can */
+    ca=sender->channels->content;
+    for (i=0;i<sender->channels->cursi;i++) {
+      if ((rcp=ca[i]->index->exts[chanservext]) && !CIsSuspended(rcp)) {
+       /* It's a Q channel */
+       if (!(*(getnumerichandlefromchanhash(ca[i]->users, sender->numeric)) & 
+             CUMODE_OP)) {
+         /* They're not opped */
+         if ((rcup=findreguseronchannel(rcp, rup)) && CUHasOpPriv(rcup) && 
+             !CUIsDeny(rcup)) {
+           /* And they have op priv on the chan: op them */
+           localsetmodeinit(&changes, ca[i], chanservnick);
+           localdosetmode_nick(&changes, sender, MC_OP);
+           localsetmodeflush(&changes,1);
+         }
+       }
+      }
+    }
+    
+    chanservstdmessage(sender, QM_DONE);
+    return CMD_OK;
+  }
+
+  /* If there is at least one arg, the first is a channel */
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "op", 0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cargc==1) {
+    /* Only one arg: "op me" */
+    if (!cs_checkaccess(sender, NULL, CA_OPPRIV | CA_DEOPPED, cip, "op", 0, 0))
+      return CMD_ERROR;
+    
+    localsetmodeinit(&changes, cip->channel, chanservnick);
+    localdosetmode_nick(&changes, sender, MC_OP);
+    localsetmodeflush(&changes,1);
+
+    chanservstdmessage(sender, QM_DONE);
+    return CMD_OK;
+  }
+
+  /* Set up the modes */
+  localsetmodeinit(&changes, cip->channel, chanservnick);
+
+  for(i=1;i<cargc;i++) {
+    if (!(np=getnickbynick(cargv[i]))) {
+      chanservstdmessage(sender, QM_UNKNOWNUSER, cargv[i]);
+      continue;
+    }
+
+    if (!(lp=getnumerichandlefromchanhash(cip->channel->users, np->numeric))) {
+      chanservstdmessage(sender, QM_USERNOTONCHAN, np->nick, cip->name->content);
+      continue;
+    }
+
+    if (*lp & CUMODE_OP) {
+      chanservstdmessage(sender, QM_USEROPPEDONCHAN, np->nick, cip->name->content);
+      continue;
+    }
+
+    rup=getreguserfromnick(np);
+    if (rup)
+      rcup=findreguseronchannel(rcp,rup);
+    else
+      rcup=NULL;
+
+    /* Bitch mode: check that this user is allowed to be opped.. */
+    if ((CIsBitch(rcp) && (!rcup || !CUHasOpPriv(rcup))) || (rcup && CUIsDeny(rcup))) {
+      chanservstdmessage(sender, QM_CANTOP, np->nick, cip->name->content);
+      continue;
+    }
+
+    localdosetmode_nick(&changes, np, MC_OP);
+  }
+
+  localsetmodeflush(&changes, 1);
+  chanservstdmessage(sender, QM_DONE);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/permban.c b/chanserv/chancmds/permban.c
new file mode 100644 (file)
index 0000000..695feb6
--- /dev/null
@@ -0,0 +1,57 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: permban
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 3
+ * CMDDESC: Permanently bans a hostmask on a channel.
+ * CMDFUNC: csc_dopermban
+ * CMDPROTO: int csc_dopermban(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dopermban(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regban *rbp;
+  regchan *rcp;
+  reguser *rup=getreguserfromnick(sender);
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "permban");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "permban",0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  rbp=getregban();
+  rbp->ID=++lastbanID;
+  rbp->cbp=makeban(cargv[1]);
+  rbp->setby=rup->ID;
+  rbp->expiry=0;
+  if (cargc>2)
+    rbp->reason=getsstring(cargv[2],200);
+  else
+    rbp->reason=NULL;
+  rbp->next=rcp->bans;
+  rcp->bans=rbp;
+
+  cs_setregban(cip, rbp);
+  csdb_createban(rcp, rbp);
+  
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/recover.c b/chanserv/chancmds/recover.c
new file mode 100644 (file)
index 0000000..5475874
--- /dev/null
@@ -0,0 +1,75 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: recover
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Recovers a channel (same as deopall, unbanall, clearchan).
+ * CMDFUNC: csc_dorecover
+ * CMDPROTO: int csc_dorecover(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dorecover(void *source, int cargc, char **cargv) {
+  nick *sender=source,*np;
+  reguser *rup;
+  regchanuser *rcup;
+  regchan *rcp;
+  chanindex *cip;
+  unsigned long *lp;
+  int i;
+  modechanges changes;
+  
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "recover");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "recover",0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cip->channel) {
+    localsetmodeinit(&changes, cip->channel, chanservnick);
+
+    /* clearchan */
+    localdosetmode_key(&changes, NULL, MCB_DEL);
+    localdosetmode_simple(&changes, 0, cip->channel->flags);
+    cs_docheckchanmodes(cip->channel, &changes);
+
+    /* unbanall */
+    while (cip->channel->bans) {
+      localdosetmode_ban(&changes, bantostring(cip->channel->bans), MCB_DEL);
+    }
+
+    /* deopall */
+    for (i=0,lp=cip->channel->users->content;
+        i<cip->channel->users->hashsize;i++,lp++) {
+      if (*lp!=nouser && (*lp & CUMODE_OP)) {
+       if (!(np=getnickbynumeric(*lp)) || 
+           (!IsService(np) && (!(rup=getreguserfromnick(np)) || 
+           !(rcup=findreguseronchannel(rcp, rup)) || !(CUHasOpPriv(rcup)) ||
+           !(CUIsProtect(rcup) || CIsProtect(rcp))))) {
+         localdosetmode_nick(&changes, np, MC_DEOP);
+       }
+      }
+    }
+
+    localsetmodeflush(&changes, 1);
+  }
+
+  cs_log(sender,"RECOVER %s",cip->name->content);
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}     
diff --git a/chanserv/chancmds/rejoin.c b/chanserv/chancmds/rejoin.c
new file mode 100644 (file)
index 0000000..20876f2
--- /dev/null
@@ -0,0 +1,48 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: rejoin
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 1
+ * CMDDESC: Makes the bot rejoin a channel.
+ * CMDFUNC: csc_dorejoin
+ * CMDPROTO: int csc_dorejoin(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dorejoin(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regchan *rcp;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "rejoin");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
+    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
+    return CMD_ERROR;
+  }
+
+  if (CIsJoined(rcp) && !CIsSuspended(rcp)) {
+    CSetSuspended(rcp);
+    chanservjoinchan(cip->channel);
+    CClearSuspended(rcp);
+    chanservjoinchan(cip->channel);
+  }
+
+  chanservstdmessage(sender, QM_DONE);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/removeuser.c b/chanserv/chancmds/removeuser.c
new file mode 100644 (file)
index 0000000..9bf4f2e
--- /dev/null
@@ -0,0 +1,77 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: removeuser
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 20
+ * CMDDESC: Removes one or more users from a channel.
+ * CMDFUNC: csc_doremoveuser
+ * CMDPROTO: int csc_doremoveuser(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_doremoveuser(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regchanuser *rcup;
+  regchan *rcp;
+  reguser *rup;
+  int isowner=0;
+  int i;
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "removeuser");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "adduser", QPRIV_CHANGECHANLEV, 0)))
+    return CMD_ERROR;
+
+  if (cs_checkaccess(sender, NULL, CA_OWNERPRIV, cip, "adduser", QPRIV_CHANGECHANLEV, 1))
+    isowner=1;
+
+  rcp=cip->exts[chanservext];
+
+  for (i=1;i<cargc;i++) {
+    if (!(rup=findreguser(sender, cargv[i])))
+      continue;
+
+    if (!(rcup=findreguseronchannel(rcp, rup))) {
+      chanservstdmessage(sender, QM_CHANUSERUNKNOWN, cargv[i], cip->name->content);
+      continue;
+    }
+
+    if (CUIsOwner(rcup)) {
+      chanservstdmessage(sender, QM_CANNOTREMOVEOWNER, cargv[i], cip->name->content);
+      continue;
+    }
+
+    if (CUIsMaster(rcup) && !isowner && (rup != getreguserfromnick(sender))) {
+      chanservstdmessage(sender, QM_CANNOTREMOVEMASTER, cargv[i], cip->name->content);
+      continue;
+    }
+    
+    cs_log(sender,"CHANLEV %s #%s -%s (%s -> +)",cip->name->content,rup->username,
+          printflags_noprefix(rcup->flags, rcuflags), printflags(rcup->flags, rcuflags));
+
+    csdb_deletechanuser(rcup);
+    delreguserfromchannel(rcp, rup);
+  }
+
+  rcp->status |= QCSTAT_OPCHECK;
+  cs_timerfunc(cip);
+
+  chanservstdmessage(sender, QM_DONE);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/renchan.c b/chanserv/chancmds/renchan.c
new file mode 100644 (file)
index 0000000..6113b83
--- /dev/null
@@ -0,0 +1,74 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: renchan
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 2
+ * CMDDESC: Renames a channel on the bot.
+ * CMDFUNC: csc_dorenchan
+ * CMDPROTO: int csc_dorenchan(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dorenchan(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  chanindex *cip1,*cip2;
+  regchan *rcp;
+
+  if (!rup)
+    return CMD_ERROR;
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "renchan");
+    return CMD_ERROR;
+  }
+
+  if (!(cip1=findchanindex(cargv[0])) || !(rcp=cip1->exts[chanservext])) {
+    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
+    return CMD_ERROR;
+  }
+
+  if (*cargv[1] != '#') {
+    chanservstdmessage(sender, QM_INVALIDCHANNAME, cargv[0]);
+    return CMD_ERROR;
+  } 
+
+  if (!(cip2=findorcreatechanindex(cargv[1])) || cip2->exts[chanservext]) {
+    chanservstdmessage(sender, QM_ALREADYREGISTERED, cip2->name->content);
+    return CMD_ERROR;
+  }
+
+  cs_log(sender,"RENCHAN %s -> %s",cip1->name->content,cip2->name->content);
+
+  /* Remove from the channel.  Don't bother if the channel doesn't exist. */
+  if (!CIsSuspended(rcp) && cip1->channel) {
+    CSetSuspended(rcp);    
+    chanservjoinchan(cip1->channel);
+    CClearSuspended(rcp);
+  }
+  
+  cip1->exts[chanservext]=NULL;
+  releasechanindex(cip1);
+
+  cip2->exts[chanservext]=rcp;
+  rcp->index=cip2;
+  if (cip2->channel) {
+    chanservjoinchan(cip2->channel);
+  }
+
+  csdb_updatechannel(rcp);
+  chanservstdmessage(sender, QM_DONE);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/settopic.c b/chanserv/chancmds/settopic.c
new file mode 100644 (file)
index 0000000..905113a
--- /dev/null
@@ -0,0 +1,52 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: settopic
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 2
+ * CMDDESC: Changes the topic on a channel.
+ * CMDFUNC: csc_dosettopic
+ * CMDPROTO: int csc_dosettopic(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dosettopic(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regchan *rcp;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "settopic");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_TOPICPRIV, 
+                          NULL, "settopic", 0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cargc>1) {
+    if (rcp->topic)
+      freesstring(rcp->topic);
+    rcp->topic=getsstring(cargv[1],TOPICLEN);
+  } 
+  
+  if (rcp->topic && cip->channel) {
+    localsettopic(chanservnick, cip->channel, rcp->topic->content);
+  }
+
+  chanservstdmessage(sender, QM_DONE);
+  csdb_updatechannel(rcp);
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/suspendchan.c b/chanserv/chancmds/suspendchan.c
new file mode 100644 (file)
index 0000000..e233ad8
--- /dev/null
@@ -0,0 +1,57 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: suspendchan
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 2
+ * CMDDESC: Suspends a channel from the bot.
+ * CMDFUNC: csc_dosuspendchan
+ * CMDPROTO: int csc_dosuspendchan(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dosuspendchan(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  chanindex *cip;
+  regchan *rcp;
+
+  if (!rup)
+    return CMD_ERROR;
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspendchan");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
+    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
+    return CMD_ERROR;
+  }
+
+  if (CIsSuspended(rcp)) {
+    chanservstdmessage(sender, QM_CHANNELALREADYSUSPENDED, cip->name->content);
+    return CMD_ERROR;
+  }
+
+  CSetSuspended(rcp);
+  rcp->suspendreason = getsstring(cargv[1], 250);
+  rcp->suspendby = rup->ID;
+  cs_log(sender,"SUSPENDCHAN %s (%s)",cip->name->content,rcp->suspendreason->content);
+  chanservjoinchan(cip->channel);
+
+  csdb_updatechannel(rcp);
+  chanservstdmessage(sender, QM_DONE);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/suspendchanlist.c b/chanserv/chancmds/suspendchanlist.c
new file mode 100644 (file)
index 0000000..b740a4d
--- /dev/null
@@ -0,0 +1,72 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: suspendchanlist
+ * CMDLEVEL: QCMD_HELPER
+ * CMDARGS: 1
+ * CMDDESC: Lists suspended channels.
+ * CMDFUNC: csc_dosuspendchanlist
+ * CMDPROTO: int csc_dosuspendchanlist(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dosuspendchanlist(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  chanindex *cip;
+  regchan *rcp;
+  int i;
+  char *bywhom;
+  unsigned int count=0;
+  
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc < 1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspendchanlist");
+    return CMD_ERROR;
+  }
+  
+  chanservstdmessage(sender, QM_SUSPENDCHANLISTHEADER);
+  for (i=0; i<CHANNELHASHSIZE; i++) {
+    for (cip=chantable[i]; cip; cip=cip->next) {
+      if (!(rcp=(regchan*)cip->exts[chanservext]))
+        continue;
+      
+      if (!CIsSuspended(rcp))
+        continue;
+      
+      if ((rcp->suspendby != rup->ID) && match(cargv[0], cip->name->content))
+        continue;
+      
+      if (rcp->suspendby == rup->ID)
+        bywhom=rup->username;
+      else {
+        reguser *trup=findreguserbyID(rcp->suspendby);
+        if (trup)
+          bywhom=trup->username;
+        else
+          bywhom="unknown";
+      }
+      count++;
+      chanservsendmessage(sender, "%-30s %-15s %s", cip->name->content, bywhom, rcp->suspendreason->content);
+      if (count >= 2000) {
+        chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "channels");
+        return CMD_ERROR;
+      }
+    }
+  }
+  chanservstdmessage(sender, QM_RESULTCOUNT, count, "channel", (count==1)?"":"s");
+  
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/tempban.c b/chanserv/chancmds/tempban.c
new file mode 100644 (file)
index 0000000..194a0b9
--- /dev/null
@@ -0,0 +1,60 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: tempban
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 4
+ * CMDDESC: Bans a hostmask on a channel for a specified time period.
+ * CMDFUNC: csc_dotempban
+ * CMDPROTO: int csc_dotempban(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dotempban(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regban *rbp;
+  regchan *rcp;
+  reguser *rup=getreguserfromnick(sender);
+  unsigned int duration;
+
+  if (cargc<3) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "tempban");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "tempban",0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  duration=durationtolong(cargv[2]);
+  
+  rbp=getregban();
+  rbp->ID=++lastbanID;
+  rbp->cbp=makeban(cargv[1]);
+  rbp->setby=rup->ID;
+  rbp->expiry=time(NULL)+duration;
+  if (cargc>3)
+    rbp->reason=getsstring(cargv[3],200);
+  else
+    rbp->reason=NULL;
+  rbp->next=rcp->bans;
+  rcp->bans=rbp;
+
+  cs_setregban(cip, rbp);
+  csdb_createban(rcp, rbp);
+  
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/unbanall.c b/chanserv/chancmds/unbanall.c
new file mode 100644 (file)
index 0000000..9298ba6
--- /dev/null
@@ -0,0 +1,52 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: unbanall
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Removes all bans from a channel.
+ * CMDFUNC: csc_dounbanall
+ * CMDPROTO: int csc_dounbanall(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dounbanall(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  regchan *rcp;
+  chanindex *cip;
+  modechanges changes;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unbanall");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_MASTERPRIV, NULL, "unbanall",0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cip->channel) {
+    localsetmodeinit(&changes, cip->channel, chanservnick);
+
+    while (cip->channel->bans) {
+      localdosetmode_ban(&changes, bantostring(cip->channel->bans), MCB_DEL);
+    }
+
+    localsetmodeflush(&changes, 1);
+  }
+
+  cs_log(sender,"UNBANALL %s",cip->name->content);
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}     
diff --git a/chanserv/chancmds/unbanmask.c b/chanserv/chancmds/unbanmask.c
new file mode 100644 (file)
index 0000000..dd4607d
--- /dev/null
@@ -0,0 +1,91 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: unbanmask
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 2
+ * CMDDESC: Removes bans matching a particular mask from a channel.
+ * CMDFUNC: csc_dounbanmask
+ * CMDPROTO: int csc_dounbanmask(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dounbanmask(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regban **rbh, *rbp;
+  chanban **cbh, *cbp;
+  regchan *rcp;
+  chanban *theban;
+  modechanges changes;
+  char *banstr;
+
+  if (cargc<2) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unbanmask");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "unbanmask", 0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+  theban=makeban(cargv[1]);
+
+  if (cip->channel)
+    localsetmodeinit(&changes, cip->channel, chanservnick);
+    
+  for (rbh=&(rcp->bans); *rbh; ) {
+    rbp=*rbh;
+    if (banoverlap(theban, rbp->cbp)) {
+      banstr=bantostring(rbp->cbp);
+      /* Check perms and remove */
+      if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, NULL, 0, 1)) {
+       chanservstdmessage(sender, QM_NOTREMOVEDPERMBAN, banstr, cip->name->content);
+       rbh=&(rbp->next);
+      } else {
+       chanservstdmessage(sender, QM_REMOVEDPERMBAN, banstr, cip->name->content);
+       if (cip->channel)
+         localdosetmode_ban(&changes, banstr, MCB_DEL);
+       /* Remove from database */
+       csdb_deleteban(rbp);
+       /* Remove from list */
+       (*rbh)=rbp->next;
+       /* Free ban/string and update setby refcount, and free actual regban */
+       freesstring(rbp->reason);
+       freechanban(rbp->cbp);
+       freeregban(rbp);
+      }
+    } else {
+      rbh=&(rbp->next);
+    }
+  }
+
+  if (cip->channel) {
+    for (cbh=&(cip->channel->bans); *cbh; ) {
+      cbp=*cbh;
+      if (banoverlap(theban, cbp)) {
+       /* Remove */
+       banstr=bantostring(cbp);
+       chanservstdmessage(sender, QM_REMOVEDCHANBAN, banstr, cip->name->content);
+       localdosetmode_ban(&changes, banstr, MCB_DEL);
+      } else {
+       cbh=&(cbp->next);
+      }
+    }
+    localsetmodeflush(&changes,1);
+  }
+  
+  
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/unbanme.c b/chanserv/chancmds/unbanme.c
new file mode 100644 (file)
index 0000000..8123c08
--- /dev/null
@@ -0,0 +1,56 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: unbanme
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Removes any bans affecting you from a channel.
+ * CMDFUNC: csc_dounbanme
+ * CMDPROTO: int csc_dounbanme(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dounbanme(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  regchan *rcp;
+  chanindex *cip;
+  modechanges changes;
+  chanban **cbh;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unbanme");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "unbanme", 0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cip->channel) {
+    localsetmodeinit(&changes, cip->channel, chanservnick);
+
+    for (cbh=&(cip->channel->bans);*cbh;) {
+      if (nickmatchban(sender, *cbh))
+       localdosetmode_ban(&changes, bantostring(*cbh), MCB_DEL);
+      else
+       cbh=&((*cbh)->next);
+    }
+
+    localsetmodeflush(&changes, 1);
+  }
+
+  cs_log(sender,"UNBANME %s",cip->name->content);
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}     
diff --git a/chanserv/chancmds/unsuspendchan.c b/chanserv/chancmds/unsuspendchan.c
new file mode 100644 (file)
index 0000000..ab25d94
--- /dev/null
@@ -0,0 +1,60 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: unsuspendchan
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 1
+ * CMDDESC: Unsuspends a channel from the bot.
+ * CMDFUNC: csc_dounsuspendchan
+ * CMDPROTO: int csc_dounsuspendchan(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dounsuspendchan(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  chanindex *cip;
+  regchan *rcp;
+
+  if (!rup)
+    return CMD_ERROR;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unsuspendchan");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext])) {
+    chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
+    return CMD_ERROR;
+  }
+
+  if(!CIsSuspended(rcp)) {
+    chanservstdmessage(sender, QM_CHANNELNOTSUSPENDED, cip->name->content);
+    cs_log(sender,"UNSUSPENDCHAN %s is not suspended",cip->name->content);
+    return CMD_ERROR;
+  }
+
+  CClearSuspended(rcp);
+  cs_log(sender,"UNSUSPENDCHAN %s (%s)",cip->name->content,rcp->suspendreason->content);
+  freesstring(rcp->suspendreason);
+  rcp->suspendreason = NULL;
+  rcp->suspendby = 0;
+
+  chanservjoinchan(cip->channel);
+
+  csdb_updatechannel(rcp);
+  chanservstdmessage(sender, QM_DONE);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/voice.c b/chanserv/chancmds/voice.c
new file mode 100644 (file)
index 0000000..7601732
--- /dev/null
@@ -0,0 +1,119 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: voice
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 20
+ * CMDDESC: Voices you or other users on channel(s).
+ * CMDFUNC: csc_dovoice
+ * CMDPROTO: int csc_dovoice(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dovoice(void *source, int cargc, char **cargv) {
+  nick *sender=source, *np;
+  reguser *rup=getreguserfromnick(sender);
+  chanindex *cip;
+  regchan *rcp=NULL;
+  regchanuser *rcup;
+  channel **ca;
+  unsigned long *lp;
+  int i;
+  modechanges changes;
+
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc==0) {
+    /* No args: "voice me on every channel you can */
+    ca=sender->channels->content;
+    for (i=0;i<sender->channels->cursi;i++) {
+      if ((rcp=ca[i]->index->exts[chanservext]) && !CIsSuspended(rcp)) {
+       /* It's a Q channel */
+       if (!(*(getnumerichandlefromchanhash(ca[i]->users, sender->numeric)) & 
+             (CUMODE_OP|CUMODE_VOICE))) {
+         /* They're not opped or voiced */
+         rcup=findreguseronchannel(rcp, rup);
+         if ((!rcup || !CUIsQuiet(rcup)) && 
+             ((rcup && CUHasVoicePriv(rcup)) ||
+             (CIsVoiceAll(rcp)))) {
+           /* And they have voice priv on the chan (or it's autovoice): 
+            * voice them */
+           localsetmodeinit(&changes, ca[i], chanservnick);
+           localdosetmode_nick(&changes, sender, MC_VOICE);
+           localsetmodeflush(&changes,1);
+         }
+       }
+      }
+    }
+    
+    chanservstdmessage(sender, QM_DONE);
+    return CMD_OK;
+  }
+
+  /* If there is at least one arg, the first is a channel */
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_VOICEPRIV, NULL, "voice", 0, 0)))
+    return CMD_ERROR;
+
+  if (cargc==1) {
+    /* Only one arg: "voice me" */
+    if (!cs_checkaccess(sender, NULL, CA_VOICEPRIV | CA_DEVOICED, cip,
+                       "voice", 0, 0))
+      return CMD_ERROR;
+
+    localsetmodeinit(&changes, cip->channel, chanservnick);
+    localdosetmode_nick(&changes, sender, MC_VOICE);
+    localsetmodeflush(&changes,1);
+
+    chanservstdmessage(sender, QM_DONE);
+    return CMD_OK;
+  }
+
+  if (!(cip=cs_checkaccess(sender, NULL, CA_OPPRIV, cip, "voice", 0, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  /* Set up the modes */
+  localsetmodeinit(&changes, cip->channel, chanservnick);
+
+  for(i=1;i<cargc;i++) {
+    if (!(np=getnickbynick(cargv[i]))) {
+      chanservstdmessage(sender, QM_UNKNOWNUSER, cargv[i]);
+      continue;
+    }
+
+    if (!(lp=getnumerichandlefromchanhash(cip->channel->users, np->numeric))) {
+      chanservstdmessage(sender, QM_USERNOTONCHAN, np->nick, cip->name->content);
+      continue;
+    }
+
+    if (*lp & CUMODE_VOICE) {
+      chanservstdmessage(sender, QM_USERVOICEDONCHAN, np->nick, cip->name->content);
+      continue;
+    }
+   
+    if ((rup=getreguserfromnick(np)) && (rcup=findreguseronchannel(rcp, rup)) && CUIsQuiet(rcup)) {
+      chanservstdmessage(sender, QM_CANTVOICE, np->nick, cip->name->content);
+      continue;
+    }
+
+    localdosetmode_nick(&changes, np, MC_VOICE);
+  }
+
+  localsetmodeflush(&changes, 1);
+  chanservstdmessage(sender, QM_DONE);
+
+  return CMD_OK;
+}
diff --git a/chanserv/chancmds/welcome.c b/chanserv/chancmds/welcome.c
new file mode 100644 (file)
index 0000000..805877e
--- /dev/null
@@ -0,0 +1,59 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: welcome
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 2
+ * CMDDESC: Shows or changes the welcome message on a channel.
+ * CMDFUNC: csc_dowelcome
+ * CMDPROTO: int csc_dowelcome(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../nick/nick.h"
+#include "../../lib/flags.h"
+#include "../../lib/irc_string.h"
+#include "../../channel/channel.h"
+#include "../../parser/parser.h"
+#include "../../irc/irc.h"
+#include "../../localuser/localuserchannel.h"
+#include <string.h>
+#include <stdio.h>
+
+int csc_dowelcome(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  chanindex *cip;
+  regchan *rcp;
+  sstring *oldwelcome;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "welcome");
+    return CMD_ERROR;
+  }
+
+  if (!(cip=cs_checkaccess(sender, cargv[0], CA_OPPRIV, NULL, "welcome",
+                          QPRIV_VIEWWELCOME, 0)))
+    return CMD_ERROR;
+
+  rcp=cip->exts[chanservext];
+
+  if (cargc>1) {
+    if (!cs_checkaccess(sender, NULL, CA_MASTERPRIV, cip, "welcome",
+                       QPRIV_CHANGEWELCOME, 0))
+      return CMD_ERROR;
+
+    oldwelcome=rcp->welcome;
+    
+    rcp->welcome=getsstring(cargv[1], 500);
+    csdb_updatechannel(rcp);
+
+    cs_log(sender,"WELCOME %s %s (was %s)",cip->name->content,rcp->welcome->content,oldwelcome?oldwelcome->content:"unset");
+    freesstring(oldwelcome);
+    chanservstdmessage(sender, QM_DONE);
+  }
+
+  chanservstdmessage(sender, QM_WELCOMEMESSAGEIS, rcp->index->name->content, 
+                    rcp->welcome?rcp->welcome->content:"(none)");
+
+  return CMD_OK;
+}
index e0f6e09c6641923bf4cbafccefc2fb6a10086477..deaa77acd3e30f306e5663f999686dc4628ceaa5 100644 (file)
@@ -817,5 +817,6 @@ void chanservdgline(void *arg);
 /* authlib.c */
 int csa_checkeboy(nick *sender, char *eboy);
 void csa_createrandompw(char *pw, int n);
+int csa_checkthrottled(nick *sender, reguser *rup, char *s);
 
 #endif
diff --git a/chanserv/mkcommandlist.pl b/chanserv/mkcommandlist.pl
new file mode 100755 (executable)
index 0000000..180b4c0
--- /dev/null
@@ -0,0 +1,135 @@
+#!/usr/bin/perl -w
+
+use strict;
+
+my @cmdnames;
+my @cmdlevels;
+my @cmdargs;
+my @cmddesc;
+my @cmdfunc;
+my @protos;
+my @files;
+
+my @filelist = <*.c>;
+
+my $modname;
+
+unless (@ARGV) {
+  print "Usage: $0 <module name>\n";
+  exit(0);
+} else {
+  $modname=$ARGV[0];
+}
+
+for (@filelist) {
+  next if (/commandlist.c/);
+  
+  my $fname = $_;
+  my ($cn, $cl, $ca, $cd, $cf, $cp);
+
+  open INFILE,"<$fname";
+  
+  while(<INFILE>) {
+    chomp;
+    
+    if (/CMDNAME: (.*)/) {
+      $cn=$1;
+    }
+        
+    if (/CMDLEVEL: (.*)/) {
+      $cl=$1;
+    }
+    
+    if (/CMDARGS: (.*)/) {
+      $ca=$1;
+    }
+    
+    if (/CMDDESC: (.*)/) {
+      $cd=$1;
+    }
+    
+    if (/CMDFUNC: (.*)/) {
+      $cf=$1;
+    }
+    
+    if (/CMDPROTO: (.*)/) {
+      $cp=$1;
+    }
+  }
+  
+  if (defined $cn and defined $cl and defined $ca and defined $cd and defined $cf and defined $cp) {
+    # valid command found 
+    push @files, $fname;
+    push @cmdnames, $cn;
+    push @cmdlevels, $cl;
+    push @cmdargs, $ca;
+    push @cmddesc, $cd;
+    push @cmdfunc, $cf;
+    push @protos, $cp;
+  } else {
+    print "Warning: found source file $fname without complete tags, skipping...\n";
+  }
+}
+
+if (@files < 1) {
+  print "No commands found - are you in the right directory?\n";
+  print "Exiting before I destroy something important.\n";
+  exit(0);
+}
+
+
+open CL, ">commandlist.c";
+
+print CL "/* Automatically generated by mkcommandlist.pl, do not edit. */\n\n";
+print CL "#include \"../chanserv.h\"\n\n";
+
+# Print prototypes
+print CL "/* Prototypes */\n";
+foreach (@protos) {
+  print CL "$_\n";
+}
+
+my @names2 = @cmdnames;
+my @func2 = @cmdfunc;
+
+print CL "\nvoid _init() {\n";
+
+while (my $cn = shift @cmdnames) {
+  print CL "  chanservaddcommand(\"".$cn."\", ".(shift @cmdlevels).", ".(shift @cmdargs).", ";
+  print CL (shift @cmdfunc).", \"".(shift @cmddesc)."\");\n";
+}
+
+print CL "}\n\nvoid _fini() {\n";
+
+while (my $cn = shift @names2) {
+  print CL "  chanservremovecommand(\"".$cn."\", ".(shift @func2).");\n";
+}
+
+print CL "}\n";
+
+close CL;
+
+open MF,">Makefile";
+
+print MF "# Automatically generated Makefile, do not edit.\n\n";
+
+print MF ".PHONY: all Makefile\n";
+
+print MF "all: Makefile $modname\n\n";
+
+print MF "Makefile:\n";
+print MF "\t../mkcommandlist.pl $modname\n";
+
+print MF "\n$modname: ";
+
+push @files,"commandlist.c";
+
+foreach (@files) {
+  s/.c$/.o/;
+  print MF "$_ ";
+}
+
+print MF "\n";
+print MF "\t ld -shared -Bdynamic -o \$\@ \$\^ \n";
+
+close MF;
diff --git a/chanserv/refactor.pl b/chanserv/refactor.pl
new file mode 100755 (executable)
index 0000000..e59d3ab
--- /dev/null
@@ -0,0 +1,81 @@
+#!/usr/bin/perl -w
+
+my @includes;
+
+my %cmdnames;
+my %cmdlevels;
+my %cmdargs;
+my %cmddesc;
+my %protos;
+
+my $infunc = 0;
+
+while (<>) {
+  chomp;
+  
+  if (/^#include (.*)$/) {
+#    print "Adding include: $1\n";
+    push @includes, $1;
+    next;
+  }
+  
+  if (/chanservaddcommand\((.*)\)/) {
+#    print "Found \"addcommand\" stanza\n";
+    my $args=$1;
+
+    unless ($args =~ m!^\s*"([^"]+)"\s*,\s*([^,]+?)\s*,\s*(\d+)\s*,\s*([^, ]+)\s*,\s*"([^"]+)! ) {
+      print "Can't decode addcommand() args: $args\n";
+      next;
+    }
+#    print "Command function is: $4\n";
+    
+    $cmdnames{$4} = $1;
+    $cmdlevels{$4} = $2;
+    $cmdargs{$4} = $3;
+    $cmddesc{$4} = $5;
+  }
+
+  if (/^int (.*?)\(.*;/) {
+    print "Found prototype for function: $1\n";
+    $protos{$1}=$_;
+  }
+  
+  if (/^int (\S+)\s*\(.*{/) {
+    print "Found start of function declaration: $1\n";
+    unless (defined $cmdnames{$1}) {
+      print "Found function $1 without definition, skipping ...\n";
+      next;
+    }
+        
+    my $fname = $cmdnames{$1}.".c";
+    
+    open CMDF, ">".$fname;
+    
+    print CMDF "/* Automatically generated by refactor.pl.\n *\n *\n";
+    print CMDF " * CMDNAME: $cmdnames{$1}\n";
+    print CMDF " * CMDLEVEL: $cmdlevels{$1}\n";
+    print CMDF " * CMDARGS: $cmdargs{$1}\n";
+    print CMDF " * CMDDESC: $cmddesc{$1}\n";
+    print CMDF " * CMDFUNC: $1\n";
+    print CMDF " * CMDPROTO: $protos{$1}\n";
+    print CMDF " */\n\n";
+    
+    for (@includes) {
+      print CMDF "#include $_\n";
+    }
+     
+    print CMDF "\n";
+    print CMDF "$_\n"; 
+    
+    $infunc=1;
+    next;
+  }
+  
+  if ($infunc) {
+    print CMDF "$_\n";
+    if (/^}/) {
+      close CMDF;
+      $infunc=0;
+    }
+  }
+}
diff --git a/chanserv/usercmds.c b/chanserv/usercmds.c
deleted file mode 100644 (file)
index 8945878..0000000
+++ /dev/null
@@ -1,1004 +0,0 @@
-/* usercmds.c */
-
-#include "chanserv.h"
-#include "../lib/irc_string.h"
-
-#include <stdio.h>
-#include <string.h>
-
-int csu_douserflags(void *source, int cargc, char **cargv);
-int csu_doinfo(void *source, int cargc, char **cargv);
-int csu_dowhois(void *source, int cargc, char **cargv);
-int csu_dousercomment(void *source, int cargc, char **cargv);
-int csu_dodeluser(void *source, int cargc, char **cargv);
-int csu_dolanguage(void *source, int cargc, char **cargv);
-int csu_dosuspenduser(void *source, int cargc, char **cargv);
-int csu_dounsuspenduser(void *source, int cargc, char **cargv);
-int csu_dospewdb(void *source, int cargc, char **cargv);
-int csu_dospewpass(void *source, int cargc, char **cargv);
-int csu_dospewemail(void *source, int cargc, char **cargv);
-int csu_dolistflags(void *source, int cargc, char **cargv);
-int csu_dosuspenduserlist(void *source, int cargc, char **cargv);
-
-void _init() {
-  chanservaddcommand("userflags"      ,   QCMD_AUTHED, 2, csu_douserflags      ,"Shows or changes user flags.");
-  chanservaddcommand("info"           ,   QCMD_AUTHED, 2, csu_doinfo           ,"Shows or changes info line.");
-  chanservaddcommand("whois"          ,   QCMD_AUTHED, 1, csu_dowhois          ,"Displays information about a user.");
-  chanservaddcommand("usercomment"    ,   QCMD_OPER  , 2, csu_dousercomment    ,"Shows or changes staff comment for a user.");
-  chanservaddcommand("deluser"        ,   QCMD_OPER  , 2, csu_dodeluser        ,"Removes a user from the bot.");
-  chanservaddcommand("language"       ,   QCMD_AUTHED, 1, csu_dolanguage       ,"Shows or changes your current language.");
-  chanservaddcommand("suspenduser"    ,   QCMD_OPER  , 1, csu_dosuspenduser    ,"Suspend/Delay GLINE/Instantly GLINE a user.");
-  chanservaddcommand("unsuspenduser"  ,   QCMD_OPER  , 1, csu_dounsuspenduser  ,"Unsuspend a user.");
-  chanservaddcommand("spewdb"         ,   QCMD_OPER  , 1, csu_dospewdb         ,"Search for a user in the database.");
-  chanservaddcommand("spewpass"       ,   QCMD_OPER  , 1, csu_dospewpass       ,"Search for a password in the database.");
-  chanservaddcommand("spewemail"      ,   QCMD_OPER  , 1, csu_dospewemail      ,"Search for an e-mail in the database.");
-  chanservaddcommand("listflags"      ,   QCMD_OPER  , 1, csu_dolistflags      ,"List users with the specified user flags.");
-  chanservaddcommand("suspenduserlist",   QCMD_HELPER, 1, csu_dosuspenduserlist,"Lists suspended/locked users.");
-}
-
-void _fini() {
-  chanservremovecommand("userflags",       csu_douserflags);
-  chanservremovecommand("info",            csu_doinfo);
-  chanservremovecommand("whois",           csu_dowhois);
-  chanservremovecommand("usercomment",     csu_dousercomment);
-  chanservremovecommand("deluser",         csu_dodeluser);
-  chanservremovecommand("language",        csu_dolanguage);
-  chanservremovecommand("suspenduser",     csu_dosuspenduser);
-  chanservremovecommand("unsuspenduser",   csu_dounsuspenduser);
-  chanservremovecommand("spewdb",          csu_dospewdb);
-  chanservremovecommand("spewpass",        csu_dospewpass);
-  chanservremovecommand("spewemail",       csu_dospewemail);
-  chanservremovecommand("listflags",       csu_dolistflags);
-  chanservremovecommand("suspenduserlist", csu_dosuspenduserlist);
-}
-
-int csu_douserflags(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender), *target;
-  int arg=0;
-  flag_t flagmask, changemask;
-  char flagbuf[30];
-
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "userflags");
-    return CMD_ERROR;
-  }
-
-  if (*cargv[0]!='+' && *cargv[0]!='-') {
-    arg++;
-    /* If the first char isn't a "change" character, it must specify a target */
-
-    if (!(target=findreguser(sender,cargv[0])))
-      return CMD_ERROR;
-
-    if (target!=rup && !cs_privcheck(QPRIV_VIEWUSERFLAGS, sender)) {
-      chanservstdmessage(sender, QM_NOACCESS, "userflags");
-      return CMD_ERROR;
-    }
-  } else {
-    target=rup;
-  }
-    
-  if (cargc>arg) {
-    /* OK, now we have a changestring.. */
-    if (target!=rup && !cs_privcheck(QPRIV_CHANGEUSERFLAGS, sender)) {
-      chanservstdmessage(sender, QM_NOACCESS, "userflags");
-      return CMD_ERROR;
-    }
-
-    strcpy(flagbuf,printflags(target->flags, ruflags));
-
-    changemask=QUFLAG_NOTICE | QUFLAG_INFO;
-
-    if (target==rup) {
-      /* If you're changing yourself, you can give up the "status" flags and add/remove notice */
-      changemask|=(target->flags & (QUFLAG_OPER | QUFLAG_DEV | QUFLAG_PROTECT | QUFLAG_HELPER | QUFLAG_ADMIN));
-    }
-
-    /* Warning, policy ahead */
-
-    if (UHasOperPriv(rup))
-      changemask |= QUFLAG_GLINE | QUFLAG_DELAYEDGLINE | QUFLAG_RESTRICTED | QUFLAG_PROTECT;
-
-    if (UHasAdminPriv(rup))
-      changemask |= (QUFLAG_OPER | QUFLAG_HELPER);
-    
-    if (UIsDev(rup))
-      changemask=QUFLAG_ALL;
-    
-    setflags(&target->flags, changemask, cargv[arg], ruflags, REJECT_NONE);
-    
-    /* More policy */
-    if (!UHasHelperPriv(target)) {
-      target->flags &= ~QUFLAG_PROTECT;
-    }
-
-    cs_log(sender,"USERFLAGS #%s %s (%s -> %s)",target->username,cargv[arg],flagbuf,printflags(target->flags, ruflags));
-    csdb_updateuser(target);
-    chanservstdmessage(sender, QM_DONE);
-  }
-
-  if (cs_privcheck(QPRIV_VIEWUSERFLAGS, sender))
-    flagmask=QUFLAG_ALL;
-  else
-    flagmask=QUFLAG_INFO | QUFLAG_NOTICE | QUFLAG_OPER | QUFLAG_HELPER | QUFLAG_DEV | QUFLAG_ADMIN;
-  
-  chanservstdmessage(sender, QM_CURUSERFLAGS, target->username, printflags(target->flags & flagmask, ruflags));
-
-  return CMD_OK;
-}
-
-int csu_doinfo(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  chanindex *cip;
-  regchan *rcp;
-  regchanuser *rcup;
-  char linebuf[INFOLEN+10];
-  char *newline="";
-  int doupdate=0;
-
-  if (cargc==0 || *cargv[0]!='#') {
-    /* Global info line */
-    if (cargc==1) {
-      /* Setting to either one word or "none" */
-      if (!ircd_strcmp(cargv[0],"none")) {
-       newline="";
-       doupdate=1;
-      } else {
-       newline=cargv[0];
-       doupdate=1;
-      }
-    } else if (cargc>1) {
-      /* More than one word: we need to stick them back together */
-      snprintf(linebuf,INFOLEN,"%s %s",cargv[0],cargv[1]);
-      newline=linebuf;
-      doupdate=1;
-    }
-
-    if (doupdate) {
-      if (rup->info)
-       freesstring(rup->info);
-      
-      rup->info=getsstring(newline, INFOLEN);
-
-      chanservstdmessage(sender, QM_DONE);
-      csdb_updateuser(rup);
-    }
-    
-    chanservstdmessage(sender, QM_GLOBALINFO, rup->info?rup->info->content:"(none)");
-  } else {
-    /* Channel info line */
-
-    if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext]) || 
-       (CIsSuspended(rcp) && !cs_privcheck(QPRIV_SUSPENDBYPASS, sender))) {
-      chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
-      return CMD_ERROR;
-    }
-    
-    if ((!(rcup=findreguseronchannel(rcp, rup)) || !CUHasVoicePriv(rcup))) {
-      chanservstdmessage(sender, QM_NOACCESSONCHAN, cargv[0], "info");
-      return CMD_ERROR;
-    }
-
-    if (cargc>1) {
-      if (rcup->info) 
-       freesstring(rcup->info);
-
-      if (!ircd_strcmp(cargv[1],"none")) 
-       rcup->info=NULL;
-      else     
-       rcup->info=getsstring(cargv[1],INFOLEN);
-      
-      csdb_updatechanuser(rcup);
-      chanservstdmessage(sender, QM_DONE);
-    }
-
-    chanservstdmessage(sender, QM_CHANNELINFO, cip->name->content, 
-                      rcup->info?rcup->info->content:"(none)");
-  }
-
-  return CMD_OK;
-}
-
-int csu_dowhois(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender), *target;
-  char buf[200];
-  char nbpos=0;
-  nicklist *nlp;
-  struct tm *tmp;
-  regchanuser *rcup, *rcup2;
-  flag_t flagmask, flags;
-  int doneheader=0;
-
-  if (!(rup=getreguserfromnick(sender)))
-    return CMD_ERROR;
-  
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "whois");
-    return CMD_ERROR;
-  }
-  
-  if (!(target=findreguser(sender, cargv[0]))) {
-    nick* np;
-    
-    if ((np=getnickbynick(cargv[0]))) {
-      activeuser* aup=getactiveuserfromnick(np);
-      chanservsendmessage(sender, "%s has attempted to auth %d time%s.", np->nick, aup->authattempts, 
-        aup->authattempts==1?"":"s");
-    }
-    return CMD_ERROR;
-  }
-
-  if (cargv[0][0]=='#') {
-    chanservstdmessage(sender, QM_WHOISHEADER_AUTH, target->username);
-  } else {
-    chanservstdmessage(sender, QM_WHOISHEADER_NICK, cargv[0], target->username);
-  }
-
-  if (rup==target || cs_privcheck(QPRIV_VIEWFULLWHOIS, sender)) {
-    chanservstdmessage(sender, QM_WHOIS_USERID, target->ID);
-  }
-
-  if (cs_privcheck(QPRIV_VIEWUSERFLAGS, sender)) {
-    flagmask=QUFLAG_ALL;
-  } else {  
-    if (UIsAdmin(target))
-      chanservstdmessage(sender, QM_USERISADMIN, target->username);
-    else if (UIsOper(target))
-      chanservstdmessage(sender, QM_USERISOPER, target->username);
-    else if (UIsHelper(target))
-      chanservstdmessage(sender, QM_USERISHELPER, target->username);
-    
-    if (UIsDev(target))
-      chanservstdmessage(sender, QM_USERISDEV, target->username);
-
-    flagmask=0;
-  }
-
-  if (rup==target)
-    flagmask|=(QUFLAG_OPER | QUFLAG_DEV | QUFLAG_HELPER | 
-              QUFLAG_ADMIN | QUFLAG_INFO | QUFLAG_NOTICE);
-
-  if (flagmask & target->flags)
-    chanservstdmessage(sender, QM_WHOIS_FLAGS, printflags(flagmask & target->flags, ruflags));
-
-  if (!target->nicks) {
-    chanservstdmessage(sender, QM_WHOIS_USERS, "(none)");
-  } else {
-    for (nlp=target->nicks; ;nlp=nlp->next) {
-      if (nbpos>0 && (!nlp || nbpos+strlen(nlp->np->nick) > 60)) {
-       chanservstdmessage(sender, QM_WHOIS_USERS, buf);
-       nbpos=0;
-      }
-
-      if (!nlp)
-       break;
-
-      nbpos+=sprintf(buf+nbpos,"%s ",nlp->np->nick);
-    }
-  }
-
-  if (target->created) {
-    tmp=gmtime(&(target->created));
-    strftime(buf,15,"%d/%m/%y %H:%M",tmp);
-    
-    chanservstdmessage(sender, QM_WHOIS_CREATED, buf);
-  }
-
-  tmp=gmtime(&(target->lastauth));
-  strftime(buf,15,"%d/%m/%y %H:%M",tmp);
-
-  chanservstdmessage(sender, QM_WHOIS_LASTAUTH, buf);
-  
-  if (target->lastuserhost && (rup==target || cs_privcheck(QPRIV_VIEWFULLWHOIS, sender))) {
-    chanservstdmessage(sender, QM_WHOIS_USERLANG, cslanguages[target->languageid] ?
-                      cslanguages[target->languageid]->name->content : "(unknown)");
-    chanservstdmessage(sender, QM_WHOIS_LASTUSERHOST, target->lastuserhost->content);
-  }
-
-  if (target->email && (rup==target || cs_privcheck(QPRIV_VIEWEMAIL, sender))) {
-    chanservstdmessage(sender, QM_WHOIS_EMAIL, target->email->content);
-
-    tmp=gmtime(&(target->lastemailchange));
-    strftime(buf,15,"%d/%m/%y %H:%M",tmp);
-    
-    chanservstdmessage(sender, QM_WHOIS_EMAILSET, buf);    
-  }
-
-  if (target->info) {
-    chanservstdmessage(sender, QM_WHOIS_INFO, target->info->content);
-  }
-
-  if (target->comment && (cs_privcheck(QPRIV_VIEWCOMMENTS, sender))) {
-    chanservstdmessage(sender, QM_WHOIS_COMMENT, target->comment->content);
-  }
-  
-  for (rcup=target->knownon;rcup;rcup=rcup->nextbyuser) {
-    if (!UHasHelperPriv(rup)) {
-      if (!(rcup2=findreguseronchannel(rcup->chan,rup)))
-       continue;
-      
-      if (!CUHasVoicePriv(rcup2))
-       continue;
-      
-      flagmask = (QCUFLAG_OWNER | QCUFLAG_MASTER | QCUFLAG_OP | QCUFLAG_VOICE | QCUFLAG_AUTOVOICE | 
-                 QCUFLAG_AUTOOP | QCUFLAG_TOPIC | QCUFLAG_SPAMCON);
-      
-      if (CUHasMasterPriv(rcup2))
-       flagmask |= (QCUFLAG_DENY | QCUFLAG_QUIET | QCUFLAG_BANNED);
-    } else {
-      flagmask=QCUFLAG_ALL;
-    }
-
-    if (!(flags=rcup->flags & flagmask)) 
-      continue;
-
-    if (!doneheader) {
-      doneheader=1;
-      chanservstdmessage(sender, QM_WHOIS_CHANHEADER, target->username);
-    }
-
-    chanservsendmessage(sender, " %-30s %s",rcup->chan->index->name->content,printflags(flags, rcuflags));
-  }
-
-  chanservstdmessage(sender, QM_ENDOFLIST);
-
-  return CMD_OK;
-}
-
-int csu_dodeluser(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender), *target;
-
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "deluser");
-    return CMD_ERROR;
-  }
-
-  if (!(target=findreguser(sender, cargv[0])))
-    return CMD_ERROR;
-  
-  cs_log(sender,"DELUSER %s (%s)",target->username,cargc>1?cargv[1]:"");
-  cs_removeuser(target);
-
-  chanservstdmessage(sender, QM_DONE);
-
-  return CMD_OK;
-}
-
-int csu_dousercomment(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender), *target;
-  char buf[300];
-  int bufpos;
-
-  if (!rup)
-    return CMD_ERROR;
-
-  if (cargc<1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "usercomment");
-    return CMD_ERROR;
-  }
-
-  if (!(target=findreguser(sender, cargv[0])))
-    return CMD_ERROR;
-
-  if (cargc>1) {
-    if (!ircd_strcmp(cargv[1],"none")) {
-      freesstring(target->comment);
-      target->comment=NULL;
-    } else {
-      if (*cargv[1]=='+') {
-       if (target->comment) {
-         strcpy(buf,target->comment->content);
-         bufpos=target->comment->length;
-         buf[bufpos++]=' ';
-       } else {
-         bufpos=0;
-       }
-       strncpy(buf+bufpos, cargv[1]+1, 250-bufpos);
-      } else {
-       strncpy(buf, cargv[1], 250);
-      }
-    
-      freesstring(target->comment);
-      target->comment=getsstring(buf,250);
-    }
-    csdb_updateuser(target);
-  }
-  
-  if (target->comment) 
-    chanservstdmessage(sender, QM_COMMENT, target->username, target->comment->content);
-  else
-    chanservstdmessage(sender, QM_NOCOMMENT, target->username);
-
-  return CMD_OK;
-}
-
-int csu_dolanguage(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  char buf[300];
-  int bufpos=0;
-  int i;
-  int len;
-
-  if (!rup)
-    return CMD_ERROR;
-
-  if (cargc==0) {
-    /* Display language */
-    i=rup->languageid;
-    chanservstdmessage(sender, QM_YOURLANGUAGE, cslanguages[i] ? cslanguages[i]->name->content : "Unknown");
-    
-    /* Display available lanaguages */
-    chanservstdmessage(sender, QM_LANGUAGELIST);
-    
-    for (i=0;i<MAXLANG;i++) {
-      if (cslanguages[i]) {
-       if (bufpos > 70) {
-         chanservsendmessage(sender, "%s", buf);
-         bufpos=0;
-       }
-       len=sprintf(buf+bufpos, "%.14s (%.2s)",cslanguages[i]->name->content,cslanguages[i]->code);
-       memset(buf+bufpos+len,' ',20-len);
-       bufpos+=20;
-       buf[bufpos]='\0';
-      }
-    }
-
-    if (bufpos) 
-      chanservsendmessage(sender, "%s", buf);
-
-    chanservstdmessage(sender, QM_ENDOFLIST);
-  } else {
-    /* Set language */
-    for (i=0;i<MAXLANG;i++) {
-      if (cslanguages[i] && !ircd_strcmp(cargv[0],cslanguages[i]->code)) {
-       /* Match. */
-       rup->languageid=i;
-       csdb_updateuser(rup);
-       
-       chanservstdmessage(sender, QM_DONE);
-       chanservstdmessage(sender, QM_YOURLANGUAGE, cslanguages[i]->name->content);
-       break;
-      }
-    }
-
-    if (i==MAXLANG)
-      chanservstdmessage(sender, QM_UNKNOWNLANGUAGE, cargv[0]);
-  }
-  
-  return CMD_OK;
-}
-
-int csu_dosuspenduser(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  reguser *vrup;
-  char* flag;
-  char* victim;
-  char* dur_p;
-  char* reason;
-  int kill=1, gline=0, email=0, password=0, hitcount=0;
-  time_t expires=0;
-  int duration=0;
-  struct tm* tmp;
-  char buf[200]="";
-  int dgwait;
-  
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc < 1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspenduser");
-    return CMD_ERROR;
-  }
-  
-  if (cargv[0][0] == '-') {
-    flag=cargv[0];
-    if (!(victim=strchr(flag, ' '))) {
-      chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspenduser");
-      return CMD_ERROR;
-    }
-    *(victim++)='\0';
-    if (!(dur_p=strchr(victim, ' '))) {
-      chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspenduser");
-      return CMD_ERROR;
-    }
-    *(dur_p++)='\0';
-    if ((reason=strchr(dur_p, ' '))) {
-      *(reason++)='\0';
-      if ((duration=durationtolong(dur_p))) {
-        if ((duration < 86400) || (duration > 2592000)) {
-          chanservstdmessage(sender, QM_INVALIDDURATION);
-          return CMD_ERROR;
-        }
-        expires=time(0)+duration;
-      }
-      else {
-        *(reason-1)=' ';
-        reason=dur_p;
-        expires=0;
-      }
-    }
-    else {
-      reason=dur_p;
-      expires=0;
-    }
-    
-    if (!ircd_strcmp(flag, "-nokill")) {
-      kill=0;
-    }
-    else if (!ircd_strcmp(flag, "-gline")) {
-      gline=1;
-    }
-    else if (!ircd_strcmp(flag, "-instantgline")) {
-      gline=2;
-    }
-    else if (!ircd_strcmp(flag, "-email")) {
-      email=1;
-    }
-    else if (!ircd_strcmp(flag, "-password")) {
-      password=1;
-    }
-    else {
-      chanservstdmessage(sender, QM_INVALIDCHANLEVCHANGE);
-      return CMD_ERROR;
-    }
-  }
-  else {
-    victim=cargv[0];
-    if (!(dur_p=strchr(victim, ' '))) {
-      chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspenduser");
-      return CMD_ERROR;
-    }
-    *(dur_p++)='\0';
-    if ((reason=strchr(dur_p, ' '))) {
-      *(reason++)='\0';
-      if ((duration=durationtolong(dur_p))) {
-        if ((duration < 86400) || (duration > 2592000)) {
-          chanservstdmessage(sender, QM_INVALIDDURATION);
-          return CMD_ERROR;
-        }
-        expires=time(0)+duration;
-      }
-      else {
-        *(reason-1)=' ';
-        reason=dur_p;
-        expires=0;
-      }
-    }
-    else {
-      reason=dur_p;
-      expires=0;
-    }
-  }
-  
-  if (expires) {
-    tmp=gmtime(&expires);
-    strftime(buf,15,"%d/%m/%y %H:%M",tmp);
-  }
-  
-  if (email) {
-    int i;
-    
-    for (i=0;i<REGUSERHASHSIZE;i++) {
-      for (vrup=regusernicktable[i]; vrup; vrup=vrup->nextbyname) {
-        if (!ircd_strcmp(vrup->email->content, victim)) {
-          if (UHasSuspension(vrup))
-            continue;
-          
-          if (UHasOperPriv(vrup) && !UHasAdminPriv(rup))
-            continue;
-          
-          hitcount++;
-          vrup->flags|=QUFLAG_SUSPENDED;
-          vrup->suspendby=rup->ID;
-          vrup->suspendexp=expires;
-          vrup->suspendreason=getsstring(reason, strlen(reason)+1);
-          
-          while (vrup->nicks) {
-            if (!vrup->nicks->np)
-              continue;
-
-            chanservstdmessage(sender, QM_DISCONNECTINGUSER, vrup->nicks->np->nick, vrup->username);
-            chanservkillstdmessage(vrup->nicks->np, QM_SUSPENDKILL);
-          }
-          csdb_updateuser(vrup);
-        }
-      }
-    }
-    
-    chanservwallmessage("%s (%s) bulk suspended <%s>, hit %d account/s (expires: %s)", sender->nick, rup->username, victim, hitcount, expires?buf:"never");
-  }
-  else if (password) {
-    int i;
-    
-    for (i=0;i<REGUSERHASHSIZE;i++) {
-      for (vrup=regusernicktable[i]; vrup; vrup=vrup->nextbyname) {
-        if (!strcmp(vrup->password, victim)) {
-          if (UHasSuspension(vrup))
-            continue;
-          
-          if (UHasOperPriv(vrup) && !UHasAdminPriv(rup))
-            continue;
-          
-          hitcount++;
-          vrup->flags|=QUFLAG_SUSPENDED;
-          vrup->suspendby=rup->ID;
-          vrup->suspendexp=expires;
-          vrup->suspendreason=getsstring(reason, strlen(reason)+1);
-          
-          while (vrup->nicks) {
-            if (!vrup->nicks->np)
-              continue;
-
-            chanservstdmessage(sender, QM_DISCONNECTINGUSER, vrup->nicks->np->nick, vrup->username);
-            chanservkillstdmessage(vrup->nicks->np, QM_SUSPENDKILL);
-          }
-          csdb_updateuser(vrup);
-        }
-      }
-    }
-    
-    chanservwallmessage("%s (%s) bulk suspended password \"%s\", hit %d account/s (expires: %s)", sender->nick, rup->username, victim, hitcount, expires?buf:"never");
-  }
-  else {
-    if (!(vrup=findreguser(sender, victim)))
-      return CMD_ERROR;
-    
-    if (!ircd_strcmp(vrup->username, rup->username)) {
-      chanservsendmessage(sender, "You can't suspend yourself, silly.");
-      return CMD_ERROR;
-    }
-    
-    if (UHasSuspension(vrup)) {
-      chanservstdmessage(sender, QM_USERALREADYSUSPENDED);
-      return CMD_ERROR;
-    }
-    
-    if (UHasOperPriv(vrup) && !UHasAdminPriv(rup)) {
-      snprintf(buf, 199, "suspenduser on %s", vrup->username);
-      chanservstdmessage(sender, QM_NOACCESS, buf);
-      chanservwallmessage("%s (%s) FAILED to suspend %s", sender->nick, rup->username, vrup->username);
-      return CMD_ERROR;
-    }
-    
-    if (gline == 2)
-      vrup->flags|=QUFLAG_GLINE;
-    else if (gline == 1)
-      vrup->flags|=QUFLAG_DELAYEDGLINE;
-    else
-      vrup->flags|=QUFLAG_SUSPENDED;
-    vrup->suspendby=rup->ID;
-    vrup->suspendexp=expires;
-    vrup->suspendreason=getsstring(reason, strlen(reason)+1);
-    
-    chanservwallmessage("%s (%s) %s %s (expires: %s)", sender->nick, rup->username, (gline)?((gline == 2)?"instantly glined":"delayed glined"):"suspended", vrup->username, expires?buf:"never");
-    if (gline) {
-      dgwait=(gline==2)?0:rand()%900;
-      chanservsendmessage(sender, "Scheduling delayed GLINE for account %s in %d %s", 
-        vrup->username, (dgwait>60)?(dgwait/60):dgwait, (dgwait>60)?"minutes":"seconds");
-      deleteschedule(NULL, &chanservdgline, (void*)vrup);
-      scheduleoneshot(time(NULL)+dgwait, &chanservdgline, (void*)vrup);
-    }
-    else if (kill) {
-      while (vrup->nicks) {
-        if (!vrup->nicks->np)
-          continue;
-        
-        chanservstdmessage(sender, QM_DISCONNECTINGUSER, vrup->nicks->np->nick, vrup->username);
-        chanservkillstdmessage(vrup->nicks->np, QM_SUSPENDKILL);
-        hitcount++;
-      }
-    }
-
-    csdb_updateuser(vrup);
-  }
-  
-  return CMD_OK;
-}
-
-int csu_dounsuspenduser(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  reguser *vrup;
-  char action[100];
-  
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc < 1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unsuspenduser");
-    return CMD_ERROR;
-  }
-  
-  if (cargv[0][0] == '#') {
-    if (!(vrup=findreguserbynick(&cargv[0][1]))) {
-      chanservstdmessage(sender, QM_UNKNOWNUSER, &cargv[0][1]);
-      return CMD_ERROR;
-    }
-  }
-  else {
-    nick *np;
-    
-    if (!(np=getnickbynick(cargv[0]))) {
-      chanservstdmessage(sender, QM_UNKNOWNUSER, cargv[0]);
-      return CMD_ERROR;
-    }
-    
-    if (!(vrup=getreguserfromnick(np)) && sender) {
-      chanservstdmessage(sender, QM_USERNOTAUTHED, cargv[0]);
-      return CMD_ERROR;
-    }
-  }
-  
-  if (!UHasSuspension(vrup)) {
-    chanservstdmessage(sender, QM_USERNOTSUSPENDED, cargv[0]);
-    return CMD_ERROR;
-  }
-  
-  if (UHasOperPriv(vrup) && !UHasAdminPriv(rup)) {
-    snprintf(action, 99, "unsuspenduser on %s", vrup->username);
-    chanservstdmessage(sender, QM_NOACCESS, action);
-    chanservwallmessage("%s (%s) FAILED to unsuspend %s", sender->nick, rup->username, vrup->username);
-    return CMD_ERROR;
-  }
-  
-  if (UIsDelayedGline(vrup)) {
-    strcpy(action, "removed delayed gline on");
-  }
-  else if (UIsGline(vrup)) {
-    strcpy(action, "removed instant gline on");
-  }
-  else if (UIsSuspended(vrup)) {
-    strcpy(action, "unsuspended");
-  }
-  else if (UIsNeedAuth(vrup)) {
-    strcpy(action, "enabled");
-  }
-  else {
-    chanservsendmessage(sender, "Unknown suspend type encountered.");
-    return CMD_ERROR;
-  }
-  
-  vrup->flags&=(~(QUFLAG_GLINE|QUFLAG_DELAYEDGLINE|QUFLAG_SUSPENDED|QUFLAG_NEEDAUTH));
-  vrup->suspendby=0;
-  vrup->suspendexp=0;
-  freesstring(vrup->suspendreason);
-  vrup->suspendreason=0;
-  csdb_updateuser(vrup);
-  
-  chanservwallmessage("%s (%s) %s %s", sender->nick, rup->username, action, vrup->username);
-  chanservstdmessage(sender, QM_DONE);
-  return CMD_OK;
-}
-
-int csu_dospewdb(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  reguser *dbrup;
-  int i;
-  unsigned int count=0;
-  
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc < 1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "spewdb");
-    return CMD_ERROR;
-  }
-  
-  chanservstdmessage(sender, QM_SPEWHEADER);
-  for (i=0;i<REGUSERHASHSIZE;i++) {
-    for (dbrup=regusernicktable[i]; dbrup; dbrup=dbrup->nextbyname) {
-      if (!match(cargv[0], dbrup->username)) {
-        chanservsendmessage(sender, "%-15s %-10s %-30s %s", dbrup->username, UHasSuspension(dbrup)?"yes":"no", dbrup->email?dbrup->email->content:"none set", dbrup->lastuserhost?dbrup->lastuserhost->content:"none");
-        count++;
-        if (count >= 2000) {
-          chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "users");
-          return CMD_ERROR;
-        }
-      }
-    }
-  }
-  chanservstdmessage(sender, QM_RESULTCOUNT, count, "user", (count==1)?"":"s");
-  
-  return CMD_OK;
-}
-
-int csu_dospewpass(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  reguser *dbrup;
-  int i;
-  unsigned int count=0;
-  
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc < 1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "spewpass");
-    return CMD_ERROR;
-  }
-  
-  chanservstdmessage(sender, QM_SPEWHEADER);
-  for (i=0;i<REGUSERHASHSIZE;i++) {
-    for (dbrup=regusernicktable[i]; dbrup; dbrup=dbrup->nextbyname) {
-      if (!match(cargv[0], dbrup->password)) {
-        chanservsendmessage(sender, "%-15s %-10s %-30s %s", dbrup->username, UHasSuspension(dbrup)?"yes":"no", dbrup->email?dbrup->email->content:"none set", dbrup->lastuserhost?dbrup->lastuserhost->content:"none");
-        count++;
-        if (count >= 2000) {
-          chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "users");
-          return CMD_ERROR;
-        }
-      }
-    }
-  }
-  chanservstdmessage(sender, QM_RESULTCOUNT, count, "user", (count==1)?"":"s");
-  
-  return CMD_OK;
-}
-
-int csu_dospewemail(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  reguser *dbrup;
-  int i;
-  unsigned int count=0;
-  
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc < 1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "spewemail");
-    return CMD_ERROR;
-  }
-  
-  chanservstdmessage(sender, QM_SPEWHEADER);
-  for (i=0;i<REGUSERHASHSIZE;i++) {
-    for (dbrup=regusernicktable[i]; dbrup; dbrup=dbrup->nextbyname) {
-      if (!dbrup->email)
-        continue;
-      if (!match(cargv[0], dbrup->email->content)) {
-        chanservsendmessage(sender, "%-15s %-10s %-30s %s", dbrup->username, UHasSuspension(dbrup)?"yes":"no", dbrup->email?dbrup->email->content:"none set", dbrup->lastuserhost?dbrup->lastuserhost->content:"none");
-        count++;
-        if (count >= 2000) {
-          chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "users");
-          return CMD_ERROR;
-        }
-      }
-    }
-  }
-  chanservstdmessage(sender, QM_RESULTCOUNT, count, "user", (count==1)?"":"s");
-  
-  return CMD_OK;
-}
-
-int csu_dolistflags(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  reguser *dbrup;
-  flag_t matchflags = 0;
-  char *ch;
-  int i, j;
-  unsigned int count=0;
-  
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc < 1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "listflags");
-    return CMD_ERROR;
-  }
-  
-  ch=cargv[0][0]=='+'?cargv[0]+1:cargv[0];
-  
-  for (i=0; ch[i]; i++) {
-    for (j = 0; ruflags[j].flagchar; j++) {
-      if (ruflags[j].flagchar == ch[i]) {
-        matchflags|=ruflags[j].flagbit;
-        break;
-      }
-    }
-  }
-  
-  chanservstdmessage(sender, QM_LISTFLAGSHEADER);
-  for (i=0;i<REGUSERHASHSIZE;i++) {
-    for (dbrup=regusernicktable[i]; dbrup; dbrup=dbrup->nextbyname) {
-      if ((dbrup->flags & matchflags) == matchflags) {
-        chanservsendmessage(sender, "%-15s %-17s %-10s %-30s %s", dbrup->username, printflags(dbrup->flags, ruflags), 
-          UHasSuspension(dbrup)?"yes":"no", dbrup->email?dbrup->email->content:"none set", 
-          dbrup->lastuserhost?dbrup->lastuserhost->content:"none");
-        count++;
-        if (count >= 2000) {
-          chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "users");
-          return CMD_ERROR;
-        }
-      }
-    }
-  }
-  chanservstdmessage(sender, QM_RESULTCOUNT, count, "user", (count==1)?"":"s");
-  
-  return CMD_OK;
-}
-
-int csu_dosuspenduserlist(void *source, int cargc, char **cargv) {
-  nick *sender=source;
-  reguser *rup=getreguserfromnick(sender);
-  reguser *vrup;
-  reguser *dbrup;
-  int i;
-  unsigned int count=0;
-  struct tm *tmp;
-  char buf[200];
-  
-  if (!rup)
-    return CMD_ERROR;
-  
-  if (cargc < 1) {
-    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspenduserlist");
-    return CMD_ERROR;
-  }
-  
-  vrup=findreguserbynick(cargv[0]);
-
-  chanservstdmessage(sender, QM_SUSPENDUSERLISTHEADER);
-  for (i=0;i<REGUSERHASHSIZE;i++) {
-    for (dbrup=regusernicktable[i]; dbrup; dbrup=dbrup->nextbyname) {
-      if (!UHasSuspension(dbrup))
-        continue;
-      
-      /*if (!ircd_strcmp(dbrup->username, cargv[0]) || (dbrup->suspendby == vrup->ID)) {*/
-      if (!match(cargv[0], dbrup->username) || (vrup && (dbrup->suspendby == vrup->ID))) {
-        char suspendtype[100];
-        char *bywhom=0;
-        
-        if ((UIsGline(dbrup) || UIsDelayedGline(dbrup)) && !UHasOperPriv(rup))
-          continue;
-        
-        if (UIsDelayedGline(dbrup))
-          strcpy(suspendtype, "delayed gline");
-        else if (UIsGline(dbrup))
-          strcpy(suspendtype, "instant gline");
-        else if (UIsSuspended(dbrup))
-          strcpy(suspendtype, "suspended");
-        else
-          strcpy(suspendtype, "not used");
-        
-        if (vrup && (dbrup->suspendby == vrup->ID)) {
-          bywhom=vrup->username;
-        }
-        else {
-          reguser* trup=findreguserbyID(dbrup->suspendby);
-          if (trup)
-            bywhom=trup->username;
-        }
-        
-        if (dbrup->suspendexp) {
-          tmp=gmtime(&(dbrup->suspendexp));
-          strftime(buf,15,"%d/%m/%y %H:%M",tmp);
-        }
-        
-        count++;
-        chanservsendmessage(sender, "%-15s %-13s %-15s %-15s %s", dbrup->username, suspendtype, UHasOperPriv(rup)?(bywhom?bywhom:"unknown"):"not shown", (dbrup->suspendexp)?((time(0) >= dbrup->suspendexp)?"next auth":buf):"never", dbrup->suspendreason->content);
-        if (count >= 2000) {
-          chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "users");
-          return CMD_ERROR;
-        }
-      }
-    }
-  }
-  chanservstdmessage(sender, QM_RESULTCOUNT, count, "user", (count==1)?"":"s");
-  
-  return CMD_OK;
-}
diff --git a/chanserv/usercmds/Makefile b/chanserv/usercmds/Makefile
new file mode 100644 (file)
index 0000000..e36b241
--- /dev/null
@@ -0,0 +1,10 @@
+# Automatically generated Makefile, do not edit.
+
+.PHONY: all Makefile
+all: Makefile chanserv_usercmds.so
+
+Makefile:
+       ../mkcommandlist.pl chanserv_usercmds.so
+
+chanserv_usercmds.so: deluser.o info.o language.o listflags.o spewdb.o spewemail.o spewpass.o suspenduser.o suspenduserlist.o unsuspenduser.o usercomment.o userflags.o whois.o commandlist.o 
+        ld -shared -Bdynamic -o $@ $^ 
diff --git a/chanserv/usercmds/commandlist.c b/chanserv/usercmds/commandlist.c
new file mode 100644 (file)
index 0000000..8fb1edf
--- /dev/null
@@ -0,0 +1,50 @@
+/* Automatically generated by mkcommandlist.pl, do not edit. */
+
+#include "../chanserv.h"
+
+/* Prototypes */
+int csu_dodeluser(void *source, int cargc, char **cargv);
+int csu_doinfo(void *source, int cargc, char **cargv);
+int csu_dolanguage(void *source, int cargc, char **cargv);
+int csu_dolistflags(void *source, int cargc, char **cargv);
+int csu_dospewdb(void *source, int cargc, char **cargv);
+int csu_dospewemail(void *source, int cargc, char **cargv);
+int csu_dospewpass(void *source, int cargc, char **cargv);
+int csu_dosuspenduser(void *source, int cargc, char **cargv);
+int csu_dosuspenduserlist(void *source, int cargc, char **cargv);
+int csu_dounsuspenduser(void *source, int cargc, char **cargv);
+int csu_dousercomment(void *source, int cargc, char **cargv);
+int csu_douserflags(void *source, int cargc, char **cargv);
+int csu_dowhois(void *source, int cargc, char **cargv);
+
+void _init() {
+  chanservaddcommand("deluser", QCMD_OPER, 2, csu_dodeluser, "Removes a user from the bot.");
+  chanservaddcommand("info", QCMD_AUTHED, 2, csu_doinfo, "Shows or changes info line.");
+  chanservaddcommand("language", QCMD_AUTHED, 1, csu_dolanguage, "Shows or changes your current language.");
+  chanservaddcommand("listflags", QCMD_OPER, 1, csu_dolistflags, "List users with the specified user flags.");
+  chanservaddcommand("spewdb", QCMD_OPER, 1, csu_dospewdb, "Search for a user in the database.");
+  chanservaddcommand("spewemail", QCMD_OPER, 1, csu_dospewemail, "Search for an e-mail in the database.");
+  chanservaddcommand("spewpass", QCMD_OPER, 1, csu_dospewpass, "Search for a password in the database.");
+  chanservaddcommand("suspenduser", QCMD_OPER, 1, csu_dosuspenduser, "Suspend/Delay GLINE/Instantly GLINE a user.");
+  chanservaddcommand("suspenduserlist", QCMD_HELPER, 1, csu_dosuspenduserlist, "Lists suspended/locked users.");
+  chanservaddcommand("unsuspenduser", QCMD_OPER, 1, csu_dounsuspenduser, "Unsuspend a user.");
+  chanservaddcommand("usercomment", QCMD_OPER, 2, csu_dousercomment, "Shows or changes staff comment for a user.");
+  chanservaddcommand("userflags", QCMD_AUTHED, 2, csu_douserflags, "Shows or changes user flags.");
+  chanservaddcommand("whois", QCMD_AUTHED, 1, csu_dowhois, "Displays information about a user.");
+}
+
+void _fini() {
+  chanservremovecommand("deluser", csu_dodeluser);
+  chanservremovecommand("info", csu_doinfo);
+  chanservremovecommand("language", csu_dolanguage);
+  chanservremovecommand("listflags", csu_dolistflags);
+  chanservremovecommand("spewdb", csu_dospewdb);
+  chanservremovecommand("spewemail", csu_dospewemail);
+  chanservremovecommand("spewpass", csu_dospewpass);
+  chanservremovecommand("suspenduser", csu_dosuspenduser);
+  chanservremovecommand("suspenduserlist", csu_dosuspenduserlist);
+  chanservremovecommand("unsuspenduser", csu_dounsuspenduser);
+  chanservremovecommand("usercomment", csu_dousercomment);
+  chanservremovecommand("userflags", csu_douserflags);
+  chanservremovecommand("whois", csu_dowhois);
+}
diff --git a/chanserv/usercmds/deluser.c b/chanserv/usercmds/deluser.c
new file mode 100644 (file)
index 0000000..514dc5b
--- /dev/null
@@ -0,0 +1,38 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: deluser
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 2
+ * CMDDESC: Removes a user from the bot.
+ * CMDFUNC: csu_dodeluser
+ * CMDPROTO: int csu_dodeluser(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_dodeluser(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender), *target;
+
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "deluser");
+    return CMD_ERROR;
+  }
+
+  if (!(target=findreguser(sender, cargv[0])))
+    return CMD_ERROR;
+  
+  cs_log(sender,"DELUSER %s (%s)",target->username,cargc>1?cargv[1]:"");
+  cs_removeuser(target);
+
+  chanservstdmessage(sender, QM_DONE);
+
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/info.c b/chanserv/usercmds/info.c
new file mode 100644 (file)
index 0000000..ba48059
--- /dev/null
@@ -0,0 +1,88 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: info
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 2
+ * CMDDESC: Shows or changes info line.
+ * CMDFUNC: csu_doinfo
+ * CMDPROTO: int csu_doinfo(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_doinfo(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  chanindex *cip;
+  regchan *rcp;
+  regchanuser *rcup;
+  char linebuf[INFOLEN+10];
+  char *newline="";
+  int doupdate=0;
+
+  if (cargc==0 || *cargv[0]!='#') {
+    /* Global info line */
+    if (cargc==1) {
+      /* Setting to either one word or "none" */
+      if (!ircd_strcmp(cargv[0],"none")) {
+       newline="";
+       doupdate=1;
+      } else {
+       newline=cargv[0];
+       doupdate=1;
+      }
+    } else if (cargc>1) {
+      /* More than one word: we need to stick them back together */
+      snprintf(linebuf,INFOLEN,"%s %s",cargv[0],cargv[1]);
+      newline=linebuf;
+      doupdate=1;
+    }
+
+    if (doupdate) {
+      if (rup->info)
+       freesstring(rup->info);
+      
+      rup->info=getsstring(newline, INFOLEN);
+
+      chanservstdmessage(sender, QM_DONE);
+      csdb_updateuser(rup);
+    }
+    
+    chanservstdmessage(sender, QM_GLOBALINFO, rup->info?rup->info->content:"(none)");
+  } else {
+    /* Channel info line */
+
+    if (!(cip=findchanindex(cargv[0])) || !(rcp=cip->exts[chanservext]) || 
+       (CIsSuspended(rcp) && !cs_privcheck(QPRIV_SUSPENDBYPASS, sender))) {
+      chanservstdmessage(sender, QM_UNKNOWNCHAN, cargv[0]);
+      return CMD_ERROR;
+    }
+    
+    if ((!(rcup=findreguseronchannel(rcp, rup)) || !CUHasVoicePriv(rcup))) {
+      chanservstdmessage(sender, QM_NOACCESSONCHAN, cargv[0], "info");
+      return CMD_ERROR;
+    }
+
+    if (cargc>1) {
+      if (rcup->info) 
+       freesstring(rcup->info);
+
+      if (!ircd_strcmp(cargv[1],"none")) 
+       rcup->info=NULL;
+      else     
+       rcup->info=getsstring(cargv[1],INFOLEN);
+      
+      csdb_updatechanuser(rcup);
+      chanservstdmessage(sender, QM_DONE);
+    }
+
+    chanservstdmessage(sender, QM_CHANNELINFO, cip->name->content, 
+                      rcup->info?rcup->info->content:"(none)");
+  }
+
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/language.c b/chanserv/usercmds/language.c
new file mode 100644 (file)
index 0000000..dd2f0ee
--- /dev/null
@@ -0,0 +1,72 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: language
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Shows or changes your current language.
+ * CMDFUNC: csu_dolanguage
+ * CMDPROTO: int csu_dolanguage(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_dolanguage(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  char buf[300];
+  int bufpos=0;
+  int i;
+  int len;
+
+  if (!rup)
+    return CMD_ERROR;
+
+  if (cargc==0) {
+    /* Display language */
+    i=rup->languageid;
+    chanservstdmessage(sender, QM_YOURLANGUAGE, cslanguages[i] ? cslanguages[i]->name->content : "Unknown");
+    
+    /* Display available lanaguages */
+    chanservstdmessage(sender, QM_LANGUAGELIST);
+    
+    for (i=0;i<MAXLANG;i++) {
+      if (cslanguages[i]) {
+       if (bufpos > 70) {
+         chanservsendmessage(sender, "%s", buf);
+         bufpos=0;
+       }
+       len=sprintf(buf+bufpos, "%.14s (%.2s)",cslanguages[i]->name->content,cslanguages[i]->code);
+       memset(buf+bufpos+len,' ',20-len);
+       bufpos+=20;
+       buf[bufpos]='\0';
+      }
+    }
+
+    if (bufpos) 
+      chanservsendmessage(sender, "%s", buf);
+
+    chanservstdmessage(sender, QM_ENDOFLIST);
+  } else {
+    /* Set language */
+    for (i=0;i<MAXLANG;i++) {
+      if (cslanguages[i] && !ircd_strcmp(cargv[0],cslanguages[i]->code)) {
+       /* Match. */
+       rup->languageid=i;
+       csdb_updateuser(rup);
+       
+       chanservstdmessage(sender, QM_DONE);
+       chanservstdmessage(sender, QM_YOURLANGUAGE, cslanguages[i]->name->content);
+       break;
+      }
+    }
+
+    if (i==MAXLANG)
+      chanservstdmessage(sender, QM_UNKNOWNLANGUAGE, cargv[0]);
+  }
+  
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/listflags.c b/chanserv/usercmds/listflags.c
new file mode 100644 (file)
index 0000000..1d8d538
--- /dev/null
@@ -0,0 +1,63 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: listflags
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 1
+ * CMDDESC: List users with the specified user flags.
+ * CMDFUNC: csu_dolistflags
+ * CMDPROTO: int csu_dolistflags(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_dolistflags(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  reguser *dbrup;
+  flag_t matchflags = 0;
+  char *ch;
+  int i, j;
+  unsigned int count=0;
+  
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc < 1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "listflags");
+    return CMD_ERROR;
+  }
+  
+  ch=cargv[0][0]=='+'?cargv[0]+1:cargv[0];
+  
+  for (i=0; ch[i]; i++) {
+    for (j = 0; ruflags[j].flagchar; j++) {
+      if (ruflags[j].flagchar == ch[i]) {
+        matchflags|=ruflags[j].flagbit;
+        break;
+      }
+    }
+  }
+  
+  chanservstdmessage(sender, QM_LISTFLAGSHEADER);
+  for (i=0;i<REGUSERHASHSIZE;i++) {
+    for (dbrup=regusernicktable[i]; dbrup; dbrup=dbrup->nextbyname) {
+      if ((dbrup->flags & matchflags) == matchflags) {
+        chanservsendmessage(sender, "%-15s %-17s %-10s %-30s %s", dbrup->username, printflags(dbrup->flags, ruflags), 
+          UHasSuspension(dbrup)?"yes":"no", dbrup->email?dbrup->email->content:"none set", 
+          dbrup->lastuserhost?dbrup->lastuserhost->content:"none");
+        count++;
+        if (count >= 2000) {
+          chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "users");
+          return CMD_ERROR;
+        }
+      }
+    }
+  }
+  chanservstdmessage(sender, QM_RESULTCOUNT, count, "user", (count==1)?"":"s");
+  
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/spewdb.c b/chanserv/usercmds/spewdb.c
new file mode 100644 (file)
index 0000000..eb0e5a4
--- /dev/null
@@ -0,0 +1,48 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: spewdb
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 1
+ * CMDDESC: Search for a user in the database.
+ * CMDFUNC: csu_dospewdb
+ * CMDPROTO: int csu_dospewdb(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_dospewdb(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  reguser *dbrup;
+  int i;
+  unsigned int count=0;
+  
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc < 1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "spewdb");
+    return CMD_ERROR;
+  }
+  
+  chanservstdmessage(sender, QM_SPEWHEADER);
+  for (i=0;i<REGUSERHASHSIZE;i++) {
+    for (dbrup=regusernicktable[i]; dbrup; dbrup=dbrup->nextbyname) {
+      if (!match(cargv[0], dbrup->username)) {
+        chanservsendmessage(sender, "%-15s %-10s %-30s %s", dbrup->username, UHasSuspension(dbrup)?"yes":"no", dbrup->email?dbrup->email->content:"none set", dbrup->lastuserhost?dbrup->lastuserhost->content:"none");
+        count++;
+        if (count >= 2000) {
+          chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "users");
+          return CMD_ERROR;
+        }
+      }
+    }
+  }
+  chanservstdmessage(sender, QM_RESULTCOUNT, count, "user", (count==1)?"":"s");
+  
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/spewemail.c b/chanserv/usercmds/spewemail.c
new file mode 100644 (file)
index 0000000..3216cb5
--- /dev/null
@@ -0,0 +1,50 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: spewemail
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 1
+ * CMDDESC: Search for an e-mail in the database.
+ * CMDFUNC: csu_dospewemail
+ * CMDPROTO: int csu_dospewemail(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_dospewemail(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  reguser *dbrup;
+  int i;
+  unsigned int count=0;
+  
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc < 1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "spewemail");
+    return CMD_ERROR;
+  }
+  
+  chanservstdmessage(sender, QM_SPEWHEADER);
+  for (i=0;i<REGUSERHASHSIZE;i++) {
+    for (dbrup=regusernicktable[i]; dbrup; dbrup=dbrup->nextbyname) {
+      if (!dbrup->email)
+        continue;
+      if (!match(cargv[0], dbrup->email->content)) {
+        chanservsendmessage(sender, "%-15s %-10s %-30s %s", dbrup->username, UHasSuspension(dbrup)?"yes":"no", dbrup->email?dbrup->email->content:"none set", dbrup->lastuserhost?dbrup->lastuserhost->content:"none");
+        count++;
+        if (count >= 2000) {
+          chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "users");
+          return CMD_ERROR;
+        }
+      }
+    }
+  }
+  chanservstdmessage(sender, QM_RESULTCOUNT, count, "user", (count==1)?"":"s");
+  
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/spewpass.c b/chanserv/usercmds/spewpass.c
new file mode 100644 (file)
index 0000000..e9cff7a
--- /dev/null
@@ -0,0 +1,48 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: spewpass
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 1
+ * CMDDESC: Search for a password in the database.
+ * CMDFUNC: csu_dospewpass
+ * CMDPROTO: int csu_dospewpass(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_dospewpass(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  reguser *dbrup;
+  int i;
+  unsigned int count=0;
+  
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc < 1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "spewpass");
+    return CMD_ERROR;
+  }
+  
+  chanservstdmessage(sender, QM_SPEWHEADER);
+  for (i=0;i<REGUSERHASHSIZE;i++) {
+    for (dbrup=regusernicktable[i]; dbrup; dbrup=dbrup->nextbyname) {
+      if (!match(cargv[0], dbrup->password)) {
+        chanservsendmessage(sender, "%-15s %-10s %-30s %s", dbrup->username, UHasSuspension(dbrup)?"yes":"no", dbrup->email?dbrup->email->content:"none set", dbrup->lastuserhost?dbrup->lastuserhost->content:"none");
+        count++;
+        if (count >= 2000) {
+          chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "users");
+          return CMD_ERROR;
+        }
+      }
+    }
+  }
+  chanservstdmessage(sender, QM_RESULTCOUNT, count, "user", (count==1)?"":"s");
+  
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/suspenduser.c b/chanserv/usercmds/suspenduser.c
new file mode 100644 (file)
index 0000000..7305381
--- /dev/null
@@ -0,0 +1,243 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: suspenduser
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 1
+ * CMDDESC: Suspend/Delay GLINE/Instantly GLINE a user.
+ * CMDFUNC: csu_dosuspenduser
+ * CMDPROTO: int csu_dosuspenduser(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_dosuspenduser(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  reguser *vrup;
+  char* flag;
+  char* victim;
+  char* dur_p;
+  char* reason;
+  int kill=1, gline=0, email=0, password=0, hitcount=0;
+  time_t expires=0;
+  int duration=0;
+  struct tm* tmp;
+  char buf[200]="";
+  int dgwait;
+  
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc < 1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspenduser");
+    return CMD_ERROR;
+  }
+  
+  if (cargv[0][0] == '-') {
+    flag=cargv[0];
+    if (!(victim=strchr(flag, ' '))) {
+      chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspenduser");
+      return CMD_ERROR;
+    }
+    *(victim++)='\0';
+    if (!(dur_p=strchr(victim, ' '))) {
+      chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspenduser");
+      return CMD_ERROR;
+    }
+    *(dur_p++)='\0';
+    if ((reason=strchr(dur_p, ' '))) {
+      *(reason++)='\0';
+      if ((duration=durationtolong(dur_p))) {
+        if ((duration < 86400) || (duration > 2592000)) {
+          chanservstdmessage(sender, QM_INVALIDDURATION);
+          return CMD_ERROR;
+        }
+        expires=time(0)+duration;
+      }
+      else {
+        *(reason-1)=' ';
+        reason=dur_p;
+        expires=0;
+      }
+    }
+    else {
+      reason=dur_p;
+      expires=0;
+    }
+    
+    if (!ircd_strcmp(flag, "-nokill")) {
+      kill=0;
+    }
+    else if (!ircd_strcmp(flag, "-gline")) {
+      gline=1;
+    }
+    else if (!ircd_strcmp(flag, "-instantgline")) {
+      gline=2;
+    }
+    else if (!ircd_strcmp(flag, "-email")) {
+      email=1;
+    }
+    else if (!ircd_strcmp(flag, "-password")) {
+      password=1;
+    }
+    else {
+      chanservstdmessage(sender, QM_INVALIDCHANLEVCHANGE);
+      return CMD_ERROR;
+    }
+  }
+  else {
+    victim=cargv[0];
+    if (!(dur_p=strchr(victim, ' '))) {
+      chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspenduser");
+      return CMD_ERROR;
+    }
+    *(dur_p++)='\0';
+    if ((reason=strchr(dur_p, ' '))) {
+      *(reason++)='\0';
+      if ((duration=durationtolong(dur_p))) {
+        if ((duration < 86400) || (duration > 2592000)) {
+          chanservstdmessage(sender, QM_INVALIDDURATION);
+          return CMD_ERROR;
+        }
+        expires=time(0)+duration;
+      }
+      else {
+        *(reason-1)=' ';
+        reason=dur_p;
+        expires=0;
+      }
+    }
+    else {
+      reason=dur_p;
+      expires=0;
+    }
+  }
+  
+  if (expires) {
+    tmp=gmtime(&expires);
+    strftime(buf,15,"%d/%m/%y %H:%M",tmp);
+  }
+  
+  if (email) {
+    int i;
+    
+    for (i=0;i<REGUSERHASHSIZE;i++) {
+      for (vrup=regusernicktable[i]; vrup; vrup=vrup->nextbyname) {
+        if (!ircd_strcmp(vrup->email->content, victim)) {
+          if (UHasSuspension(vrup))
+            continue;
+          
+          if (UHasOperPriv(vrup) && !UHasAdminPriv(rup))
+            continue;
+          
+          hitcount++;
+          vrup->flags|=QUFLAG_SUSPENDED;
+          vrup->suspendby=rup->ID;
+          vrup->suspendexp=expires;
+          vrup->suspendreason=getsstring(reason, strlen(reason)+1);
+          
+          while (vrup->nicks) {
+            if (!vrup->nicks->np)
+              continue;
+
+            chanservstdmessage(sender, QM_DISCONNECTINGUSER, vrup->nicks->np->nick, vrup->username);
+            chanservkillstdmessage(vrup->nicks->np, QM_SUSPENDKILL);
+          }
+          csdb_updateuser(vrup);
+        }
+      }
+    }
+    
+    chanservwallmessage("%s (%s) bulk suspended <%s>, hit %d account/s (expires: %s)", sender->nick, rup->username, victim, hitcount, expires?buf:"never");
+  }
+  else if (password) {
+    int i;
+    
+    for (i=0;i<REGUSERHASHSIZE;i++) {
+      for (vrup=regusernicktable[i]; vrup; vrup=vrup->nextbyname) {
+        if (!strcmp(vrup->password, victim)) {
+          if (UHasSuspension(vrup))
+            continue;
+          
+          if (UHasOperPriv(vrup) && !UHasAdminPriv(rup))
+            continue;
+          
+          hitcount++;
+          vrup->flags|=QUFLAG_SUSPENDED;
+          vrup->suspendby=rup->ID;
+          vrup->suspendexp=expires;
+          vrup->suspendreason=getsstring(reason, strlen(reason)+1);
+          
+          while (vrup->nicks) {
+            if (!vrup->nicks->np)
+              continue;
+
+            chanservstdmessage(sender, QM_DISCONNECTINGUSER, vrup->nicks->np->nick, vrup->username);
+            chanservkillstdmessage(vrup->nicks->np, QM_SUSPENDKILL);
+          }
+          csdb_updateuser(vrup);
+        }
+      }
+    }
+    
+    chanservwallmessage("%s (%s) bulk suspended password \"%s\", hit %d account/s (expires: %s)", sender->nick, rup->username, victim, hitcount, expires?buf:"never");
+  }
+  else {
+    if (!(vrup=findreguser(sender, victim)))
+      return CMD_ERROR;
+    
+    if (!ircd_strcmp(vrup->username, rup->username)) {
+      chanservsendmessage(sender, "You can't suspend yourself, silly.");
+      return CMD_ERROR;
+    }
+    
+    if (UHasSuspension(vrup)) {
+      chanservstdmessage(sender, QM_USERALREADYSUSPENDED);
+      return CMD_ERROR;
+    }
+    
+    if (UHasOperPriv(vrup) && !UHasAdminPriv(rup)) {
+      snprintf(buf, 199, "suspenduser on %s", vrup->username);
+      chanservstdmessage(sender, QM_NOACCESS, buf);
+      chanservwallmessage("%s (%s) FAILED to suspend %s", sender->nick, rup->username, vrup->username);
+      return CMD_ERROR;
+    }
+    
+    if (gline == 2)
+      vrup->flags|=QUFLAG_GLINE;
+    else if (gline == 1)
+      vrup->flags|=QUFLAG_DELAYEDGLINE;
+    else
+      vrup->flags|=QUFLAG_SUSPENDED;
+    vrup->suspendby=rup->ID;
+    vrup->suspendexp=expires;
+    vrup->suspendreason=getsstring(reason, strlen(reason)+1);
+    
+    chanservwallmessage("%s (%s) %s %s (expires: %s)", sender->nick, rup->username, (gline)?((gline == 2)?"instantly glined":"delayed glined"):"suspended", vrup->username, expires?buf:"never");
+    if (gline) {
+      dgwait=(gline==2)?0:rand()%900;
+      chanservsendmessage(sender, "Scheduling delayed GLINE for account %s in %d %s", 
+        vrup->username, (dgwait>60)?(dgwait/60):dgwait, (dgwait>60)?"minutes":"seconds");
+      deleteschedule(NULL, &chanservdgline, (void*)vrup);
+      scheduleoneshot(time(NULL)+dgwait, &chanservdgline, (void*)vrup);
+    }
+    else if (kill) {
+      while (vrup->nicks) {
+        if (!vrup->nicks->np)
+          continue;
+        
+        chanservstdmessage(sender, QM_DISCONNECTINGUSER, vrup->nicks->np->nick, vrup->username);
+        chanservkillstdmessage(vrup->nicks->np, QM_SUSPENDKILL);
+        hitcount++;
+      }
+    }
+
+    csdb_updateuser(vrup);
+  }
+  
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/suspenduserlist.c b/chanserv/usercmds/suspenduserlist.c
new file mode 100644 (file)
index 0000000..afdd274
--- /dev/null
@@ -0,0 +1,86 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: suspenduserlist
+ * CMDLEVEL: QCMD_HELPER
+ * CMDARGS: 1
+ * CMDDESC: Lists suspended/locked users.
+ * CMDFUNC: csu_dosuspenduserlist
+ * CMDPROTO: int csu_dosuspenduserlist(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_dosuspenduserlist(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  reguser *vrup;
+  reguser *dbrup;
+  int i;
+  unsigned int count=0;
+  struct tm *tmp;
+  char buf[200];
+  
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc < 1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "suspenduserlist");
+    return CMD_ERROR;
+  }
+  
+  vrup=findreguserbynick(cargv[0]);
+
+  chanservstdmessage(sender, QM_SUSPENDUSERLISTHEADER);
+  for (i=0;i<REGUSERHASHSIZE;i++) {
+    for (dbrup=regusernicktable[i]; dbrup; dbrup=dbrup->nextbyname) {
+      if (!UHasSuspension(dbrup))
+        continue;
+      
+      /*if (!ircd_strcmp(dbrup->username, cargv[0]) || (dbrup->suspendby == vrup->ID)) {*/
+      if (!match(cargv[0], dbrup->username) || (vrup && (dbrup->suspendby == vrup->ID))) {
+        char suspendtype[100];
+        char *bywhom=0;
+        
+        if ((UIsGline(dbrup) || UIsDelayedGline(dbrup)) && !UHasOperPriv(rup))
+          continue;
+        
+        if (UIsDelayedGline(dbrup))
+          strcpy(suspendtype, "delayed gline");
+        else if (UIsGline(dbrup))
+          strcpy(suspendtype, "instant gline");
+        else if (UIsSuspended(dbrup))
+          strcpy(suspendtype, "suspended");
+        else
+          strcpy(suspendtype, "not used");
+        
+        if (vrup && (dbrup->suspendby == vrup->ID)) {
+          bywhom=vrup->username;
+        }
+        else {
+          reguser* trup=findreguserbyID(dbrup->suspendby);
+          if (trup)
+            bywhom=trup->username;
+        }
+        
+        if (dbrup->suspendexp) {
+          tmp=gmtime(&(dbrup->suspendexp));
+          strftime(buf,15,"%d/%m/%y %H:%M",tmp);
+        }
+        
+        count++;
+        chanservsendmessage(sender, "%-15s %-13s %-15s %-15s %s", dbrup->username, suspendtype, UHasOperPriv(rup)?(bywhom?bywhom:"unknown"):"not shown", (dbrup->suspendexp)?((time(0) >= dbrup->suspendexp)?"next auth":buf):"never", dbrup->suspendreason->content);
+        if (count >= 2000) {
+          chanservstdmessage(sender, QM_TOOMANYRESULTS, 2000, "users");
+          return CMD_ERROR;
+        }
+      }
+    }
+  }
+  chanservstdmessage(sender, QM_RESULTCOUNT, count, "user", (count==1)?"":"s");
+  
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/unsuspenduser.c b/chanserv/usercmds/unsuspenduser.c
new file mode 100644 (file)
index 0000000..cb6dacc
--- /dev/null
@@ -0,0 +1,90 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: unsuspenduser
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 1
+ * CMDDESC: Unsuspend a user.
+ * CMDFUNC: csu_dounsuspenduser
+ * CMDPROTO: int csu_dounsuspenduser(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_dounsuspenduser(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender);
+  reguser *vrup;
+  char action[100];
+  
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc < 1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "unsuspenduser");
+    return CMD_ERROR;
+  }
+  
+  if (cargv[0][0] == '#') {
+    if (!(vrup=findreguserbynick(&cargv[0][1]))) {
+      chanservstdmessage(sender, QM_UNKNOWNUSER, &cargv[0][1]);
+      return CMD_ERROR;
+    }
+  }
+  else {
+    nick *np;
+    
+    if (!(np=getnickbynick(cargv[0]))) {
+      chanservstdmessage(sender, QM_UNKNOWNUSER, cargv[0]);
+      return CMD_ERROR;
+    }
+    
+    if (!(vrup=getreguserfromnick(np)) && sender) {
+      chanservstdmessage(sender, QM_USERNOTAUTHED, cargv[0]);
+      return CMD_ERROR;
+    }
+  }
+  
+  if (!UHasSuspension(vrup)) {
+    chanservstdmessage(sender, QM_USERNOTSUSPENDED, cargv[0]);
+    return CMD_ERROR;
+  }
+  
+  if (UHasOperPriv(vrup) && !UHasAdminPriv(rup)) {
+    snprintf(action, 99, "unsuspenduser on %s", vrup->username);
+    chanservstdmessage(sender, QM_NOACCESS, action);
+    chanservwallmessage("%s (%s) FAILED to unsuspend %s", sender->nick, rup->username, vrup->username);
+    return CMD_ERROR;
+  }
+  
+  if (UIsDelayedGline(vrup)) {
+    strcpy(action, "removed delayed gline on");
+  }
+  else if (UIsGline(vrup)) {
+    strcpy(action, "removed instant gline on");
+  }
+  else if (UIsSuspended(vrup)) {
+    strcpy(action, "unsuspended");
+  }
+  else if (UIsNeedAuth(vrup)) {
+    strcpy(action, "enabled");
+  }
+  else {
+    chanservsendmessage(sender, "Unknown suspend type encountered.");
+    return CMD_ERROR;
+  }
+  
+  vrup->flags&=(~(QUFLAG_GLINE|QUFLAG_DELAYEDGLINE|QUFLAG_SUSPENDED|QUFLAG_NEEDAUTH));
+  vrup->suspendby=0;
+  vrup->suspendexp=0;
+  freesstring(vrup->suspendreason);
+  vrup->suspendreason=0;
+  csdb_updateuser(vrup);
+  
+  chanservwallmessage("%s (%s) %s %s", sender->nick, rup->username, action, vrup->username);
+  chanservstdmessage(sender, QM_DONE);
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/usercomment.c b/chanserv/usercmds/usercomment.c
new file mode 100644 (file)
index 0000000..48ee077
--- /dev/null
@@ -0,0 +1,64 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: usercomment
+ * CMDLEVEL: QCMD_OPER
+ * CMDARGS: 2
+ * CMDDESC: Shows or changes staff comment for a user.
+ * CMDFUNC: csu_dousercomment
+ * CMDPROTO: int csu_dousercomment(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_dousercomment(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender), *target;
+  char buf[300];
+  int bufpos;
+
+  if (!rup)
+    return CMD_ERROR;
+
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "usercomment");
+    return CMD_ERROR;
+  }
+
+  if (!(target=findreguser(sender, cargv[0])))
+    return CMD_ERROR;
+
+  if (cargc>1) {
+    if (!ircd_strcmp(cargv[1],"none")) {
+      freesstring(target->comment);
+      target->comment=NULL;
+    } else {
+      if (*cargv[1]=='+') {
+       if (target->comment) {
+         strcpy(buf,target->comment->content);
+         bufpos=target->comment->length;
+         buf[bufpos++]=' ';
+       } else {
+         bufpos=0;
+       }
+       strncpy(buf+bufpos, cargv[1]+1, 250-bufpos);
+      } else {
+       strncpy(buf, cargv[1], 250);
+      }
+    
+      freesstring(target->comment);
+      target->comment=getsstring(buf,250);
+    }
+    csdb_updateuser(target);
+  }
+  
+  if (target->comment) 
+    chanservstdmessage(sender, QM_COMMENT, target->username, target->comment->content);
+  else
+    chanservstdmessage(sender, QM_NOCOMMENT, target->username);
+
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/userflags.c b/chanserv/usercmds/userflags.c
new file mode 100644 (file)
index 0000000..fb5794b
--- /dev/null
@@ -0,0 +1,94 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: userflags
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 2
+ * CMDDESC: Shows or changes user flags.
+ * CMDFUNC: csu_douserflags
+ * CMDPROTO: int csu_douserflags(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_douserflags(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender), *target;
+  int arg=0;
+  flag_t flagmask, changemask;
+  char flagbuf[30];
+
+  if (!rup)
+    return CMD_ERROR;
+  
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "userflags");
+    return CMD_ERROR;
+  }
+
+  if (*cargv[0]!='+' && *cargv[0]!='-') {
+    arg++;
+    /* If the first char isn't a "change" character, it must specify a target */
+
+    if (!(target=findreguser(sender,cargv[0])))
+      return CMD_ERROR;
+
+    if (target!=rup && !cs_privcheck(QPRIV_VIEWUSERFLAGS, sender)) {
+      chanservstdmessage(sender, QM_NOACCESS, "userflags");
+      return CMD_ERROR;
+    }
+  } else {
+    target=rup;
+  }
+    
+  if (cargc>arg) {
+    /* OK, now we have a changestring.. */
+    if (target!=rup && !cs_privcheck(QPRIV_CHANGEUSERFLAGS, sender)) {
+      chanservstdmessage(sender, QM_NOACCESS, "userflags");
+      return CMD_ERROR;
+    }
+
+    strcpy(flagbuf,printflags(target->flags, ruflags));
+
+    changemask=QUFLAG_NOTICE | QUFLAG_INFO;
+
+    if (target==rup) {
+      /* If you're changing yourself, you can give up the "status" flags and add/remove notice */
+      changemask|=(target->flags & (QUFLAG_OPER | QUFLAG_DEV | QUFLAG_PROTECT | QUFLAG_HELPER | QUFLAG_ADMIN));
+    }
+
+    /* Warning, policy ahead */
+
+    if (UHasOperPriv(rup))
+      changemask |= QUFLAG_GLINE | QUFLAG_DELAYEDGLINE | QUFLAG_RESTRICTED | QUFLAG_PROTECT;
+
+    if (UHasAdminPriv(rup))
+      changemask |= (QUFLAG_OPER | QUFLAG_HELPER);
+    
+    if (UIsDev(rup))
+      changemask=QUFLAG_ALL;
+    
+    setflags(&target->flags, changemask, cargv[arg], ruflags, REJECT_NONE);
+    
+    /* More policy */
+    if (!UHasHelperPriv(target)) {
+      target->flags &= ~QUFLAG_PROTECT;
+    }
+
+    cs_log(sender,"USERFLAGS #%s %s (%s -> %s)",target->username,cargv[arg],flagbuf,printflags(target->flags, ruflags));
+    csdb_updateuser(target);
+    chanservstdmessage(sender, QM_DONE);
+  }
+
+  if (cs_privcheck(QPRIV_VIEWUSERFLAGS, sender))
+    flagmask=QUFLAG_ALL;
+  else
+    flagmask=QUFLAG_INFO | QUFLAG_NOTICE | QUFLAG_OPER | QUFLAG_HELPER | QUFLAG_DEV | QUFLAG_ADMIN;
+  
+  chanservstdmessage(sender, QM_CURUSERFLAGS, target->username, printflags(target->flags & flagmask, ruflags));
+
+  return CMD_OK;
+}
diff --git a/chanserv/usercmds/whois.c b/chanserv/usercmds/whois.c
new file mode 100644 (file)
index 0000000..4537852
--- /dev/null
@@ -0,0 +1,162 @@
+/* Automatically generated by refactor.pl.
+ *
+ *
+ * CMDNAME: whois
+ * CMDLEVEL: QCMD_AUTHED
+ * CMDARGS: 1
+ * CMDDESC: Displays information about a user.
+ * CMDFUNC: csu_dowhois
+ * CMDPROTO: int csu_dowhois(void *source, int cargc, char **cargv);
+ */
+
+#include "../chanserv.h"
+#include "../../lib/irc_string.h"
+#include <stdio.h>
+#include <string.h>
+
+int csu_dowhois(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  reguser *rup=getreguserfromnick(sender), *target;
+  char buf[200];
+  char nbpos=0;
+  nicklist *nlp;
+  struct tm *tmp;
+  regchanuser *rcup, *rcup2;
+  flag_t flagmask, flags;
+  int doneheader=0;
+
+  if (!(rup=getreguserfromnick(sender)))
+    return CMD_ERROR;
+  
+  if (cargc<1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "whois");
+    return CMD_ERROR;
+  }
+  
+  if (!(target=findreguser(sender, cargv[0]))) {
+    nick* np;
+    
+    if ((np=getnickbynick(cargv[0]))) {
+      activeuser* aup=getactiveuserfromnick(np);
+      chanservsendmessage(sender, "%s has attempted to auth %d time%s.", np->nick, aup->authattempts, 
+        aup->authattempts==1?"":"s");
+    }
+    return CMD_ERROR;
+  }
+
+  if (cargv[0][0]=='#') {
+    chanservstdmessage(sender, QM_WHOISHEADER_AUTH, target->username);
+  } else {
+    chanservstdmessage(sender, QM_WHOISHEADER_NICK, cargv[0], target->username);
+  }
+
+  if (rup==target || cs_privcheck(QPRIV_VIEWFULLWHOIS, sender)) {
+    chanservstdmessage(sender, QM_WHOIS_USERID, target->ID);
+  }
+
+  if (cs_privcheck(QPRIV_VIEWUSERFLAGS, sender)) {
+    flagmask=QUFLAG_ALL;
+  } else {  
+    if (UIsAdmin(target))
+      chanservstdmessage(sender, QM_USERISADMIN, target->username);
+    else if (UIsOper(target))
+      chanservstdmessage(sender, QM_USERISOPER, target->username);
+    else if (UIsHelper(target))
+      chanservstdmessage(sender, QM_USERISHELPER, target->username);
+    
+    if (UIsDev(target))
+      chanservstdmessage(sender, QM_USERISDEV, target->username);
+
+    flagmask=0;
+  }
+
+  if (rup==target)
+    flagmask|=(QUFLAG_OPER | QUFLAG_DEV | QUFLAG_HELPER | 
+              QUFLAG_ADMIN | QUFLAG_INFO | QUFLAG_NOTICE);
+
+  if (flagmask & target->flags)
+    chanservstdmessage(sender, QM_WHOIS_FLAGS, printflags(flagmask & target->flags, ruflags));
+
+  if (!target->nicks) {
+    chanservstdmessage(sender, QM_WHOIS_USERS, "(none)");
+  } else {
+    for (nlp=target->nicks; ;nlp=nlp->next) {
+      if (nbpos>0 && (!nlp || nbpos+strlen(nlp->np->nick) > 60)) {
+       chanservstdmessage(sender, QM_WHOIS_USERS, buf);
+       nbpos=0;
+      }
+
+      if (!nlp)
+       break;
+
+      nbpos+=sprintf(buf+nbpos,"%s ",nlp->np->nick);
+    }
+  }
+
+  if (target->created) {
+    tmp=gmtime(&(target->created));
+    strftime(buf,15,"%d/%m/%y %H:%M",tmp);
+    
+    chanservstdmessage(sender, QM_WHOIS_CREATED, buf);
+  }
+
+  tmp=gmtime(&(target->lastauth));
+  strftime(buf,15,"%d/%m/%y %H:%M",tmp);
+
+  chanservstdmessage(sender, QM_WHOIS_LASTAUTH, buf);
+  
+  if (target->lastuserhost && (rup==target || cs_privcheck(QPRIV_VIEWFULLWHOIS, sender))) {
+    chanservstdmessage(sender, QM_WHOIS_USERLANG, cslanguages[target->languageid] ?
+                      cslanguages[target->languageid]->name->content : "(unknown)");
+    chanservstdmessage(sender, QM_WHOIS_LASTUSERHOST, target->lastuserhost->content);
+  }
+
+  if (target->email && (rup==target || cs_privcheck(QPRIV_VIEWEMAIL, sender))) {
+    chanservstdmessage(sender, QM_WHOIS_EMAIL, target->email->content);
+
+    tmp=gmtime(&(target->lastemailchange));
+    strftime(buf,15,"%d/%m/%y %H:%M",tmp);
+    
+    chanservstdmessage(sender, QM_WHOIS_EMAILSET, buf);    
+  }
+
+  if (target->info) {
+    chanservstdmessage(sender, QM_WHOIS_INFO, target->info->content);
+  }
+
+  if (target->comment && (cs_privcheck(QPRIV_VIEWCOMMENTS, sender))) {
+    chanservstdmessage(sender, QM_WHOIS_COMMENT, target->comment->content);
+  }
+  
+  for (rcup=target->knownon;rcup;rcup=rcup->nextbyuser) {
+    if (!UHasHelperPriv(rup)) {
+      if (!(rcup2=findreguseronchannel(rcup->chan,rup)))
+       continue;
+      
+      if (!CUHasVoicePriv(rcup2))
+       continue;
+      
+      flagmask = (QCUFLAG_OWNER | QCUFLAG_MASTER | QCUFLAG_OP | QCUFLAG_VOICE | QCUFLAG_AUTOVOICE | 
+                 QCUFLAG_AUTOOP | QCUFLAG_TOPIC | QCUFLAG_SPAMCON);
+      
+      if (CUHasMasterPriv(rcup2))
+       flagmask |= (QCUFLAG_DENY | QCUFLAG_QUIET | QCUFLAG_BANNED);
+    } else {
+      flagmask=QCUFLAG_ALL;
+    }
+
+    if (!(flags=rcup->flags & flagmask)) 
+      continue;
+
+    if (!doneheader) {
+      doneheader=1;
+      chanservstdmessage(sender, QM_WHOIS_CHANHEADER, target->username);
+    }
+
+    chanservsendmessage(sender, " %-30s %s",rcup->chan->index->name->content,printflags(flags, rcuflags));
+  }
+
+  chanservstdmessage(sender, QM_ENDOFLIST);
+
+  return CMD_OK;
+}