/*
 * glinemask.c
 * (C) Christian Magnusson 2000, Email: d1mag@dtek.chalmers.se
 * This program is copyright, and covered by the Gnu Public License.
 * The Q bot.
 */

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>

#include "settings.h"
#include "bottypes.h"
#include "globals.h"
#include "dl.h"

#define MIN(x, y) (((x) < (y)) ? (x) : (y))

MODULE_PUBLIC int _init_glinemask(void *a, void *b)
{
  dl_command_entry_t *dl = a;
  if(!a) return 0;

  snprintf(dl->help, MAX_COMMAND_HELP_LEN,
           "/msg %s GLINEMASK <*pattern*> [123h/d/w/m/y] [Reason]\nThis will G-line all users matching a specifik pattern. The G-line will currently be *@host.com (1 week) for the users who match the pattern.\n"\
	   "/msg %s GLINEMASK *!*username@host* Clones\n"\
	   "/msg %s GLINEMASK *!*username@host* 1y Clones\n"\
	   "/msg %s GLINEMASK *nick*!*@*.com Clones\n"\
	   "/msg %s GLINEMASK *showdown* Bad Client\n"
           , BOT_NAME, BOT_NAME, BOT_NAME, BOT_NAME, BOT_NAME);
  snprintf(dl->summary, MAX_COMMAND_SUMMARY_LEN,
	   "G-line many hosts at the same time.");
  dl->level = 950;
#if 0
  dl->func = m_glinemask;
#else
  dl->func = (void (*)(char*)) DL_sym(dl->val, "m_glinemask");
#endif
  return 1;
}

MODULE_PUBLIC int _remove_glinemask(char *a, char *b)
{
  remove_command("glinemask");
  return 1;
}

static char banstylename_buffer[BANLEN+1];
static char *banstylename2(char *nick, char *user, char *host)
{
  sprintf(banstylename_buffer, "%s%s%s@%s", nick, "!", user, host);
  return banstylename_buffer;
}

