/*
 * msghandlers.c
 * (C) Peter Salanki 2002
 * This program is copyright, and covered by the Gnu Public License.
 * The Natasha bot.
 * sorcer@linux.se
 */

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <time.h>
#include <dlfcn.h>
#include "../../settings.h"
#include "../../globals.h"
#include "../../bottypes.h"
#include "msgtab.h"

#define NAME "MSGHandlers"
#define VERSION 1.00

MODULE_INIT _module_init(MODULE m);
MODULE_DESTROY _module_destroy(MODULE m);

MODULE_INIT _module_init(MODULE m) {
  strncpy(m->name, NAME, 20);
  strncpy(m->compiledate, __DATE__ " " __TIME__, 30);
  m->version = VERSION;  
}

MODULE_DESTROY _module_destroy(MODULE m) {

}

void m_parse (char *command, char *a, struct arm *arm)
{
  int i = 0;
  int userlev = 0;
  char msg[256];

#ifdef DEBUG  
  printf ("%s:%s\n", command, a);
#endif

  userlev = userlevel(arm->parsevars->sender);

  while (msgtab[i].func != 0)
    {
      if (strcasecmp (msgtab[i].msg, command) == 0)
	{
 	  if (userlev >= msgtab[i].level)
	    {
	      msgtab[i].func (a, arm);
	    } else { 
#ifndef Q_AUTOAUTH
	      if(strcasecmp("NEWPASS", command) == 0) say(arm->parsevars->sender, "You need to AUTH with your old password before you can change.");
	      else {
#endif
		sprintf(msg, "You don't have access to this command. If you think you should have, check that you are AUTH'd and try /msg %s IDENT", arm->nick);
		say(arm->parsevars->sender, msg, arm);
#ifdef Q_AUTOAUTH
    if(userlev == 0) findauser(arm->parsevars->sender)->check = time(NULL);
#endif
#ifndef Q_AUTOAUTH
	      }
#endif
	    }
	  return;
	}
      i++;
    }
   sprintf(msg, "Unknown command. Try: /msg %s SHOWCOMMANDS.", arm->nick);
   say(arm->parsevars->sender, msg, arm); 
}

void m_gban (char *a, struct arm *arm) {

  struct channel *c;
  struct activeuser *u;
  char reason[512] = "";
  char msg[512+CHANNELLEN+NICKLEN+50] = "";
  char target[HOSTLEN+1] = "";
  char duration[100] = "";
  int expire;
  int i = 0;
  int j = 0;
  int hit = 0;
  int direct = 0;
  
  if(!checkargs(3, 1, a, arm)) return;

  j = 0;
  while (a[i] != ' ' && a[i] != '\0') {
    target[j] = a[i];
    ++i;
    ++j; 
  }

  ++i;
  j = 0;
  while (a[i] != ' ' && a[i] != '\0') {
    duration[j] = a[i];
    ++i;
    ++j; 
  }

  ++i;
  j = 0;
  while (a[i] != '\0') {
    reason[j] = a[i];
    ++i;
    ++j; 
  }
  
  
  i = findauser(arm->parsevars->sender)->userid;
  
  
  u = NULL;
  
  /* Check the target */
  if(strstr(target, "@") == NULL) {
    u = findauser(target);
    
    if (u == NULL) {
      say(arm->parsevars->sender, "That is not a hostmask and no user with that nick exists.", arm);
      return;
    } else sprintf(target, "%s@%s", u->username, u->hostname);
  }
  
  /* Check duration */
  if (strstr(duration, "h") != NULL) {
    STR_replace_c (duration, "h", "", msg);
    expire = time(NULL) + atoi(msg)*3600;
  }

  else if (strstr(duration, "m") != NULL) {
    STR_replace_c (duration, "m", "", msg);
    expire = time(NULL) + atoi(msg)*60;
  }

  else if (strstr(duration, "d") != NULL) {
    STR_replace_c (duration, "d", "", msg);
    expire = time(NULL) + atoi(msg)*86400;
  } 

  else {
    say(arm->parsevars->sender, "Wrong duration, duration can be day(d), hour(h), minute(m). I.e: 2h (two hours)", arm);
    return;
  }

  sprintf(msg, "Global ban. Head to %c%s%c for more information. Ban reason: %c%s%c", BOLD, PUBCHAN, BOLD, BOLD, reason, BOLD);
  /* Ban */  

  c = firstchan;
  
  while (c != NULL) {
    if(c->isop) {
      ++hit;
      addban(c->name, target, reason, i, expire);
      if(u != NULL && findachanuser(u->nick, c->name) != NULL) {
	kick(c->name, u->nick, msg);
	++direct;
      }
    }
    c = c->next;
  }
  
  sprintf(msg, "Added global ban for: %c%s%c by: %c%s%c Duration: %c%s%c Reason: %c%s%c", BOLD, target, BOLD, BOLD, arm->parsevars->sender, BOLD, BOLD, duration, BOLD, BOLD, reason, BOLD);
  privmsg(HOMECHAN, msg);

  snprintf(msg, 512, "Ban hit %c%i%c channels, %c%i%c were direct hits (nick on channel).", BOLD, hit, BOLD, BOLD, direct, BOLD);
  say(arm->parsevars->sender, msg, arm);

}

void m_ban (char *a, struct arm *arm)
{
  struct channel *c;
  struct activeuser *u;
  char reason[512] = "";
  char msg[512+CHANNELLEN+NICKLEN+50] = "";
  char channel[CHANNELLEN+1] = "";
  char target[HOSTLEN+1] = "";
  char duration[100] = "";
  int expire;
  int i = 0;
  int j = 0;
  
  if(!checkargs(2, 1, a, arm)) return;

  if(countargs(a) == 2) sscanf(a, "%" STRCHANNELLEN "s %" STRHOSTLEN "s", channel, target);
  else {

    while (a[i] != ' ' && a[i] != '\0') {
      channel[j] = a[i];
      ++i;
      ++j; 
    }

    ++i;
    j = 0;
    while (a[i] != ' ' && a[i] != '\0') {
      target[j] = a[i];
      ++i;
      ++j; 
    }

    ++i;
    j = 0;
    while (a[i] != ' ' && a[i] != '\0') {
      duration[j] = a[i];
      ++i;
      ++j; 
    }

    ++i;
    j = 0;
    while (a[i] != '\0') {
      reason[j] = a[i];
      ++i;
      ++j; 
    }
  }
  
  c = findchannel(channel);
  
  if (c == NULL) {
    say(arm->parsevars->sender, "Channel doesen't exist", arm);
    return;
  } else if (c->isop == 0) {
    say(arm->parsevars->sender, "I do not have Operator status there.", arm);
    return;
  }
  
  if((chanuserlevel(arm->parsevars->sender, channel) >= CHAN_OP || userlevel(arm->parsevars->sender) >= TECHNICIAN) && (strcasecmp(target, arm->nick) != 0)) {
    u = findauser(arm->parsevars->sender);
    
    i = u->userid;

    u = NULL;

    /* Check the target */
    if(strstr(target, "@") == NULL) {
      u = findauser(target);
      
      if (u == NULL) {
	say(arm->parsevars->sender, "That is not a hostmask and no user with that nick exists.", arm);
	return;
      } else sprintf(target, "%s@%s", u->username, u->hostname);
    }
    
    if(countargs(a) > 2) {

      /* Check duration */
      if (strstr(duration, "h") != NULL) {
        STR_replace_c (duration, "h", "", msg);
	expire = time(NULL) + atoi(msg)*3600;
      }

      else if (strstr(duration, "m") != NULL) {
        STR_replace_c (duration, "m", "", msg);
	expire = time(NULL) + atoi(msg)*60;
      }

      else if (strstr(duration, "d") != NULL) {
        STR_replace_c (duration, "d", "", msg);
	expire = time(NULL) + atoi(msg)*86400;
      } 

      else {
	say(arm->parsevars->sender, "Wrong duration, duration can be day(d), hour(h), minute(m). I.e: 2h (two hours)", arm);
	return;
      }
    } else {
      strcpy(duration, "One hour (Default)");
      expire = time(NULL) + 3600;
    }
    if(countargs(a) <= 3) strcpy(reason, "Requested");

    /* Ban */  
    addban (channel, target, reason, i, expire);
    
    if(u != NULL) { 
      sprintf(msg, "Banned by: %c%s%c Duration: %c%s%c Reason: %c%s%c", BOLD, arm->parsevars->sender, BOLD, BOLD, duration, BOLD, BOLD, reason, BOLD);
      kick(channel, u->nick, msg);
    } else {
      sprintf(msg, "Added ban for: %c%s%c by: %c%s%c Duration: %c%s%c Reason: %c%s%c", BOLD, target, BOLD, BOLD, arm->parsevars->sender, BOLD, BOLD, duration, BOLD, BOLD, reason, BOLD);
      privmsg(channel, msg);
    }
    say(arm->parsevars->sender, "Banned.", arm);
  } else say(arm->parsevars->sender, "Insufficient access", arm);
}

