/******************************************************************
 * PTlink Services is (C) CopyRight PTlink IRC Software 1999-2005 *
 *                http://software.pt-link.net                     *
 * This program is distributed under GNU Public License           *
 * Please read the file COPYING for copyright information.        *
 ******************************************************************

  File: ns_identify.c
  Description: nickserv identify command

 *  $Id: ns_identify.c,v 1.12 2005/10/22 12:42:51 jpinto Exp $
*/

#include "module.h"
#include "nickserv.h"
#include "dbconf.h"
#include "encrypt.h"
#include "my_sql.h"
#include "nsmacros.h"
#include "lang/common.lh"
#include "lang/nickserv.lh"
#include "lang/ns_identify.lh"

SVS_Module mod_info =
/* module, version, description */
{ "ns_identify", "2.3", "nickserv identify command" };

/* Change Log
  2.2 - #21 : remove unused/moved fields from nickserv table
        #10 : add nickserv suspensions
  2.1 - 0000338: when the targer nick is used, login should behave like ns_identify
  2.0 - 0000276: nick password expire option
        0000272: move nickserv security info to a specific table
        0000265: remove nickserv cache system  
  1.2 - Added missing code for the issue 0000245
      - 0000255: new field to store nick expire time
  1.1 - 0000245: use snid to track previous identify
*/
  
/* functions and events we require */
ServiceUser* (*nickserv_suser)(void);
int (*update_nick_online_info)(IRC_User* u, u_int32_t snid, int lang);
int (*check_nick_security)
  (u_int32_t snid, IRC_User *u, char* pass, char* email, int flags);
int e_nick_identify;                                         
int ns_log;

MOD_REQUIRES
  MOD_FUNC(dbconf_get)
  MOD_FUNC(nickserv_suser)
  MOD_FUNC(e_nick_identify)
  MOD_FUNC(update_nick_online_info)
  MOD_FUNC(check_nick_security)
MOD_END

/* internal functions */
void ns_identify(IRC_User *s, IRC_User *u);

/* Local settings */
static int FailedLoginMax;
static int ExpireTime;
static int AgeBonusPeriod;
static int AgeBonusValue;

/* List of dbconf items we provide */
DBCONF_REQUIRES
  DBCONF_GET("nickserv", FailedLoginMax)
  DBCONF_GET("nickserv", ExpireTime)
  DBCONF_GET("nickserv", AgeBonusPeriod)
  DBCONF_GET("nickserv", AgeBonusValue)
DBCONF_END
                                                                              
/* this is called before load and at services rehash */
int mod_rehash(void)
{
  if(dbconf_get(dbconf_requires) < 0 )
  {
    errlog("Error reading dbconf!");
    return -1;
  }
  return 0;
}

/* Local variables */
ServiceUser* nsu;

int mod_load(void)
{

  ns_log = log_handle("nickserv");

  /* get service user */
  nsu = nickserv_suser();
          
  suser_add_cmd(nsu, "IDENTIFY", 
    ns_identify, IDENTIFY_SUMMARY, IDENTIFY_HELP);
  	
  return 0;
}

void
mod_unload(void)
{
  suser_del_mod_cmds(nsu, &mod_info);
}
 
/* s = service the command was sent to
   u = user the command was sent from */
void ns_identify(IRC_User *s, IRC_User *u)
{
  MYSQL_RES *res = NULL;
  MYSQL_ROW row;  
  char *pass = strtok(NULL, " ");
  char *extraopt = NULL;

  if(pass != NULL)
    extraopt = strtok(NULL, "");
    
  if(IsNull(pass))
    send_lang(u, s, IDENTIFY_SYNTAX);
  else if(u->snid)
    send_lang(u, s, ALREADY_IDENTIFIED);
  else if((res = sql_query("SELECT snid, flags, lang, email, vhost"
    " FROM nickserv WHERE nick=%s", sql_str(irc_lower_nick(u->nick))))
      && (row = sql_next_row(res)))
  {
    int c = 0;
    u_int32_t snid = atoi(row[c++]);    
    u_int32_t flags = atoi(row[c++]);    
    int lang = atoi(row[c++]);
    char *email = row[c++];
    char *vhost = row[c++];

    if((flags & NFL_SUSPENDED) &&
      sql_singlequery("SELECT reason FROM nickserv_suspensions WHERE snid=%d", snid))
    {
      send_lang(u,s, NICK_X_IS_SUSPENDED_X, u->nick, sql_field(0));
      return;
    }    
    if(check_nick_security(snid, u, pass, email, flags) == -1)
    {
      log_log(ns_log, mod_info.name, "Nick %s failed identify by %s",
        u->nick, irc_UserSMask(u));
      if(FailedLoginMax && ++u->fcount>FailedLoginMax)
      {
        log_log(ns_log, mod_info.name, 
          "Killing %s on too many failed identify attempts", u->nick);
        irc_Kill(u, s, "Too many failed identify attempts");
      }
      else
        send_lang(u, s, INCORRECT_PASSWORD);
      sql_free(res);    
      return;
    }
    else
    {
      send_lang(u, s, IDENTIFY_OK); 
      log_log(ns_log, mod_info.name, "Nick %s identified by %s",
        u->nick, irc_UserSMask(u));    
      update_nick_online_info(u, snid, lang);      
      if(vhost && irccmp(u->publichost, vhost)) /* we need to set the vhost */
        irc_ChgHost(u, vhost);      
      irc_CancelUserTimerEvents(u); /* delete the pending change nick event */
      mod_do_event(e_nick_identify, u, &snid);
    }
  }
  else
    send_lang(u, s, NICK_NOT_REGISTERED);    
  sql_free(res);
}



syntax highlighted by Code2HTML, v. 0.9.1