/*
 * whois.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"

void m_whois(char *a);
char *crypt(const char *key, const char *salt);

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

  snprintf(dl->help, MAX_COMMAND_HELP_LEN,
	   "/msg %s WHOIS <nick>\nTells you what name a user has AUTHed under, if it's not the same as their nick.\n"
	   , BOT_NAME);
  snprintf(dl->summary, MAX_COMMAND_SUMMARY_LEN,
	   "Tells you who someone really is");
  dl->level = 1;
#if 0
  dl->func = m_whois;
#else
  dl->func = (void (*)(char*)) DL_sym(dl->val, "m_whois");
#endif
  return 1;
}

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

#define MAXHOST_LEN 255

static void print_crypt(char *username, char *userhost)
{
  int i;
  int len;
  char salt[3];
  char *str;
  char *p;
  char host[MAXHOST_LEN+1];
  int ip_number = 1;
  int dot_nr = 0;
  int dot_pos = 0;

  p = userhost;
  len = strlen(p);
  for(i=0; i<len; i++) {
    if(! isdigit(p[i]) ) {
      if(p[i] == '.') {
        if(++dot_nr == 3) {
          dot_pos = i;
        }
        continue;
      }
      ip_number = 0;
      break;
    }
  }
  if(ip_number) {
    if(!dot_pos) {
      /* user have probaly no info "\0" */
#if 0
      say_sender_("Internal error. Couldn't find '.' [%d] [%d]", len, dot_nr);
#endif
      return;
    }
    p = &p[dot_pos+1];
    len -= dot_pos;
    if(!p || len<=0 || len>MAXHOST_LEN) {
      /* user have probaly no info "???" */
#if 0
      say_sender_("Internal error");
      log("print_crypt: ERROR: [%d] [%d] [%X]\n", ip_number, len, p);
      len = strlen(username);
      if(len < 50) log("print_crypt: ERROR: username=[%d] [%s]\n", len, username);
      len = strlen(userhost);
      if(len < 50) log("print_crypt: ERROR: userhost=[%d] [%s]\n", len, userhost);
#endif
      return;
    }
    strncpy(host, p, len);  host[len] = '\0';

    strncpy(salt, host, 2);  salt[2] = '\0';
    str = crypt(p, salt);
    
    strncpy(salt, &str[2], 2);  salt[2] = '\0';
    str = crypt(p, salt);
    if(str[0] == '.') str[0] = 'a'; /* avoid . in the end */
    if(str[12] == '.') str[12] = 'a'; /* avoid . in the end */
    
    strncpy(host, userhost, dot_pos+1);  host[dot_pos+1] = '\0';
    say_sender_("Crypt host: %s@%s%s", username, host, str);
  } else {
    p = strchr(userhost, '.');
    len = p - userhost;
    if(!p || len<=0 || len>MAXHOST_LEN) {
      /* user have probaly no info "???" */
#if 0
      say_sender_("Internal error");
      log("print_crypt: ERROR: [%d] [%d] [%X]\n", ip_number, len, p);
      len = strlen(username);
      if(len < 50) log("print_crypt: ERROR: username=[%d] [%s]\n", len, username);
      len = strlen(userhost);
      if(len < 50) log("print_crypt: ERROR: userhost=[%d] [%s]\n", len, userhost);
#endif
      return;
    }
    strncpy(host, userhost, len);  host[len] = '\0';

    strncpy(salt, host, 2);  salt[2] = '\0';
    str = crypt(userhost, salt);

    strncpy(salt, &str[2], 2);  salt[2] = '\0';
    str = crypt(userhost, salt);
    
    if(str[0] == '.') str[0] = 'a'; /* avoid . in the end */
    if(str[12] == '.') str[12] = 'a'; /* avoid . in the end */
    say_sender_("Crypt host: %s@qnet-%s%s", username, str, p);
  }
  return;
}



MODULE_PUBLIC void m_whois(char *a)
{
  int i, nr_chans, nr;
  char victim[NICKLEN+2];
  char buffer[512];
  char tmp[64];
  struct tm *tm_;
  struct activeuser *u, *u2;
  struct dbaseuser *p;
  struct dbaseuser *db;
  struct chanpriv *cp;
  ListElem *el;

  i=0;
  strncpy(victim,getword(a,&i),NICKLEN+1);
  victim[NICKLEN+1] = '\0';
  if(!strlen(victim)) {
    say_sender( "You forgot to type the nickname.");
    say_sender_( "/msg %s WHOIS nick    Check an active user.", BOT_NAME);
    say_sender_( "/msg %s WHOIS #nick   Check user in database.", BOT_NAME);
    return;
  }
  if(victim[0] != '#') {
    u = findauser(victim);
    if(!u) {
      say_sender("Who on earth is that?");
      return;
    }
    p = NULL;
    say_sender_("%s is online right now.", u->nick);
    if(u->userid) {
      p = u->dbuser;
      if(p) {
	say_sender_("%s is authed as %s.", u->nick, p->nick);
	nr = 0;
	el = GetHead(auser_list);
	while(el) {
	  u2 = ((struct activeuser *)el->data);
	  if((u != u2) && (u2->userid == p->userid)) {
	    if(nr++ == 0) {
	      say_sender( "There are more users authed with that id.");
	    }
	    say_sender_("%s is also authed as %s", u2->nick, p->nick);
	  }
	  el = GetSucc(el);
	}
      } else {
	say_sender_("%s is authed as (some deleted user) uid=%d", u->nick, u->userid);
      }
    } else {
      say_sender_("%s is NOT authed", u->nick);
    }
    say_sender_("%s has global auth level %d.", u->nick, u->auth);
    
    if(is_oper()) print_crypt(u->username, u->hostname);
  } else {
    p = finduserfromname(victim+1);
    u = NULL;
    if(!p) {
      say_sender("Who on earth is that?");
      return;
    }
    say_sender_("%s has global auth level %d.", p->nick, p->globalauth);

    nr = 0;
    el = GetHead(auser_list);
    while(el) {
      u2 = ((struct activeuser *)el->data);
      if(u2->userid == p->userid) {
	if(nr++ == 0) {
	  say_sender( "There users authed with that id.");
	}
	say_sender_("%s is authed as %s", u2->nick, p->nick);
      }
      el = GetSucc(el);
    }

    if(is_oper()) print_crypt(p->last_username, p->last_hostname);
  }

  if(p) {
    tm_ = localtime(&(p->last_auth));
    buffer[0] = '\0';
    strftime(tmp, 60, "%c", tm_);
    say_sender_("Last auth: [%s]", tmp);
    if(is_oper()) {
      db = sender_au->dbuser;
      if(db && (db->globalauth > 900)) {
	if(p->email) {
	  say_sender_("E-mail: %s", p->email);
	} else {
	  say_sender("E-mail: (not set)");
	}
      }
      say_sender_("Last host: %s@%s", p->last_username, p->last_hostname);
    }

    nr_chans = 0;
    say_sender( "Channel list:");
    cp = p->privs;
    while(cp) {
      nr_chans++;
      createmodes(cp->chanlevel, tmp);
      say_sender_("Access level %8s on channel %s", tmp, cp->channel);
      cp = cp->next;
    }
    if(nr_chans>0) {
      say_sender( "End of list.");
    } else {
      say_sender( "User not known in any channels.");
    }
  }
  return;
}