void m_unban (char *a, struct arm *arm)
{
  struct channel *c;
  struct activeuser *u = NULL;
  char msg[512+CHANNELLEN+NICKLEN+50] = "";
  char channel[CHANNELLEN+1] = "";
  char target[HOSTLEN+1] = "";
  
  if(!checkargs(2, 0, a, arm)) return;

  sscanf(a, "%" STRCHANNELLEN "s %s", channel, target);
  
  c = findchannel(channel);
  
  if(c == NULL) {
    say(arm->parsevars->sender, "Channel doesen't exist", arm);
    return;
  } else if (c->isop == 0) {
    say(arm->parsevars->sender, "I do not have Operator status there.", arm);
    return;
  }
  
  if(chanuserlevel(arm->parsevars->sender, channel) >= 3 || userlevel(arm->parsevars->sender) >= 10) {

    /* Check the target */
    if(strstr(target, "@") == NULL) {
      u = findauser(target);
      
      if (u == NULL) {
	say(arm->parsevars->sender, "That is not a hostmask and no user with that nick exists.", arm);
	return;
      } else sprintf(target, "%s@%s", u->username, u->hostname);
    }
    
    /* UnBan */  
    if(findban(target, channel) != NULL) {
      delban (target, channel);
    
      if(u != NULL) { 
	sprintf(msg, "%c%s%c has unbanned you from %c%s%c", BOLD, arm->parsevars->sender, BOLD, BOLD, channel, BOLD);
	privmsg(u->nick, msg);
      }
      sprintf(msg, "Removed ban for: %c%s%c (%c%s%c)", BOLD, target, BOLD, BOLD, arm->parsevars->sender, BOLD);
      privmsg(channel, msg);
      say(arm->parsevars->sender, "Unbanned.", arm);
      
    } else { 
      say(arm->parsevars->sender, "No such ban in memory, still unbanning on channel.", arm);
      sprintf(msg, "MODE %s -b %s\n\r", channel, target);
      putserver(msg, findchannel(channel)->arm);
    }
  } else say(arm->parsevars->sender, "Insufficient access", arm);
}

void m_op (char *a, struct arm *arm)
{
  struct channel *c;
  char nick[NICKLEN+1], channel[CHANNELLEN+1];

  if(!checkargs(2, 0, a, arm)) return;

  sscanf(a, "%" STRCHANNELLEN "s %" STRNICKLEN "s", channel, nick);
  
  c = findchannel(channel);
  
  if(c == NULL) {
    say(arm->parsevars->sender, "Channel doesen't exist", arm);
    return;
  }
  
  if((chanuserlevel(arm->parsevars->sender, channel) >= 3 && c->bitch == 0) || (chanuserlevel(arm->parsevars->sender, channel) >= 4 && c->bitch == 1) || userlevel(arm->parsevars->sender) >= 10) op(channel, nick);
  else say(arm->parsevars->sender, "Insufficient access", arm);
}

void m_deop (char *a, struct arm *arm) {
  struct channel *c;
  char nick[NICKLEN+1], channel[CHANNELLEN+1];

  if(!checkargs(2, 0, a, arm)) return;

  sscanf(a, "%" STRCHANNELLEN "s %" STRNICKLEN "s", channel, nick);
  
  c = findchannel(channel);
  
  if(c == NULL) {
    say(arm->parsevars->sender, "Channel doesen't exist", arm);
    return;
  }
  
  if(((chanuserlevel(arm->parsevars->sender, channel) >= CHAN_OP && c->bitch == 0) || (chanuserlevel(arm->parsevars->sender, channel) >= CHAN_MASTER && c->bitch == 1) || userlevel(arm->parsevars->sender) >= TECHNICIAN) && (strcasecmp(nick, arm->nick) != 0)) deop(channel, nick);
  else say(arm->parsevars->sender, "Insufficient access", arm);
}

void m_voice (char *a, struct arm *arm)
{
  struct channel *c;
  char nick[NICKLEN+1], channel[CHANNELLEN+1];

  if(!checkargs(2, 0, a, arm)) return;

  sscanf(a, "%" STRCHANNELLEN "s %" STRNICKLEN "s", channel, nick);
  
  c = findchannel(channel);
  
  if(c == NULL) {
    say(arm->parsevars->sender, "Channel doesen't exist", arm);
    return;
  }
  
  if((chanuserlevel(arm->parsevars->sender, channel) >= CHAN_VOICE && c->bitch == 0) || (chanuserlevel(arm->parsevars->sender, channel) >= CHAN_OP && c->bitch == 1)  || userlevel(arm->parsevars->sender) >= TECHNICIAN) voice(channel, nick);
  else say(arm->parsevars->sender, "Insufficient access", arm);
}

void m_devoice (char *a, struct arm *arm) {
  struct channel *c;
  char nick[NICKLEN+1], channel[CHANNELLEN+1];

  if(!checkargs(2, 0, a, arm)) return;


  sscanf(a, "%" STRCHANNELLEN "s %" STRNICKLEN "s", channel, nick);
  
  c = findchannel(channel);
  
  if(c == NULL) {
    say(arm->parsevars->sender, "Channel doesen't exist", arm);
    return;
  }
  
  if((chanuserlevel(arm->parsevars->sender, channel) >= CHAN_VOICE && c->bitch == 0) || (chanuserlevel(arm->parsevars->sender, channel) >= CHAN_OP && c->bitch == 1)  || userlevel(arm->parsevars->sender) >= TECHNICIAN) devoice(channel, nick);
  else say(arm->parsevars->sender, "Insufficient access", arm);
}

void m_devoiceall (char *a, struct arm *arm) {
  struct channel *c;
  struct activechanuser *acu;

  char buffer[512] = "";
  char modebuffer[50] = "";
  char nickbuffer[512] = "";

  int i = 0;
  int total = 0;
  
  if(!checkargs(1, 0, a, arm)) return;
 
  c = findchannel(a);
  
  if(c == NULL) {
    say(arm->parsevars->sender, "Channel doesen't exist", arm);
    return;
  }  
  
  acu = firstacu;

  while (acu != NULL)
    {
      if(acu->channel == c && acu->voice == 1 && acu->op == 0 && chanuserlevel(acu->user->nick, c->name) < CHAN_VOICE) {
	strcat(modebuffer, "v");
	strcat(nickbuffer, acu->user->nick);
	strcat(nickbuffer, " ");
	++i;
	  
	if(i >= 6) {
	  snprintf(buffer, 512, "MODE %s -%s %s\n\r", c->name, modebuffer, nickbuffer);
	  putserver(buffer, c->arm);

	  strncpy(modebuffer, "", 50);
	  strncpy(nickbuffer, "", 512);
	    
	  i = 0;
	}

	++total;
      }
      acu = acu->next;
    }
  
  if(i > 0) {
    snprintf(buffer, 512, "MODE %s -%s %s\n\r", c->name, modebuffer, nickbuffer);
    putserver(buffer, c->arm);
  }

  snprintf(buffer, 512, "Done. Totally devoiced: %c%i%c", BOLD, total, BOLD);
  say(arm->parsevars->sender, buffer, arm);
}

void m_invite (char *a, struct arm *arm) {
  struct channel *c;

  if(!checkargs(1, 0, a, arm)) return;
 
  if((c = findchannel(a)) == NULL) {
    say(arm->parsevars->sender, "Channel doesen't exist", arm);
    return;
  }

  if(c->isop != 1 || c->ison != 1) {
   say(arm->parsevars->sender, "I do not have channel operator status there.", arm); 
  }
  
  if((chanuserlevel(arm->parsevars->sender, c->name) >= CHAN_FRIEND) || (userlevel(arm->parsevars->sender) >= TECHNICIAN)) invite(c, arm->parsevars->sender);  else say(arm->parsevars->sender, "Insufficient access", arm);
}