MODULE_PUBLIC void m_glinemask(char *a)
{
  struct activeuser *u;
  char user_mask[256+1];
  char pattern[HOSTLEN+1];
  char tmp[513];
  char time_str[80];
  char gline[GLINELEN+1];
  char gline_mask[GLINELEN+1];
  char reason[REASONLEN+1];
  char reason_test[REASONLEN+1];
  int i, start, rlen;
  ListElem *el, *el2;
  int matches = 0;
  struct gline *g;
  int nr;
  int dur_len;
  long durationl;
  char duration[21];
  struct tm *tm_;
  time_t time_;

  struct dbaseuser *db;
  db = sender_au->dbuser;
  if(db) {
    log("From: %s glinemask [%s]\n", db->nick, a);
  } else
    return;
  if(!is_oper()) {
    say_sender("You are not an Oper.");
    log("To: %s Is not an Oper\n", db->nick);
    return;
  }

  if(!a) return;

  i = 0;
  strncpy(pattern,getword(a,&i),HOSTLEN);
  pattern[HOSTLEN] = '\0';
  if(!strlen(pattern)) {
    say_sender("You forgot the pattern parameter");
    say_sender_( "/msg %s GLINEMASK <*pattern*> [123 h/d/w/m/y] [reason]", BOT_NAME);
    return;
  }

  start = i+1;
  strncpy(duration, getword(a,&i), REASONLEN);
  duration[REASONLEN] = '\0';
  if(strlen(duration)) {
    if(isdigit(duration[0])) {

      durationl = atol(duration);
      dur_len = strlen(duration);

      if(dur_len && !isdigit(duration[dur_len-1])) {
        switch(duration[dur_len-1]) {
        case 'h':
          durationl *= 3600;
          break;
        case 'd':
          durationl *= 24*3600;
          break;
        case 'w':
          durationl *= 7*24*3600;
          break;
        case 'm':
          durationl *= 30*24*3600;
          break;
        case 'y':
          durationl *= 365*24*3600;
          break;
        default:
          break;
        }
      }
      if(durationl == 0) {
        say_sender("No duration length was given.");
        return;
      }

      start = i+1;
      strncpy(reason_test, getword(a,&i), 10);
      reason_test[10] = '\0';
      if(!strlen(reason_test)) {
	sprintf(reason, "Network Trouble Maker");
      } else {
	strncpy(reason, &a[start], REASONLEN);
	rlen = MIN(strlen(&a[start]), REASONLEN);
	reason[rlen] = '\0';
      }
    } else {
      durationl = 7*24*3600;
      strncpy(reason, &a[start], REASONLEN);
      rlen = MIN(strlen(&a[start]), REASONLEN);
      reason[rlen] = '\0';
    }
  } else {
    /* there are no more parameters */
    durationl = 7*24*3600;
    sprintf(reason, "Network Trouble Maker");
  }
  sprintf(duration, "%ld", durationl);


  nr = 0;
  matches = 0;
  el = GetHead(auser_list);
  while(el) {
    u = (struct activeuser *)el->data;
    
    strncpy(user_mask, banstylename2(u->nick, u->username, u->hostname), 256);
    user_mask[256] = '\0';
        
    if( !match(pattern, u->nick) ||
        !match(pattern, u->username) ||
        !match(pattern, u->hostname) ||
        !match(pattern, u->fullname) ||
        !match(pattern, user_mask)) {
      struct gline gl;

      matches++;

      strncpy(gline_mask, banstylename2("*", "*", u->hostname), GLINELEN);
      gline_mask[GLINELEN] = '\0';

      strncpy(gline, &gline_mask[2], GLINELEN-2);
      gline[GLINELEN-2] = '\0';

      strncpy(gl.user, u->username, USERLEN);
      gl.user[USERLEN] = '\0';
      strncpy(gl.host, u->hostname, HOSTLEN);
      gl.host[HOSTLEN] = '\0';

      el2 = GetHead(auser_list);
      while(el2) {
	u = (struct activeuser *)el2->data;
	if(u && matches_gline(u, &gl)) { 
	  nr++;
	}
	el2 = GetSucc(el2);
      }
      if((nr > 100) && (nr > servers[MAX_SERVERS].users/10)) {
	say_sender_("You are not allowed to G-line %d users", nr);
	return;
      }
    }
    el = GetSucc(el);
  }


  nr = 0;
  matches = 0;
  el = GetHead(auser_list);
  while(el) {
    u = (struct activeuser *)el->data;
    
    strncpy(user_mask, banstylename2(u->nick, u->username, u->hostname), 256);
    user_mask[256] = '\0';
        
    if( !match(pattern, u->nick) ||
        !match(pattern, u->username) ||
        !match(pattern, u->hostname) ||
        !match(pattern, u->fullname) ||
        !match(pattern, user_mask)) {

      matches++;

      /*
	strncpy(gline_mask, banstylename2("*", u->username, u->hostname), GLINELEN);
      */
      strncpy(gline_mask, banstylename2("*", "*", u->hostname), GLINELEN);
      gline_mask[GLINELEN] = '\0';

      strncpy(gline, &gline_mask[2], GLINELEN-2);
      gline[GLINELEN-2] = '\0';

      log("glinemask: G-line user %s!%s@%s (%s)\n", u->nick, u->username,
	  u->hostname, u->fullname);
      g = gline_add(gline, duration, reason, sender_au->userid, 0);
      if(g) {
	strncpy(g->user, u->username, USERLEN);
	g->user[USERLEN] = '\0';
	strncpy(g->host, u->hostname, HOSTLEN);
	g->host[HOSTLEN] = '\0';
	
	el2 = GetHead(auser_list);
	while(el2) {
	  u = (struct activeuser *)el2->data;
	  if(u && matches_gline(u, g)) { 
	    nr++;
	  }
	  el2 = GetSucc(el2);
	}

	time_ = g->expire;
	tm_ = localtime(&time_);
	strftime(time_str, 60, "%c", tm_);
	
	sprintf(tmp, "GLINEMASK %s expires %s (%d user%s) (set by %s)\n",
		gline, time_str, nr, ((nr==1) ? "" : "s"), sender_au->dbuser->nick);
	log(tmp);
	putserver("%c%c GL * +%s %ld :%s\n\r", yxx[0], yxx[1], g->gline, g->duration, g->reason);
      }
    }
    el = GetSucc(el);
  }
  say_sender_("Found %d user(s)", matches);

  /*
[Sun 000528 16:11:19] GLINEMASK *@courtesy.courtesycomputers.com expires ,xxxxxx (2 users) (set by [E]SuperDuck)
[Sun 000528 16:11:19] glinemask: G-line user [E]SuperFucker!~hog@courtesy.courtesycomputers.com (^lamer)
[Sun 000528 16:11:19] glinemask: G-line user [E]SuperFucker!~hog@courtesy.courtesycomputers.com (^lamer)
[Sun 000528 16:11:19] glinemask: G-line user [E]SuperFucker!~hog@courtesy.courtesycomputers.com (^lamer)
*/

  if(matches) {
    time_ = durationl + time(NULL);
    tm_ = localtime(&time_);
    strftime(time_str, 60, "%c", tm_);

    sprintf(tmp, "GLINEMASK %s expires %s (%d user%s) Set by: %s (%s) Reason: %s\n",
	    pattern, time_str,
	    matches, ((matches==1) ? "" : "s"),
	    sender_au->nick, sender_au->dbuser->nick, reason);
    wallop(tmp);
    log(tmp);
  }
  return;
}