void m_kick (char *a, struct arm *arm) {
  struct channel *c;
  int i, j;
  char nick[NICKLEN+1], channel[CHANNELLEN+1], reason[512] = "";

  if(!checkargs(2, 1, a, arm)) return;

  sscanf(a, "%" STRCHANNELLEN "s %" STRNICKLEN "s", channel, nick);

  c = findchannel(channel);

  if(c == NULL) {
    say(arm->parsevars->sender, "Channel doesen't exist", arm);
    return;
  }

  if(c->isop != 1) {
    say(arm->parsevars->sender, "I do no have channel operator status there.", arm);
    return;
  }
  
  if(findachanuser(nick, channel) == NULL) {
    say(arm->parsevars->sender, "Target is not on channel.", arm);
    return;
  }
  
  if((chanuserlevel(arm->parsevars->sender, channel) >= CHAN_MASTER || userlevel(arm->parsevars->sender) >= TECHNICIAN) && (strcasecmp(nick, arm->nick) != 0)) {
    if(countargs(a) == 2) {
      sprintf(reason, "Requested by: %c%s%c", BOLD, arm->parsevars->sender, BOLD);
    } else {
      for(i = 0; a[i] != ' '; ++i);
      ++i;
      for(; a[i] != ' '; ++i);
      ++i;

      j = 0;
      while (a[i] != '\0' && j < 512) {
	reason[j] = a[i];
	++i;
	++j; 
      }
    }
    kick(channel, nick, reason);
    say(arm->parsevars->sender, "Done.", arm);
  }
  else say(arm->parsevars->sender, "Insufficient access", arm);
}

void m_flushlog (char *a, struct arm *arm) {
  say(arm->parsevars->sender, "Flushing log...", arm);
  flushlog();
}

void m_listauth (char *a, struct arm *arm) {
    struct activeuser *u;
    char msg[512];

    u = firstauser;
    while (u != NULL)
      {
	if(u->auth > 1 && u->auth < 30) {
	  snprintf(msg, 512, "%c%s%c is AUTH'd as %c%s%c with level: %c%i%c", BOLD, u->nick, BOLD, BOLD, u->hand, BOLD, BOLD, u->auth, BOLD);
	  bestsay(arm->parsevars->sender, msg);
	}
	u = u->next;
    }
}

void m_badchan (char *a, struct arm *arm) {
  char channel[CHANNELLEN+1] = "";
  char reason[250] = "";
  char query[MAX_QUERY];
  char duration[20] = "";
  int i = 0;
  int j = 0;
  int finalduration;
  struct activeuser *u;

  if(!checkargs(3, 1, a, arm)) return;

  while (a[i] != ' ' && a[i] != '\0') {
    channel[j] = a[i];
    ++i;
    ++j; 
  }

  ++i;
  j = 0;
  while (a[i] != ' ' && j < 20) {
    duration[j] = a[i];
    ++i;
    ++j; 
  }
    
  ++i;
  j = 0;
  while (a[i] != '\0' && j < 249) {
    reason[j] = a[i];
    ++i;
    ++j; 
  }

  if((u = findauser(arm->parsevars->sender)) == NULL) return;

  if((finalduration = StrDurationToSeconds(duration)) == -1) {
    say(arm->parsevars->sender, "Wrong duration, duration can be day(d), hour(h), minute(m). I.e: 2h (two hours)", arm);
    return;
  }

  if(AddBadChan(channel, reason, finalduration, u->userid) == 1) {
    sprintf(query,"Added BADCHAN for: %c%s%c, expireing in: %c%s%c (%c%s%c)", BOLD, channel, BOLD, BOLD, duration, BOLD, BOLD, arm->parsevars->sender, BOLD);
    privmsg(HOMECHAN, query);  
  } else {
    say(arm->parsevars->sender, "There is already an active badchan for that channel.", arm);
    return;
  }
}

void m_regexbadchan (char *a, struct arm *arm) {
char channel[CHANNELLEN+1] = "";
  char reason[250] = "";
  char query[MAX_QUERY];
  char duration[20] = "";
  int i = 0;
  int j = 0;
  int finalduration;
  struct activeuser *u;

  if(!checkargs(3, 1, a, arm)) return;

  while (a[i] != ' ' && a[i] != '\0') {
    channel[j] = a[i];
    ++i;
    ++j; 
  }

  ++i;
  j = 0;
  while (a[i] != ' ' && j < 20) {
    duration[j] = a[i];
    ++i;
    ++j; 
  }
    
  ++i;
  j = 0;
  while (a[i] != '\0' && j < 249) {
    reason[j] = a[i];
    ++i;
    ++j; 
  }

  if((u = findauser(arm->parsevars->sender)) == NULL) return;

  if((finalduration = StrDurationToSeconds(duration)) == -1) {
    say(arm->parsevars->sender, "Wrong duration, duration can be day(d), hour(h), minute(m). I.e: 2h (two hours)", arm);
    return;
  }

  if(AddRegexBadChan(channel, reason, finalduration, u->userid) == 1) {
    sprintf(query,"Added BADCHAN for: %c%s%c, expireing in: %c%s%c (%c%s%c)", BOLD, channel, BOLD, BOLD, duration, BOLD, BOLD, arm->parsevars->sender, BOLD);
    privmsg(HOMECHAN, query);  
  } else {
    say(arm->parsevars->sender, "There is already an active badchan for that regex.", arm);
    return;
  }
}

void m_unbadchan (char *a, struct arm *arm) {
  
  if(DelBadChan (a)) {
    say(arm->parsevars->sender, "Done.", arm);
    return;
  } else {
    say(arm->parsevars->sender, "No active badchan matching that regex exists.", arm);
    return;
  }
}

void m_reloadmod (char *a, struct arm *arm) {
  struct module *m;
  char path[100];

  if(!checkargs(1, 0, a, arm)) return;
  
  if((m = findmodule(a)) != NULL) {
    if(strcasecmp(a, "MSGHandlers") == 0) {
      say(arm->parsevars->sender, "This module will be reloaded in 20 seconds.", arm);
      reloadmsgmod = 1;
      return;
    } else if(strcasecmp(a, "IRCHandlers") == 0) {
      say(arm->parsevars->sender, "This module will be reloaded in 20 seconds.", arm);
      reloadircmod = 1;
      return;
    }

    strncpy(path, m->path, 100);
    unloadmodule(a);
    loadmodule(path, 0);

    say(arm->parsevars->sender, "Done.", arm);
  } else say(arm->parsevars->sender, "No module with that name is loaded.", arm); 
}

void m_unloadmod (char *a, struct arm *arm) {
  struct module *m;

  if(!checkargs(1, 0, a, arm)) return;
  
  if((m = findmodule(a)) != NULL) {
    if(strcasecmp(a, "MSGHandlers") == 0) {
      say(arm->parsevars->sender, "This module cannot be unloaded.", arm);
      return;
    }
    unloadmodule(a);
    say(arm->parsevars->sender, "Done.", arm);
  } else say(arm->parsevars->sender, "No module with that name is loaded.", arm); 
}

void m_loadmod (char *a, struct arm *arm) {
  struct module *m;

  if(!checkargs(1, 0, a, arm)) return;
  
  if((m = findmodulebypath(a)) == NULL) {
    loadmodule(a, 0);
    say(arm->parsevars->sender, "Done.", arm);
  } else say(arm->parsevars->sender, "A module with that name is already loaded.", arm); 
}

void m_modstats (char *a, struct arm *arm) {
  struct module *m;
  char msg[512];
  
  if(!checkargs(0, 0, a, arm)) return;
  
  snprintf(msg, 512, "NOTICE %s :Name    Version Compiled @          Path\n\r", arm->parsevars->sender);
  puttoserver(msg, findarmbyid(1));
  usleep(200);

  m = firstmodule;
  while (m != NULL)
    {
      snprintf(msg, 512, "%s    %0.2f    %s %s", m->name, m->version, m->compiledate, m->path);
      bestsay(arm->parsevars->sender, msg);
      m = m->next;
    }
}

void m_accept (char *a, struct arm *arm) {
  findauser(arm->parsevars->sender)->requestok = 1;
  say(arm->parsevars->sender, "You will now be able to commit 1 request from our homepage. If you experience any problems, please head to " PUBCHAN, arm);
}

void m_addarm (char *a, struct arm *arm) {
    char query[MAX_QUERY];
    int id;

    if(!checkargs(1, 0, a, arm)) return;

    if(findarm(a) != NULL) { 
      bestsay(arm->parsevars->sender, "ARM already exists.");
      return;
    }
    
    id = lastarm->id + 1;

    sprintf(query, "INSERT INTO arms (id, nick, sid) VALUES ('%i','%s', '" SID "')", id, a);
    dbquery(query);  
    EndDbQuery();
    
    addarm(a, id, 30);

    bestsay(arm->parsevars->sender, "ARM added.");
    
    sprintf(query, "%c%s%c added ARM %c%s%c", BOLD, arm->parsevars->sender, BOLD, BOLD, a, BOLD);
    privmsg(HOMECHAN, query);
}

void m_delarm (char *a, struct arm *arm) {
    char query[MAX_QUERY];

    if(!checkargs(1, 0, a, arm)) return;

    if(findarm(a) == NULL) { 
      dumpmessage(arm->parsevars->sender, "ARM doesen't exist.");
      return;
    }
    
    deldbarm(a);
    delarm(a);
    
    sprintf(query, "%c%s%c deleted ARM %c%s%c", BOLD, arm->parsevars->sender, BOLD, BOLD, a, BOLD);
    privmsg(HOMECHAN, query);
}

void m_connectarms (char *a, struct arm *arm) {
  char msg[512];

  if(!checkargs(0, 0, a, arm)) return;
    
  if(connectarms == 1) {
    connectarms = 0;
    printf("ARM connection disabled.\n");
    snprintf(msg, 512, "ARM connectin is now %cdisabled%c.", BOLD, BOLD);
  } else {
    connectarms = 1;
    printf("ARM connection enabled.\n");
    snprintf(msg, 512, "ARM connectin is now %cenabled%c.", BOLD, BOLD);
  }

  say(arm->parsevars->sender, msg, arm);
}

void m_armmode (char *a, struct arm *arm) {
  struct arm *tarm;
  char msg[512];

  if(!checkargs(1, 0, a, arm)) return;
  
  if((tarm = findarm(a)) == NULL) {
    say(arm->parsevars->sender, "No such ARM.", arm); 
    return;
  }
  
  if(tarm->connect == 1) {
    tarm->connect = 0;
    snprintf(msg, 512, "QUIT :Suspending...\n\r");
    puttoserver(msg, tarm);
    
    linkbreak(tarm);

    say(arm->parsevars->sender, "ARM suspended.", arm);
  } else {
    tarm->connect = 1;
    say(arm->parsevars->sender, "ARM activated.", arm);
  }
}

#ifdef OUTGOING_VHOST
void m_vhost (char *a, struct arm *arm) {
  struct arm *tarm;
  char msg[512];
  char nick[NICKLEN];
  char vhost[512];

  if(!checkargs(2, 0, a, arm)) return;
  
  sscanf(a, "%" STRNICKLEN "s %150s", nick, vhost);

  if((tarm = findarm(nick)) == NULL) {
    say(arm->parsevars->sender, "No such ARM.", arm); 
    return;
  }

  if(gethostbyname(vhost) == NULL) {
    say(arm->parsevars->sender, "Lookup of vhost failed.", arm);
    return;
  }

  strncpy(tarm->vhost, vhost, 150);

  snprintf(msg, 512, "QUIT :Host change...\n\r");
  puttoserver(msg, tarm);
    
  linkbreak(tarm);

  say(arm->parsevars->sender, "Done.", arm);
 
}
#endif

void m_syncarm (char *a, struct arm *arm) {
  struct arm *tarm;
  char armnick[NICKLEN];
  char msg[512];
  int type;

  if(!checkargs(2, 0, a, arm)) return;
    
  sscanf(a, "%s %i", armnick, &type);
  
  if((tarm = findarm(armnick)) == NULL && !(strcmp(armnick, "*") == 0 && type == 0)) {
    say(arm->parsevars->sender, "No such ARM.", arm); 
    return;
  }
  
  if(type == 0) {
    
    if(strcmp(armnick, "*") == 0) {
      tarm = firstarm;

      while(tarm != NULL) {
	if(tarm->status == 1) rejoinchannel(HOMECHAN, tarm);
	tarm = tarm->next;
      }
    } else rejoinchannel(HOMECHAN, tarm);

    strncpy(msg, "Done.", 512);
  } else if(type == 1) {
    snprintf(msg, 512, "QUIT :Reconnecing...\n\r");
    puttoserver(msg, tarm);
 
    close(tarm->fd);
    linkbreak(tarm);

    strncpy(msg, "Done.", 512);
  } else if(type == 2) {
    snprintf(msg, 512,  "UPDATE `arms` SET `status` = '%i', `channels` = '%i' WHERE `id` = '%i'", tarm->status, tarm->channels, tarm->id);
    dbquery(msg);

    EndDbQuery();

    strncpy(msg, "Done.", 512);
  } else if(type == 3) {
    linkbreak(tarm);

    if(pthread_create(&tarm->thread, NULL, armthread, tarm)) printf("Errorcreating thread for %s.", tarm->nick);
    tarm->activethread = 1;

    strncpy(msg, "Done.", 512);
  } else strncpy(msg, "No such type.", 512);

    say(arm->parsevars->sender, msg, arm);
}

void m_status (char *a, struct arm *arm) {
  int users = 0;
  int authed = 0;
  char msg[512];
  struct activeuser *u;

  sprintf(msg, "The service is on %i channels.", ServiceChannelCount());
  bestsay(arm->parsevars->sender, msg);

  sprintf(msg, "The service has %i lines in log cache.", lines);
  bestsay(arm->parsevars->sender, msg);

  u = firstauser;
  while (u != NULL)
    {
      ++users;
      if(u->auth > UNAUTHED && u->auth < BOT_NORMAL) ++authed;
      u = u->next;
    }
  sprintf(msg, "The service has %i active users in memory. %i of them are AUTH'd.", users, authed);
  bestsay(arm->parsevars->sender, msg);
}

void m_armstatus (char *a, struct arm *arm) {
  char msg[1024];
  char tmp[5];
  int ops = 0;
  int voices = 0;
  int total = 0;
  int i = 0;
  struct channel *c;
  struct activechanuser *acu;

  sprintf(msg, "I'm currently on %i channels.", arm->channels);
  bestsay(arm->parsevars->sender, msg);
  
  strncpy(msg, "", 1024);
  
  /* Build up channel list */

  c = firstchan;

  while (c != NULL)
    {
      if(c->arm == arm) {
	if(c->ison == 0) strcat(msg, "*");
	else if(c->isop == 1) strcat(msg, "@");
	
	strcat(msg, c->name);
	
	total = ops = voices = 0;
	
	acu = firstacu;
	while (acu != NULL)
	{
	  if(acu->channel == c) {
	    if(acu->op == 1) ++ops;
	    if(acu->voice == 1) ++voices;
	    ++total;
	  }
	  acu = acu->next;
	}
	
	strcat(msg, " (@:");
	sprintf(tmp, "%i", ops);
	strcat(msg, tmp);
	strcat(msg, " +:");
	sprintf(tmp, "%i", voices);
	strcat(msg, tmp);
	strcat(msg, " T:");
	sprintf(tmp, "%i) ", total);
	strcat(msg, tmp);
	++i;
	if(i == 10) {
	strcat(msg, "\n");
	i = 0;
	}
      }
      c = c->next;
    }

  dumpmessage(arm->parsevars->sender, msg);
}

void m_rehash (char *a, struct arm *arm) {
  /*
  char query[MAX_QUERY];
  char msg[255];

  sprintf(query, "Rehash requested by: %s.", arm->parsevars->sender);
  privmsg(HOMECHAN, query);
  sprintf(query, "SELECT `botname` FROM `bots` WHERE id = '%s'", botid);
  dbquery(query);
  EndDbQuery()

  if(!(row = mysql_fetch_row(res))) {
    printf("Mysql query failed (result probably empty).\n");
    sprintf(msg, "%c4Warning:%c MySQL query during rehash failed.", COLORS, COLORS);
    privmsg(HOMECHAN, msg);
    quit("Rehash failed"); 
  } 
  
 
  if(strcmp(row[0], botname) != 0) {
    strcpy(botname, row[0]);
    nick(botname);
  }
  
  say(arm->parsevars->sender, "Rehash complete.", arm);
*/
  say(arm->parsevars->sender, "Rehash is not possible yet.", arm);
}

#ifndef Q_AUTOAUTH
void m_hello (char *a, struct arm *arm)
{
  struct activeuser *u;
  char message[512];
  char pass[10];
  char query[MAX_QUERY];
  char hubq[5];

  u = findauser(arm->parsevars->sender);

  srand(time(NULL));

  if (u != NULL)
    {
     
      if (u->auth != 0)
	{
	  say (arm->parsevars->sender, "You've already AUTH'd!", arm);
	  return;
	}

      sprintf(pass, "NAT%dAS%dHA", rand()/100000000, rand()/1000000000);
      
      sprintf(query, "HELLO %s %s\n", arm->parsevars->sender, pass);
      //puthub(query);
      
      // sprintf(hubq, gethubline());
      if(atoi(hubq) == 1) {

	sprintf(query, "AUTH %s %s %s %s %s\n", arm->parsevars->sender, pass, arm->parsevars->sender, u->username, u->hostname); // Send auth request to hub. format: AUTH hand password arm->parsevars->sender
	// puthub(query);

	sprintf(message, "Hello, %s. A new user account has been created for you, with handle %s.", arm->parsevars->sender, arm->parsevars->sender);
	say (arm->parsevars->sender, message, arm);
	sprintf (message, "Your password is initially %s.", pass);
	say (arm->parsevars->sender, message, arm);
	say (arm->parsevars->sender, "We recommend you to do as following:");
	sprintf (message, "Set new password: /msg %s NEWPASS <pass> Example: /msg %s NEWPASS coolpass", botname, botname);
	say (arm->parsevars->sender, message, arm);
	sprintf (message, "Set E-Mail (for password retrieval purposes): /msg %s EMAIL <email> Example: /msg %s EMAIL cool@dudes.com", botname, botname);
	say (arm->parsevars->sender, message, arm);
	sprintf (message, "Add AUTH in your clients \"perform\": /msg %s AUTH %s <pass> Example: /msg %s AUTH %s coolpass", botname, arm->parsevars->sender, botname, arm->parsevars->sender);
	say (arm->parsevars->sender, message, arm);
	sprintf (message, "To see all commands available to you, use the command SHOWCOMMANDS Example: /msg %s SHOWCOMMANDS", botname);
	say (arm->parsevars->sender, message, arm);
	sprintf (message, "For more information and help visit: %s", HELPSITE);
	say (arm->parsevars->sender, message, arm);

      } else say (arm->parsevars->sender, "Someone's already registered with that nick!", arm);
    }
}
#endif

void m_quit (char *a, struct arm *arm) {
  quit(a);
}
  
void m_say (char *a, struct arm *arm) {
  char msg[512] = "";
  char target[CHANNELLEN] = "";
  int i = 0;
  int j = 0;
  struct channel *c;

  if(!checkargs(2, 1, a, arm)) return;

  while (a[i] != ' ' && a[i] != '\0' && i < CHANNELLEN) {
    target[j] = a[i];
    ++i;
    ++j; 
  }
    
  ++i;
  j = 0;
  while (a[i] != '\0' && j < 512) {
    msg[j] = a[i];
    ++i;
    ++j; 
  }

  if(target[0] == '#' && findchannel(target) == NULL) return;

#ifdef Q
  if(((a[0] == 'Q' || a[0] == 'q') || (a[0] == 'L' || a[0] == 'l')) && userlevel(arm->parsevars->sender) < 21) say(arm->parsevars->sender, "Only Master Technicians can send Q commands", arm);
  else {
#endif

    if((c = findchannel(target)) != NULL && (chanuserlevel(arm->parsevars->sender, target) >= CHAN_VOICE || userlevel(arm->parsevars->sender) >= 10)) 
#ifdef SPAMSCAN
      (!SOnChannel(c)) ? privmsg(target, msg) : say(arm->parsevars->sender, "You cannot use the say command on channels with S (spamscan).", arm);
#else
    privmsg(target, msg);
#endif

 else if(userlevel(arm->parsevars->sender) >= 10) exprivmsg(target, msg, arm);

#ifdef Q
  }
#endif
}

void m_staffmsg (char *a, struct arm *arm) {
  char msg[512] = "";
  char message[512] = "";
  int i = 0;
  int j = 0;
  int targetauth = 0;
  char mask;
  struct activeuser *u;

  if(!checkargs(2, 1, a, arm)) return;

  sscanf(a, "%c%i", &mask, &targetauth);
  
  if(mask != '<' && mask != '>' && mask != '=') {
    say(arm->parsevars->sender, "The mask first char must be < > or =", arm);
    return;
  }
  
  for(i = 0; a[i] != ' '; ++i);
  ++i;

  j = 0;
  while (a[i] != '\0' && j < 512) {
    message[j] = a[i];
    ++i;
    ++j; 
  }

  say(arm->parsevars->sender, "Done.", arm);

  u = firstauser;
  while (u != NULL)
    {
      if(u->auth > 1 && u->auth < 30 && u->auth != 22) {

	if((mask == '<' && u->auth < targetauth) || (mask == '>' && u->auth > targetauth) || (mask == '=' && u->auth == targetauth)) {
	  snprintf(msg, 512, "Message from %c%s%c: %s", BOLD, arm->parsevars->sender, BOLD, message);
	  privmsg(u->nick, msg);
	}
      }
      u = u->next;
    }
}

void m_staffnotice (char *a, struct arm *arm) {
  char msg[512] = "";
  char message[512] = "";
  int i = 0;
  int j = 0;
  int targetauth = 0;
  char mask;
  struct activeuser *u;

  if(!checkargs(2, 1, a, arm)) return;

  sscanf(a, "%c%i", &mask, &targetauth);
  
  if(mask != '<' && mask != '>' && mask != '=') {
    say(arm->parsevars->sender, "The mask first char must be < > or =", arm);
    return;
  }
  
  for(i = 0; a[i] != ' '; ++i);
  ++i;

  j = 0;
  while (a[i] != '\0' && j < 512) {
    message[j] = a[i];
    ++i;
    ++j; 
  }

  say(arm->parsevars->sender, "Done.", arm);

  u = firstauser;
  while (u != NULL)
    {
      if(u->auth > 1 && u->auth < 30 && u->auth != 22) {

	if((mask == '<' && u->auth < targetauth) || (mask == '>' && u->auth > targetauth) || (mask == '=' && u->auth == targetauth)) {
	  snprintf(msg, 512, "Message from %c%s%c: %s", BOLD, arm->parsevars->sender, BOLD, message);
#ifdef CNOTICE
	  cnotice(u->nick, msg);
#else
	  bestsay(u->nick, msg);
#endif
	}
      }
      u = u->next;
    }
}

void m_allsay (char *a, struct arm *arm) {
  char msg[512] = "";
  char out[512];
  char target[CHANNELLEN] = "";
  int i = 0;
  int j = 0;
  struct arm *am;

  if(!checkargs(2, 1, a, arm)) return;

  while (a[i] != ' ' && a[i] != '\0' && i < CHANNELLEN) {
    target[j] = a[i];
    ++i;
    ++j; 
  }
    
  ++i;
  j = 0;
  while (a[i] != '\0' && j < 512) {
    msg[j] = a[i];
    ++i;
    ++j; 
  }

  snprintf(out, 512, "PRIVMSG %s :%s\n\r", target, msg);

  
  am = firstarm;
  while (am != NULL)
    {
      if(am->status == 1 && am->id != 1) putserver(out, am);
      am = am->next;
    }

  say(arm->parsevars->sender, "Done.", arm);
}

void m_broadcast (char *a, struct arm *arm) {
  char out[1024];
  struct channel *c;

  if(!checkargs(1, 1, a, arm)) return;

  sprintf(out, "Broadcast: %c%s%c (%s)", BOLD, a, BOLD, arm->parsevars->sender);
  privmsg(HOMECHAN, out);

  sprintf(out, "Broadcast: %c%s", BOLD, a);

  c = firstchan;

  while (c != NULL) {
    if(c->ison == 1 && c->isop == 1) privmsg(c->name, out);
    c = c->next;
  }
}

#ifndef Q_AUTOAUTH
void m_auth (char *a, struct arm *arm)
{
  char uids[NICKLEN];
  char password[512];
  char temp[30] = "";
  char query[MAX_QUERY];
  int i;
  struct activeuser *u;

  i = 0;

  if(!checkargs(2, 0, a, arm)) return;

  sscanf(a, "%s %s", uids, password);
  sprintf(query, "AUTH %s %s %s %s %s\n", uids, password, arm->parsevars->sender, u->username, u->hostname); // Send auth request to hub. format: AUTH hand password arm->parsevars->sender
  // puthub(query);

  // sprintf(temp, gethubline());
  
  if(strcmp(temp, "1\n") == 0) {
    say(arm->parsevars->sender, "AUTH'd successfully.", arm);
  } else if(strcmp(temp, "0\n") == 0) say (arm->parsevars->sender, "Wrong password or nick.");
  else say(arm->parsevars->sender, "This bot is currently not linked. Please wait until the problem is fixed or try to auth through another bot.", arm);
    
}
#endif

void m_showcommands (char *a, struct arm *arm)
{
  int i = 0, j;
  char buffer[512];

  while (msgtab[i].func != 0)
    {
      if (msgtab[i].level <= userlevel (arm->parsevars->sender))
	{

         memset (buffer, 0, 512);
         strncpy (buffer, msgtab[i].msg, 256);
         strcat (buffer, " ");
         strncat (buffer, msgtab[i].summary, 200);

	 j = strlen (buffer);
	 sprintf (buffer + j, " - level %d.", msgtab[i].level);
	 dumpmessage (arm->parsevars->sender, buffer);
	}
      i++;
    }
  
  amodfunc("PUBHandlers", "p_showcommands", arm);
  
}

void m_help (char *a, struct arm *arm)
{
  int i;
  char send[4096];
  struct module *m;
  void (*p_help)(char *a, struct arm *arm);

  i = 0;
  while (msgtab[i].func != 0)
    {
      if (strcasecmp (a, msgtab[i].msg) == 0)
	{
	  snprintf(send, 4096, msgtab[i].help, arm->nick);
	  dumpmessage (arm->parsevars->sender, send);  
	  return;
	}
      i++;
    }
  m = findmodule("PUBHandlers");
  if(m != NULL) {
    p_help = dlsym(m->fl, "p_help");
    p_help(a, arm);
  } else {
    sprintf(send, "No help found on that topic. Try /msg %s SHOWCOMMANDS.", arm->nick);
    say (arm->parsevars->sender, send, arm);
  }
}

void m_whoami (char *a, struct arm *arm)
{
  struct activeuser *u;
  char buffer[512];
 
  u = findauser (arm->parsevars->sender);
  if (u != NULL)
    {
      if (u->auth < 1)
	{
	  sprintf (buffer, "You are probably %s.", u->nick);
	  say (arm->parsevars->sender, buffer, arm);
	}
      else
	{
	  sprintf (buffer, "You are definately %s.", u->hand);
	  say (arm->parsevars->sender, buffer, arm);
	}
      sprintf (buffer, "Global auth level: %d (%s).", u->auth, authtotext(u->auth));
      say (arm->parsevars->sender, buffer, arm);
      sprintf (buffer, (u->userid != 0) ? "You have authed as userid %d." : "You have not authed.", u->userid);
      say (arm->parsevars->sender, buffer, arm);
    }
  else
    {
      say (arm->parsevars->sender, "You don't exist!", arm);
    }
}

void m_join (char *a, struct arm *arm)
{
  char msg[255];
  char locsender[NICKLEN];
  char locchan[CHANNELLEN];

  if(!checkargs(1, 0, a, arm)) return;

  if(arm->channels+1 == MAXCHANS) say(arm->parsevars->sender, "Channel limit reached.", arm);
  else {
    strncpy(locsender, arm->parsevars->sender, NICKLEN);
    strncpy(locchan, a, CHANNELLEN);

    if(strcasecmp(locchan, HOMECHAN) != 0 && c_join(a, arm)) {
      sprintf(msg, "Joining channel: %s", locchan);
      say(locsender, msg, arm);
      
      sprintf(msg, "Joining channel: %s (%s)", locchan, locsender);
      privmsg(HOMECHAN, msg);
    } else { 
      sprintf(msg, "I'm already on channel: %s", a);
      say(arm->parsevars->sender, msg, arm);
    }
  }
}

void m_part (char *a, struct arm *arm)
{
  char msg[512];
 
  if(!checkargs(1, 0, a, arm)) return;

  if(strcasecmp(a, HOMECHAN) == 0) {
    say(arm->parsevars->sender, "I won't leave home.", arm);
    sprintf(msg, "%s wanted me to leave home, but i don't want to leave.", arm->parsevars->sender);
    privmsg(HOMECHAN, msg);
  } else {
    sprintf(msg, "Requested by admin: %s", arm->parsevars->sender);
    if(c_part(a, msg)) {
      sprintf(msg, "Leaving channel: %s", a);
      say(arm->parsevars->sender, msg, arm);

      sprintf(msg, "Leaving channel: %s (%s)", a, arm->parsevars->sender);
      privmsg(HOMECHAN, msg); 
    } else { 
      sprintf(msg, "I'm not on channel: %s", a);
      say(arm->parsevars->sender, msg, arm);
    }
  }
  
}

void m_cycle (char *a, struct arm *arm)
{
  struct channel *c;

  if(!checkargs(1, 0, a, arm)) return;

  if((c = findchannel(a)) == NULL) {
    say(arm->parsevars->sender, "No such channel.", arm);
    return;
  }

  if(userlevel(arm->parsevars->sender) >= HELPER || chanuserlevel(arm->parsevars->sender, c->name) == CHAN_OWNER) {
    cyclechannel(c, "cycle requested");
    say(arm->parsevars->sender, "Done.", arm);
  } else say(arm->parsevars->sender, "Not enough access. Only helpers or channel owners can move bots.", arm);
}

void m_listachanusers (char *a, struct arm *arm) {
  char msg[512];
  struct activechanuser *acu;
  int in = 0;

  acu = firstacu;

  while (acu != NULL)
    {
      if(strcasecmp(acu->channel->name, a) == 0) { 
	snprintf(msg, 512, "%s %s@%s", acu->user->nick, acu->user->username, acu->user->hostname);
	bestsay(arm->parsevars->sender, msg);
	++in;
      }
      acu = acu->next;
    }

  sprintf(msg, "Total users: %c%i%c in %c%s%c.", BOLD, in, BOLD, BOLD, a, BOLD);
  bestsay(arm->parsevars->sender, msg);
}

#ifdef Q
void m_requestop (char *a, struct arm *arm) {
  struct channel *c;
  char msg[512];

  c = firstchan;

  while (c != NULL) {
    if(isOpLessChan(c)) { 
      sprintf(msg, "Found opless channel: %c%s%c", BOLD, c->name, BOLD); 
      privmsg(HOMECHAN, msg); 
      o_requestop(c);
    }
    c = c->next;
  }
  say(arm->parsevars->sender, "Done.", arm);
}
#endif

void m_move (char *a, struct arm *arm)
{
  char from[CHANNELLEN];
  char to[CHANNELLEN];
  char msg[512];
  short out;

  if(!checkargs(2, 0, a, arm)) return;

  sscanf(a, "%" STRCHANNELLEN "s %" STRCHANNELLEN "s", from, to);

  if(userlevel(arm->parsevars->sender) >= HELPER || chanuserlevel(arm->parsevars->sender, from) == CHAN_OWNER) {
    out = c_move(from, to);

    if(out == 1) {
      say(arm->parsevars->sender, "Move successful.", arm);
      sprintf(msg, "Moving from: %c%s%c to: %c%s%c (%c%s%c)", BOLD, from, BOLD, BOLD, to, BOLD, BOLD, arm->parsevars->sender, BOLD);
      privmsg(HOMECHAN, msg);
    }
    else if (out == 2) say(arm->parsevars->sender, "The service is already on the channel you are trying to move to.", arm);
    else if (out == 0) say(arm->parsevars->sender, "I'm not on that channel.", arm);
  } else say(arm->parsevars->sender, "Not enough access. Only helpers or channel owners can move bots.", arm);
}

void m_version (char *a, struct arm *arm)
{
  char msg[512];
  snprintf(msg, 512, CTCP_VERSION_REPLY " Compiled at: %s", compiledate);

  say(arm->parsevars->sender, msg, arm);
}

void m_chanset (char *a, struct arm *arm) {
  char channame[CHANNELLEN+1] = "";
  char mode[20] = "";
  char value[500] = "";
  char query[MAX_QUERY];
  struct channel *c;
  int go = 1;
  int i;
  int j;

  if(!checkargs(2, 1, a, arm)) return;

  sscanf(a, "%s %s %s", channame, mode, value);
  
  if(mode[0] != '+' && mode[0] != '-') say(arm->parsevars->sender, "You must start your mode with + or -", arm);
  else {
    
    c = findchannel(channame);
  
    if(strcmp(channame, HOMECHAN) == 0) say(arm->parsevars->sender, "Can't change modes on home.", arm);
    else {
      if(c == NULL) say(arm->parsevars->sender, "Sorry, that channel does not exist", arm);
      else {
	if(chanuserlevel(arm->parsevars->sender,channame) >= 4 || userlevel(arm->parsevars->sender) >= 10) {
	  if (strcmp(mode, "+modes") == 0) {
	    strcpy(c->modes, value);
	    dbchanmode(c->id, "modes", value);
	  } else if (strcmp(mode, "-modes") == 0) {
	    strcpy(c->modes, "");
	    dbchanmode(c->id, "modes", "");
	  } else if (strcmp(mode, "+key") == 0) {
	    strcpy(c->key, value);
	    dbchanmode(c->id, "key", value);
	  } else if (strcmp(mode, "-key") == 0) {
	    strcpy(c->key, "");
	    dbchanmode(c->id, "key", "");
	  } else if (strcmp(mode, "+autoop") == 0) {
	    c->autoop = 1;
	    dbchanmode(c->id, "autoop", "1");
	  } else if (strcmp(mode, "-autoop") == 0) {
	    c->autoop = 0;
	    dbchanmode(c->id, "autoop", "0");
	  } else if (strcmp(mode, "+autovoice") == 0) {
	    c->autovoice = 1;
	    dbchanmode(c->id, "autovoice", "1");
	  } else if (strcmp(mode, "-autovoice") == 0) {
	    c->autovoice = 0;
	    dbchanmode(c->id, "autovoice", "0");
	  } else if (strcmp(mode, "+bitch") == 0) {
	    c->bitch = 1;
	    dbchanmode(c->id, "bitch", "1");
	  } else if (strcmp(mode, "-bitch") == 0) {
	    c->bitch = 0;
	    dbchanmode(c->id, "bitch", "0");
	  } else if (strcmp(mode, "+topic") == 0) {
	    c->ftopic = 1;
	    dbchanmode(c->id, "ftopic", "1");
	  } else if (strcmp(mode, "-topic") == 0) {
	    c->ftopic = 0;
	    dbchanmode(c->id, "ftopic", "0");
	  } else if (strcmp(mode, "+massvoice") == 0) {
	    if(value[0] == '\0') strcpy(value, "*");
	    strcpy(c->mvoice, value);
	    dbchanmode(c->id, "mvoice", value);
	  } else if (strcmp(mode, "-massvoice") == 0) {
	    strcpy(c->mvoice, "");
	    dbchanmode(c->id, "mvoice", "");
	  } else if (strcmp(mode, "+advertise") == 0) {
	    c->advertise = 1;
	    dbchanmode(c->id, "advertise", "1");
	  } else if (strcmp(mode, "-advertise") == 0) {
	    c->advertise = 0;
	    dbchanmode(c->id, "advertise", "0");
	    } else if (strcmp(mode, "+flood") == 0) {
	      sscanf(value, "%i:%i", &c->floodrep, &c->floodtime);
	      dbchanmode(c->id, "flood", value);
	  } else if (strcmp(mode, "-flood") == 0) {
	    c->floodrep = 0;
	    c->floodtime = 0;
	    dbchanmode(c->id, "flood", "0:0"); 
	  } else if (strcmp(mode, "+peak") == 0) {
	    c->peak = 1;
	    dbchanmode(c->id, "peak", "1");
	  } else if (strcmp(mode, "-peak") == 0) {
	    c->peak = 0;
	    dbchanmode(c->id, "peak", "0");
	  } else if (strcmp(mode, "+greet") == 0) {
	    c->greet = 1;
	    dbchanmode(c->id, "greet", "1");
	  }  else if (strcmp(mode, "-greet") == 0) {
	    c->greet = 0;
	    dbchanmode(c->id, "greet", "0");
	  } else if (strcmp(mode, "+tv") == 0) {
	    c->tv = 1;
	    dbchanmode(c->id, "tv", "1");
	  } else if (strcmp(mode, "-tv") == 0) {
	    c->tv = 0;
	    dbchanmode(c->id, "tv", "0");
	  } else if (strcmp(mode, "+vote") == 0) {
	    c->vote = 1;
	    dbchanmode(c->id, "vote", "1");
	  } else if (strcmp(mode, "-vote") == 0) {
	    c->vote = 0;
	    dbchanmode(c->id, "vote", "0");
	  } else if (strcmp(mode, "+infobot") == 0) {
	    c->infobot = 1;
	    dbchanmode(c->id, "infobot", "1");
	  } else if (strcmp(mode, "-infobot") == 0) {
	    c->infobot = 0;
	    dbchanmode(c->id, "infobot", "0");
	  } else if (strcmp(mode, "+stats") == 0) {
	    c->stats = 1;
	    dbchanmode(c->id, "stats", "1");
	  } else if (strcmp(mode, "-stats") == 0) {
	    c->stats = 0;
	    dbchanmode(c->id, "stats", "0");
	  } else if (strcmp(mode, "+onjoin") == 0) {
	    /* Get out the entire text string */
	    strcpy(value, "");
	    i = j = 0;

	    while(a[i] != '\0' && a[i] != ' ') ++i;
	    ++i;
	    while(a[i] != '\0' && a[i] != ' ') ++i;
	    ++i;
	    while(a[i] != '\0') {
	      value[j] = a[i];
	      ++j;
	      ++i;
	    }

	    strcpy(c->onjoin, value);
	    dbchanmode(c->id, "onjoin", value);
	  } else if (strcmp(mode, "-onjoin") == 0) {
	    strcpy(c->onjoin, "");
	    dbchanmode(c->id, "onjoin", "");
	  }

	  else {
	    say(arm->parsevars->sender, "Sorry, that mode doesen't exist. Try HELP CHANSET.", arm);   
	    go = 0;
	  }
	  if(go == 1) {
	    sprintf(query, "Setting mode %s %s", mode, value);
	    say(arm->parsevars->sender, query, arm);
	  }
	} else say(arm->parsevars->sender, "Sorry, you need to be master or higher to change channel modes.", arm);
      }
    }
  }
}

void m_greet (char *a, struct arm *arm) {
  int i = 0;
  int j = 0;
  char channame[CHANNELLEN+1] = "";
  char nick[NICKLEN+1] = "";
  char value[102] = "";

  struct channel *c;
  struct activeuser *u;

  if(!checkargs(2, 1, a, arm)) return;

  sscanf(a, "%" STRCHANNELLEN "s %" STRNICKLEN "s", channame, nick);
  
  u = findauser(arm->parsevars->sender);
  c = findchannel(channame);
 
  /* Get out the entire text string */
  while(a[i] != '\0' && a[i] != ' ') ++i;
  ++i;
  while(a[i] != '\0' && a[i] != ' ') ++i;
  ++i;
  while(a[i] != '\0' && j < 100) {
    value[j] = a[i];
    ++j;
    ++i;
  }

  if(c == NULL) {
    say(arm->parsevars->sender, "Channel doesen't exist", arm);
    return;
  }

  if(chanuserlevel(arm->parsevars->sender, c->name) < CHAN_MASTER && userlevel(arm->parsevars->sender) < 10) {
    say(arm->parsevars->sender, "Insufficient access.", arm);
    return;
  }

  u = NULL;
  u = findauser(nick);

  if(u == NULL) {
    say(arm->parsevars->sender, "No such user.", arm);
    return;
  }

#ifdef SPAMSCAN
  if (SOnChannel(c)) {
    say(arm->parsevars->sender, "You cannot use greet on channels with " SPAMSCANNICK " (spamscan).", arm);

    c->greet = 0;
    dbchanmode(c->id, "greet", "0");
    return;
  }
#endif

  if(chanuserlevel(nick, channame) == 0) c_setlev(u->userid, channame, 0);
  
  c_setgreet(u->userid, channame, value);
  say(arm->parsevars->sender, "Greet set was sucessfull.", arm);
}

void m_access (char *a, struct arm *arm) {
  struct channel *c;
  char msg[300];
  char text[20];
  char channame[CHANNELLEN+1] = "";
  char nick[NICKLEN+1] = "";

  if(!checkargs(2, 0, a, arm)) return;

  sscanf(a, "%s %s", channame, nick);
  c = findchannel(channame);

  if (c == NULL) say(arm->parsevars->sender, "Channel doesen't exist", arm);
  else {
    chanlevtotext(chanuserlevel(nick, channame), text);
    if(strcasecmp(nick, arm->nick) == 0) sprintf(msg, "It is me.");
    else sprintf(msg, "%s is a(n) %s on channel: %s.", nick, text, channame);
    say(arm->parsevars->sender, msg, arm);
  }
}

void m_userlev (char *a, struct arm *arm) {
  char msg[200];
  char channame[CHANNELLEN+1] = "";
  char nick[NICKLEN+1] = "";
  char level[10] = "";
  struct channel *c;
  struct activeuser *u;
  int senderlev;
  int targetlev;
  int targetuid;
  int go = 0;

  if(!checkargs(3, 0, a, arm)) return;

  u = findauser(arm->parsevars->sender);
  sscanf(a, "%s %s %s", channame, nick, level);
  c = findchannel(channame);

  if (c != NULL) {
    senderlev = chanuserlevel(arm->parsevars->sender, channame);
    
    if(u->auth >= 10) senderlev = 5;
    
    if(senderlev >= 3) {
      targetlev = texttochanlev(level);
      u = NULL;
      u = findauser(nick);

      if (u == NULL || u->auth == 0) say(arm->parsevars->sender, "Your target need to be AUTH'd before you can set his/her level.", arm);
      else {
	targetuid = u->userid;

	if (targetlev == 99) say(arm->parsevars->sender, "That level doesen't exist.", arm);
	else {

	  chanlevtotext(targetlev, level);

	  if(senderlev >= 3 && targetlev < 3) {
	    go = 1;
	    c_setlev(targetuid, channame, targetlev);
	  }
	  if(senderlev >= 4 && targetlev <= 3) {
	    go = 1;
	    c_setlev(targetuid, channame, targetlev);
	  }
	  if(senderlev >= 5 && targetlev <= 5) {
	    go = 1;
	    c_setlev(targetuid, channame, targetlev);
	  }
	  if(go == 1) {
	    say(arm->parsevars->sender, "Level set was sucessfull.", arm);
	    sprintf(msg, "%s made %s %c%s%c on this channel.", arm->parsevars->sender, nick, BOLD, level, BOLD);
	    privmsg(channame, msg);
	    sprintf(msg, "You have been given level: %s on channel: %s by: %s", level, channame, arm->parsevars->sender);
	    say(nick, msg, arm);
	    
	    setrightmode(channame, nick);	
	  }
	  else say(arm->parsevars->sender, "Insufficient access.", arm);
	}
      }
    } else say(arm->parsevars->sender, "Insufficient access.", arm);
  } else say(arm->parsevars->sender, "Channel doesen't exist.", arm);
}

#ifndef Q_AUTOAUTH
void m_newpass (char *a, struct arm *arm)
{

  struct activeuser *u;
  char query[MAX_QUERY] = "";

  if(!checkargs(1, 0, a, arm)) return;

  u = findauser(arm->parsevars->sender);
  if (u->auth == 0)
    {
      say (arm->parsevars->sender, "You need to AUTH with your old password first.", arm);
      return;
    }

  sprintf(query, "NEWPASS %d %s\n", u->userid, a);
  // puthub(query);

  say (arm->parsevars->sender, "OK, password changed.", arm);
}
#endif

void m_whois (char *a, struct arm *arm)
{
  int i, found = 0, lev = 0;
  char victim[NICKLEN];
  char buffer[512], mode;
  char query[MAX_QUERY];
  struct activeuser *u;
  struct activechanuser *acu;
  char *esvictim, *tauth;

  if(!checkargs(1, 0, a, arm)) return;

  i = 0;
  strncpy (victim, a, NICKLEN);

  if(strcasecmp(victim, arm->nick) != 0) {

    u = findauser(victim);

    if(u == NULL) {

      esvictim = escapequery(victim);
      snprintf(query, MAX_QUERY, "SELECT `auth` FROM `users` WHERE `handle` = '%s'", esvictim);
      free(esvictim);

      dbquery(query);
      EndDbQuery();
      
      if((row = mysql_fetch_row(res))) {
	lev = atoi(row[0]);
	found = 1;
      }
      else found = 0;
    }
    
    if (u != NULL)
      {
	sprintf (buffer, "%s is online right now.", u->nick);
	say (arm->parsevars->sender, buffer, arm);
	if (u->auth > 0)
	  {
	    if (strcasecmp (u->nick, u->hand) != 0)
	      {
		sprintf (buffer, "%s is actually %s.", u->nick, u->hand);
		say (arm->parsevars->sender, buffer, arm);
	      }
	    else
	      {
		sprintf (buffer, "%s is indeed %s.", u->nick, u->hand);
		say (arm->parsevars->sender, buffer, arm);
	      }

	  }  
      } else if (found == 0)
	{
	  if (u == NULL)
	    {
	      say (arm->parsevars->sender, "Who on earth is that?", arm);
	    }
	  else
	    {
	      say (arm->parsevars->sender, "Theres someone of that name online, but they haven't AUTHed.", arm);
	    }
	}
    if (u != NULL)
      {
	if(u->auth == 0) sprintf (buffer, "%s is not AUTHed.", u->nick); 
	else {
	  tauth = authtotext(u->auth);
	  sprintf (buffer, "%s has global auth level %d (%s).", u->nick, u->auth, tauth);
	  free(tauth);
	}
	say (arm->parsevars->sender, buffer, arm);

#ifndef DEBUG	
	if(u->auth > NORMAL && userlevel(arm->parsevars->sender) < SERVICE_FRIEND) return;
#endif
	sprintf(buffer, "%s is on following channels:", u->nick);
	say (arm->parsevars->sender, buffer, arm);

	if(u->isinhome == 1) {
	  sprintf(buffer, " %s", HOMECHAN);
	  say(arm->parsevars->sender, buffer, arm);
	}

	acu = firstacu;
	while (acu != NULL)
	  {
	    if(acu->user == u) {
	      if(acu->op == 1) mode = '@';
	      else if(acu->voice == 1) mode = '+';
	      else mode = ' ';
	      
	      sprintf(buffer, "%c%s", mode, acu->channel->name);
	      bestsay(arm->parsevars->sender, buffer);
	    }	      
	    acu = acu->next;
	  }
      }
    if (found == 1 && u == NULL) {
      sprintf (buffer, "%s is not online right now.", victim);
      say (arm->parsevars->sender, buffer, arm);
      /* sprintf (buffer, "%s was last authed: %s", victim, "Need to be implemented"); // Need to be implemented
	 say (arm->parsevars->sender, buffer, arm); */
      tauth = authtotext(lev);
      sprintf (buffer, "%s has global auth level %d (%s).", victim, lev, tauth);
      free(tauth);

      say (arm->parsevars->sender, buffer, arm);
    }
  } else say(arm->parsevars->sender, "That's me.\n", arm);
}

#ifndef Q_AUTOAUTH
void m_email (char *a, struct arm *arm) {
  char msg[512];
  struct activeuser *u;

  if(!checkargs(1, 0, a, arm)) return;

  u = findauser(arm->parsevars->sender);
  
  sprintf(msg, "EMAIL %i %s\n", u->userid, a);
  // puthub(msg);
  
  sprintf(msg, "Your E-Mail has been set to: %s.", a);
  say(arm->parsevars->sender, msg, arm);
}
#endif

#ifndef Q_AUTOAUTH
void m_oper (char *a, struct arm *arm) {
  char whois[10+NICKLEN] = "";

  say(arm->parsevars->sender, "Doing a WHOIS to check if you are an Operator.", arm);
  add(arm->parsevars->sender);
}
#endif

#ifdef Q_AUTOAUTH
void m_ident (char *a, struct arm *arm) {
  char msg[512];
  struct activeuser *u;
  
  if(countargs(a) == 0) {
    if((u = findauser(arm->parsevars->sender)) == NULL) {
      say(arm->parsevars->sender, "Massive bug, report this NOW!", arm);
      return;
    }  
     
    add(u);
    say(arm->parsevars->sender, "Checking if you are AUTH'd. You will NOT get any confirmation if you are AUTH'd or not.", arm);
  } else if(countargs(a) == 1 && strlen(a) <= NICKLEN) {
    if((u = findauser(a)) == NULL) {
      say(arm->parsevars->sender, "There is no such user active on any of my channels.", arm);
      return;
    }
    add(u);
    sprintf(msg, "Checking if %s is AUTH'd.", a);
    say(arm->parsevars->sender, msg, arm);
  } else return;
}

void m_sync (char *a, struct arm *arm) {
  struct activechanuser *acu;
  struct channel *c;

  if(!checkargs(1, 0, a, arm)) return;

  if ((c = findchannel(a)) == NULL) {
    say(arm->parsevars->sender, "No such channel.", arm);
    return;
  }

  say(arm->parsevars->sender, "Checking AUTH status of all unauthed users on the channel.", arm);

  acu = firstacu;
  while (acu != NULL)
    {
      if (acu->channel == c && acu->user->auth == UNAUTHED) add(acu->user);
      acu = acu->next;
    }
}

#endif
